Skip to content

Commit

Permalink
Merge pull request #10 from ibejohn818/refactor-userdata
Browse files Browse the repository at this point in the history
update asg
  • Loading branch information
ibejohn818 authored Dec 29, 2017
2 parents 2931a48 + 0becd8f commit a684174
Show file tree
Hide file tree
Showing 11 changed files with 126 additions and 36 deletions.
8 changes: 1 addition & 7 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,7 @@ StackFormation
:alt: Updates


Stackfromation is an AWS CloudFormation framework that allows you to enforce "Infrastructure-as-code".
It uses a convention to allow you to manage your stack-resources as python objects.
It does not bind stacks together using Import and allows for more predictable updates to existing stacks
and quick prototyping of your infrastructure to different stages IE: DEV, STAGING & PRODUCTION.

Optionally, it also enforces an AMI workflow that separates the construction and updating of your AMI's
using ansible and packer.
Cloudformation framework to enforce infrastructure-as-code paradigm


Installation
Expand Down
8 changes: 1 addition & 7 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,16 +48,10 @@
zip_safe=False,
keywords='stackformation',
classifiers=[
'Development Status :: 2 - Pre-Alpha',
'Development Status :: Beta',
'Intended Audience :: Developers',
'License :: OSI Approved :: MIT License',
'Natural Language :: English',
"Programming Language :: Python :: 2",
'Programming Language :: Python :: 2.6',
'Programming Language :: Python :: 2.7',
'Programming Language :: Python :: 3',
'Programming Language :: Python :: 3.3',
'Programming Language :: Python :: 3.4',
'Programming Language :: Python :: 3.5',
],
test_suite='tests',
Expand Down
2 changes: 1 addition & 1 deletion stackformation/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -198,7 +198,7 @@ def get_dependent_stacks(self, stack):

env = utils.jinja_env({}, True)

stack.parse_template_components(env[0], Context())
stack.render_template_components(env[0], Context())


params += env[1]
Expand Down
25 changes: 25 additions & 0 deletions stackformation/aws/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,24 @@


DEFAULT_AMIS = {
'us-east-1':{
'awslinux': '',
'ubuntu': ''
},
'us-east-2': {
'awslinux': '',
'ubuntu': ''
},
'us-west-1': {
'awslinux': '',
'ubuntu': ''
},
'us-west-2': {
'awslinux': '',
'ubuntu': ''
},
}

class PackerImage(object):

def __init__(self, name):
Expand All @@ -9,6 +29,11 @@ def __init__(self, name):
self.boto_session = None
self.stack = None

def get_base_ami(self):
region = self.boto_session.get_conf('region')
ami = DEFAULT_AMIS[region][self.os_type]
return ami

def add_role(self, role_name, vars = {}, weight=900):
"""Add ansible role to image
Expand Down
12 changes: 8 additions & 4 deletions stackformation/aws/ami.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
},
]
},
'aws': {
'awslinux': {
'username': 'ec2-user',
'ami_filters': [
{
Expand Down Expand Up @@ -48,11 +48,11 @@ def __init__(self, name, os_type='aws'):

class Ami(PackerImage):

def __init__(self, name, os_type='aws'):
def __init__(self, name, os_type='awslinux'):

super(Ami, self).__init__(name)
self.os_type = os_type

self.base_ami_info = None


def get_base_ami(self):
Expand Down Expand Up @@ -107,7 +107,11 @@ def get_base_ami(self):
key=lambda item: item['CreationDate'],
reverse=True)

return amis_query['Images'][0]['ImageId']
ami = amis_query['Images'][0]

self.base_ami_info = ami

return ami['ImageId']

def get_ami(self):
return self.get_base_ami()
Expand Down
10 changes: 5 additions & 5 deletions stackformation/aws/stacks/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ def add_template_component(self, var, component):

self.template_components[var].append(component)

def parse_template_components(self, env, context):
def render_template_components(self, env, context):

results = {}

Expand All @@ -112,7 +112,7 @@ def parse_template_components(self, env, context):

for k, v in self.template_components.items():
for c in v:
text = c.text()
text = c.render()
t = env.from_string(text)
if not results.get(k):
results[k] = []
Expand Down Expand Up @@ -239,12 +239,12 @@ def start_deploy(self, infra, context):

template = self.build_template()
parameters = self.get_parameters()
template_vars = self.parse_template_components(env[0], context)
template_vars = self.render_template_components(env[0], context)

self.before_deploy(context, parameters)

parameters = self.fill_params(parameters, context)
print(parameters)

dep_kw = {
'StackName': self.get_remote_stack_name(),
'TemplateBody': template.to_json(),
Expand Down Expand Up @@ -432,5 +432,5 @@ def build_template(self):

class TemplateComponent(object):

def text(self, infra, context):
def render(self, infra, context):
raise Exception("Must implement get_template method")
28 changes: 22 additions & 6 deletions stackformation/aws/stacks/asg.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,9 @@ def __init__(self, name, vpc, iam_profile):
self.private_subnet = False
self.security_groups = []
self.pause_time = 'PT5M'
self.update_policy_instance_count = 0
self.ami = None
self.update_policy_instance_count = 2
self.ami = None,
self.keyname = None

def set_ami(self, ami):
if isinstance(ami, (PackerImage)):
Expand Down Expand Up @@ -113,6 +114,8 @@ def build_template(self):
Description="{} Root Device Type".format(self.stack_name)
))



# instance profile
instance_profile_param = t.add_parameter(Parameter(
self.iam_profile.output_instance_profile(),
Expand Down Expand Up @@ -157,6 +160,7 @@ def build_template(self):

lconfig = t.add_resource(autoscaling.LaunchConfiguration(
'{}LaunchConfiguration'.format(self.name),
AssociatePublicIpAddress=True,
IamInstanceProfile=Ref(instance_profile_param),
BlockDeviceMappings=[
ec2.BlockDeviceMapping(
Expand All @@ -176,18 +180,30 @@ def build_template(self):
"exec > >(tee /var/log/user-data.log|logger ",
"-t user-data -s 2>/dev/console) 2>&1\n",
] + user_data_refs + [
"\n", "yum update -y aws-cfn-bootstrap", "\n",
"\n",
"#yum update -y aws-cfn-bootstrap",
"\n",
"curl -L https://gist.github.com/ibejohn818",
"/aa2bcd6743a59f62e1baa098d6365a61/raw/",
"/ubuntu-init.sh",
" -o /tmp/ubuntu-init.sh && chmod +x /tmp/ubuntu-init.sh",
"\n",
"/tmp/ubuntu-init.sh",
"\n",
#] + wait_cmd + [
"/opt/aws/bin/cfn-signal -e 0",
" --resource AutoscalingGroup",
"cfn-signal -e 0",
" --resource {}AutoScalingGroup".format(self.stack_name),
" --stack ", Ref("AWS::StackName"),
" --region ", Ref("AWS::Region"), "\n",
]
))
))

if self.keyname:
lconfig.KeyName = self.keyname

asg = t.add_resource(autoscaling.AutoScalingGroup(
'{}AutoScalingGroup'.format(self.name),
'{}AutoScalingGroup'.format(self.stack_name),
LaunchConfigurationName=Ref(lconfig),
MinSize=Ref(min_inst),
MaxSize=Ref(max_inst),
Expand Down
10 changes: 5 additions & 5 deletions stackformation/aws/user_data.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ class CreateCommonDirs(UserData):
def __init__(self, name):
super(CreateCommonDirs, self).__init__(name)

def text(self):
def render(self):
return """
mkdir -p /opt/stackformation/serf || true
"""
Expand All @@ -30,7 +30,7 @@ def __init__(self, name, text):

self.text = text

def text(self):
def render(self):
return text


Expand All @@ -42,7 +42,7 @@ def __init__(self, eip):

self.eip = eip

def text(self):
def render(self):

return """
echo {{context('%s')}} >> /tmp/testip
Expand All @@ -56,7 +56,7 @@ def __init__(self, eip):

self.eip = eip

def text(self):
def render(self):
return """
echo {{{{context('{0}')}}}} > /opt/ip.eip
echo {{{{context('{1}')}}}} > /opt/allocation.eip
Expand All @@ -72,7 +72,7 @@ def __init__(self, ebs_volume, path):
self.ebs_volume = ebs_volume
self.path = path

def text(self):
def render(self):

return """
if file -sL {{{{context('Input{0}EBSDeviceName')}}}} | grep -vq ext4; then
Expand Down
2 changes: 1 addition & 1 deletion tests/test_aws_ec2.py
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ def test_ec2_stack(infra):

env = utils.jinja_env(prod_infra.context, True)

res = ec2_stack.parse_template_components(env[0], prod_infra.context)
res = ec2_stack.render_template_components(env[0], prod_infra.context)

assert env[1][0] == 'ProdTestTestEIPWebEipEIP'
assert env[1][1] == 'ProdTestTestEIPWebEipAllocationId'
Expand Down
36 changes: 36 additions & 0 deletions tests/test_aws_stacks_eip.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import pytest
import stackformation
from stackformation.aws.stacks import eip




@pytest.fixture
def test_infra():

infra = stackformation.Infra('test')
test_infra = infra.create_sub_infra('test')


return {
'infra': infra,
'test_infra': test_infra
}

def test_eip_stack(test_infra):

eip_stack = test_infra['test_infra'].add_stack(eip.EIPStack('test'))

web_ip = eip_stack.add_ip('Web')

assert isinstance(web_ip, (eip.EIP))

find_ip = eip_stack.find_ip('Web')

assert find_ip.name == 'Web'

none_ip = eip_stack.find_ip('none')

assert none_ip is None

t = eip_stack.build_template()
21 changes: 21 additions & 0 deletions tests/test_aws_user_data.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import pytest
import stackformation
from stackformation.aws import user_data
from stackformation.aws.stacks import (ec2)
from stackformation import utils


@pytest.fixture
def test_infra():

infra = stackformation.Infra("test")
test_infra = infra.create_sub_infra("test")
ec2_stack = test_infra.add_stack(ec2.EC2Stack('test'))
env = utils.jinja_env(test_infra.context, True)

return {
'infra': infra,
'test_infra': test_infra,
'ec2_stack': ec2_stack,
'env': env
}

0 comments on commit a684174

Please sign in to comment.