core: signalResource option in CloudFormationInit.attach() cannot signal WaitConditionHandle
- Dominant language
- TypeScript
- Stars
- 12.9k
- Forks
- 4.6k
- Avg merge
- 2d 3h
- Merged PRs (30d)
- 83
Description
### Describe the bug
If you specify a `WaitConditionHandle` for `signalResource`, it will render the `cfn-signal` command using a syntax that is meant for resource signaling. This leads to an error on the `SignalResource` call.
### Expected Behavior
A successful `SignalResource` to the `WaitConditionHandle`
### Current Behavior
An error. Here's the relevant section from CloudTrail:
```
"errorCode": "ValidationException",
"errorMessage": "Resource MyWaitConditionHandle is of type AWS_CLOUDFORMATION_WAIT_CONDITION_HANDLE_V3 and cannot be signaled"
```
Thus the stack times out and fails.
### Reproduction Steps
1. Create the relevant `WaitCondition`, `WaitConditionHandle`, instance, `CloudFormationInit`, and then call `attach()` and pass in the handle.
```python
my_wait_handle = cfn.CfnWaitConditionHandle(self, "myWaitConditionHandle")
my_wait_condition = cfn.CfnWaitCondition(self, "myWaitCondition",
handle=my_wait_handle.ref,
timeout='1800')
my_init = ec2.CloudFormationInit.from_config_sets(...)
my_instance = ec2.CfnInstance(...)
my_init.attach(my_instance,
instance_role=my_server_role,
platform=ec2.OperatingSystemType.WINDOWS,
user_data=my_user_data,
signal_resource=my_wait_handle)
my_instance.user_data = Fn.base64(my_user_data.render())
```
2. `cdk synth` and you see that the user data was rendered like this:
```json
"UserData": {
"Fn::Base64": {
"Fn::Join": [
"",
[
"# fingerprint: 006d0ff4f5cc554a\ncfn-init.exe -v --region ",
{"Ref": "AWS::Region"},
" --stack ",
{"Ref": "AWS::StackName"},
" --resource myEC2 -c default\ncfn-signal.exe -e $LASTEXITCODE --region ",
{"Ref": "AWS::Region"},
" --stack ",
{"Ref": "AWS::StackName"},
" --resource myWaitConditionHandle\ntype C:\\cfn\\log\\cfn-init.log"
]
]
}
}
```
But it should be rendered like this:
```json
"UserData": {
"Fn::Base64": {
"Fn::Join": [
"",
[
"# fingerprint: 006d0ff4f5cc554a", "\n",
"cfn-init.exe -v --region ", {"Ref": "AWS::Region"},
" --stack ", {"Ref": "AWS::StackName"},
" --resource myEC2 -c default", "\n",
"cfn-signal.exe -e $LASTEXITCODE --region ", {"Ref": "AWS::Region"},
" --stack ", {"Ref": "AWS::StackName"},
{ "Fn::Base64" : { "Ref" : "myWaitConditionHandle" }}, "\n",
"type C:\\cfn\\log\\cfn-init.log"
]
]
}
}
```
### Possible Solution
Add another variable to the `attach()` method, something like `waitConditionHandle,` that can be used as an alternative to (and is mutually exclusive with) `signalResource`.
### Additional Information/Context
I know Cfn docs says to prefer a `CreationPolicy` instead of `WaitConditionHandle`, yet a proper handle is a way to avoid circular dependencies. In my case: a cfn-init depends on an elastic IP to fetch data from an S3 bucket; the EIP depends on an instance, the instance depends on the cfn-signal after cfn-init.
### CDK CLI Version
2.69.0
### Framework Version
_No response_
### Node.js Version
16.19.0
### OS
MacOS Ventura 13.2.1
### Language
Python
### Language Version
Python 3.9.16
### Other information
_No response_
Contributor guide
Research direction
Start at CloudFormationInit.attach() and trace how cfn-signal is rendered when cdk synth processes signalResource. Compare the current resource-signaling output with the expected WaitConditionHandle output shown here. Done means a WaitConditionHandle can be signaled successfully without breaking existing signalResource behavior, with synthesized user data matching the intended form.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- aws, python, typescript
- Domain
- cloud, infrastructure
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 42/100