From eecc4dbd5198cca5b66e5c3018c407cd38b13c80 Mon Sep 17 00:00:00 2001 From: Dmitriy Matrenichev Date: Mon, 4 Dec 2023 14:34:16 +0300 Subject: [PATCH] fix: trim leading spaces\newlines in inline manifest contents In route `LoadPatches` -> `configpatcher.Apply` -> `configloader.NewFromBytes` any leading newlines will be transformed into `|4` yaml. We want to prevent that. Closes #7993 Signed-off-by: Dmitriy Matrenichev --- .../config/configpatcher/apply_test.go | 50 +++++++++++++++++-- .../testdata/apply/expected_manifests.yaml | 27 ++++++++++ .../testdata/apply/strategic4.yaml | 17 +++++++ .../config/types/v1alpha1/v1alpha1_types.go | 17 +++++++ 4 files changed, 106 insertions(+), 5 deletions(-) create mode 100644 pkg/machinery/config/configpatcher/testdata/apply/expected_manifests.yaml create mode 100644 pkg/machinery/config/configpatcher/testdata/apply/strategic4.yaml diff --git a/pkg/machinery/config/configpatcher/apply_test.go b/pkg/machinery/config/configpatcher/apply_test.go index 23b8447751..2875970c37 100644 --- a/pkg/machinery/config/configpatcher/apply_test.go +++ b/pkg/machinery/config/configpatcher/apply_test.go @@ -2,7 +2,6 @@ // License, v. 2.0. If a copy of the MPL was not distributed with this // file, You can obtain one at http://mozilla.org/MPL/2.0/. -//nolint:dupl package configpatcher_test import ( @@ -20,13 +19,16 @@ import ( var config []byte //go:embed testdata/apply/expected.yaml -var expected []byte +var expected string //go:embed testdata/multidoc/config.yaml var configMultidoc []byte //go:embed testdata/multidoc/expected.yaml -var expectedMultidoc []byte +var expectedMultidoc string + +//go:embed testdata/apply/expected_manifests.yaml +var expectedManifests string func TestApply(t *testing.T) { patches, err := configpatcher.LoadPatches([]string{ @@ -61,7 +63,7 @@ func TestApply(t *testing.T) { bytes, err := out.Bytes() require.NoError(t, err) - assert.Equal(t, string(expected), string(bytes)) + assert.Equal(t, expected, string(bytes)) }) } } @@ -126,7 +128,7 @@ func TestApplyMultiDoc(t *testing.T) { bytes, err := out.Bytes() require.NoError(t, err) - assert.Equal(t, string(expectedMultidoc), string(bytes)) + assert.Equal(t, expectedMultidoc, string(bytes)) }) } } @@ -170,3 +172,41 @@ func TestApplyAuditPolicy(t *testing.T) { }) } } + +func TestApplyWithManifestNewline(t *testing.T) { + patches, err := configpatcher.LoadPatches([]string{ + "@testdata/apply/strategic4.yaml", + }) + require.NoError(t, err) + + cfg, err := configloader.NewFromBytes(config) + require.NoError(t, err) + + for _, tt := range []struct { + name string + input configpatcher.Input + }{ + { + name: "WithConfig", + input: configpatcher.WithConfig(cfg), + }, + { + name: "WithBytes", + input: configpatcher.WithBytes(config), + }, + } { + t.Run(tt.name, func(t *testing.T) { + out, err := configpatcher.Apply(tt.input, patches) + require.NoError(t, err) + + bytes, err := out.Bytes() + require.NoError(t, err) + + // Verify that after all our transformations the YAML is still valid and newline is removed + _, err = configloader.NewFromBytes(bytes) + require.NoError(t, err) + + assert.Equal(t, expectedManifests, string(bytes)) + }) + } +} diff --git a/pkg/machinery/config/configpatcher/testdata/apply/expected_manifests.yaml b/pkg/machinery/config/configpatcher/testdata/apply/expected_manifests.yaml new file mode 100644 index 0000000000..c7e0dd375e --- /dev/null +++ b/pkg/machinery/config/configpatcher/testdata/apply/expected_manifests.yaml @@ -0,0 +1,27 @@ +version: v1alpha1 +machine: + type: "" + token: "" + certSANs: [] + network: + hostname: hostname1 + interfaces: + - interface: eth0 + dhcp: true +cluster: + controlPlane: null + inlineManifests: + - name: cilium + contents: | + --- + apiVersion: v1 + kind: ServiceAccount + metadata: + name: cilium + namespace: kube-system + --- + apiVersion: v1 + kind: ServiceAccount + metadata: + name: cilium-operator + namespace: kube-system diff --git a/pkg/machinery/config/configpatcher/testdata/apply/strategic4.yaml b/pkg/machinery/config/configpatcher/testdata/apply/strategic4.yaml new file mode 100644 index 0000000000..b8e75e290b --- /dev/null +++ b/pkg/machinery/config/configpatcher/testdata/apply/strategic4.yaml @@ -0,0 +1,17 @@ +cluster: + inlineManifests: + - name: cilium + contents: | # the empty newline below is important + + --- + apiVersion: v1 + kind: ServiceAccount + metadata: + name: cilium + namespace: kube-system + --- + apiVersion: v1 + kind: ServiceAccount + metadata: + name: cilium-operator + namespace: kube-system diff --git a/pkg/machinery/config/types/v1alpha1/v1alpha1_types.go b/pkg/machinery/config/types/v1alpha1/v1alpha1_types.go index 9bcd88b4e3..b11bc62b12 100644 --- a/pkg/machinery/config/types/v1alpha1/v1alpha1_types.go +++ b/pkg/machinery/config/types/v1alpha1/v1alpha1_types.go @@ -2183,6 +2183,23 @@ type VolumeMountConfig struct { // ClusterInlineManifests is a list of ClusterInlineManifest. type ClusterInlineManifests []ClusterInlineManifest +// UnmarshalYAML implements yaml.Unmarshaler. +func (manifests *ClusterInlineManifests) UnmarshalYAML(value *yaml.Node) error { + var result []ClusterInlineManifest + + if err := value.Decode(&result); err != nil { + return err + } + + for i := range result { + result[i].InlineManifestContents = strings.TrimLeft(result[i].InlineManifestContents, "\t\n\v\f\r") + } + + *manifests = result + + return nil +} + // ClusterInlineManifest struct describes inline bootstrap manifests for the user. type ClusterInlineManifest struct { // description: |