When using the ${output stack::output} lookup, Stacker automatically generates a dependency for the current stack on the referenced stack. This behaviour works as expected. However, this behaviour changes when using nested lookups.
Steps to reproduce:
Use this blueprint as s3.py:
from stacker.blueprints.base import Blueprint
from troposphere import s3, Output
class Buckets(Blueprint):
"""
Create a bucket with the given name, and output that name again.
"""
VARIABLES = {
"Bucket": {
"type": object,
"description": "S3 buckets to create"
}
}
def create_template(self):
t = self.template
variables = self.get_variables()
t.add_resource(s3.Bucket(
"Bucket",
BucketName=variables["Bucket"]
))
t.add_output(Output(
"BucketName",
Value=variables["Bucket"],
))
with this config:
stacks:
- name: source
class_path: s3.Buckets
variables:
Bucket: unique-bucket-name
- name: dest
class_path: s3.Buckets
variables:
# Bucket: ${output source::name} # this works as expected
Bucket: ${output source::${default whatever::name}}
Note that, when creating from scratch, the dependency is not created. Hence the dest stack is created in parallel with the source stack, but fails to resolve the lookup:
[2018-09-26T10:47:28] Couldn't resolve lookup in variable `Bucket`, lookup: ${output source::name}: (<class 'TypeError'>) 'NoneType' object is not subscriptable
Traceback (most recent call last):
File "<omitted>/stacker/lookups/registry.py", line 76, in resolve_lookups
provider=provider,
File "<omitted>/stacker/lookups/handlers/output.py", line 29, in handler
return stack.outputs[d.output_name]
TypeError: 'NoneType' object is not subscriptable
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "<omitted>/stacker/stacker/plan.py", line 93, in _run_once
status = self.fn(self.stack, status=self.status)
File "<omitted>/stacker/stacker/actions/build.py", line 321, in _launch_stack
stack.resolve(self.context, self.provider)
File "<omitted>/stacker/stacker/stack.py", line 200, in resolve
resolve_variables(self.variables, context, provider)
File "<omitted>/stacker/stacker/variables.py", line 80, in resolve_variables
variable.resolve(context, provider)
File "<omitted>/stacker/stacker/variables.py", line 145, in resolve
resolved_lookups = resolve_lookups(self, context, provider)
File "<omitted>/stacker/stacker/lookups/registry.py", line 79, in resolve_lookups
raise FailedVariableLookup(variable.name, lookup, e)
stacker.exceptions.FailedVariableLookup: Couldn't resolve lookup in variable `Bucket`, lookup: ${output source::name}: (<class 'TypeError'>) 'NoneType' object is not subscriptable
[2018-09-26T10:47:28] dest: failed (Couldn't resolve lookup in variable `Bucket`, lookup: ${output source::name}: (<class 'TypeError'>) 'NoneType' object is not subscriptable)
[2018-09-26T10:47:28] source: submitted (creating new stack)
When using the
${output stack::output}
lookup, Stacker automatically generates a dependency for the current stack on the referenced stack. This behaviour works as expected. However, this behaviour changes when using nested lookups.Steps to reproduce:
Use this blueprint as
s3.py
:with this config:
Note that, when creating from scratch, the dependency is not created. Hence the
dest
stack is created in parallel with thesource
stack, but fails to resolve the lookup: