Lessons in AWS Python CDK: 1-Getting Started
Tags: aws, python, beginners, tutorial
Published: 2022-03-05 20:07:02

{% details TLDR %}
Install dependencies:

- Definitely - `brew install aws-cdk`
- Maybe: - node version manager

Bootstrap account:

- `cdk bootstrap aws://<Account_ID><AWS_Region>`

Make Project:

- `cdk init app --language python`

Install Requirements:

- `pip install -r requirements.txt`

Deploy Project:

- `cdk deploy`

Profit
{% enddetails %}

{% details About Me %}
My name is Jakob and I am a DevOps Engineer. I used to be a lot of other things as well (Dish Washer, Retail Employee, Camp Counselor, Army Medic, Infectious Disease Researcher), but now I am a DevOps Engineer. I received no formal CS education but I'm not self taught, because I had thousands of instructors who taught me through their tutorials and blog posts. The culture of information sharing within the software engineering community is vital to everyone, especially those like me who didn't have other options. So, as I learn new things I will be documenting them through the eyes of someone learning for the first time, because those are the people most in need of a guide. Happy Learning! And don't be a stranger.
{% enddetails %}

Note: I am NOT going to be sourcing and fact checking everything here. This is not an O'Reilly book. The language and descriptions are intended to allow beginners to understand. If you want to be pedantic about details or critique my framing of what something is or how it works feel free to write your own post about it. These posts are intended to be enough to get you started so that you can begin breaking things in new ways on your own!

---

## Install The CDK and it's dependencies ##

### The AWS CDK ###

Step one is to install the AWS CDK. I am going to be installing AWS CDK v2 and not v1. Newer is better right? Right?? The official docs are [here](https://docs.aws.amazon.com/cdk/v2/guide/cli.html). 


### Using npm ###
AWS suggests installing with npm (Node Package Manager). Thats fine. Just go to your terminal and make sure you have it installed by checking for the version. (almost always the best way to see if you have something installed)

```sh
npm --version
```

If you have npm installed you can go ahead and install the cdk.

```sh
npm install -g aws-cdk
```

This will globally install the latest version of the aws-cdk. 

Assuming you didn't get any errors, the CDK CLI should now be properly installed and you can check. 

```sh
cdk --version
```

If your output is a version number you are good to go. If it looks like THIS, you will need to change your node version. I will show you how to do that after I discuss the other ways to install the CDK.

![Node Version Error](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/79cpeg16zobkxg785576.png)

### Using Homebrew ###
If you are using Homebrew for everything else, you might as well use it to install the CDK as well. You can also use Homebrew to install the CDK because you feel like it. Sometimes it is nice to have choices! Of course verify that you have Homebrew installed by checking the version. 

```sh
brew --version
```

Then go ahead and install the CDK with Homebrew.

```sh
brew install aws-cdk
```

Assuming you didn't get any errors, the CDK CLI should now be properly installed and you can check. 

```sh
cdk --version
```

If your output is a version number you are good to go. If it looks like THIS, you will need to change your node version. I will show you how to do that after I discuss the other ways to install the CDK.

![Node Version Error](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/79cpeg16zobkxg785576.png)


### Other Ways ###

I am betting you can use a number of other package managers to install the AWS-CDK. Since you are using Python to write your CDK stacks, I bet you can install it with `pip install aws-cdk` or something like that. `apt install aws-cdk` or `yum install aws-cdk` might get you there too. Feel free to try! 

---

## Changing Node Versions ## 

Did you get an error about the CDK not being tested on your current done version. Yeah, me too. I don't use node for anything but the CDK (that I am aware of) so to fix this issue I opted to just change my node version to the most recent supported version: `16.3.0`. You can do it using a [node version manager](https://npm.github.io/installation-setup-docs/installing/using-a-node-version-manager.html). That link has more detailed instructions that you can read to install [nvm](https://github.com/nvm-sh/nvm) (for OSX / *nix) or [nodist](https://github.com/nullivex/nodist) (for Windows). I will summarize the nvm instructions because that is what im using. 

__CAUTION__: It is _risky_ to run remote scripts on your machine. When you see something like `curl <url> | bash` your alarm bells should go off. The command will take the script that you haven't read and execute it on your computer, often with root permissions. Use common sense. Do you trust the source? Have you read the source? 

With that.. To install nvm you can follow their instructions [here](https://github.com/nvm-sh/nvm#installing-and-updating) or you can run the two commands below. The remote script you will execute can be viewed first [here](https://github.com/nvm-sh/nvm/blob/v0.39.1/install.sh).

Install:

```sh
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.1/install.sh | bash
```

Export the directory and Load:

```sh
export NVM_DIR="$([ -z "${XDG_CONFIG_HOME-}" ] && printf %s "${HOME}/.nvm" || printf %s "${XDG_CONFIG_HOME}/nvm")"
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" # This loads nvm
```

Verify that nvm is installed with `vnm --version` and use the above links to troubleshoot further if you run into issues. 

Now that nvm is working you can switch node versions and get rid of that super annoying warning. I am using node version `16.3.0` because that is the newest one that is supported. 

```sh
nvm install 16.3
nvm use 16.3
node -v
```

This should now show that your node version is one that is fully tested with the AWS CDK. Rechecking your CDK version should no longer show the error. 

---

## Bootstrapping your account/region for CDK deployments ##

As I mentioned, CDK is just a great way to use a programming language to build and deploy Cloudformation templates. This means that the CDK will need some infrastructure in place in your account deployment region to work. It will make a bucket for storing your CFn template files and other assets like zipped lambda functions. Bootstrapping will also create a number of roles that the CDK needs to operate. 


![Roles that the CDK makes](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9kmrw9p681bufpa42ke8.png)

### Get your AWS account Number ###

If you have your account number handy you don't need to do anything. But if you are unsure or are using a [Cloud Playground](https://acloudguru.com/platform/cloud-sandbox-playgrounds) (you have added your Access Key ID and Secret Access Key to your `.aws/credentials` file already right?) the easiest way to get your account number is the below sts command.

```sh
aws sts get-caller-identity
```

The output should have the account number of the default account saved at `.aws/credentials`

![return of aws sts get-called-identity](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ry7ygt23hx1nceupph4q.png)

Hint: hit `q` to leave screens like this.

Then you use that account number and your deployment region in the bootstrap command.

```sh
cdk bootstrap aws://<AccountID>/<region>
```

You should see the following satisfying output as the CDK gets busy making things for you.

![cdk bootstrap output](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hqu7zieoeaimzbapvsq5.png)

Once the bootstrapping process is completed you are ready to make your first project.  Just be aware that if you update your CDK version (and it is being developed and versioned at a rapid pace) you may need to bootstrap the account/region again. 

Also, a special note for those who may be sharing an AWS account, if another person upgrades their CDK version and then updates the bootstrap version, you may be forced to update your CDK version to match. Keep your eyes open for strange errors. 

---

## Make a project

Wahoo!!  We can finally get started making a project! 

To make a CDK project you need to start with an empty directory. Note that the name of this directory will be the default name of your stack. Don't worry, you will be able to change things after the cdk project is first created, but you can do yourself a favor name the directory something meaningful. 

So, to repeat, you will make an empty directory and then initialize the cdk project within that empty directory.

```sh
mkdir <project-name>
cd <project-name>
cdk init app --language python
```

This is what it would look like to make my groundbreaking disruptor project I have in the works. 

![cdk init](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7w0uswvp5jsu3x6aa44m.png)

Once the init is done, you will find that a virtual environment has been created and activated for you (.venv) and a git repository has also been initialized. Additionally, the previously empty folder will have a number of assets in it. 

![assets created by cdk init](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ejhso3wfronerf7uu2dj.png)

The most important ones for you to note will be `requirements.txt`, `app.py`, and `uber_for_cats/uber_for_cats_stack.py`. we will address them in that order. 

### `requirements.txt` ###

If you are working in python, you should use a virtual environment for your development. Seriously. Especially if you plan on deploying things to the cloud and having them work there. When you first `init` your project, the cdk creates and activates a virtual environment for you. It uses .venv I'm sure to keep it at the top of the file structure. 

Using a virtual environment allows you to install and import python packages in different versions and varieties for use in your project while not impacting the rest of your system. One project uses version 1 and another uses version 2.2? no problem. The versions that you want of your project are specified in the `requirements.txt` file. Open up the file and you will see that there are two requirements already! Install them with pip. 

```sh
pip install -r requirements.txt
```

Note that the above command can be repeated any time you have an additional dependency or version change.

Now that the requirements are installed, lets move on to the next `important file`.

### `app.py` ###

The `app.py` file in the root of your project directory is where everything starts.

![app.py](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/lrygcavw3156n4hrjw0n.png)

There are a number of things to talk about with this file. 


- `os` is imported on `line 2`. This is so that, if you were to comment out `line 18` you would be able to pull some environmental variables from whatever is building this stack. 
- `aws_cdk` is imported as `cdk` (remember that is one of the things installed via `pip install -r requirements.txt`). This is so that the app object can be created in `line 9` and the cloudformation template can be created in `line 28`. 
- `UberForCats` class is imported from the other important file we are going to talk about next. The class is scoped the the `cdk.App` construct and named. 
- You can change the names of your folders/files and classes if you would like, but make sure the change is reflected in `line 6` and maybe `line 10`. Think of it this way:

```python
from directory/file import class_name
```
  
- There are a number of commented out arguments in this class that we aren't really going to touch on, but you can read the comments and get the gist of it. 


### `uber_for_cats.uber_for_cats_stack.py` ###

This file is the meat and potatoes of the cdk magic. 

![uber_for_cats.py](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/spycdqva66d3atck181j.png)

I have uncommented the sqs queue example that comes with the template so that we can see it easier in the IDE. It contains a couple of things.

- Standard imports at the top for the file. 
- The `UberForCastStack` class. Now, I am going to be honest with you, I don't mess with the code from `line 8` to `line 11`. I just leave it there and start building the stack below. maybe I'm a coward. 
- Resources! `Line 16` to `line 19` create an SQS Queue that will be named `UberForCatsQueue` with the parameter `visibility_timeout` set to 300 seconds. 
  - Documentation for the other parameters is at [https://docs.aws.amazon.com/cdk/api/v2/python/aws_cdk.aws_sqs/Queue.html]()
  - While the queue will have "UberForCatsQueue" in its name in AWS, it is called "queue" in this stack. This will allow us to reference it for other things like if we were to use it for a lambda trigger. 

## Deploy a Project ##

Remember that the CDK is used to make a CloudFormation template which CloudFormation then deploys. To view the the CFn template execute:

```sh
cdk synth
```

This will output the CFn template in yaml format on your terminal as well as save it formatted in json at `cdk.out/UberForCatsStack.template.json`. There is a lot more than what is included on the screenshot below, but that is what the important part is. 

![cdk.out/template.json](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/o4w5l5rgpkgsgly2bu56.png)

You can also run a command that will compare your desired state (the result of a `cdk synth`) and what is currently saved as the desired state in aws. Think of it like `terraform plan`.

```sh
cdk diff
```

This one is pretty busy because I don't have ANYTHING in the stack yet. 

![cdk diff](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/lmjfflazlsrbehpixlwu.png)

To deploy the resources you will run trhe following command:

```sh
cdk deploy
```

It may ask you to approve it there are any IAM permissions increases, but otherwise it will synthesize your CFn template, upload it to S3, and then cloudformation will begin deploying it. 

![cdk deploy](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/q1ngch30ajs4d41mum7u.png)

After it is complete, we will have the stack and an SQS Queue in AWS. 


![CFn stack](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/u6xb258ebqsb3m578nht.png)

![CFn queue](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ymkx6vp2e2wk5gt13kax.png)

But Wait!!  That isn't the name I wanted to give the queue! Lets add a parameter to the stack, safe the file and run `cdk diff`

![change queue name](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/glhj1fsfv1wh18gnn8zp.png)
![cdk diff](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/tsakzlxhka6mzxnvzak4.png)

You can see that it is telling is that if we make the changes we are adding a QueueName "UberForCatsQueue" and that will require a replacement of the queue.  Note that not all changes would require a replacement. 

![new queue](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/yytegm56rkxa5svcr66l.png)

Thats, better. Now it is easier to read if you are in the console, but this is definitely not needed if you just care about your stack working with itself. 


Okay, now that we have had our fun, and because who needs an UberForCats, Lets get rid of all those resources.

```sh
cdk destroy
```

![cdk destroy](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/r8icvyqjiwzopy1obplp.png)

## Conclusion ##

Alright, those are the bones of setting up, deploying, and destroying a CDK project in AWS. There are a number of `neater` things that I have learned in the course of deploying resources with the CDK and I cant wait to share them with you. But this is already too long. Until next time!