Пример #1
0
func (f *Factory) NewCmdGet(out io.Writer) *cobra.Command {
	cmd := &cobra.Command{
		Use:   "get [(-o|--output=)json|yaml|...] <resource> [<id>]",
		Short: "Display one or many resources",
		Long: `Display one or many resources.

Possible resources include pods (po), replication controllers (rc), services
(se), minions (mi), or events (ev).

If you specify a Go template, you can use any fields defined for the API version
you are connecting to the server with.

Examples:
  $ kubectl get pods
  <list all pods in ps output format>

  $ kubectl get replicationController 1234-56-7890-234234-456456
  <list single replication controller in ps output format>

  $ kubectl get -f json pod 1234-56-7890-234234-456456
  <list single pod in json output format>`,
		Run: func(cmd *cobra.Command, args []string) {
			mapping, namespace, name := ResourceOrTypeFromArgs(cmd, args, f.Mapper)

			selector := GetFlagString(cmd, "selector")
			labels, err := labels.ParseSelector(selector)
			checkErr(err)

			client, err := f.Client(cmd, mapping)
			checkErr(err)

			outputFormat := GetFlagString(cmd, "output")
			templateFile := GetFlagString(cmd, "template")
			defaultPrinter, err := f.Printer(cmd, mapping, GetFlagBool(cmd, "no-headers"))
			checkErr(err)

			outputVersion := GetFlagString(cmd, "output-version")
			if len(outputVersion) == 0 {
				outputVersion = mapping.APIVersion
			}
			printer, err := kubectl.GetPrinter(outputVersion, outputFormat, templateFile, defaultPrinter)
			checkErr(err)

			obj, err := kubectl.NewRESTHelper(client, mapping).Get(namespace, name, labels)
			checkErr(err)

			if err := printer.PrintObj(obj, out); err != nil {
				checkErr(fmt.Errorf("Unable to output the provided object: %v", err))
			}
		},
	}
	cmd.Flags().StringP("output", "o", "", "Output format: json|yaml|template|templatefile")
	cmd.Flags().String("output-version", "", "Output the formatted object with the given version (default api-version)")
	cmd.Flags().Bool("no-headers", false, "When using the default output, don't print headers")
	cmd.Flags().StringP("template", "t", "", "Template string or path to template file to use when --output=template or --output=templatefile")
	cmd.Flags().StringP("selector", "l", "", "Selector (label query) to filter on")
	return cmd
}
Пример #2
0
// PrinterForCommand returns the default printer for this command.
// Requires that printer flags have been added to cmd (see AddPrinterFlags).
func PrinterForCommand(cmd *cobra.Command) (kubectl.ResourcePrinter, bool, error) {
	outputFormat := GetFlagString(cmd, "output")
	templateFile := GetFlagString(cmd, "template")
	if len(outputFormat) == 0 && len(templateFile) != 0 {
		outputFormat = "template"
	}

	return kubectl.GetPrinter(outputFormat, templateFile)
}
Пример #3
0
// Print prints a deployment config in the specified format with the given
// template.
func (r *helper) Print(config *deployapi.DeploymentConfig, format, template string, out io.Writer) error {
	printer, _, err := kubectl.GetPrinter(format, template)
	if err != nil {
		return err
	}
	versionedPrinter := kubectl.NewVersionedPrinter(printer, kapi.Scheme, latest.Version)
	versionedPrinter.PrintObj(config, out)
	return nil
}
Пример #4
0
func GenDocs(cmd *cobra.Command, filename string) error {
	out := new(bytes.Buffer)
	templateFile, err := filepath.Abs("hack/clibyexample/template")
	if err != nil {
		return err
	}
	template, err := ioutil.ReadFile(templateFile)
	if err != nil {
		return err
	}

	examples := extractExamples(cmd)
	items := []runtime.Object{}
	for _, example := range examples {
		items = append(items, example)
	}

	printer, _, err := kubectl.GetPrinter("template", string(template))
	if err != nil {
		return err
	}

	err = printer.PrintObj(&kapi.List{
		ListMeta: kapi.ListMeta{},
		Items:    items,
	}, out)
	if err != nil {
		return err
	}

	outFile, err := os.Create(filename)
	if err != nil {
		return err
	}
	defer outFile.Close()

	_, err = outFile.Write(out.Bytes())
	if err != nil {
		return err
	}
	return nil
}
Пример #5
0
func (v *VolumeOptions) RunVolume(args []string) error {
	b := resource.NewBuilder(v.Mapper, v.Typer, resource.ClientMapperFunc(v.RESTClientFactory)).
		ContinueOnError().
		NamespaceParam(v.DefaultNamespace).DefaultNamespace().
		FilenameParam(v.Filenames...).
		SelectorParam(v.Selector).
		ResourceTypeOrNameArgs(v.All, args...).
		Flatten()

	one := false
	infos, err := b.Do().IntoSingular(&one).Infos()
	if err != nil {
		return err
	}

	skipped := 0
	for _, info := range infos {
		ok, err := v.UpdatePodSpecForObject(info.Object, func(spec *kapi.PodSpec) error {
			var e error
			switch {
			case v.Add:
				e = v.addVolumeToSpec(spec)
			case v.Remove:
				e = v.removeVolumeFromSpec(spec)
			case v.List:
				e = v.listVolumeForSpec(spec, info)
			}
			return e
		})
		if !ok {
			skipped++
			continue
		}
		if err != nil {
			fmt.Fprintf(v.Writer, "error: %s/%s %v\n", info.Mapping.Resource, info.Name, err)
			continue
		}
	}
	if one && skipped == len(infos) {
		return fmt.Errorf("the %s %s is not a pod or does not have a pod template", infos[0].Mapping.Resource, infos[0].Name)
	}

	if v.List {
		return nil
	}

	objects, err := resource.AsVersionedObject(infos, false, v.OutputVersion)
	if err != nil {
		return err
	}

	if len(v.Output) != 0 {
		p, _, err := kubectl.GetPrinter(v.Output, "")
		if err != nil {
			return err
		}
		return p.PrintObj(objects, v.Writer)
	}

	failed := false
	for _, info := range infos {
		data, err := info.Mapping.Codec.Encode(info.Object)
		if err != nil {
			fmt.Fprintf(v.Writer, "Error: %v\n", err)
			failed = true
			continue
		}
		obj, err := resource.NewHelper(info.Client, info.Mapping).Update(info.Namespace, info.Name, true, data)
		if err != nil {
			handlePodUpdateError(v.Writer, err, "volume")
			failed = true
			continue
		}
		info.Refresh(obj, true)
		fmt.Fprintf(v.Writer, "%s/%s\n", info.Mapping.Resource, info.Name)
	}
	if failed {
		return errExit
	}
	return nil
}
Пример #6
0
// RunEnv contains all the necessary functionality for the OpenShift cli env command
func RunEnv(f *clientcmd.Factory, in io.Reader, out io.Writer, cmd *cobra.Command, args []string, envParams, filenames kutil.StringList) error {
	resources, envArgs := []string{}, []string{}
	first := true
	for _, s := range args {
		isEnv := strings.Contains(s, "=") || strings.HasSuffix(s, "-")
		switch {
		case first && isEnv:
			first = false
			fallthrough
		case !first && isEnv:
			envArgs = append(envArgs, s)
		case first && !isEnv:
			resources = append(resources, s)
		case !first && !isEnv:
			return cmdutil.UsageError(cmd, "all resources must be specified before environment changes: %s", s)
		}
	}
	if len(filenames) == 0 && len(resources) < 1 {
		return cmdutil.UsageError(cmd, "one or more resources must be specified as <resource> <name> or <resource>/<name>")
	}

	containerMatch := cmdutil.GetFlagString(cmd, "containers")
	list := cmdutil.GetFlagBool(cmd, "list")
	selector := cmdutil.GetFlagString(cmd, "selector")
	all := cmdutil.GetFlagBool(cmd, "all")
	//overwrite := cmdutil.GetFlagBool(cmd, "overwrite")
	resourceVersion := cmdutil.GetFlagString(cmd, "resource-version")
	outputFormat := cmdutil.GetFlagString(cmd, "output")

	if list && len(outputFormat) > 0 {
		return cmdutil.UsageError(cmd, "--list and --output may not be specified together")
	}

	clientConfig, err := f.ClientConfig()
	if err != nil {
		return err
	}
	outputVersion := cmdutil.OutputVersion(cmd, clientConfig.Version)

	cmdNamespace, err := f.DefaultNamespace()
	if err != nil {
		return err
	}

	env, remove, err := parseEnv(append(envParams, envArgs...), in)
	if err != nil {
		return err
	}

	mapper, typer := f.Object()
	b := resource.NewBuilder(mapper, typer, f.ClientMapperForCommand()).
		ContinueOnError().
		NamespaceParam(cmdNamespace).DefaultNamespace().
		FilenameParam(filenames...).
		SelectorParam(selector).
		ResourceTypeOrNameArgs(all, resources...).
		Flatten()

	one := false
	infos, err := b.Do().IntoSingular(&one).Infos()
	if 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")
	}

	skipped := 0
	for _, info := range infos {
		ok, err := f.UpdatePodSpecForObject(info.Object, func(spec *kapi.PodSpec) error {
			containers, _ := selectContainers(spec.Containers, containerMatch)
			if len(containers) == 0 {
				fmt.Fprintf(cmd.Out(), "warning: %s/%s does not have any containers matching %q\n", info.Mapping.Resource, info.Name, containerMatch)
				return nil
			}
			for _, c := range containers {
				c.Env = updateEnv(c.Env, env, remove)

				if list {
					fmt.Fprintf(out, "# %s %s, container %s\n", info.Mapping.Resource, info.Name, c.Name)
					for _, env := range c.Env {
						// if env.ValueFrom != nil && env.ValueFrom.FieldRef != nil {
						// 	fmt.Fprintf(cmd.Out(), "%s= # calculated from pod %s %s\n", env.Name, env.ValueFrom.FieldRef.FieldPath, env.ValueFrom.FieldRef.APIVersion)
						// 	continue
						// }
						fmt.Fprintf(out, "%s=%s\n", env.Name, env.Value)

					}
				}
			}
			return nil
		})
		if !ok {
			skipped++
			continue
		}
		if err != nil {
			fmt.Fprintf(cmd.Out(), "error: %s/%s %v\n", info.Mapping.Resource, info.Name, err)
			continue
		}
	}
	if one && skipped == len(infos) {
		return fmt.Errorf("the %s %s is not a pod or does not have a pod template", infos[0].Mapping.Resource, infos[0].Name)
	}

	if list {
		return nil
	}

	objects, err := resource.AsVersionedObject(infos, false, outputVersion)
	if err != nil {
		return err
	}

	if len(outputFormat) != 0 {
		p, _, err := kubectl.GetPrinter(outputFormat, "")
		if err != nil {
			return err
		}
		return p.PrintObj(objects, out)
	}

	failed := false
	for _, info := range infos {
		data, err := info.Mapping.Codec.Encode(info.Object)
		if err != nil {
			fmt.Fprintf(cmd.Out(), "Error: %v\n", err)
			failed = true
			continue
		}
		obj, err := resource.NewHelper(info.Client, info.Mapping).Update(info.Namespace, info.Name, true, data)
		if err != nil {
			handlePodUpdateError(cmd.Out(), err, "environment variables")
			failed = true
			continue
		}
		info.Refresh(obj, true)
		fmt.Fprintf(out, "%s/%s\n", info.Mapping.Resource, info.Name)
	}
	if failed {
		return errExit
	}
	return nil
}
Пример #7
0
// Run performs a rollback.
func (o *RollbackOptions) Run() error {
	// Get the resource referenced in the command args.
	obj, err := o.findResource(o.TargetName)
	if err != nil {
		return err
	}

	// Interpret the resource to resolve a target for rollback.
	var target *kapi.ReplicationController
	switch r := obj.(type) {
	case *kapi.ReplicationController:
		// A specific deployment was used.
		target = r
	case *deployapi.DeploymentConfig:
		// A deploymentconfig was used. Find the target deployment by the
		// specified version, or by a lookup of the last completed deployment if
		// no version was supplied.
		deployment, err := o.findTargetDeployment(r, o.DesiredVersion)
		if err != nil {
			return err
		}
		target = deployment
	}
	if target == nil {
		return fmt.Errorf("%s is not a valid deployment or deploymentconfig", o.TargetName)
	}

	// Set up the rollback and generate a new rolled back config.
	rollback := &deployapi.DeploymentConfigRollback{
		Spec: deployapi.DeploymentConfigRollbackSpec{
			From: kapi.ObjectReference{
				Name: target.Name,
			},
			IncludeTemplate:        true,
			IncludeTriggers:        o.IncludeTriggers,
			IncludeStrategy:        o.IncludeStrategy,
			IncludeReplicationMeta: o.IncludeScalingSettings,
		},
	}
	newConfig, err := o.oc.DeploymentConfigs(o.Namespace).Rollback(rollback)
	if err != nil {
		return err
	}

	// If this is a dry run, print and exit.
	if o.DryRun {
		describer := describe.NewDeploymentConfigDescriberForConfig(o.oc, o.kc, newConfig)
		description, err := describer.Describe(newConfig.Namespace, newConfig.Name)
		if err != nil {
			return err
		}
		o.out.Write([]byte(description))
		return nil
	}

	// If an output format is specified, print and exit.
	if len(o.Format) > 0 {
		printer, _, err := kubectl.GetPrinter(o.Format, o.Template)
		if err != nil {
			return err
		}
		versionedPrinter := kubectl.NewVersionedPrinter(printer, kapi.Scheme, latest.Version)
		versionedPrinter.PrintObj(newConfig, o.out)
		return nil
	}

	// Perform a real rollback.
	rolledback, err := o.oc.DeploymentConfigs(newConfig.Namespace).Update(newConfig)
	if err != nil {
		return err
	}

	// Print warnings about any image triggers disabled during the rollback.
	fmt.Fprintf(o.out, "#%d rolled back to %s\n", rolledback.LatestVersion, rollback.Spec.From.Name)
	for _, trigger := range rolledback.Triggers {
		disabled := []string{}
		if trigger.Type == deployapi.DeploymentTriggerOnImageChange && !trigger.ImageChangeParams.Automatic {
			disabled = append(disabled, trigger.ImageChangeParams.From.Name)
		}
		if len(disabled) > 0 {
			reenable := fmt.Sprintf("oc deploy %s --enable-triggers", rolledback.Name)
			fmt.Fprintf(o.out, "Warning: the following images triggers were disabled: %s\n  You can re-enable them with: %s\n", strings.Join(disabled, ","), reenable)
		}
	}

	return nil
}
Пример #8
0
func RunExport(f *clientcmd.Factory, exporter Exporter, in io.Reader, out io.Writer, cmd *cobra.Command, args []string, filenames util.StringList) error {
	selector := cmdutil.GetFlagString(cmd, "selector")
	all := cmdutil.GetFlagBool(cmd, "all")
	exact := cmdutil.GetFlagBool(cmd, "exact")
	asTemplate := cmdutil.GetFlagString(cmd, "as-template")
	raw := cmdutil.GetFlagBool(cmd, "raw")
	if exact && raw {
		return cmdutil.UsageError(cmd, "--exact and --raw may not both be specified")
	}

	clientConfig, err := f.ClientConfig()
	if err != nil {
		return err
	}
	outputVersion := cmdutil.OutputVersion(cmd, clientConfig.Version)

	cmdNamespace, explicit, err := f.DefaultNamespace()
	if err != nil {
		return err
	}

	mapper, typer := f.Object()
	b := resource.NewBuilder(mapper, typer, f.ClientMapperForCommand()).
		NamespaceParam(cmdNamespace).DefaultNamespace().
		FilenameParam(explicit, filenames...).
		SelectorParam(selector).
		ResourceTypeOrNameArgs(all, args...).
		Flatten()

	one := false
	infos, err := b.Do().IntoSingular(&one).Infos()
	if err != nil {
		return err
	}

	if len(infos) == 0 {
		return fmt.Errorf("no resources found - nothing to export")
	}

	if !raw {
		newInfos := []*resource.Info{}
		errs := []error{}
		for _, info := range infos {
			if err := exporter.Export(info.Object, exact); err != nil {
				if err == ErrExportOmit {
					continue
				}
				errs = append(errs, err)
			}
			newInfos = append(newInfos, info)
		}
		if len(errs) > 0 {
			return utilerrors.NewAggregate(errs)
		}
		infos = newInfos
	}

	var result runtime.Object
	if len(asTemplate) > 0 {
		objects, err := resource.AsVersionedObjects(infos, outputVersion)
		if err != nil {
			return err
		}
		template := &templateapi.Template{
			Objects: objects,
		}
		template.Name = asTemplate
		result, err = kapi.Scheme.ConvertToVersion(template, outputVersion)
		if err != nil {
			return err
		}
	} else {
		object, err := resource.AsVersionedObject(infos, !one, outputVersion)
		if err != nil {
			return err
		}
		result = object
	}

	// use YAML as the default format
	outputFormat := cmdutil.GetFlagString(cmd, "output")
	templateFile := cmdutil.GetFlagString(cmd, "template")
	if len(outputFormat) == 0 && len(templateFile) != 0 {
		outputFormat = "template"
	}
	if len(outputFormat) == 0 {
		outputFormat = "yaml"
	}
	p, _, err := kubectl.GetPrinter(outputFormat, templateFile)
	if err != nil {
		return err
	}
	return p.PrintObj(result, out)
}
Пример #9
0
// RunProject contains all the necessary functionality for the OpenShift cli process command
func RunProcess(f *clientcmd.Factory, out io.Writer, cmd *cobra.Command, args []string) error {
	storedTemplate := ""
	if len(args) > 0 {
		storedTemplate = args[0]
	}

	filename := kcmdutil.GetFlagString(cmd, "filename")
	if len(storedTemplate) == 0 && len(filename) == 0 {
		return kcmdutil.UsageError(cmd, "Must pass a filename or name of stored template")
	}

	namespace, err := f.DefaultNamespace()
	if err != nil {
		return err
	}

	mapper, typer := f.Object()

	client, _, err := f.Clients()
	if err != nil {
		return err
	}

	var (
		objects []runtime.Object
		infos   []*resource.Info
		mapping *meta.RESTMapping
	)

	version, kind, err := mapper.VersionAndKindForResource("template")
	if mapping, err = mapper.RESTMapping(kind, version); err != nil {
		return err
	}

	// When storedTemplate is not empty, then we fetch the template from the
	// server, otherwise we require to set the `-f` parameter.
	if len(storedTemplate) > 0 {
		templateObj, err := client.Templates(namespace).Get(storedTemplate)
		if err != nil {
			if errors.IsNotFound(err) {
				return fmt.Errorf("template %q could not be found", storedTemplate)
			}
			return err
		}
		templateObj.CreationTimestamp = util.Now()
		infos = append(infos, &resource.Info{Object: templateObj})
	} else {
		infos, err = resource.NewBuilder(mapper, typer, f.ClientMapperForCommand()).
			NamespaceParam(namespace).RequireNamespace().
			FilenameParam(filename).
			Do().
			Infos()
		if err != nil {
			return err
		}
	}

	outputFormat := kcmdutil.GetFlagString(cmd, "output")

	for i := range infos {
		obj, ok := infos[i].Object.(*api.Template)
		if !ok {
			sourceName := filename
			if len(storedTemplate) > 0 {
				sourceName = namespace + "/" + storedTemplate
			}
			fmt.Fprintf(cmd.Out(), "unable to parse %q, not a valid Template but %s\n", sourceName, reflect.TypeOf(infos[i].Object))
			continue
		}

		// If 'parameters' flag is set it does not do processing but only print
		// the template parameters to console for inspection.
		// If multiple templates are passed, this will print combined output for all
		// templates.
		if kcmdutil.GetFlagBool(cmd, "parameters") {
			if len(infos) > 1 {
				fmt.Fprintf(out, "\n%s:\n", obj.Name)
			}
			if err := describe.PrintTemplateParameters(obj.Parameters, out); err != nil {
				fmt.Fprintf(cmd.Out(), "error printing parameters for %q: %v\n", obj.Name, err)
			}
			continue
		}

		if label := kcmdutil.GetFlagString(cmd, "labels"); len(label) > 0 {
			lbl, err := kubectl.ParseLabels(label)
			if err != nil {
				fmt.Fprintf(cmd.Out(), "error parsing labels: %v\n", err)
				continue
			}
			if obj.ObjectLabels == nil {
				obj.ObjectLabels = make(map[string]string)
			}
			for key, value := range lbl {
				obj.ObjectLabels[key] = value
			}
		}

		// Override the values for the current template parameters
		// when user specify the --value
		if cmd.Flag("value").Changed {
			injectUserVars(cmd, obj)
		}

		resultObj, err := client.TemplateConfigs(namespace).Create(obj)
		if err != nil {
			fmt.Fprintf(cmd.Out(), "error processing the template %q: %v\n", obj.Name, err)
			continue
		}

		if outputFormat == "describe" {
			if s, err := (&describe.TemplateDescriber{
				MetadataAccessor: meta.NewAccessor(),
				ObjectTyper:      kapi.Scheme,
				ObjectDescriber:  nil,
			}).DescribeTemplate(resultObj); err != nil {
				fmt.Fprintf(cmd.Out(), "error describing %q: %v\n", obj.Name, err)
			} else {
				fmt.Fprintf(out, s)
			}
			continue
		}
		objects = append(objects, resultObj.Objects...)
	}

	// Do not print the processed templates when asked to only show parameters or
	// describe.
	if kcmdutil.GetFlagBool(cmd, "parameters") || outputFormat == "describe" {
		return nil
	}

	p, _, err := kubectl.GetPrinter(outputFormat, "")
	if err != nil {
		return err
	}
	p = kubectl.NewVersionedPrinter(p, kapi.Scheme, kcmdutil.OutputVersion(cmd, mapping.APIVersion))

	// use generic output
	if kcmdutil.GetFlagBool(cmd, "raw") {
		for i := range objects {
			p.PrintObj(objects[i], out)
		}
		return nil
	}

	return p.PrintObj(&kapi.List{
		ListMeta: kapi.ListMeta{},
		Items:    objects,
	}, out)
}
Пример #10
0
func (f *Factory) NewCmdGet(out io.Writer) *cobra.Command {
	cmd := &cobra.Command{
		Use:   "get [(-o|--output=)json|yaml|...] <resource> [<id>]",
		Short: "Display one or many resources",
		Long: `Display one or many resources.

Possible resources include pods (po), replication controllers (rc), services
(se), minions (mi), or events (ev).

If you specify a Go template, you can use any fields defined for the API version
you are connecting to the server with.

Examples:
  $ kubectl get pods
  <list all pods in ps output format>

  $ kubectl get replicationController 1234-56-7890-234234-456456
  <list single replication controller in ps output format>

  $ kubectl get -o json pod 1234-56-7890-234234-456456
  <list single pod in json output format>`,
		Run: func(cmd *cobra.Command, args []string) {
			mapping, namespace, name := ResourceOrTypeFromArgs(cmd, args, f.Mapper)

			selector := GetFlagString(cmd, "selector")
			labelSelector, err := labels.ParseSelector(selector)
			checkErr(err)

			client, err := f.RESTClient(cmd, mapping)
			checkErr(err)

			outputFormat := GetFlagString(cmd, "output")
			templateFile := GetFlagString(cmd, "template")
			defaultPrinter, err := f.Printer(cmd, mapping, GetFlagBool(cmd, "no-headers"))
			checkErr(err)

			outputVersion := GetFlagString(cmd, "output-version")
			if len(outputVersion) == 0 {
				outputVersion = mapping.APIVersion
			}

			printer, err := kubectl.GetPrinter(outputFormat, templateFile, outputVersion, mapping.ObjectConvertor, defaultPrinter)
			checkErr(err)

			restHelper := resource.NewHelper(client, mapping)
			var obj runtime.Object
			if len(name) == 0 {
				obj, err = restHelper.List(namespace, labelSelector)
			} else {
				obj, err = restHelper.Get(namespace, name)
			}
			checkErr(err)

			isWatch, isWatchOnly := GetFlagBool(cmd, "watch"), GetFlagBool(cmd, "watch-only")

			// print the current object
			if !isWatchOnly {
				if err := printer.PrintObj(obj, out); err != nil {
					checkErr(fmt.Errorf("unable to output the provided object: %v", err))
				}
			}

			// print watched changes
			if isWatch || isWatchOnly {
				rv, err := mapping.MetadataAccessor.ResourceVersion(obj)
				checkErr(err)

				w, err := restHelper.Watch(namespace, rv, labelSelector, labels.Everything())
				checkErr(err)

				kubectl.WatchLoop(w, printer, out)
			}
		},
	}
	cmd.Flags().StringP("output", "o", "", "Output format: json|yaml|template|templatefile")
	cmd.Flags().String("output-version", "", "Output the formatted object with the given version (default api-version)")
	cmd.Flags().Bool("no-headers", false, "When using the default output, don't print headers")
	cmd.Flags().StringP("template", "t", "", "Template string or path to template file to use when --output=template or --output=templatefile")
	cmd.Flags().StringP("selector", "l", "", "Selector (label query) to filter on")
	cmd.Flags().BoolP("watch", "w", false, "After listing/getting the requested object, watch for changes.")
	cmd.Flags().Bool("watch-only", false, "Watch for changes to the requseted object(s), without listing/getting first.")
	return cmd
}