aws-ec2: ec2.InitFile.fromObject generates a JSON file with properties converted to string
- Dominant language
- TypeScript
- Stars
- 12.9k
- Forks
- 4.6k
- Avg merge
- 2d 3h
- Merged PRs (30d)
- 83
Description
### Describe the bug
When creating files in an EC2 instance during CloudFormation Init, if using `ec2.InitFile.fromObject()`, than the JSON fields are converted to string. For example, the object
```JSON
{
"integer": 10,
"string": "eleven",
"decimal": 12.12,
"boolean": true,
"array": [1, "two", 3.3, false]
}
```
Is converted to
```JSON
{
"integer": "10",
"string": "eleven",
"decimal": "12.12",
"boolean": "true",
"array": ["1", "two", "3.3", "false"]
}
```
### Expected Behavior
File content generated by `ec2.InitFile.fromObject()` to be similar to:
```{"integer":10,"string":"eleven","decimal":12.12,"boolean":true,"array":[1,"two",3.3,false]}```
### Current Behavior
File content is like:
```{"boolean": "true", "string": "eleven", "integer": "10", "array": ["1", "two", "3.3", "false"], "decimal": "12.12"}```
### Reproduction Steps
In a new CDK project (initialized with `cdk init app --language typescript`):
```
#!/usr/bin/env node
import "source-map-support/register";
import { Construct } from "constructs";
import * as cdk from "aws-cdk-lib";
import * as ec2 from "aws-cdk-lib/aws-ec2";
class InstanceStack extends cdk.Stack {
constructor(scope: Construct, id: string, props?: cdk.StackProps) {
super(scope, id, props);
const vpc = ec2.Vpc.fromLookup(this, "VPC", {
isDefault: true,
});
const jsonFile = {
integer: 10,
string: "eleven",
decimal: 12.12,
boolean: true,
array: [1, "two", 3.3, false],
};
new ec2.Instance(this, "Instance", {
vpc,
instanceType: new ec2.InstanceType("t3.nano"),
machineImage: ec2.MachineImage.latestAmazonLinux2(),
init: ec2.CloudFormationInit.fromElements(
ec2.InitFile.fromObject("/tmp/first.json", jsonFile),
ec2.InitFile.fromString("/tmp/second.json", JSON.stringify(jsonFile))
),
});
}
}
const app = new cdk.App();
new InstanceStack(app, "InstanceStack", {
env: {
account: process.env.CDK_DEFAULT_ACCOUNT,
region: process.env.CDK_DEFAULT_REGION,
},
});
```
### Possible Solution
_No response_
### Additional Information/Context
Here are the files section of the generated template
JSON
```JSON
"files": {
"/var/first.json": {
"content": {
"integer": 10,
"string": "eleven",
"decimal": 12.12,
"boolean": true,
"arary": [1, "two", 3.3, false]
},
"mode": "000644",
"owner": "root",
"group": "root"
},
"/var/second.json": {
"content": "{\"integer\":10,\"string\":\"eleven\",\"decimal\":12.12,\"boolean\":true,\"array\":[1,\"two\",3.3,false]}",
"encoding": "plain",
"mode": "000644",
"owner": "root",
"group": "root"
}
}
```
YAML
```YAML
files:
/var/first.json:
content:
integer: 10
string: eleven
decimal: 12.12
boolean: true
array:
- 1
- two
- 3.3
- false
mode: '000644'
owner: root
group: root
/var/second.json:
content: >-
{"integer":10,"string":"eleven","decimal":12.12,"boolean":true,"array":[1,"two",3.3,false]}
encoding: plain
mode: '000644'
owner: root
group: root
```
And here is the content of `/var/lib/cfn-init/data/metadata.json` in the instance:
```JSON
{
"AWS::CloudFormation::Init": {
"configSets": {
"default": [
"config"
]
},
"config": {
"files": {
"/var/first.json": {
"mode": "000644",
"owner": "root",
"content": {
"boolean": "true",
"string": "eleven",
"array": [
"1",
"two",
"3.3",
"false"
],
"integer": "10",
"decimal": "12.12"
},
"group": "root"
},
"/var/second.json": {
"mode": "000644",
"owner": "root",
"encoding": "plain",
"content": "{\"integer\":10,\"string\":\"eleven\",\"decimal\":12.12,\"boolean\":true,\"array\":[1,\"two\",3.3,false]}",
"group": "root"
}
}
}
},
"aws:cdk:path": "InstanceStack/Instance/Resource"
}
```
### CDK CLI Version
2.117.0
### Framework Version
2.117.0
### Node.js Version
20.2.0
### OS
Windows 11
### Language
TypeScript
### Language Version
5.3.3
### Other information
There is an older issue [here](https://github.com/aws/aws-cdk/issues/14100) for the same issue, but even though it was closed, I can still reproduce the issue in 2.117.0.
Contributor guide
Research direction
Start at ec2.InitFile.fromObject and compare its generated CloudFormation Init metadata with the fromString example in the reproduction. Verify the resulting /var/first.json content preserves numeric, boolean, and array element types, using the issue's expected JSON as the completion criterion.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- aws, typescript
- Domain
- cloud, infrastructure
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 42/100