Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Better support for conditionals inside properties #668

Open
pbudzon opened this issue Feb 21, 2017 · 3 comments
Open

Better support for conditionals inside properties #668

pbudzon opened this issue Feb 21, 2017 · 3 comments

Comments

@pbudzon
Copy link
Contributor

pbudzon commented Feb 21, 2017

Conditionals like IF can be used inside some properties, but because of strict type checking, troposphere does not allow for their use.

For example, the following is a correct template snippet (not a specific use-case I had, just an example):

"InstanceRolePolicy": {
            "Properties": {
                "PolicyDocument": {
                    "Statement": [
                        {
                            "Action": [
                                "logs:PutLogEvents"
                            ],
                            "Effect": "Allow",
                            "Resource": [
                                "arn:aws:logs:*:*:*"
                            ]
                        },
                        {
                            "Fn::If": [
                                "SomeConditionHere",
                                {
                                    "Action": [
                                        "logs:CreateLogStream"
                                    ],
                                    "Effect": "Allow",
                                    "Resource": [
                                        "arn:aws:logs:*:*:*"
                                    ]
                                },
                                {
                                    "Ref": "AWS::NoValue"
                                }
                            ]
                        }
                    ]
                },
                "PolicyName": "test",
                "Roles": [
                    {
                        "Ref": "InstanceRole"
                    }
                ]
            },
            "Type": "AWS::IAM::Policy"
        },

which should have a representation in troposphere as below:

iam.PolicyType(
            "InstanceRolePolicy",
            PolicyName="test",
            PolicyDocument=aws.Policy(
                Statement=[
                    aws.Statement(
                        Effect=aws.Allow,
                        Action=[
                            aws.Action("logs", "PutLogEvents"),
                        ],
                        Resource=["arn:aws:logs:*:*:*"]
                    ),
                    If(
                        "SomeConditionHere",
                        aws.Statement(
                            Effect=aws.Allow,
                            Action=[
                                aws.Action("logs", "CreateLogStream"),
                            ],
                            Resource=["arn:aws:logs:*:*:*"]
                        ),
                        Ref(AWS_NO_VALUE)
                    )
                ]
            ),
)

but it obviously fails with TypeError: Statement is <class 'troposphere.If'>, expected [<class 'awacs.aws.Statement'>]

This specific example is related to awacs, but I imagine the same problems happen directly in troposphere as well, wherever the property is expected to be a specific object.

Should conditionals be allowed by troposphere inside most (all?) properties? Either via something simple to how policytypes are solved in iam or by something more complex which will detect the condition and check for the types inside the condition?

@markpeek
Copy link
Member

Good issue to bring up. In general this should not be an issue with just troposphere. The "If" class is derived from AWSHelperFn and there is specific code in BaseAWSObject::setattr() which allows these AWSHelperFn to be used instead of the normal validation. I think you're seeing an issue due to awacs and troposphere being separate projects (yeah, in hindsight I might have just made them one project). I'd have to look harder at your specific example to see if there is a good workaround.

@pbudzon
Copy link
Contributor Author

pbudzon commented Feb 22, 2017

Thanks! To get the JSON generated I modified the aws.Policy object definition, changed

        'Statement': ([Statement], True),

to

        'Statement': (list, True),

which is obviously not ideal, but got the template I needed.

@noelmccrory
Copy link
Contributor

noelmccrory commented Mar 15, 2018

Another example.

When try to use the TemplateGenerator to read the following CFT which contains the following S3 Bucket resource which has a condition on MetricsConfiguration , an AssertionError occurs:

"AlfrescoS3Bucket" : {
  "Type" : "AWS::S3::Bucket",
  "Properties" : {
    "BucketName" : "test-bucket",
    "MetricsConfigurations" : [ 
      {
        "Fn::If" : [
          "EnableRequestAndDataTransferMetrics", 
          {"Id" : "EntireBucket"},   
          {"Ref" : "AWS::NoValue"}
        ]
      }
    ]
  }
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants