aws / aws-cdk

The AWS Cloud Development Kit is a framework for defining cloud infrastructure in code
https://aws.amazon.com/cdk
Apache License 2.0
11.65k stars 3.91k forks source link

(golang) awscdk/v2/awsiot: CfnTopicRule_DynamoDBv2ActionProperty empty generated cfn #17902

Closed karl-dau closed 2 years ago

karl-dau commented 2 years ago

What is the problem?

When I construct a TopicRule using CfnTopicRule_DynamoDBv2ActionProperty, then the generated CloudFormation is missing the actual action details.

Reproduction Steps

    ddbV2Action := &awsiot.CfnTopicRule_ActionProperty{
        DynamoDBv2: &awsiot.CfnTopicRule_DynamoDBv2ActionProperty{
            PutItem: awsiot.CfnTopicRule_PutItemInputProperty{
                TableName: table.TableName(),
            },
            RoleArn: iotRole.RoleArn(),
        },
    }

    ruleprops := &awsiot.CfnTopicRuleProps{
        TopicRulePayload: awsiot.CfnTopicRule_TopicRulePayloadProperty{
            Actions:          &[]*awsiot.CfnTopicRule_ActionProperty{ddbV2Action},
            AwsIotSqlVersion: aws.String("2016-03-23"),
            Sql:              aws.String(sqlStatement),
        },
    }

    awsiot.NewCfnTopicRule(stack, aws.String("ExampleRule"), ruleprops)

What did you expect to happen?

I expected the Output to look like this:

  Type: AWS::IoT::TopicRule
    Properties:
      TopicRulePayload:
        Actions:
          - DynamoDBv2:
              PutItem:
                TableName:
                  Ref: <table name redacted>
              RoleArn:
                Fn::GetAtt:
                  - IoTtoDynamoDBRole47C5C8A5
                  - Arn
        AwsIotSqlVersion: "2016-03-23"
        Sql: <sql redacted>

What actually happened?

I only see this:

  Type: AWS::IoT::TopicRule
    Properties:
      TopicRulePayload:
        Actions:
          - DynamoDBv2: {}
        AwsIotSqlVersion: "2016-03-23"
        RuleDisabled: false
        Sql: <sql redacted>

CDK CLI Version

2.0.0 (build 4b6ce31)

Framework Version

No response

Node.js Version

v17.2.0.

OS

macOS Monteray

Language

Go

Language Version

Go 1.17.3

Other information

A workaround:

ddbV2Action := &awsiot.CfnTopicRule_ActionProperty{
        DynamoDBv2: &awsiot.CfnTopicRule_DynamoDBv2ActionProperty{
            PutItem: awsiot.CfnTopicRule_PutItemInputProperty{
                TableName: table.TableName(),
            },
            RoleArn: iotRole.RoleArn(),
        },
    }

    ruleprops := &awsiot.CfnTopicRuleProps{
        TopicRulePayload: awsiot.CfnTopicRule_TopicRulePayloadProperty{
            Actions:          &[]*awsiot.CfnTopicRule_ActionProperty{ddbV2Action},
            AwsIotSqlVersion: aws.String("2016-03-23"),
            Sql:              aws.String(SqlString),
        },
    }

    bytes, err := json.MarshalIndent(ruleprops, "", "    ")
    if err != nil {
        panic(err)
    }

    correctProps := &awsiot.CfnTopicRuleProps{}
    err = json.Unmarshal(bytes, correctProps)
    if err != nil {
        panic(err)
    }

    awsiot.NewCfnTopicRule(stack, aws.String("EampleRule"), correctProps)
karl-dau commented 2 years ago

I downgraded node to v16.13.1, same problem.

skinny85 commented 2 years ago

Hey @karl-dau,

thanks for opening the issue.

I'm not sure if the problem is not in your JSON marshal/unmarshal code. Can you try removing that part, and see if that works?

Thanks, Adam

skinny85 commented 2 years ago

BTW, we also have Layer 2 IoT TopicRule resources 🙂.

karl-dau commented 2 years ago

Hey @karl-dau,

thanks for opening the issue.

I'm not sure if the problem is not in your JSON marshal/unmarshal code. Can you try removing that part, and see if that works?

Thanks,

Adam

Hi

The JSON marshal/Unmarshal is what makes it work.

For some reason the CFN code generation for that action is not working or I am missing something.

skinny85 commented 2 years ago

Sorry. Can you show the code without the marshal/unmarshal part, and how it fails?

skinny85 commented 2 years ago

Oh, I see - you edited your description to include the original code (I missed that in the original notification).

karl-dau commented 2 years ago

Oh, I see - you edited your description to include the original code (I missed that in the original notification).

Hi

Yes, everything should be there. The action seems to be generating

- DynamoDBv2: {}

instead of

- DynamoDBv2:
              PutItem:
                TableName:
                  Ref: <table name redacted>
              RoleArn:
                Fn::GetAtt:
                  - IoTtoDynamoDBRole47C5C8A5
                  - Arn```

The JSON marshal/unmarshal trick works because the struct tags match.

skinny85 commented 2 years ago

Hey @karl-dau,

can you show me the Go module declaration and import you are using?

Thanks, Adam

skinny85 commented 2 years ago

OK, I figured it out. The mistake was that you made the array of CfnTopicRule_ActionProperty an array of pointers, but it's in fact an array of values.

This works for me:

    awsiot.NewCfnTopicRule(stack, jsii.String("ExampleRule"), &awsiot.CfnTopicRuleProps{
        TopicRulePayload: awsiot.CfnTopicRule_TopicRulePayloadProperty{
            Sql:              jsii.String("SELECT topic(2) as device_id, temperature FROM 'device/+/data'"),
            AwsIotSqlVersion: jsii.String("2016-03-23"),
            Actions: &[]awsiot.CfnTopicRule_ActionProperty{
                awsiot.CfnTopicRule_ActionProperty{
                    DynamoDBv2: &awsiot.CfnTopicRule_DynamoDBv2ActionProperty{
                        PutItem: &awsiot.CfnTopicRule_PutItemInputProperty{
                            TableName: jsii.String("mytable"),
                        },
                        RoleArn: jsii.String("my-role-arn"),
                    },
                },
            },
        },
    })
skinny85 commented 2 years ago

I'm resolving this one, please comment if you need anything else from our side.

github-actions[bot] commented 2 years ago

⚠️COMMENT VISIBILITY WARNING⚠️

Comments on closed issues are hard for our team to see. If you need more assistance, please either tag a team member or open a new issue that references this one. If you wish to keep having a conversation with other community members under this issue feel free to do so.

karl-dau commented 2 years ago

@skinny85 Thanks! that was it!

I got confused with optionals being pointer types and building up those structs with values and not pointers. The JSON marshal/unmarshal trick works because the reflection code dereferences those pointers. I guess everything taking interface{} also did not help.

skinny85 commented 2 years ago

BTW, we now have Layer 2 IoT constructs: https://docs.aws.amazon.com/cdk/api/latest/docs/aws-iot-readme.html, you might want to check them out!