From a1fd6efe5d6a98d9f02b1d7e0249e1009a27a22a Mon Sep 17 00:00:00 2001 From: isarns Date: Sun, 11 Aug 2024 17:44:44 +0300 Subject: [PATCH 1/5] feat: annotation to disable list conversion --- api/krusty/no_list_items_test.go | 122 +++++++++++++++++++++++++++++++ api/resource/factory.go | 11 +++ go.work.sum | 5 ++ 3 files changed, 138 insertions(+) create mode 100644 api/krusty/no_list_items_test.go diff --git a/api/krusty/no_list_items_test.go b/api/krusty/no_list_items_test.go new file mode 100644 index 0000000000..27b8ae7264 --- /dev/null +++ b/api/krusty/no_list_items_test.go @@ -0,0 +1,122 @@ +// Copyright 2019 The Kubernetes Authors. +// SPDX-License-Identifier: Apache-2.0 + +package krusty_test + +import ( + "testing" + + kusttest_test "sigs.k8s.io/kustomize/api/testutils/kusttest" +) + +// test for https://github.com/kubernetes-sigs/kustomize/issues/4240 +func TestSuffix5042(t *testing.T) { + th := kusttest_test.MakeHarness(t) + th.WriteK(".", ` +resources: +- resource.yaml +`) + + th.WriteF("resource.yaml", ` +apiVersion: example.com/v1alpha1 +kind: MyResource +metadata: + name: service +--- +apiVersion: example.com/v1alpha1 +kind: MyResourceTwo +metadata: + name: test +rules: [] +`) + m := th.Run(".", th.MakeDefaultOptions()) + + th.AssertActualEqualsExpected(m, ` +apiVersion: example.com/v1alpha1 +kind: MyResource +metadata: + name: service +--- +apiVersion: example.com/v1alpha1 +kind: MyResourceTwo +metadata: + name: test +rules: [] +`) +} + +func TestListSuffix5042(t *testing.T) { + th := kusttest_test.MakeHarness(t) + th.WriteK(".", ` +resources: +- resource.yaml +`) + + th.WriteF("resource.yaml", ` +apiVersion: example.com/v1alpha1 +kind: MyResource +metadata: + name: service +--- +apiVersion: example.com/v1alpha1 +kind: MyResourceList +metadata: + annotations: + kustomize.config.k8s.io/convertToInlineList: "false" + name: test +rules: [] +`) + m := th.Run(".", th.MakeDefaultOptions()) + + th.AssertActualEqualsExpected(m, ` +apiVersion: example.com/v1alpha1 +kind: MyResource +metadata: + name: service +--- +apiVersion: example.com/v1alpha1 +kind: MyResourceList +metadata: + annotations: + kustomize.config.k8s.io/convertToInlineList: "false" + name: test +rules: [] +`) +} + +func TestListSuffix5485(t *testing.T) { + th := kusttest_test.MakeHarness(t) + th.WriteK(".", ` +resources: +- resource.yaml + `) + + th.WriteF("resource.yaml", ` +apiVersion: infra.protonbase.io/v1alpha1 +kind: AccessWhiteList +metadata: + annotations: + kustomize.config.k8s.io/convertToInlineList: "false" + name: wlmls5769f + namespace: dc7i4hyxzw +spec: + rules: + - sourceIps: 0.0.0.0/16 +`) + + m := th.Run(".", th.MakeDefaultOptions()) + + th.AssertActualEqualsExpected(m, ` +apiVersion: infra.protonbase.io/v1alpha1 +kind: AccessWhiteList +metadata: + annotations: + kustomize.config.k8s.io/convertToInlineList: "false" + name: wlmls5769f + namespace: dc7i4hyxzw +spec: + rules: + - sourceIps: 0.0.0.0/16 +`) + +} \ No newline at end of file diff --git a/api/resource/factory.go b/api/resource/factory.go index fef2f6e499..c4c6a6e9ac 100644 --- a/api/resource/factory.go +++ b/api/resource/factory.go @@ -7,6 +7,7 @@ import ( "encoding/json" "fmt" "log" + "strconv" "strings" "sigs.k8s.io/kustomize/api/ifc" @@ -189,6 +190,16 @@ func (rf *Factory) inlineAnyEmbeddedLists( var n0 *yaml.RNode for len(nodes) > 0 { n0, nodes = nodes[0], nodes[1:] + annotations := n0.GetAnnotations() + convertToInlineList, err := strconv.ParseBool(annotations["kustomize.config.k8s.io/convertToInlineList"]) + if err != nil { + convertToInlineList = true + } + if !convertToInlineList { + // if the annotation is set to true, then we should not convert the list to inline + result = append(result, n0) + continue + } kind := n0.GetKind() if !strings.HasSuffix(kind, "List") { result = append(result, n0) diff --git a/go.work.sum b/go.work.sum index b858ddeb8b..03812685dd 100644 --- a/go.work.sum +++ b/go.work.sum @@ -232,6 +232,7 @@ github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumC github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954 h1:RMLoZVzv4GliuWafOuPuQDKSm1SJph7uCRnnS61JAn4= github.com/dimchansky/utfbom v1.1.1/go.mod h1:SxdoEBH5qIqFocHMyGOXVAybYJdr71b1Q/j0mACtrfE= github.com/djherbis/atime v1.1.0/go.mod h1:28OF6Y8s3NQWwacXc5eZTsEsiMzp7LF8MbXE+XJPdBE= +github.com/dnaeon/go-vcr v1.2.0/go.mod h1:R4UdLID7HZT3taECzJs4YgbbH6PIGXB6W/sc5OLb6RQ= github.com/docker/docker v0.7.3-0.20190327010347-be7ac8be2ae0 h1:w3NnFcKR5241cfmQU5ZZAsf0xcpId6mWOupTvJlUX2U= github.com/docker/go-units v0.4.0 h1:3uh0PgVws3nIA0Q+MwDC8yjEPf9zjRfZZWXZYDct3Tw= github.com/docker/spdystream v0.0.0-20160310174837-449fdfce4d96 h1:cenwrSVm+Z7QLSV/BsnenAOcDXdX4cMv4wP0B/5QbPg= @@ -275,6 +276,7 @@ github.com/go-stack/stack v1.8.0 h1:5SgMzNM5HxrEjV0ww2lTmX6E2Izsfxas4+YHWRs3Lsk= github.com/goccy/go-json v0.9.11/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= github.com/golang-jwt/jwt v3.2.1+incompatible h1:73Z+4BJcrTC+KczS6WvTPvRGOp1WmfEP4Q1lOd9Z/+c= github.com/golang-jwt/jwt v3.2.1+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I= +github.com/golang-jwt/jwt/v4 v4.5.0/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58= github.com/golang/glog v1.1.0/go.mod h1:pfYeQZ3JWZoXTV5sFc986z3HTpwQs9At6P4ImfuP3NQ= github.com/golang/mock v1.4.4 h1:l75CXGRSwbaYNpl/Z2X1XIIAMSCquvXgpVZDhwEIJsc= @@ -528,6 +530,7 @@ golang.org/x/net v0.14.0/go.mod h1:PpSgVXXLK0OxS0F31C1/tv6XNguvCrnXIDrFMspZIUI= golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk= golang.org/x/net v0.16.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= +golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM= golang.org/x/oauth2 v0.5.0/go.mod h1:9/XBHVqLaWO3/BRHs5jbpYCnOZVjj5V0ndyaAM7KB4I= golang.org/x/oauth2 v0.8.0/go.mod h1:yr7u4HXZRm1R1kBWqr/xKNqewf0plRYoB7sla+BCIXE= golang.org/x/oauth2 v0.10.0/go.mod h1:kTpgurOux7LqtuxjuyZa4Gj2gdezIt/jQtGnNFfypQI= @@ -548,7 +551,9 @@ golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.14.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/telemetry v0.0.0-20240208230135-b75ee8823808/go.mod h1:KG1lNk5ZFNssSZLrpVb4sMXKMpGwGXOxSG3rnu2gZQQ= +golang.org/x/telemetry v0.0.0-20240228155512-f48c80bd79b2/go.mod h1:TeRTkGYfJXctD9OcfyVLyj2J3IxLnKwHJR8f4D8a3YE= golang.org/x/term v0.0.0-20220526004731-065cf7ba2467/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU= golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= From 77daec89b85d8f9c29c6debe4ac81c886f3dca95 Mon Sep 17 00:00:00 2001 From: isarns Date: Tue, 13 Aug 2024 14:35:46 +0300 Subject: [PATCH 2/5] refactor: inlineAnyEmbeddedLists --- api/krusty/no_list_items_test.go | 108 ++++++++++++++++++++++++++++--- api/resource/factory.go | 16 ++--- 2 files changed, 104 insertions(+), 20 deletions(-) diff --git a/api/krusty/no_list_items_test.go b/api/krusty/no_list_items_test.go index 27b8ae7264..b6cc587427 100644 --- a/api/krusty/no_list_items_test.go +++ b/api/krusty/no_list_items_test.go @@ -61,8 +61,6 @@ metadata: apiVersion: example.com/v1alpha1 kind: MyResourceList metadata: - annotations: - kustomize.config.k8s.io/convertToInlineList: "false" name: test rules: [] `) @@ -77,8 +75,6 @@ metadata: apiVersion: example.com/v1alpha1 kind: MyResourceList metadata: - annotations: - kustomize.config.k8s.io/convertToInlineList: "false" name: test rules: [] `) @@ -95,8 +91,6 @@ resources: apiVersion: infra.protonbase.io/v1alpha1 kind: AccessWhiteList metadata: - annotations: - kustomize.config.k8s.io/convertToInlineList: "false" name: wlmls5769f namespace: dc7i4hyxzw spec: @@ -110,8 +104,6 @@ spec: apiVersion: infra.protonbase.io/v1alpha1 kind: AccessWhiteList metadata: - annotations: - kustomize.config.k8s.io/convertToInlineList: "false" name: wlmls5769f namespace: dc7i4hyxzw spec: @@ -119,4 +111,104 @@ spec: - sourceIps: 0.0.0.0/16 `) +} + +func TestListToIndividualResources(t *testing.T) { + th := kusttest_test.MakeHarness(t) + th.WriteK(".", ` +resources: +- list.yaml +`) + + th.WriteF("list.yaml", ` +apiVersion: v1 +kind: PodList +items: + - apiVersion: v1 + kind: Pod + metadata: + name: my-pod-1 + namespace: default + labels: + app: my-app + spec: + containers: + - name: my-container + image: nginx:1.19.10 + ports: + - containerPort: 80 + - apiVersion: v1 + kind: Pod + metadata: + name: my-pod-2 + namespace: default + labels: + app: my-app + spec: + containers: + - name: my-container + image: nginx:1.19.10 + ports: + - containerPort: 80 + - apiVersion: v1 + kind: Pod + metadata: + name: my-pod-3 + namespace: default + labels: + app: my-app + spec: + containers: + - name: my-container + image: nginx:1.19.10 + ports: + - containerPort: 80 +`) + + m := th.Run(".", th.MakeDefaultOptions()) + + + th.AssertActualEqualsExpected(m, ` +apiVersion: v1 +kind: Pod +metadata: + labels: + app: my-app + name: my-pod-1 + namespace: default +spec: + containers: + - image: nginx:1.19.10 + name: my-container + ports: + - containerPort: 80 +--- +apiVersion: v1 +kind: Pod +metadata: + labels: + app: my-app + name: my-pod-2 + namespace: default +spec: + containers: + - image: nginx:1.19.10 + name: my-container + ports: + - containerPort: 80 +--- +apiVersion: v1 +kind: Pod +metadata: + labels: + app: my-app + name: my-pod-3 + namespace: default +spec: + containers: + - image: nginx:1.19.10 + name: my-container + ports: + - containerPort: 80 +`) } \ No newline at end of file diff --git a/api/resource/factory.go b/api/resource/factory.go index c4c6a6e9ac..a42f93bb8e 100644 --- a/api/resource/factory.go +++ b/api/resource/factory.go @@ -7,7 +7,6 @@ import ( "encoding/json" "fmt" "log" - "strconv" "strings" "sigs.k8s.io/kustomize/api/ifc" @@ -190,16 +189,6 @@ func (rf *Factory) inlineAnyEmbeddedLists( var n0 *yaml.RNode for len(nodes) > 0 { n0, nodes = nodes[0], nodes[1:] - annotations := n0.GetAnnotations() - convertToInlineList, err := strconv.ParseBool(annotations["kustomize.config.k8s.io/convertToInlineList"]) - if err != nil { - convertToInlineList = true - } - if !convertToInlineList { - // if the annotation is set to true, then we should not convert the list to inline - result = append(result, n0) - continue - } kind := n0.GetKind() if !strings.HasSuffix(kind, "List") { result = append(result, n0) @@ -213,7 +202,10 @@ func (rf *Factory) inlineAnyEmbeddedLists( } items, ok := m["items"] if !ok { - // treat as an empty list + // Items field is not present. + // This is not a collections resource. + // read more https://kubernetes.io/docs/reference/using-api/api-concepts/#collections + result = append(result, n0) continue } slice, ok := items.([]interface{}) From bbb0b08576e4a256f21f81d5f927786e4a47acd1 Mon Sep 17 00:00:00 2001 From: isarns Date: Sun, 18 Aug 2024 14:56:54 +0300 Subject: [PATCH 3/5] test: add empty list test --- api/krusty/no_list_items_test.go | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/api/krusty/no_list_items_test.go b/api/krusty/no_list_items_test.go index b6cc587427..49092b0bd3 100644 --- a/api/krusty/no_list_items_test.go +++ b/api/krusty/no_list_items_test.go @@ -211,4 +211,20 @@ spec: ports: - containerPort: 80 `) +} + +// Empty list should result in no resources +func TestEmptyList(t *testing.T) { + th := kusttest_test.MakeHarness(t) + th.WriteK(".", ` +resources: +- emptyList.yaml +`) + th.WriteF("emptyList.yaml", ` +apiVersion: v1 +kind: PodList +items: [] +`) + m := th.Run(".", th.MakeDefaultOptions()) + th.AssertActualEqualsExpected(m, "") } \ No newline at end of file From e6266d4559d5e19870506af4085fc14b552d6dd4 Mon Sep 17 00:00:00 2001 From: isarns Date: Mon, 9 Sep 2024 13:26:33 +0300 Subject: [PATCH 4/5] refactor: fix test with not 'items:' --- api/resource/factory_test.go | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/api/resource/factory_test.go b/api/resource/factory_test.go index 8695ab0364..953caa7ddb 100644 --- a/api/resource/factory_test.go +++ b/api/resource/factory_test.go @@ -301,6 +301,17 @@ kind: List t.Fatalf("failed to create new instance with %v: %v", deploymentB, errB) } + deploymentNoItems := "deployment-no-items" + testDeploymentNoItems, errNoItems := factory.FromMap( + map[string]interface{}{ + "apiVersion": "v1", + "kind": "List", + }, + ) + if errNoItems != nil { + t.Fatalf("failed to create new instance with %v: %v", deploymentNoItems, testDeploymentNoItems) + } + fSys := filesys.MakeFsInMemory() fSys.WriteFile(string(patchGood1), []byte(patch1)) fSys.WriteFile(string(patchGood2), []byte(patch2)) @@ -363,7 +374,7 @@ kind: List }, "listWithNoItems": { input: []types.PatchStrategicMerge{patchList4}, - expectedOut: []*Resource{}, + expectedOut: []*Resource{testDeploymentNoItems}, expectedErr: false, }, } From a5f43ec75a1b500f0a5ad385cc3bc7f365e4c022 Mon Sep 17 00:00:00 2001 From: isarns Date: Mon, 9 Sep 2024 13:26:53 +0300 Subject: [PATCH 5/5] style: linting --- api/krusty/no_list_items_test.go | 58 +++++++++++++++----------------- 1 file changed, 28 insertions(+), 30 deletions(-) diff --git a/api/krusty/no_list_items_test.go b/api/krusty/no_list_items_test.go index 49092b0bd3..befe621ea9 100644 --- a/api/krusty/no_list_items_test.go +++ b/api/krusty/no_list_items_test.go @@ -4,20 +4,20 @@ package krusty_test import ( - "testing" + "testing" - kusttest_test "sigs.k8s.io/kustomize/api/testutils/kusttest" + kusttest_test "sigs.k8s.io/kustomize/api/testutils/kusttest" ) // test for https://github.com/kubernetes-sigs/kustomize/issues/4240 func TestSuffix5042(t *testing.T) { - th := kusttest_test.MakeHarness(t) - th.WriteK(".", ` + th := kusttest_test.MakeHarness(t) + th.WriteK(".", ` resources: - resource.yaml `) - th.WriteF("resource.yaml", ` + th.WriteF("resource.yaml", ` apiVersion: example.com/v1alpha1 kind: MyResource metadata: @@ -29,9 +29,9 @@ metadata: name: test rules: [] `) - m := th.Run(".", th.MakeDefaultOptions()) + m := th.Run(".", th.MakeDefaultOptions()) - th.AssertActualEqualsExpected(m, ` + th.AssertActualEqualsExpected(m, ` apiVersion: example.com/v1alpha1 kind: MyResource metadata: @@ -46,13 +46,13 @@ rules: [] } func TestListSuffix5042(t *testing.T) { - th := kusttest_test.MakeHarness(t) - th.WriteK(".", ` + th := kusttest_test.MakeHarness(t) + th.WriteK(".", ` resources: - resource.yaml `) - th.WriteF("resource.yaml", ` + th.WriteF("resource.yaml", ` apiVersion: example.com/v1alpha1 kind: MyResource metadata: @@ -64,9 +64,9 @@ metadata: name: test rules: [] `) - m := th.Run(".", th.MakeDefaultOptions()) + m := th.Run(".", th.MakeDefaultOptions()) - th.AssertActualEqualsExpected(m, ` + th.AssertActualEqualsExpected(m, ` apiVersion: example.com/v1alpha1 kind: MyResource metadata: @@ -81,13 +81,13 @@ rules: [] } func TestListSuffix5485(t *testing.T) { - th := kusttest_test.MakeHarness(t) - th.WriteK(".", ` + th := kusttest_test.MakeHarness(t) + th.WriteK(".", ` resources: - resource.yaml `) - th.WriteF("resource.yaml", ` + th.WriteF("resource.yaml", ` apiVersion: infra.protonbase.io/v1alpha1 kind: AccessWhiteList metadata: @@ -98,9 +98,9 @@ spec: - sourceIps: 0.0.0.0/16 `) - m := th.Run(".", th.MakeDefaultOptions()) + m := th.Run(".", th.MakeDefaultOptions()) - th.AssertActualEqualsExpected(m, ` + th.AssertActualEqualsExpected(m, ` apiVersion: infra.protonbase.io/v1alpha1 kind: AccessWhiteList metadata: @@ -110,17 +110,16 @@ spec: rules: - sourceIps: 0.0.0.0/16 `) - } func TestListToIndividualResources(t *testing.T) { - th := kusttest_test.MakeHarness(t) - th.WriteK(".", ` + th := kusttest_test.MakeHarness(t) + th.WriteK(".", ` resources: - list.yaml `) - th.WriteF("list.yaml", ` + th.WriteF("list.yaml", ` apiVersion: v1 kind: PodList items: @@ -165,10 +164,9 @@ items: - containerPort: 80 `) - m := th.Run(".", th.MakeDefaultOptions()) + m := th.Run(".", th.MakeDefaultOptions()) - - th.AssertActualEqualsExpected(m, ` + th.AssertActualEqualsExpected(m, ` apiVersion: v1 kind: Pod metadata: @@ -215,16 +213,16 @@ spec: // Empty list should result in no resources func TestEmptyList(t *testing.T) { - th := kusttest_test.MakeHarness(t) - th.WriteK(".", ` + th := kusttest_test.MakeHarness(t) + th.WriteK(".", ` resources: - emptyList.yaml `) - th.WriteF("emptyList.yaml", ` + th.WriteF("emptyList.yaml", ` apiVersion: v1 kind: PodList items: [] `) - m := th.Run(".", th.MakeDefaultOptions()) - th.AssertActualEqualsExpected(m, "") -} \ No newline at end of file + m := th.Run(".", th.MakeDefaultOptions()) + th.AssertActualEqualsExpected(m, "") +}