You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
<!-- markdownlint-disable-next-line first-line-heading -->
## Description
As a general rule, the repository template should provide functionality
that works out of the box. The terraform example is problematic because
the options default to running the example, and the example doesn't give
any guidance as to how people should set up their own code.
This patch removes the example, and replaces it with a more fully
explained quick start example in `Scripting_Terraform.md`.
It also adds the `TF_ENV` environment variable, as a shorthand for
selecting the terraform environment directory under
`infrastructure/environments`.
## Type of changes
<!-- What types of changes does your code introduce? Put an `x` in all
the boxes that apply. -->
- [ ] Refactoring (non-breaking change)
- [x] New feature (non-breaking change which adds functionality)
- [x] Breaking change (fix or feature that would change existing
functionality)
- [ ] Bug fix (non-breaking change which fixes an issue)
## Checklist
<!-- Go over all the following points, and put an `x` in all the boxes
that apply. -->
- [ ] I am familiar with the [contributing
guidelines](../docs/CONTRIBUTING.md)
- [ ] I have followed the code style of the project
- [ ] I have added tests to cover my changes
- [ ] I have updated the documentation accordingly
- [ ] This PR is a result of pair or mob programming
---
## Sensitive Information Declaration
To ensure the utmost confidentiality and protect your and others
privacy, we kindly ask you to NOT including [PII (Personal Identifiable
Information) / PID (Personal Identifiable
Data)](https://digital.nhs.uk/data-and-information/keeping-data-safe-and-benefitting-the-public)
or any other sensitive data in this PR (Pull Request) and the codebase
changes. We will remove any PR that do contain any sensitive
information. We really appreciate your cooperation in this matter.
- [x] I confirm that neither PII/PID nor sensitive data are included in
this PR and the codebase changes.
@@ -62,35 +62,202 @@ Here are some key features built into this repository's Terraform module:
62
62
63
63
### Quick start
64
64
65
-
Run the example:
65
+
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.
66
+
67
+
Open the file `infrastructure/modules/private_s3_bucket/main.tf`, and put this in it:
68
+
69
+
```terraform
70
+
# Define the provider
71
+
provider "aws" {
72
+
region = "eu-west-2"
73
+
}
74
+
75
+
variable "bucket_name" {
76
+
description = "Name of the bucket, which can be different per environment"
77
+
}
78
+
79
+
resource "aws_s3_bucket" "my_bucket" {
80
+
bucket = var.bucket_name # Replace with your desired bucket name
81
+
acl = "private"
82
+
}
83
+
```
84
+
85
+
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.
86
+
87
+
Now, we're going to define two deployment environments: `dev`, and `test`. Run this:
88
+
89
+
```bash
90
+
mkdir -p infrastructure/environments/{dev,test}
91
+
```
92
+
93
+
It is important that the directory names match your environment names.
94
+
95
+
Now, let's create the environment definition files. Open `infrastructure/environments/dev/main.tf` and copy in:
96
+
97
+
```terraform
98
+
module "dev_environment" {
99
+
source = "../../modules/private_s3_bucket"
100
+
bucket_name = "nhse-ee-my-fancy-bucket"
101
+
}
102
+
```
103
+
104
+
Some things to note:
105
+
106
+
- 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.
107
+
- 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.
108
+
- 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.
109
+
110
+
Let's create our `test` environment now. Open `infrastructure/environments/test/main.tf` and copy in:
111
+
112
+
```terraform
113
+
module "test_environment" {
114
+
source = "../../modules/private_s3_bucket"
115
+
bucket_name = "nhse-ee-my-fancy-test-bucket"
116
+
}
117
+
```
118
+
119
+
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.
120
+
121
+
Now we have our modules and our environments configured, we need to initialise each of them. Run these two commands:
122
+
123
+
```bash
124
+
TF_ENV=dev make terraform-init
125
+
TF_ENV=test make terraform-init
126
+
```
127
+
128
+
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`.
129
+
130
+
We are now ready to try deploying to AWS, from our local environment.
131
+
132
+
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.
133
+
134
+
Run the following:
135
+
136
+
```shell
137
+
TF_ENV=dev AWS_PROFILE=my-dev-environment make terraform-plan
138
+
```
139
+
140
+
If all is working correctly (and you may need to do a round of `aws sso login` first), you should see this output:
141
+
142
+
```text
143
+
144
+
Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols:
145
+
+ create
146
+
147
+
Terraform will perform the following actions:
148
+
149
+
# module.dev_environment.aws_s3_bucket.my_bucket will be created
150
+
+ resource "aws_s3_bucket" "my_bucket" {
151
+
+ acceleration_status = (known after apply)
152
+
+ acl = "private"
153
+
+ arn = (known after apply)
154
+
+ bucket = "my-dev-bucket"
155
+
+ bucket_domain_name = (known after apply)
156
+
+ bucket_prefix = (known after apply)
157
+
+ bucket_regional_domain_name = (known after apply)
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:
225
+
74
226
```shell
75
-
$ make terraform-example-provision-aws-infrastructure
227
+
TF_ENV=dev AWS_PROFILE=my-dev-environment make terraform-apply opts="-auto-approve"
228
+
```
76
229
77
-
Initializing the backend..
78
-
...
79
-
Plan: 5 to add, 0 to change, 0 to destroy.
80
-
Saved the plan to: terraform.tfplan
81
-
To perform exactly these actions, run the following command to apply:
82
-
terraform apply "terraform.tfplan"
230
+
If you check the contents of your AWS account, you should see your new bucket:
Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols:
245
+
- destroy
246
+
247
+
Terraform will perform the following actions:
248
+
249
+
# module.dev_environment.aws_s3_bucket.my_bucket will be destroyed
250
+
...(more terraform output not shown because it's boring, but the end result is the bucket going away)
92
251
```
93
252
253
+
To create your `test` environment, you run the same commands with `test` where previously you had `dev`:
254
+
255
+
```shell
256
+
TF_ENV=test AWS_PROFILE=my-test-environment make terraform-apply opts="-auto-approve"
257
+
```
258
+
259
+
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).
260
+
94
261
### Your stack implementation
95
262
96
263
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.
terraform-init: # Initialise Terraform - optional: terraform_dir|dir=[path to a directory where the command will be executed, relative to the project's top-level directory, default is one of the module variables or the example directory, if not set], terraform_opts|opts=[options to pass to the Terraform init command, default is none/empty] @Development
_terraform: # Terraform command wrapper - mandatory: cmd=[command to execute]; optional: dir=[path to a directory where the command will be executed, relative to the project's top-level directory, default is one of the module variables or the example directory, if not set], opts=[options to pass to the Terraform command, default is none/empty]
44
-
# 'TERRAFORM_STACK' is passed to the functions as environment variable
0 commit comments