From 5e0731ec94c2c82862b1a84eb4eb5f47b38eb7a6 Mon Sep 17 00:00:00 2001 From: Giacomo Marciani Date: Fri, 29 Nov 2024 15:12:48 +0100 Subject: [PATCH 1/2] [Test] Make deployment script able to deploy an unreleased version of ParallelCluster API. Signed-off-by: Giacomo Marciani --- api/infrastructure/deploy-api.sh | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/api/infrastructure/deploy-api.sh b/api/infrastructure/deploy-api.sh index d1307aac88..bfc4f0c9f0 100755 --- a/api/infrastructure/deploy-api.sh +++ b/api/infrastructure/deploy-api.sh @@ -7,7 +7,7 @@ # OR CONDITIONS OF ANY KIND, express or implied. See the License for the specific language governing permissions and # limitations under the License. -usage="$(basename "$0") [-h] --s3-bucket bucket-name --region aws-region [--stack-name name] [--enable-iam-admin true|false] [--create-api-user true|false])" +usage="$(basename "$0") [-h] --s3-bucket bucket-name --region aws-region [--stack-name name] [--enable-iam-admin true|false] [--create-api-user true|false] [--lambda-layer abs_path]" SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )" @@ -15,6 +15,7 @@ S3_BUCKET= STACK_NAME="ParallelClusterApi" ENABLE_IAM_ADMIN="true" CREATE_API_USER="false" +LAMBDA_LAYER= while [[ $# -gt 0 ]] do key="$1" @@ -59,6 +60,11 @@ case $key in shift # past argument shift # past value ;; + --lambda-layer) + export LAMBDA_LAYER=$2 + shift # past argument + shift # past value + ;; *) # unknown option echo "$usage" >&2 exit 1 @@ -71,6 +77,8 @@ if [ -z "${S3_BUCKET}" ] || [ -z "${AWS_DEFAULT_REGION}" ] ; then exit 1 fi +PC_VERSION=$(yq ".Mappings.ParallelCluster.Constants.Version" "${SCRIPT_DIR}/parallelcluster-api.yaml") + S3_UPLOAD_URI="s3://${S3_BUCKET}/api/ParallelCluster.openapi.yaml" POLICIES_S3_URI="s3://${S3_BUCKET}/stacks/parallelcluster-policies.yaml" POLICIES_TEMPLATE_URI="http://${S3_BUCKET}.s3.${AWS_DEFAULT_REGION}.amazonaws.com/stacks/parallelcluster-policies.yaml" @@ -81,6 +89,12 @@ aws s3 cp "${SCRIPT_DIR}/../spec/openapi/ParallelCluster.openapi.yaml" "${S3_UPL echo "Publishing policies CloudFormation stack to S3" aws s3 cp "${SCRIPT_DIR}/../../cloudformation/policies/parallelcluster-policies.yaml" "${POLICIES_S3_URI}" +if [ -n "${LAMBDA_LAYER}" ]; then + LAMBDA_LAYER_S3_URI="s3://${S3_BUCKET}/parallelcluster/${PC_VERSION}/layers/aws-parallelcluster/lambda-layer.zip" + echo "Publishing Lambda Layer for version ${PC_VERSION} to S3" + aws s3 cp "${LAMBDA_LAYER}" "${LAMBDA_LAYER_S3_URI}" +fi + echo "Deploying API template" aws cloudformation deploy \ --stack-name "${STACK_NAME}" \ @@ -90,4 +104,5 @@ aws cloudformation deploy \ --parameter-overrides ApiDefinitionS3Uri="${S3_UPLOAD_URI}" \ PoliciesTemplateUri="${POLICIES_TEMPLATE_URI}" \ EnableIamAdminAccess="${ENABLE_IAM_ADMIN}" CreateApiUserRole="${CREATE_API_USER}" \ + "$([[ -n "${LAMBDA_LAYER}" ]] && echo "CustomBucket=${S3_BUCKET}" || echo " ")" \ --capabilities CAPABILITY_NAMED_IAM From b7120f15d8828f31764fa7721a3631b116252b37 Mon Sep 17 00:00:00 2001 From: Giacomo Marciani Date: Fri, 29 Nov 2024 15:13:38 +0100 Subject: [PATCH 2/2] [Test] Improve the script to make a sample request to a deployed ParallelCluster API. Signed-off-by: Giacomo Marciani --- api/README.md | 12 ++++++++++++ api/client/example.py | 37 ++++++++++++++++++++++++++++--------- api/client/requirements.txt | 2 ++ 3 files changed, 42 insertions(+), 9 deletions(-) create mode 100644 api/client/requirements.txt diff --git a/api/README.md b/api/README.md index 1eb8387e64..a0aa3cae46 100644 --- a/api/README.md +++ b/api/README.md @@ -99,3 +99,15 @@ through unit tests and integration tests that exercise the operations. In order to test the API specifically, there are integraiton tests which will deploy the API and test the functionality using the generated client. +### Invoking the API + +Install requirements for the example: +``` +pip install -r client/requirements.txt +``` + +Invoke a deployed ParallelCluster API: +``` +python client/example.py --region [REGION] --stack-name [PCAPI_STACK_NAME] +``` + diff --git a/api/client/example.py b/api/client/example.py index 8852a20ad4..8ac66be026 100755 --- a/api/client/example.py +++ b/api/client/example.py @@ -13,19 +13,18 @@ # language governing permissions and limitations under the License. import boto3 +import click from pcluster_client.api import cluster_operations_api from pcluster_client import Configuration, ApiClient, ApiException -apigateway = boto3.client("apigateway") - -def request(): +@click.command() +@click.option("--stack-name", help="ParallelCluster API stack name") +@click.option("--region", help="AWS region") +def request(stack_name: str, region: str): """Makes a simple request to the API Gateway""" - apis = apigateway.get_rest_apis()["items"] - api_id = next(api["id"] for api in apis if api["name"] == "ParallelCluster") - region = boto3.session.Session().region_name - host = f"{api_id}.execute-api.{region}.amazonaws.com" - configuration = Configuration(host=f"https://{host}/prod") + invoke_url = describe_stack_output(region, stack_name, "ParallelClusterApiInvokeUrl") + configuration = Configuration(host=invoke_url) with ApiClient(configuration) as api_client: client = cluster_operations_api.ClusterOperationsApi(api_client) @@ -33,10 +32,30 @@ def request(): try: response = client.list_clusters(region=region_filter) - print("clusters: ", [c["cluster_name"] for c in response["clusters"]]) + print("Response: ", response) except ApiException as ex: print("Exception when calling ClusterOperationsApi->list_clusters: %s\n" % ex) +def describe_stack_output(region: str, stack_name: str, output_name: str): + try: + # Describe stack + cloudformation = boto3.client("cloudformation", region_name=region) + response = cloudformation.describe_stacks(StackName=stack_name) + + # Get the stack details + stacks = response.get("Stacks", []) + if not stacks: + print(f"No stacks found with the name: {stack_name}") + return None + + # Extract output + outputs = stacks[0].get("Outputs", []) + return list(filter(lambda o: o['OutputKey'] == 'ParallelClusterApiInvokeUrl', outputs))[0]['OutputValue'] + + except Exception as e: + print(f"Cannot describe output '{output_name}' for stack '{stack_name}': {e}") + return None + if __name__ == "__main__": request() diff --git a/api/client/requirements.txt b/api/client/requirements.txt new file mode 100644 index 0000000000..fcbc3b2f8e --- /dev/null +++ b/api/client/requirements.txt @@ -0,0 +1,2 @@ +boto3>=1.16.14 +click~=8.1.7 \ No newline at end of file