From e1e7a1975410fe74770c576e5b00af9cc48d26bd Mon Sep 17 00:00:00 2001 From: sbraverman Date: Tue, 16 Jun 2015 11:14:58 -0700 Subject: [PATCH] Added cfn2pyclass - this is backwards compatible. Creates python classes of resources for AWS --- scripts/TroposphereClassCreator.py | 239 +++++++++++++++++ scripts/cfn2pyclass | 394 +++++++++++++++++++++++++++++ scripts/templates/base | 65 +++++ scripts/templates/egressParent | 14 + scripts/templates/ingressParent | 14 + scripts/templates/securityGroup | 34 +++ 6 files changed, 760 insertions(+) create mode 100644 scripts/TroposphereClassCreator.py create mode 100644 scripts/cfn2pyclass create mode 100644 scripts/templates/base create mode 100644 scripts/templates/egressParent create mode 100644 scripts/templates/ingressParent create mode 100644 scripts/templates/securityGroup diff --git a/scripts/TroposphereClassCreator.py b/scripts/TroposphereClassCreator.py new file mode 100644 index 000000000..12b45ce0d --- /dev/null +++ b/scripts/TroposphereClassCreator.py @@ -0,0 +1,239 @@ +#!/usr/bin/env python + +from jinja2 import Environment, FileSystemLoader +import os +import json +import re + + +class TroposphereClassCreator(object): + """ + Creates python classes for AWS instances in an easy to use tree structure + """ + + def __init__(self, baseDirectory, instances): + self.baseDirectory = baseDirectory + self.instances = instances + + def makeClasses(self): + hasSecurityGroup = False + for instance in self.instances: + for name in self.instances[instance]: + # Security Groups will be handled later in the process + if self.isSecurityGroupType(name): + hasSecurityGroup = True + continue + for node in self.instances[instance][name]: + baseDir = self.baseDirectory + '/' + nameDir = baseDir + name + '/' + self.makePythonDirectoryIfNecessary(baseDir) + self.makePythonDirectoryIfNecessary(nameDir) + nodeParams = self.getParamsFromNode(name, node) + className = nodeParams['class_name'] + '.py' + output = self.getDataFromTemplate('base', nodeParams) + self.makeFile(nameDir, className, output) + # if security groups exist, handle them now + if hasSecurityGroup: + self.makeSecurityGroups() + + def makeSecurityGroups(self): + securityGroups = self.initSecurityGroups() + securityGroups = self.initIngressRules(securityGroups) + securityGroups = self.initEgressRules(securityGroups) + + baseDir = self.baseDirectory + '/' + securityGroupDir = baseDir + 'SecurityGroups/' + + self.makePythonDirectoryIfNecessary(securityGroupDir) + + ingressParent = self.getDataFromTemplate('ingressParent') + ingressFile = 'SecurityGroupIngress.py' + self.makeFile(securityGroupDir, ingressFile, ingressParent) + egressParent = self.getDataFromTemplate('egressParent') + egressFile = 'SecurityGroupEgress.py' + self.makeFile(securityGroupDir, egressFile, egressParent) + + for node in self.getAWSInstanceNameContent('ec2', 'SecurityGroup'): + params = self.getParamsFromNode('SecurityGroup', node) + className = params['class_name'] + ingressRules = securityGroups[className]['ingressRules'] + params['egress_rules'] = securityGroups[className]['egressRules'] + + # SecurityGroups may not contain more than 50 rules each. + counter = 1 + while len(ingressRules) > 50: + counter += 1 + params['class_name'] = className + str(counter) + classFile = params['class_name'] + '.py' + params['ingress_rules'] = ingressRules[:50] + parsedOutput = self.getDataFromTemplate('securityGroup', + params) + self.makeFile(securityGroupDir, classFile, parsedOutput) + del ingressRules[:50] + + # At this point, we have less than 50 rules. Create the file as is. + params['class_name'] = className + classFile = className + '.py' + params['ingress_rules'] = ingressRules + parsedOutput = self.getDataFromTemplate('securityGroup', params) + self.makeFile(securityGroupDir, classFile, parsedOutput) + + def initIngressRules(self, securityGroups): + ingressRuleKey = 'ingressRules' + ingressName = 'SecurityGroupIngress' + ingressNodes = self.getAWSInstanceNameContent('ec2', ingressName) + for node in ingressNodes: + allParams = self.getParamList(node) + securityGroupName = self.getValidSecurityGroupName(allParams) + ingressRule = self.getIngressRule(allParams) + ingressRules = securityGroups[securityGroupName][ingressRuleKey] + if ingressRule not in ingressRules: + ingressRules.append(ingressRule) + return securityGroups + + def initEgressRules(self, securityGroups): + egressRuleKey = 'egressRules' + egressName = 'SecurityGroupEgress' + egressNodes = self.getAWSInstanceNameContent('ec2', egressName) + for node in egressNodes: + allParams = self.getParamList(node) + securityGroupName = self.getValidSecurityGroupName(allParams) + egressRule = self.getEgressRule(allParams) + egressRules = securityGroups[securityGroupName][egressRuleKey] + if egressRule not in egressRules: + egressRules.append(egressRule) + return securityGroups + + def getEgressRule(self, nodeList): + ipProtocol = self.findStringInList('IpProtocol', nodeList) + cidrIP = self.findStringInList('CidrIp', nodeList) + baseString = 'securityGroupEgress.addRule(' + endString = ')' + + ruleParams = "ipProtocol='{}', cidrIp='{}'".format(ipProtocol, cidrIP) + return baseString + ruleParams + endString + + def getValidSecurityGroupName(self, params): + name = self.findStringInList('GroupId', params) + if name == '': + name = self.findStringInList('GroupName', params) + if name == '': + name = self.findStringInList('GroupId', params, '(', ')') + if name == '': + name = self.findStringInList('GroupName', params, '(', ')') + return name + + def getIngressRule(self, nodeList): + ipProtocol = self.findStringInList('IpProtocol', nodeList) + fromPort = self.findStringInList('FromPort', nodeList) + toPort = self.findStringInList('ToPort', nodeList) + cidrIP = self.findStringInList('CidrIp', nodeList) + baseString = 'securityGroupIngress.addRule(' + endString = ')' + + ruleParams = "ipProtocol='{0}', fromPort='{1}', toPort='{2}', " \ + "cidrIp='{3}'" + formattedRules = ruleParams.format( + ipProtocol, fromPort, toPort, cidrIP) + return baseString + formattedRules + endString + + def findStringInList(self, string, theList, + lowerBound='"', upperBound='"'): + line = '' + for item in theList: + if string in item: + return self.getValueInDelimiter(item.strip(), + lowerBound, upperBound) + return line + + def getValueInDelimiter(self, string, lowerBound='"', upperBound='"'): + try: + regEx = r"\{0}(.*)\{1}".format(lowerBound, upperBound) + matchedName = re.search(regEx, string) + return matchedName.group(1) + except: + return '' + + def initSecurityGroups(self): + SecurityGroups = {} + awsName = 'SecurityGroup' + securityGroupNodes = self.getAWSInstanceNameContent('ec2', awsName) + for node in securityGroupNodes: + paramList = self.getParamList(node) + name = self.getName(paramList[1]) + if name not in SecurityGroups: + SecurityGroups[name] = {'properties': paramList[1:-1], + 'ingressRules': [], 'egressRules': []} + return SecurityGroups + + def makePythonDirectoryIfNecessary(self, directory): + if not os.path.exists(directory): + os.makedirs(directory) + self.makeInitPythonFile(directory) + + def makeInitPythonFile(self, directory): + self.makeFile(directory, '__init__.py') + + def makeFile(self, directory, fileName, contents=' '): + with open(directory + fileName, 'w') as newFile: + newFile.write(contents) + + def getParamsFromNode(self, instance, node): + paramList = self.getParamList(node) + method = self.getMethod(paramList[0]) + name = self.getName(paramList[1]) + properties = paramList[1:-1] + return {'template_method': method, 'instance_type': instance, + 'class_name': name, 'properties': properties} + + def getParamList(self, node): + return node.strip().split('\n') + + def getProperties(self, paramList): + return '\n'.join(paramList) + + def getName(self, secondLineOfNode): + return secondLineOfNode.split(',')[0].strip()[1:-1] + + def getMethod(self, firstLineOfNode): + methodLine = firstLineOfNode.split('=')[1].strip() + return methodLine.split('(')[0] + + def isSecurityGroupType(self, name): + securityName = 'SecurityGroup' + ingressName = 'SecurityGroupIngress' + egressName = 'SecurityGroupEgress' + securityGroupTypes = [securityName, ingressName, egressName] + return name in securityGroupTypes + + def getDataFromTemplate(self, fileName, dictionary={}): + env = Environment(loader=FileSystemLoader('templates')) + template = env.get_template(fileName) + return template.render(dictionary) + + def getAWSInstances(self): + return self.instances + + def getAWSInstanceNames(self, awsInstance): + try: + return self.dictionary[awsInstance] + except: + print 'Failed to get: {0}'.format(awsInstance) + + def printAWSInstances(self): + for x in self.instances: + print x + + def printAWSInstanceNames(self, instance): + for x in self.instances[instance]: + print x + + def printAWSInstanceNameContent(self, instance, name): + for x in self.instances[instance][name]: + print x + + def getAWSInstanceNameContent(self, instance, name): + try: + return self.instances[instance][name] + except: + print 'Failed to get: {0}/{1}'.format(instance, name) diff --git a/scripts/cfn2pyclass b/scripts/cfn2pyclass new file mode 100644 index 000000000..6bba7f7ff --- /dev/null +++ b/scripts/cfn2pyclass @@ -0,0 +1,394 @@ +#!/usr/bin/env python + +import argparse +import json +import pprint +from TroposphereClassCreator import TroposphereClassCreator + +imports = '' +header = '' +footer = '' +currentNode = '' +allNodes = {} +def addToNode(node, addition=''): + return node + addition + '\n' + +def appendToAllNodes(awsType, tropo_name, node): + global allNodes + if awsType not in allNodes: + allNodes[awsType] = {} + if tropo_name not in allNodes[awsType]: + allNodes[awsType][tropo_name] = [node] + else: + allNodes[awsType][tropo_name].append(node) + +class object_registry(object): + """Keep track of objects being created as Parameters or Resources + in order to map back to due to use in intrinsic functions like + Ref() and GetAtt(). + """ + def __init__(self): + self.objects = {} + + def add(self, o): + new_name = o.replace('-', '_') + self.objects[o] = new_name + return new_name + + def lookup(self, o): + if o in self.objects: + return self.objects[o] + else: + return output_value(o) + +objects = object_registry() + +object_functions = { + "Table": [ "ProvisionedThroughput", "PrimaryKey", "Element" ], + "LoadBalancer": [ "HealthCheck", "ConnectionDrainingPolicy", "AccessLoggingPolicy" ], + "Queue": [ "RedrivePolicy" ], + "Bucket": [ "WebsiteConfiguration" ], + "User": [ "LoginProfile" ], + "Topic": [ "Subscription" ], + "Instance": [ "NetworkInterfaceProperty", "PrivateIpAddressSpecification" ], + "RecordSet": [ "RecordSetType" ], + "Policy": [ "PolicyType" ], +} + +def additional_imports(o): + if object_functions.has_key(o): + return ", ".join([o] + object_functions[o]) + else: + return o + +def do_header(d): + global imports + global header + """Output a stock header for the new Python script and also try to + figure out the Resource imports needed by the template. + """ + imports = addToNode(imports,'from troposphere import Base64, Select, FindInMap, GetAtt, GetAZs, Join, Output') + imports = addToNode(imports, 'from troposphere import Parameter, Ref, Tags, Template') + imports = addToNode(imports, 'from troposphere.cloudformation import Init') + imports = addToNode(imports, 'from troposphere.cloudfront import Distribution, DistributionConfig') + imports = addToNode(imports, 'from troposphere.cloudfront import Origin, DefaultCacheBehavior') + imports = addToNode(imports, 'from troposphere.ec2 import PortRange') + + # Loop over the resources to find imports + if 'Resources' in d: + seen = [] + resources = d['Resources'] + for k, v in resources.items(): + (mod, tropo_object) = generate_troposphere_object(v['Type']) + if tropo_object not in seen: + seen.append(tropo_object) + imports = addToNode(imports, 'from troposphere.%s import %s' % (mod, additional_imports(tropo_object))) + imports = addToNode(imports) + imports = addToNode(imports) + header = addToNode(header, "t = Template()") + header = addToNode(header) + + +def do_awstemplateformatversion(d): + """Output the template version""" + global header + header = addToNode(header, 't.add_version("%s")' % (d['AWSTemplateFormatVersion'], )) + header = addToNode(header) + + +def do_description(d): + """Output the template Description""" + global header + header = addToNode(header, 't.add_description("""\\\n%s""")' % (d['Description'], )) + + +def do_parameters(d): + global currentNode + """Output the template Parameters""" + params = d['Parameters'] + for k, v in params.items(): + object_name = objects.add(k) + currentNode = addToNode(currentNode, '%s = t.add_parameter(Parameter(' % (object_name,)) + currentNode = addToNode(currentNode, ' "%s",' % (k, )) + for pk, pv in v.items(): + currentNode = addToNode(currentNode, ' %s=%s,' % (pk, output_value(pv))) + currentNode = addToNode(currentNode, "))") + + +def do_mappings(d): + global currentNode + """Output the template Mappings""" + mappings = d['Mappings'] + for k, v in mappings.items(): + currentNode = addToNode(currentNode, 't.add_mapping("%s",' % (k,)) + currentNode = addToNode(v) + currentNode = addToNode(currentNode, ")") + + +def generate_troposphere_object(typename): + """Try to determine the troposphere object to create from the Type + specification from the Resource being converted. + """ + t = typename.split(':') + if len(t) == 5: + return (t[2].lower(), t[4]) + else: + return ('', typename) + + +def output_dict(d): + out = [] + for k,v in d.items(): + out.append("%s=%s" % (k.replace('\\', '\\\\'), output_value(v))) + return ", ".join(out) + +known_functions = { + "DistributionConfig": 1, + "DefaultCacheBehavior": 1, + "ProvisionedThroughput": 1, + "NetworkInterfaces": 1, + "WebsiteConfiguration": 1, + "RedrivePolicy": 1, + "Subscription": 1, + "KeySchema": 1, + "HashKeyElement": 1, + "HealthCheck": 1, + "LoginProfile": 1, + "ConnectionDrainingPolicy": 1, + "AccessLoggingPolicy": 1, + "AWS::CloudFormation::Init":1, + "PrivateIpAddresses" :1, + "VersioningConfiguration": 1, + "HostedZoneConfig": 1, +} + +function_quirks = { + "KeySchema": "PrimaryKey", + "HashKeyElement": { "Element": ["AttributeName", "AttributeType"] }, + "NetworkInterfaces": [ "NetworkInterfaceProperty" ], + "Subscription": [ "Subscription" ], + "LoginProfile": { "LoginProfile": ["Password"] }, + "AWS::CloudFormation::Init": {"Init": []}, + "PrivateIpAddresses" : ["PrivateIpAddressSpecification"], + "VersioningConfiguration": "VersioningConfiguration", + "HostedZoneConfig": "HostedZoneConfiguration", +} + +def do_output_function(k, f, v): + global currentNode + currentNode = addToNode(currentNode, ' %s=%s(' % (k, f)) + for pk, pv in v.items(): + if known_functions.has_key(pk): + do_resources_content(pk, pv) + else: + currentNode = addToNode(currentNode, " %s=%s," % (pk, output_value(pv))) + currentNode = addToNode(currentNode, ' ),') + +def do_output_quirk_list(k, f, v): + global currentNode + currentNode = addToNode(currentNode, ' %s=[' % (k)) + for e in v: + currentNode = addToNode(currentNode, ' %s(' % (f)) + for pk, pv in e.items(): + if known_functions.has_key(pk): + do_resources_content(pk, pv) + else: + currentNode = addToNode(currentNode, " %s=%s," % (pk, output_value(pv))) + currentNode = addToNode(currentNode, ' ),') + currentNode = addToNode(currentNode, ' ],') + +def do_output_quirk_mapping(k, v): + global currentNode + m = function_quirks[k] + for pk in m.keys(): + currentNode = addToNode(currentNode, ' %s=%s(' % (k, pk)) + for e in m[pk]: + currentNode = addToNode(currentNode, " %s," % (output_value(v[e]))) + currentNode = addToNode(currentNode, ' ),') + +def do_output_quirk_metadata(k, v): + global currentNode + m = function_quirks[k] + for pk in m.keys(): + currentNode = addToNode(currentNode, ' Metadata=%s(' % (pk)) + currentNode = addToNode(currentNode, " %s," % (output_value(v))) + currentNode = addToNode(currentNode, ' ),') + +def do_resources_content(k, v, p=""): + if function_quirks.has_key(k): + x = function_quirks[k]; + if(isinstance(x, dict)): + if(p == "Metadata"): + do_output_quirk_metadata(k, v) + else: + do_output_quirk_mapping(k, v) + elif(isinstance(x, list)): + do_output_quirk_list(k, x[0], v) + else: + do_output_function(k, x, v) + else: + do_output_function(k, k, v) + +top_level_aliases = { + "RecordSet": "RecordSetType", + "Policy": "PolicyType", +} + +def do_resources(d): + global currentNode + """Output the template Resources""" + resources = d['Resources'] + for k, v in resources.items(): + currentNode = '' + object_name = objects.add(k) + (_, tropo_object) = generate_troposphere_object(v['Type']) + if(top_level_aliases.has_key(tropo_object)): + tropo_object = top_level_aliases[tropo_object] + currentNode = addToNode(currentNode, '%s = t.add_resource(%s(' % (object_name, tropo_object)) + currentNode = addToNode(currentNode, ' "%s",' % (k, )) + for p in filter(lambda x: v.has_key(x), ['Metadata', 'Properties']): + for pk, pv in v[p].items(): + if pk == "Tags": + currentNode = addToNode(currentNode, ' Tags=Tags(') + for d in pv: + currentNode = addToNode(currentNode, " %s=%s," % ( + d['Key'], output_value(d['Value']))) + currentNode = addToNode(currentNode, ' ),') + elif pk == 'PortRange': + currentNode = addToNode(currentNode, " %s=%s(%s)," % (pk, pk, output_dict(pv))) + elif known_functions.has_key(pk): + do_resources_content(pk, pv, p) + elif isinstance(pv, basestring): + if pkShouldBeInt(pk): + currentNode = addToNode(currentNode, ' {0}={1},'.format(pk, pv)) + else: + currentNode = addToNode(currentNode, ' %s="%s",' % (pk, pv)) + else: + currentNode = addToNode(currentNode, ' %s=%s,' % (pk, output_value(pv))) + if v.has_key("DependsOn"): + currentNode = addToNode(currentNode, ' %s=%s,' % ("DependsOn", output_value(v['DependsOn']))) + currentNode = addToNode(currentNode, "))") + appendToAllNodes(_, tropo_object, currentNode) + +def pkShouldBeInt(pv): + intList = ['HealthCheckGracePeriod'] + return pv in intList + +def handle_no_objects(name, values): + """Handle intrinsic functions which do not have a named resource""" + return name + "(" + ", ".join(map(output_value, values)) + ")" + +def handle_one_object(name, values): + """Handle intrinsic functions which have a single named resource""" + ret = name + "(" + for i, param in enumerate(values): + if i > 0: + ret += ", " + # First parameter might be an object name or pseudo parameter + if i == 0: + ret += objects.lookup(param) + else: + ret += output_value(param) + return ret + ")" + + +function_map = { + 'Fn::Base64': ("Base64", handle_no_objects), + 'Fn::FindInMap': ("FindInMap", handle_no_objects), + 'Fn::GetAtt': ("GetAtt", handle_no_objects), + 'Fn::GetAZs': ("GetAZs", handle_no_objects), + 'Fn::Join': ("Join", handle_no_objects), + 'Fn::Select': ("Select", handle_one_object), + 'Ref': ("Ref", handle_no_objects), +} + + +def output_value(v): + """Output a value which may be a string or a set of function calls.""" + if isinstance(v, basestring): + return '"%s"' % (v.replace('\\', '\\\\').replace('\n', '\\n').replace("\"", "\\\"")) + elif isinstance(v, bool): + return '%s' % (str(v)) + elif isinstance(v, int): + return '%d' % (v) + elif isinstance(v, list): + return "[" + ", ".join(map(output_value, v)) + "]" + + out = [] + # Should only be one of these... + for fk, fv in v.items(): + if fk in function_map: + (shortname, handler) = function_map[fk] + if not isinstance(fv, list): + fv = [fv] + return handler(shortname, fv) + else: + for x in fv: + if isinstance(x, dict) and 'Ref' in x: + x['Ref'] = '"' + x['Ref'] + '"' + out.append( '"' + fk + '": ' + output_value(fv)) + return "{ " + ", ".join(out) + " }" + + +def do_outputs(d): + global currentNode + """Output the template Outputs""" + outputs = d['Outputs'] + for k, v in outputs.items(): + currentNode = addToNode(currentNode, '%s = t.add_output(Output(' % (k,)) + currentNode = addToNode(currentNode, ' "%s",' % (k, )) + for pk, pv in v.items(): + if isinstance(pv, basestring): + currentNode = addToNode(currentNode, ' %s="%s",' % (pk, pv)) + else: + currentNode = addToNode(currentNode, ' %s=%s,' % (pk, output_value(pv))) + currentNode = addToNode(currentNode, "))") + + +def do_trailer(d): + """Output a trailer section for the new Python script.""" + print 'print(t.to_json())' + +def createTroposphereClasses(region, dictionary): + troposphereClassCreator = TroposphereClassCreator(region, dictionary) + troposphereClassCreator.makeClasses() + + +if __name__ == "__main__": + parser = argparse.ArgumentParser() + parser.add_argument("filename", help="template to convert") + parser.add_argument("createfiles", nargs="?", help="save files to region", default="") + args = parser.parse_args() + + d = json.load(open(args.filename)) + + do_header(d) + + sections = [ + 'AWSTemplateFormatVersion', + 'Description', + 'Parameters', + 'Mappings', + 'Resources', + 'Outputs', + ] + + for s in sections: + if s in d.keys(): + globals()["do_" + s.lower()](d) + + if len(args.createfiles) > 0: + region = raw_input('Please enter the region to save Python classes to: ') + if len(region) > 0: + createTroposphereClasses(region, allNodes) + else: + print "please enter a valid region name" + exit(2) + else: + print imports + print header + for resources in allNodes: + for resource in allNodes[resources]: + for x in allNodes[resources][resource]: + print x + do_trailer(d) diff --git a/scripts/templates/base b/scripts/templates/base new file mode 100644 index 000000000..06db8873e --- /dev/null +++ b/scripts/templates/base @@ -0,0 +1,65 @@ +#!/usr/bin/env python + +from troposphere import Base64, Select, FindInMap, GetAtt, GetAZs, Join, Output +from troposphere import Parameter, Ref, Tags, Template +from troposphere.cloudformation import Init +from troposphere.cloudfront import Distribution, DistributionConfig +from troposphere.cloudfront import Origin, DefaultCacheBehavior +from troposphere.ec2 import PortRange +from troposphere.ec2 import SecurityGroupIngress +from troposphere.ec2 import NetworkInterface +from troposphere.s3 import Bucket, WebsiteConfiguration +from troposphere.ec2 import SecurityGroup +from troposphere.ec2 import Subnet +from troposphere.route53 import RecordSetGroup +from troposphere.sns import TopicPolicy +from troposphere.sns import Topic, Subscription +from troposphere.ec2 import SubnetRouteTableAssociation +from troposphere.ec2 import Instance, NetworkInterfaceProperty, PrivateIpAddressSpecification +from troposphere.ec2 import EIP +from troposphere.ec2 import VPC +from troposphere.sqs import Queue, RedrivePolicy +from troposphere.s3 import BucketPolicy +from troposphere.ec2 import SubnetNetworkAclAssociation +from troposphere.ec2 import SecurityGroupEgress +from troposphere.ec2 import Volume +from troposphere.rds import DBSubnetGroup +from troposphere.route53 import HostedZone +from troposphere.ec2 import EIPAssociation +from troposphere.sqs import QueuePolicy +from troposphere.ec2 import NetworkInterfaceAttachment +from troposphere.ec2 import VPCPeeringConnection +from troposphere.ec2 import InternetGateway +from troposphere.ec2 import Route +from troposphere.ec2 import DHCPOptions +from troposphere.ec2 import RouteTable +from troposphere.elasticache import SubnetGroup +from troposphere.elasticache import CacheCluster +from troposphere.autoscaling import AutoScalingGroup +from troposphere.ec2 import VPCGatewayAttachment +from troposphere.ec2 import VPCDHCPOptionsAssociation +from troposphere.autoscaling import LaunchConfiguration +from troposphere.ec2 import NetworkAcl +from troposphere.ec2 import VPNGateway +from troposphere.rds import DBInstance +from troposphere.ec2 import NetworkAclEntry +from ...BaseObject import BaseObject +{{ imports }} + + +class {{ class_name }}(BaseObject): + + def __init__(self): + + {{ extra_params }} + + self.instance_type = {{ instance_type }}( + {%- for property in properties %} + {{ property }} + {%- endfor %} + ) + + def addToTemplate(self, t): + {{ template_method }}(self.instance_type) + return t + diff --git a/scripts/templates/egressParent b/scripts/templates/egressParent new file mode 100644 index 000000000..10b91fdb9 --- /dev/null +++ b/scripts/templates/egressParent @@ -0,0 +1,14 @@ +#!/usr/bin/env python + + +class SecurityGroupEgress(): + + def __init__(self): + self.ruleList = [] + + def addRule(self, ipProtocol="", cidrIp=""): + ruleDictionary = {"IpProtocol" : ipProtocol, "CidrIp" : cidrIp} + self.ruleList.append(ruleDictionary) + + def toList(self): + return self.ruleList diff --git a/scripts/templates/ingressParent b/scripts/templates/ingressParent new file mode 100644 index 000000000..c485600da --- /dev/null +++ b/scripts/templates/ingressParent @@ -0,0 +1,14 @@ +#!/usr/bin/env python + + +class SecurityGroupIngress(): + + def __init__(self): + self.ruleList = [] + + def addRule(self, ipProtocol="", fromPort="", toPort="", cidrIp=""): + ruleDictionary = {"IpProtocol" : ipProtocol, "FromPort" : fromPort, "ToPort" : toPort, "CidrIp" : cidrIp} + self.ruleList.append(ruleDictionary) + + def toList(self): + return self.ruleList diff --git a/scripts/templates/securityGroup b/scripts/templates/securityGroup new file mode 100644 index 000000000..2d559fb6d --- /dev/null +++ b/scripts/templates/securityGroup @@ -0,0 +1,34 @@ +#!/usr/bin/env python + +from troposphere import * +from troposphere.ec2 import * +from SecurityGroupIngress import SecurityGroupIngress +from SecurityGroupEgress import SecurityGroupEgress +{{ imports }} + + +class {{ class_name }}(): + + def __init__(self): + + securityGroupIngress = SecurityGroupIngress() + {%- for rule in ingress_rules %} + {{ rule }} + {%- endfor %} + + securityGroupEgress = SecurityGroupEgress() + {%- for rule in egress_rules %} + {{ rule }} + {%- endfor %} + + self.instance_type = {{ instance_type }}( + {%- for property in properties %} + {{ property }} + {%- endfor %} + SecurityGroupIngress=securityGroupIngress.toList(), + SecurityGroupEgress=securityGroupEgress.toList() + ) + + def addToTemplate(self, t): + {{ template_method }}(self.instance_type) + return t