fix: performance recession when propagating namespace to helm (#5971)

* fix: performance recession when propagating namespace to helm

* fix: handle passing namespace downstream more elegant

* Revert "fix: handle passing namespace downstream more elegant"

This reverts commit 976a7cf2aa.

* Revert "fix: performance recession when propagating namespace to helm"

This reverts commit c7612d1dba.

* fix: use annotation to identify helm chart generated resources

* fix: deduplicate code

* fix: missing import in NamespaceTransformer.go

* ci: allow manual trigger of pipeline in fork

* Revert "ci: allow manual trigger of pipeline in fork"

This reverts commit 8948788fe2.

* fix: test cases

* chore: fix code comment was on wrong line

* chore: fix code comment was on wrong line pt2
This commit is contained in:
Niklas Wagner
2025-09-29 23:08:19 +02:00
committed by GitHub
parent b62d746b80
commit 278dd6e55d
10 changed files with 58 additions and 24 deletions

View File

@@ -11,6 +11,7 @@ import (
"slices" "slices"
"strings" "strings"
"sigs.k8s.io/kustomize/api/konfig"
"sigs.k8s.io/kustomize/api/resmap" "sigs.k8s.io/kustomize/api/resmap"
"sigs.k8s.io/kustomize/api/types" "sigs.k8s.io/kustomize/api/types"
"sigs.k8s.io/kustomize/kyaml/errors" "sigs.k8s.io/kustomize/kyaml/errors"
@@ -294,6 +295,9 @@ func (p *HelmChartInflationGeneratorPlugin) Generate() (rm resmap.ResMap, err er
rm, resMapErr := p.h.ResmapFactory().NewResMapFromBytes(stdout) rm, resMapErr := p.h.ResmapFactory().NewResMapFromBytes(stdout)
if resMapErr == nil { if resMapErr == nil {
if err := p.markHelmGeneratedResources(rm); err != nil {
return nil, err
}
return rm, nil return rm, nil
} }
// try to remove the contents before first "---" because // try to remove the contents before first "---" because
@@ -309,6 +313,9 @@ func (p *HelmChartInflationGeneratorPlugin) Generate() (rm resmap.ResMap, err er
if err != nil { if err != nil {
return nil, fmt.Errorf("could not parse rnode slice into resource map: %w", err) return nil, fmt.Errorf("could not parse rnode slice into resource map: %w", err)
} }
if err := p.markHelmGeneratedResources(rm); err != nil {
return nil, err
}
return rm, nil return rm, nil
} }
return nil, fmt.Errorf("could not parse bytes into resource map: %w", resMapErr) return nil, fmt.Errorf("could not parse bytes into resource map: %w", resMapErr)
@@ -351,6 +358,15 @@ func (p *HelmChartInflationGeneratorPlugin) chartExistsLocally() (string, bool)
return path, s.IsDir() return path, s.IsDir()
} }
func (p *HelmChartInflationGeneratorPlugin) markHelmGeneratedResources(rm resmap.ResMap) error {
for _, r := range rm.Resources() {
if err := r.RNode.PipeE(kyaml.SetAnnotation(konfig.HelmGeneratedAnnotation, "true")); err != nil {
return fmt.Errorf("failed to set helm annotation: %w", err)
}
}
return nil
}
// checkHelmVersion will return an error if the helm version is not V3 // checkHelmVersion will return an error if the helm version is not V3
func (p *HelmChartInflationGeneratorPlugin) checkHelmVersion() error { func (p *HelmChartInflationGeneratorPlugin) checkHelmVersion() error {
stdout, err := p.runHelmCommand([]string{"version", "-c", "--short"}) stdout, err := p.runHelmCommand([]string{"version", "-c", "--short"})

View File

@@ -5,6 +5,7 @@ import (
"fmt" "fmt"
"sigs.k8s.io/kustomize/api/filters/namespace" "sigs.k8s.io/kustomize/api/filters/namespace"
"sigs.k8s.io/kustomize/api/konfig"
"sigs.k8s.io/kustomize/api/resmap" "sigs.k8s.io/kustomize/api/resmap"
"sigs.k8s.io/kustomize/api/types" "sigs.k8s.io/kustomize/api/types"
"sigs.k8s.io/kustomize/kyaml/errors" "sigs.k8s.io/kustomize/kyaml/errors"
@@ -51,11 +52,9 @@ func (p *NamespaceTransformerPlugin) Transform(m resmap.ResMap) error {
// Don't mutate empty objects? // Don't mutate empty objects?
continue continue
} }
if origin, err := r.GetOrigin(); err == nil && origin != nil { if annotations := r.GetAnnotations(konfig.HelmGeneratedAnnotation); annotations[konfig.HelmGeneratedAnnotation] == "true" {
if origin.ConfiguredBy.Kind == "HelmChartInflationGenerator" { // Don't apply namespace on Helm generated manifest. Helm should take care of it.
// Don't apply namespace on Helm generated manifest. Helm should take care of it. continue
continue
}
} }
r.StorePreviousId() r.StorePreviousId()
if err := r.ApplyFilter(namespace.Filter{ if err := r.ApplyFilter(namespace.Filter{

View File

@@ -127,11 +127,11 @@ func (kt *KustTarget) MakeCustomizedResMap() (resmap.ResMap, error) {
} }
func (kt *KustTarget) makeCustomizedResMap() (resmap.ResMap, error) { func (kt *KustTarget) makeCustomizedResMap() (resmap.ResMap, error) {
// Track origin for all resources so builtins can make decisions var origin *resource.Origin
// based on where resources originated from. if len(kt.kustomization.BuildMetadata) != 0 {
// Origin annotations will be stripped from the output if not origin = &resource.Origin{}
// requested via build metadata options. }
kt.origin = &resource.Origin{} kt.origin = origin
ra, err := kt.AccumulateTarget() ra, err := kt.AccumulateTarget()
if err != nil { if err != nil {
return nil, err return nil, err

View File

@@ -46,4 +46,7 @@ const (
// Label key that indicates the resources are validated by a validator // Label key that indicates the resources are validated by a validator
ValidatedByLabelKey = "validated-by" ValidatedByLabelKey = "validated-by"
// Annotation key for marking helm-generated resources to skip namespace transformation
HelmGeneratedAnnotation = ConfigAnnoDomain + "/helm-generated"
) )

View File

@@ -1174,6 +1174,7 @@ kind: Service
metadata: metadata:
annotations: annotations:
helm-namespace: helm-ns helm-namespace: helm-ns
internal.config.kubernetes.io/helm-generated: "true"
name: test-service name: test-service
namespace: helm-ns namespace: helm-ns
`) `)

View File

@@ -11,6 +11,7 @@ import (
"sigs.k8s.io/kustomize/api/filters/patchstrategicmerge" "sigs.k8s.io/kustomize/api/filters/patchstrategicmerge"
"sigs.k8s.io/kustomize/api/ifc" "sigs.k8s.io/kustomize/api/ifc"
"sigs.k8s.io/kustomize/api/internal/utils" "sigs.k8s.io/kustomize/api/internal/utils"
"sigs.k8s.io/kustomize/api/konfig"
"sigs.k8s.io/kustomize/api/types" "sigs.k8s.io/kustomize/api/types"
"sigs.k8s.io/kustomize/kyaml/kio" "sigs.k8s.io/kustomize/kyaml/kio"
"sigs.k8s.io/kustomize/kyaml/kio/kioutil" "sigs.k8s.io/kustomize/kyaml/kio/kioutil"
@@ -47,6 +48,8 @@ var BuildAnnotations = []string{
kioutil.LegacyPathAnnotation, kioutil.LegacyPathAnnotation,
kioutil.LegacyIndexAnnotation, kioutil.LegacyIndexAnnotation,
kioutil.LegacyIdAnnotation, kioutil.LegacyIdAnnotation,
konfig.HelmGeneratedAnnotation,
} }
func (r *Resource) ResetRNode(incoming *Resource) { func (r *Resource) ResetRNode(incoming *Resource) {

View File

@@ -17,6 +17,7 @@ import (
"slices" "slices"
"strings" "strings"
"sigs.k8s.io/kustomize/api/konfig"
"sigs.k8s.io/kustomize/api/resmap" "sigs.k8s.io/kustomize/api/resmap"
"sigs.k8s.io/kustomize/api/types" "sigs.k8s.io/kustomize/api/types"
"sigs.k8s.io/kustomize/kyaml/errors" "sigs.k8s.io/kustomize/kyaml/errors"
@@ -302,6 +303,9 @@ func (p *plugin) Generate() (rm resmap.ResMap, err error) {
rm, resMapErr := p.h.ResmapFactory().NewResMapFromBytes(stdout) rm, resMapErr := p.h.ResmapFactory().NewResMapFromBytes(stdout)
if resMapErr == nil { if resMapErr == nil {
if err := p.markHelmGeneratedResources(rm); err != nil {
return nil, err
}
return rm, nil return rm, nil
} }
// try to remove the contents before first "---" because // try to remove the contents before first "---" because
@@ -317,6 +321,9 @@ func (p *plugin) Generate() (rm resmap.ResMap, err error) {
if err != nil { if err != nil {
return nil, fmt.Errorf("could not parse rnode slice into resource map: %w", err) return nil, fmt.Errorf("could not parse rnode slice into resource map: %w", err)
} }
if err := p.markHelmGeneratedResources(rm); err != nil {
return nil, err
}
return rm, nil return rm, nil
} }
return nil, fmt.Errorf("could not parse bytes into resource map: %w", resMapErr) return nil, fmt.Errorf("could not parse bytes into resource map: %w", resMapErr)
@@ -359,6 +366,15 @@ func (p *plugin) chartExistsLocally() (string, bool) {
return path, s.IsDir() return path, s.IsDir()
} }
func (p *plugin) markHelmGeneratedResources(rm resmap.ResMap) error {
for _, r := range rm.Resources() {
if err := r.RNode.PipeE(kyaml.SetAnnotation(konfig.HelmGeneratedAnnotation, "true")); err != nil {
return fmt.Errorf("failed to set helm annotation: %w", err)
}
}
return nil
}
// checkHelmVersion will return an error if the helm version is not V3 // checkHelmVersion will return an error if the helm version is not V3
func (p *plugin) checkHelmVersion() error { func (p *plugin) checkHelmVersion() error {
stdout, err := p.runHelmCommand([]string{"version", "-c", "--short"}) stdout, err := p.runHelmCommand([]string{"version", "-c", "--short"})

View File

@@ -191,7 +191,6 @@ type: Opaque
apiVersion: v1 apiVersion: v1
kind: Service kind: Service
metadata: metadata:
annotations: {}
labels: labels:
app: moria-minecraft app: moria-minecraft
chart: minecraft-3.1.3 chart: minecraft-3.1.3
@@ -211,7 +210,6 @@ spec:
apiVersion: v1 apiVersion: v1
kind: Service kind: Service
metadata: metadata:
annotations: {}
labels: labels:
app: moria-minecraft app: moria-minecraft
chart: minecraft-3.1.3 chart: minecraft-3.1.3

View File

@@ -8,6 +8,7 @@ import (
"fmt" "fmt"
"sigs.k8s.io/kustomize/api/filters/namespace" "sigs.k8s.io/kustomize/api/filters/namespace"
"sigs.k8s.io/kustomize/api/konfig"
"sigs.k8s.io/kustomize/api/resmap" "sigs.k8s.io/kustomize/api/resmap"
"sigs.k8s.io/kustomize/api/types" "sigs.k8s.io/kustomize/api/types"
"sigs.k8s.io/kustomize/kyaml/errors" "sigs.k8s.io/kustomize/kyaml/errors"
@@ -56,11 +57,9 @@ func (p *plugin) Transform(m resmap.ResMap) error {
// Don't mutate empty objects? // Don't mutate empty objects?
continue continue
} }
if origin, err := r.GetOrigin(); err == nil && origin != nil { if annotations := r.GetAnnotations(konfig.HelmGeneratedAnnotation); annotations[konfig.HelmGeneratedAnnotation] == "true" {
if origin.ConfiguredBy.Kind == "HelmChartInflationGenerator" { // Don't apply namespace on Helm generated manifest. Helm should take care of it.
// Don't apply namespace on Helm generated manifest. Helm should take care of it. continue
continue
}
} }
r.StorePreviousId() r.StorePreviousId()
if err := r.ApplyFilter(namespace.Filter{ if err := r.ApplyFilter(namespace.Filter{

View File

@@ -9,9 +9,9 @@ import (
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
"sigs.k8s.io/kustomize/api/konfig"
"sigs.k8s.io/kustomize/api/provider" "sigs.k8s.io/kustomize/api/provider"
"sigs.k8s.io/kustomize/api/resmap" "sigs.k8s.io/kustomize/api/resmap"
"sigs.k8s.io/kustomize/api/resource"
kusttest_test "sigs.k8s.io/kustomize/api/testutils/kusttest" kusttest_test "sigs.k8s.io/kustomize/api/testutils/kusttest"
kyaml "sigs.k8s.io/kustomize/kyaml/yaml" kyaml "sigs.k8s.io/kustomize/kyaml/yaml"
) )
@@ -779,15 +779,12 @@ kind: Service
metadata: metadata:
name: svc name: svc
namespace: helm-ns namespace: helm-ns
annotations:
this-should-be-keept: "true"
`)) `))
require.NoError(t, err) require.NoError(t, err)
r := rm.Resources()[0] r := rm.Resources()[0]
origin := &resource.Origin{ require.NoError(t, r.RNode.PipeE(kyaml.SetAnnotation(konfig.HelmGeneratedAnnotation, "true")))
ConfiguredBy: kyaml.ResourceIdentifier{
TypeMeta: kyaml.TypeMeta{APIVersion: "builtin", Kind: "HelmChartInflationGenerator"},
},
}
require.NoError(t, r.SetOrigin(origin))
rm, err = th.RunTransformerFromResMap(` rm, err = th.RunTransformerFromResMap(`
apiVersion: builtin apiVersion: builtin
@@ -801,6 +798,8 @@ metadata:
th.AssertActualEqualsExpectedNoIdAnnotations(rm, `apiVersion: v1 th.AssertActualEqualsExpectedNoIdAnnotations(rm, `apiVersion: v1
kind: Service kind: Service
metadata: metadata:
annotations:
this-should-be-keept: "true"
name: svc name: svc
namespace: helm-ns namespace: helm-ns
`) `)