aws / aws/aws-cdk

aws-ec2: ec2.InitFile.fromObject generates a JSON file with properties converted to string

Open
#28,561 5 comments 0 reactions 0 assignees View on GitHub
@aws-cdk/aws-ec2 bug documentation effort/medium p2
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

Open the contributing 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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.