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 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, _, err := f.DefaultNamespace() if err != nil { return err } mapper, typer := f.Object() r := resource.NewBuilder(mapper, typer, f.ClientMapperForCommand()). Schema(schema). ContinueOnError(). NamespaceParam(cmdNamespace).DefaultNamespace(). FilenameParam(false, options.Filenames...). Flatten(). Do() err = r.Err() if err != nil { return err } 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) 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); 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 := info.Mapping.Codec.Encode(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) } // Compute a three way strategic merge patch to send to server. patch, err := strategicpatch.CreateThreeWayMergePatch(original, modified, current, info.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) } 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 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 }
// ApplyResource applies the given data as a kubernetes resource func ApplyResource(f *cmdutil.Factory, c *client.Client, ns string, data []byte, name string) error { schemaCacheDir := "/tmp/kubectl.schema" validate := true schema, err := f.Validator(validate, schemaCacheDir) if err != nil { log.Info("Failed to load kubernetes schema: %s", err) return err } mapper, typer := f.Object() r := resource.NewBuilder(mapper, typer, resource.ClientMapperFunc(f.ClientForMapping), f.Decoder(true)). Schema(schema). ContinueOnError(). NamespaceParam(ns).DefaultNamespace(). Stream(bytes.NewReader(data), name). Flatten(). Do() err = r.Err() if err != nil { log.Info("Failed to load mapper!") return err } 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, f.JSONEncoder()) 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 { return cmdutil.AddSourceToErr(fmt.Sprintf("retrieving current configuration of:\n%v\nfrom server for:", info), info.Source, err) } // Serialize the current configuration of the object from the server. current, err := runtime.Encode(f.JSONEncoder(), 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) } // Compute a three way strategic merge patch to send to server. patch, err := strategicpatch.CreateThreeWayMergePatch(original, modified, current, info.VersionedObject, false) 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) } count++ cmdutil.PrintSuccess(mapper, false, os.Stdout, 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 }