cloudtools / stacker

An AWS CloudFormation Stack orchestrator/manager.
http://stacker.readthedocs.io/en/stable/
BSD 2-Clause "Simplified" License
711 stars 167 forks source link

Lookups on outputs of locked stacks crash stacker #753

Closed mromaszewicz closed 4 years ago

mromaszewicz commented 4 years ago

Here's a trivial stack definition, using default stacker_blueprints

namespace: ${namespace}
stacker_bucket: ${stacker_bucket}
sys_path: ./
stacks:
  - name: TestGroupsLocked
    class_path: stacker_deploy.stacker_blueprints.ec2.SecurityGroups
    enabled: true
    locked: true
    variables:
      SecurityGroups:
        Group1:
          GroupDescription: TestGroup1
        Group2:
          GroupDescription: TestGroup2

  - name: DependsOnLocked
    class_path: stacker_deploy.stacker_blueprints.security_rules.Rules
    enabled: true
    variables:
      IngressRules:
        TestRule1:
          GroupId: ${output TestGroupsLocked::Group1Id}
          FromPort: 5432
          ToPort: 5432
          IpProtocol: tcp
          SourceSecurityGroupId: ${output TestGroupsLocked::Group2Id}

Deploy this, then try to diff it.

$ stacker diff -r us-west-2 conf/marcin.env ./test.yaml
[2020-03-25T14:41:42] Using default AWS provider mode
[2020-03-25T14:41:43] Diffing stacks: TestGroupsLocked, DependsOnLocked
[2020-03-25T14:41:43] TestGroupsLocked: skipped (locked)
[2020-03-25T14:41:43] Couldn't resolve lookup in variable `IngressRules`, lookup: ${Lookup<Literal<'output'> Literal<'TestGroupsLocked::Group1Id'>>}: (<class 'TypeError'>) 'NoneType' object is not subscriptable
Traceback (most recent call last):
  File "/Users/marcinromaszewicz/virtualenv/default3/lib/python3.7/site-packages/stacker/variables.py", line 382, in resolve
    provider=provider
  File "/Users/marcinromaszewicz/virtualenv/default3/lib/python3.7/site-packages/stacker/lookups/handlers/output.py", line 35, in handle
    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 "/Users/marcinromaszewicz/virtualenv/default3/lib/python3.7/site-packages/stacker/variables.py", line 82, in resolve
    self._value.resolve(context, provider)
  File "/Users/marcinromaszewicz/virtualenv/default3/lib/python3.7/site-packages/stacker/variables.py", line 270, in resolve
    item.resolve(context, provider)
  File "/Users/marcinromaszewicz/virtualenv/default3/lib/python3.7/site-packages/stacker/variables.py", line 270, in resolve
    item.resolve(context, provider)
  File "/Users/marcinromaszewicz/virtualenv/default3/lib/python3.7/site-packages/stacker/variables.py", line 392, in resolve
    raise FailedLookup(self, e)
stacker.exceptions.FailedLookup: Failed lookup

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/Users/marcinromaszewicz/virtualenv/default3/lib/python3.7/site-packages/stacker/plan.py", line 93, in _run_once
    status = self.fn(self.stack, status=self.status)
  File "/Users/marcinromaszewicz/virtualenv/default3/lib/python3.7/site-packages/stacker/actions/diff.py", line 172, in _diff_stack
    stack.resolve(self.context, provider)
  File "/Users/marcinromaszewicz/virtualenv/default3/lib/python3.7/site-packages/stacker/stack.py", line 187, in resolve
    resolve_variables(self.variables, context, provider)
  File "/Users/marcinromaszewicz/virtualenv/default3/lib/python3.7/site-packages/stacker/variables.py", line 35, in resolve_variables
    variable.resolve(context, provider)
  File "/Users/marcinromaszewicz/virtualenv/default3/lib/python3.7/site-packages/stacker/variables.py", line 84, in resolve
    raise FailedVariableLookup(self.name, e.lookup, e.error)
stacker.exceptions.FailedVariableLookup: Couldn't resolve lookup in variable `IngressRules`, lookup: ${Lookup<Literal<'output'> Literal<'TestGroupsLocked::Group1Id'>>}: (<class 'TypeError'>) 'NoneType' object is not subscriptable
[2020-03-25T14:41:43] DependsOnLocked: failed (Couldn't resolve lookup in variable `IngressRules`, lookup: ${Lookup<Literal<'output'> Literal<'TestGroupsLocked::Group1Id'>>}: (<class 'TypeError'>) 'NoneType' object is not subscriptable)
[2020-03-25T14:41:43] The following steps failed: DependsOnLocked
deepmap-marcinr commented 4 years ago

Actually, it turns out the stack doesn't even need to be locked. Diff just fails.

ITProKyle commented 4 years ago

I was able to track the cause down to outputs not being added to the stack object when the stack's change set returns no change which was an oversight when I added the feature. opened a PR with the resolution.