This repository has been archived by the owner on Mar 23, 2021. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 32
/
service.py
80 lines (60 loc) · 2.51 KB
/
service.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
# -*- coding: utf-8 -*-
import os
import subprocess
import urllib
import boto3
# Version of Terraform that we're using
TERRAFORM_VERSION = '0.8.5'
# Download URL for Terraform
TERRAFORM_DOWNLOAD_URL = (
'https://releases.hashicorp.com/terraform/%s/terraform_%s_linux_amd64.zip'
% (TERRAFORM_VERSION, TERRAFORM_VERSION))
# Paths where Terraform should be installed
TERRAFORM_DIR = os.path.join('/tmp', 'terraform_%s' % TERRAFORM_VERSION)
TERRAFORM_PATH = os.path.join(TERRAFORM_DIR, 'terraform')
def check_call(args):
"""Wrapper for subprocess that checks if a process runs correctly,
and if not, prints stdout and stderr.
"""
proc = subprocess.Popen(args,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
cwd='/tmp')
stdout, stderr = proc.communicate()
if proc.returncode != 0:
print(stdout)
print(stderr)
raise subprocess.CalledProcessError(
returncode=proc.returncode,
cmd=args)
def install_terraform():
"""Install Terraform on the Lambda instance."""
# Most of a Lambda's disk is read-only, but some transient storage is
# provided in /tmp, so we install Terraform here. This storage may
# persist between invocations, so we skip downloading a new version if
# it already exists.
# http://docs.aws.amazon.com/lambda/latest/dg/lambda-introduction.html
if os.path.exists(TERRAFORM_PATH):
return
urllib.urlretrieve(TERRAFORM_DOWNLOAD_URL, '/tmp/terraform.zip')
# Flags:
# '-o' = overwrite existing files without prompting
# '-d' = output directory
check_call(['unzip', '-o', '/tmp/terraform.zip', '-d', TERRAFORM_DIR])
check_call([TERRAFORM_PATH, '--version'])
def apply_terraform_plan(s3_bucket, path):
"""Download a Terraform plan from S3 and run a 'terraform apply'.
:param s3_bucket: Name of the S3 bucket where the plan is stored.
:param path: Path to the Terraform planfile in the S3 bucket.
"""
# Although the /tmp directory may persist between invocations, we always
# download a new copy of the planfile, as it may have changed externally.
s3 = boto3.resource('s3')
planfile = s3.Object(s3_bucket, path)
planfile.download_file('/tmp/terraform.plan')
check_call([TERRAFORM_PATH, 'apply', '/tmp/terraform.plan'])
def handler(event, context):
s3_bucket = event['Records'][0]['s3']['bucket']['name']
path = event['Records'][0]['s3']['object']['key']
install_terraform()
apply_terraform_plan(s3_bucket=s3_bucket, path=path)