Closed
Description
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
Labels
No labels