DEV Community

Ken Choong
Ken Choong

Posted on

How to provision APIgateway StageVariables and Deployment using AWS CDK?

In previous post, you know all the basic concept about how APIGateway, Lambda, Lambda version, alias, environment work together.

Now, we start provision the APIgateway using the CDK python.

In this post, we already learned that provision Lambda and Lambda Layer, so we will use back the code here, if you new here, just read the post, cause I mention a lot details about Lambda and Lambda Layer here

Now your MySampleAppStack file look like this:


from aws_cdk.aws_lambda_python import PythonFunction, PythonLayerVersion


class MySampleStack(core.Stack):

        def __init__(self, scope: core.Construct, id: str, **kwargs) -> None:
           super().__init__(scope, id, **kwargs)

           # All the aws resources define here

            # Here define a Lambda Layer 
            boto3_lambda_layer = PythonLayerVersion(
               self, 'Boto3LambdaLayer',
               entry='lambda/boto3Folder',
               compatible_runtimes=[lambda_.Runtime.PYTHON_3_8],
               description='Boto3 Library',
               layer_version_name='Whatever name you want'
           )

          my_first_lambda_function=PythonFunction(
                 self, 'MyFirstLambda',
                 entry='lambda/MyFirstLambdaFunction',
                 index='app.py',
                 runtime=lambda_.Runtime.PYTHON_3_8,
                 layers=[boto3_lambda_layer], 
                 handler='MyFirstLambdaHandler',
                timeout=core.Duration.seconds(10)
          )


Enter fullscreen mode Exit fullscreen mode

Alright, the Lambda already done, continue from here, we provision our API first.

First

pip install aws_cdk.aws_apigateway
Enter fullscreen mode Exit fullscreen mode

This install all the necessary package.

As mention in this post, we need 2 API stage nameddev and prod,

dev is for us to develop and testing
prod is for our production user

Then we need to set the StageVaribles for each API stage which is

dev stage have Stage Variables of "lambdaAlias": "dev"
prod stage have stage variables of "lambdaAlias": "prod"

As you can see both API stage also have lambdaAlias, just the value is different. Therefore we will use this value to differentiate the API call from frontend is either developer or production user.

Again, I talk a lot of details here, I strongly recommend you read it, this will help you better understand throughout the whole series.

In order to achieve that, we do the code below, then I explain step by step.

from aws_cdk import (
    aws_lambda as lambda_,
    aws_apigateway as apigateway, #add this
    core
)

class MySampleStack(core.Stack):

        def __init__(self, scope: core.Construct, id: str, **kwargs) -> None:
           super().__init__(scope, id, **kwargs)

           # ... all the lambda code above 

           # define a dev deployment
           dev_deployment = apigateway.StageOptions(
              stage_name="dev",
              variables={
                "lambdaAlias": "dev" # this is stage variable 
            })

           # define an API 
           api = apigateway.LambdaRestApi(
               self, "MyAPI", # give it a name
               handler=my_first_lambda_function, # the lambda above
               deploy_options=dev_deployment
           )

           #define a prod deployment
           prod_deployment = apigateway.Deployment(
              self, "ProdDeployment08052021", # change the date here
              api=api,
              retain_deployments=True,
              # Change the description here as well for our reference
              description="Production API deployment as 08-05-2021 Live version"
        )

          # Production stage
          prod_stage = apigateway.Stage(
            self, "ProdStage",
            deployment=prod_deployment,
            stage_name="prod",
            variables={
                "lambdaAlias": "prod"
          })
Enter fullscreen mode Exit fullscreen mode

Some explanation for our code above

Dev deployment
dev_deployment: This is our dev deployment. We define a stage named dev and the stage variable key value "lambdaAlias": "dev"

API
api : This is our main API object, it will use my_first_lambda_function that we define above as handler. Means that, when this API endpoint is hit, it will trigger my_first_lambda_function by default(Lambda is not specially set to a method). We specify deploy_options to dev_deployment which means everytime we deploy our CDK, it will only update the dev stage and effect to prod stage, which is what we want. In other words, dev stage is the default stage of our API.

Prod deployment
prod_deployment : This is our prod stage deployment. The ID ProdDeployment08052021 in the code above, after we make sure everything is ok, and we like to push the stack the our production user, we change the date 08052021, by this, CDK will create a brand new deployment for all the code your define in your stack.

Remember, we only want update dev_deployment for testing, then everything ok then only push to production?

This is exactly what we do, let's say we 3 new method to the API, at the meantime, we just testing in dev_deployment, prod_deployment is not effected. At 11-05-2021 we done all the testing, everything ok, is time to push to product, we change to ProdDeployment11052021, this will create a new deployment for all 3 method we defined before.

Prod stage
prod_stage: This is the production stage of our API. All production user will hit this API stage. It will always use prod_deployment, so everytime a new prod_deployment created, it will use that. Therefore change the date in the ID, then new deployment is created, prod_stage will use that. This is how we update our production API stage.

All right, for now the basic of our API is completed.

Now we can add some API method to our API. We can do it like this:

# ... continue with the code above

store = api.root.add_resource("store") 
store.add_method("GET") # GET /store
store.add_method("POST") # POST /store

profile = api.root.add_resource("profile")
profile.add_method("GET") # GET /profile
profile.add_method("POST") # POST /profile

product = api.root.add_resource("product")
product.add_method("GET") # GET /product
product.add_method("DELETE") # DELETE /product

Enter fullscreen mode Exit fullscreen mode

Alright, so now you have 3 API root, which is store, profile and product with all the different CRUD method.

For now, if you ok for all the method you defined, you should change the date in ProdDeployment<Your date> and description in prod_deployment.

For summarize:
In this tutorial, you learned about:
1) How to create different API stage using CDK
2) How to create different API deployment using CDK
3) How to define stage variable for each API stage using CDK
4) How to define API method using CDK

I hope all this make sense to you. Have a good day.

In next part of the series:
For now, all this 3 API root(store, profile , product), no matter what CRUD method, it also will only trigger my_first_lambda_function that we define above.

In next part, I will make different API root, will trigger different lambda function. This is called Lambda Integration.

I also will tell how we can build our CDK Constructs, what is it and why we should use it.

Before you go, if you like this series or find this useful consider to buy me a coffee 😊🤞 for 5 USD or more.
I will prepare a GitHub repo for this whole tutorial series and arrange into separate commit for each part.
This will only available for my supporter cause I spent a lot of time to prepare this. Anyway, I appreciate you here. Have a good day.


bmaco

Shout out to me on Twitter: @upupkenchoong

Discussion (0)