Skip to content

Instantly share code, notes, and snippets.

@dharrisio
Created August 16, 2016 17:11
Show Gist options
  • Save dharrisio/ad5f3a46cffc3b24e90705b40b4edab1 to your computer and use it in GitHub Desktop.
Save dharrisio/ad5f3a46cffc3b24e90705b40b4edab1 to your computer and use it in GitHub Desktop.
Terraform provisioner script to create Elastic Beanstalk Application Version.
#!/usr/bin/env python
"""Upload and Create Elastic Beanstalk Application Version
https://gitlab.com/dharrisio/terraform-elastic-beanstalk-application-version
This can be used as an alternative to the Terraform managed resource aws_elastic_beanstalk_application_version. This
script is meant to be used by a continuous deployment system (Bamboo, Jenkins, etc) and it should be called in two
places:
1) Separate task/stage that runs before Terraform
2) As a Terraform provisioner for the aws_elastic_beanstalk_application resource
This will ensure that the application version is created before Terraform creates or updates the Elastic Beanstalk
Environment. This also enables the Environment to be updated with one API call, instead of potentially two. On the
initial run, the script may fail if the Elastic Beanstalk Application has not been created yet. Because of this that
specific error is ignored by the script.
The following environment variables are used
TF_VAR_aws_region
TF_VAR_elastic_beanstalk_s3_bucket
TF_VAR_elastic_beanstalk_s3_key
TF_VAR_elastic_beanstalk_application_name
TF_VAR_elastic_beanstalk_application_version
Example Terraform Document
variable "aws_region" { }
variable "elastic_beanstalk_application_name" { }
variable "elastic_beanstalk_application_version" { }
provider "aws" {
region = "${var.aws_region}"
}
resource "aws_elastic_beanstalk_application" "default" {
name = "${var.elastic_beanstalk_application_name}"
description = ""
provisioner "local-exec" {
command = "./create_application_version.py"
}
}
resource "aws_elastic_beanstalk_environment" "default" {
name = ""
application = "${aws_elastic_beanstalk_application.default.name}"
solution_stack_name = ""
version_label = "${var.elastic_beanstalk_application_version}"
}
"""
import boto3, botocore.exceptions
import os, sys
import re
def check_bundle():
"""Check if the Elastic Beanstalk Application Version source bundle already exists"""
s3 = boto3.client('s3', region_name=os.environ['TF_VAR_aws_region'])
try:
s3.get_object(
Bucket=os.environ['TF_VAR_elastic_beanstalk_s3_bucket'],
Key=os.environ['TF_VAR_elastic_beanstalk_s3_key']
)
except botocore.exceptions.ClientError as e:
if e.response['Error']['Code'] == "NoSuchKey":
return False
else:
raise e
else:
return True
def upload_bundle():
"""Upload Elastic Beanstalk Application Version source bundle to S3"""
s3 = boto3.client('s3', region_name=os.environ['TF_VAR_aws_region'])
try:
s3.put_object(
Body=os.environ['TF_VAR_elastic_beanstalk_s3_key'],
Bucket=os.environ['TF_VAR_elastic_beanstalk_s3_bucket'],
Key=os.environ['TF_VAR_elastic_beanstalk_s3_key']
)
except Exception as e:
raise e
def create_application_version():
"""Create Elastic Beanstalk Application Version"""
beanstalk = boto3.client('elasticbeanstalk', region_name=os.environ['TF_VAR_aws_region'])
application_not_found_re = r'^No Application named .*? found.$'
try:
beanstalk.create_application_version(
ApplicationName=os.environ['TF_VAR_elastic_beanstalk_application_name'],
VersionLabel=os.environ['TF_VAR_elastic_beanstalk_application_version'],
SourceBundle={
'S3Bucket': os.environ['TF_VAR_elastic_beanstalk_s3_bucket'],
'S3Key': os.environ['TF_VAR_elastic_beanstalk_s3_key']
}
)
except botocore.exceptions.ClientError as e:
if re.match(application_not_found_re, e.response['Error']['Message']):
pass
else:
raise e
if __name__ == "__main__":
if not check_bundle():
upload_bundle()
create_application_version()
else:
print("Failed to create Application Version: source bundle already exists, please use a uniqe name")
sys.exit(-1)
@dsalazar-carecloud
Copy link

Really dig this gist! Quick question though. Does the current release of terraform actually contain the aws_elastic_beanstalk_application_version resource? And does the aws_elastic_beanstalk_environment support the version_label parameter? Master doesn't seem to have it and certainly not the version I have installed (Terraform v0.6.16).

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