Skip to content

Generated code seems to be wrong when using definitions #114

Closed
@wnkz

Description

@wnkz

TLDR

Generated code in models.py seems to be wrongfully using definition's name as a key instead of the property referencing the definition.


If I try to implement a Tags property defined ike this one Sample: Kinesis Stream Integration

Simplified example, a resource with Tags property defined like this, generates the following documentation and code.

foo-bar-baz.json

{
    "typeName": "FOO::Bar::Baz",
    "definitions": {
        "Tag": {
            "properties": {
                "Key": {
                    "description": "The key name of the tag.",
                    "type": "string"
                },
                "Value": {
                    "description": "The value for the tag.",
                    "type": "string"
                }
            }
        }
    },
    "properties": {
        "Tags": {
            "type": "array",
            "uniqueItems": true,
            "items": {
                "$ref": "#/definitions/Tag"
            },
            "maximum": 50
        }
    }
    ...
}

README.md

# FOO::Bar::Baz

## Properties

#### Tags

An arbitrary set of tags (key-value pairs) for this S3 bucket.

_Required_: No

_Type_: List of <a href="tag.md">Tag</a>

_Update requires_: [No interruption](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/using-cfn-updating-stacks-update-behaviors.html#update-no-interrupt)

tag.md

# FOO::Bar::Baz Tag

## Syntax

To declare this entity in your AWS CloudFormation template, use the following syntax:

### JSON

<pre>
{
    "<a href="#key" title="Key">Key</a>" : <i>String</i>,
    "<a href="#value" title="Value">Value</a>" : <i>String</i>
}
</pre>

### YAML

<pre>
<a href="#key" title="Key">Key</a>: <i>String</i>
<a href="#value" title="Value">Value</a>: <i>String</i>
</pre>

## Properties

#### Key

The key name of the tag.

_Required_: No

_Type_: String

_Update requires_: [No interruption](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/using-cfn-updating-stacks-update-behaviors.html#update-no-interrupt)

#### Value

The value for the tag.

_Required_: No

_Type_: String

_Update requires_: [No interruption](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/using-cfn-updating-stacks-update-behaviors.html#update-no-interrupt)

models.py

@dataclass
class ResourceModel(BaseModel):
    Tags: Optional[Sequence["_Tag"]]

    @classmethod
    def _deserialize(
        cls: Type["_ResourceModel"],
        json_data: Optional[Mapping[str, Any]],
    ) -> Optional["_ResourceModel"]:
        if not json_data:
            return None
        dataclasses = {n: o for n, o in getmembers(sys.modules[__name__]) if isclass(o)}
        recast_object(cls, json_data, dataclasses)
        return cls(
            Tags=deserialize_list(json_data.get("Tag"), Tag),
        )

@dataclass
class Tag(BaseModel):
    Key: Optional[str]
    Value: Optional[str]

    @classmethod
    def _deserialize(
        cls: Type["_Tag"],
        json_data: Optional[Mapping[str, Any]],
    ) -> Optional["_Tag"]:
        if not json_data:
            return None
        return cls(
            Key=json_data.get("Key"),
            Value=json_data.get("Value"),
        )

The problem here is that ResourceModel class tries to fetch Tags from JSON using the Tag key instead of Tags

With the following desiredResourceState

{
    "credentials": {
        "accessKeyId": "",
        "secretAccessKey": "",
        "sessionToken": ""
    },
    "action": "CREATE",
    "request": {
        "clientRequestToken": "4b90a7e4-b790-456b-a937-0cfdfa211dfe",
        "desiredResourceState": {
            "Tags": [
                {
                    "Key": "FOO",
                    "Value": "BAR"
                }
            ]
        },
        "logicalResourceIdentifier": "MyResource"
    },
    "callbackContext": null
}

We end up with a resource model looking like this

ResourceModel(Tags=None)

instead of

ResourceModel(Tags=[Tag(Key='FOO', Value='BAR')])

Because of

Tags=deserialize_list(json_data.get("Tag"), Tag),

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions