org-formation / org-formation-cli

Better than landingzones!
MIT License
1.41k stars 131 forks source link

Feature: support functions in TemplatingContext parameters #259

Open zaro0508 opened 3 years ago

zaro0508 commented 3 years ago

Subject of the issue

OFN function references (!Ref, !Sub, !CopyValue, etc..) do no work with TemplatingContext parameters. References always resolve to object Object

Your environment

Steps to reproduce

noop.njk:

Description: noop template
AWSTemplateFormatVersion: 2010-09-09
Resources:
  {{ my_test_var }}:
    Type: AWS::CloudFormation::WaitConditionHandle

_tasks.yaml:

NoOp:
  Type: update-stacks
  Template: ./noop.njk
  StackName: noop
  TemplatingContext:
    my_test_var: !Ref MasterAccount
  DefaultOrganizationBinding:
    Account: !Ref MasterAccount
    Region: !Ref primaryRegion

run ofn print-tasks _tasks.yaml --output yaml

my out put in .printed-stacks/noop/us-east-1-master-account.yaml:

AWSTemplateFormatVersion: '2010-09-09'
Description: noop template
Parameters: {}
Resources:
  object Object:
    Type: AWS::CloudFormation::WaitConditionHandle
Outputs: {}

Expected behaviour

The resource ID/name should be set to the master account ID, something like this..

Resources:
  987264522347:
    Type: AWS::CloudFormation::WaitConditionHandle

Actual behaviour

The resource ID/name is set to object Object. Anywhere a reference (!Ref, !Sub, !CopyValue, etc..) is used it resolves to object Object.

OlafConijn commented 2 years ago

what happen with these expressions is that they do not resolve before getting added to the templating context, but they are copied over as expressions.

MyAccount: {{ MasterAccount }} will resolve to MyAccount: [object object] MyAccount: {{ MasterAccount | object }} will resolve to to MyAccount: {Ref: MasterAccount}

there is a number of examples here.

the reason for this is that some expressions (e.g. CurrentAccount) cannot be resolved at "templating time", they need to be resolved at deployment time and might have a different value for each target.

Parameters do get evaluated before passed to the templating context. What you might be able to do to is have the expression evaluate early when assigned to a parameter, then pass the parameter to the templating context.

maybe a solution would be to add an Eval function? eagerly eval most expressions? but I would be interested to understand the usecase better before adding such function

zaro0508 commented 2 years ago

The use case for me is when I want to pass TemplatingContext variables to nunjuks templates and I want to use any of the !Ref, !Sub, !CopyValue, etc.. on those variables.

Examples:

Mappings:
  TgwSpokesA:
    VpcName:
      '111111111111': 'dustbunnyvpc'
      '222222222222': 'sandcastlevpc'  

TestStack:
  Type: update-stacks
  Template: test.yaml
  StackName: test
  TemplatingContext:
    MasterAccount: !Ref MasterAccount
    VpcId: !CopyValue [!Sub '${resourcePrefix}-tgw-${vpnVpc}-VpcId']
    SubnetIds:
      - !CopyValue [!Join ["-", [!Ref primaryRegion, !FindInMap [TgwSpokesA, VpcName, !Ref CurrentAccount], 'PrivateSubnet']]]
      - !CopyValue [!Join ["-", [!Ref primaryRegion, !FindInMap [TgwSpokesA, VpcName, !Ref CurrentAccount], 'PrivateSubnet1']]]
mhlchirosca commented 1 month ago

I think the following issue might be related to this one mainly because

OFN function references (!Ref, !Sub, !CopyValue, etc..) do no work with TemplatingContext parameters. References always resolve to object Object