Skip to content

Commit

Permalink
Merge pull request #20 from remind101/use_existing_params
Browse files Browse the repository at this point in the history
Use existing params
  • Loading branch information
phobologic committed Mar 31, 2015
2 parents 68e72b9 + 53de657 commit 4ea541d
Show file tree
Hide file tree
Showing 2 changed files with 44 additions and 16 deletions.
19 changes: 10 additions & 9 deletions stacker/blueprints/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,15 +31,16 @@ def __init__(self, name, context, mappings=None):

@property
def parameters(self):
params = []
for param in self.template.parameters:
try:
params.append((param, self.context.parameters[param]))
except KeyError:
logger.debug("Parameter '%s' not found in context, skipping.",
param)
continue
return params
return self.template.parameters

@property
def required_parameters(self):
""" Returns all parameters that do not have a default value. """
required = []
for k, v in self.parameters.items():
if not hasattr(v, 'Default'):
required.append((k, v))
return required

def setup_parameters(self):
t = self.template
Expand Down
41 changes: 34 additions & 7 deletions stacker/builder.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,17 @@
COMPLETE_STATUSES)


class MissingParameterException(Exception):
def __init__(self, blueprint, parameters):
self.blueprint = blueprint
self.parameter = parameters
self.message = "Blueprint %s missing required parameters: %s" % (
blueprint, ', '.join(parameters))

def __str__(self):
return self.message


class Builder(object):
""" Responsible for building & coordinating CloudFormation stacks.
Expand Down Expand Up @@ -144,17 +155,18 @@ def build_blueprint(self, stack_context):
self.plan[stack_name].blueprint = blueprint
return blueprint

def resolve_parameters(self, parameters, blueprint):
def resolve_parameters(self, parameters, blueprint, existing_stack=None):
""" Resolves parameters for a given blueprint.
Given a list of parameters, first discard any parameters that the
blueprint does not use. Then, if a remaining parameter is in the format
<stack_name>::<output_name>, pull that output from the foreign
stack.
"""
params = []
params = {}
blueprint_params = blueprint.parameters
for k, v in parameters.items():
if k not in blueprint.template.parameters:
if k not in blueprint_params:
logger.debug("Template %s does not use parameter %s.",
blueprint.name, k)
continue
Expand All @@ -164,8 +176,23 @@ def resolve_parameters(self, parameters, blueprint):
stack_name, output = value.split('::')
self.get_outputs(stack_name)
value = self.outputs[stack_name][output]
params.append((k, value))
return params
params[k] = value
# Deal w/ missing parameters
required_params = [k for k, v in blueprint.required_parameters]
missing_params = list(set(required_params) - set(params.keys()))
if existing_stack:
stack_params = {p.key: p.value for p in existing_stack.parameters}
for p in missing_params:
if p in stack_params:
value = stack_params[p]
logger.debug("Using parameter %s from existing stack: %s",
p, value)
params[p] = value
final_missing = list(set(required_params) - set(params.keys()))
if final_missing:
raise MissingParameterException(blueprint.name, final_missing)

return params.items()

def get_stack(self, stack_full_name):
""" Give a stacks full name, query for the boto Stack object.
Expand Down Expand Up @@ -232,7 +259,7 @@ def launch_stack(self, stack_name, blueprint):
template_url = self.s3_stack_push(blueprint)
tags = self.build_stack_tags(stack_context, template_url)
parameters = self.resolve_parameters(stack_context.parameters,
blueprint)
blueprint, stack)
submitted = False
if not stack:
submitted = self.create_stack(full_name, template_url, parameters,
Expand All @@ -249,9 +276,9 @@ def get_outputs(self, stack_name, force=False):
Updates the local output cache with the values it finds.
"""
logger.debug("Getting outputs from stack %s.", stack_name)
if stack_name in self.outputs and not force:
return
logger.debug("Getting outputs from stack %s.", stack_name)

full_name = self.get_stack_full_name(stack_name)
stack = self.conn.cloudformation.describe_stacks(full_name)[0]
Expand Down

0 comments on commit 4ea541d

Please sign in to comment.