From 509df69554196f5ca501e1cd61ee4979341cce0c Mon Sep 17 00:00:00 2001 From: Jan David Date: Mon, 19 Dec 2022 12:47:05 +0100 Subject: [PATCH] Build Fastly function during terraform plan The Fastly function is now built whenever `terraform plan` is run. This This ensures that the function is always up to date, and prevents users from accidentally uploading a stale version of the WASM module. This is implemented using an external data source [^1] inside Terraform. The data source calls a script that compiles the function and returns the path to the artifact. [^1]: https://registry.terraform.io/providers/hashicorp/external/latest/docs/data-sources/data_source --- Cargo.toml | 1 - .../crates-io/.terraform.lock.hcl | 19 + .../crates-io/compute-static/Cargo.lock | 411 ++++++++++++++++++ .../crates-io/compute-static/Cargo.toml | 5 + .../crates-io/compute-static/README.md | 10 +- .../bin/terraform-external-build.sh | 25 ++ terragrunt/modules/crates-io/fastly-static.tf | 9 +- 7 files changed, 475 insertions(+), 5 deletions(-) create mode 100644 terragrunt/modules/crates-io/compute-static/Cargo.lock create mode 100755 terragrunt/modules/crates-io/compute-static/bin/terraform-external-build.sh diff --git a/Cargo.toml b/Cargo.toml index 87194abc6..3ae9e2d4e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -2,5 +2,4 @@ members = [ "setup-deploy-keys", "ansible/roles/dev-desktop/files/team_login", - "terragrunt/modules/crates-io/compute-static" ] diff --git a/terragrunt/accounts/legacy/crates-io-staging/crates-io/.terraform.lock.hcl b/terragrunt/accounts/legacy/crates-io-staging/crates-io/.terraform.lock.hcl index 4e95838a8..d8b278a94 100644 --- a/terragrunt/accounts/legacy/crates-io-staging/crates-io/.terraform.lock.hcl +++ b/terragrunt/accounts/legacy/crates-io-staging/crates-io/.terraform.lock.hcl @@ -45,3 +45,22 @@ provider "registry.terraform.io/hashicorp/aws" { "zh:f6d355a2fb3bcebb597f68bbca4fa2aaa364efd29240236c582375e219d77656", ] } + +provider "registry.terraform.io/hashicorp/external" { + version = "2.2.3" + hashes = [ + "h1:648ZjJR81c2W1OLtYmUQa9/1rGr3vvZSuX9dR1ucGWY=", + "zh:184ecd339d764de845db0e5b8a9c87893dcd0c9d822167f73658f89d80ec31c9", + "zh:2661eaca31d17d6bbb18a8f673bbfe3fe1b9b7326e60d0ceb302017003274e3c", + "zh:2c0a180f6d1fc2ba6e03f7dfc5f73b617e45408681f75bca75aa82f3796df0e4", + "zh:4b92ae44c6baef4c4952c47be00541055cb5280dd3bc8031dba5a1b2ee982387", + "zh:5641694d5daf3893d7ea90be03b6fa575211a08814ffe70998d5adb8b59cdc0a", + "zh:5bd55a2be8a1c20d732ac9c604b839e1cadc8c49006315dffa4d709b6874df32", + "zh:6e0ef5d11e1597202424b7d69b9da7b881494c9b13a3d4026fc47012dc651c79", + "zh:78d5eefdd9e494defcb3c68d282b8f96630502cac21d1ea161f53cfe9bb483b3", + "zh:9e19f89fa25004d3b926a8d15ea630b4bde62f1fa4ed5e11a3d27aabddb77353", + "zh:b763efdd69fd097616b4a4c89cf333b4cee9699ac6432d73d2756f8335d1213f", + "zh:e3b561efdee510b2b445f76a52a902c52bee8e13095e7f4bed7c80f10f8d294a", + "zh:fe660bb8781ee043a093b9a20e53069974475dcaa5791a1f45fd03c61a26478a", + ] +} diff --git a/terragrunt/modules/crates-io/compute-static/Cargo.lock b/terragrunt/modules/crates-io/compute-static/Cargo.lock new file mode 100644 index 000000000..cabef6508 --- /dev/null +++ b/terragrunt/modules/crates-io/compute-static/Cargo.lock @@ -0,0 +1,411 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "anyhow" +version = "1.0.68" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2cb2f989d18dd141ab8ae82f64d1a8cdd37e0840f73a406896cf5e99502fab61" + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "block-buffer" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4152116fd6e9dadb291ae18fc1ec3575ed6d84c29642d97890f4b4a3417297e4" +dependencies = [ + "generic-array", +] + +[[package]] +name = "bytes" +version = "0.5.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e4cec68f03f32e44924783795810fa50a7035d8c8ebe78580ad7e6c703fba38" + +[[package]] +name = "bytes" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dfb24e866b15a1af2a1b663f10c6b6b8f397a84aadb828f12e5b289ec23a3a3c" + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "compute-static" +version = "0.1.0" +dependencies = [ + "fastly", + "log", +] + +[[package]] +name = "cpufeatures" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28d997bd5e24a5928dd43e46dc529867e207907fe0b239c3477d924f7f2ca320" +dependencies = [ + "libc", +] + +[[package]] +name = "digest" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066" +dependencies = [ + "generic-array", +] + +[[package]] +name = "fastly" +version = "0.8.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d14ee2f12a3191582449a2e080287eff8898fc52da61c437869d91c41b3ae2a" +dependencies = [ + "anyhow", + "bytes 0.5.6", + "cfg-if", + "fastly-macros", + "fastly-shared", + "fastly-sys", + "http", + "lazy_static", + "mime", + "serde", + "serde_json", + "serde_urlencoded", + "sha2", + "thiserror", + "time", + "url", +] + +[[package]] +name = "fastly-macros" +version = "0.8.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3d1b2980c09148cb84bfd18591943ee449a350dc1ff1ead69edbf012f7e2eef" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "fastly-shared" +version = "0.8.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f79939bdbbab8b1de759d584f386319454f8623681400675a07f9ad35f2b158" +dependencies = [ + "bitflags", + "http", + "thiserror", +] + +[[package]] +name = "fastly-sys" +version = "0.8.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d01e98274a6b12c85c0eef22924871cc12c54b5322268947322463e59d09336" +dependencies = [ + "bitflags", + "fastly-shared", +] + +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[package]] +name = "form_urlencoded" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a9c384f161156f5260c24a097c56119f9be8c798586aecc13afbcbe7b7e26bf8" +dependencies = [ + "percent-encoding", +] + +[[package]] +name = "generic-array" +version = "0.14.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bff49e947297f3312447abdca79f45f4738097cc82b06e72054d2223f601f1b9" +dependencies = [ + "typenum", + "version_check", +] + +[[package]] +name = "http" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75f43d41e26995c17e71ee126451dd3941010b0514a81a9d11f3b341debc2399" +dependencies = [ + "bytes 1.3.0", + "fnv", + "itoa", +] + +[[package]] +name = "idna" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e14ddfc70884202db2244c223200c204c2bda1bc6e0998d11b5e024d657209e6" +dependencies = [ + "unicode-bidi", + "unicode-normalization", +] + +[[package]] +name = "itoa" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fad582f4b9e86b6caa621cabeb0963332d92eea04729ab12892c2533951e6440" + +[[package]] +name = "lazy_static" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" + +[[package]] +name = "libc" +version = "0.2.138" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db6d7e329c562c5dfab7a46a2afabc8b987ab9a4834c9d1ca04dc54c1546cef8" + +[[package]] +name = "log" +version = "0.4.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "mime" +version = "0.3.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a60c7ce501c71e03a9c9c0d35b861413ae925bd979cc7a4e30d060069aaac8d" + +[[package]] +name = "opaque-debug" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" + +[[package]] +name = "percent-encoding" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "478c572c3d73181ff3c2539045f6eb99e5491218eae919370993b890cdbdd98e" + +[[package]] +name = "proc-macro2" +version = "1.0.49" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57a8eca9f9c4ffde41714334dee777596264c7825420f521abc92b5b5deb63a5" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8856d8364d252a14d474036ea1358d63c9e6965c8e5c1885c18f73d70bff9c7b" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "ryu" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b4b9743ed687d4b4bcedf9ff5eaa7398495ae14e61cba0a295704edbc7decde" + +[[package]] +name = "serde" +version = "1.0.151" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97fed41fc1a24994d044e6db6935e69511a1153b52c15eb42493b26fa87feba0" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.151" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "255abe9a125a985c05190d687b320c12f9b1f0b99445e608c21ba0782c719ad8" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "serde_json" +version = "1.0.91" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "877c235533714907a8c2464236f5c4b2a17262ef1bd71f38f35ea592c8da6883" +dependencies = [ + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "serde_urlencoded" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" +dependencies = [ + "form_urlencoded", + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "sha2" +version = "0.9.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4d58a1e1bf39749807d89cf2d98ac2dfa0ff1cb3faa38fbb64dd88ac8013d800" +dependencies = [ + "block-buffer", + "cfg-if", + "cpufeatures", + "digest", + "opaque-debug", +] + +[[package]] +name = "syn" +version = "1.0.107" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f4064b5b16e03ae50984a5a8ed5d4f8803e6bc1fd170a3cda91a1be4b18e3f5" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "thiserror" +version = "1.0.38" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a9cd18aa97d5c45c6603caea1da6628790b37f7a34b6ca89522331c5180fed0" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.38" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fb327af4685e4d03fa8cbcf1716380da910eeb2bb8be417e7f9fd3fb164f36f" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "time" +version = "0.3.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a561bf4617eebd33bca6434b988f39ed798e527f51a1e797d0ee4f61c0a38376" +dependencies = [ + "serde", + "time-core", + "time-macros", +] + +[[package]] +name = "time-core" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e153e1f1acaef8acc537e68b44906d2db6436e2b35ac2c6b42640fff91f00fd" + +[[package]] +name = "time-macros" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d967f99f534ca7e495c575c62638eebc2898a8c84c119b89e250477bc4ba16b2" +dependencies = [ + "time-core", +] + +[[package]] +name = "tinyvec" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50" +dependencies = [ + "tinyvec_macros", +] + +[[package]] +name = "tinyvec_macros" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c" + +[[package]] +name = "typenum" +version = "1.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba" + +[[package]] +name = "unicode-bidi" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "099b7128301d285f79ddd55b9a83d5e6b9e97c92e0ea0daebee7263e932de992" + +[[package]] +name = "unicode-ident" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "84a22b9f218b40614adcb3f4ff08b703773ad44fa9423e4e0d346d5db86e4ebc" + +[[package]] +name = "unicode-normalization" +version = "0.1.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c5713f0fc4b5db668a2ac63cdb7bb4469d8c9fed047b1d0292cc7b0ce2ba921" +dependencies = [ + "tinyvec", +] + +[[package]] +name = "url" +version = "2.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d68c799ae75762b8c3fe375feb6600ef5602c883c5d21eb51c09f22b83c4643" +dependencies = [ + "form_urlencoded", + "idna", + "percent-encoding", +] + +[[package]] +name = "version_check" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" diff --git a/terragrunt/modules/crates-io/compute-static/Cargo.toml b/terragrunt/modules/crates-io/compute-static/Cargo.toml index 7bceffcba..24a9e4b36 100644 --- a/terragrunt/modules/crates-io/compute-static/Cargo.toml +++ b/terragrunt/modules/crates-io/compute-static/Cargo.toml @@ -1,3 +1,8 @@ +# The Fastly function is built inside a virtual Terragrunt environment. Only the +# crates-io module is copied into this environment, which means it cannot be a +# part of the workspace at the root of this repository. +[workspace] + [package] name = "compute-static" description = "Compute@Edge function for static.crates.io" diff --git a/terragrunt/modules/crates-io/compute-static/README.md b/terragrunt/modules/crates-io/compute-static/README.md index 3bda35cff..da25b0287 100644 --- a/terragrunt/modules/crates-io/compute-static/README.md +++ b/terragrunt/modules/crates-io/compute-static/README.md @@ -6,7 +6,7 @@ function on [Fastly](https://fastly.com) to route incoming traffic for bucket, and will fail over to a fallback if it receives any HTTP `5xx` responses. -## Deployment +## Development Build the function: @@ -15,9 +15,17 @@ cd compute-static fastly compute build ``` +## Deployment + +Terraform uses an [external data source] to build the function as part of its +plan. This ensures that the function is always up-to-date, and prevents users +from accidentally uploading a stale version of the WASM module. + Export an API token for Fastly and then run Terraform: ```shell export FASTLY_API_KEY="" terraform plan ``` + +[external data source]: https://registry.terraform.io/providers/hashicorp/external/latest/docs/data-sources/data_source diff --git a/terragrunt/modules/crates-io/compute-static/bin/terraform-external-build.sh b/terragrunt/modules/crates-io/compute-static/bin/terraform-external-build.sh new file mode 100755 index 000000000..1c5e2fd18 --- /dev/null +++ b/terragrunt/modules/crates-io/compute-static/bin/terraform-external-build.sh @@ -0,0 +1,25 @@ +#!/usr/bin/env bash + +# Build script used by Terraform to build the function when planning. +# +# This script is called by Terraform to build the function when a user runs +# `terraform plan`. This ensures that the function is always up-to-date, and +# prevents users from accidentally uploading a stale version of the WASM module. +# +# Terraform expects the script to output a valid JSON object. +# +# https://registry.terraform.io/providers/hashicorp/external/latest/docs/data-sources/data_source + +# Enable strict mode for Bash +# http://redsymbol.net/articles/unofficial-bash-strict-mode/ +set -euo pipefail +IFS=$'\n\t' + +script_path=$(cd "$(dirname "${BASH_SOURCE[0]}")" &>/dev/null && pwd) +project_path=$(cd "${script_path}" && cd ".." && pwd) +project_name="${project_path##*/}" + +cd "${project_path}" && fastly compute build &>/dev/null + +# Return a valid JSON object that Terraform can consume +echo "{\"path\": \"./${project_name}/pkg/compute-static.tar.gz\"}" diff --git a/terragrunt/modules/crates-io/fastly-static.tf b/terragrunt/modules/crates-io/fastly-static.tf index c5454f7a3..31d5f5634 100644 --- a/terragrunt/modules/crates-io/fastly-static.tf +++ b/terragrunt/modules/crates-io/fastly-static.tf @@ -10,8 +10,11 @@ locals { fallback_host_name = aws_s3_bucket.fallback.region dictionary_name = "compute_static" +} - package_path = "./compute-static/pkg/compute-static.tar.gz" +data "external" "package" { + program = ["bash", "terraform-external-build.sh"] + working_dir = "./compute-static/bin" } ### Stage 1 @@ -52,8 +55,8 @@ resource "fastly_service_compute" "static" { } package { - filename = local.package_path - source_code_hash = filesha512(local.package_path) + filename = data.external.package.result.path + source_code_hash = filesha512(data.external.package.result.path) } }