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 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 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 }
func RunPatch(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []string, shortOutput bool) error { cmdNamespace, _, 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") } mapper, typer := f.Object() r := resource.NewBuilder(mapper, typer, f.ClientMapperForCommand()). ContinueOnError(). NamespaceParam(cmdNamespace).DefaultNamespace(). ResourceTypeOrNameArgs(false, args...). Flatten(). Do() err = r.Err() if err != nil { return err } mapping, err := r.ResourceMapping() if err != nil { return err } client, err := f.RESTClient(mapping) if err != nil { return err } infos, err := r.Infos() if err != nil { return err } name, namespace := infos[0].Name, infos[0].Namespace helper := resource.NewHelper(client, mapping) _, err = helper.Patch(namespace, name, api.StrategicMergePatchType, []byte(patch)) if err != nil { return err } cmdutil.PrintSuccess(mapper, shortOutput, out, "", name, "patched") return nil }
// RunCreateSubcommand executes a create subcommand using the specified options func RunCreateSubcommand(f *cmdutil.Factory, cmd *cobra.Command, out io.Writer, options *CreateSubcommandOptions) error { namespace, _, err := f.DefaultNamespace() if err != nil { return err } obj, err := options.StructuredGenerator.StructuredGenerate() if err != nil { return err } mapper, typer := f.Object() gvk, err := typer.ObjectKind(obj) mapping, err := mapper.RESTMapping(unversioned.GroupKind{Group: gvk.Group, Kind: gvk.Kind}, gvk.Version) if err != nil { return err } client, err := f.RESTClient(mapping) if err != nil { return err } resourceMapper := &resource.Mapper{ObjectTyper: typer, RESTMapper: mapper, ClientMapper: f.ClientMapperForCommand()} info, err := resourceMapper.InfoForObject(obj) if err != nil { return err } if err := kubectl.UpdateApplyAnnotation(info); err != nil { return err } if !options.DryRun { obj, err = resource.NewHelper(client, mapping).Create(namespace, false, info.Object) if err != nil { return err } } if useShortOutput := options.OutputFormat == "name"; useShortOutput || len(options.OutputFormat) == 0 { cmdutil.PrintSuccess(mapper, useShortOutput, out, mapping.Resource, options.Name, "created") return nil } return f.PrintObject(cmd, obj, out) }
// Complete completes all the required options for port-forward cmd. func (o *PortForwardOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args []string, cmdOut io.Writer, cmdErr io.Writer) error { var err error o.PodName = cmdutil.GetFlagString(cmd, "pod") if len(o.PodName) == 0 && len(args) == 0 { return cmdutil.UsageError(cmd, "POD is required for port-forward") } if len(o.PodName) != 0 { printDeprecationWarning("port-forward POD", "-p POD") o.Ports = args } else { o.PodName = args[0] o.Ports = args[1:] } o.Namespace, _, err = f.DefaultNamespace() if err != nil { return err } clientset, err := f.ClientSet() if err != nil { return err } o.PodClient = clientset.Core() o.Config, err = f.ClientConfig() if err != nil { return err } o.RESTClient, err = f.RESTClient() if err != nil { return err } o.StopChannel = make(chan struct{}, 1) o.ReadyChannel = make(chan struct{}) return nil }
// RunAnnotate does the work func (o AnnotateOptions) RunAnnotate(f *cmdutil.Factory) error { r := o.builder.Do() if err := r.Err(); err != nil { return err } return r.Visit(func(info *resource.Info, err error) error { if err != nil { return err } name, namespace, obj := info.Name, info.Namespace, info.Object oldData, err := json.Marshal(obj) if err != nil { return err } if err := o.updateAnnotations(obj); err != nil { return err } newData, err := json.Marshal(obj) if err != nil { return err } patchBytes, err := strategicpatch.CreateTwoWayMergePatch(oldData, newData, obj) if err != nil { return err } 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) return err }) }
func Run(f *cmdutil.Factory, cmdIn io.Reader, cmdOut, cmdErr io.Writer, cmd *cobra.Command, args []string) error { if len(os.Args) > 1 && os.Args[1] == "run-container" { printDeprecationWarning("run", "run-container") } if len(args) != 1 { return cmdutil.UsageError(cmd, "NAME is required for run") } interactive := cmdutil.GetFlagBool(cmd, "stdin") tty := cmdutil.GetFlagBool(cmd, "tty") if tty && !interactive { return cmdutil.UsageError(cmd, "-i/--stdin is required for containers with --tty=true") } replicas := cmdutil.GetFlagInt(cmd, "replicas") if interactive && replicas != 1 { return cmdutil.UsageError(cmd, fmt.Sprintf("-i/--stdin requires that replicas is 1, found %d", replicas)) } namespace, _, err := f.DefaultNamespace() if err != nil { return err } restartPolicy, err := getRestartPolicy(cmd, interactive) if err != nil { return err } if restartPolicy != api.RestartPolicyAlways && replicas != 1 { return cmdutil.UsageError(cmd, fmt.Sprintf("--restart=%s requires that --repliacs=1, found %d", restartPolicy, replicas)) } generatorName := cmdutil.GetFlagString(cmd, "generator") if len(generatorName) == 0 { if restartPolicy == api.RestartPolicyAlways { generatorName = "run/v1" } else { generatorName = "run-pod/v1" } } generator, found := f.Generator(generatorName) if !found { return cmdutil.UsageError(cmd, fmt.Sprintf("Generator: %s not found.", generatorName)) } names := generator.ParamNames() params := kubectl.MakeParams(cmd, names) params["name"] = args[0] err = kubectl.ValidateParams(names, params) if err != nil { return err } obj, err := generator.Generate(params) if err != nil { return err } mapper, typer := f.Object() version, kind, err := typer.ObjectVersionAndKind(obj) if err != nil { return err } inline := cmdutil.GetFlagString(cmd, "overrides") if len(inline) > 0 { obj, err = cmdutil.Merge(obj, inline, kind) if err != nil { return err } } mapping, err := mapper.RESTMapping(kind, version) if err != nil { return err } client, err := f.RESTClient(mapping) if err != nil { return err } // TODO: extract this flag to a central location, when such a location exists. if !cmdutil.GetFlagBool(cmd, "dry-run") { data, err := mapping.Codec.Encode(obj) if err != nil { return err } obj, err = resource.NewHelper(client, mapping).Create(namespace, false, data) if err != nil { return err } } attachFlag := cmd.Flags().Lookup("attach") attach := cmdutil.GetFlagBool(cmd, "attach") if !attachFlag.Changed && interactive { attach = true } if attach { opts := &AttachOptions{ In: cmdIn, Out: cmdOut, Err: cmdErr, Stdin: interactive, TTY: tty, Attach: &DefaultRemoteAttach{}, } config, err := f.ClientConfig() if err != nil { return err } opts.Config = config client, err := f.Client() if err != nil { return err } opts.Client = client // TODO: this should be abstracted into Factory to support other types switch t := obj.(type) { case *api.ReplicationController: return handleAttachReplicationController(client, t, opts) case *api.Pod: return handleAttachPod(client, t, opts) default: return fmt.Errorf("cannot attach to %s: not implemented", kind) } } return f.PrintObject(cmd, obj, cmdOut) }
func RunLabel(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []string, options *LabelOptions) error { resources, labelArgs := []string{}, []string{} first := true for _, s := range args { isLabel := strings.Contains(s, "=") || strings.HasSuffix(s, "-") switch { case first && isLabel: first = false fallthrough case !first && isLabel: labelArgs = append(labelArgs, s) case first && !isLabel: resources = append(resources, s) case !first && !isLabel: return cmdutil.UsageError(cmd, "all resources must be specified before label changes: %s", s) } } if len(resources) < 1 && len(options.Filenames) == 0 { return cmdutil.UsageError(cmd, "one or more resources must be specified as <resource> <name> or <resource>/<name>") } if len(labelArgs) < 1 { return cmdutil.UsageError(cmd, "at least one label update is required") } selector := cmdutil.GetFlagString(cmd, "selector") all := cmdutil.GetFlagBool(cmd, "all") overwrite := cmdutil.GetFlagBool(cmd, "overwrite") resourceVersion := cmdutil.GetFlagString(cmd, "resource-version") cmdNamespace, enforceNamespace, err := f.DefaultNamespace() if err != nil { return err } lbls, remove, err := parseLabels(labelArgs) if err != nil { return cmdutil.UsageError(cmd, err.Error()) } mapper, typer := f.Object() b := resource.NewBuilder(mapper, typer, f.ClientMapperForCommand()). ContinueOnError(). NamespaceParam(cmdNamespace).DefaultNamespace(). FilenameParam(enforceNamespace, options.Filenames...). SelectorParam(selector). ResourceTypeOrNameArgs(all, resources...). Flatten(). Latest() one := false r := b.Do().IntoSingular(&one) if err := r.Err(); err != nil { return err } // only apply resource version locking on a single resource if !one && len(resourceVersion) > 0 { return cmdutil.UsageError(cmd, "--resource-version may only be used with a single resource") } // TODO: support bulk generic output a la Get return r.Visit(func(info *resource.Info, err error) error { if err != nil { return err } var outputObj runtime.Object dataChangeMsg := "not labeled" if cmdutil.GetFlagBool(cmd, "dry-run") { err = labelFunc(info.Object, overwrite, resourceVersion, lbls, remove) if err != nil { return err } outputObj = info.Object } else { name, namespace, obj := info.Name, info.Namespace, info.Object oldData, err := json.Marshal(obj) if err != nil { return err } meta, err := api.ObjectMetaFor(obj) for _, label := range remove { if _, ok := meta.Labels[label]; !ok { fmt.Fprintf(out, "label %q not found.\n", label) } } if err := labelFunc(obj, overwrite, resourceVersion, lbls, remove); err != nil { return err } newData, err := json.Marshal(obj) if err != nil { return err } if !reflect.DeepEqual(oldData, newData) { dataChangeMsg = "labeled" } patchBytes, err := strategicpatch.CreateTwoWayMergePatch(oldData, newData, obj) if err != nil { return err } mapping := info.ResourceMapping() client, err := f.RESTClient(mapping) if err != nil { return err } helper := resource.NewHelper(client, mapping) outputObj, err = helper.Patch(namespace, name, api.StrategicMergePatchType, patchBytes) if err != nil { return err } } outputFormat := cmdutil.GetFlagString(cmd, "output") if outputFormat != "" { return f.PrintObject(cmd, outputObj, out) } cmdutil.PrintSuccess(mapper, false, out, info.Mapping.Resource, info.Name, dataChangeMsg) return nil }) }
func RunExpose(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []string) error { namespace, enforceNamespace, err := f.DefaultNamespace() if err != nil { return err } mapper, typer := f.Object() r := resource.NewBuilder(mapper, typer, f.ClientMapperForCommand()). ContinueOnError(). NamespaceParam(namespace).DefaultNamespace(). FilenameParam(enforceNamespace, cmdutil.GetFlagStringSlice(cmd, "filename")...). 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: %v", args) } info := infos[0] mapping := info.ResourceMapping() // Get the input object client, err := f.RESTClient(mapping) if err != nil { return err } inputObject, err := resource.NewHelper(client, mapping).Get(info.Namespace, info.Name) if err != nil { return err } // Get the generator, setup and validate all required parameters generatorName := cmdutil.GetFlagString(cmd, "generator") generator, found := f.Generator(generatorName) if !found { return cmdutil.UsageError(cmd, fmt.Sprintf("generator %q not found.", generatorName)) } names := generator.ParamNames() params := kubectl.MakeParams(cmd, names) params["default-name"] = info.Name if s, found := params["selector"]; !found || kubectl.IsZero(s) || cmdutil.GetFlagInt(cmd, "port") < 1 { if kubectl.IsZero(s) { s, err := f.PodSelectorForObject(inputObject) if err != nil { return cmdutil.UsageError(cmd, fmt.Sprintf("couldn't find selectors via --selector flag or introspection: %s", err)) } params["selector"] = s } noPorts := true for _, param := range names { if param.Name == "port" { noPorts = false break } } if cmdutil.GetFlagInt(cmd, "port") < 0 && !noPorts { ports, err := f.PortsForObject(inputObject) if err != nil { return cmdutil.UsageError(cmd, fmt.Sprintf("couldn't find port via --port flag or introspection: %s", err)) } switch len(ports) { case 0: return cmdutil.UsageError(cmd, "couldn't find port via --port flag or introspection") case 1: params["port"] = ports[0] default: return cmdutil.UsageError(cmd, fmt.Sprintf("multiple ports to choose from: %v, please explicitly specify a port using the --port flag.", ports)) } } } if cmdutil.GetFlagBool(cmd, "create-external-load-balancer") { params["create-external-load-balancer"] = "true" } if kubectl.IsZero(params["labels"]) { labels, err := f.LabelsForObject(inputObject) if err != nil { return err } params["labels"] = kubectl.MakeLabels(labels) } if v := cmdutil.GetFlagString(cmd, "type"); v != "" { params["type"] = v } err = kubectl.ValidateParams(names, params) if err != nil { return err } // Expose new object object, err := generator.Generate(params) if err != nil { return err } inline := cmdutil.GetFlagString(cmd, "overrides") if len(inline) > 0 { object, err = cmdutil.Merge(object, inline, mapping.Kind) if err != nil { return 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(object) if err != nil { return err } data, err := info.Mapping.Codec.Encode(object) if err != nil { return err } _, err = resource.NewHelper(info.Client, info.Mapping).Create(namespace, false, data) if err != nil { return err } } return f.PrintObject(cmd, object, out) }
// RunGet implements the generic Get command // TODO: convert all direct flag accessors to a struct and pass that instead of cmd func RunGet(f cmdutil.Factory, out, errOut io.Writer, cmd *cobra.Command, args []string, options *GetOptions) error { if len(options.Raw) > 0 { restClient, err := f.RESTClient() if err != nil { return err } stream, err := restClient.Get().RequestURI(options.Raw).Stream() if err != nil { return err } defer stream.Close() _, err = io.Copy(out, stream) if err != nil && err != io.EOF { return err } return nil } selector := cmdutil.GetFlagString(cmd, "selector") allNamespaces := cmdutil.GetFlagBool(cmd, "all-namespaces") showKind := cmdutil.GetFlagBool(cmd, "show-kind") mapper, typer, err := f.UnstructuredObject() if err != nil { return err } filterFuncs := f.DefaultResourceFilterFunc() filterOpts := f.DefaultResourceFilterOptions(cmd, allNamespaces) cmdNamespace, enforceNamespace, err := f.DefaultNamespace() if err != nil { return err } if allNamespaces { enforceNamespace = false } if len(args) == 0 && cmdutil.IsFilenameEmpty(options.Filenames) { fmt.Fprint(errOut, "You must specify the type of resource to get. ", valid_resources) fullCmdName := cmd.Parent().CommandPath() usageString := "Required resource not specified." if len(fullCmdName) > 0 && cmdutil.IsSiblingCommandExists(cmd, "explain") { usageString = fmt.Sprintf("%s\nUse \"%s explain <resource>\" for a detailed description of that resource (e.g. %[2]s explain pods).", usageString, fullCmdName) } return cmdutil.UsageError(cmd, usageString) } // always show resources when getting by name or filename argsHasNames, err := resource.HasNames(args) if err != nil { return err } if len(options.Filenames) > 0 || argsHasNames { cmd.Flag("show-all").Value.Set("true") } export := cmdutil.GetFlagBool(cmd, "export") // handle watch separately since we cannot watch multiple resource types isWatch, isWatchOnly := cmdutil.GetFlagBool(cmd, "watch"), cmdutil.GetFlagBool(cmd, "watch-only") if isWatch || isWatchOnly { r := resource.NewBuilder(mapper, typer, resource.ClientMapperFunc(f.UnstructuredClientForMapping), runtime.UnstructuredJSONScheme). NamespaceParam(cmdNamespace).DefaultNamespace().AllNamespaces(allNamespaces). FilenameParam(enforceNamespace, &options.FilenameOptions). SelectorParam(selector). ExportParam(export). ResourceTypeOrNameArgs(true, args...). SingleResourceType(). Latest(). 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("watch is only supported on individual resources and resource collections - %d resources were found", len(infos)) } info := infos[0] mapping := info.ResourceMapping() printer, err := f.PrinterForMapping(cmd, mapping, allNamespaces) if err != nil { return err } obj, err := r.Object() if err != nil { return err } // watching from resourceVersion 0, starts the watch at ~now and // will return an initial watch event. Starting form ~now, rather // the rv of the object will insure that we start the watch from // inside the watch window, which the rv of the object might not be. rv := "0" isList := meta.IsListType(obj) if isList { // the resourceVersion of list objects is ~now but won't return // an initial watch event rv, err = mapping.MetadataAccessor.ResourceVersion(obj) if err != nil { return err } } // print the current object filteredResourceCount := 0 if !isWatchOnly { if err := printer.PrintObj(obj, out); err != nil { return fmt.Errorf("unable to output the provided object: %v", err) } filteredResourceCount++ cmdutil.PrintFilterCount(filteredResourceCount, mapping.Resource, filterOpts) } // print watched changes w, err := r.Watch(rv) if err != nil { return err } first := true filteredResourceCount = 0 intr := interrupt.New(nil, w.Stop) intr.Run(func() error { _, err := watch.Until(0, w, func(e watch.Event) (bool, error) { if !isList && first { // drop the initial watch event in the single resource case first = false return false, nil } err := printer.PrintObj(e.Object, out) if err != nil { return false, err } filteredResourceCount++ cmdutil.PrintFilterCount(filteredResourceCount, mapping.Resource, filterOpts) return false, nil }) return err }) return nil } r := resource.NewBuilder(mapper, typer, resource.ClientMapperFunc(f.UnstructuredClientForMapping), runtime.UnstructuredJSONScheme). NamespaceParam(cmdNamespace).DefaultNamespace().AllNamespaces(allNamespaces). FilenameParam(enforceNamespace, &options.FilenameOptions). SelectorParam(selector). ExportParam(export). ResourceTypeOrNameArgs(true, args...). ContinueOnError(). Latest(). Flatten(). Do() err = r.Err() if err != nil { return err } printer, generic, err := cmdutil.PrinterForCommand(cmd) if err != nil { return err } if generic { // we flattened the data from the builder, so we have individual items, but now we'd like to either: // 1. if there is more than one item, combine them all into a single list // 2. if there is a single item and that item is a list, leave it as its specific list // 3. if there is a single item and it is not a a list, leave it as a single item var errs []error singular := false infos, err := r.IntoSingular(&singular).Infos() if err != nil { if singular { return err } errs = append(errs, err) } if len(infos) == 0 && len(errs) == 0 { outputEmptyListWarning(errOut) } res := "" if len(infos) > 0 { res = infos[0].ResourceMapping().Resource } var obj runtime.Object if singular { obj = infos[0].Object } else { // we have more than one item, so coerce all items into a list list := &runtime.UnstructuredList{ Object: map[string]interface{}{ "kind": "List", "apiVersion": "v1", "metadata": map[string]interface{}{}, }, } for _, info := range infos { list.Items = append(list.Items, info.Object.(*runtime.Unstructured)) } obj = list } isList := meta.IsListType(obj) if isList { filteredResourceCount, items, err := cmdutil.FilterResourceList(obj, filterFuncs, filterOpts) if err != nil { return err } // take the filtered items and create a new list for display list := &runtime.UnstructuredList{ Object: map[string]interface{}{ "kind": "List", "apiVersion": "v1", "metadata": map[string]interface{}{}, }, } if listMeta, err := meta.ListAccessor(obj); err == nil { list.Object["selfLink"] = listMeta.GetSelfLink() list.Object["resourceVersion"] = listMeta.GetResourceVersion() } for _, item := range items { list.Items = append(list.Items, item.(*runtime.Unstructured)) } if err := printer.PrintObj(list, out); err != nil { errs = append(errs, err) } cmdutil.PrintFilterCount(filteredResourceCount, res, filterOpts) return utilerrors.Reduce(utilerrors.Flatten(utilerrors.NewAggregate(errs))) } filteredResourceCount := 0 if isFiltered, err := filterFuncs.Filter(obj, filterOpts); !isFiltered { if err != nil { glog.V(2).Infof("Unable to filter resource: %v", err) } else if err := printer.PrintObj(obj, out); err != nil { errs = append(errs, err) } } else if isFiltered { filteredResourceCount++ } cmdutil.PrintFilterCount(filteredResourceCount, res, filterOpts) return utilerrors.Reduce(utilerrors.Flatten(utilerrors.NewAggregate(errs))) } allErrs := []error{} errs := sets.NewString() infos, err := r.Infos() if err != nil { allErrs = append(allErrs, err) } if len(infos) == 0 && len(allErrs) == 0 { outputEmptyListWarning(errOut) } objs := make([]runtime.Object, len(infos)) for ix := range infos { objs[ix] = infos[ix].Object } sorting, err := cmd.Flags().GetString("sort-by") if err != nil { return err } var sorter *kubectl.RuntimeSort if len(sorting) > 0 && len(objs) > 1 { // TODO: questionable if sorter, err = kubectl.SortObjects(f.Decoder(true), objs, sorting); err != nil { return err } } // use the default printer for each object printer = nil var lastMapping *meta.RESTMapping w := kubectl.GetNewTabWriter(out) filteredResourceCount := 0 if resource.MultipleTypesRequested(args) || cmdutil.MustPrintWithKinds(objs, infos, sorter) { showKind = true } for ix := range objs { var mapping *meta.RESTMapping var original runtime.Object if sorter != nil { mapping = infos[sorter.OriginalPosition(ix)].Mapping original = infos[sorter.OriginalPosition(ix)].Object } else { mapping = infos[ix].Mapping original = infos[ix].Object } if printer == nil || lastMapping == nil || mapping == nil || mapping.Resource != lastMapping.Resource { if printer != nil { w.Flush() cmdutil.PrintFilterCount(filteredResourceCount, lastMapping.Resource, filterOpts) } printer, err = f.PrinterForMapping(cmd, mapping, allNamespaces) if err != nil { if !errs.Has(err.Error()) { errs.Insert(err.Error()) allErrs = append(allErrs, err) } continue } // add linebreak between resource groups (if there is more than one) // skip linebreak above first resource group noHeaders := cmdutil.GetFlagBool(cmd, "no-headers") if lastMapping != nil && !noHeaders { fmt.Fprintf(errOut, "%s\n", "") } lastMapping = mapping } // filter objects if filter has been defined for current object if isFiltered, err := filterFuncs.Filter(original, filterOpts); isFiltered { if err == nil { filteredResourceCount++ continue } if !errs.Has(err.Error()) { errs.Insert(err.Error()) allErrs = append(allErrs, err) } } if resourcePrinter, found := printer.(*kubectl.HumanReadablePrinter); found { resourceName := resourcePrinter.GetResourceKind() if mapping != nil { if resourceName == "" { resourceName = mapping.Resource } if alias, ok := kubectl.ResourceShortFormFor(mapping.Resource); ok { resourceName = alias } else if resourceName == "" { resourceName = "none" } } else { resourceName = "none" } if showKind { resourcePrinter.EnsurePrintWithKind(resourceName) } if err := printer.PrintObj(original, w); err != nil { if !errs.Has(err.Error()) { errs.Insert(err.Error()) allErrs = append(allErrs, err) } } continue } if err := printer.PrintObj(original, w); err != nil { if !errs.Has(err.Error()) { errs.Insert(err.Error()) allErrs = append(allErrs, err) } continue } } w.Flush() if printer != nil && lastMapping != nil { cmdutil.PrintFilterCount(filteredResourceCount, lastMapping.Resource, filterOpts) } return utilerrors.NewAggregate(allErrs) }
// RunGet implements the generic Get command // TODO: convert all direct flag accessors to a struct and pass that instead of cmd func RunGet(f *cmdutil.Factory, out io.Writer, errOut io.Writer, cmd *cobra.Command, args []string, options *GetOptions) error { if len(options.Raw) > 0 { restClient, err := f.RESTClient() if err != nil { return err } stream, err := restClient.Get().RequestURI(options.Raw).Stream() if err != nil { return err } defer stream.Close() for { buffer := make([]byte, 1024, 1024) bytesRead, err := stream.Read(buffer) if bytesRead > 0 { fmt.Printf("%s", string(buffer[:bytesRead])) } if err == io.EOF { return nil } if err != nil { return err } } } selector := cmdutil.GetFlagString(cmd, "selector") allNamespaces := cmdutil.GetFlagBool(cmd, "all-namespaces") showKind := cmdutil.GetFlagBool(cmd, "show-kind") mapper, typer := f.Object() printAll := false cmdNamespace, enforceNamespace, err := f.DefaultNamespace() if err != nil { return err } if allNamespaces { enforceNamespace = false } if len(args) == 0 && cmdutil.IsFilenameEmpty(options.Filenames) { fmt.Fprint(errOut, "You must specify the type of resource to get. ", valid_resources) return cmdutil.UsageError(cmd, "Required resource not specified.") } // determine if args contains "all" for _, a := range args { if a == "all" { printAll = true break } } // always show resources when getting by name or filename argsHasNames, err := resource.HasNames(args) if err != nil { return err } if len(options.Filenames) > 0 || argsHasNames { cmd.Flag("show-all").Value.Set("true") } export := cmdutil.GetFlagBool(cmd, "export") // handle watch separately since we cannot watch multiple resource types isWatch, isWatchOnly := cmdutil.GetFlagBool(cmd, "watch"), cmdutil.GetFlagBool(cmd, "watch-only") if isWatch || isWatchOnly { r := resource.NewBuilder(mapper, typer, resource.ClientMapperFunc(f.ClientForMapping), f.Decoder(true)). NamespaceParam(cmdNamespace).DefaultNamespace().AllNamespaces(allNamespaces). FilenameParam(enforceNamespace, &options.FilenameOptions). SelectorParam(selector). ExportParam(export). ResourceTypeOrNameArgs(true, args...). SingleResourceType(). Latest(). 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("watch is only supported on individual resources and resource collections - %d resources were found", len(infos)) } info := infos[0] mapping := info.ResourceMapping() printer, err := f.PrinterForMapping(cmd, mapping, allNamespaces) if err != nil { return err } obj, err := r.Object() if err != nil { return err } // watching from resourceVersion 0, starts the watch at ~now and // will return an initial watch event. Starting form ~now, rather // the rv of the object will insure that we start the watch from // inside the watch window, which the rv of the object might not be. rv := "0" isList := meta.IsListType(obj) if isList { // the resourceVersion of list objects is ~now but won't return // an initial watch event rv, err = mapping.MetadataAccessor.ResourceVersion(obj) if err != nil { return err } } // print the current object if !isWatchOnly { if err := printer.PrintObj(obj, out); err != nil { return fmt.Errorf("unable to output the provided object: %v", err) } printer.AfterPrint(errOut, mapping.Resource) } // print watched changes w, err := r.Watch(rv) if err != nil { return err } first := true kubectl.WatchLoop(w, func(e watch.Event) error { if !isList && first { // drop the initial watch event in the single resource case first = false return nil } err := printer.PrintObj(e.Object, out) if err == nil { printer.AfterPrint(errOut, mapping.Resource) } return err }) return nil } r := resource.NewBuilder(mapper, typer, resource.ClientMapperFunc(f.ClientForMapping), f.Decoder(true)). NamespaceParam(cmdNamespace).DefaultNamespace().AllNamespaces(allNamespaces). FilenameParam(enforceNamespace, &options.FilenameOptions). SelectorParam(selector). ExportParam(export). ResourceTypeOrNameArgs(true, args...). ContinueOnError(). Latest(). Flatten(). Do() err = r.Err() if err != nil { return err } printer, generic, err := cmdutil.PrinterForCommand(cmd) if err != nil { return err } if generic { clientConfig, err := f.ClientConfig() if err != nil { return err } allErrs := []error{} singular := false infos, err := r.IntoSingular(&singular).Infos() if err != nil { if singular { return err } allErrs = append(allErrs, err) } // the outermost object will be converted to the output-version, but inner // objects can use their mappings version, err := cmdutil.OutputVersion(cmd, clientConfig.GroupVersion) if err != nil { return err } res := "" if len(infos) > 0 { res = infos[0].ResourceMapping().Resource } obj, err := resource.AsVersionedObject(infos, !singular, version, f.JSONEncoder()) if err != nil { return err } if err := printer.PrintObj(obj, out); err != nil { allErrs = append(allErrs, err) } printer.AfterPrint(errOut, res) return utilerrors.NewAggregate(allErrs) } allErrs := []error{} infos, err := r.Infos() if err != nil { allErrs = append(allErrs, err) } objs := make([]runtime.Object, len(infos)) for ix := range infos { objs[ix] = infos[ix].Object } sorting, err := cmd.Flags().GetString("sort-by") if err != nil { return err } var sorter *kubectl.RuntimeSort if len(sorting) > 0 && len(objs) > 1 { clientConfig, err := f.ClientConfig() if err != nil { return err } version, err := cmdutil.OutputVersion(cmd, clientConfig.GroupVersion) if err != nil { return err } for ix := range infos { objs[ix], err = infos[ix].Mapping.ConvertToVersion(infos[ix].Object, version) if err != nil { allErrs = append(allErrs, err) continue } } // TODO: questionable if sorter, err = kubectl.SortObjects(f.Decoder(true), objs, sorting); err != nil { return err } } // use the default printer for each object printer = nil var lastMapping *meta.RESTMapping w := kubectl.GetNewTabWriter(out) if mustPrintWithKinds(objs, infos, sorter, printAll) { showKind = true } for ix := range objs { var mapping *meta.RESTMapping var original runtime.Object if sorter != nil { mapping = infos[sorter.OriginalPosition(ix)].Mapping original = infos[sorter.OriginalPosition(ix)].Object } else { mapping = infos[ix].Mapping original = infos[ix].Object } if printer == nil || lastMapping == nil || mapping == nil || mapping.Resource != lastMapping.Resource { if printer != nil { w.Flush() printer.AfterPrint(errOut, lastMapping.Resource) } printer, err = f.PrinterForMapping(cmd, mapping, allNamespaces) if err != nil { allErrs = append(allErrs, err) continue } lastMapping = mapping } if resourcePrinter, found := printer.(*kubectl.HumanReadablePrinter); found { resourceName := resourcePrinter.GetResourceKind() if mapping != nil { if resourceName == "" { resourceName = mapping.Resource } if alias, ok := kubectl.ResourceShortFormFor(mapping.Resource); ok { resourceName = alias } else if resourceName == "" { resourceName = "none" } } else { resourceName = "none" } if showKind { resourcePrinter.EnsurePrintWithKind(resourceName) } if err := printer.PrintObj(original, w); err != nil { allErrs = append(allErrs, err) } continue } if err := printer.PrintObj(original, w); err != nil { allErrs = append(allErrs, err) continue } } w.Flush() if printer != nil { printer.AfterPrint(errOut, lastMapping.Resource) } return utilerrors.NewAggregate(allErrs) }
func Run(f *cmdutil.Factory, cmdIn io.Reader, cmdOut, cmdErr io.Writer, cmd *cobra.Command, args []string) error { if len(os.Args) > 1 && os.Args[1] == "run-container" { printDeprecationWarning("run", "run-container") } if len(args) == 0 { return cmdutil.UsageError(cmd, "NAME is required for run") } interactive := cmdutil.GetFlagBool(cmd, "stdin") tty := cmdutil.GetFlagBool(cmd, "tty") if tty && !interactive { return cmdutil.UsageError(cmd, "-i/--stdin is required for containers with --tty=true") } replicas := cmdutil.GetFlagInt(cmd, "replicas") if interactive && replicas != 1 { return cmdutil.UsageError(cmd, fmt.Sprintf("-i/--stdin requires that replicas is 1, found %d", replicas)) } namespace, _, err := f.DefaultNamespace() if err != nil { return err } restartPolicy, err := getRestartPolicy(cmd, interactive) if err != nil { return err } if restartPolicy != api.RestartPolicyAlways && replicas != 1 { return cmdutil.UsageError(cmd, fmt.Sprintf("--restart=%s requires that --replicas=1, found %d", restartPolicy, replicas)) } generatorName := cmdutil.GetFlagString(cmd, "generator") if len(generatorName) == 0 { if restartPolicy == api.RestartPolicyAlways { generatorName = "run/v1" } else { generatorName = "run-pod/v1" } } generator, found := f.Generator(generatorName) if !found { return cmdutil.UsageError(cmd, fmt.Sprintf("Generator: %s not found.", generatorName)) } names := generator.ParamNames() params := kubectl.MakeParams(cmd, names) params["name"] = args[0] if len(args) > 1 { params["args"] = args[1:] } params["env"] = cmdutil.GetFlagStringSlice(cmd, "env") err = kubectl.ValidateParams(names, params) if err != nil { return err } obj, err := generator.Generate(params) if err != nil { return err } mapper, typer := f.Object() version, kind, err := typer.ObjectVersionAndKind(obj) if err != nil { return err } inline := cmdutil.GetFlagString(cmd, "overrides") if len(inline) > 0 { obj, err = cmdutil.Merge(obj, inline, kind) if err != nil { return err } } mapping, err := mapper.RESTMapping(kind, version) if err != nil { return err } client, err := f.RESTClient(mapping) if err != nil { return 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 err } // Serialize the configuration into an annotation. if err := kubectl.UpdateApplyAnnotation(info); err != nil { return err } obj, err = resource.NewHelper(client, mapping).Create(namespace, false, info.Object) if err != nil { return err } } attachFlag := cmd.Flags().Lookup("attach") attach := cmdutil.GetFlagBool(cmd, "attach") if !attachFlag.Changed && interactive { attach = true } if attach { opts := &AttachOptions{ In: cmdIn, Out: cmdOut, Err: cmdErr, Stdin: interactive, TTY: tty, Attach: &DefaultRemoteAttach{}, } config, err := f.ClientConfig() if err != nil { return err } opts.Config = config client, err := f.Client() if err != nil { return err } opts.Client = client attachablePod, err := f.AttachablePodForObject(obj) if err != nil { return err } return handleAttachPod(f, client, attachablePod, opts) } outputFormat := cmdutil.GetFlagString(cmd, "output") if outputFormat != "" { return f.PrintObject(cmd, obj, cmdOut) } cmdutil.PrintSuccess(mapper, false, cmdOut, mapping.Resource, args[0], "created") return nil }