+++ title = "Polish Pipeline" weight = 5000 +++ ## Get Endpoints Stepping back, we can see a problem now that our app is being deployed by our pipeline. There is no easy way to find the endpoints of our application (the `TableViewer` and `APIGateway` endpoints), so we can't call it! Let's add a little bit of code to expose these more obviously. First edit `CdkWorkshop/CdkWorkshopStack.cs` to get these values and expose them as properties of our stack: {{}} using Amazon.CDK; using Amazon.CDK.AWS.APIGateway; using Amazon.CDK.AWS.Lambda; using Cdklabs.DynamoTableViewer; using Constructs; namespace CdkWorkshop { public class CdkWorkshopStack : Stack { public readonly CfnOutput HCViewerUrl; public readonly CfnOutput HCEndpoint; // Defines a new lambda resource public CdkWorkshopStack(Construct parent, string id, IStackProps props = null) : base(parent, id, props) { var hello = new Function(this, "HelloHandler", new FunctionProps { Runtime = Runtime.NODEJS_14_X, Code = Code.FromAsset("lambda"), Handler = "hello.handler" }); var helloWithCounter = new HitCounter(this, "HelloHitCounter", new HitCounterProps { Downstream = hello }); var gateway = new LambdaRestApi(this, "Endpoint", new LambdaRestApiProps { Handler = helloWithCounter.Handler }); var tv = new TableViewer(this, "ViewerHitCount", new TableViewerProps { Title = "Hello Hits", Table = helloWithCounter.MyTable }); this.HCViewerUrl = new CfnOutput(this, "TableViewerUrl", new CfnOutputProps { Value = tv.Endpoint }); this.HCEndpoint = new CfnOutput(this, "GatewayUrl", new CfnOutputProps { Value = gateway.Url }); } } } {{}} By adding outputs `HCViewerUrl` and `HCEndpoint`, we expose the necessary endpoints to our HitCounter application. We are using the core construct `CfnOutput` to declare these as CloudFormation stack outputs (we will get to this in a minute). Let's commit these changes to our repo (`git commit -am "MESSAGE" && git push`), and navigate to the [CloudFormation console](https://console.aws.amazon.com/cloudformation). You can see there are three stacks. * `CDKToolkit`: The first is the integrated CDK stack (you should always see this on bootstrapped accounts). You can ignore this. * `WorkshopPipelineStack`: This is the stack that declares our pipeline. It isn't the one we need right now. * `Deploy-WebService`: Here is our application! Select this, and under details, select the `Outputs` tab. Here you should see four endpoints (two pairs of duplicate values). Two of them, `EndpointXXXXXX` and `ViewerHitCounterViewerEndpointXXXXXXX`, are defaults generated by CloudFormation, and the other two are the outputs we declared ourselves. ![](./stack-outputs.png) If you click the `TableViewerUrl` value, you should see our pretty hitcounter table that we created in the initial workshop. ## Add Validation Test Now we have our application deployed, but no CD pipeline is complete without tests! Let's start with a simple test to ping our endpoints to see if they are alive. Return to `CdkWorkshop/PipelineStack.cs` and add the following: {{}} using Amazon.CDK; using Amazon.CDK.AWS.CodeCommit; using Amazon.CDK.AWS.CodePipeline; using Amazon.CDK.AWS.CodePipeline.Actions; using Amazon.CDK.Pipelines; using Constructs; using System.Collections.Generic; namespace CdkWorkshop { public class WorkshopPipelineStack : Stack { public WorkshopPipelineStack(Construct parent, string id, IStackProps props = null) : base(parent, id, props) { // PIPELINE CODE HERE... var deploy = new WorkshopPipelineStage(this, "Deploy"); var deployStage = pipeline.AddStage(deploy); deployStage.AddPost(new ShellStep("TestViewerEndpoint", new ShellStepProps{ EnvFromCfnOutputs = new Dictionary { { "ENDPOINT_URL", /* TBD */ } }, Commands = new string[] { "curl -Ssf $ENDPOINT_URL" } })); deployStage.AddPost(new ShellStep("TestAPIGatewayEndpoint", new ShellStepProps{ EnvFromCfnOutputs = new Dictionary { { "ENDPOINT_URL", /* TBD */ } }, Commands = new string[] { "curl -Ssf $ENDPOINT_URL/", "curl -Ssf $ENDPOINT_URL/hello", "curl -Ssf $ENDPOINT_URL/test" } })); } } } {{}} We add post-deployment steps via `deployStage.AddPost(...)` from CDK Pipelines. We add two actions to our deployment stage: to test our TableViewer endpoint and our APIGateway endpoint, respectively. > Note: We submit several `curl` requests to the APIGateway endpoint so that when we look at our tableviewer, there are several values already populated. You may notice that we have not yet set the URLs of these endpoints. This is because they are not yet exposed to this stack! With a slight modification to `CdkWorkshop/PipelineStage.cs` we can expose them: {{}} using Amazon.CDK; using Amazon.CDK.Pipelines; using Constructs; namespace CdkWorkshop { public class WorkshopPipelineStage : Stage { public readonly CfnOutput HCViewerUrl; public readonly CfnOutput HCEndpoint; public WorkshopPipelineStage(Construct scope, string id, StageProps props = null) : base(scope, id, props) { var service = new CdkWorkshopStack(this, "WebService"); this.HCEndpoint = service.HCEndpoint; this.HCViewerUrl = service.HCViewerUrl; } } } {{}} Now we can add those values to our actions in `CdkWorkshop/PipelineStack.cs` by getting the `CfnOutput` of our deploy stage: {{}} // CODE HERE... deployStage.AddPost(new ShellStep("TestViewerEndpoint", new ShellStepProps{ EnvFromCfnOutputs = new Dictionary { { "ENDPOINT_URL", deploy.HCViewerUrl } }, Commands = new string[] { "curl -Ssf $ENDPOINT_URL" } })); deployStage.AddPost(new ShellStep("TestAPIGatewayEndpoint", new ShellStepProps{ EnvFromCfnOutputs = new Dictionary { { "ENDPOINT_URL", deploy.HCEndpoint } }, Commands = new string[] { "curl -Ssf $ENDPOINT_URL/", "curl -Ssf $ENDPOINT_URL/hello", "curl -Ssf $ENDPOINT_URL/test" } })); {{}} ## Commit and View! Commit those changes, wait for the pipeline to re-deploy the app, and navigate back to the [CodePipeline Console](https://console.aws.amazon.com/codesuite/codepipeline/pipelines) and you can now see that there are two test actions contained within the `Deploy` stage! ![](./pipeline-tests.png) Congratulations! You have successfully created a CD pipeline for your application complete with tests and all! Feel free to explore the console to see the details of the stack created, or check out the [API Reference](https://docs.aws.amazon.com/cdk/api/latest/docs/aws-construct-library.html) section on CDK Pipelines and build one for your application.