From 91aafe7365da4c78b28e1c3d10f120f1eed74297 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Flemstr=C3=B6m?= Date: Thu, 13 Aug 2020 14:15:38 +0200 Subject: [PATCH 1/2] Avoid emitting YAML back-references in kpt fn output --- ts/kpt-functions/src/io.ts | 2 + ts/kpt-functions/src/io_test.ts | 68 ++++++++++++++++++++++++++++++++- ts/kpt-functions/src/types.ts | 6 +-- 3 files changed, 72 insertions(+), 4 deletions(-) diff --git a/ts/kpt-functions/src/io.ts b/ts/kpt-functions/src/io.ts index 6eceb8540..78bdf5dc6 100644 --- a/ts/kpt-functions/src/io.ts +++ b/ts/kpt-functions/src/io.ts @@ -38,6 +38,8 @@ const YAML_STYLE: DumpOptions = { skipInvalid: true, // unset lineWidth from default of 80 to avoid reformatting lineWidth: -1, + // avoid refs because many YAML parsers in the k8s ecosystem don't support them + noRefs: true, }; /** diff --git a/ts/kpt-functions/src/io_test.ts b/ts/kpt-functions/src/io_test.ts index f775ab985..136e95649 100644 --- a/ts/kpt-functions/src/io_test.ts +++ b/ts/kpt-functions/src/io_test.ts @@ -15,7 +15,8 @@ */ import { FileFormat, parse, stringify } from './io'; -import { Configs, KubernetesObject } from './types'; +import { Configs, JsonArray, KubernetesObject } from './types'; +import { kubernetesObjectResult } from './result'; describe('read', () => { describe('in YAML format', () => { @@ -686,3 +687,68 @@ results: }); }); }); + +describe('roundtrip', () => { + describe('using YAML', () => { + it('should not insert YAML references', () => { + interface Baz { + baz: number; + } + + interface Foo extends KubernetesObject { + spec: { + array: Baz[]; + }; + } + + const input = + 'items: [{apiVersion: v1, kind: Foo, metadata: {name: bar}, spec: {array: [{baz: 1}]}}]'; + const configs = parse(input, FileFormat.YAML); + + const foo = configs.getAll()[0] as Foo; + configs.addResults( + kubernetesObjectResult('something is wrong', foo, { + path: 'spec.array', + // Note: we re-use objects from the input to trigger YAML refs to normally be created + currentValue: (foo.spec.array as unknown) as JsonArray, + suggestedValue: (foo.spec.array.concat([ + { baz: 3 }, + ]) as unknown) as JsonArray, + }) + ); + + const stringified = stringify(configs, FileFormat.YAML); + + // We want to verify that there are no back-references like &ref and *ref in the output + expect(stringified).toEqual(`apiVersion: v1 +kind: ResourceList +metadata: + name: output +items: +- apiVersion: v1 + kind: Foo + metadata: + name: bar + spec: + array: + - baz: 1 +results: +- message: something is wrong + severity: error + resourceRef: + apiVersion: v1 + kind: Foo + namespace: '' + name: bar + file: {} + field: + path: spec.array + currentValue: + - baz: 1 + suggestedValue: + - baz: 1 + - baz: 3 +`); + }); + }); +}); diff --git a/ts/kpt-functions/src/types.ts b/ts/kpt-functions/src/types.ts index 972630ce3..5d7dc4264 100644 --- a/ts/kpt-functions/src/types.ts +++ b/ts/kpt-functions/src/types.ts @@ -403,13 +403,13 @@ export interface Result { */ export type Severity = 'error' | 'warn' | 'info'; -interface JsonArray extends Array {} +export interface JsonArray extends Array {} -interface JsonMap { +export interface JsonMap { [field: string]: Json; } -type Json = null | boolean | number | string | JsonArray | JsonMap; +export type Json = null | boolean | number | string | JsonArray | JsonMap; /** * Metadata about a specific field in a Kubernetes object. From ff17d67701655aa0f5195cce8d498bf8e053161d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Flemstr=C3=B6m?= Date: Wed, 19 Aug 2020 09:26:07 +0200 Subject: [PATCH 2/2] Add comments to exported types --- ts/kpt-functions/src/types.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/ts/kpt-functions/src/types.ts b/ts/kpt-functions/src/types.ts index 5d7dc4264..e118d0df6 100644 --- a/ts/kpt-functions/src/types.ts +++ b/ts/kpt-functions/src/types.ts @@ -403,12 +403,15 @@ export interface Result { */ export type Severity = 'error' | 'warn' | 'info'; +/** A plain old JSON array according to ECMA-404. */ export interface JsonArray extends Array {} +/** A plain old JSON object/map according to ECMA-404. */ export interface JsonMap { [field: string]: Json; } +/** Any plain old JSON value according to ECMA-404. */ export type Json = null | boolean | number | string | JsonArray | JsonMap; /**