How to pass the API gateway URL from a deploy action into my test action?

0

How do I pass in the API Gateway URL defined in one action into a test action in the same stage? I have a pipeline stage, defined in CDK:

A screenshot of a Beta CDK pipeline stage with 3 actions, RestSvc.Prepare, RestSvc.Deploy, and E2ETests

The code defining this stage is in 3 TypeScript files:

export class WeatherServiceStack extends cdk.Stage {
  constructor(scope: Construct, id: string, props?: cdk.StackProps) {
    super(scope, id, props);
    const restSvc = new RestSvcStack(this, 'RestSvc', props);
  }
}
export class RestSvcStack extends Stack {
    constructor(scope: Construct, id: string, props?: StackProps) {
        super(scope, id, props);
        const backend = new Function(this, "RestBackend", {
            runtime: Runtime.PYTHON_3_12,
            handler: "weather_svc.handler",
            code: Code.fromAsset("handler")
        })
        new LambdaRestApi(this, 'RestSvc', {
            handler: backend,
            restApiName: 'WeatherSvc',
            defaultCorsPreflightOptions: {
                allowOrigins: Cors.ALL_ORIGINS,
                allowMethods: Cors.ALL_METHODS
            },
            apiKeySourceType: ApiKeySourceType.HEADER,
        });

    }
}

Finally, the pipeline itself (just the fragment setting up the Beta stage):

        const betaStack = new WeatherServiceStack(this, 'Beta', {
            env: {
                account: '975049914859',
                region: 'us-west-2',
            },
        })
        const betaStage = pipeline.addStage(betaStack);

        betaStage.addPost(new pipelines.CodeBuildStep("E2ETests", {
            env: {
                "WEATHER_API_URL": "https://1bbca9941f.execute-api.us-west-2.amazonaws.com/prod",
            },
            commands: [
                'python3 test_api.py'
            ]
        }));

In the code above, my test_api.py expects the API Gateway URL as an env var, WEATHER_API_URL. I want to set this parameter based on the LambdaRestApi.url in RestSvcStack. I tried passing the value up and out by setting a field RestSvcStack.apiUrl, which I copied into another field in WeatherServiceStack.apiUrl, and finally pointed my E2ETest step at it with "WEATHER_API_URL": betaStack.apiUrl,. Unfortunately, I got an error:

Error: Stack "WeatherServicePipelineStack" cannot reference {WeatherServicePipelineStack/Beta/RestSvc/RestSvc/Resource[Ref]} in stack "WeatherServicePipelineStack/Beta/RestSvc". Cross stack references are only supported for stacks deployed to the same account or between nested stacks and their parent stack

... but I'm not sure how to solve that.

My ultimate goal is to roll back the deployment RestSvc.Deploy if E2ETest fails, so bonus internet points if you give me that soln' too :-)

2 Answers
2
Accepted Answer

Hi Dan.

To pass the API Gateway URL from the RestSvcStack to the test action in the same stage, you need to ensure that the URL is accessible as an output of the stack and then use that output in your pipeline stage.

I would suggest you to declare a variable both on your Stack and on your Stage as follow:

    public readonly loadBalancerAddress: CfnOutput;

This documentation shows how you can define an atribute/value via CfnOutput as follow:

this.loadBalancerAddress = new cdk.CfnOutput(lbStack, 'LbAddress', {
  value: `https://${lbStack.loadBalancer.loadBalancerDnsName}/`
});

And then use it as follow as part of your action:

// pass the load balancer address to a shell step
stage.addPost(new ShellStep("lbaddr", {
  envFromCfnOutputs: {lb_addr: lbStack.loadBalancerAddress},
  commands: ['echo $lb_addr']
}));

Please accept this answer if it helped you. Otherwise, feel free to ping me so we can troubleshoot.

Regards, Pablo Silva

profile pictureAWS
answered a month ago
profile pictureAWS
EXPERT
reviewed a month ago
  • This worked! I think the key was the envFromCfnOutputs property. I just needed to modify it from a load balancer to the API GW URL and it worked like a treat :-)

1

As a workaround, you can capture the API Gateway URL in the context of the RestSvcStack, retrieve it in the WeatherServiceStack, and then pass it as an environment variable to the E2ETests CodeBuild step. Additionally, you can use the pipeline's wave mechanism to automatically roll back the RestSvc deployment if the E2ETests fail.

profile picture
EXPERT
answered a month ago

You are not logged in. Log in to post an answer.

A good answer clearly answers the question and provides constructive feedback and encourages professional growth in the question asker.

Guidelines for Answering Questions