Skip to content

Instantly share code, notes, and snippets.

@asalkeld
Created June 28, 2013 03:49
Show Gist options
  • Save asalkeld/5882347 to your computer and use it in GitHub Desktop.
Save asalkeld/5882347 to your computer and use it in GitHub Desktop.
Quick cfn parser using taskflow
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
import argparse
import logging
import os
import sys
import urllib2
import yaml
logging.basicConfig(level=logging.ERROR)
if not os.path.isfile(os.path.join(os.getcwd(), "taskflow", '__init__.py')):
sys.path.insert(0, os.path.join(os.path.abspath(os.getcwd()), os.pardir))
else:
sys.path.insert(0, os.path.abspath(os.getcwd()))
from taskflow.patterns import graph_flow
from taskflow import task
# try:
# python <this script> https://raw.github.com/openstack/heat-templates/master/cfn/AutoScalingMultiAZSample.template
parser = argparse.ArgumentParser(description='Process some integers.')
parser.add_argument('template',
help='url to the template to parse')
args = parser.parse_args()
print(args.template)
template_body = urllib2.urlopen(args.template).read()
t = yaml.safe_load(template_body)
class ActionTask(task.Task):
def __call__(self, context, *args, **kwargs):
stack = context
resource = stack.resources[self.name]
action_l = kwargs['action'].lower()
handle = getattr(resource, '%s' % action_l, None)
if callable(handle):
return handle()
else:
raise AttributeError(_('Resource action %s not found') %
action_l)
class Resource(object):
def __init__(self, name, stack):
self.name = name
self.type = stack.t['Resources'][name]['Type']
self.stack = stack
self.task = ActionTask(self.name)
self.task.provides.add(self.name)
def create(self):
print 'created %s' % self.name
def delete(self):
print 'deleted %s' % self.name
def __str__(self):
return 'Resource: %s' % self.name
def add_tasks(self, flow, creation_order=True):
flow.add(self.task)
self.find_deps(self.stack.t['Resources'][self.name],
creation_order=creation_order)
def find_deps(self, snippet, creation_order=True):
def _add_resource_dep(resource, dep):
if dep.type == 'AWS::CloudWatch::Alarm':
# one workaround...
print 'ignoring: %s -> %s' % (resource.name, dep.name)
return
print '%s -> %s' % (resource.name, dep.name)
resource.task.requires.add(dep.name)
if isinstance(snippet, basestring):
return
elif isinstance(snippet, (list, tuple)):
for l in snippet:
self.find_deps(l)
return
for (k, v) in iter(snippet.items()):
if k in ('DependsOn', 'Ref', 'Fn::GetAtt'):
if k == 'Fn::GetAtt':
v, head = v
if v in self.stack.resources:
if creation_order:
_add_resource_dep(self, self.stack.resources[v])
else:
_add_resource_dep(self.name, self.stack.resources[v])
else:
self.find_deps(v)
class Stack(object):
def __init__(self, name, template):
self.name = name
self.t = template
self.resources = {}
for r in t['Resources']:
self.resources[r] = Resource(r, self)
def create(self):
fl = graph_flow.Flow('%s-%s' % (self.name, 'create'))
for (n, r) in iter(self.resources.items()):
r.add_tasks(fl, creation_order=True)
print(fl)
fl.run(self, action='create')
def delete(self):
fl = graph_flow.Flow('%s-%s' % (self.name, 'delete'))
for (n, r) in iter(self.resources.items()):
r.add_tasks(fl, creation_order=False)
print(fl)
fl.run(self, action='delete')
st = Stack('fruity', t)
st.create()
st.delete()
print 'smell you later'
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment