rails_template_18f 2.1.0 → 2.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (57) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +12 -0
  3. data/Gemfile.lock +85 -70
  4. data/lib/generators/rails_template18f/active_storage/active_storage_generator.rb +4 -3
  5. data/lib/generators/rails_template18f/auditree/auditree_generator.rb +36 -6
  6. data/lib/generators/rails_template18f/auditree/templates/gitlab/auditree.yml.tt +48 -0
  7. data/lib/generators/rails_template18f/circleci/templates/circleci/config.yml.tt +6 -2
  8. data/lib/generators/rails_template18f/cloud_gov_config/cloud_gov_config_generator.rb +0 -8
  9. data/lib/generators/rails_template18f/cloud_gov_config/templates/app/models/cloud_gov_config.rb +6 -15
  10. data/lib/generators/rails_template18f/cloud_gov_config/templates/spec/models/cloud_gov_config_spec.rb +13 -19
  11. data/lib/generators/rails_template18f/github_actions/github_actions_generator.rb +0 -4
  12. data/lib/generators/rails_template18f/github_actions/templates/github/dependabot.yml.tt +16 -0
  13. data/lib/generators/rails_template18f/github_actions/templates/github/workflows/deploy-production.yml +4 -1
  14. data/lib/generators/rails_template18f/github_actions/templates/github/workflows/deploy-staging.yml +4 -1
  15. data/lib/generators/rails_template18f/github_actions/templates/github/workflows/terraform-production.yml +4 -1
  16. data/lib/generators/rails_template18f/github_actions/templates/github/workflows/terraform-staging.yml +4 -1
  17. data/lib/generators/rails_template18f/gitlab_ci/gitlab_ci_generator.rb +9 -18
  18. data/lib/generators/rails_template18f/gitlab_ci/templates/gitlab/{node.yml.tt → node.yml} +1 -1
  19. data/lib/generators/rails_template18f/gitlab_ci/templates/gitlab/rails.yml +11 -18
  20. data/lib/generators/rails_template18f/gitlab_ci/templates/gitlab-ci.yml.tt +80 -152
  21. data/lib/generators/rails_template18f/oscal/oscal_generator.rb +15 -1
  22. data/lib/generators/rails_template18f/oscal/templates/bin/trestle.tt +10 -1
  23. data/lib/generators/rails_template18f/oscal/templates/gitlab/trestle.yml.tt +29 -0
  24. data/lib/generators/rails_template18f/public_egress/public_egress_generator.rb +2 -2
  25. data/lib/generators/rails_template18f/sidekiq/templates/config/initializers/redis.rb +1 -1
  26. data/lib/generators/rails_template18f/terraform/templates/gitlab_bootstrap/apply.sh +25 -0
  27. data/lib/generators/rails_template18f/terraform/templates/gitlab_bootstrap/main.tf.tt +114 -0
  28. data/lib/generators/rails_template18f/terraform/templates/gitlab_bootstrap/setup_shadowenv.sh +61 -0
  29. data/lib/generators/rails_template18f/terraform/templates/s3_bootstrap/common/templates/backend_config.tftpl +6 -0
  30. data/lib/generators/rails_template18f/terraform/templates/s3_bootstrap/common/users.auto.tfvars +5 -0
  31. data/lib/generators/rails_template18f/terraform/templates/{full_bootstrap → s3_bootstrap/full}/main.tf.tt +7 -27
  32. data/lib/generators/rails_template18f/terraform/templates/{sandbox_bootstrap → s3_bootstrap/sandbox}/main.tf.tt +6 -19
  33. data/lib/generators/rails_template18f/terraform/templates/terraform/.shadowenv.d/.gitignore +3 -0
  34. data/lib/generators/rails_template18f/terraform/templates/terraform/README.md.tt +41 -29
  35. data/lib/generators/rails_template18f/terraform/templates/terraform/app.tf.tt +7 -6
  36. data/lib/generators/rails_template18f/terraform/templates/terraform/main.tf.tt +16 -14
  37. data/lib/generators/rails_template18f/terraform/templates/terraform/{production.tfvars.tt → production.env.tfvars.tt} +0 -1
  38. data/lib/generators/rails_template18f/terraform/templates/terraform/providers.tf.tt +6 -8
  39. data/lib/generators/rails_template18f/terraform/templates/terraform/staging.env.tfvars.tt +7 -0
  40. data/lib/generators/rails_template18f/terraform/templates/terraform/terraform.sh.tt +52 -18
  41. data/lib/generators/rails_template18f/terraform/templates/terraform/variables.tf.tt +15 -11
  42. data/lib/generators/rails_template18f/terraform/terraform_generator.rb +80 -6
  43. data/lib/rails_template18f/generators/cloud_gov_parsing.rb +2 -2
  44. data/lib/rails_template18f/version.rb +1 -1
  45. data/template.rb +33 -16
  46. data/templates/README.md.tt +1 -1
  47. metadata +23 -17
  48. data/lib/generators/rails_template18f/gitlab_ci/templates/gitlab/terraform.yml +0 -28
  49. data/lib/generators/rails_template18f/terraform/templates/terraform/bootstrap/templates/backend_config.tftpl +0 -8
  50. data/lib/generators/rails_template18f/terraform/templates/terraform/staging.tfvars.tt +0 -8
  51. /data/lib/generators/rails_template18f/{github_actions → oscal}/templates/github/workflows/assemble-ssp.yml.tt +0 -0
  52. /data/lib/generators/rails_template18f/{github_actions → oscal}/templates/github/workflows/validate-ssp.yml +0 -0
  53. /data/lib/generators/rails_template18f/terraform/templates/{terraform/bootstrap → gitlab_bootstrap}/users.auto.tfvars +0 -0
  54. /data/lib/generators/rails_template18f/terraform/templates/{terraform/bootstrap → s3_bootstrap/common}/apply.sh +0 -0
  55. /data/lib/generators/rails_template18f/terraform/templates/{terraform/bootstrap → s3_bootstrap/common}/templates/bot_secrets.tftpl +0 -0
  56. /data/lib/generators/rails_template18f/terraform/templates/{full_bootstrap → s3_bootstrap/full}/imports.tf.tftpl +0 -0
  57. /data/lib/generators/rails_template18f/terraform/templates/{sandbox_bootstrap → s3_bootstrap/sandbox}/imports.tf.tftpl +0 -0
@@ -0,0 +1,61 @@
1
+ #!/usr/bin/env bash
2
+ #
3
+ # Setup .shadowenv.d/ files for terraform configuration
4
+
5
+ set -e
6
+
7
+ # ensure we're operating with the correct relative paths
8
+ cd `dirname "$0"`
9
+
10
+ shadowenv trust && eval "$(shadowenv hook)"
11
+
12
+ ans=""
13
+ prompt_ans() {
14
+ local prompt="$1"
15
+ local default="$2"
16
+ if [ -n "$default" ]; then
17
+ prompt="$prompt (default: $default)"
18
+ fi
19
+ read -r -p "$prompt: " ans
20
+ }
21
+
22
+ prompt_ans "GitLab hostname" "${GITLAB_HOSTNAME:=workshop.cloud.gov}"
23
+ if [ -n "$ans" ]; then
24
+ GITLAB_HOSTNAME="$ans"
25
+ fi
26
+
27
+ prompt_ans "GitLab project id" "$GITLAB_PROJECT_ID"
28
+ if [ -n "$ans" ]; then
29
+ GITLAB_PROJECT_ID="$ans"
30
+ fi
31
+
32
+ if [ ! -d ../.shadowenv.d ]; then
33
+ mkdir ../.shadowenv.d
34
+ fi
35
+
36
+ cat <<EOF > ../.shadowenv.d/100_gitlab_project.lisp
37
+ (provide "gitlab-backend-config")
38
+ (env/set "GITLAB_PROJECT_ID" "$GITLAB_PROJECT_ID")
39
+ (env/set "GITLAB_HOSTNAME" "$GITLAB_HOSTNAME")
40
+ (env/set "GITLAB_BASE_URL" "https://${GITLAB_HOSTNAME}/api/v4")
41
+ EOF
42
+
43
+ prompt_ans "GitLab username" "$TF_HTTP_USERNAME"
44
+ if [ -n "$ans" ]; then
45
+ TF_HTTP_USERNAME=$ans
46
+ fi
47
+ if [ -z "$TF_HTTP_PASSWORD" ]; then
48
+ prompt_ans "GitLab PAT (with api scope)"
49
+ else
50
+ prompt_ans "GitLab PAT (with api scope, Leave blank to re-use existing PAT)"
51
+ fi
52
+ if [ -n "$ans" ]; then
53
+ TF_HTTP_PASSWORD=$ans
54
+ fi
55
+
56
+ cat <<EOF > ../.shadowenv.d/500_tf_backend_secrets.lisp
57
+ (provide "tf-backend-secrets")
58
+ (env/set "TF_HTTP_USERNAME" "$TF_HTTP_USERNAME")
59
+ (env/set "TF_HTTP_PASSWORD" "$TF_HTTP_PASSWORD")
60
+ (env/set "GITLAB_TOKEN" "$TF_HTTP_PASSWORD")
61
+ EOF
@@ -0,0 +1,6 @@
1
+ (provide "terraform-backend-config")
2
+ (env/set "S3_BUCKET_NAME" "${creds.bucket}")
3
+ (env/set "AWS_ACCESS_KEY_ID" "${creds.access_key_id}")
4
+ (env/set "AWS_SECRET_ACCESS_KEY" "${creds.secret_access_key}")
5
+ ; not a secret, but setting it here enables the aws cli to work when in the terraform directory
6
+ (env/set "AWS_REGION" "${creds.region}")
@@ -0,0 +1,5 @@
1
+ terraform_users = [
2
+ # add your terraform_users list here: example values:
3
+ # "team.member@gsa.gov",
4
+ # "cf_user-guid-value-for-space-developer-service-account",
5
+ ]
@@ -3,7 +3,7 @@ terraform {
3
3
  required_providers {
4
4
  cloudfoundry = {
5
5
  source = "cloudfoundry/cloudfoundry"
6
- version = "1.2.0"
6
+ version = "~> 1.10"
7
7
  }
8
8
  }
9
9
  }
@@ -59,7 +59,7 @@ data "cloudfoundry_service_plans" "cg_service_account" {
59
59
  locals {
60
60
  sa_service_name = "<%= app_name %>-cicd-deployer"
61
61
  sa_key_name = "cicd-deployer-access-key"
62
- sa_bot_credentials = jsondecode(data.cloudfoundry_service_credential_binding.runner_sa_key.credential_bindings.0.credential_binding).credentials
62
+ sa_bot_credentials = jsondecode(cloudfoundry_service_credential_binding.runner_sa_key.credential_binding).credentials
63
63
  sa_cf_username = nonsensitive(local.sa_bot_credentials.username)
64
64
  sa_cf_password = local.sa_bot_credentials.password
65
65
  }
@@ -67,7 +67,7 @@ resource "cloudfoundry_service_instance" "runner_service_account" {
67
67
  name = local.sa_service_name
68
68
  type = "managed"
69
69
  space = module.mgmt_space.space_id
70
- service_plan = data.cloudfoundry_service_plans.cg_service_account.service_plans.0.id
70
+ service_plan = data.cloudfoundry_service_plans.cg_service_account.service_plans[0].id
71
71
  depends_on = [module.mgmt_space]
72
72
  }
73
73
  resource "cloudfoundry_service_credential_binding" "runner_sa_key" {
@@ -75,11 +75,6 @@ resource "cloudfoundry_service_credential_binding" "runner_sa_key" {
75
75
  service_instance = cloudfoundry_service_instance.runner_service_account.id
76
76
  type = "key"
77
77
  }
78
- data "cloudfoundry_service_credential_binding" "runner_sa_key" {
79
- name = local.sa_key_name
80
- service_instance = cloudfoundry_service_instance.runner_service_account.id
81
- depends_on = [cloudfoundry_service_credential_binding.runner_sa_key]
82
- }
83
78
  data "cloudfoundry_org" "org" {
84
79
  name = local.org_name
85
80
  }
@@ -87,24 +82,16 @@ data "cloudfoundry_user" "sa_user" {
87
82
  name = local.sa_cf_username
88
83
  }
89
84
  resource "cloudfoundry_org_role" "sa_org_manager" {
90
- user = data.cloudfoundry_user.sa_user.users.0.id
85
+ user = data.cloudfoundry_user.sa_user.users[0].id
91
86
  type = "organization_manager"
92
87
  org = data.cloudfoundry_org.org.id
93
88
  }
94
89
 
95
- locals {
96
- bucket_creds_key_name = "backend-state-bucket-creds"
97
- }
98
90
  resource "cloudfoundry_service_credential_binding" "bucket_creds" {
99
- name = local.bucket_creds_key_name
91
+ name = "backend-state-bucket-creds"
100
92
  service_instance = module.s3.bucket_id
101
93
  type = "key"
102
94
  }
103
- data "cloudfoundry_service_credential_binding" "bucket_creds" {
104
- name = local.bucket_creds_key_name
105
- service_instance = module.s3.bucket_id
106
- depends_on = [cloudfoundry_service_credential_binding.bucket_creds]
107
- }
108
95
 
109
96
  locals {
110
97
  import_map = {
@@ -129,12 +116,12 @@ resource "local_file" "recreate_script" {
129
116
  }
130
117
 
131
118
  locals {
132
- bucket_creds = jsondecode(data.cloudfoundry_service_credential_binding.bucket_creds.credential_bindings.0.credential_binding).credentials
119
+ bucket_creds = jsondecode(cloudfoundry_service_credential_binding.bucket_creds.credential_binding).credentials
133
120
  backend_config = templatefile("${path.module}/templates/backend_config.tftpl", { creds = local.bucket_creds })
134
121
  }
135
122
  resource "local_sensitive_file" "bucket_creds" {
136
123
  content = local.backend_config
137
- filename = "${path.module}/../secrets.backend.tfvars"
124
+ filename = "${path.module}/../.shadowenv.d/500_tf_backend_secrets.lisp"
138
125
  file_permission = "0600"
139
126
  }
140
127
 
@@ -150,10 +137,3 @@ resource "local_sensitive_file" "bot_secrets_file" {
150
137
  password = local.sa_cf_password
151
138
  })
152
139
  }
153
-
154
- output "mgmt_space_id" {
155
- value = module.mgmt_space.space_id
156
- }
157
- output "mgmt_org_id" {
158
- value = data.cloudfoundry_org.org.id
159
- }
@@ -3,7 +3,7 @@ terraform {
3
3
  required_providers {
4
4
  cloudfoundry = {
5
5
  source = "cloudfoundry/cloudfoundry"
6
- version = "1.2.0"
6
+ version = "~> 1.10"
7
7
  }
8
8
  }
9
9
  }
@@ -44,38 +44,25 @@ data "cloudfoundry_service_plans" "cg_service_account" {
44
44
  locals {
45
45
  sa_service_name = "<%= app_name %>-cicd-deployer"
46
46
  sa_key_name = "cicd-deployer-access-key"
47
- sa_bot_credentials = jsondecode(data.cloudfoundry_service_credential_binding.runner_sa_key.credential_bindings.0.credential_binding).credentials
47
+ sa_bot_credentials = jsondecode(cloudfoundry_service_credential_binding.runner_sa_key.credential_binding).credentials
48
48
  }
49
49
  resource "cloudfoundry_service_instance" "runner_service_account" {
50
50
  name = local.sa_service_name
51
51
  type = "managed"
52
52
  space = data.cloudfoundry_space.space.id
53
- service_plan = data.cloudfoundry_service_plans.cg_service_account.service_plans.0.id
53
+ service_plan = data.cloudfoundry_service_plans.cg_service_account.service_plans[0].id
54
54
  }
55
55
  resource "cloudfoundry_service_credential_binding" "runner_sa_key" {
56
56
  name = local.sa_key_name
57
57
  service_instance = cloudfoundry_service_instance.runner_service_account.id
58
58
  type = "key"
59
59
  }
60
- data "cloudfoundry_service_credential_binding" "runner_sa_key" {
61
- name = local.sa_key_name
62
- service_instance = cloudfoundry_service_instance.runner_service_account.id
63
- depends_on = [cloudfoundry_service_credential_binding.runner_sa_key]
64
- }
65
60
 
66
- locals {
67
- bucket_creds_key_name = "backend-state-bucket-creds"
68
- }
69
61
  resource "cloudfoundry_service_credential_binding" "bucket_creds" {
70
- name = local.bucket_creds_key_name
62
+ name = "backend-state-bucket-creds"
71
63
  service_instance = module.s3.bucket_id
72
64
  type = "key"
73
65
  }
74
- data "cloudfoundry_service_credential_binding" "bucket_creds" {
75
- name = local.bucket_creds_key_name
76
- service_instance = module.s3.bucket_id
77
- depends_on = [cloudfoundry_service_credential_binding.bucket_creds]
78
- }
79
66
 
80
67
  locals {
81
68
  import_map = {
@@ -94,12 +81,12 @@ resource "local_file" "recreate_script" {
94
81
  }
95
82
 
96
83
  locals {
97
- bucket_creds = jsondecode(data.cloudfoundry_service_credential_binding.bucket_creds.credential_bindings.0.credential_binding).credentials
84
+ bucket_creds = jsondecode(cloudfoundry_service_credential_binding.bucket_creds.credential_binding).credentials
98
85
  backend_config = templatefile("${path.module}/templates/backend_config.tftpl", { creds = local.bucket_creds })
99
86
  }
100
87
  resource "local_sensitive_file" "bucket_creds" {
101
88
  content = local.backend_config
102
- filename = "${path.module}/../secrets.backend.tfvars"
89
+ filename = "${path.module}/../.shadowenv.d/500_tf_backend_secrets.lisp"
103
90
  file_permission = "0600"
104
91
  }
105
92
 
@@ -10,48 +10,57 @@ is very limited.
10
10
  When you are ready to move the application to a non-sandbox cloud.gov organization, please re-run the terraform generator with…
11
11
 
12
12
  ```bash
13
- bin/rails generate rails_template18f:terraform --cg-org=<ORG_NAME> --cg-staging=<STAGING_SPACE_NAME> --cg-prod=<PRODUCTION_SPACE_NAME>
13
+ bin/rails generate rails_template18f:terraform --cg-org=<ORG_NAME> --cg-staging=<STAGING_SPACE_NAME> --cg-prod=<PRODUCTION_SPACE_NAME> --backend=<%= backend_unless_local %>
14
14
  ```
15
15
 
16
16
  …to take full advantage of the generator, and then re-run your CI generator of choice to add production terraform plan and apply steps to your workflow.
17
17
  <% end %>
18
- ## Terraform State Credentials
18
+ <% unless use_local_backend? %>## Terraform State Credentials
19
19
 
20
- The `bootstrap` module is used to create an s3 bucket for later terraform runs to store their state in as well as
21
- create credentials files so developers can use that s3 bucket to create their own sandbox environments.
20
+ The `bootstrap` module is used to create resources that must be created by an individual developers credentials before automation can be run:
22
21
 
23
- ### Initial project setup
22
+ * service account and credentials to provide to the CI/CD pipeline to perform future updates<% unless use_gitlab_backend? %>
23
+ * an s3 bucket for later terraform runs to store their state in<% end %>
24
+
25
+ ### Initial <%= use_gitlab_backend? ? "CI/CD pipeline" : "project" %> setup
24
26
 
25
27
  These steps only need to be run once per project.
26
28
 
27
- 1. `cd bootstrap`<% if terraform_manage_spaces? %>
28
- 1. Add any users who should have access to the terraform state bucket to `users.auto.tfvars`<% end %>
29
+ 1. `cd bootstrap`<% if use_gitlab_backend? %>
30
+ 1. Run `./setup_shadowenv.sh`<% end %><% if terraform_manage_spaces? %>
31
+ 1. Add any users who should have access to the management space to `users.auto.tfvars`<% end %><% if use_gitlab_backend? %>
32
+ 1. Run `./apply.sh`<% else %>
29
33
  1. Run `./apply.sh -var create_bot_secrets_file=true`
30
- 1. Add `imports.tf` to git and commit the changes
31
- 1. Setup your CI/CD Pipeline to run terraform and deploy your staging and production environments
32
- 1. Copy backend credentials from `/terraform/secrets.backend.tfvars` to your CI/CD secrets using the instructions in the base README
33
- 1. Copy the cf_user and cf_password credentials from `/terraform/secrets.cicd.tfvars` to your CI/CD secrets using the instructions in the base README
34
- 1. Delete the two secrets files
34
+ 1. Add `imports.tf` to git and commit the changes<% end %>
35
+ 1. Setup your CI/CD Pipeline to run terraform and deploy your staging and production environments<% unless use_gitlab_backend? %>
36
+ 1. Copy backend credentials from `/terraform/.shadowenv.d/500_tf_backend_secrets.lisp` to your CI/CD secrets using the instructions in the base README<% end %>
37
+ 1. Copy the `cf_user` and `cf_password` credentials from `secrets.cicd.tfvars` to your CI/CD secrets using the instructions in the base README
38
+ 1. Delete `secrets.cicd.tfvars`
39
+ 1. Delete `.shadowenv.d/500_tf_backend_secrets.lisp` if you won't be running terraform locally
35
40
 
36
41
  ### To make changes to the bootstrap module
37
42
 
38
- *This should not be necessary in most cases<% if terraform_manage_spaces? %>, other than adding or removing users who should have access to the state bucket in `bootstrap/users.auto.tfvars`<% end %>*
43
+ *This should not be necessary in most cases<% if terraform_manage_spaces? %>, other than adding or removing users who should have access to the mgmt space in `bootstrap/users.auto.tfvars`<% end %>*
39
44
 
40
45
  1. Make your changes
41
- 1. Run `./apply.sh` and verify the plan before entering `yes`
42
- 1. Commit any changes to `imports.tf`
46
+ 1. Run `./apply.sh` and verify the plan before entering `yes`<% unless use_gitlab_backend? %>
47
+ 1. Commit any changes to `imports.tf`<% end %><% end %>
43
48
 
44
- ## Set up a sandbox environment or review app
49
+ <% if use_local_backend? %>
50
+ ## Deploy the App
51
+ <% else %>
52
+ ## Set up a sandbox environment or review app<% unless use_gitlab_backend? %>
45
53
 
46
54
  ### Pre-requisites:
47
55
 
48
56
  1. Someone on the team has run the [Initial project setup](#initial-project-setup) steps and `imports.tf` is up-to-date on your branch.
49
- <% if terraform_manage_spaces? %>1. You are included in the list of users in `bootstrap/users.auto.tfvars` and `bootstrap/imports.tf`<% end %>
57
+ <% if terraform_manage_spaces? %>1. You are included in the list of users in `bootstrap/users.auto.tfvars` and `bootstrap/imports.tf`<% end %><% end %><% end %>
50
58
 
51
59
  ### Steps:
52
-
53
- <% if terraform_manage_spaces? %>1. Create a new `sandbox-<NAME>.tfvars` file to hold variable values for your environment. A good starting point is copying `staging.tfvars` and editing it with your values
54
- 1. Add a `cf_user = "your.email@agency.gov"` line to the `sandbox-<NAME>.tfvars` file<% end %>
60
+ <% if use_gitlab_backend? %>
61
+ 1. Run `./bootstrap/setup_shadowenv.sh`<% end %>
62
+ <% if terraform_manage_spaces? %>1. Create a new `sandbox-<NAME>.env.tfvars` file to hold variable values for your environment. A good starting point is copying `staging.env.tfvars` and editing it with your values
63
+ 1. Add a `cf_user = "your.email@gsa.gov"` line to the `sandbox-<NAME>.env.tfvars` file<% end %>
55
64
 
56
65
  1. Run terraform plan with:
57
66
  ```bash
@@ -70,17 +79,19 @@ These steps only need to be run once per project.
70
79
 
71
80
  ## Structure
72
81
 
73
- ```
82
+ ```<% unless use_local_backend? %>
74
83
  |- bootstrap/
75
84
  | |- main.tf
76
85
  | |- apply.sh
86
+ | |- users.auto.tfvars<% if use_gitlab_backend? %>
87
+ | |- setup_shadowenv.sh
88
+ | |- bot_secrets.tftpl<% else %>
77
89
  | |- imports.tf (automatically generated)
78
- | |- users.auto.tfvars
79
90
  | |- terraform.tfstate(.backup) (automatically generated)
80
91
  | |- templates/
81
92
  | |- backend_config.tftpl
82
93
  | |- bot_secrets.tftpl
83
- | |- imports.tf.tftpl
94
+ | |- imports.tf.tftpl<% end %><% end %>
84
95
  |- dist/
85
96
  | |- src.zip (automatically generated)
86
97
  |- README.md
@@ -89,19 +100,20 @@ These steps only need to be run once per project.
89
100
  |- providers.tf
90
101
  |- terraform.sh
91
102
  |- variables.tf
92
- |- <env>.tfvars
103
+ |- <env>.env.tfvars
93
104
  ```
94
105
 
95
106
  In the root module:
96
- - `<env>.tfvars` is where to set variable values for the given environment name
107
+ - `<env>.env.tfvars` is where to set variable values for the given environment name
97
108
  - `terraform.sh` Helper script to setup terraform to point to the correct state file, create a service account to run the root module, and apply the root module.
98
109
  - `app.tf` defines the application resource and configuration
99
110
  - `main.tf` defines the persistent infrastructure
100
111
  - `providers.tf` lists the required providers and shell backend config
101
112
  - `variables.tf` lists the variables that will be needed
102
113
 
103
- In the bootstrap module:
114
+ <% unless use_local_backend? %>In the bootstrap module:
104
115
  - `main.tf` sets up a management space, an s3 bucket to store terraform state files, and an initial SpaceDeployer for the system
105
- - `apply.sh` Helper script to either recreate the state locally or call `terraform apply` Any arguments are passed through to the `apply` call
106
- - `imports.tf` import blocks to create a new local state file when new developers need to access the state file. This file is automatically generated by calling `./apply.sh` and should be checked into git on any changes
107
- - `users.auto.tfvars` this file defines the list of cloud.gov accounts that should have access to the terraform state bucket
116
+ - `apply.sh` Helper script to setup terraform and call `terraform apply`. Any arguments are passed through to the `apply` call
117
+ - `users.auto.tfvars` this file defines the list of cloud.gov accounts that should have access to the management space<% if use_gitlab_backend? %>
118
+ - `setup_shadowenv.sh` helper script to set terraform backend values using the gitlab http backend in shadowenv<% else %>
119
+ - `imports.tf` import blocks to create a new local state file when new developers need to access the state file. This file is automatically generated by calling `./apply.sh` and should be checked into git on any changes<% end %><% end %>
@@ -15,17 +15,18 @@ data "archive_file" "src" {
15
15
  }
16
16
 
17
17
  resource "cloudfoundry_app" "app" {
18
- name = "${local.app_name}-${var.env}"
19
- space_name = var.cf_space_name
18
+ name = "${local.app_name}-${var.environment_slug}"
19
+ space_name = <% if terraform_manage_spaces? %>module.app_space.space_name<% else %>var.cf_space_name<% end %>
20
20
  org_name = local.cf_org_name
21
21
 
22
22
  path = data.archive_file.src.output_path
23
23
  source_code_hash = data.archive_file.src.output_base64sha256
24
24
  buildpacks = ["ruby_buildpack"]
25
25
  strategy = "rolling"
26
+ enable_ssh = var.allow_ssh
26
27
 
27
28
  environment = {
28
- RAILS_ENV = var.env
29
+ RAILS_ENV = var.environment_type
29
30
  RAILS_MASTER_KEY = var.rails_master_key
30
31
  RAILS_LOG_TO_STDOUT = "true"
31
32
  RAILS_SERVE_STATIC_FILES = "true"
@@ -43,9 +44,9 @@ resource "cloudfoundry_app" "app" {
43
44
  ]
44
45
 
45
46
  service_bindings = [
46
- <% if has_active_job? %> { service_instance = "${local.app_name}-redis-${var.env}" },<% end %>
47
- <% if has_active_storage? %> { service_instance = "${local.app_name}-s3-${var.env}" },<% end %>
48
- { service_instance = "${local.app_name}-rds-${var.env}" }
47
+ <% if has_active_job? %> { service_instance = "${local.app_name}-redis-${var.environment_slug}" },<% end %>
48
+ <% if has_active_storage? %> { service_instance = "${local.app_name}-s3-${var.environment_slug}" },<% end %>
49
+ { service_instance = "${local.app_name}-rds-${var.environment_slug}" }
49
50
  ]
50
51
 
51
52
  depends_on = [
@@ -1,17 +1,16 @@
1
1
  locals {
2
- cf_org_name = "<%= cloud_gov_organization %>"
3
- app_name = "<%= app_name %>"
4
- space_deployers = setunion([var.cf_user], var.space_deployers)
2
+ cf_org_name = "<%= cloud_gov_organization %>"
3
+ app_name = "<%= app_name.tr("_", "-") %>"
5
4
  }
6
5
  <% if terraform_manage_spaces? %>
7
6
  module "app_space" {
8
7
  source = "github.com/gsa-tts/terraform-cloudgov//cg_space?ref=v2.3.0"
9
8
 
10
9
  cf_org_name = local.cf_org_name
11
- cf_space_name = var.cf_space_name
12
- allow_ssh = var.allow_space_ssh
13
- deployers = local.space_deployers
14
- developers = var.space_developers
10
+ cf_space_name = coalesce(var.cf_space_name, "${local.app_name}-${var.environment_slug}")
11
+ allow_ssh = var.allow_ssh
12
+ deployers = var.space_deployers
13
+ developers = setunion([var.cf_user], var.space_developers)
15
14
  auditors = var.space_auditors
16
15
  security_group_names = ["trusted_local_networks_egress"]
17
16
  }
@@ -35,7 +34,7 @@ module "database" {
35
34
  source = "github.com/gsa-tts/terraform-cloudgov//database?ref=v2.3.0"
36
35
 
37
36
  cf_space_id = <% if terraform_manage_spaces? %>module.app_space.space_id<% else %>data.cloudfoundry_space.app_space.id<% end %>
38
- name = "${local.app_name}-rds-${var.env}"
37
+ name = "${local.app_name}-rds-${var.environment_slug}"
39
38
  rds_plan_name = var.rds_plan_name<% if terraform_manage_spaces? %>
40
39
  # depends_on line is required only for initial creation and destruction. It can be commented out for updates if you see unwanted cascading effects
41
40
  depends_on = [module.app_space]<% end %>
@@ -45,8 +44,11 @@ module "redis" {
45
44
  source = "github.com/gsa-tts/terraform-cloudgov//redis?ref=v2.3.0"
46
45
 
47
46
  cf_space_id = <% if terraform_manage_spaces? %>module.app_space.space_id<% else %>data.cloudfoundry_space.app_space.id<% end %>
48
- name = "${local.app_name}-redis-${var.env}"
49
- redis_plan_name = var.redis_plan_name<% if terraform_manage_spaces? %>
47
+ name = "${local.app_name}-redis-${var.environment_slug}"
48
+ redis_plan_name = var.redis_plan_name
49
+ json_params = jsonencode({
50
+ engineVersion = "7.0"
51
+ })<% if terraform_manage_spaces? %>
50
52
  # depends_on line is required only for initial creation and destruction. It can be commented out for updates if you see unwanted cascading effects
51
53
  depends_on = [module.app_space]<% end %>
52
54
  }
@@ -55,7 +57,7 @@ module "s3" {
55
57
  source = "github.com/gsa-tts/terraform-cloudgov//s3?ref=v2.3.0"
56
58
 
57
59
  cf_space_id = <% if terraform_manage_spaces? %>module.app_space.space_id<% else %>data.cloudfoundry_space.app_space.id<% end %>
58
- name = "${local.app_name}-s3-${var.env}"
60
+ name = "${local.app_name}-s3-${var.environment_slug}"
59
61
  s3_plan_name = var.s3_plan_name<% if terraform_manage_spaces? %>
60
62
  # depends_on line is required only for initial creation and destruction. It can be commented out for updates if you see unwanted cascading effects
61
63
  depends_on = [module.app_space]<% end %>
@@ -66,7 +68,7 @@ module "clamav" {
66
68
 
67
69
  cf_org_name = local.cf_org_name
68
70
  cf_space_name = var.cf_space_name
69
- name = "${local.app_name}-clamapi-${var.env}"
71
+ name = "${local.app_name}-clamapi-${var.environment_slug}"
70
72
  clamav_image = "ghcr.io/gsa-tts/clamav-rest/clamav:latest"
71
73
  max_file_size = "30M"<% if terraform_manage_spaces? %>
72
74
  # depends_on line is required only for initial creation and destruction. It can be commented out for updates if you see unwanted cascading effects
@@ -109,9 +111,9 @@ module "app_route" {
109
111
  source = "github.com/gsa-tts/terraform-cloudgov//app_route?ref=v2.3.0"
110
112
 
111
113
  cf_org_name = local.cf_org_name
112
- cf_space_name = var.cf_space_name
114
+ cf_space_name = <% if terraform_manage_spaces? %>module.app_space.space_name<% else %>var.cf_space_name<% end %>
113
115
  app_ids = [cloudfoundry_app.app.id]
114
- hostname = coalesce(var.host_name, "${local.app_name}-${var.env}")<% if terraform_manage_spaces? %>
116
+ hostname = coalesce(var.host_name, "${local.app_name}-${var.environment_slug}")<% if terraform_manage_spaces? %>
115
117
  # depends_on line is required only for initial creation and destruction. It can be commented out for updates if you see unwanted cascading effects
116
118
  depends_on = [module.app_space]<% end %>
117
119
  }
@@ -1,5 +1,4 @@
1
1
  cf_space_name = "<%= cloud_gov_production_space %>"
2
- env = "production"
3
2
  rds_plan_name = "TKTK-production-rds-plan"
4
3
  custom_domain_name = null
5
4
  host_name = null
@@ -3,16 +3,14 @@ terraform {
3
3
  required_providers {
4
4
  cloudfoundry = {
5
5
  source = "cloudfoundry/cloudfoundry"
6
- version = "1.5.0"
6
+ version = "~> 1.10"
7
+ }
8
+ archive = {
9
+ source = "hashicorp/archive"
10
+ version = "~> 2"
7
11
  }
8
12
  }
9
13
 
10
- backend "s3" {
11
- encrypt = true
12
- use_lockfile = true
13
- use_fips_endpoint = true
14
- region = "us-gov-west-1"
15
- }
16
- }
14
+ <%= backend_block %>}
17
15
 
18
16
  provider "cloudfoundry" {}
@@ -0,0 +1,7 @@
1
+ cf_space_name = "<%= cloud_gov_staging_space %>"
2
+ allow_ssh = true
3
+ # host_name must be unique across cloud.gov, default is "<%= app_name.tr("_", "-") %>-${var.environment_slug}"
4
+ host_name = null<% if terraform_manage_spaces? %>
5
+ space_developers = [
6
+ # enter developer emails that should have ssh access to staging
7
+ ]<% end %>
@@ -20,8 +20,8 @@ Options:
20
20
  "
21
21
 
22
22
 
23
- rmk=`cat $rmk_file || echo -n ""`
24
- env=""
23
+ rmk=$(cat $rmk_file || echo -n "")
24
+ env="<% unless terraform_manage_spaces? %>staging<% end %>"
25
25
  force=""
26
26
  args_to_shift=0
27
27
 
@@ -54,7 +54,21 @@ done
54
54
  shift $args_to_shift
55
55
  if [[ "$1" = "--" ]]; then
56
56
  shift 1
57
- fi
57
+ fi<% if use_gitlab_backend? %>
58
+
59
+ if [ -z "$GITLAB_PROJECT_ID" ] || [ -z "$GITLAB_BASE_URL" ]; then
60
+ echo "GITLAB_PROJECT_ID or GITLAB_BASE_URL have not been set. Running bootstrap/setup_shadowenv.sh now..."
61
+ (cd bootstrap && ./setup_shadowenv.sh)
62
+ eval "$(shadowenv hook)"
63
+ fi<% elsif use_s3_backend? %>
64
+
65
+ if [[ ! -f .shadowenv.d/500_tf_backend_secrets.lisp ]]; then
66
+ echo "=============================================================================================================="
67
+ echo "= Recreating backend config file. It is fine if this step wants to delete any local_sensitive_file resources"
68
+ echo "=============================================================================================================="
69
+ (cd bootstrap && ./apply.sh $force)
70
+ shadowenv trust && eval "$(shadowenv hook)"
71
+ fi<% end %>
58
72
 
59
73
  if [[ -z "$env" ]]; then
60
74
  echo "-e <ENV_NAME> is required"
@@ -62,34 +76,54 @@ if [[ -z "$env" ]]; then
62
76
  exit 1
63
77
  fi
64
78
 
65
- if [[ ! -f "$env.tfvars" ]]; then
66
- echo "$env.tfvars file is missing. Create it first"
79
+ if [[ ! -f "$env.env.tfvars" ]]; then
80
+ echo "$env.env.tfvars file is missing. Create it first"
67
81
  exit 1
68
82
  fi
69
83
 
84
+ if [[ "$env" = "staging" ]] || [[ "$env" = "production" ]]; then
85
+ echo "environment_type = \"$env\"" > env_vars.auto.tfvars
86
+ echo "environment_slug = \"$env\"" >> env_vars.auto.tfvars
87
+ elif [[ "$env" = "sandbox" ]]; then
88
+ echo "environment_type = \"review\"" > env_vars.auto.tfvars
89
+ else
90
+ rm env_vars.auto.tfvars
91
+ fi
92
+
70
93
  # ensure we're logged in via cli
71
94
  cf spaces &> /dev/null || cf login -a api.fr.cloud.gov --sso
72
95
 
73
- tfm_needs_init=true
96
+ tfm_needs_init=true<% if use_gitlab_backend? %>
97
+ tf_state_address="$GITLAB_BASE_URL/projects/$GITLAB_PROJECT_ID/terraform/state/$env"
74
98
  if [[ -f .terraform/terraform.tfstate ]]; then
75
- backend_state_env=`cat .terraform/terraform.tfstate | jq -r ".backend.config.key" | cut -d '.' -f3`
99
+ backend_state_address=$(cat .terraform/terraform.tfstate | jq -r ".backend.config.address")
100
+ if [[ "$backend_state_address" = "$tf_state_address" ]]; then
101
+ tfm_needs_init=false
102
+ fi
103
+ fi<% elsif use_s3_backend? %>
104
+ if [[ -f .terraform/terraform.tfstate ]]; then
105
+ backend_state_env=$(cat .terraform/terraform.tfstate | jq -r ".backend.config.key" | cut -d '.' -f3)
76
106
  if [[ "$backend_state_env" = "$env" ]]; then
77
107
  tfm_needs_init=false
78
108
  fi
79
- fi
109
+ else
110
+ echo "Sleeping for 10 seconds to avoid a bucket creation race condition"
111
+ sleep 10
112
+ fi<% else %>
113
+ if [[ -f .terraform.lock.hcl ]]; then
114
+ tfm_needs_init=false
115
+ fi<% end %>
80
116
 
81
- if [[ $tfm_needs_init = true ]]; then
82
- if [[ ! -f secrets.backend.tfvars ]]; then
83
- echo "=============================================================================================================="
84
- echo "= Recreating backend config file. It is fine if this step wants to delete any local_sensitive_file resources"
85
- echo "=============================================================================================================="
86
- (cd bootstrap && ./apply.sh -auto-approve)
87
- fi
88
- terraform init -backend-config=secrets.backend.tfvars -backend-config="key=terraform.tfstate.$env" -reconfigure
89
- rm secrets.backend.tfvars
117
+ if [[ $tfm_needs_init = true ]]; then<% if use_gitlab_backend? %>
118
+ terraform init -reconfigure \
119
+ -backend-config="address=$tf_state_address" \
120
+ -backend-config="lock_address=$tf_state_address/lock" \
121
+ -backend-config="unlock_address=$tf_state_address/lock"<% elsif use_s3_backend? %>
122
+ terraform init -backend-config="bucket=$S3_BUCKET_NAME" -backend-config="key=terraform.tfstate.$env" -reconfigure<% else %>
123
+ terraform init<% end %>
90
124
  fi
91
125
 
92
126
  echo "=============================================================================================================="
93
127
  echo "= Calling $cmd $force on the application infrastructure"
94
128
  echo "=============================================================================================================="
95
- terraform "$cmd" -var-file="$env.tfvars" -var rails_master_key="$rmk" $force "$@"
129
+ terraform "$cmd" -var-file="$env.env.tfvars" -var rails_master_key="$rmk" $force "$@"