Skip to content

Instantly share code, notes, and snippets.

@tomassedovic
Created September 8, 2014 13:06
Show Gist options
  • Save tomassedovic/6e7f18021f83b87b9f9c to your computer and use it in GitHub Desktop.
Save tomassedovic/6e7f18021f83b87b9f9c to your computer and use it in GitHub Desktop.
'''
USAGE: python import.py path/to/overcloud.yaml
Load the overcloud.yaml and figure out the top-level resources (i.e. ones that
don't represent a role).
Figure out which parameters these top-level resources use.
Build a mapping of property -> value for each non-trivial property in
the role (i.e. one that can't be generated by Tuskar as {get_param: XYZ}).
This could be wrapped up in a function within Tuskar. We would
(optionally) run it during the initialisation phase. Our load-roles
script would use the "overcloud.yaml" as well. It would be introspected
by this code.
Tuskar would then be able to add the necessary parameters, resources,
outputs and set the right properties for each role when generating the plan.
Assumptions:
* The users aren't able to add new roles after the initial upload
* The Role resources in the input template are either ResourceGroup or AutoScalingGroup
and the inner resource's type has the "OS::TripleO::" prefix
* The Role resources generated by Tuskar have identical names to the ones in the
input template (if not, the top-level resources would have to be updated, too)
'''
import sys
import yaml
parsed_plan_structure = yaml.safe_load(open(sys.argv[1]))
STANDALONE_PARAMETERS = set()
ROLES = set()
STANDALONE_RESOURCES = set()
OUTPUTS = set(parsed_plan_structure.get('outputs', {}).keys())
# Mapping from a role's property (input) to a call involving a top-level
# resource or parameter:
INPUT_MAP = {}
def is_resource(resource):
return 'type' in resource and 'properties' in resource
def is_role(resource):
scaling_groups = ('OS::Heat::ResourceGroup', 'OS::Heat::AutoScalingGroup')
if is_resource(resource) and resource['type'] in scaling_groups:
inner = role_inner_resource(resource)
return 'OS::TripleO::' in inner['type']
else:
return False
def role_inner_resource(role):
properties = role.get('properties', {})
inner = properties.get('resource_def', {}) or properties.get('resource', {})
assert is_resource(inner)
return inner
def get_all_params_from_resource(resource):
params = []
if not hasattr(resource, 'items'):
return params
for k, v in resource.items():
if k == 'get_param':
params.append(v)
else:
params.extend(get_all_params_from_resource(v))
return params
# Sort resources to "role" / "standalone resource" buckets
for name, resource in parsed_plan_structure.get('resources', {}).items():
assert is_resource(resource)
if is_role(resource):
ROLES.add(name)
else:
STANDALONE_RESOURCES.add(name)
# No resource should be both a role and standalone
assert len(ROLES.intersection(STANDALONE_RESOURCES)) == 0
# Pick out the top-level parameters (i.e. ones not connected to any role)
for name in STANDALONE_RESOURCES:
resource = parsed_plan_structure['resources'][name]
params = get_all_params_from_resource(resource)
STANDALONE_PARAMETERS.update(params)
# Generate the property map for each role
for role_name in ROLES:
role = parsed_plan_structure['resources'][role_name]
role_input_map = {}
inner_props = role_inner_resource(role).get('properties', {})
for prop, value in inner_props.items():
# value is {'get_param': a_role_specific_parameter}
if hasattr(value, 'get'):
param = value.get('get_param')
if (param and param not in STANDALONE_PARAMETERS):
continue # this will be generated by Tuskar
# value is more complex than {'get_param'} or refers a top-level parameter
# Tuskar has no way of knowing how to generate this so we just store the value
role_input_map[prop] = value
INPUT_MAP[role_name] = role_input_map
print "Top-level parameters:\n\t", '\n\t'.join(STANDALONE_PARAMETERS)
print "\nRoles:\n\t", '\n\t'.join(ROLES)
print "\nTop-level resources:\n\t", '\n\t'.join(STANDALONE_RESOURCES)
print "\nOutputs:\n\t", '\n\t'.join(OUTPUTS)
for role, mappings in INPUT_MAP.items():
print "\nInput map for role %s:" % role
for key, value in mappings.items():
print "\t%s -> %s" % (key, value)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment