Skip to content

Instantly share code, notes, and snippets.

@Roms1383
Last active January 12, 2020 09:23
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Roms1383/dda6bf9af5746548de074135b19ec0a0 to your computer and use it in GitHub Desktop.
Save Roms1383/dda6bf9af5746548de074135b19ec0a0 to your computer and use it in GitHub Desktop.
handle Serverless provisioning from Terraform
#!/bin/bash
# $1 is the name of the repository
# $2 is the optional tag of the repository
REMOVE=$(node should-remove.js microservice)
if [[ $REMOVE == "true" ]]; then
git clone https://github.com/owner/$1.git
cd $1/
if [ "$2" != "" ]; then
git checkout tags/$2 -b $2
fi
yarn install
yarn serverless remove
cd ..
rm -rf $1/
fi
#!/bin/bash
# $1 is the name of the repository
# $2 is the optional tag of the repository
git clone https://github.com/owner/$1.git
cd $1/
if [ "$2" != "" ]; then
git checkout tags/$2 -b $2
fi
yarn install
yarn serverless deploy
cd ..
rm -rf $1/
...
locals { microservice_version = "v1.9.0" }
resource "null_resource" "microservice" {
# either do not define count or set count = 0 for soft deletion
depends_on = [null_resource.some_other_resource]
triggers = { version = "${local.microservice_version}" }
provisioner "local-exec" {
# deploy from serverless
command = "bash deploy.sh microservice ${local.microservice_version}"
# required environment variables
environment = { ... }
}
provisioner "local-exec" {
# deploy from serverless
command = "bash conditional-removal.sh microservice ${local.microservice_version}"
when = destroy
# required environment variables
environment = { ... }
}
}
const fs = require('fs')
const path = require('path')
const hcltojson = require('hcl-to-json')
const config = fs.readFileSync(path.join(__dirname, 'main.tf'), { encoding: 'utf8' })
// $1 is the name of the repository
const [repo] = process.argv.slice(2)
const { resource } = hcltojson(config)
const { null_resource } = resource
const definition = null_resource[repo]
const count = definition.hasOwnProperty('count') ? definition.count : 1
// not marked for deletion
if (count === 1) console.log(false)
// count should either be undefined or set to 0
else if (count > 1) throw new Error('this script cannot handle multiple count of the same null_resource')
// has been marked for deletion
else console.log(true)
@Roms1383
Copy link
Author

It's worth mentioning that any change to null_resource definition will trigger the destroy-time provisioner, but we might not want serverless remove to be run on each change, except if count = 0 or if the resource it depends_on has been deleted, hence this workaround to handle conditional-removal.

@Roms1383
Copy link
Author

Roms1383 commented Jan 10, 2020

As a side note it seems possible to handle multiple count on the null_resource by introspecting both terraform.tfstate and terraform.tfstate.backup and guessing which one have been added, deleted or had its version updated.

Also it's probably possible to do everything in bash in case we don't want to rely on JavaScript for files parsing purpose, but that might require hardcore awk commands or installing additional package like jq (which then would require additional scripts / packages work to work on platforms other than Linux).

A better alternative would be to create a Terraform Module to handle all this automatically, but it's far beyond my sample purpose :)

@Roms1383
Copy link
Author

Roms1383 commented Jan 10, 2020

Sadly I tested to create a Terraform module locally but even if the script currently executes and does the job, this way is clearly stated as deprecated and might stop to work in future versions of Terraform.

My current version is :

Terraform v0.12.19
+ provider.null v2.1.2

whether using variables.tf :
Screen Shot 2563-01-10 at 21 26 16

or piping them through environment :
Screen Shot 2563-01-10 at 21 11 25

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment