// RunExplain executes the appropriate steps to print a model's documentation func RunExplain(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []string) error { if len(args) != 1 { return cmdutil.UsageError(cmd, "We accept only this format: explain RESOURCE") } client, err := f.Client() if err != nil { return err } recursive := cmdutil.GetFlagBool(cmd, "recursive") apiV := cmdutil.GetFlagString(cmd, "api-version") swagSchema, err := kubectl.GetSwaggerSchema(apiV, client) if err != nil { return err } mapper, _ := f.Object() inModel, fieldsPath, err := kubectl.SplitAndParseResourceRequest(args[0], mapper) if err != nil { return err } return kubectl.PrintModelDescription(inModel, fieldsPath, out, swagSchema, recursive) }
func RunStop(f cmdutil.Factory, cmd *cobra.Command, args []string, out io.Writer, options *resource.FilenameOptions) error { 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(). ResourceTypeOrNameArgs(false, args...). FilenameParam(enforceNamespace, options). SelectorParam(cmdutil.GetFlagString(cmd, "selector")). SelectAllParam(cmdutil.GetFlagBool(cmd, "all")). Flatten(). Do() if r.Err() != nil { return r.Err() } shortOutput := cmdutil.GetFlagString(cmd, "output") == "name" gracePeriod := cmdutil.GetFlagInt(cmd, "grace-period") waitForDeletion := false if gracePeriod == 0 { // To preserve backwards compatibility, but prevent accidental data loss, we convert --grace-period=0 // into --grace-period=1 and wait until the object is successfully deleted. gracePeriod = 1 waitForDeletion = true } return ReapResult(r, f, out, false, cmdutil.GetFlagBool(cmd, "ignore-not-found"), cmdutil.GetFlagDuration(cmd, "timeout"), gracePeriod, waitForDeletion, shortOutput, mapper, false) }
func RunClusterInfo(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command) error { if len(os.Args) > 1 && os.Args[1] == "clusterinfo" { printDeprecationWarning("cluster-info", "clusterinfo") } client, err := f.ClientConfig() if err != nil { return err } printService(out, "Kubernetes master", client.Host) mapper, typer := f.Object(cmdutil.GetIncludeThirdPartyAPIs(cmd)) cmdNamespace := cmdutil.GetFlagString(cmd, "namespace") if cmdNamespace == "" { cmdNamespace = api.NamespaceSystem } // TODO use generalized labels once they are implemented (#341) b := resource.NewBuilder(mapper, typer, resource.ClientMapperFunc(f.ClientForMapping), f.Decoder(true)). NamespaceParam(cmdNamespace).DefaultNamespace(). SelectorParam("kubernetes.io/cluster-service=true"). ResourceTypeOrNameArgs(false, []string{"services"}...). Latest() b.Do().Visit(func(r *resource.Info, err error) error { if err != nil { return err } services := r.Object.(*api.ServiceList).Items for _, service := range services { var link string if len(service.Status.LoadBalancer.Ingress) > 0 { ingress := service.Status.LoadBalancer.Ingress[0] ip := ingress.IP if ip == "" { ip = ingress.Hostname } for _, port := range service.Spec.Ports { link += "http://" + ip + ":" + strconv.Itoa(int(port.Port)) + " " } } else { if len(client.GroupVersion.Group) == 0 { link = client.Host + "/api/" + client.GroupVersion.Version + "/proxy/namespaces/" + service.ObjectMeta.Namespace + "/services/" + service.ObjectMeta.Name } else { link = client.Host + "/api/" + client.GroupVersion.Group + "/" + client.GroupVersion.Version + "/proxy/namespaces/" + service.ObjectMeta.Namespace + "/services/" + service.ObjectMeta.Name } } name := service.ObjectMeta.Labels["kubernetes.io/name"] if len(name) == 0 { name = service.ObjectMeta.Name } printService(out, name, link) } return nil }) out.Write([]byte("\nTo further debug and diagnose cluster problems, use 'kubectl cluster-info dump'.\n")) return nil // TODO consider printing more information about cluster }
// popCluster fetches the cluster object with the given name, deletes // it and returns the deleted cluster object. func popCluster(f cmdutil.Factory, name string) (*federationapi.Cluster, error) { // Boilerplate to create the secret in the host cluster. mapper, typer := f.Object() gvks, _, err := typer.ObjectKinds(&federationapi.Cluster{}) if err != nil { return nil, err } gvk := gvks[0] mapping, err := mapper.RESTMapping(schema.GroupKind{Group: gvk.Group, Kind: gvk.Kind}, gvk.Version) if err != nil { return nil, err } client, err := f.ClientForMapping(mapping) if err != nil { return nil, err } rh := resource.NewHelper(client, mapping) obj, err := rh.Get("", name, false) if isNotFound(err) { // Cluster isn't registered, there isn't anything to be done here. return nil, nil } else if err != nil { return nil, err } cluster, ok := obj.(*federationapi.Cluster) if !ok { return nil, fmt.Errorf("unexpected object type: expected \"federation/v1beta1.Cluster\", got %T: obj: %#v", obj, obj) } // Remove the cluster resource in the federation API server by // calling rh.Delete() return cluster, rh.Delete("", name) }
func getMapperAndResult(f cmdutil.Factory, args []string, options *resource.FilenameOptions) (meta.RESTMapper, *resource.Mapper, *resource.Result, string, error) { cmdNamespace, enforceNamespace, err := f.DefaultNamespace() if err != nil { return nil, nil, nil, "", err } mapper, typer := f.Object() resourceMapper := &resource.Mapper{ ObjectTyper: typer, RESTMapper: mapper, ClientMapper: resource.ClientMapperFunc(f.ClientForMapping), // NB: we use `f.Decoder(false)` to get a plain deserializer for // the resourceMapper, since it's used to read in edits and // we don't want to convert into the internal version when // reading in edits (this would cause us to potentially try to // compare two different GroupVersions). Decoder: f.Decoder(false), } r := resource.NewBuilder(mapper, typer, resource.ClientMapperFunc(f.ClientForMapping), f.Decoder(true)). NamespaceParam(cmdNamespace).DefaultNamespace(). FilenameParam(enforceNamespace, options). ResourceTypeOrNameArgs(true, args...). ContinueOnError(). Flatten(). Latest(). Do() err = r.Err() if err != nil { return nil, nil, nil, "", err } return mapper, resourceMapper, r, cmdNamespace, err }
func (o *PauseConfig) CompletePause(f cmdutil.Factory, cmd *cobra.Command, out io.Writer, args []string) error { if len(args) == 0 && cmdutil.IsFilenameEmpty(o.Filenames) { return cmdutil.UsageError(cmd, cmd.Use) } o.Mapper, o.Typer = f.Object() o.Encoder = f.JSONEncoder() o.Pauser = f.Pauser o.Out = out cmdNamespace, enforceNamespace, err := f.DefaultNamespace() if err != nil { return err } r := resource.NewBuilder(o.Mapper, o.Typer, resource.ClientMapperFunc(f.ClientForMapping), f.Decoder(true)). NamespaceParam(cmdNamespace).DefaultNamespace(). FilenameParam(enforceNamespace, &o.FilenameOptions). ResourceTypeOrNameArgs(true, args...). ContinueOnError(). Latest(). Flatten(). Do() err = r.Err() if err != nil { return err } o.Infos, err = r.Infos() if err != nil { return err } return nil }
func RunStop(f *cmdutil.Factory, cmd *cobra.Command, args []string, out io.Writer, options *StopOptions) error { cmdNamespace, enforceNamespace, err := f.DefaultNamespace() if err != nil { return err } cmdTenant, enforceTenant, err := f.DefaultTenant() if err != nil { return err } mapper, typer := f.Object() r := resource.NewBuilder(mapper, typer, f.ClientMapperForCommand()). ContinueOnError(). NamespaceParam(cmdNamespace).DefaultNamespace(). TenantParam(cmdTenant).DefaultTenant(). ResourceTypeOrNameArgs(false, args...). FilenameParam(enforceTenant, enforceNamespace, options.Filenames...). SelectorParam(cmdutil.GetFlagString(cmd, "selector")). SelectAllParam(cmdutil.GetFlagBool(cmd, "all")). Flatten(). Do() if r.Err() != nil { return r.Err() } shortOutput := cmdutil.GetFlagString(cmd, "output") == "name" return ReapResult(r, f, out, false, cmdutil.GetFlagBool(cmd, "ignore-not-found"), cmdutil.GetFlagDuration(cmd, "timeout"), cmdutil.GetFlagInt(cmd, "grace-period"), shortOutput, mapper) }
func RunHistory(f *cmdutil.Factory, cmd *cobra.Command, out io.Writer, args []string, options *HistoryOptions) error { if len(args) == 0 && len(options.Filenames) == 0 { return cmdutil.UsageError(cmd, "Required resource not specified.") } revisionDetail := cmdutil.GetFlagInt64(cmd, "revision") mapper, typer := f.Object(false) cmdNamespace, enforceNamespace, err := f.DefaultNamespace() if err != nil { return err } r := resource.NewBuilder(mapper, typer, resource.ClientMapperFunc(f.ClientForMapping), f.Decoder(true)). NamespaceParam(cmdNamespace).DefaultNamespace(). FilenameParam(enforceNamespace, options.Recursive, options.Filenames...). ResourceTypeOrNameArgs(true, args...). ContinueOnError(). Latest(). Flatten(). Do() err = r.Err() if err != nil { return err } err = r.Visit(func(info *resource.Info, err error) error { if err != nil { return err } mapping := info.ResourceMapping() historyViewer, err := f.HistoryViewer(mapping) if err != nil { return err } historyInfo, err := historyViewer.History(info.Namespace, info.Name) if err != nil { return err } if revisionDetail > 0 { // Print details of a specific revision template, ok := historyInfo.RevisionToTemplate[revisionDetail] if !ok { return fmt.Errorf("unable to find revision %d of %s %q", revisionDetail, mapping.Resource, info.Name) } fmt.Fprintf(out, "%s %q revision %d\n", mapping.Resource, info.Name, revisionDetail) kubectl.DescribePodTemplate(template, out) } else { // Print all revisions formattedOutput, printErr := kubectl.PrintRolloutHistory(historyInfo, mapping.Resource, info.Name) if printErr != nil { return printErr } fmt.Fprintf(out, "%s\n", formattedOutput) } return nil }) return err }
func (o *ResourcesOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args []string) error { o.f = f o.Mapper, o.Typer = f.Object() o.UpdatePodSpecForObject = f.UpdatePodSpecForObject o.Encoder = f.JSONEncoder() o.ShortOutput = cmdutil.GetFlagString(cmd, "output") == "name" o.Record = cmdutil.GetRecordFlag(cmd) o.ChangeCause = f.Command() o.PrintObject = f.PrintObject o.Cmd = cmd cmdNamespace, enforceNamespace, err := f.DefaultNamespace() if err != nil { return err } builder := resource.NewBuilder(o.Mapper, o.Typer, resource.ClientMapperFunc(f.ClientForMapping), f.Decoder(true)). ContinueOnError(). NamespaceParam(cmdNamespace).DefaultNamespace(). //FilenameParam(enforceNamespace, o.Filenames...). FilenameParam(enforceNamespace, &o.FilenameOptions). Flatten() if !o.Local { builder = builder. SelectorParam(o.Selector). ResourceTypeOrNameArgs(o.All, args...). Latest() } o.Infos, err = builder.Do().Infos() if err != nil { return err } return nil }
// Complete assigns the SelectorOptions from args. func (o *SelectorOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args []string, out io.Writer) error { o.local = cmdutil.GetFlagBool(cmd, "local") o.all = cmdutil.GetFlagBool(cmd, "all") o.record = cmdutil.GetRecordFlag(cmd) o.dryrun = cmdutil.GetDryRunFlag(cmd) cmdNamespace, enforceNamespace, err := f.DefaultNamespace() if err != nil { return err } o.changeCause = f.Command() mapper, _ := f.Object() o.mapper = mapper o.encoder = f.JSONEncoder() o.builder = f.NewBuilder(). ContinueOnError(). NamespaceParam(cmdNamespace).DefaultNamespace(). FilenameParam(enforceNamespace, &o.fileOptions). Flatten() o.PrintObject = func(obj runtime.Object) error { return f.PrintObject(cmd, mapper, obj, o.out) } o.ClientForMapping = func(mapping *meta.RESTMapping) (resource.RESTClient, error) { return f.ClientForMapping(mapping) } o.resources, o.selector, err = getResourcesAndSelector(args) return err }
func (o *UndoOptions) CompleteUndo(f *cmdutil.Factory, cmd *cobra.Command, out io.Writer, args []string) error { if len(args) == 0 && len(o.Filenames) == 0 { return cmdutil.UsageError(cmd, "Required resource not specified.") } o.ToRevision = cmdutil.GetFlagInt64(cmd, "to-revision") o.Mapper, o.Typer = f.Object(false) o.Out = out cmdNamespace, enforceNamespace, err := f.DefaultNamespace() if err != nil { return err } infos, err := resource.NewBuilder(o.Mapper, o.Typer, resource.ClientMapperFunc(f.ClientForMapping), f.Decoder(true)). NamespaceParam(cmdNamespace).DefaultNamespace(). FilenameParam(enforceNamespace, o.Recursive, o.Filenames...). ResourceTypeOrNameArgs(true, args...). Latest(). Flatten(). Do(). Infos() if err != nil { return err } if len(infos) != 1 { return fmt.Errorf("rollout undo is only supported on individual resources - %d resources were found", len(infos)) } o.Info = infos[0] o.Rollbacker, err = f.Rollbacker(o.Info.ResourceMapping()) return err }
func (o *PauseConfig) CompletePause(f *cmdutil.Factory, cmd *cobra.Command, out io.Writer, args []string) error { if len(args) == 0 && len(o.Filenames) == 0 { return cmdutil.UsageError(cmd, cmd.Use) } o.Mapper, o.Typer = f.Object() o.PauseObject = f.PauseObject o.Out = out cmdNamespace, enforceNamespace, err := f.DefaultNamespace() if err != nil { return err } infos, err := resource.NewBuilder(o.Mapper, o.Typer, resource.ClientMapperFunc(f.ClientForMapping), f.Decoder(true)). NamespaceParam(cmdNamespace).DefaultNamespace(). FilenameParam(enforceNamespace, o.Filenames...). ResourceTypeOrNameArgs(true, args...). SingleResourceType(). Latest(). Do().Infos() if err != nil { return err } if len(infos) != 1 { return fmt.Errorf("rollout pause is only supported on individual resources - %d resources were found", len(infos)) } o.Info = infos[0] return nil }
func RunReplace(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []string, options *ReplaceOptions) error { if len(os.Args) > 1 && os.Args[1] == "update" { printDeprecationWarning("replace", "update") } 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 } force := cmdutil.GetFlagBool(cmd, "force") if len(options.Filenames) == 0 { return cmdutil.UsageError(cmd, "Must specify --filename to replace") } shortOutput := cmdutil.GetFlagString(cmd, "output") == "name" if force { return forceReplace(f, out, cmd, args, shortOutput, options) } mapper, typer := f.Object() r := resource.NewBuilder(mapper, typer, f.ClientMapperForCommand()). Schema(schema). ContinueOnError(). NamespaceParam(cmdNamespace).DefaultNamespace(). FilenameParam(enforceNamespace, options.Filenames...). Flatten(). Do() err = r.Err() if err != nil { return err } return r.Visit(func(info *resource.Info, err error) error { if err != nil { return err } // Serialize the configuration into an annotation. if err := kubectl.UpdateApplyAnnotation(info); err != nil { return err } // Serialize the object with the annotation applied. obj, err := resource.NewHelper(info.Client, info.Mapping).Replace(info.Namespace, info.Name, true, info.Object) if err != nil { return cmdutil.AddSourceToErr("replacing", info.Source, err) } info.Refresh(obj, true) printObjectSpecificMessage(obj, out) cmdutil.PrintSuccess(mapper, shortOutput, out, info.Mapping.Resource, info.Name, "replaced") return nil }) }
func createGeneratedObject(f *cmdutil.Factory, cmd *cobra.Command, generator kubectl.Generator, names []kubectl.GeneratorParam, params map[string]interface{}, overrides, namespace string) (runtime.Object, string, meta.RESTMapper, *meta.RESTMapping, error) { err := kubectl.ValidateParams(names, params) if err != nil { return nil, "", nil, nil, err } obj, err := generator.Generate(params) if err != nil { return nil, "", nil, nil, err } mapper, typer := f.Object() version, kind, err := typer.ObjectVersionAndKind(obj) if err != nil { return nil, "", nil, nil, err } if len(overrides) > 0 { obj, err = cmdutil.Merge(obj, overrides, kind) if err != nil { return nil, "", nil, nil, err } } mapping, err := mapper.RESTMapping(kind, version) if err != nil { return nil, "", nil, nil, err } client, err := f.RESTClient(mapping) if err != nil { return nil, "", nil, nil, err } // TODO: extract this flag to a central location, when such a location exists. if !cmdutil.GetFlagBool(cmd, "dry-run") { resourceMapper := &resource.Mapper{ObjectTyper: typer, RESTMapper: mapper, ClientMapper: f.ClientMapperForCommand()} info, err := resourceMapper.InfoForObject(obj) if err != nil { return nil, "", nil, nil, err } // Serialize the configuration into an annotation. if err := kubectl.UpdateApplyAnnotation(info); err != nil { return nil, "", nil, nil, err } // Serialize the object with the annotation applied. data, err := mapping.Codec.Encode(info.Object) if err != nil { return nil, "", nil, nil, err } obj, err = resource.NewHelper(client, mapping).Create(namespace, false, data) if err != nil { return nil, "", nil, nil, err } } return obj, kind, mapper, mapping, err }
func RunCreate(f *cmdutil.Factory, cmd *cobra.Command, out io.Writer, options *CreateOptions) error { 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.Filenames...). 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 } if err := kubectl.CreateOrUpdateAnnotation(cmdutil.GetFlagBool(cmd, cmdutil.ApplyAnnotationsFlag), info, f.JSONEncoder()); 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 err := createAndRefresh(info); err != nil { return cmdutil.AddSourceToErr("creating", info.Source, err) } count++ shortOutput := cmdutil.GetFlagString(cmd, "output") == "name" if !shortOutput { printObjectSpecificMessage(info.Object, out) } cmdutil.PrintSuccess(mapper, shortOutput, out, info.Mapping.Resource, info.Name, "created") return nil }) if err != nil { return err } if count == 0 { return fmt.Errorf("no objects passed to create") } return nil }
func createGeneratedObject(f *cmdutil.Factory, cmd *cobra.Command, generator kubectl.Generator, names []kubectl.GeneratorParam, params map[string]interface{}, overrides, namespace string) (runtime.Object, string, meta.RESTMapper, *meta.RESTMapping, error) { err := kubectl.ValidateParams(names, params) if err != nil { return nil, "", nil, nil, err } // TODO: Validate flag usage against selected generator. More tricky since --expose was added. obj, err := generator.Generate(params) if err != nil { return nil, "", nil, nil, err } mapper, typer := f.Object() groupVersionKind, err := typer.ObjectKind(obj) if err != nil { return nil, "", nil, nil, err } if len(overrides) > 0 { codec := runtime.NewCodec(f.JSONEncoder(), f.Decoder(true)) obj, err = cmdutil.Merge(codec, obj, overrides, groupVersionKind.Kind) if err != nil { return nil, "", nil, nil, err } } mapping, err := mapper.RESTMapping(groupVersionKind.GroupKind(), groupVersionKind.Version) if err != nil { return nil, "", nil, nil, err } client, err := f.ClientForMapping(mapping) if err != nil { return nil, "", nil, nil, err } // TODO: extract this flag to a central location, when such a location exists. if !cmdutil.GetFlagBool(cmd, "dry-run") { resourceMapper := &resource.Mapper{ ObjectTyper: typer, RESTMapper: mapper, ClientMapper: resource.ClientMapperFunc(f.ClientForMapping), Decoder: f.Decoder(true), } info, err := resourceMapper.InfoForObject(obj) if err != nil { return nil, "", nil, nil, err } if err := kubectl.CreateOrUpdateAnnotation(cmdutil.GetFlagBool(cmd, cmdutil.ApplyAnnotationsFlag), info, f.JSONEncoder()); err != nil { return nil, "", nil, nil, err } obj, err = resource.NewHelper(client, mapping).Create(namespace, false, info.Object) if err != nil { return nil, "", nil, nil, err } } return obj, groupVersionKind.Kind, mapper, mapping, err }
// Complete adapts from the command line args and factory to the data required. func (o *TaintOptions) Complete(f cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []string) (err error) { namespace, _, err := f.DefaultNamespace() if err != nil { return err } // retrieves resource and taint args from args // also checks args to verify that all resources are specified before taints taintArgs := []string{} metTaintArg := false for _, s := range args { isTaint := strings.Contains(s, "=") || strings.HasSuffix(s, "-") switch { case !metTaintArg && isTaint: metTaintArg = true fallthrough case metTaintArg && isTaint: taintArgs = append(taintArgs, s) case !metTaintArg && !isTaint: o.resources = append(o.resources, s) case metTaintArg && !isTaint: return fmt.Errorf("all resources must be specified before taint changes: %s", s) } } if len(o.resources) < 1 { return fmt.Errorf("one or more resources must be specified as <resource> <name>") } if len(taintArgs) < 1 { return fmt.Errorf("at least one taint update is required") } if o.taintsToAdd, o.taintsToRemove, err = parseTaints(taintArgs); err != nil { return cmdutil.UsageError(cmd, err.Error()) } mapper, typer := f.Object() o.builder = resource.NewBuilder(mapper, typer, resource.ClientMapperFunc(f.ClientForMapping), f.Decoder(true)). ContinueOnError(). NamespaceParam(namespace).DefaultNamespace() if o.all { o.builder = o.builder.SelectAllParam(o.all).ResourceTypes("node") } else { if len(o.resources) < 2 { return fmt.Errorf("at least one resource name must be specified since 'all' parameter is not set") } o.builder = o.builder.ResourceNames("node", o.resources[1:]...) } o.builder = o.builder.SelectorParam(o.selector). Flatten(). Latest() o.f = f o.out = out o.cmd = cmd return nil }
func RunDescribe(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []string, options *DescribeOptions, describerSettings *kubectl.DescriberSettings) error { selector := cmdutil.GetFlagString(cmd, "selector") cmdNamespace, enforceNamespace, err := f.DefaultNamespace() if err != nil { return err } if len(args) == 0 && len(options.Filenames) == 0 { fmt.Fprint(out, "You must specify the type of resource to describe. ", valid_resources) return cmdutil.UsageError(cmd, "Required resource not specified.") } mapper, typer := f.Object(cmdutil.GetIncludeThirdPartyAPIs(cmd)) r := resource.NewBuilder(mapper, typer, resource.ClientMapperFunc(f.ClientForMapping), f.Decoder(true)). ContinueOnError(). NamespaceParam(cmdNamespace).DefaultNamespace(). FilenameParam(enforceNamespace, options.Recursive, options.Filenames...). SelectorParam(selector). ResourceTypeOrNameArgs(true, args...). Flatten(). Do() err = r.Err() if err != nil { return err } allErrs := []error{} infos, err := r.Infos() if err != nil { if apierrors.IsNotFound(err) && len(args) == 2 { return DescribeMatchingResources(mapper, typer, f, cmdNamespace, args[0], args[1], describerSettings, out, err) } allErrs = append(allErrs, err) } first := true for _, info := range infos { mapping := info.ResourceMapping() describer, err := f.Describer(mapping) if err != nil { allErrs = append(allErrs, err) continue } s, err := describer.Describe(info.Namespace, info.Name, *describerSettings) if err != nil { allErrs = append(allErrs, err) continue } if first { first = false } else { fmt.Fprintf(out, "\n\n") } fmt.Fprint(out, s) } return utilerrors.NewAggregate(allErrs) }
func createGeneratedObject(f *cmdutil.Factory, cmd *cobra.Command, generator kubectl.Generator, names []kubectl.GeneratorParam, params map[string]interface{}, overrides, namespace string) (runtime.Object, string, meta.RESTMapper, *meta.RESTMapping, error) { err := kubectl.ValidateParams(names, params) if err != nil { return nil, "", nil, nil, err } obj, err := generator.Generate(params) if err != nil { return nil, "", nil, nil, err } mapper, typer := f.Object() gvString, kind, err := typer.ObjectVersionAndKind(obj) if err != nil { return nil, "", nil, nil, err } gv, err := unversioned.ParseGroupVersion(gvString) if err != nil { return nil, "", nil, nil, err } gvk := gv.WithKind(kind) if len(overrides) > 0 { obj, err = cmdutil.Merge(obj, overrides, kind) if err != nil { return nil, "", nil, nil, err } } mapping, err := mapper.RESTMapping(gvk.GroupKind(), gvk.Version) if err != nil { return nil, "", nil, nil, err } client, err := f.RESTClient(mapping) if err != nil { return nil, "", nil, nil, err } // TODO: extract this flag to a central location, when such a location exists. if !cmdutil.GetFlagBool(cmd, "dry-run") { resourceMapper := &resource.Mapper{ObjectTyper: typer, RESTMapper: mapper, ClientMapper: f.ClientMapperForCommand()} info, err := resourceMapper.InfoForObject(obj) if err != nil { return nil, "", nil, nil, err } if err := kubectl.CreateOrUpdateAnnotation(cmdutil.GetFlagBool(cmd, cmdutil.ApplyAnnotationsFlag), info); err != nil { return nil, "", nil, nil, err } obj, err = resource.NewHelper(client, mapping).Create(namespace, false, info.Object) if err != nil { return nil, "", nil, nil, err } } return obj, kind, mapper, mapping, err }
func (o *LogsOptions) Complete(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []string) error { containerName := cmdutil.GetFlagString(cmd, "container") switch len(args) { case 0: return cmdutil.UsageError(cmd, "POD is required for logs") case 1: o.ResourceArg = args[0] case 2: if cmd.Flag("container").Changed { return cmdutil.UsageError(cmd, "only one of -c, [CONTAINER] arg is allowed") } o.ResourceArg = args[0] containerName = args[1] default: return cmdutil.UsageError(cmd, "logs POD [-c CONTAINER]") } var err error o.Namespace, _, err = f.DefaultNamespace() if err != nil { return err } logOptions := &api.PodLogOptions{ Container: containerName, Follow: cmdutil.GetFlagBool(cmd, "follow"), Previous: cmdutil.GetFlagBool(cmd, "previous"), Timestamps: cmdutil.GetFlagBool(cmd, "timestamps"), } if sinceTime := cmdutil.GetFlagString(cmd, "since-time"); len(sinceTime) > 0 { t, err := api.ParseRFC3339(sinceTime, unversioned.Now) if err != nil { return err } logOptions.SinceTime = &t } if limit := cmdutil.GetFlagInt64(cmd, "limit-bytes"); limit != 0 { logOptions.LimitBytes = &limit } if tail := cmdutil.GetFlagInt64(cmd, "tail"); tail != -1 { logOptions.TailLines = &tail } if sinceSeconds := cmdutil.GetFlagDuration(cmd, "since"); sinceSeconds != 0 { // round up to the nearest second sec := int64(math.Ceil(float64(sinceSeconds) / float64(time.Second))) logOptions.SinceSeconds = &sec } o.Options = logOptions o.Mapper, o.Typer = f.Object() o.Decoder = f.Decoder(true) o.ClientMapper = resource.ClientMapperFunc(f.ClientForMapping) o.LogsForObject = f.LogsForObject o.Out = out return nil }
func RunCreate(f *cmdutil.Factory, cmd *cobra.Command, out io.Writer) error { schema, err := f.Validator() if err != nil { return err } cmdNamespace, enforceNamespace, err := f.DefaultNamespace() if err != nil { return err } filenames := cmdutil.GetFlagStringSlice(cmd, "filename") mapper, typer := f.Object() r := resource.NewBuilder(mapper, typer, f.ClientMapperForCommand()). Schema(schema). ContinueOnError(). NamespaceParam(cmdNamespace).DefaultNamespace(). FilenameParam(enforceNamespace, filenames...). 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 } data, err := info.Mapping.Codec.Encode(info.Object) if err != nil { return cmdutil.AddSourceToErr("creating", info.Source, err) } obj, err := resource.NewHelper(info.Client, info.Mapping).Create(info.Namespace, true, data) if err != nil { return cmdutil.AddSourceToErr("creating", info.Source, err) } count++ info.Refresh(obj, true) shortOutput := cmdutil.GetFlagString(cmd, "output") == "name" if !shortOutput { printObjectSpecificMessage(info.Object, out) } cmdutil.PrintSuccess(mapper, shortOutput, out, info.Mapping.Resource, info.Name, "created") return nil }) if err != nil { return err } if count == 0 { return fmt.Errorf("no objects passed to create") } return nil }
func initExample(cmdNamespace string, resource string, f *cmdutil.Factory, cmd *cobra.Command) (runtime.Object, error) { mapper, _ := f.Object() version, kind, err := mapper.VersionAndKindForResource(resource) if err != nil { return nil, err } exBuilder := f.ExampleBuilder() obj, _, err := exBuilder.NewExample(version, kind) if err != nil { return nil, err } mapping, err := mapper.RESTMapping(kind, version) if err != nil { return nil, err } err = mapping.SetAPIVersion(obj, version) if err != nil { return nil, err } err = mapping.SetKind(obj, kind) if err != nil { return nil, err } err = mapping.SetNamespace(obj, cmdNamespace) if err != nil { return nil, err } nameFlag := cmdutil.GetFlagString(cmd, "name") if nameFlag != "" { err = mapping.SetName(obj, nameFlag) } else { err = mapping.SetName(obj, " ") } if err != nil { return nil, err } labelsFlag := cmdutil.GetFlagString(cmd, "labels") if labelsFlag != "" { parsedLabels, err := kubectl.ParseLabels(labelsFlag) if err != nil { return nil, err } err = mapping.SetLabels(obj, parsedLabels) if err != nil { return nil, err } } return obj, nil }
func RunReplace(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []string) error { if len(os.Args) > 1 && os.Args[1] == "update" { printDeprecationWarning("replace", "update") } schema, err := f.Validator() if err != nil { return err } cmdNamespace, enforceNamespace, err := f.DefaultNamespace() if err != nil { return err } force := cmdutil.GetFlagBool(cmd, "force") filenames := cmdutil.GetFlagStringSlice(cmd, "filename") if len(filenames) == 0 { return cmdutil.UsageError(cmd, "Must specify --filename to replace") } shortOutput := cmdutil.GetFlagString(cmd, "output") == "name" if force { return forceReplace(f, out, cmd, args, filenames, shortOutput) } mapper, typer := f.Object() r := resource.NewBuilder(mapper, typer, f.ClientMapperForCommand()). Schema(schema). ContinueOnError(). NamespaceParam(cmdNamespace).DefaultNamespace(). FilenameParam(enforceNamespace, filenames...). Flatten(). Do() err = r.Err() if err != nil { return err } return r.Visit(func(info *resource.Info, err error) error { if err != nil { return err } data, err := info.Mapping.Codec.Encode(info.Object) if err != nil { return cmdutil.AddSourceToErr("replacing", info.Source, err) } obj, err := resource.NewHelper(info.Client, info.Mapping).Replace(info.Namespace, info.Name, true, data) if err != nil { return cmdutil.AddSourceToErr("replacing", info.Source, err) } info.Refresh(obj, true) printObjectSpecificMessage(obj, out) cmdutil.PrintSuccess(mapper, shortOutput, out, info.Mapping.Resource, info.Name, "replaced") return nil }) }
// RunExplain executes the appropriate steps to print a model's documentation func RunExplain(f *cmdutil.Factory, out, cmdErr io.Writer, cmd *cobra.Command, args []string) error { if len(args) == 0 { fmt.Fprint(cmdErr, "You must specify the type of resource to explain. ", valid_resources) return cmdutil.UsageError(cmd, "Required resource not specified.") } if len(args) > 1 { return cmdutil.UsageError(cmd, "We accept only this format: explain RESOURCE") } recursive := cmdutil.GetFlagBool(cmd, "recursive") apiVersionString := cmdutil.GetFlagString(cmd, "api-version") apiVersion := unversioned.GroupVersion{} mapper, _ := f.Object(cmdutil.GetIncludeThirdPartyAPIs(cmd)) // TODO: After we figured out the new syntax to separate group and resource, allow // the users to use it in explain (kubectl explain <group><syntax><resource>). // Refer to issue #16039 for why we do this. Refer to PR #15808 that used "/" syntax. inModel, fieldsPath, err := kubectl.SplitAndParseResourceRequest(args[0], mapper) if err != nil { return err } // TODO: We should deduce the group for a resource by discovering the supported resources at server. fullySpecifiedGVR, groupResource := unversioned.ParseResourceArg(inModel) gvk := unversioned.GroupVersionKind{} if fullySpecifiedGVR != nil { gvk, _ = mapper.KindFor(*fullySpecifiedGVR) } if gvk.Empty() { gvk, err = mapper.KindFor(groupResource.WithVersion("")) if err != nil { return err } } if len(apiVersionString) == 0 { groupMeta, err := registered.Group(gvk.Group) if err != nil { return err } apiVersion = groupMeta.GroupVersion } else { apiVersion, err = unversioned.ParseGroupVersion(apiVersionString) if err != nil { return nil } } schema, err := f.SwaggerSchema(apiVersion.WithKind(gvk.Kind)) if err != nil { return err } return kubectl.PrintModelDescription(inModel, fieldsPath, out, schema, recursive) }
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 } cmdTenant, enforceTenant, err := f.DefaultTenant() 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, f.ClientMapperForCommand()). ContinueOnError(). NamespaceParam(cmdNamespace).DefaultNamespace(). TenantParam(cmdTenant).DefaultTenant(). FilenameParam(enforceTenant, 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.RESTClient(mapping) if err != nil { return err } helper := resource.NewHelper(client, mapping) _, err = helper.Patch(namespace, name, api.StrategicMergePatchType, patchBytes) if err != nil { return err } cmdutil.PrintSuccess(mapper, shortOutput, out, "", name, "patched") return nil }
// Complete adapts from the command line args and factory to the data required. func (o *AnnotateOptions) Complete(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []string) (err error) { namespace, enforceNamespace, err := f.DefaultNamespace() if err != nil { return err } // retrieves resource and annotation args from args // also checks args to verify that all resources are specified before annotations annotationArgs := []string{} metAnnotaionArg := false for _, s := range args { isAnnotation := strings.Contains(s, "=") || strings.HasSuffix(s, "-") switch { case !metAnnotaionArg && isAnnotation: metAnnotaionArg = true fallthrough case metAnnotaionArg && isAnnotation: annotationArgs = append(annotationArgs, s) case !metAnnotaionArg && !isAnnotation: o.resources = append(o.resources, s) case metAnnotaionArg && !isAnnotation: return fmt.Errorf("all resources must be specified before annotation changes: %s", s) } } if len(o.resources) < 1 && len(o.filenames) == 0 { return fmt.Errorf("one or more resources must be specified as <resource> <name> or <resource>/<name>") } if len(annotationArgs) < 1 { return fmt.Errorf("at least one annotation update is required") } if o.newAnnotations, o.removeAnnotations, err = parseAnnotations(annotationArgs); err != nil { return err } o.recordChangeCause = cmdutil.GetRecordFlag(cmd) o.changeCause = f.Command() mapper, typer := f.Object(cmdutil.GetIncludeThirdPartyAPIs(cmd)) o.builder = resource.NewBuilder(mapper, typer, resource.ClientMapperFunc(f.ClientForMapping), f.Decoder(true)). ContinueOnError(). NamespaceParam(namespace).DefaultNamespace(). FilenameParam(enforceNamespace, o.recursive, o.filenames...). SelectorParam(o.selector). ResourceTypeOrNameArgs(o.all, o.resources...). Flatten(). Latest() o.f = f o.out = out o.cmd = cmd return nil }
func RunHistory(f *cmdutil.Factory, cmd *cobra.Command, out io.Writer, args []string, options *HistoryOptions) error { if len(args) == 0 && len(options.Filenames) == 0 { return cmdutil.UsageError(cmd, "Required resource not specified.") } revision := cmdutil.GetFlagInt64(cmd, "revision") if revision < 0 { return fmt.Errorf("revision must be a positive integer: %v", revision) } mapper, typer := f.Object(false) cmdNamespace, enforceNamespace, err := f.DefaultNamespace() if err != nil { return err } r := resource.NewBuilder(mapper, typer, resource.ClientMapperFunc(f.ClientForMapping), f.Decoder(true)). NamespaceParam(cmdNamespace).DefaultNamespace(). FilenameParam(enforceNamespace, options.Recursive, options.Filenames...). ResourceTypeOrNameArgs(true, args...). ContinueOnError(). Latest(). Flatten(). Do() err = r.Err() if err != nil { return err } return r.Visit(func(info *resource.Info, err error) error { if err != nil { return err } mapping := info.ResourceMapping() historyViewer, err := f.HistoryViewer(mapping) if err != nil { return err } historyInfo, err := historyViewer.ViewHistory(info.Namespace, info.Name, revision) if err != nil { return err } header := fmt.Sprintf("%s %q", mapping.Resource, info.Name) if revision > 0 { header = fmt.Sprintf("%s with revision #%d", header, revision) } fmt.Fprintf(out, "%s\n", header) fmt.Fprintf(out, "%s\n", historyInfo) return nil }) }
func getMapperAndResult(f cmdutil.Factory, args []string, options *resource.FilenameOptions, editMode EditMode) (meta.RESTMapper, *resource.Mapper, *resource.Result, string, error) { cmdNamespace, enforceNamespace, err := f.DefaultNamespace() if err != nil { return nil, nil, nil, "", err } var mapper meta.RESTMapper var typer runtime.ObjectTyper switch editMode { case NormalEditMode: mapper, typer = f.Object() case EditBeforeCreateMode: mapper, typer, err = f.UnstructuredObject() default: return nil, nil, nil, "", fmt.Errorf("Not supported edit mode %q", editMode) } if err != nil { return nil, nil, nil, "", err } resourceMapper := &resource.Mapper{ ObjectTyper: typer, RESTMapper: mapper, ClientMapper: resource.ClientMapperFunc(f.ClientForMapping), // NB: we use `f.Decoder(false)` to get a plain deserializer for // the resourceMapper, since it's used to read in edits and // we don't want to convert into the internal version when // reading in edits (this would cause us to potentially try to // compare two different GroupVersions). Decoder: f.Decoder(false), } var b *resource.Builder switch editMode { case NormalEditMode: b = resource.NewBuilder(mapper, typer, resource.ClientMapperFunc(f.ClientForMapping), f.Decoder(true)). ResourceTypeOrNameArgs(true, args...). Latest() case EditBeforeCreateMode: b = resource.NewBuilder(mapper, typer, resource.ClientMapperFunc(f.UnstructuredClientForMapping), runtime.UnstructuredJSONScheme) default: return nil, nil, nil, "", fmt.Errorf("Not supported edit mode %q", editMode) } r := b.NamespaceParam(cmdNamespace).DefaultNamespace(). FilenameParam(enforceNamespace, options). ContinueOnError(). Flatten(). Do() err = r.Err() if err != nil { return nil, nil, nil, "", err } return mapper, resourceMapper, r, cmdNamespace, err }
func RunDescribe(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []string) error { selector := cmdutil.GetFlagString(cmd, "selector") cmdNamespace, enforceNamespace, err := f.DefaultNamespace() if err != nil { return err } filenames := cmdutil.GetFlagStringSlice(cmd, "filename") if len(args) == 0 && len(filenames) == 0 { fmt.Fprint(out, "You must specify the type of resource to describe. ", valid_resources) return cmdutil.UsageError(cmd, "Required resource not specified.") } mapper, typer := f.Object() r := resource.NewBuilder(mapper, typer, f.ClientMapperForCommand()). ContinueOnError(). NamespaceParam(cmdNamespace).DefaultNamespace(). FilenameParam(enforceNamespace, filenames...). SelectorParam(selector). ResourceTypeOrNameArgs(true, args...). Flatten(). Do() err = r.Err() if err != nil { return err } allErrs := []error{} infos, err := r.Infos() if err != nil { if apierrors.IsNotFound(err) && len(args) == 2 { return DescribeMatchingResources(mapper, typer, f, cmdNamespace, args[0], args[1], out, err) } allErrs = append(allErrs, err) } for _, info := range infos { mapping := info.ResourceMapping() describer, err := f.Describer(mapping) if err != nil { allErrs = append(allErrs, err) continue } s, err := describer.Describe(info.Namespace, info.Name) if err != nil { allErrs = append(allErrs, err) continue } fmt.Fprintf(out, "%s\n\n", s) } return errors.NewAggregate(allErrs) }
// Complete collects information required to run Convert command from command line. func (o *ConvertOptions) Complete(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []string) (err error) { o.outputVersion, err = cmdutil.OutputVersion(cmd, ®istered.EnabledVersionsForGroup(api.GroupName)[0]) if err != nil { return err } if !registered.IsEnabledVersion(o.outputVersion) { cmdutil.UsageError(cmd, "'%s' is not a registered version.", o.outputVersion) } // build the builder mapper, typer := f.Object(cmdutil.GetIncludeThirdPartyAPIs(cmd)) clientMapper := resource.ClientMapperFunc(f.ClientForMapping) if o.local { fmt.Fprintln(os.Stderr, "running in local mode...") o.builder = resource.NewBuilder(mapper, typer, resource.DisabledClientForMapping{ClientMapper: clientMapper}, f.Decoder(true)) } else { o.builder = resource.NewBuilder(mapper, typer, clientMapper, f.Decoder(true)) schema, err := f.Validator(cmdutil.GetFlagBool(cmd, "validate"), cmdutil.GetFlagString(cmd, "schema-cache-dir")) if err != nil { return err } o.builder = o.builder.Schema(schema) } cmdNamespace, _, err := f.DefaultNamespace() if err != nil { return err } o.builder = o.builder.NamespaceParam(cmdNamespace). ContinueOnError(). FilenameParam(false, o.recursive, o.filenames...). Flatten() // build the printer o.out = out outputFormat := cmdutil.GetFlagString(cmd, "output") templateFile := cmdutil.GetFlagString(cmd, "template") if len(outputFormat) == 0 { if len(templateFile) == 0 { outputFormat = "yaml" } else { outputFormat = "template" } } o.encoder = f.JSONEncoder() o.printer, _, err = kubectl.GetPrinter(outputFormat, templateFile, false) if err != nil { return err } return nil }