Skip to content

Commit ee1eee2

Browse files
author
sbraverman
committed
WIP cfn2py enhanced with cfn2pyclass. Creates tree structure of python classes for manageable json creation
1 parent 0ad9496 commit ee1eee2

8 files changed

Lines changed: 758 additions & 1 deletion

File tree

scripts/TroposphereClassCreator.py

Lines changed: 222 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,222 @@
1+
#!/usr/bin/env python
2+
3+
from jinja2 import Environment, FileSystemLoader
4+
import os
5+
import re
6+
7+
8+
class TroposphereClassCreator(object):
9+
"""
10+
Creates python classes for AWS instances in an easy to use tree structure
11+
"""
12+
13+
def __init__(self, baseDirectory, instances):
14+
self.baseDirectory = baseDirectory
15+
self.instances = instances
16+
17+
def makeClasses(self):
18+
hasSecurityGroup = False
19+
for instance in self.instances:
20+
for name in self.instances[instance]:
21+
# Security Groups will be handled later in the process
22+
if self.isSecurityGroupType(name):
23+
hasSecurityGroup = True
24+
continue
25+
for node in self.instances[instance][name]:
26+
baseDir = self.baseDirectory + '/'
27+
nameDir = baseDir + name + '/'
28+
self.makePythonDirectoryIfNecessary(baseDir)
29+
self.makePythonDirectoryIfNecessary(nameDir)
30+
nodeParams = self.getParamsFromNode(name, node)
31+
className = nodeParams['class_name'] + '.py'
32+
output = self.getDataFromTemplate('base', nodeParams)
33+
self.makeFile(nameDir, className, output)
34+
# if security groups exist, handle them now
35+
if hasSecurityGroup:
36+
self.makeSecurityGroups()
37+
38+
def makeSecurityGroups(self):
39+
securityGroups = self.initSecurityGroups()
40+
securityGroups = self.initIngressRules(securityGroups)
41+
securityGroups = self.initEgressRules(securityGroups)
42+
43+
baseDir = self.baseDirectory + '/'
44+
securityGroupDir = baseDir + 'SecurityGroups/'
45+
46+
self.makePythonDirectoryIfNecessary(securityGroupDir)
47+
48+
ingressParent = self.getDataFromTemplate('ingressParent')
49+
ingressFile = 'SecurityGroupIngress.py'
50+
self.makeFile(securityGroupDir, ingressFile, ingressParent)
51+
egressParent = self.getDataFromTemplate('egressParent')
52+
egressFile = 'SecurityGroupEgress.py'
53+
self.makeFile(securityGroupDir, egressFile, egressParent)
54+
55+
for node in self.getAWSInstanceNameContent('ec2', 'SecurityGroup'):
56+
params = self.getParamsFromNode('SecurityGroup', node)
57+
className = params['class_name']
58+
classFile = className + '.py'
59+
params['ingress_rules'] = securityGroups[className]['ingressRules']
60+
params['egress_rules'] = securityGroups[className]['egressRules']
61+
parsedOutput = self.getDataFromTemplate('securityGroup', params)
62+
self.makeFile(securityGroupDir, classFile, parsedOutput)
63+
64+
def initIngressRules(self, securityGroups):
65+
ingressRuleKey = 'ingressRules'
66+
ingressName = 'SecurityGroupIngress'
67+
ingressNodes = self.getAWSInstanceNameContent('ec2', ingressName)
68+
for node in ingressNodes:
69+
allParams = self.getParamList(node)
70+
securityGroupName = self.getValidSecurityGroupName(allParams)
71+
ingressRule = self.getIngressRule(allParams)
72+
ingressRules = securityGroups[securityGroupName][ingressRuleKey]
73+
if ingressRule not in ingressRules:
74+
ingressRules.append(ingressRule)
75+
return securityGroups
76+
77+
def initEgressRules(self, securityGroups):
78+
egressRuleKey = 'egressRules'
79+
egressName = 'SecurityGroupEgress'
80+
egressNodes = self.getAWSInstanceNameContent('ec2', egressName)
81+
for node in egressNodes:
82+
allParams = self.getParamList(node)
83+
securityGroupName = self.getValidSecurityGroupName(allParams)
84+
egressRule = self.getEgressRule(allParams)
85+
egressRules = securityGroups[securityGroupName][egressRuleKey]
86+
if egressRule not in egressRules:
87+
egressRules.append(egressRule)
88+
return securityGroups
89+
90+
def getEgressRule(self, nodeList):
91+
ipProtocol = self.findStringInList('IpProtocol', nodeList)
92+
cidrIP = self.findStringInList('CidrIp', nodeList)
93+
baseString = 'securityGroupEgress.addRule('
94+
endString = ')'
95+
96+
ruleParams = "ipProtocol='{}', cidrIp='{}'".format(ipProtocol, cidrIP)
97+
return baseString + ruleParams + endString
98+
99+
def getValidSecurityGroupName(self, params):
100+
name = self.findStringInList('GroupId', params)
101+
if name == '':
102+
name = self.findStringInList('GroupName', params)
103+
if name == '':
104+
name = self.findStringInList('GroupId', params, '(', ')')
105+
if name == '':
106+
name = self.findStringInList('GroupName', params, '(', ')')
107+
return name
108+
109+
def getIngressRule(self, nodeList):
110+
ipProtocol = self.findStringInList('IpProtocol', nodeList)
111+
fromPort = self.findStringInList('FromPort', nodeList)
112+
toPort = self.findStringInList('ToPort', nodeList)
113+
cidrIP = self.findStringInList('CidrIp', nodeList)
114+
baseString = 'securityGroupIngress.addRule('
115+
endString = ')'
116+
117+
ruleParams = "ipProtocol='{0}', fromPort='{1}', toPort='{2}', " \
118+
"cidrIp='{3}'"
119+
formattedRules = ruleParams.format(
120+
ipProtocol, fromPort, toPort, cidrIP)
121+
return baseString + formattedRules + endString
122+
123+
def findStringInList(self, string, theList,
124+
lowerBound='"', upperBound='"'):
125+
line = ''
126+
for item in theList:
127+
if string in item:
128+
return self.getValueInDelimiter(item.strip(),
129+
lowerBound, upperBound)
130+
return line
131+
132+
def getValueInDelimiter(self, string, lowerBound='"', upperBound='"'):
133+
try:
134+
regEx = r"\{0}(.*)\{1}".format(lowerBound, upperBound)
135+
matchedName = re.search(regEx, string)
136+
return matchedName.group(1)
137+
except:
138+
return ''
139+
140+
def initSecurityGroups(self):
141+
SecurityGroups = {}
142+
awsName = 'SecurityGroup'
143+
securityGroupNodes = self.getAWSInstanceNameContent('ec2', awsName)
144+
for node in securityGroupNodes:
145+
paramList = self.getParamList(node)
146+
name = self.getName(paramList[1])
147+
if name not in SecurityGroups:
148+
SecurityGroups[name] = {'properties': paramList[1:-1],
149+
'ingressRules': [], 'egressRules': []}
150+
return SecurityGroups
151+
152+
def makePythonDirectoryIfNecessary(self, directory):
153+
if not os.path.exists(directory):
154+
os.makedirs(directory)
155+
self.makeInitPythonFile(directory)
156+
157+
def makeInitPythonFile(self, directory):
158+
self.makeFile(directory, '__init__.py')
159+
160+
def makeFile(self, directory, fileName, contents=' '):
161+
with open(directory + fileName, 'w') as newFile:
162+
newFile.write(contents)
163+
164+
def getParamsFromNode(self, instance, node):
165+
paramList = self.getParamList(node)
166+
method = self.getMethod(paramList[0])
167+
name = self.getName(paramList[1])
168+
properties = paramList[1:-1]
169+
return {'template_method': method, 'instance_type': instance,
170+
'class_name': name, 'properties': properties}
171+
172+
def getParamList(self, node):
173+
return node.strip().split('\n')
174+
175+
def getProperties(self, paramList):
176+
return '\n'.join(paramList)
177+
178+
def getName(self, secondLineOfNode):
179+
return secondLineOfNode.split(',')[0].strip()[1:-1]
180+
181+
def getMethod(self, firstLineOfNode):
182+
methodLine = firstLineOfNode.split('=')[1].strip()
183+
return methodLine.split('(')[0]
184+
185+
def isSecurityGroupType(self, name):
186+
securityName = 'SecurityGroup'
187+
ingressName = 'SecurityGroupIngress'
188+
egressName = 'SecurityGroupEgress'
189+
securityGroupTypes = [securityName, ingressName, egressName]
190+
return name in securityGroupTypes
191+
192+
def getDataFromTemplate(self, fileName, dictionary={}):
193+
env = Environment(loader=FileSystemLoader('templates'))
194+
template = env.get_template(fileName)
195+
return template.render(dictionary)
196+
197+
def getAWSInstances(self):
198+
return self.instances
199+
200+
def getAWSInstanceNames(self, awsInstance):
201+
try:
202+
return self.dictionary[awsInstance]
203+
except:
204+
print 'Failed to get: {0}'.format(awsInstance)
205+
206+
def printAWSInstances(self):
207+
for x in self.instances:
208+
print x
209+
210+
def printAWSInstanceNames(self, instance):
211+
for x in self.instances[instance]:
212+
print x
213+
214+
def printAWSInstanceNameContent(self, instance, name):
215+
for x in self.instances[instance][name]:
216+
print x
217+
218+
def getAWSInstanceNameContent(self, instance, name):
219+
try:
220+
return self.instances[instance][name]
221+
except:
222+
print 'Failed to get: {0}/{1}'.format(instance, name)

0 commit comments

Comments
 (0)