Skip to content

Commit

Permalink
feat: optional construct metadata in charts (#721) (#776)
Browse files Browse the repository at this point in the history
* feat: optional construct metadata in charts (#721)

Resolves #688

(cherry picked from commit 4b71d6c)
Signed-off-by: Eli Polonsky <[email protected]>

# Conflicts:
#	test/chart.test.ts

* use Node.of instead of .node

Signed-off-by: iliapolo <[email protected]>

Signed-off-by: iliapolo <[email protected]>
  • Loading branch information
iliapolo authored Sep 28, 2022
1 parent a64aa80 commit 603e2b9
Show file tree
Hide file tree
Showing 7 changed files with 174 additions and 2 deletions.
24 changes: 24 additions & 0 deletions docs/java.md
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,7 @@ import org.cdk8s.App;
App.Builder.create()
// .outdir(java.lang.String)
// .outputFileExtension(java.lang.String)
// .recordConstructMetadata(java.lang.Boolean)
// .yamlOutputType(YamlOutputType)
.build();
```
Expand All @@ -227,6 +228,15 @@ The file extension to use for rendered YAML files.

---

##### `recordConstructMetadata`<sup>Optional</sup> <a name="org.cdk8s.AppProps.parameter.recordConstructMetadata"></a>

- *Type:* `java.lang.Boolean`
- *Default:* false

When set to true, the output directory will contain a `construct-metadata.json` file that holds construct related metadata on every resource in the app.

---

##### `yamlOutputType`<sup>Optional</sup> <a name="org.cdk8s.AppProps.parameter.yamlOutputType"></a>

- *Type:* [`org.cdk8s.YamlOutputType`](#org.cdk8s.YamlOutputType)
Expand Down Expand Up @@ -818,6 +828,7 @@ import org.cdk8s.AppProps;
AppProps.builder()
// .outdir(java.lang.String)
// .outputFileExtension(java.lang.String)
// .recordConstructMetadata(java.lang.Boolean)
// .yamlOutputType(YamlOutputType)
.build();
```
Expand Down Expand Up @@ -848,6 +859,19 @@ The file extension to use for rendered YAML files.

---

##### `recordConstructMetadata`<sup>Optional</sup> <a name="org.cdk8s.AppProps.property.recordConstructMetadata"></a>

```java
public java.lang.Boolean getRecordConstructMetadata();
```

- *Type:* `java.lang.Boolean`
- *Default:* false

When set to true, the output directory will contain a `construct-metadata.json` file that holds construct related metadata on every resource in the app.

---

##### `yamlOutputType`<sup>Optional</sup> <a name="org.cdk8s.AppProps.property.yamlOutputType"></a>

```java
Expand Down
34 changes: 34 additions & 0 deletions docs/python.md
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,7 @@ import cdk8s
cdk8s.App(
outdir: str = None,
output_file_extension: str = None,
record_construct_metadata: bool = None,
yaml_output_type: YamlOutputType = None
)
```
Expand All @@ -235,6 +236,15 @@ The file extension to use for rendered YAML files.

---

##### `record_construct_metadata`<sup>Optional</sup> <a name="cdk8s.AppProps.parameter.record_construct_metadata"></a>

- *Type:* `bool`
- *Default:* false

When set to true, the output directory will contain a `construct-metadata.json` file that holds construct related metadata on every resource in the app.

---

##### `yaml_output_type`<sup>Optional</sup> <a name="cdk8s.AppProps.parameter.yaml_output_type"></a>

- *Type:* [`cdk8s.YamlOutputType`](#cdk8s.YamlOutputType)
Expand Down Expand Up @@ -840,6 +850,7 @@ import cdk8s
cdk8s.AppProps(
outdir: str = None,
output_file_extension: str = None,
record_construct_metadata: bool = None,
yaml_output_type: YamlOutputType = None
)
```
Expand Down Expand Up @@ -870,6 +881,19 @@ The file extension to use for rendered YAML files.

---

##### `record_construct_metadata`<sup>Optional</sup> <a name="cdk8s.AppProps.property.record_construct_metadata"></a>

```python
record_construct_metadata: bool
```

- *Type:* `bool`
- *Default:* false

When set to true, the output directory will contain a `construct-metadata.json` file that holds construct related metadata on every resource in the app.

---

##### `yaml_output_type`<sup>Optional</sup> <a name="cdk8s.AppProps.property.yaml_output_type"></a>

```python
Expand Down Expand Up @@ -2818,6 +2842,7 @@ import cdk8s
cdk8s.Testing.app(
outdir: str = None,
output_file_extension: str = None,
record_construct_metadata: bool = None,
yaml_output_type: YamlOutputType = None
)
```
Expand All @@ -2840,6 +2865,15 @@ The file extension to use for rendered YAML files.

---

###### `record_construct_metadata`<sup>Optional</sup> <a name="cdk8s.AppProps.parameter.record_construct_metadata"></a>

- *Type:* `bool`
- *Default:* false

When set to true, the output directory will contain a `construct-metadata.json` file that holds construct related metadata on every resource in the app.

---

###### `yaml_output_type`<sup>Optional</sup> <a name="cdk8s.AppProps.parameter.yaml_output_type"></a>

- *Type:* [`cdk8s.YamlOutputType`](#cdk8s.YamlOutputType)
Expand Down
13 changes: 13 additions & 0 deletions docs/typescript.md
Original file line number Diff line number Diff line change
Expand Up @@ -717,6 +717,19 @@ The file extension to use for rendered YAML files.

---

##### `recordConstructMetadata`<sup>Optional</sup> <a name="cdk8s.AppProps.property.recordConstructMetadata"></a>

```typescript
public readonly recordConstructMetadata: boolean;
```

- *Type:* `boolean`
- *Default:* false

When set to true, the output directory will contain a `construct-metadata.json` file that holds construct related metadata on every resource in the app.

---

##### `yamlOutputType`<sup>Optional</sup> <a name="cdk8s.AppProps.property.yamlOutputType"></a>

```typescript
Expand Down
1 change: 1 addition & 0 deletions src/api-object.ts
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,7 @@ export class ApiObject extends Construct {
...props.metadata?.labels,
},
});

}

/**
Expand Down
31 changes: 29 additions & 2 deletions src/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,14 @@ export interface AppProps {
* @default YamlOutputType.FILE_PER_CHART
*/
readonly yamlOutputType?: YamlOutputType;

/**
* When set to true, the output directory will contain a `construct-metadata.json` file
* that holds construct related metadata on every resource in the app.
*
* @default false
*/
readonly recordConstructMetadata?: boolean;
}

/**
Expand Down Expand Up @@ -99,6 +107,8 @@ export class App extends Construct {
*/
public readonly yamlOutputType: YamlOutputType;

private readonly recordConstructMetadata: boolean;

/**
* Returns all the charts in this app, sorted topologically.
*/
Expand All @@ -118,6 +128,9 @@ export class App extends Construct {
this.outdir = props.outdir ?? process.env.CDK8S_OUTDIR ?? 'dist';
this.outputFileExtension = props.outputFileExtension ?? '.k8s.yaml';
this.yamlOutputType = props.yamlOutputType ?? YamlOutputType.FILE_PER_CHART;

this.recordConstructMetadata = props.recordConstructMetadata ?? (process.env.CDK8S_RECORD_CONSTRUCT_METADATA === 'true' ? true : false);

}

/**
Expand Down Expand Up @@ -154,11 +167,9 @@ export class App extends Construct {

case YamlOutputType.FILE_PER_CHART:
const namer: ChartNamer = hasDependantCharts ? new IndexedChartNamer() : new SimpleChartNamer();

for (const chart of charts) {
const chartName = namer.name(chart);
const objects = chartToKube(chart);

Yaml.save(path.join(this.outdir, chartName+this.outputFileExtension), objects.map(obj => obj.toJson()));
}
break;
Expand Down Expand Up @@ -199,6 +210,11 @@ export class App extends Construct {
break;
}

if (this.recordConstructMetadata) {
const allObjects = this.charts.flatMap(chartToKube);
this.writeConstructMetadata(allObjects);
}

}

/**
Expand All @@ -219,6 +235,17 @@ export class App extends Construct {

return Yaml.stringify(...docs);
}

private writeConstructMetadata(apiObjects: ApiObject[]) {
const resources: { [key: string]: any } = {};
for (const apiObject of apiObjects) {
resources[apiObject.name] = { path: Node.of(apiObject).path };
}
fs.writeFileSync(path.join(this.outdir, 'construct-metadata.json'), JSON.stringify({
version: '1.0.0',
resources: resources,
}));
}
}

function validate(app: App) {
Expand Down
1 change: 1 addition & 0 deletions src/chart.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ export interface ChartProps {
* @default - no common labels
*/
readonly labels?: { [name: string]: string };

}

export class Chart extends Construct {
Expand Down
72 changes: 72 additions & 0 deletions test/chart.test.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import * as fs from 'fs';
import * as path from 'path';
import { Construct, Node, Dependency } from 'constructs';
import { Chart, ApiObject, Testing } from '../src';
import { Lazy } from '../src/lazy';
Expand Down Expand Up @@ -313,6 +315,76 @@ describe('toJson', () => {

});

test('construct metadata is recorded when requested by api', () => {

const app = Testing.app({ recordConstructMetadata: true });
const chart = new Chart(app, 'chart1');

new ApiObject(chart, 'obj1', {
kind: 'Deployment',
apiVersion: 'v1',
});

app.synth();

const constructMetadata = JSON.parse(fs.readFileSync(path.join(app.outdir, 'construct-metadata.json'), { encoding: 'utf-8' }));
expect(constructMetadata).toEqual({
version: '1.0.0',
resources: {
'chart1-obj1-c818e77f': {
path: 'chart1/obj1',
},
},
});


});

test('construct metadata is recoreded when requested by env variable', () => {

try {
process.env.CDK8S_RECORD_CONSTRUCT_METADATA = 'true';
const app = Testing.app();
const chart = new Chart(app, 'chart1');

new ApiObject(chart, 'obj1', {
kind: 'Deployment',
apiVersion: 'v1',
});

app.synth();

const constructMetadata = JSON.parse(fs.readFileSync(path.join(app.outdir, 'construct-metadata.json'), { encoding: 'utf-8' }));
expect(constructMetadata).toEqual({
version: '1.0.0',
resources: {
'chart1-obj1-c818e77f': {
path: 'chart1/obj1',
},
},
});
} finally {
delete process.env.CDK8S_RECORD_CONSTRUCT_METADATA;
}

});

test('construct metadata is not recorded when not requested', () => {

const app = Testing.app();
const chart = new Chart(app, 'chart1');

new ApiObject(chart, 'obj1', {
kind: 'Deployment',
apiVersion: 'v1',
});

app.synth();

expect(fs.existsSync(path.join(app.outdir, 'construct-metadata.json'))).toBeFalsy();

});

function createImplictToken(value: any) {
const implicit = {};
Object.defineProperty(implicit, 'resolve', { value: () => value });
Expand Down

0 comments on commit 603e2b9

Please sign in to comment.