Skip to content

Commit 7f51832

Browse files
committed
added : buildstack.py : to build cfn stack
modified: create_managed_endpoint.py
1 parent 00e4838 commit 7f51832

File tree

2 files changed

+181
-0
lines changed

2 files changed

+181
-0
lines changed

buildstack.py

Lines changed: 179 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,179 @@
1+
import boto3
2+
import sys
3+
import time
4+
import datetime
5+
import argparse
6+
import re
7+
import urllib3
8+
from botocore.exceptions import ClientError
9+
import os
10+
import json
11+
12+
13+
def buildstack(region):
14+
try:
15+
16+
client = boto3.client('cloudformation',region_name=region)
17+
18+
create_stack_response = client.create_stack(
19+
StackName=stackname,
20+
TemplateBody=templateBody,
21+
NotificationARNs=[],
22+
Capabilities=[
23+
'CAPABILITY_NAMED_IAM',
24+
],
25+
OnFailure='ROLLBACK'
26+
)
27+
28+
stackuuid = create_stack_response['StackId']
29+
# stackuuid = str(uuid.uuid4())
30+
return stackuuid
31+
32+
except ClientError as e:
33+
print("[ERROR]",e)
34+
raise
35+
except Exception as e:
36+
print("[ERROR]", e)
37+
38+
def checkstackstatus(region):
39+
40+
try:
41+
42+
stack_building = True
43+
44+
client = boto3.client('cloudformation',region_name=region)
45+
46+
event_list = client.describe_stack_events(StackName=stackname).get("StackEvents")
47+
stack_event = event_list[0]
48+
49+
if (stack_event.get('ResourceType') == 'AWS::CloudFormation::Stack' and
50+
stack_event.get('ResourceStatus') == 'CREATE_COMPLETE'):
51+
stack_building = False
52+
print("Stack construction completed for region...", region)
53+
elif (stack_event.get('ResourceType') == 'AWS::CloudFormation::Stack' and
54+
stack_event.get('ResourceStatus') == 'ROLLBACK_COMPLETE'):
55+
stack_building = False
56+
print("Stack construction failed for region...", region)
57+
sys.exit(1)
58+
else:
59+
print("Stack creation in progress for region...", region)
60+
61+
return stack_building
62+
63+
except ClientError as e:
64+
print("[ERROR]",e)
65+
raise
66+
except Exception as e:
67+
print("[ERROR]", e)
68+
69+
70+
def main():
71+
# Main routine
72+
73+
74+
try:
75+
76+
parser = argparse.ArgumentParser()
77+
parser.add_argument("-t","--template-body", default='managed-gdb-cft.yml', type=str, help="CloudFormation template file")
78+
parser.add_argument("-r","--region", type=str,help="List of regions seperated by commas, where the stack will be deployed")
79+
parser.add_argument("-s","--stack-name", type=str, help="CloudFormation Stack Name")
80+
parser.add_argument("-a","--agree-anonymous-data-collect", type=str, default='yes',help="Opt in for anonymous one time data collection.(yes/no). Only collects region name, creation time and uuid portion of the stack id (for uniqueness).")
81+
82+
83+
# process arguments
84+
args = parser.parse_args()
85+
86+
#region and stack ids
87+
stack_regions = {}
88+
89+
global stackname
90+
stackname = args.stack_name
91+
92+
http = urllib3.PoolManager()
93+
94+
tepmlatefname = args.template_body
95+
if not (os.path.isfile(tepmlatefname)):
96+
print("invalid filename passed for cloudformation template body. Please check the file name and path.")
97+
exit(1)
98+
99+
#Open and Read the Cloudformation
100+
global templateBody
101+
f = open(tepmlatefname, "r")
102+
templateBody = f.read()
103+
104+
# Get the list of regions
105+
regions = args.region.split(',')
106+
107+
108+
# validate all passed region names for correctness
109+
for region in regions:
110+
111+
regionregex = re.compile(r"^us-[a-z]*-[0-9]{1}")
112+
regionmatch = re.search(regionregex, region)
113+
114+
if not regionmatch:
115+
print ("Please provide a valid region name in region list. For example: us-east-1. Incorrect value", region)
116+
sys.exit(1)
117+
118+
119+
# print (sys.platform)
120+
121+
stack_building = True
122+
regionscount=1
123+
# Build stack for all regions
124+
for region in regions:
125+
126+
stackid = buildstack (region)
127+
stackids = stackid.split('/')
128+
stackid = stackids[2]
129+
stack_regions[stackid] = region
130+
regionscount += 1
131+
buildtime = datetime.datetime.utcnow().isoformat() + 'Z'
132+
print("Started building stackid",stackid,"in Region",region, "at:",buildtime)
133+
payload = {
134+
'stack_uuid': stackid,
135+
'stack_name': stackname,
136+
'stack_region': region,
137+
'event_timestamp': datetime.datetime.utcnow().isoformat() + 'Z'
138+
139+
}
140+
if (args.agree_anonymous_data_collect == 'yes'):
141+
r = http.request('POST', "https://ksacb35t5m.execute-api.us-east-1.amazonaws.com/v1/track", body=json.dumps(payload).encode('utf-8'), headers={'Content-Type': 'application/json'})
142+
print("[INFO]", "Event tracking for UUID:", payload["stack_uuid"])
143+
144+
145+
146+
try_count = 1 #Initialize counter to keep track of regions
147+
148+
while stack_building:
149+
150+
waitcount = 1 #Initialize counter for waiting 10 se
151+
for stack in stack_regions:
152+
153+
stackid = stack
154+
stackregion = stack_regions[stack]
155+
156+
157+
stack_building = checkstackstatus(stackregion)
158+
waitcount += 1
159+
# sleep 5 seconds after looping through allregions, then check all regions again
160+
if waitcount==regionscount:
161+
time.sleep(5)
162+
163+
# Break the loop only if all regions completed building
164+
if not stack_building:
165+
try_count += 1
166+
if try_count==regionscount:
167+
break
168+
else:
169+
stack_building = True
170+
171+
except ClientError as e:
172+
print("[ERROR]",e)
173+
raise
174+
except Exception as e:
175+
print("[ERROR]", e)
176+
177+
178+
if __name__ == "__main__":
179+
main()

create_managed_endpoint.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66
from botocore.exceptions import ClientError
77
import re
88
import sys
9+
import datetime
10+
import time
911

1012
def exists_hz(hzonename):
1113
# Detects if hosted zone exists. returns True if found, False if not found.

0 commit comments

Comments
 (0)