func RunPatch(f cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []string, options *PatchOptions) error { switch { case options.Local && len(args) != 0: return fmt.Errorf("cannot specify --local and server resources") } cmdNamespace, enforceNamespace, err := f.DefaultNamespace() if err != nil { return err } patchType := api.StrategicMergePatchType patchTypeString := strings.ToLower(cmdutil.GetFlagString(cmd, "type")) if len(patchTypeString) != 0 { ok := false patchType, ok = patchTypes[patchTypeString] if !ok { return cmdutil.UsageError(cmd, fmt.Sprintf("--type must be one of %v, not %q", sets.StringKeySet(patchTypes).List(), patchTypeString)) } } patch := cmdutil.GetFlagString(cmd, "patch") if len(patch) == 0 { return cmdutil.UsageError(cmd, "Must specify -p to patch") } patchBytes, err := yaml.ToJSON([]byte(patch)) if err != nil { return fmt.Errorf("unable to parse %q: %v", patch, err) } mapper, typer := f.Object() r := resource.NewBuilder(mapper, typer, resource.ClientMapperFunc(f.ClientForMapping), f.Decoder(true)). ContinueOnError(). NamespaceParam(cmdNamespace).DefaultNamespace(). FilenameParam(enforceNamespace, &options.FilenameOptions). ResourceTypeOrNameArgs(false, args...). Flatten(). Do() err = r.Err() if err != nil { return err } count := 0 err = r.Visit(func(info *resource.Info, err error) error { if err != nil { return err } name, namespace := info.Name, info.Namespace mapping := info.ResourceMapping() client, err := f.ClientForMapping(mapping) if err != nil { return err } if !options.Local { helper := resource.NewHelper(client, mapping) _, err := helper.Patch(namespace, name, patchType, patchBytes) if err != nil { return err } if cmdutil.ShouldRecord(cmd, info) { // don't return an error on failure. The patch itself succeeded, its only the hint for that change that failed // don't bother checking for failures of this replace, because a failure to indicate the hint doesn't fail the command // also, don't force the replacement. If the replacement fails on a resourceVersion conflict, then it means this // record hint is likely to be invalid anyway, so avoid the bad hint patch, err := cmdutil.ChangeResourcePatch(info, f.Command()) if err == nil { helper.Patch(info.Namespace, info.Name, api.StrategicMergePatchType, patch) } } count++ if options.OutputFormat == "name" || len(options.OutputFormat) == 0 { cmdutil.PrintSuccess(mapper, options.OutputFormat == "name", out, "", name, false, "patched") } return nil } count++ patchedObj, err := api.Scheme.DeepCopy(info.VersionedObject) if err != nil { return err } originalObjJS, err := runtime.Encode(api.Codecs.LegacyCodec(mapping.GroupVersionKind.GroupVersion()), info.VersionedObject.(runtime.Object)) if err != nil { return err } originalPatchedObjJS, err := getPatchedJSON(patchType, originalObjJS, patchBytes, patchedObj.(runtime.Object)) if err != nil { return err } targetObj, err := runtime.Decode(api.Codecs.UniversalDecoder(), originalPatchedObjJS) if err != nil { return err } // TODO: if we ever want to go generic, this allows a clean -o yaml without trying to print columns or anything // rawExtension := &runtime.Unknown{ // Raw: originalPatchedObjJS, // } printer, err := f.PrinterForMapping(cmd, mapping, false) if err != nil { return err } if err := printer.PrintObj(targetObj, out); err != nil { return err } return nil }) if err != nil { return err } if count == 0 { return fmt.Errorf("no objects passed to patch") } return nil }
func RunApply(f *cmdutil.Factory, cmd *cobra.Command, out io.Writer, options *resource.FilenameOptions) error { shortOutput := cmdutil.GetFlagString(cmd, "output") == "name" schema, err := f.Validator(cmdutil.GetFlagBool(cmd, "validate"), cmdutil.GetFlagString(cmd, "schema-cache-dir")) if err != nil { return err } cmdNamespace, enforceNamespace, err := f.DefaultNamespace() if err != nil { return err } mapper, typer := f.Object() r := resource.NewBuilder(mapper, typer, resource.ClientMapperFunc(f.ClientForMapping), f.Decoder(true)). Schema(schema). ContinueOnError(). NamespaceParam(cmdNamespace).DefaultNamespace(). FilenameParam(enforceNamespace, options). Flatten(). Do() err = r.Err() if err != nil { return err } encoder := f.JSONEncoder() decoder := f.Decoder(false) count := 0 err = r.Visit(func(info *resource.Info, err error) error { // In this method, info.Object contains the object retrieved from the server // and info.VersionedObject contains the object decoded from the input source. if err != nil { return err } // Get the modified configuration of the object. Embed the result // as an annotation in the modified configuration, so that it will appear // in the patch sent to the server. modified, err := kubectl.GetModifiedConfiguration(info, true, encoder) if err != nil { return cmdutil.AddSourceToErr(fmt.Sprintf("retrieving modified configuration from:\n%v\nfor:", info), info.Source, err) } if err := info.Get(); err != nil { if !errors.IsNotFound(err) { return cmdutil.AddSourceToErr(fmt.Sprintf("retrieving current configuration of:\n%v\nfrom server for:", info), info.Source, err) } // Create the resource if it doesn't exist // First, update the annotation used by kubectl apply if err := kubectl.CreateApplyAnnotation(info, encoder); err != nil { return cmdutil.AddSourceToErr("creating", info.Source, err) } if cmdutil.ShouldRecord(cmd, info) { if err := cmdutil.RecordChangeCause(info.Object, f.Command()); err != nil { return cmdutil.AddSourceToErr("creating", info.Source, err) } } // Then create the resource and skip the three-way merge if err := createAndRefresh(info); err != nil { return cmdutil.AddSourceToErr("creating", info.Source, err) } count++ cmdutil.PrintSuccess(mapper, shortOutput, out, info.Mapping.Resource, info.Name, "created") return nil } overwrite := cmdutil.GetFlagBool(cmd, "overwrite") helper := resource.NewHelper(info.Client, info.Mapping) patcher := NewPatcher(encoder, decoder, info.Mapping, helper, overwrite) patchBytes, err := patcher.patch(info.Object, modified, info.Source, info.Namespace, info.Name) if err != nil { return cmdutil.AddSourceToErr(fmt.Sprintf("applying patch:\n%s\nto:\n%v\nfor:", patchBytes, info), info.Source, err) } if cmdutil.ShouldRecord(cmd, info) { patch, err := cmdutil.ChangeResourcePatch(info, f.Command()) if err != nil { return err } _, err = helper.Patch(info.Namespace, info.Name, api.StrategicMergePatchType, patch) if err != nil { return cmdutil.AddSourceToErr(fmt.Sprintf("applying patch:\n%s\nto:\n%v\nfor:", patch, info), info.Source, err) } } count++ cmdutil.PrintSuccess(mapper, shortOutput, out, info.Mapping.Resource, info.Name, "configured") return nil }) if err != nil { return err } if count == 0 { return fmt.Errorf("no objects passed to apply") } return nil }
func (o *ImageOptions) Run() error { allErrs := []error{} patches := CalculatePatches(o.Infos, o.Encoder, func(info *resource.Info) (bool, error) { transformed := false _, err := o.UpdatePodSpecForObject(info.Object, func(spec *api.PodSpec) error { for name, image := range o.ContainerImages { containerFound := false // Find the container to update, and update its image for i, c := range spec.Containers { if c.Name == name || name == "*" { spec.Containers[i].Image = image containerFound = true // Perform updates transformed = true } } // Add a new container if not found if !containerFound { allErrs = append(allErrs, fmt.Errorf("error: unable to find container named %q", name)) } } return nil }) return transformed, err }) for _, patch := range patches { info := patch.Info if patch.Err != nil { allErrs = append(allErrs, fmt.Errorf("error: %s/%s %v\n", info.Mapping.Resource, info.Name, patch.Err)) continue } // no changes if string(patch.Patch) == "{}" || len(patch.Patch) == 0 { continue } if o.Local { fmt.Fprintln(o.Out, "running in local mode...") return o.PrintObject(o.Cmd, o.Mapper, info.Object, o.Out) } // patch the change obj, err := resource.NewHelper(info.Client, info.Mapping).Patch(info.Namespace, info.Name, api.StrategicMergePatchType, patch.Patch) if err != nil { allErrs = append(allErrs, fmt.Errorf("failed to patch image update to pod template: %v\n", err)) continue } info.Refresh(obj, true) // record this change (for rollout history) if o.Record || cmdutil.ContainsChangeCause(info) { if patch, err := cmdutil.ChangeResourcePatch(info, o.ChangeCause); err == nil { if obj, err = resource.NewHelper(info.Client, info.Mapping).Patch(info.Namespace, info.Name, api.StrategicMergePatchType, patch); err != nil { fmt.Fprintf(o.Err, "WARNING: changes to %s/%s can't be recorded: %v\n", info.Mapping.Resource, info.Name, err) } } } info.Refresh(obj, true) cmdutil.PrintSuccess(o.Mapper, o.ShortOutput, o.Out, info.Mapping.Resource, info.Name, false, "image updated") } return utilerrors.NewAggregate(allErrs) }
func (o *ImageOptions) Run() error { allErrs := []error{} patches := CalculatePatches(o.Infos, o.Encoder, func(info *resource.Info) ([]byte, error) { transformed := false _, err := o.UpdatePodSpecForObject(info.Object, func(spec *api.PodSpec) error { for name, image := range o.ContainerImages { var ( containerFound bool err error resolved string ) // Find the container to update, and update its image for i, c := range spec.Containers { if c.Name == name || name == "*" { containerFound = true if len(resolved) == 0 { if resolved, err = o.ResolveImage(image); err != nil { allErrs = append(allErrs, fmt.Errorf("error: unable to resolve image %q for container %q: %v", image, name, err)) // Do not loop again if the image resolving failed for wildcard case as we // will report the same error again for the next container. if name == "*" { break } continue } } spec.Containers[i].Image = resolved // Perform updates transformed = true } } // Add a new container if not found if !containerFound { allErrs = append(allErrs, fmt.Errorf("error: unable to find container named %q", name)) } } return nil }) if transformed && err == nil { return runtime.Encode(o.Encoder, info.Object) } return nil, err }) for _, patch := range patches { info := patch.Info if patch.Err != nil { allErrs = append(allErrs, fmt.Errorf("error: %s/%s %v\n", info.Mapping.Resource, info.Name, patch.Err)) continue } // no changes if string(patch.Patch) == "{}" || len(patch.Patch) == 0 { continue } if o.PrintObject != nil && (o.Local || o.DryRun) { return o.PrintObject(o.Cmd, o.Mapper, info.Object, o.Out) } // patch the change obj, err := resource.NewHelper(info.Client, info.Mapping).Patch(info.Namespace, info.Name, types.StrategicMergePatchType, patch.Patch) if err != nil { allErrs = append(allErrs, fmt.Errorf("failed to patch image update to pod template: %v\n", err)) continue } info.Refresh(obj, true) // record this change (for rollout history) if o.Record || cmdutil.ContainsChangeCause(info) { if patch, err := cmdutil.ChangeResourcePatch(info, o.ChangeCause); err == nil { if obj, err = resource.NewHelper(info.Client, info.Mapping).Patch(info.Namespace, info.Name, types.StrategicMergePatchType, patch); err != nil { fmt.Fprintf(o.Err, "WARNING: changes to %s/%s can't be recorded: %v\n", info.Mapping.Resource, info.Name, err) } } } info.Refresh(obj, true) if len(o.Output) > 0 { return o.PrintObject(o.Cmd, o.Mapper, obj, o.Out) } cmdutil.PrintSuccess(o.Mapper, o.ShortOutput, o.Out, info.Mapping.Resource, info.Name, o.DryRun, "image updated") } return utilerrors.NewAggregate(allErrs) }
func RunApply(f cmdutil.Factory, cmd *cobra.Command, out io.Writer, options *ApplyOptions) error { shortOutput := cmdutil.GetFlagString(cmd, "output") == "name" schema, err := f.Validator(cmdutil.GetFlagBool(cmd, "validate"), cmdutil.GetFlagString(cmd, "schema-cache-dir")) if err != nil { return err } cmdNamespace, enforceNamespace, err := f.DefaultNamespace() if err != nil { return err } if options.Prune { options.PruneResources, err = parsePruneResources(cmdutil.GetFlagStringArray(cmd, "prune-whitelist")) if err != nil { return err } } mapper, typer := f.Object() r := resource.NewBuilder(mapper, typer, resource.ClientMapperFunc(f.ClientForMapping), f.Decoder(true)). Schema(schema). ContinueOnError(). NamespaceParam(cmdNamespace).DefaultNamespace(). FilenameParam(enforceNamespace, &options.FilenameOptions). SelectorParam(options.Selector). Flatten(). Do() err = r.Err() if err != nil { return err } dryRun := cmdutil.GetFlagBool(cmd, "dry-run") encoder := f.JSONEncoder() decoder := f.Decoder(false) visitedUids := sets.NewString() visitedNamespaces := sets.NewString() count := 0 err = r.Visit(func(info *resource.Info, err error) error { // In this method, info.Object contains the object retrieved from the server // and info.VersionedObject contains the object decoded from the input source. if err != nil { return err } if info.Namespaced() { visitedNamespaces.Insert(info.Namespace) } // Get the modified configuration of the object. Embed the result // as an annotation in the modified configuration, so that it will appear // in the patch sent to the server. modified, err := kubectl.GetModifiedConfiguration(info, true, encoder) if err != nil { return cmdutil.AddSourceToErr(fmt.Sprintf("retrieving modified configuration from:\n%v\nfor:", info), info.Source, err) } if err := info.Get(); err != nil { if !errors.IsNotFound(err) { return cmdutil.AddSourceToErr(fmt.Sprintf("retrieving current configuration of:\n%v\nfrom server for:", info), info.Source, err) } // Create the resource if it doesn't exist // First, update the annotation used by kubectl apply if err := kubectl.CreateApplyAnnotation(info, encoder); err != nil { return cmdutil.AddSourceToErr("creating", info.Source, err) } if cmdutil.ShouldRecord(cmd, info) { if err := cmdutil.RecordChangeCause(info.Object, f.Command()); err != nil { return cmdutil.AddSourceToErr("creating", info.Source, err) } } if !dryRun { // Then create the resource and skip the three-way merge if err := createAndRefresh(info); err != nil { return cmdutil.AddSourceToErr("creating", info.Source, err) } if uid, err := info.Mapping.UID(info.Object); err != nil { return err } else { visitedUids.Insert(string(uid)) } } count++ cmdutil.PrintSuccess(mapper, shortOutput, out, info.Mapping.Resource, info.Name, dryRun, "created") return nil } if !dryRun { overwrite := cmdutil.GetFlagBool(cmd, "overwrite") helper := resource.NewHelper(info.Client, info.Mapping) patcher := &patcher{ encoder: encoder, decoder: decoder, mapping: info.Mapping, helper: helper, clientsetFunc: f.ClientSet, overwrite: overwrite, backOff: clockwork.NewRealClock(), force: options.Force, cascade: options.Cascade, timeout: options.Timeout, gracePeriod: options.GracePeriod, } patchBytes, err := patcher.patch(info.Object, modified, info.Source, info.Namespace, info.Name) if err != nil { return cmdutil.AddSourceToErr(fmt.Sprintf("applying patch:\n%s\nto:\n%v\nfor:", patchBytes, info), info.Source, err) } if cmdutil.ShouldRecord(cmd, info) { patch, err := cmdutil.ChangeResourcePatch(info, f.Command()) if err != nil { return err } _, err = helper.Patch(info.Namespace, info.Name, api.StrategicMergePatchType, patch) if err != nil { return cmdutil.AddSourceToErr(fmt.Sprintf("applying patch:\n%s\nto:\n%v\nfor:", patch, info), info.Source, err) } } if uid, err := info.Mapping.UID(info.Object); err != nil { return err } else { visitedUids.Insert(string(uid)) } } count++ cmdutil.PrintSuccess(mapper, shortOutput, out, info.Mapping.Resource, info.Name, dryRun, "configured") return nil }) if err != nil { return err } if count == 0 { return fmt.Errorf("no objects passed to apply") } if !options.Prune { return nil } selector, err := labels.Parse(options.Selector) if err != nil { return err } p := pruner{ mapper: mapper, clientFunc: f.ClientForMapping, clientsetFunc: f.ClientSet, selector: selector, visitedUids: visitedUids, cascade: options.Cascade, dryRun: dryRun, gracePeriod: options.GracePeriod, out: out, } namespacedRESTMappings, nonNamespacedRESTMappings, err := getRESTMappings(&(options.PruneResources)) if err != nil { return fmt.Errorf("error retrieving RESTMappings to prune: %v", err) } for n := range visitedNamespaces { for _, m := range namespacedRESTMappings { if err := p.prune(n, m, shortOutput); err != nil { return fmt.Errorf("error pruning namespaced object %v: %v", m.GroupVersionKind, err) } } } for _, m := range nonNamespacedRESTMappings { if err := p.prune(api.NamespaceNone, m, shortOutput); err != nil { return fmt.Errorf("error pruning nonNamespaced object %v: %v", m.GroupVersionKind, err) } } return nil }
// RunScale executes the scaling func RunScale(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []string, shortOutput bool, options *resource.FilenameOptions) error { if len(os.Args) > 1 && os.Args[1] == "resize" { printDeprecationWarning("scale", "resize") } cmdNamespace, enforceNamespace, err := f.DefaultNamespace() if err != nil { return err } mapper, typer := f.Object() r := resource.NewBuilder(mapper, typer, resource.ClientMapperFunc(f.ClientForMapping), f.Decoder(true)). ContinueOnError(). NamespaceParam(cmdNamespace).DefaultNamespace(). FilenameParam(enforceNamespace, options). ResourceTypeOrNameArgs(false, args...). Flatten(). Do() err = r.Err() if resource.IsUsageError(err) { return cmdutil.UsageError(cmd, err.Error()) } if err != nil { return err } count := cmdutil.GetFlagInt(cmd, "replicas") if count < 0 { return cmdutil.UsageError(cmd, "The --replicas=COUNT flag is required, and COUNT must be greater than or equal to 0") } infos := []*resource.Info{} err = r.Visit(func(info *resource.Info, err error) error { if err == nil { infos = append(infos, info) } return nil }) resourceVersion := cmdutil.GetFlagString(cmd, "resource-version") if len(resourceVersion) != 0 && len(infos) > 1 { return fmt.Errorf("cannot use --resource-version with multiple resources") } counter := 0 err = r.Visit(func(info *resource.Info, err error) error { if err != nil { return err } mapping := info.ResourceMapping() scaler, err := f.Scaler(mapping) if err != nil { return err } currentSize := cmdutil.GetFlagInt(cmd, "current-replicas") precondition := &kubectl.ScalePrecondition{Size: currentSize, ResourceVersion: resourceVersion} retry := kubectl.NewRetryParams(kubectl.Interval, kubectl.Timeout) var waitForReplicas *kubectl.RetryParams if timeout := cmdutil.GetFlagDuration(cmd, "timeout"); timeout != 0 { waitForReplicas = kubectl.NewRetryParams(kubectl.Interval, timeout) } if err := scaler.Scale(info.Namespace, info.Name, uint(count), precondition, retry, waitForReplicas); err != nil { return err } if cmdutil.ShouldRecord(cmd, info) { patchBytes, err := cmdutil.ChangeResourcePatch(info, f.Command()) if err != nil { return err } mapping := info.ResourceMapping() client, err := f.ClientForMapping(mapping) if err != nil { return err } helper := resource.NewHelper(client, mapping) _, err = helper.Patch(info.Namespace, info.Name, api.StrategicMergePatchType, patchBytes) if err != nil { return err } } counter++ cmdutil.PrintSuccess(mapper, shortOutput, out, info.Mapping.Resource, info.Name, false, "scaled") return nil }) if err != nil { return err } if counter == 0 { return fmt.Errorf("no objects passed to scale") } return nil }
func RunPatch(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []string, shortOutput bool, options *PatchOptions) error { cmdNamespace, enforceNamespace, err := f.DefaultNamespace() if err != nil { return err } patch := cmdutil.GetFlagString(cmd, "patch") if len(patch) == 0 { return cmdutil.UsageError(cmd, "Must specify -p to patch") } patchBytes, err := yaml.ToJSON([]byte(patch)) if err != nil { return fmt.Errorf("unable to parse %q: %v", patch, err) } mapper, typer := f.Object() r := resource.NewBuilder(mapper, typer, resource.ClientMapperFunc(f.ClientForMapping), f.Decoder(true)). ContinueOnError(). NamespaceParam(cmdNamespace).DefaultNamespace(). FilenameParam(enforceNamespace, options.Filenames...). ResourceTypeOrNameArgs(false, args...). Flatten(). Do() err = r.Err() if err != nil { return err } infos, err := r.Infos() if err != nil { return err } if len(infos) > 1 { return fmt.Errorf("multiple resources provided") } info := infos[0] name, namespace := info.Name, info.Namespace mapping := info.ResourceMapping() client, err := f.ClientForMapping(mapping) if err != nil { return err } helper := resource.NewHelper(client, mapping) _, err = helper.Patch(namespace, name, api.StrategicMergePatchType, patchBytes) if err != nil { return err } if cmdutil.ShouldRecord(cmd, info) { patchBytes, err = cmdutil.ChangeResourcePatch(info, f.Command()) if err != nil { return err } _, err = helper.Patch(namespace, name, api.StrategicMergePatchType, patchBytes) if err != nil { return err } } cmdutil.PrintSuccess(mapper, shortOutput, out, "", name, "patched") return nil }
func RunApply(f *cmdutil.Factory, cmd *cobra.Command, out io.Writer, options *ApplyOptions) error { shortOutput := cmdutil.GetFlagString(cmd, "output") == "name" schema, err := f.Validator(cmdutil.GetFlagBool(cmd, "validate"), cmdutil.GetFlagString(cmd, "schema-cache-dir")) if err != nil { return err } cmdNamespace, enforceNamespace, err := f.DefaultNamespace() if err != nil { return err } mapper, typer := f.Object(cmdutil.GetIncludeThirdPartyAPIs(cmd)) r := resource.NewBuilder(mapper, typer, resource.ClientMapperFunc(f.ClientForMapping), f.Decoder(true)). Schema(schema). ContinueOnError(). NamespaceParam(cmdNamespace).DefaultNamespace(). FilenameParam(enforceNamespace, options.Recursive, options.Filenames...). Flatten(). Do() err = r.Err() if err != nil { return err } encoder := f.JSONEncoder() decoder := f.Decoder(false) count := 0 err = r.Visit(func(info *resource.Info, err error) error { // In this method, info.Object contains the object retrieved from the server // and info.VersionedObject contains the object decoded from the input source. if err != nil { return err } // Get the modified configuration of the object. Embed the result // as an annotation in the modified configuration, so that it will appear // in the patch sent to the server. modified, err := kubectl.GetModifiedConfiguration(info, true, encoder) if err != nil { return cmdutil.AddSourceToErr(fmt.Sprintf("retrieving modified configuration from:\n%v\nfor:", info), info.Source, err) } if err := info.Get(); err != nil { if !errors.IsNotFound(err) { return cmdutil.AddSourceToErr(fmt.Sprintf("retrieving current configuration of:\n%v\nfrom server for:", info), info.Source, err) } // Create the resource if it doesn't exist // First, update the annotation used by kubectl apply if err := kubectl.CreateApplyAnnotation(info, encoder); err != nil { return cmdutil.AddSourceToErr("creating", info.Source, err) } if cmdutil.ShouldRecord(cmd, info) { if err := cmdutil.RecordChangeCause(info.Object, f.Command()); err != nil { return cmdutil.AddSourceToErr("creating", info.Source, err) } } // Then create the resource and skip the three-way merge if err := createAndRefresh(info); err != nil { return cmdutil.AddSourceToErr("creating", info.Source, err) } count++ cmdutil.PrintSuccess(mapper, shortOutput, out, info.Mapping.Resource, info.Name, "created") return nil } // Serialize the current configuration of the object from the server. current, err := runtime.Encode(encoder, info.Object) if err != nil { return cmdutil.AddSourceToErr(fmt.Sprintf("serializing current configuration from:\n%v\nfor:", info), info.Source, err) } // Retrieve the original configuration of the object from the annotation. original, err := kubectl.GetOriginalConfiguration(info) if err != nil { return cmdutil.AddSourceToErr(fmt.Sprintf("retrieving original configuration from:\n%v\nfor:", info), info.Source, err) } // Create the versioned struct from the original from the server for // strategic patch. // TODO: Move all structs in apply to use raw data. Can be done once // builder has a RawResult method which delivers raw data instead of // internal objects. versionedObject, _, err := decoder.Decode(current, nil, nil) if err != nil { return cmdutil.AddSourceToErr(fmt.Sprintf("converting encoded server-side object back to versioned struct:\n%v\nfor:", info), info.Source, err) } // Compute a three way strategic merge patch to send to server. patch, err := strategicpatch.CreateThreeWayMergePatch(original, modified, current, versionedObject, true) if err != nil { format := "creating patch with:\noriginal:\n%s\nmodified:\n%s\ncurrent:\n%s\nfrom:\n%v\nfor:" return cmdutil.AddSourceToErr(fmt.Sprintf(format, original, modified, current, info), info.Source, err) } helper := resource.NewHelper(info.Client, info.Mapping) _, err = helper.Patch(info.Namespace, info.Name, api.StrategicMergePatchType, patch) if err != nil { return cmdutil.AddSourceToErr(fmt.Sprintf("applying patch:\n%s\nto:\n%v\nfor:", patch, info), info.Source, err) } if cmdutil.ShouldRecord(cmd, info) { patch, err = cmdutil.ChangeResourcePatch(info, f.Command()) if err != nil { return err } _, err = helper.Patch(info.Namespace, info.Name, api.StrategicMergePatchType, patch) if err != nil { return cmdutil.AddSourceToErr(fmt.Sprintf("applying patch:\n%s\nto:\n%v\nfor:", patch, info), info.Source, err) } } count++ cmdutil.PrintSuccess(mapper, shortOutput, out, info.Mapping.Resource, info.Name, "configured") return nil }) if err != nil { return err } if count == 0 { return fmt.Errorf("no objects passed to apply") } return nil }