Repository: kubernetes/kubernetes (language: go)

Issue:
[FG:InPlacePodVerticalScaling] kubectl subcommand to resize pod resources
### What would you like to be added?

In #128266, we are introducing a new /resize subresource to request pod resource resizing. It would be good add support for this in kubectl. 

Few options:

1. A new `resize` subcommand: 

```
kubectl resize pods <pod-name> -c <container> --cpu <cpu> --memory <memory>
```

2. support for `resize` subresource in existing commands like `kubectl patch` and `kubectl edit`:

```
kubectl patch pod pause \
     -p '{"spec":{"containers":[{"name":"pause", "resources": {"requests": {"cpu": "200m"}}}]}}' \
    --subresource=resize
```

```
kubectl edit pod pause --subresource=resize
```

### Why is this needed?

This will help us manually test this feature as well as making it user friendly to use the new subresource.


Discussion / hints:
/sig cli
/triage accepted
/assign @AnishShah 
I don't think we'd need a new command for this. I think, minor changes would required to support this in kubectl apply, patch and edit.


Fix patch:
diff --git a/staging/src/k8s.io/kubectl/pkg/cmd/apply/apply.go b/staging/src/k8s.io/kubectl/pkg/cmd/apply/apply.go
index 3b0b2667ed78e..6ea921eb91848 100644
--- a/staging/src/k8s.io/kubectl/pkg/cmd/apply/apply.go
+++ b/staging/src/k8s.io/kubectl/pkg/cmd/apply/apply.go
@@ -50,7 +50,6 @@ import (
 	"k8s.io/kubectl/pkg/util/i18n"
 	"k8s.io/kubectl/pkg/util/openapi"
 	"k8s.io/kubectl/pkg/util/prune"
-	"k8s.io/kubectl/pkg/util/slice"
 	"k8s.io/kubectl/pkg/util/templates"
 	"k8s.io/kubectl/pkg/validation"
 )
@@ -181,8 +180,6 @@ var (
 
 var ApplySetToolVersion = version.Get().GitVersion
 
-var supportedSubresources = []string{"status", "scale"}
-
 // NewApplyFlags returns a default ApplyFlags
 func NewApplyFlags(streams genericiooptions.IOStreams) *ApplyFlags {
 	return &ApplyFlags{
@@ -240,7 +237,7 @@ func (flags *ApplyFlags) AddFlags(cmd *cobra.Command) {
 	cmdutil.AddPruningFlags(cmd, &flags.Prune, &flags.PruneAllowlist, &flags.All, &flags.ApplySetRef)
 	cmd.Flags().BoolVar(&flags.Overwrite, "overwrite", flags.Overwrite, "Automatically resolve conflicts between the modified and live configuration by using values from the modified configuration")
 	cmd.Flags().BoolVar(&flags.OpenAPIPatch, "openapi-patch", flags.OpenAPIPatch, "If true, use openapi to calculate diff when the openapi presents and the resource can be found in the openapi spec. Otherwise, fall back to use baked-in types.")
-	cmdutil.AddSubresourceFlags(cmd, &flags.Subresource, "If specified, apply will operate on the subresource of the requested object.  Only allowed when using --server-side.", supportedSubresources...)
+	cmdutil.AddSubresourceFlags(cmd, &flags.Subresource, "If specified, apply will operate on the subresource of the requested object.  Only allowed when using --server-side.")
 }
 
 // ToOptions converts from CLI inputs to runtime inputs
@@ -445,9 +442,6 @@ func (o *ApplyOptions) Validate() error {
 			}
 		}
 	}
-	if len(o.Subresource) > 0 && !slice.ContainsString(supportedSubresources, o.Subresource, nil) {
-		return fmt.Errorf("invalid subresource value: %q. Must be one of %v", o.Subresource, supportedSubresources)
-	}
 	if len(o.Subresource) > 0 && !o.ServerSideApply {
 		return fmt.Errorf("--subresource can only be specified for --server-side")
 	}
diff --git a/staging/src/k8s.io/kubectl/pkg/cmd/edit/edit.go b/staging/src/k8s.io/kubectl/pkg/cmd/edit/edit.go
index 2e9228324a48d..6e896dcfdc7ba 100644
--- a/staging/src/k8s.io/kubectl/pkg/cmd/edit/edit.go
+++ b/staging/src/k8s.io/kubectl/pkg/cmd/edit/edit.go
@@ -103,6 +103,6 @@ func NewCmdEdit(f cmdutil.Factory, ioStreams genericiooptions.IOStreams) *cobra.
 		"Defaults to the line ending native to your platform.")
 	cmdutil.AddFieldManagerFlagVar(cmd, &o.FieldManager, "kubectl-edit")
 	cmdutil.AddApplyAnnotationVarFlags(cmd, &o.ApplyAnnotation)
-	cmdutil.AddSubresourceFlags(cmd, &o.Subresource, "If specified, edit will operate on the subresource of the requested object.", editor.SupportedSubresources...)
+	cmdutil.AddSubresourceFlags(cmd, &o.Subresource, "If specified, edit will operate on the subresource of the requested object.")
 	return cmd
 }
diff --git a/staging/src/k8s.io/kubectl/pkg/cmd/get/get.go b/staging/src/k8s.io/kubectl/pkg/cmd/get/get.go
index 4d0ff217fc4f3..f4652392d5858 100644
--- a/staging/src/k8s.io/kubectl/pkg/cmd/get/get.go
+++ b/staging/src/k8s.io/kubectl/pkg/cmd/get/get.go
@@ -47,7 +47,6 @@ import (
 	"k8s.io/kubectl/pkg/scheme"
 	"k8s.io/kubectl/pkg/util/i18n"
 	"k8s.io/kubectl/pkg/util/interrupt"
-	"k8s.io/kubectl/pkg/util/slice"
 	"k8s.io/kubectl/pkg/util/templates"
 	"k8s.io/utils/ptr"
 )
@@ -145,8 +144,6 @@ const (
 	useServerPrintColumns = "server-print"
 )
 
-var supportedSubresources = []string{"status", "scale"}
-
 // NewGetOptions returns a GetOptions with default chunk size 500.
 func NewGetOptions(parent string, streams genericiooptions.IOStreams) *GetOptions {
 	return &GetOptions{
@@ -192,7 +189,7 @@ func NewCmdGet(parent string, f cmdutil.Factory, streams genericiooptions.IOStre
 	cmdutil.AddFilenameOptionFlags(cmd, &o.FilenameOptions, "identifying the resource to get from a server.")
 	cmdutil.AddChunkSizeFlag(cmd, &o.ChunkSize)
 	cmdutil.AddLabelSelectorFlagVar(cmd, &o.LabelSelector)
-	cmdutil.AddSubresourceFlags(cmd, &o.Subresource, "If specified, gets the subresource of the requested object.", supportedSubresources...)
+	cmdutil.AddSubresourceFlags(cmd, &o.Subresource, "If specified, gets the subresource of the requested object.")
 	return cmd
 }
 
@@ -319,9 +316,6 @@ func (o *GetOptions) Validate() error {
 	if o.OutputWatchEvents && !(o.Watch || o.WatchOnly) {
 		return fmt.Errorf("--output-watch-events option can only be used with --watch or --watch-only")
 	}
-	if len(o.Subresource) > 0 && !slice.ContainsString(supportedSubresources, o.Subresource, nil) {
-		return fmt.Errorf("invalid subresource value: %q. Must be one of %v", o.Subresource, supportedSubresources)
-	}
 	return nil
 }
 
diff --git a/staging/src/k8s.io/kubectl/pkg/cmd/patch/patch.go b/staging/src/k8s.io/kubectl/pkg/cmd/patch/patch.go
index 594e9d088d47e..81340596c88ac 100644
--- a/staging/src/k8s.io/kubectl/pkg/cmd/patch/patch.go
+++ b/staging/src/k8s.io/kubectl/pkg/cmd/patch/patch.go
@@ -45,7 +45,6 @@ import (
 	"k8s.io/kubectl/pkg/scheme"
 	"k8s.io/kubectl/pkg/util/completion"
 	"k8s.io/kubectl/pkg/util/i18n"
-	"k8s.io/kubectl/pkg/util/slice"
 	"k8s.io/kubectl/pkg/util/templates"
 )
 
@@ -107,8 +106,6 @@ var (
 		kubectl patch deployment nginx-deployment --subresource='scale' --type='merge' -p '{"spec":{"replicas":2}}'`))
 )
 
-var supportedSubresources = []string{"status", "scale"}
-
 func NewPatchOptions(ioStreams genericiooptions.IOStreams) *PatchOptions {
 	return &PatchOptions{
 		RecordFlags: genericclioptions.NewRecordFlags(),
@@ -145,7 +142,7 @@ func NewCmdPatch(f cmdutil.Factory, ioStreams genericiooptions.IOStreams) *cobra
 	cmdutil.AddFilenameOptionFlags(cmd, &o.FilenameOptions, "identifying the resource to update")
 	cmd.Flags().BoolVar(&o.Local, "local", o.Local, "If true, patch will operate on the content of the file, not the server-side resource.")
 	cmdutil.AddFieldManagerFlagVar(cmd, &o.fieldManager, "kubectl-patch")
-	cmdutil.AddSubresourceFlags(cmd, &o.Subresource, "If specified, patch will operate on the subresource of the requested object.", supportedSubresources...)
+	cmdutil.AddSubresourceFlags(cmd, &o.Subresource, "If specified, patch will operate on the subresource of the requested object.")
 
 	return cmd
 }
@@ -200,9 +197,6 @@ func (o *PatchOptions) Validate() error {
 			return fmt.Errorf("--type must be one of %v, not %q", sets.StringKeySet(patchTypes).List(), o.PatchType)
 		}
 	}
-	if len(o.Subresource) > 0 && !slice.ContainsString(supportedSubresources, o.Subresource, nil) {
-		return fmt.Errorf("invalid subresource value: %q. Must be one of %v", o.Subresource, supportedSubresources)
-	}
 	return nil
 }
 
diff --git a/staging/src/k8s.io/kubectl/pkg/cmd/replace/replace.go b/staging/src/k8s.io/kubectl/pkg/cmd/replace/replace.go
index 0893847d1864f..b8989762a402a 100644
--- a/staging/src/k8s.io/kubectl/pkg/cmd/replace/replace.go
+++ b/staging/src/k8s.io/kubectl/pkg/cmd/replace/replace.go
@@ -40,7 +40,6 @@ import (
 	"k8s.io/kubectl/pkg/scheme"
 	"k8s.io/kubectl/pkg/util"
 	"k8s.io/kubectl/pkg/util/i18n"
-	"k8s.io/kubectl/pkg/util/slice"
 	"k8s.io/kubectl/pkg/util/templates"
 	"k8s.io/kubectl/pkg/validation"
 )
@@ -68,8 +67,6 @@ var (
 		kubectl replace --force -f ./pod.json`))
 )
 
-var supportedSubresources = []string{"status", "scale"}
-
 type ReplaceOptions struct {
 	PrintFlags  *genericclioptions.PrintFlags
 	RecordFlags *genericclioptions.RecordFlags
@@ -136,7 +133,7 @@ func NewCmdReplace(f cmdutil.Factory, streams genericiooptions.IOStreams) *cobra
 
 	cmd.Flags().StringVar(&o.Raw, "raw", o.Raw, "Raw URI to PUT to the server.  Uses the transport specified by the kubeconfig file.")
 	cmdutil.AddFieldManagerFlagVar(cmd, &o.fieldManager, "kubectl-replace")
-	cmdutil.AddSubresourceFlags(cmd, &o.Subresource, "If specified, replace will operate on the subresource of the requested object.", supportedSubresources...)
+	cmdutil.AddSubresourceFlags(cmd, &o.Subresource, "If specified, replace will operate on the subresource of the requested object.")
 
 	return cmd
 }
@@ -249,10 +246,6 @@ func (o *ReplaceOptions) Validate() error {
 		}
 	}
 
-	if len(o.Subresource) > 0 && !slice.ContainsString(supportedSubresources, o.Subresource, nil) {
-		return fmt.Errorf("invalid subresource value: %q. Must be one of %v", o.Subresource, supportedSubresources)
-	}
-
 	return nil
 }
 
diff --git a/staging/src/k8s.io/kubectl/pkg/cmd/util/editor/editoptions.go b/staging/src/k8s.io/kubectl/pkg/cmd/util/editor/editoptions.go
index 2f60808f4b5be..416a2306c62f5 100644
--- a/staging/src/k8s.io/kubectl/pkg/cmd/util/editor/editoptions.go
+++ b/staging/src/k8s.io/kubectl/pkg/cmd/util/editor/editoptions.go
@@ -52,11 +52,8 @@ import (
 	"k8s.io/kubectl/pkg/cmd/util/editor/crlf"
 	"k8s.io/kubectl/pkg/scheme"
 	"k8s.io/kubectl/pkg/util"
-	"k8s.io/kubectl/pkg/util/slice"
 )
 
-var SupportedSubresources = []string{"status"}
-
 // EditOptions contains all the options for running edit cli command.
 type EditOptions struct {
 	resource.FilenameOptions
@@ -230,9 +227,6 @@ func (o *EditOptions) Complete(f cmdutil.Factory, args []string, cmd *cobra.Comm
 
 // Validate checks the EditOptions to see if there is sufficient information to run the command.
 func (o *EditOptions) Validate() error {
-	if len(o.Subresource) > 0 && !slice.ContainsString(SupportedSubresources, o.Subresource, nil) {
-		return fmt.Errorf("invalid subresource value: %q. Must be one of %v", o.Subresource, SupportedSubresources)
-	}
 	return nil
 }
 
diff --git a/staging/src/k8s.io/kubectl/pkg/cmd/util/helpers.go b/staging/src/k8s.io/kubectl/pkg/cmd/util/helpers.go
index d20c3226df0c5..653aa78409ba9 100644
--- a/staging/src/k8s.io/kubectl/pkg/cmd/util/helpers.go
+++ b/staging/src/k8s.io/kubectl/pkg/cmd/util/helpers.go
@@ -537,10 +537,11 @@ func AddPruningFlags(cmd *cobra.Command, prune *bool, pruneAllowlist *[]string,
 	}
 }
 
-func AddSubresourceFlags(cmd *cobra.Command, subresource *string, usage string, allowedSubresources ...string) {
-	cmd.Flags().StringVar(subresource, "subresource", "", fmt.Sprintf("%s Must be one of %v. This flag is beta and may change in the future.", usage, allowedSubresources))
+func AddSubresourceFlags(cmd *cobra.Command, subresource *string, usage string) {
+	cmd.Flags().StringVar(subresource, "subresource", "", fmt.Sprintf("%s This flag is beta and may change in the future.", usage))
 	CheckErr(cmd.RegisterFlagCompletionFunc("subresource", func(*cobra.Command, []string, string) ([]string, cobra.ShellCompDirective) {
-		return allowedSubresources, cobra.ShellCompDirectiveNoFileComp
+		var commonSubresources = []string{"status", "scale", "resize"}
+		return commonSubresources, cobra.ShellCompDirectiveNoFileComp
 	}))
 }
 


Test patch: