Merge pull request #6037 from rohithnarasimha/feat/add-configuration-command

feat: add support for 'kustomize edit add configuration' command
This commit is contained in:
Kubernetes Prow Robot
2026-04-07 21:45:33 +05:30
committed by GitHub
3 changed files with 171 additions and 0 deletions

View File

@@ -0,0 +1,86 @@
// Copyright 2025 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
package add
import (
"errors"
"fmt"
"log"
"slices"
"github.com/spf13/cobra"
"sigs.k8s.io/kustomize/kustomize/v5/commands/internal/kustfile"
"sigs.k8s.io/kustomize/kustomize/v5/commands/internal/util"
"sigs.k8s.io/kustomize/kyaml/filesys"
)
type addConfigurationOptions struct {
configurationFilePaths []string
}
// newCmdAddConfiguration adds the name of a file containing a configuration
// to the kustomization file.
func newCmdAddConfiguration(fSys filesys.FileSystem) *cobra.Command {
var o addConfigurationOptions
cmd := &cobra.Command{
Use: "configuration",
Short: "Add the name of a file containing a configuration to the kustomization file",
Long: `Add the name of a file containing a configuration (e.g., a Kubernetes configuration resource)
to the kustomization file. Configurations are used to define custom transformer specifications
for CRDs and other resource types.`,
Example: `
# Adds a configuration file to the kustomization
kustomize edit add configuration <filepath>
# Adds multiple configuration files
kustomize edit add configuration <filepath1>,<filepath2>`,
RunE: func(cmd *cobra.Command, args []string) error {
err := o.Validate(fSys, args)
if err != nil {
return err
}
return o.RunAddConfiguration(fSys)
},
}
return cmd
}
// Validate validates add configuration command.
func (o *addConfigurationOptions) Validate(fSys filesys.FileSystem, args []string) error {
if len(args) == 0 {
return errors.New("must specify a yaml file which contains a configuration resource")
}
var err error
o.configurationFilePaths, err = util.GlobPatterns(fSys, args)
if err != nil {
return fmt.Errorf("glob patterns: %w", err)
}
return nil
}
// RunAddConfiguration runs add configuration command (do real work).
func (o *addConfigurationOptions) RunAddConfiguration(fSys filesys.FileSystem) error {
if len(o.configurationFilePaths) == 0 {
return nil
}
mf, err := kustfile.NewKustomizationFile(fSys)
if err != nil {
return fmt.Errorf("new kustomization file: %w", err)
}
m, err := mf.Read()
if err != nil {
return fmt.Errorf("read kustomization: %w", err)
}
for _, c := range o.configurationFilePaths {
if slices.Contains(m.Configurations, c) {
log.Printf("configuration %s already in kustomization file", c)
continue
}
m.Configurations = append(m.Configurations, c)
}
if err := mf.Write(m); err != nil {
return fmt.Errorf("write kustomization: %w", err)
}
return nil
}

View File

@@ -0,0 +1,78 @@
// Copyright 2025 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
package add
import (
"strings"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
testutils_test "sigs.k8s.io/kustomize/kustomize/v5/commands/internal/testutils"
"sigs.k8s.io/kustomize/kyaml/filesys"
)
func TestAddConfiguration(t *testing.T) {
fSys := filesys.MakeEmptyDirInMemory()
testutils_test.WriteTestKustomization(fSys)
cmd := newCmdAddConfiguration(fSys)
if cmd == nil {
t.Fatal("Expected cmd to not be nil")
}
if cmd.Use != "configuration" {
t.Fatalf("Expected Use to be 'configuration', got '%s'", cmd.Use)
}
if cmd.Short == "" {
t.Fatal("Expected Short to not be empty")
}
}
func TestAddConfigurationHappyPath(t *testing.T) {
fSys := filesys.MakeEmptyDirInMemory()
err := fSys.WriteFile("config1.yaml", []byte("apiVersion: v1\nkind: Config"))
require.NoError(t, err)
err = fSys.WriteFile("config2.yaml", []byte("apiVersion: v1\nkind: Config"))
require.NoError(t, err)
testutils_test.WriteTestKustomization(fSys)
cmd := newCmdAddConfiguration(fSys)
args := []string{"config1.yaml", "config2.yaml"}
require.NoError(t, cmd.RunE(cmd, args))
content, err := testutils_test.ReadTestKustomization(fSys)
require.NoError(t, err)
assert.Contains(t, string(content), "config1.yaml")
assert.Contains(t, string(content), "config2.yaml")
}
func TestAddConfigurationDuplicate(t *testing.T) {
fSys := filesys.MakeEmptyDirInMemory()
err := fSys.WriteFile("config.yaml", []byte("apiVersion: v1\nkind: Config"))
require.NoError(t, err)
testutils_test.WriteTestKustomization(fSys)
cmd := newCmdAddConfiguration(fSys)
// First addition
args := []string{"config.yaml"}
require.NoError(t, cmd.RunE(cmd, args))
content, err := testutils_test.ReadTestKustomization(fSys)
require.NoError(t, err)
assert.Contains(t, string(content), "config.yaml")
// Second addition (should skip duplicate)
require.NoError(t, cmd.RunE(cmd, args))
content, err = testutils_test.ReadTestKustomization(fSys)
require.NoError(t, err)
// Count occurrences - should only appear once
count := strings.Count(string(content), "config.yaml")
assert.Equal(t, 1, count, "config.yaml should appear exactly once")
}

View File

@@ -47,6 +47,12 @@ func NewCmdAdd(
# Adds a transformer configuration to the kustomization
kustomize edit add transformer <filepath>
# Adds a configuration file to the kustomization
kustomize edit add configuration <filepath>
# Adds a generator configuration to the kustomization
kustomize edit add generator <filepath>
`,
Args: cobra.MinimumNArgs(1),
}
@@ -61,6 +67,7 @@ func NewCmdAdd(
newCmdAddLabel(fSys, ldr.Validator().MakeLabelValidator()),
newCmdAddAnnotation(fSys, ldr.Validator().MakeAnnotationValidator()),
newCmdAddTransformer(fSys),
newCmdAddConfiguration(fSys),
newCmdAddGenerator(fSys),
)
return c