github.com/buildtool/build-tools@v0.2.29-0.20240322150259-6a1d0a553c23/pkg/kubectl/kubectl_test.go (about)

     1  // MIT License
     2  //
     3  // Copyright (c) 2018 buildtool
     4  //
     5  // Permission is hereby granted, free of charge, to any person obtaining a copy
     6  // of this software and associated documentation files (the "Software"), to deal
     7  // in the Software without restriction, including without limitation the rights
     8  // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
     9  // copies of the Software, and to permit persons to whom the Software is
    10  // furnished to do so, subject to the following conditions:
    11  //
    12  // The above copyright notice and this permission notice shall be included in all
    13  // copies or substantial portions of the Software.
    14  //
    15  // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    16  // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    17  // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    18  // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    19  // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    20  // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
    21  // SOFTWARE.
    22  
    23  package kubectl
    24  
    25  import (
    26  	"encoding/base64"
    27  	"errors"
    28  	"fmt"
    29  	"io"
    30  	"os"
    31  	"path/filepath"
    32  	"testing"
    33  	"time"
    34  
    35  	"github.com/apex/log"
    36  	"github.com/spf13/cobra"
    37  	"github.com/stretchr/testify/assert"
    38  	mocks "gitlab.com/unboundsoftware/apex-mocks"
    39  	"k8s.io/kubectl/pkg/cmd/util"
    40  
    41  	"github.com/buildtool/build-tools/pkg"
    42  	"github.com/buildtool/build-tools/pkg/cli"
    43  	"github.com/buildtool/build-tools/pkg/config"
    44  )
    45  
    46  func TestNew(t *testing.T) {
    47  	logMock := mocks.New()
    48  	log.SetHandler(logMock)
    49  	log.SetLevel(log.InfoLevel)
    50  	k := New(&config.Target{Context: "missing", Namespace: "dev"})
    51  
    52  	assert.Equal(t, "missing", k.(*kubectl).args["context"])
    53  	assert.Equal(t, "dev", k.(*kubectl).args["namespace"])
    54  	logMock.Check(t, []string{})
    55  }
    56  
    57  func TestNew_NoNamespace(t *testing.T) {
    58  	logMock := mocks.New()
    59  	log.SetHandler(logMock)
    60  	log.SetLevel(log.DebugLevel)
    61  
    62  	calls = [][]string{}
    63  	newKubectlCmd = mockCmd
    64  	tempDir, _ := os.MkdirTemp(os.TempDir(), "build-tools")
    65  
    66  	k := &kubectl{args: map[string]string{"context": "missing"}, tempDir: tempDir, out: cli.NewWriter(logMock)}
    67  
    68  	err := k.Apply("")
    69  	assert.NoError(t, err)
    70  	assert.Equal(t, 1, len(calls))
    71  	assert.Equal(t, []string{"apply", "--context", "missing", "--file", fmt.Sprintf("%s/content.yaml", tempDir), "--v=6", "--server-side", "--force-conflicts"}, calls[0])
    72  	logMock.Check(t, []string{})
    73  }
    74  func TestNew_NoContext(t *testing.T) {
    75  	logMock := mocks.New()
    76  	log.SetHandler(logMock)
    77  	log.SetLevel(log.InfoLevel)
    78  	calls = [][]string{}
    79  	newKubectlCmd = mockCmd
    80  	tempDir, _ := os.MkdirTemp(os.TempDir(), "build-tools")
    81  
    82  	k := &kubectl{args: map[string]string{"namespace": "namespace"}, tempDir: tempDir, out: cli.NewWriter(logMock)}
    83  
    84  	err := k.Apply("")
    85  	assert.NoError(t, err)
    86  	assert.Equal(t, 1, len(calls))
    87  	assert.Equal(t, []string{"apply", "--namespace", "namespace", "--file", fmt.Sprintf("%s/content.yaml", tempDir), "--server-side", "--force-conflicts"}, calls[0])
    88  	logMock.Check(t, []string{})
    89  }
    90  
    91  func TestKubectl_Apply(t *testing.T) {
    92  	logMock := mocks.New()
    93  	log.SetHandler(logMock)
    94  	log.SetLevel(log.InfoLevel)
    95  	calls = [][]string{}
    96  	newKubectlCmd = mockCmd
    97  	tempDir, _ := os.MkdirTemp(os.TempDir(), "build-tools")
    98  
    99  	k := &kubectl{args: map[string]string{"context": "missing", "namespace": "default"}, tempDir: tempDir, out: cli.NewWriter(logMock)}
   100  
   101  	err := k.Apply("")
   102  	assert.NoError(t, err)
   103  	assert.Equal(t, 1, len(calls))
   104  	assert.Equal(t, []string{"apply", "--context", "missing", "--namespace", "default", "--file", fmt.Sprintf("%s/content.yaml", tempDir), "--server-side", "--force-conflicts"}, calls[0])
   105  	logMock.Check(t, []string{})
   106  }
   107  
   108  func TestKubectl_UnableToCreateTempDir(t *testing.T) {
   109  	logMock := mocks.New()
   110  	log.SetHandler(logMock)
   111  	log.SetLevel(log.InfoLevel)
   112  	newKubectlCmd = mockCmd
   113  
   114  	k := &kubectl{args: nil, tempDir: "/missing", out: cli.NewWriter(logMock)}
   115  
   116  	err := k.Apply("")
   117  	assert.EqualError(t, err, "open /missing/content.yaml: no such file or directory")
   118  	logMock.Check(t, []string{})
   119  }
   120  
   121  func TestKubectl_Target(t *testing.T) {
   122  	logMock := mocks.New()
   123  	log.SetHandler(logMock)
   124  	log.SetLevel(log.InfoLevel)
   125  	env := &config.Target{Context: "missing", Namespace: ""}
   126  	k := New(env)
   127  
   128  	assert.Equal(t, "", k.(*kubectl).args["namespace"])
   129  	logMock.Check(t, []string{})
   130  }
   131  
   132  func TestKubectl_DeploymentExistsTrue(t *testing.T) {
   133  	logMock := mocks.New()
   134  	log.SetHandler(logMock)
   135  	log.SetLevel(log.InfoLevel)
   136  	calls = [][]string{}
   137  	cmdError = nil
   138  	o := `NAME          READY   UP-TO-DATE   AVAILABLE   AGE
   139  api           1/1     1            1           2d11h
   140  `
   141  	cmdOut = &o
   142  	newKubectlCmd = mockCmd
   143  
   144  	k := New(&config.Target{Context: "missing", Namespace: "default"})
   145  
   146  	result := k.DeploymentExists("image")
   147  	assert.True(t, result)
   148  	assert.Equal(t, 1, len(calls))
   149  	assert.Equal(t, []string{"get", "deployment", "image", "--context", "missing", "--namespace", "default", "--ignore-not-found"}, calls[0])
   150  	logMock.Check(t, []string{})
   151  }
   152  
   153  func TestKubectl_DeploymentExistsFalse(t *testing.T) {
   154  	logMock := mocks.New()
   155  	log.SetHandler(logMock)
   156  	log.SetLevel(log.DebugLevel)
   157  	calls = [][]string{}
   158  	e := "deployment not found"
   159  	cmdError = &e
   160  	newKubectlCmd = mockCmd
   161  
   162  	k := New(&config.Target{Context: "missing", Namespace: "default"})
   163  
   164  	result := k.DeploymentExists("image")
   165  	assert.False(t, result)
   166  	assert.Equal(t, 1, len(calls))
   167  	assert.Equal(t, []string{"get", "deployment", "image", "--context", "missing", "--namespace", "default", "--ignore-not-found", "--v=6"}, calls[0])
   168  	logMock.Check(t, []string{"debug: kubectl --context missing --namespace default --v=6 get deployment image --ignore-not-found\n"})
   169  }
   170  
   171  func TestKubectl_RolloutStatusSuccess(t *testing.T) {
   172  	logMock := mocks.New()
   173  	log.SetHandler(logMock)
   174  	log.SetLevel(log.InfoLevel)
   175  	calls = [][]string{}
   176  	cmdOut = nil
   177  	cmdError = nil
   178  	newKubectlCmd = mockCmd
   179  
   180  	k := New(&config.Target{Context: "missing", Namespace: "other"})
   181  
   182  	result := k.RolloutStatus("image", "2m")
   183  	assert.True(t, result)
   184  	assert.Equal(t, 1, len(calls))
   185  	assert.Equal(t, []string{"rollout", "status", "deployment", "image", "--context", "missing", "--namespace", "other", "--timeout", "2m0s"}, calls[0])
   186  	logMock.Check(t, []string{})
   187  }
   188  
   189  func TestKubectl_RolloutStatusFailure(t *testing.T) {
   190  	logMock := mocks.New()
   191  	log.SetHandler(logMock)
   192  	log.SetLevel(log.InfoLevel)
   193  	calls = [][]string{}
   194  	e := "rollout failed"
   195  	cmdError = &e
   196  	newKubectlCmd = mockCmd
   197  
   198  	k := New(&config.Target{Context: "missing", Namespace: "default"})
   199  
   200  	result := k.RolloutStatus("image", "2m")
   201  	assert.False(t, result)
   202  	assert.Equal(t, 1, len(calls))
   203  	assert.Equal(t, []string{"rollout", "status", "deployment", "image", "--context", "missing", "--namespace", "default", "--timeout", "2m0s"}, calls[0])
   204  	logMock.Check(t, []string{})
   205  }
   206  
   207  func TestKubectl_RolloutStatusFatal(t *testing.T) {
   208  	logMock := mocks.New()
   209  	log.SetHandler(logMock)
   210  	log.SetLevel(log.InfoLevel)
   211  	calls = [][]string{}
   212  	e := "rollout failed"
   213  	cmdError = &e
   214  	fatal = true
   215  	defer func() { fatal = false }()
   216  
   217  	newKubectlCmd = mockCmd
   218  
   219  	k := New(&config.Target{Context: "missing", Namespace: "default"})
   220  
   221  	result := k.RolloutStatus("image", "3m")
   222  	assert.False(t, result)
   223  	assert.Equal(t, 1, len(calls))
   224  	assert.Equal(t, []string{"rollout", "status", "deployment", "image", "--context", "missing", "--namespace", "default", "--timeout", "3m0s"}, calls[0])
   225  	logMock.Check(t, []string{})
   226  }
   227  
   228  func TestKubectl_KubeconfigSet(t *testing.T) {
   229  	yaml := `contexts:
   230  - context:
   231      cluster: k8s.prod
   232      user: user@example.org
   233  `
   234  	defer pkg.SetEnv(envKubeconfigContent, yaml)()
   235  	k := New(&config.Target{})
   236  
   237  	kubeconfigFile := filepath.Join(k.(*kubectl).tempDir, "kubeconfig")
   238  	fileContent, err := os.ReadFile(kubeconfigFile)
   239  	assert.NoError(t, err)
   240  	assert.Equal(t, "contexts:\n- context:\n    cluster: k8s.prod\n    user: user@example.org\n", string(fileContent))
   241  	assert.Equal(t, kubeconfigFile, k.(*kubectl).args["kubeconfig"])
   242  	k.Cleanup()
   243  }
   244  
   245  func TestKubectl_KubeconfigSetToEmptyValue(t *testing.T) {
   246  	yaml := ``
   247  	defer pkg.SetEnv(envKubeconfigContent, yaml)()
   248  	k := New(&config.Target{})
   249  
   250  	assert.Equal(t, "", k.(*kubectl).args["kubeconfig"])
   251  	k.Cleanup()
   252  }
   253  
   254  func TestKubectl_KubeconfigBase64Set(t *testing.T) {
   255  	yaml := `contexts:
   256  - context:
   257      cluster: k8s.prod
   258      user: user@example.org
   259  `
   260  	defer pkg.SetEnv(envKubeconfigContent, base64.StdEncoding.EncodeToString([]byte(yaml)))()
   261  	k := New(&config.Target{})
   262  
   263  	kubeconfigFile := filepath.Join(k.(*kubectl).tempDir, "kubeconfig")
   264  	fileContent, err := os.ReadFile(kubeconfigFile)
   265  	assert.NoError(t, err)
   266  	assert.Equal(t, "contexts:\n- context:\n    cluster: k8s.prod\n    user: user@example.org\n", string(fileContent))
   267  	assert.Equal(t, kubeconfigFile, k.(*kubectl).args["kubeconfig"])
   268  	k.Cleanup()
   269  }
   270  
   271  func TestKubectl_KubeconfigExistingFile(t *testing.T) {
   272  
   273  	name, _ := os.CreateTemp(os.TempDir(), "kubecontent")
   274  	defer func() {
   275  		_ = os.Remove(name.Name())
   276  	}()
   277  
   278  	k := New(&config.Target{Kubeconfig: name.Name()})
   279  	assert.Equal(t, name.Name(), k.(*kubectl).args["kubeconfig"])
   280  	k.Cleanup()
   281  }
   282  
   283  func TestKubectl_DeploymentEvents_Error(t *testing.T) {
   284  	logMock := mocks.New()
   285  	log.SetHandler(logMock)
   286  	log.SetLevel(log.InfoLevel)
   287  	calls = [][]string{}
   288  	newKubectlCmd = mockCmd
   289  	e := "deployment not found"
   290  	cmdError = &e
   291  
   292  	k := New(&config.Target{Context: "missing", Namespace: "default"})
   293  
   294  	result := k.DeploymentEvents("image")
   295  	assert.Equal(t, "deployment not found", result)
   296  	assert.Equal(t, 1, len(calls))
   297  	assert.Equal(t, []string{"describe", "deployment", "image", "--context", "missing", "--namespace", "default", "--show-events", "true"}, calls[0])
   298  	logMock.Check(t, []string{})
   299  }
   300  
   301  func TestKubectl_DeploymentEvents_NoEvents(t *testing.T) {
   302  	logMock := mocks.New()
   303  	log.SetHandler(logMock)
   304  	log.SetLevel(log.InfoLevel)
   305  	calls = [][]string{}
   306  	cmdError = nil
   307  	newKubectlCmd = mockCmd
   308  	e := `
   309  Name:               gpe-core
   310  Namespace:          default
   311  Events:          <none>
   312  `
   313  	cmdOut = &e
   314  
   315  	k := New(&config.Target{Context: "missing", Namespace: "default"})
   316  
   317  	result := k.DeploymentEvents("image")
   318  	assert.Equal(t, "", result)
   319  	assert.Equal(t, 1, len(calls))
   320  	assert.Equal(t, []string{"describe", "deployment", "image", "--context", "missing", "--namespace", "default", "--show-events", "true"}, calls[0])
   321  	logMock.Check(t, []string{})
   322  }
   323  
   324  func TestKubectl_DeploymentEvents_SomeEvents(t *testing.T) {
   325  	logMock := mocks.New()
   326  	log.SetHandler(logMock)
   327  	log.SetLevel(log.InfoLevel)
   328  	calls = [][]string{}
   329  	cmdError = nil
   330  	newKubectlCmd = mockCmd
   331  	e := `
   332  Name:               gpe-core
   333  Namespace:          default
   334  Events:
   335    Type    Reason             Age   From                   Message
   336    ----    ------             ----  ----                   -------
   337    Normal  ScalingReplicaSet  9m    deployment-controller  Scaled up replica set gpe-core-5cb459ff7d to 1
   338    Normal  ScalingReplicaSet  9m    deployment-controller  Scaled down replica set gpe-core-7fc44679dc to 0
   339    Normal  ScalingReplicaSet  61s   deployment-controller  Scaled up replica set gpe-core-c8798ff88 to 1
   340    Normal  ScalingReplicaSet  61s   deployment-controller  Scaled down replica set gpe-core-5cb459ff7d to 0
   341  `
   342  	cmdOut = &e
   343  
   344  	k := New(&config.Target{Context: "missing", Namespace: "default"})
   345  
   346  	result := k.DeploymentEvents("image")
   347  	assert.Equal(t, "Events:\n  Type    Reason             Age   From                   Message\n  ----    ------             ----  ----                   -------\n  Normal  ScalingReplicaSet  9m    deployment-controller  Scaled up replica set gpe-core-5cb459ff7d to 1\n  Normal  ScalingReplicaSet  9m    deployment-controller  Scaled down replica set gpe-core-7fc44679dc to 0\n  Normal  ScalingReplicaSet  61s   deployment-controller  Scaled up replica set gpe-core-c8798ff88 to 1\n  Normal  ScalingReplicaSet  61s   deployment-controller  Scaled down replica set gpe-core-5cb459ff7d to 0\n", result)
   348  	assert.Equal(t, 1, len(calls))
   349  	assert.Equal(t, []string{"describe", "deployment", "image", "--context", "missing", "--namespace", "default", "--show-events", "true"}, calls[0])
   350  	logMock.Check(t, []string{})
   351  }
   352  
   353  func TestKubectl_PodEvents_Error(t *testing.T) {
   354  	logMock := mocks.New()
   355  	log.SetHandler(logMock)
   356  	log.SetLevel(log.InfoLevel)
   357  	calls = [][]string{}
   358  	newKubectlCmd = mockCmd
   359  	e := "pod not found"
   360  	cmdError = &e
   361  
   362  	k := New(&config.Target{Context: "missing", Namespace: "default"})
   363  
   364  	result := k.PodEvents("image")
   365  	assert.Equal(t, "pod not found", result)
   366  	assert.Equal(t, 1, len(calls))
   367  	assert.Equal(t, []string{"describe", "pods", "--context", "missing", "--namespace", "default", "--show-events", "true", "--selector", "app=image"}, calls[0])
   368  	logMock.Check(t, []string{})
   369  }
   370  
   371  func TestKubectl_PodEvents_NoEvents(t *testing.T) {
   372  	logMock := mocks.New()
   373  	log.SetHandler(logMock)
   374  	log.SetLevel(log.InfoLevel)
   375  	calls = [][]string{}
   376  	cmdError = nil
   377  	newKubectlCmd = mockCmd
   378  	e := `
   379  Name:               gpe-core
   380  Namespace:          default
   381  Events:          <none>
   382  `
   383  	cmdOut = &e
   384  
   385  	k := New(&config.Target{Context: "missing", Namespace: "default"})
   386  
   387  	result := k.PodEvents("image")
   388  	assert.Equal(t, "", result)
   389  	assert.Equal(t, 1, len(calls))
   390  	assert.Equal(t, []string{"describe", "pods", "--context", "missing", "--namespace", "default", "--show-events", "true", "--selector", "app=image"}, calls[0])
   391  	logMock.Check(t, []string{})
   392  }
   393  
   394  func TestKubectl_PodEvents_SomeEvents(t *testing.T) {
   395  	logMock := mocks.New()
   396  	log.SetHandler(logMock)
   397  	log.SetLevel(log.InfoLevel)
   398  	calls = [][]string{}
   399  	cmdError = nil
   400  	newKubectlCmd = mockCmd
   401  	e := `
   402  Events:
   403    Type     Reason     Age                From                                                 Message
   404    ----     ------     ----               ----                                                 -------
   405    Normal   Scheduled  61s                default-scheduler                                    Successfully assigned dev/gpe-core-c8798ff88-674tr to some-ip-somewhere
   406    Normal   Pulling    10s (x4 over 60s)  kubelet, some-ip-somewhere                           pulling image "quay.io/somewhere/gpe-core:9cdb0243e82b9bfdf037627d9d59cbfcbf55406c"
   407    Normal   Pulled     9s (x4 over 57s)   kubelet, some-ip-somewhere                           Successfully pulled image "quay.io/somewhere/gpe-core:9cdb0243e82b9bfdf037627d9d59cbfcbf55406c"
   408    Normal   Created    8s (x4 over 57s)   kubelet, some-ip-somewhere                           Created container
   409    Normal   Started    8s (x4 over 57s)   kubelet, some-ip-somewhere                           Started container
   410    Warning  BackOff    8s (x5 over 54s)   kubelet, some-ip-somewhere                           Back-off restarting failed container`
   411  	cmdOut = &e
   412  
   413  	k := New(&config.Target{Context: "missing", Namespace: "default"})
   414  
   415  	result := k.PodEvents("image")
   416  	assert.Equal(t, "Events:\n  Type     Reason     Age                From                                                 Message\n  ----     ------     ----               ----                                                 -------\n  Normal   Scheduled  61s                default-scheduler                                    Successfully assigned dev/gpe-core-c8798ff88-674tr to some-ip-somewhere\n  Normal   Pulling    10s (x4 over 60s)  kubelet, some-ip-somewhere                           pulling image \"quay.io/somewhere/gpe-core:9cdb0243e82b9bfdf037627d9d59cbfcbf55406c\"\n  Normal   Pulled     9s (x4 over 57s)   kubelet, some-ip-somewhere                           Successfully pulled image \"quay.io/somewhere/gpe-core:9cdb0243e82b9bfdf037627d9d59cbfcbf55406c\"\n  Normal   Created    8s (x4 over 57s)   kubelet, some-ip-somewhere                           Created container\n  Normal   Started    8s (x4 over 57s)   kubelet, some-ip-somewhere                           Started container\n  Warning  BackOff    8s (x5 over 54s)   kubelet, some-ip-somewhere                           Back-off restarting failed container\n", result)
   417  	assert.Equal(t, 1, len(calls))
   418  	assert.Equal(t, []string{"describe", "pods", "--context", "missing", "--namespace", "default", "--show-events", "true", "--selector", "app=image"}, calls[0])
   419  	logMock.Check(t, []string{})
   420  }
   421  
   422  var calls [][]string
   423  var cmdError *string
   424  var cmdOut *string
   425  var fatal = false
   426  
   427  func mockCmd(_ io.Reader, out, _ io.Writer, args []string) *cobra.Command {
   428  	var ctx, ns, file *string
   429  	var timeout *time.Duration
   430  	var showEvents *bool
   431  	var ignoreNotFound *bool
   432  	var selector *string
   433  	var kubeconfig *string
   434  	var verbose *string
   435  	var serverSide *bool
   436  	var forceConflicts *bool
   437  
   438  	cmd := cobra.Command{
   439  		Use: "kubectl",
   440  		Args: func(cmd *cobra.Command, args []string) error {
   441  			var call = args
   442  			if *ctx != "" {
   443  				call = append(call, "--context", *ctx)
   444  			}
   445  			if *kubeconfig != "" {
   446  				call = append(call, "--kubeconfig", *kubeconfig)
   447  			}
   448  			if *ns != "" {
   449  				call = append(call, "--namespace", *ns)
   450  			}
   451  			if *file != "" {
   452  				call = append(call, "--file", *file)
   453  			}
   454  			if *timeout != time.Duration(0) {
   455  				call = append(call, "--timeout", timeout.String())
   456  			}
   457  			if *showEvents {
   458  				call = append(call, "--show-events", "true")
   459  			}
   460  			if *ignoreNotFound {
   461  				call = append(call, "--ignore-not-found")
   462  			}
   463  			if *verbose != "0" {
   464  				call = append(call, fmt.Sprintf("--v=%s", *verbose))
   465  			}
   466  			if *selector != "" {
   467  				call = append(call, "--selector", fmt.Sprintf("%v", *selector))
   468  			}
   469  			if *serverSide {
   470  				call = append(call, "--server-side")
   471  			}
   472  			if *forceConflicts {
   473  				call = append(call, "--force-conflicts")
   474  			}
   475  			calls = append(calls, call)
   476  			return nil
   477  		},
   478  		RunE: func(cmd *cobra.Command, args []string) error {
   479  			if fatal {
   480  				util.CheckErr(errors.New(*cmdError))
   481  			}
   482  			if cmdError != nil {
   483  				return errors.New(*cmdError)
   484  			}
   485  			if cmdOut != nil {
   486  				_, _ = out.Write([]byte(*cmdOut))
   487  			}
   488  			return nil
   489  		},
   490  	}
   491  
   492  	ctx = cmd.Flags().StringP("context", "c", "", "")
   493  	ns = cmd.Flags().StringP("namespace", "n", "", "")
   494  	file = cmd.Flags().StringP("filename", "f", "", "")
   495  	timeout = cmd.Flags().DurationP("timeout", "t", 0*time.Second, "")
   496  	showEvents = cmd.Flags().BoolP("show-events", "", false, "")
   497  	ignoreNotFound = cmd.Flags().BoolP("ignore-not-found", "", false, "")
   498  	selector = cmd.Flags().StringP("selector", "l", "", "")
   499  	kubeconfig = cmd.Flags().StringP("kubeconfig", "", "", "")
   500  	verbose = cmd.Flags().StringP("v", "v", "0", "")
   501  	serverSide = cmd.Flags().BoolP("server-side", "", false, "")
   502  	forceConflicts = cmd.Flags().BoolP("force-conflicts", "", false, "")
   503  	cmd.SetArgs(args)
   504  	return &cmd
   505  }