From bee2251aef5c8045033fb90fd5c0e24d50e1813a Mon Sep 17 00:00:00 2001 From: kfess <35001425+kfess@users.noreply.github.com> Date: Thu, 18 Dec 2025 16:28:34 +0900 Subject: [PATCH] Fixed `kubectl alpha kuberc set` command to preserve unspecified fields on overwrite (#135619) * Fix kuberc set command to preserve unspecified fields on overwrite * remove ambiguous description --- .../src/k8s.io/kubectl/pkg/cmd/kuberc/set.go | 30 +- .../k8s.io/kubectl/pkg/cmd/kuberc/set_test.go | 263 ++++++++++++++++++ 2 files changed, 291 insertions(+), 2 deletions(-) diff --git a/staging/src/k8s.io/kubectl/pkg/cmd/kuberc/set.go b/staging/src/k8s.io/kubectl/pkg/cmd/kuberc/set.go index cd47dc15076..8603bde08f6 100644 --- a/staging/src/k8s.io/kubectl/pkg/cmd/kuberc/set.go +++ b/staging/src/k8s.io/kubectl/pkg/cmd/kuberc/set.go @@ -243,6 +243,12 @@ func (o *SetOptions) setDefaults(pref *v1beta1.Preference, options []v1beta1.Com return fmt.Errorf("defaults for command %q already exist, use --overwrite to replace", o.Command) } + if len(options) == 0 { + // Preserve existing options if --option flag was not specified + // If specified, completely replace existing options + options = def.Options + } + pref.Defaults[i].Options = options return nil } @@ -265,11 +271,31 @@ func (o *SetOptions) setAlias(pref *v1beta1.Preference, options []v1beta1.Comman return fmt.Errorf("alias %q already exists, use --overwrite to replace", o.AliasName) } + if len(options) == 0 { + // Preserve existing options if --option flag was not specified + // If specified, completely replace existing options + options = alias.Options + } + + prependArgs := o.PrependArgs + if len(prependArgs) == 0 { + // Preserve existing prependArgs if --prependarg flag was not specified + // If specified, completely replace existing prependArgs + prependArgs = alias.PrependArgs + } + + appendArgs := o.AppendArgs + if len(appendArgs) == 0 { + // Preserve existing appendArgs if --appendarg flag was not specified + // If specified, completely replace existing appendArgs + appendArgs = alias.AppendArgs + } + pref.Aliases[i] = v1beta1.AliasOverride{ Name: o.AliasName, Command: o.Command, - PrependArgs: o.PrependArgs, - AppendArgs: o.AppendArgs, + PrependArgs: prependArgs, + AppendArgs: appendArgs, Options: options, } return nil diff --git a/staging/src/k8s.io/kubectl/pkg/cmd/kuberc/set_test.go b/staging/src/k8s.io/kubectl/pkg/cmd/kuberc/set_test.go index 185a6c1b08f..49a5c45849b 100644 --- a/staging/src/k8s.io/kubectl/pkg/cmd/kuberc/set_test.go +++ b/staging/src/k8s.io/kubectl/pkg/cmd/kuberc/set_test.go @@ -141,6 +141,77 @@ defaults: }, }, }, + { + name: "overwrite without options preserves existing options", + existingKuberc: `apiVersion: kubectl.config.k8s.io/v1beta1 +kind: Preference +defaults: +- command: get + options: + - name: output + default: wide +`, + options: SetOptions{ + Section: sectionDefaults, + Command: "get", + Options: []string{}, // no options provided + Overwrite: true, + }, + expectedPref: &v1beta1.Preference{ + TypeMeta: metav1.TypeMeta{ + APIVersion: "kubectl.config.k8s.io/v1beta1", + Kind: "Preference", + }, + Defaults: []v1beta1.CommandDefaults{ + { + Command: "get", + Options: []v1beta1.CommandOptionDefault{ + { + Name: "output", + Default: "wide", + }, + }, + }, + }, + }, + }, + { + name: "overwrite with single option replaces all options", + existingKuberc: `apiVersion: kubectl.config.k8s.io/v1beta1 +kind: Preference +defaults: +- command: get + options: + - name: output + default: wide + - name: show-labels + default: "true" +`, + options: SetOptions{ + Section: sectionDefaults, + Command: "get", + Options: []string{"output=json"}, + Overwrite: true, + }, + expectedPref: &v1beta1.Preference{ + TypeMeta: metav1.TypeMeta{ + APIVersion: "kubectl.config.k8s.io/v1beta1", + Kind: "Preference", + }, + Defaults: []v1beta1.CommandDefaults{ + { + Command: "get", + Options: []v1beta1.CommandOptionDefault{ + { + Name: "output", + Default: "json", + }, + // show-labels option is overwritten and thus not present + }, + }, + }, + }, + }, { name: "error without overwrite", existingKuberc: `apiVersion: kubectl.config.k8s.io/v1beta1 @@ -357,6 +428,198 @@ aliases: }, }, }, + { + name: "overwrite alias without options preserves existing options", + existingKuberc: `apiVersion: kubectl.config.k8s.io/v1beta1 +kind: Preference +aliases: +- name: getn + command: get + options: + - name: output + default: wide +`, + options: SetOptions{ + Section: sectionAliases, + AliasName: "getn", + Command: "get", + Options: []string{}, // no options provided + Overwrite: true, + }, + expectedPref: &v1beta1.Preference{ + TypeMeta: metav1.TypeMeta{ + APIVersion: "kubectl.config.k8s.io/v1beta1", + Kind: "Preference", + }, + Aliases: []v1beta1.AliasOverride{ + { + Name: "getn", + Command: "get", + PrependArgs: nil, + Options: []v1beta1.CommandOptionDefault{ + { + Name: "output", + Default: "wide", + }, + }, + }, + }, + }, + }, + { + name: "overwrite alias without prependArgs preserves existing prependArgs", + existingKuberc: `apiVersion: kubectl.config.k8s.io/v1beta1 +kind: Preference +aliases: +- name: getn + command: get + prependArgs: + - nodes +`, + options: SetOptions{ + Section: sectionAliases, + AliasName: "getn", + Command: "get", + PrependArgs: []string{}, // no prependArgs provided + Overwrite: true, + }, + expectedPref: &v1beta1.Preference{ + TypeMeta: metav1.TypeMeta{ + APIVersion: "kubectl.config.k8s.io/v1beta1", + Kind: "Preference", + }, + Aliases: []v1beta1.AliasOverride{ + { + Name: "getn", + Command: "get", + PrependArgs: []string{"nodes"}, + Options: nil, + }, + }, + }, + }, + + { + name: "overwrite alias without appendArgs preserves existing appendArgs", + existingKuberc: `apiVersion: kubectl.config.k8s.io/v1beta1 +kind: Preference +aliases: +- name: getn + command: get + prependArgs: + - nodes + appendArgs: + - -- + - custom-arg +`, + options: SetOptions{ + Section: sectionAliases, + AliasName: "getn", + Command: "get", + AppendArgs: []string{}, // no appendArgs provided + Overwrite: true, + }, + expectedPref: &v1beta1.Preference{ + TypeMeta: metav1.TypeMeta{ + APIVersion: "kubectl.config.k8s.io/v1beta1", + Kind: "Preference", + }, + Aliases: []v1beta1.AliasOverride{ + { + Name: "getn", + Command: "get", + PrependArgs: []string{"nodes"}, + AppendArgs: []string{"--", "custom-arg"}, + Options: nil, + }, + }, + }, + }, + { + name: "update multiple fields simultaneously", + existingKuberc: `apiVersion: kubectl.config.k8s.io/v1beta1 +kind: Preference +aliases: +- name: getn + command: get + prependArgs: + - nodes + appendArgs: + - --watch + options: + - name: output + default: wide +`, + options: SetOptions{ + Section: sectionAliases, + AliasName: "getn", + Command: "get", + PrependArgs: []string{"pods"}, + Options: []string{"output=json"}, + AppendArgs: []string{}, // no appendArgs provided + Overwrite: true, + }, + expectedPref: &v1beta1.Preference{ + TypeMeta: metav1.TypeMeta{ + APIVersion: "kubectl.config.k8s.io/v1beta1", + Kind: "Preference", + }, + Aliases: []v1beta1.AliasOverride{ + { + Name: "getn", + Command: "get", + PrependArgs: []string{"pods"}, + AppendArgs: []string{"--watch"}, + Options: []v1beta1.CommandOptionDefault{ + { + Name: "output", + Default: "json", + }, + }, + }, + }, + }, + }, + { + name: "overwrite with single option replaces all options", + existingKuberc: `apiVersion: kubectl.config.k8s.io/v1beta1 +kind: Preference +aliases: +- name: getn + command: get + options: + - name: output + default: wide + - name: show-labels + default: "true" +`, + options: SetOptions{ + Section: sectionAliases, + AliasName: "getn", + Command: "get", + Options: []string{"output=json"}, + Overwrite: true, + }, + expectedPref: &v1beta1.Preference{ + TypeMeta: metav1.TypeMeta{ + APIVersion: "kubectl.config.k8s.io/v1beta1", + Kind: "Preference", + }, + Aliases: []v1beta1.AliasOverride{ + { + Name: "getn", + Command: "get", + Options: []v1beta1.CommandOptionDefault{ + { + Name: "output", + Default: "json", + }, + // show-labels option is overwritten and thus not present + }, + }, + }, + }, + }, { name: "error without overwrite", existingKuberc: `apiVersion: kubectl.config.k8s.io/v1beta1