Created
January 23, 2019 16:50
-
-
Save Qix-/6bc9a709b661a4f4defa7d822fb9d80a to your computer and use it in GitHub Desktop.
Example Terraform HTTP backend implementation for Node.js. Stores the state in a local object. Not meant for production, but more to show how one would go about implementing the HTTP api for it since it's not well documented.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
terraform { | |
backend "http" { | |
address = "http://localhost:8080/tfstate" | |
lock_address = "http://localhost:8080/tfstate" | |
unlock_address = "http://localhost:8080/tfstate" | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const URL = require('url'); | |
const bodyParser = require('body-parser'); | |
const express = require('express'); | |
const app = express(); | |
app.use(bodyParser.json()); | |
app.use(bodyParser.text()); | |
app.use((req, res, next) => { | |
req.uri = URL.parse(req.url, true); | |
req.uri | |
next(); | |
}); | |
app.use((req, res, next) => { | |
console.error('\x1b[47m\n\x1b[m'); | |
console.error('------------'); | |
console.error('%s %s', req.method, req.url); | |
console.error(''); | |
console.error('HEADERS'); | |
console.error(''); | |
console.error(req.headers); | |
console.error(''); | |
console.error('BODY'); | |
console.error(''); | |
console.error(req.body); | |
console.error('------------'); | |
next(); | |
}); | |
let locked = null; | |
let state = null; | |
app.use('/tfstate', (req, res) => { | |
switch (req.method) { | |
case 'LOCK': | |
if (locked) { | |
console.error('FAIL: already locked'); | |
return res.status(409).end('nice try, buckaroo - I already seen ye'); | |
} | |
console.error('OK: lock'); | |
locked = req.body.ID; | |
return res.status(200).end('as you wisharoo, buckaroo'); | |
case 'UNLOCK': | |
if (locked && req.body.ID !== locked) { | |
console.error('FAIL: lock conflict (wrong ID)'); | |
return res.status(409).end('uhwaiit, who are you again?'); | |
} | |
console.error('OK: unlock'); | |
locked = null; | |
return res.status(200).end('mischief managed, buckaroo'); | |
case 'POST': | |
if (!locked || (locked && locked === req.uri.query['ID'])) { | |
console.error('OK: store'); | |
state = req.body; | |
return res.status(200).end('gimme dat JSON, buckaroo'); | |
} | |
console.error('FAIL: locked'); | |
return res.status(423).end('not today, karen'); | |
case 'GET': | |
console.error('OK: give state'); | |
return res.status(200).end(state !== null && typeof state === 'object' ? JSON.stringify(state) : state || ''); | |
default: | |
console.error('FAIL: unknown method'); | |
return res.status(405).end('wat?'); | |
} | |
}); | |
app.get('/health', (req, res) => res.status(200).end('ok')); | |
app.listen(8080); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Note that you have to check if the state is an object if you're using an automatic body parser since some old versions of Terraform's state were plaintext.