From afde778e29a0c92fac082d9ff2f0c02dcf01f0e5 Mon Sep 17 00:00:00 2001 From: Dan Buch Date: Sat, 22 Aug 2020 22:28:12 -0400 Subject: [PATCH 1/4] Modernizing many things - use hashicorp/setup-terraform action - bump terraform requirement to 0.13 - bump digitalocean provider requirement to 1.22 - bump to latest nvm - remove a bunch of unnecessary quotes --- .github/workflows/terraform.yml | 27 +++++------ .gitignore | 25 +--------- README.md | 15 ++++-- main.tf | 86 ++++++++++++++++++--------------- spoke-app-provision | 2 +- 5 files changed, 71 insertions(+), 84 deletions(-) diff --git a/.github/workflows/terraform.yml b/.github/workflows/terraform.yml index 4a85c6c..fb1848f 100644 --- a/.github/workflows/terraform.yml +++ b/.github/workflows/terraform.yml @@ -1,23 +1,18 @@ name: terraform -on: [push, pull_request] +on: + push: + branches: [main] + pull_request: + branches: [main] jobs: terraform: name: Terraform runs-on: ubuntu-latest steps: - - uses: actions/checkout@master - - name: fmt - uses: hashicorp/terraform-github-actions@master + - uses: actions/checkout@v2 + - uses: hashicorp/setup-terraform@v1 with: - tf_actions_version: 0.12.21 - tf_actions_subcommand: fmt - - name: init - uses: hashicorp/terraform-github-actions@master - with: - tf_actions_version: 0.12.21 - tf_actions_subcommand: init - - name: validate - uses: hashicorp/terraform-github-actions@master - with: - tf_actions_version: 0.12.21 - tf_actions_subcommand: validate + terraform_version: 0.13.0 + - run: terraform fmt -check -recursive + - run: terraform init + - run: terraform validate diff --git a/.gitignore b/.gitignore index 7a3e2fd..9c907e4 100644 --- a/.gitignore +++ b/.gitignore @@ -1,29 +1,8 @@ -# Local .terraform directories **/.terraform/* - -# .tfstate files *.tfstate *.tfstate.* - -# Crash log files +*_override.tf +*_override.tf.json crash.log - -# Ignore any .tfvars files that are generated automatically for each Terraform run. Most -# .tfvars files are managed as part of configuration and so should be included in -# version control. -# -# example.tfvars - -# Ignore override files as they are usually used to override resources locally and so -# are not checked in override.tf override.tf.json -*_override.tf -*_override.tf.json - -# Include override files you do wish to add to version control using negated pattern -# -# !example_override.tf - -# Include tfplan files to ignore the plan output of command: terraform plan -out=tfplan -# example: *tfplan* diff --git a/README.md b/README.md index e0c6abd..ee79844 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ This is a terraform module that provisions a ## Terraform versions -This module is compatible with Terraform version `0.12+`. +This module is compatible with Terraform version `0.13+`. ## Usage @@ -48,21 +48,28 @@ module "digitalocean_spoke" { } ``` +## Requirements + +| Name | Version | +|------|---------| +| digitalocean | >= 1.22 | + ## Providers | Name | Version | |------|---------| -| digitalocean | >= 1.14 | +| digitalocean | >= 1.22 | | null | n/a | | random | n/a | ## Inputs | Name | Description | Type | Default | Required | -|------|-------------|------|---------|:-----:| +|------|-------------|------|---------|:--------:| | base\_url | Fully qualified https URL of the app | `string` | n/a | yes | | cert\_certificate | Certificate with leaf and intermediates to pass to nginx | `string` | n/a | yes | | cert\_private\_key | Certificate key to pass to nginx | `string` | n/a | yes | +| droplet\_image | Image to use when provisioning app droplet | `string` | `"ubuntu-20-04-x64"` | no | | droplet\_size | Size value passed when provisioning app droplet | `string` | `"s-1vcpu-1gb"` | no | | env | Arbitrary *additional* environment variables passed at build time and run time | `map(string)` | `{}` | no | | node\_env | Value defined at build time and run time as NODE\_ENV | `string` | `"production"` | no | @@ -71,7 +78,7 @@ module "digitalocean_spoke" { | region | Region in which all resources will be provisioned | `string` | `"nyc1"` | no | | resource\_prefix | Prefix prepended to resource names | `string` | `"spoke-"` | no | | server\_name | Server name used in nginx config | `string` | n/a | yes | -| spoke\_version | Git ref of MoveOnOrg/Spoke to deploy | `string` | `"v5.2"` | no | +| spoke\_version | Git ref of MoveOnOrg/Spoke to deploy | `string` | `"v8.0"` | no | | ssh\_keys | List of ssh public keys to pass to droplet provisioning | `list(string)` | n/a | yes | ## Outputs diff --git a/main.tf b/main.tf index 3babf1b..ce47d75 100644 --- a/main.tf +++ b/main.tf @@ -7,7 +7,7 @@ * * ## Terraform versions * - * This module is compatible with Terraform version `0.12+`. + * This module is compatible with Terraform version `0.13+`. * * ## Usage * @@ -52,91 +52,97 @@ terraform { required_providers { - digitalocean = ">= 1.14" + digitalocean = ">= 1.22" } } -variable "server_name" { +variable server_name { description = "Server name used in nginx config" type = string } -variable "base_url" { +variable base_url { description = "Fully qualified https URL of the app" type = string } -variable "resource_prefix" { +variable resource_prefix { description = "Prefix prepended to resource names" default = "spoke-" type = string } -variable "node_options" { +variable node_options { description = "Value defined at build time and run time as NODE_OPTIONS" default = "--max_old_space_size=8192" type = string } -variable "node_env" { +variable node_env { description = "Value defined at build time and run time as NODE_ENV" default = "production" type = string } -variable "port" { +variable port { description = "TCP port used to communicate between droplet and nginx" default = "3000" type = string } -variable "droplet_size" { +variable droplet_image { + description = "Image to use when provisioning app droplet" + default = "ubuntu-20-04-x64" + type = string +} + +variable droplet_size { description = "Size value passed when provisioning app droplet" default = "s-1vcpu-1gb" type = string } -variable "region" { +variable region { description = "Region in which all resources will be provisioned" default = "nyc1" type = string } -variable "spoke_version" { +variable spoke_version { description = "Git ref of MoveOnOrg/Spoke to deploy" - default = "v5.2" + default = "v8.0" type = string } -variable "ssh_keys" { +variable ssh_keys { type = list(string) description = "List of ssh public keys to pass to droplet provisioning" } -variable "cert_private_key" { +variable cert_private_key { description = "Certificate key to pass to nginx" type = string } -variable "cert_certificate" { +variable cert_certificate { description = "Certificate with leaf and intermediates to pass to nginx" type = string } -variable "env" { +variable env { description = "Arbitrary *additional* environment variables passed at build time and run time" default = {} type = map(string) } -resource "digitalocean_ssh_key" "app" { +resource digitalocean_ssh_key app { count = length(var.ssh_keys) name = "${var.resource_prefix}app-${count.index}" public_key = element(var.ssh_keys, count.index) } -resource "digitalocean_droplet" "app" { - image = "ubuntu-18-04-x64" +resource digitalocean_droplet app { + image = var.droplet_image name = "${var.resource_prefix}app" region = var.region size = var.droplet_size @@ -144,17 +150,17 @@ resource "digitalocean_droplet" "app" { ssh_keys = digitalocean_ssh_key.app[*].id } -resource "digitalocean_floating_ip" "app" { +resource digitalocean_floating_ip app { droplet_id = digitalocean_droplet.app.id region = digitalocean_droplet.app.region } -resource "digitalocean_firewall" "app" { +resource digitalocean_firewall app { name = "pghdsa-spoke-app" droplet_ids = [digitalocean_droplet.app.id] - dynamic "inbound_rule" { + dynamic inbound_rule { for_each = ["22", "80", "443"] content { protocol = "tcp" @@ -168,7 +174,7 @@ resource "digitalocean_firewall" "app" { source_addresses = ["0.0.0.0/0", "::/0"] } - dynamic "outbound_rule" { + dynamic outbound_rule { for_each = ["tcp", "udp"] content { protocol = outbound_rule.value @@ -183,12 +189,12 @@ resource "digitalocean_firewall" "app" { } } -resource "random_string" "session_secret" { +resource random_string session_secret { length = 199 special = false } -resource "random_string" "pg_password" { +resource random_string pg_password { length = 31 } @@ -216,7 +222,7 @@ locals { }, var.env) } -resource "null_resource" "app_provision" { +resource null_resource app_provision { triggers = { droplet_id = digitalocean_droplet.app.id provision_script_sha1 = filesha1("${path.module}/spoke-app-provision") @@ -236,17 +242,17 @@ resource "null_resource" "app_provision" { host = digitalocean_droplet.app.ipv4_address } - provisioner "file" { + provisioner file { source = "${path.module}/spoke-app-provision" destination = "/tmp/spoke-app-provision" } - provisioner "file" { + provisioner file { source = "${path.module}/spoke-app-run" destination = "/tmp/spoke-app-run" } - provisioner "file" { + provisioner file { content = templatefile("${path.module}/nginx-sites-default.conf.tpl", { server_name = var.server_name, port = var.port, @@ -254,32 +260,32 @@ resource "null_resource" "app_provision" { destination = "/tmp/nginx-sites-default.conf" } - provisioner "file" { + provisioner file { content = var.cert_certificate destination = "/tmp/spoke.crt" } - provisioner "file" { + provisioner file { content = var.cert_private_key destination = "/tmp/spoke.key" } - provisioner "file" { - content = <<-ENV_TMPL + provisioner file { + content = <<-ENVTMPL %{for key, value in local.env_map~} ${key}='${value}' %{endfor~} -ENV_TMPL +ENVTMPL destination = "/tmp/app.env" } - provisioner "file" { + provisioner file { source = "${path.module}/spoke.service" destination = "/tmp/spoke.service" } - provisioner "remote-exec" { + provisioner remote-exec { inline = [ "bash /tmp/spoke-app-provision system0", "sudo -H -u spoke bash /tmp/spoke-app-provision spoke0", @@ -288,22 +294,22 @@ ENV_TMPL } } -output "droplet_urn" { +output droplet_urn { description = "urn of the droplet suitable for adding to project resources" value = digitalocean_droplet.app.urn } -output "droplet_ipv4_address" { +output droplet_ipv4_address { description = "ipv4 address of the droplet" value = digitalocean_droplet.app.ipv4_address } -output "floating_ip_address" { +output floating_ip_address { description = "floating IP address assigned to the droplet suitable for creating a DNS A record" value = digitalocean_floating_ip.app.ip_address } -output "floating_ip_urn" { +output floating_ip_urn { description = "urn of the floating IP address assigned to the droplet suitable for adding to project resources" value = digitalocean_floating_ip.app.urn } diff --git a/spoke-app-provision b/spoke-app-provision index 99c4001..681904f 100755 --- a/spoke-app-provision +++ b/spoke-app-provision @@ -116,7 +116,7 @@ _run_spoke0() { if ! command -v nvm; then curl -fsSL \ - https://raw.githubusercontent.com/nvm-sh/nvm/v0.35.2/install.sh | bash + https://raw.githubusercontent.com/nvm-sh/nvm/v0.35.3/install.sh | bash set +o errexit set +o xtrace # shellcheck source=/dev/null From ab570f1900b65dead48c5b1e9ce419c07da6d34f Mon Sep 17 00:00:00 2001 From: Dan Buch Date: Sat, 22 Aug 2020 22:32:47 -0400 Subject: [PATCH 2/4] Trivial change to get actions flowing --- README.md | 2 +- main.tf | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index ee79844..fd20c8c 100644 --- a/README.md +++ b/README.md @@ -27,7 +27,7 @@ module "digitalocean_spoke" { cert_certificate = file("path/to/cert.crt") env = { AUTH0_CLIENT_ID = "8570285697946a0cc03f8049b9309d7e" - AUTH0_CLIENT_SECRET = "1194435d32479ef99ed51a0a5f244cd5" + AUTH0_CLIENT_SECRET = "1194435d32479ab99ed51a0a5f244cd5" AUTH0_DOMAIN = "example.auth0.com" EMAIL_FROM = "admin@example.org" EMAIL_HOST = "mail.example.org" diff --git a/main.tf b/main.tf index ce47d75..528add8 100644 --- a/main.tf +++ b/main.tf @@ -28,7 +28,7 @@ * cert_certificate = file("path/to/cert.crt") * env = { * AUTH0_CLIENT_ID = "8570285697946a0cc03f8049b9309d7e" - * AUTH0_CLIENT_SECRET = "1194435d32479ef99ed51a0a5f244cd5" + * AUTH0_CLIENT_SECRET = "1194435d32479ab99ed51a0a5f244cd5" * AUTH0_DOMAIN = "example.auth0.com" * EMAIL_FROM = "admin@example.org" * EMAIL_HOST = "mail.example.org" From de21ab34ab4733e4f0980b81c73e89494e94496d Mon Sep 17 00:00:00 2001 From: Dan Buch Date: Sat, 22 Aug 2020 22:34:08 -0400 Subject: [PATCH 3/4] Run terraform 0.13upgrade --- README.md | 1 + main.tf | 11 ++++++++++- versions.tf | 3 +++ 3 files changed, 14 insertions(+), 1 deletion(-) create mode 100644 versions.tf diff --git a/README.md b/README.md index fd20c8c..f2eb424 100644 --- a/README.md +++ b/README.md @@ -52,6 +52,7 @@ module "digitalocean_spoke" { | Name | Version | |------|---------| +| terraform | >= 0.13 | | digitalocean | >= 1.22 | ## Providers diff --git a/main.tf b/main.tf index 528add8..dda92e7 100644 --- a/main.tf +++ b/main.tf @@ -52,7 +52,16 @@ terraform { required_providers { - digitalocean = ">= 1.22" + digitalocean = { + source = "terraform-providers/digitalocean" + version = ">= 1.22" + } + null = { + source = "hashicorp/null" + } + random = { + source = "hashicorp/random" + } } } diff --git a/versions.tf b/versions.tf new file mode 100644 index 0000000..6b6318d --- /dev/null +++ b/versions.tf @@ -0,0 +1,3 @@ +terraform { + required_version = ">= 0.13" +} From 21084e4f12dda01bf598c30e2ed221af07e12376 Mon Sep 17 00:00:00 2001 From: Dan Buch Date: Sat, 22 Aug 2020 22:36:05 -0400 Subject: [PATCH 4/4] Point at correct digitalocean provider --- main.tf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/main.tf b/main.tf index dda92e7..200d146 100644 --- a/main.tf +++ b/main.tf @@ -53,7 +53,7 @@ terraform { required_providers { digitalocean = { - source = "terraform-providers/digitalocean" + source = "digitalocean/digitalocean" version = ">= 1.22" } null = {