Skip to content

Commit

Permalink
Merge branch 'main' into wip-lambda-tutorial
Browse files Browse the repository at this point in the history
  • Loading branch information
regularfry authored May 22, 2024
2 parents 1fa6e52 + 0ed3c55 commit b269fa6
Show file tree
Hide file tree
Showing 20 changed files with 319 additions and 190 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,5 @@ runs:
- name: "Check English usage"
shell: bash
run: |
export BRANCH_NAME=origin/${{ github.event.repository.default_branch }}
check=branch ./scripts/githooks/check-english-usage.sh
8 changes: 4 additions & 4 deletions .github/workflows/stage-1-commit.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -56,17 +56,17 @@ jobs:
- name: "Check file format"
uses: ./.github/actions/check-file-format
check-markdown-format:
name: "Check markdown format"
name: "Check Markdown format"
runs-on: ubuntu-latest
timeout-minutes: 2
steps:
- name: "Checkout code"
uses: actions/checkout@v4
with:
fetch-depth: 0 # Full history is needed to compare branches
- name: "Check markdown format"
- name: "Check Markdown format"
uses: ./.github/actions/check-markdown-format
lint-prose:
check-english-usage:
name: "Check English usage"
runs-on: ubuntu-latest
timeout-minutes: 2
Expand All @@ -76,7 +76,7 @@ jobs:
with:
fetch-depth: 0 # Full history is needed to compare branches
- name: "Check English usage"
uses: ./.github/actions/lint-prose
uses: ./.github/actions/check-english-usage
lint-terraform:
name: "Lint Terraform"
runs-on: ubuntu-latest
Expand Down
5 changes: 3 additions & 2 deletions .tool-versions
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# This file is for you! Please, updated to the versions agreed by your team.

terraform 1.5.7
pre-commit 3.4.0
terraform 1.7.0
pre-commit 3.6.0

# ==============================================================================
# The section below is reserved for Docker image versions.
Expand All @@ -15,6 +15,7 @@ pre-commit 3.4.0
# docker/ghcr.io/nhs-england-tools/github-runner-image 20230909-321fd1e-rt@sha256:ce4fd6035dc450a50d3cbafb4986d60e77cb49a71ab60a053bb1b9518139a646 # SEE: https://github.com/nhs-england-tools/github-runner-image/pkgs/container/github-runner-image
# docker/hadolint/hadolint 2.12.0-alpine@sha256:7dba9a9f1a0350f6d021fb2f6f88900998a4fb0aaf8e4330aa8c38544f04db42 # SEE: https://hub.docker.com/r/hadolint/hadolint/tags
# docker/hashicorp/terraform 1.5.6@sha256:180a7efa983386a27b43657ed610e9deed9e6c3848d54f9ea9b6cb8a5c8c25f5 # SEE: https://hub.docker.com/r/hashicorp/terraform/tags
# docker/jdkato/vale v2.29.7@sha256:5ccfac574231b006284513ac3e4e9f38833989d83f2a68db149932c09de85149 # SEE: https://hub.docker.com/r/jdkato/vale/tags
# docker/koalaman/shellcheck latest@sha256:e40388688bae0fcffdddb7e4dea49b900c18933b452add0930654b2dea3e7d5c # SEE: https://hub.docker.com/r/koalaman/shellcheck/tags
# docker/mstruebing/editorconfig-checker 2.7.1@sha256:dd3ca9ea50ef4518efe9be018d669ef9cf937f6bb5cfe2ef84ff2a620b5ddc24 # SEE: https://hub.docker.com/r/mstruebing/editorconfig-checker/tags
# docker/sonarsource/sonar-scanner-cli 5.0.1@sha256:494ecc3b5b1ee1625bd377b3905c4284e4f0cc155cff397805a244dee1c7d575 # SEE: https://hub.docker.com/r/sonarsource/sonar-scanner-cli/tags
14 changes: 10 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,9 +48,6 @@ The following software packages, or their equivalents, are expected to be instal
- [Docker](https://www.docker.com/) container runtime or a compatible tool, e.g. [Podman](https://podman.io/),
- [asdf](https://asdf-vm.com/) version manager,
- [GNU make](https://www.gnu.org/software/make/) 3.82 or later,
- [GNU coreutils](https://www.gnu.org/software/coreutils/) and [GNU binutils](https://www.gnu.org/software/binutils/) may be required to build dependencies like Python, which may need to be compiled during installation. For macOS users, this has been scripted and automated by the `dotfiles` project; please see this [script](https://github.com/nhs-england-tools/dotfiles/blob/main/assets/20-install-base-packages.macos.sh) for details,
- [Python](https://www.python.org/) required to run Git hooks,
- [`jq`](https://jqlang.github.io/jq/) a lightweight and flexible command-line JSON processor.

> [!NOTE]<br>
> The version of GNU make available by default on macOS is earlier than 3.82. You will need to upgrade it or certain `make` tasks will fail. On macOS, you will need [Homebrew](https://brew.sh/) installed, then to install `make`, like so:
Expand All @@ -59,7 +56,16 @@ The following software packages, or their equivalents, are expected to be instal
> brew install make
> ```
>
> You will then see instructions to fix your `$PATH` variable to make the newly installed version available. If you are using [dotfiles](https://github.com/nhs-england-tools/dotfiles), this is all done for you.
> You will then see instructions to fix your [`$PATH`](https://github.com/nhs-england-tools/dotfiles/blob/main/dot_path.tmpl) variable to make the newly installed version available. If you are using [dotfiles](https://github.com/nhs-england-tools/dotfiles), this is all done for you.
- [GNU sed](https://www.gnu.org/software/sed/) and [GNU grep](https://www.gnu.org/software/grep/) are required for the scripted command-line output processing,
- [GNU coreutils](https://www.gnu.org/software/coreutils/) and [GNU binutils](https://www.gnu.org/software/binutils/) may be required to build dependencies like Python, which may need to be compiled during installation,
> [!NOTE]<br>
> For macOS users, installation of the GNU toolchain has been scripted and automated as part of the `dotfiles` project. Please see this [script](https://github.com/nhs-england-tools/dotfiles/blob/main/assets/20-install-base-packages.macos.sh) for details.
- [Python](https://www.python.org/) required to run Git hooks,
- [`jq`](https://jqlang.github.io/jq/) a lightweight and flexible command-line JSON processor.
### Configuration
Expand Down
203 changes: 185 additions & 18 deletions docs/developer-guides/Scripting_Terraform.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,35 +62,202 @@ Here are some key features built into this repository's Terraform module:

### Quick start

Run the example:
The Repository Template assumes that you will be constructing the bulk of your infrastructure in `infrastructure/modules` as generic deployment configuration, which you will then compose into environment-specific modules, each stored in their own directory under `infrastructure/environments`. Let's create a simple deployable thing, and configure an S3 bucket. We'll make the name of the bucket a variable, so that each environment can have its own.

Open the file `infrastructure/modules/private_s3_bucket/main.tf`, and put this in it:

```terraform
# Define the provider
provider "aws" {
region = "eu-west-2"
}
variable "bucket_name" {
description = "Name of the bucket, which can be different per environment"
}
resource "aws_s3_bucket" "my_bucket" {
bucket = var.bucket_name # Replace with your desired bucket name
acl = "private"
}
```

Note that the variable has been given no value. This is intentional, and allows us to pass the bucket name in as a parameter from the environment.

Now, we're going to define two deployment environments: `dev`, and `test`. Run this:

```bash
mkdir -p infrastructure/environments/{dev,test}
```

It is important that the directory names match your environment names.

Now, let's create the environment definition files. Open `infrastructure/environments/dev/main.tf` and copy in:

```terraform
module "dev_environment" {
source = "../../modules/private_s3_bucket"
bucket_name = "nhse-ee-my-fancy-bucket"
}
```

Some things to note:

- The `source` path is relative to the directory that the `main.tf` file is in. When `terraform` runs, it will `chdir` to that directory first, before doing anything else.
- The `module` name, `"dev_environment"` here, can be anything. Module names are only scoped to the file they're in, so you don't need to follow any particular convention here.
- The `bucket_name` is going to end up as the bucket name in AWS. It wants to be meaningful to you, and you need to pick your own. The framework doesn't constrain your choice, but remember that AWS needs them to be globally unique and if you steal `"nhse-ee-my-fancy-bucket"` then I can't test these docs and then I will be sad.

Let's create our `test` environment now. Open `infrastructure/environments/test/main.tf` and copy in:

```terraform
module "test_environment" {
source = "../../modules/private_s3_bucket"
bucket_name = "nhse-ee-my-fancy-test-bucket"
}
```

We have changed the bucket name here. In this example, I am making no assumptions as to how your AWS accounts are set up. If you intend for your development and test infrastructure to be in the same AWS account (perhaps by necessity, for organisational reasons) and you need to separate them by a naming convention, the framework can support that.

Now we have our modules and our environments configured, we need to initialise each of them. Run these two commands:

```bash
TF_ENV=dev make terraform-init
TF_ENV=test make terraform-init
```

Each invocation will download the `terraform` dependencies we need. The `TF_ENV` name we give to each invocation is the name of the environment, and must match the directory name we chose under `infrastructure/environments` so that `make` gives the right parameters to `terraform`.

We are now ready to try deploying to AWS, from our local environment.

I am going to assume that you have an `~/.aws/credentials` file set up with a separate profile for each environment that you want to use, called `my-test-environment` and `my-dev-environment`. They might have the same credential values in them, in which case `terraform` will create the resources in the same account; or you might have them set up to deploy to different accounts. Either would work.

Run the following:

```shell
TF_ENV=dev AWS_PROFILE=my-dev-environment make terraform-plan
```

If all is working correctly (and you may need to do a round of `aws sso login` first), you should see this output:

```text
Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols:
+ create
Terraform will perform the following actions:
# module.dev_environment.aws_s3_bucket.my_bucket will be created
+ resource "aws_s3_bucket" "my_bucket" {
+ acceleration_status = (known after apply)
+ acl = "private"
+ arn = (known after apply)
+ bucket = "my-dev-bucket"
+ bucket_domain_name = (known after apply)
+ bucket_prefix = (known after apply)
+ bucket_regional_domain_name = (known after apply)
+ force_destroy = false
+ hosted_zone_id = (known after apply)
+ id = (known after apply)
+ object_lock_enabled = (known after apply)
+ policy = (known after apply)
+ region = (known after apply)
+ request_payer = (known after apply)
+ tags_all = (known after apply)
+ website_domain = (known after apply)
+ website_endpoint = (known after apply)
}
Plan: 1 to add, 0 to change, 0 to destroy.
─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
Note: You didn't use the -out option to save this plan, so Terraform can't guarantee to take exactly these actions if you run "terraform apply" now.
```

No errors found, so we can now create the bucket:

```shell
# AWS console access setup
export AWS_ACCESS_KEY_ID="..."
export AWS_SECRET_ACCESS_KEY="..."
export AWS_SESSION_TOKEN="..."
$ TF_ENV=dev AWS_PROFILE=my-dev-environment make terraform-apply

Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols:
+ create

Terraform will perform the following actions:

# module.dev_environment.aws_s3_bucket.my_bucket will be created
+ resource "aws_s3_bucket" "my_bucket" {
+ acceleration_status = (known after apply)
+ acl = (known after apply)
+ arn = (known after apply)
+ bucket = "nhse-ee-my-dev-bucket"
+ bucket_domain_name = (known after apply)
+ bucket_prefix = (known after apply)
+ bucket_regional_domain_name = (known after apply)
+ force_destroy = false
+ hosted_zone_id = (known after apply)
+ id = (known after apply)
+ object_lock_enabled = (known after apply)
+ policy = (known after apply)
+ region = (known after apply)
+ request_payer = (known after apply)
+ tags_all = (known after apply)
+ website_domain = (known after apply)
+ website_endpoint = (known after apply)
}

Plan: 1 to add, 0 to change, 0 to destroy.

Do you want to perform these actions?
Terraform will perform the actions described above.
Only 'yes' will be accepted to approve.

Enter a value: yes

module.dev_environment.aws_s3_bucket.my_bucket: Creating...
module.dev_environment.aws_s3_bucket.my_bucket: Creation complete after 1s [id=nhse-ee-my-dev-bucket]

Apply complete! Resources: 1 added, 0 changed, 0 destroyed.

```

You will notice here that I needed to confirm the action to `terraform` manually. If you don't want to do that, you can pass the `-auto-approve` option to `terraform` like this:

```shell
$ make terraform-example-provision-aws-infrastructure
TF_ENV=dev AWS_PROFILE=my-dev-environment make terraform-apply opts="-auto-approve"
```

Initializing the backend..
...
Plan: 5 to add, 0 to change, 0 to destroy.
Saved the plan to: terraform.tfplan
To perform exactly these actions, run the following command to apply:
terraform apply "terraform.tfplan"
If you check the contents of your AWS account, you should see your new bucket:

```shell
$ aws s3 ls --profile my-dev-environment
...
Apply complete! Resources: 5 added, 0 changed, 0 destroyed.
2024-03-01 16:33:55 nhse-ee-my-dev-bucket
```

$ make terraform-example-destroy-aws-infrastructure
Now I don't want to leave that there, so I will run the corresponding `destroy` command to get rid of it:

...
Plan: 0 to add, 0 to change, 5 to destroy.
...
Apply complete! Resources: 0 added, 0 changed, 5 destroyed.
```shell
$ TF_ENV=dev AWS_PROFILE=my-dev-environment make terraform-destroy opts="-auto-approve"
module.dev_environment.aws_s3_bucket.my_bucket: Refreshing state... [id=nhse-ee-my-dev-bucket]

Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols:
- destroy

Terraform will perform the following actions:

# module.dev_environment.aws_s3_bucket.my_bucket will be destroyed
...(more terraform output not shown because it's boring, but the end result is the bucket going away)
```
To create your `test` environment, you run the same commands with `test` where previously you had `dev`:
```shell
TF_ENV=test AWS_PROFILE=my-test-environment make terraform-apply opts="-auto-approve"
```
To use the same `terraform` files in a GitHub action, see the docs [here](https://docs.github.com/en/actions/deployment/security-hardening-your-deployments/configuring-openid-connect-in-amazon-web-services).
### Your stack implementation
Always follow [best practices for using Terraform](https://cloud.google.com/docs/terraform/best-practices-for-terraform) while providing infrastructure as code (IaC) for your service.
Expand Down
Loading

0 comments on commit b269fa6

Please sign in to comment.