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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +12 -0
- data/Gemfile.lock +85 -70
- data/lib/generators/rails_template18f/active_storage/active_storage_generator.rb +4 -3
- data/lib/generators/rails_template18f/auditree/auditree_generator.rb +36 -6
- data/lib/generators/rails_template18f/auditree/templates/gitlab/auditree.yml.tt +48 -0
- data/lib/generators/rails_template18f/circleci/templates/circleci/config.yml.tt +6 -2
- data/lib/generators/rails_template18f/cloud_gov_config/cloud_gov_config_generator.rb +0 -8
- data/lib/generators/rails_template18f/cloud_gov_config/templates/app/models/cloud_gov_config.rb +6 -15
- data/lib/generators/rails_template18f/cloud_gov_config/templates/spec/models/cloud_gov_config_spec.rb +13 -19
- data/lib/generators/rails_template18f/github_actions/github_actions_generator.rb +0 -4
- data/lib/generators/rails_template18f/github_actions/templates/github/dependabot.yml.tt +16 -0
- data/lib/generators/rails_template18f/github_actions/templates/github/workflows/deploy-production.yml +4 -1
- data/lib/generators/rails_template18f/github_actions/templates/github/workflows/deploy-staging.yml +4 -1
- data/lib/generators/rails_template18f/github_actions/templates/github/workflows/terraform-production.yml +4 -1
- data/lib/generators/rails_template18f/github_actions/templates/github/workflows/terraform-staging.yml +4 -1
- data/lib/generators/rails_template18f/gitlab_ci/gitlab_ci_generator.rb +9 -18
- data/lib/generators/rails_template18f/gitlab_ci/templates/gitlab/{node.yml.tt → node.yml} +1 -1
- data/lib/generators/rails_template18f/gitlab_ci/templates/gitlab/rails.yml +11 -18
- data/lib/generators/rails_template18f/gitlab_ci/templates/gitlab-ci.yml.tt +80 -152
- data/lib/generators/rails_template18f/oscal/oscal_generator.rb +15 -1
- data/lib/generators/rails_template18f/oscal/templates/bin/trestle.tt +10 -1
- data/lib/generators/rails_template18f/oscal/templates/gitlab/trestle.yml.tt +29 -0
- data/lib/generators/rails_template18f/public_egress/public_egress_generator.rb +2 -2
- data/lib/generators/rails_template18f/sidekiq/templates/config/initializers/redis.rb +1 -1
- data/lib/generators/rails_template18f/terraform/templates/gitlab_bootstrap/apply.sh +25 -0
- data/lib/generators/rails_template18f/terraform/templates/gitlab_bootstrap/main.tf.tt +114 -0
- data/lib/generators/rails_template18f/terraform/templates/gitlab_bootstrap/setup_shadowenv.sh +61 -0
- data/lib/generators/rails_template18f/terraform/templates/s3_bootstrap/common/templates/backend_config.tftpl +6 -0
- data/lib/generators/rails_template18f/terraform/templates/s3_bootstrap/common/users.auto.tfvars +5 -0
- data/lib/generators/rails_template18f/terraform/templates/{full_bootstrap → s3_bootstrap/full}/main.tf.tt +7 -27
- data/lib/generators/rails_template18f/terraform/templates/{sandbox_bootstrap → s3_bootstrap/sandbox}/main.tf.tt +6 -19
- data/lib/generators/rails_template18f/terraform/templates/terraform/.shadowenv.d/.gitignore +3 -0
- data/lib/generators/rails_template18f/terraform/templates/terraform/README.md.tt +41 -29
- data/lib/generators/rails_template18f/terraform/templates/terraform/app.tf.tt +7 -6
- data/lib/generators/rails_template18f/terraform/templates/terraform/main.tf.tt +16 -14
- data/lib/generators/rails_template18f/terraform/templates/terraform/{production.tfvars.tt → production.env.tfvars.tt} +0 -1
- data/lib/generators/rails_template18f/terraform/templates/terraform/providers.tf.tt +6 -8
- data/lib/generators/rails_template18f/terraform/templates/terraform/staging.env.tfvars.tt +7 -0
- data/lib/generators/rails_template18f/terraform/templates/terraform/terraform.sh.tt +52 -18
- data/lib/generators/rails_template18f/terraform/templates/terraform/variables.tf.tt +15 -11
- data/lib/generators/rails_template18f/terraform/terraform_generator.rb +80 -6
- data/lib/rails_template18f/generators/cloud_gov_parsing.rb +2 -2
- data/lib/rails_template18f/version.rb +1 -1
- data/template.rb +33 -16
- data/templates/README.md.tt +1 -1
- metadata +23 -17
- data/lib/generators/rails_template18f/gitlab_ci/templates/gitlab/terraform.yml +0 -28
- data/lib/generators/rails_template18f/terraform/templates/terraform/bootstrap/templates/backend_config.tftpl +0 -8
- data/lib/generators/rails_template18f/terraform/templates/terraform/staging.tfvars.tt +0 -8
- /data/lib/generators/rails_template18f/{github_actions → oscal}/templates/github/workflows/assemble-ssp.yml.tt +0 -0
- /data/lib/generators/rails_template18f/{github_actions → oscal}/templates/github/workflows/validate-ssp.yml +0 -0
- /data/lib/generators/rails_template18f/terraform/templates/{terraform/bootstrap → gitlab_bootstrap}/users.auto.tfvars +0 -0
- /data/lib/generators/rails_template18f/terraform/templates/{terraform/bootstrap → s3_bootstrap/common}/apply.sh +0 -0
- /data/lib/generators/rails_template18f/terraform/templates/{terraform/bootstrap → s3_bootstrap/common}/templates/bot_secrets.tftpl +0 -0
- /data/lib/generators/rails_template18f/terraform/templates/{full_bootstrap → s3_bootstrap/full}/imports.tf.tftpl +0 -0
- /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}")
|
|
@@ -3,7 +3,7 @@ terraform {
|
|
|
3
3
|
required_providers {
|
|
4
4
|
cloudfoundry = {
|
|
5
5
|
source = "cloudfoundry/cloudfoundry"
|
|
6
|
-
version = "1.
|
|
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(
|
|
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
|
|
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
|
|
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 =
|
|
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(
|
|
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}
|
|
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.
|
|
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(
|
|
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
|
|
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 =
|
|
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(
|
|
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}
|
|
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
|
-
|
|
18
|
+
<% unless use_local_backend? %>## Terraform State Credentials
|
|
19
19
|
|
|
20
|
-
The `bootstrap` module is used to create
|
|
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
|
-
|
|
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
|
|
28
|
-
1.
|
|
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/
|
|
33
|
-
1. Copy the cf_user and cf_password credentials from
|
|
34
|
-
1. Delete
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
54
|
-
1.
|
|
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
|
|
106
|
-
- `
|
|
107
|
-
- `
|
|
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.
|
|
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.
|
|
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.
|
|
47
|
-
<% if has_active_storage? %> { service_instance = "${local.app_name}-s3-${var.
|
|
48
|
-
{ service_instance = "${local.app_name}-rds-${var.
|
|
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
|
|
3
|
-
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.
|
|
13
|
-
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.
|
|
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.
|
|
49
|
-
redis_plan_name = var.redis_plan_name
|
|
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.
|
|
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.
|
|
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.
|
|
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
|
}
|
|
@@ -3,16 +3,14 @@ terraform {
|
|
|
3
3
|
required_providers {
|
|
4
4
|
cloudfoundry = {
|
|
5
5
|
source = "cloudfoundry/cloudfoundry"
|
|
6
|
-
version = "1.
|
|
6
|
+
version = "~> 1.10"
|
|
7
|
+
}
|
|
8
|
+
archive = {
|
|
9
|
+
source = "hashicorp/archive"
|
|
10
|
+
version = "~> 2"
|
|
7
11
|
}
|
|
8
12
|
}
|
|
9
13
|
|
|
10
|
-
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
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 "$@"
|