add --subresource to kubectl apply

This commit is contained in:
David Eads 2024-09-25 17:23:09 -04:00
parent 3582dce115
commit 55ba8b2cbb
3 changed files with 37 additions and 7 deletions

11
hack/testdata/pod-apply-status.yaml vendored Normal file
View File

@ -0,0 +1,11 @@
apiVersion: v1
kind: Pod
metadata:
name: test-pod
status:
conditions:
- type: example.io/Foo
status: "True"
message: message
reason: reason

View File

@ -50,6 +50,7 @@ import (
"k8s.io/kubectl/pkg/util/i18n" "k8s.io/kubectl/pkg/util/i18n"
"k8s.io/kubectl/pkg/util/openapi" "k8s.io/kubectl/pkg/util/openapi"
"k8s.io/kubectl/pkg/util/prune" "k8s.io/kubectl/pkg/util/prune"
"k8s.io/kubectl/pkg/util/slice"
"k8s.io/kubectl/pkg/util/templates" "k8s.io/kubectl/pkg/util/templates"
"k8s.io/kubectl/pkg/validation" "k8s.io/kubectl/pkg/validation"
) )
@ -71,6 +72,7 @@ type ApplyFlags struct {
All bool All bool
Overwrite bool Overwrite bool
OpenAPIPatch bool OpenAPIPatch bool
Subresource string
PruneAllowlist []string PruneAllowlist []string
@ -97,6 +99,7 @@ type ApplyOptions struct {
All bool All bool
Overwrite bool Overwrite bool
OpenAPIPatch bool OpenAPIPatch bool
Subresource string
ValidationDirective string ValidationDirective string
Validator validation.Schema Validator validation.Schema
@ -178,6 +181,8 @@ var (
var ApplySetToolVersion = version.Get().GitVersion var ApplySetToolVersion = version.Get().GitVersion
var supportedSubresources = []string{"status", "scale"}
// NewApplyFlags returns a default ApplyFlags // NewApplyFlags returns a default ApplyFlags
func NewApplyFlags(streams genericiooptions.IOStreams) *ApplyFlags { func NewApplyFlags(streams genericiooptions.IOStreams) *ApplyFlags {
return &ApplyFlags{ return &ApplyFlags{
@ -235,6 +240,7 @@ func (flags *ApplyFlags) AddFlags(cmd *cobra.Command) {
cmdutil.AddPruningFlags(cmd, &flags.Prune, &flags.PruneAllowlist, &flags.All, &flags.ApplySetRef) 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.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.") 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...)
} }
// ToOptions converts from CLI inputs to runtime inputs // ToOptions converts from CLI inputs to runtime inputs
@ -356,6 +362,7 @@ func (flags *ApplyFlags) ToOptions(f cmdutil.Factory, cmd *cobra.Command, baseNa
All: flags.All, All: flags.All,
Overwrite: flags.Overwrite, Overwrite: flags.Overwrite,
OpenAPIPatch: flags.OpenAPIPatch, OpenAPIPatch: flags.OpenAPIPatch,
Subresource: flags.Subresource,
Recorder: recorder, Recorder: recorder,
Namespace: namespace, Namespace: namespace,
@ -438,6 +445,12 @@ 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")
}
return nil return nil
} }
@ -577,7 +590,9 @@ func (o *ApplyOptions) applyOneObject(info *resource.Info) error {
options := metav1.PatchOptions{ options := metav1.PatchOptions{
Force: &o.ForceConflicts, Force: &o.ForceConflicts,
} }
obj, err := helper.Patch( obj, err := helper.
WithSubresource(o.Subresource).
Patch(
info.Namespace, info.Namespace,
info.Name, info.Name,
types.ApplyPatchType, types.ApplyPatchType,

View File

@ -413,6 +413,10 @@ run_kubectl_server_side_apply_tests() {
kubectl apply --server-side --field-manager=my-field-manager --force-conflicts -f hack/testdata/pod.yaml "${kube_flags[@]:?}" kubectl apply --server-side --field-manager=my-field-manager --force-conflicts -f hack/testdata/pod.yaml "${kube_flags[@]:?}"
output_message=$(kubectl get -f hack/testdata/pod.yaml -o=jsonpath='{.metadata.managedFields[*].manager}' "${kube_flags[@]:?}" 2>&1) output_message=$(kubectl get -f hack/testdata/pod.yaml -o=jsonpath='{.metadata.managedFields[*].manager}' "${kube_flags[@]:?}" 2>&1)
kube::test::if_has_string "${output_message}" 'my-field-manager' kube::test::if_has_string "${output_message}" 'my-field-manager'
# can add pod condition
kubectl apply --server-side --subresource=status --field-manager=my-field-manager -f hack/testdata/pod-apply-status.yaml "${kube_flags[@]:?}"
output_message=$(kubectl get -f hack/testdata/pod.yaml -o=jsonpath='{.status.conditions[*].type}' "${kube_flags[@]:?}" 2>&1)
kube::test::if_has_string "${output_message}" 'example.io/Foo'
# Clean up # Clean up
kubectl delete pods test-pod "${kube_flags[@]:?}" kubectl delete pods test-pod "${kube_flags[@]:?}"