// PrinterForMapping returns a printer suitable for displaying the provided resource type. // Requires that printer flags have been added to cmd (see AddPrinterFlags). func (f *Factory) PrinterForMapping(cmd *cobra.Command, mapping *meta.RESTMapping, withNamespace bool) (kubectl.ResourcePrinter, error) { printer, ok, err := PrinterForCommand(cmd) if err != nil { return nil, err } if ok { clientConfig, err := f.ClientConfig() if err != nil { return nil, err } defaultVersion := clientConfig.Version version := OutputVersion(cmd, defaultVersion) if len(version) == 0 { version = mapping.APIVersion } if len(version) == 0 { return nil, fmt.Errorf("you must specify an output-version when using this output format") } printer = kubectl.NewVersionedPrinter(printer, mapping.ObjectConvertor, version, mapping.APIVersion) } else { printer, err = f.Printer(mapping, GetFlagBool(cmd, "no-headers"), withNamespace, GetWideFlag(cmd), GetFlagStringList(cmd, "label-columns")) if err != nil { return nil, err } } return printer, nil }
// PrinterForMapping returns a printer suitable for displaying the provided resource type. // Requires that printer flags have been added to cmd (see AddPrinterFlags). func (f *Factory) PrinterForMapping(cmd *cobra.Command, mapping *meta.RESTMapping, withNamespace bool) (kubectl.ResourcePrinter, error) { printer, ok, err := PrinterForCommand(cmd) if err != nil { return nil, err } if ok { clientConfig, err := f.ClientConfig() if err != nil { return nil, err } defaultVersion := clientConfig.Version version := OutputVersion(cmd, defaultVersion) if len(version) == 0 { version = mapping.APIVersion } if len(version) == 0 { return nil, fmt.Errorf("you must specify an output-version when using this output format") } printer = kubectl.NewVersionedPrinter(printer, mapping.ObjectConvertor, version, mapping.APIVersion) } else { // Some callers do not have "label-columns" so we can't use the GetFlagStringSlice() helper columnLabel, err := cmd.Flags().GetStringSlice("label-columns") if err != nil { columnLabel = []string{} } printer, err = f.Printer(mapping, GetFlagBool(cmd, "no-headers"), withNamespace, GetWideFlag(cmd), GetFlagBool(cmd, "show-all"), columnLabel) if err != nil { return nil, err } printer = maybeWrapSortingPrinter(cmd, printer) } return printer, nil }
func (f *ring1Factory) PrinterForMapping(cmd *cobra.Command, mapping *meta.RESTMapping, withNamespace bool) (kubectl.ResourcePrinter, error) { printer, generic, err := PrinterForCommand(cmd) if err != nil { return nil, err } // Make sure we output versioned data for generic printers if generic { clientConfig, err := f.clientAccessFactory.ClientConfig() if err != nil { return nil, err } version, err := OutputVersion(cmd, clientConfig.GroupVersion) if err != nil { return nil, err } if version.Empty() && mapping != nil { version = mapping.GroupVersionKind.GroupVersion() } if version.Empty() { return nil, fmt.Errorf("you must specify an output-version when using this output format") } if mapping != nil { printer = kubectl.NewVersionedPrinter(printer, mapping.ObjectConvertor, version, mapping.GroupVersionKind.GroupVersion()) } } else { // Some callers do not have "label-columns" so we can't use the GetFlagStringSlice() helper columnLabel, err := cmd.Flags().GetStringSlice("label-columns") if err != nil { columnLabel = []string{} } printer, err = f.clientAccessFactory.Printer(mapping, kubectl.PrintOptions{ NoHeaders: GetFlagBool(cmd, "no-headers"), WithNamespace: withNamespace, Wide: GetWideFlag(cmd), ShowAll: GetFlagBool(cmd, "show-all"), ShowLabels: GetFlagBool(cmd, "show-labels"), AbsoluteTimestamps: isWatch(cmd), ColumnLabels: columnLabel, }) if err != nil { return nil, err } printer = maybeWrapSortingPrinter(cmd, printer) } return printer, nil }
func NewCmdConfigView(out io.Writer, ConfigAccess clientcmd.ConfigAccess) *cobra.Command { options := &ViewOptions{ConfigAccess: ConfigAccess} // Default to yaml defaultOutputFormat := "yaml" cmd := &cobra.Command{ Use: "view", Short: "Displays merged kubeconfig settings or a specified kubeconfig file.", Long: view_long, Example: view_example, Run: func(cmd *cobra.Command, args []string) { options.Complete() outputFormat := cmdutil.GetFlagString(cmd, "output") if outputFormat == "wide" { fmt.Printf("--output wide is not available in kubectl config view; reset to default output format (%s)\n\n", defaultOutputFormat) cmd.Flags().Set("output", defaultOutputFormat) } if outputFormat == "" { fmt.Printf("reset to default output format (%s) as --output is empty", defaultOutputFormat) cmd.Flags().Set("output", defaultOutputFormat) } printer, _, err := cmdutil.PrinterForCommand(cmd) cmdutil.CheckErr(err) version, err := cmdutil.OutputVersion(cmd, &latest.ExternalVersion) cmdutil.CheckErr(err) printer = kubectl.NewVersionedPrinter(printer, clientcmdapi.Scheme, version) cmdutil.CheckErr(options.Run(out, printer)) }, } cmdutil.AddPrinterFlags(cmd) cmd.Flags().Set("output", defaultOutputFormat) options.Merge.Default(true) f := cmd.Flags().VarPF(&options.Merge, "merge", "", "merge together the full hierarchy of kubeconfig files") f.NoOptDefVal = "true" cmd.Flags().BoolVar(&options.RawByteData, "raw", false, "display raw byte data") cmd.Flags().BoolVar(&options.Flatten, "flatten", false, "flatten the resulting kubeconfig file into self contained output (useful for creating portable kubeconfig files)") cmd.Flags().BoolVar(&options.Minify, "minify", false, "remove all information not used by current-context from the output") return cmd }
func NewCmdConfigView(out io.Writer, ConfigAccess ConfigAccess) *cobra.Command { options := &ViewOptions{ConfigAccess: ConfigAccess} cmd := &cobra.Command{ Use: "view", Short: "displays Merged kubeconfig settings or a specified kubeconfig file.", Long: view_long, Example: view_example, Run: func(cmd *cobra.Command, args []string) { options.Complete() printer, _, err := cmdutil.PrinterForCommand(cmd) if err != nil { glog.FatalDepth(1, err) } version := cmdutil.OutputVersion(cmd, latest.Version) printer = kubectl.NewVersionedPrinter(printer, clientcmdapi.Scheme, version) if err := options.Run(out, printer); err != nil { glog.FatalDepth(1, err) } }, } cmdutil.AddPrinterFlags(cmd) // Default to yaml cmd.Flags().Set("output", "yaml") options.Merge.Default(true) cmd.Flags().Var(&options.Merge, "merge", "merge together the full hierarchy of kubeconfig files") cmd.Flags().BoolVar(&options.RawByteData, "raw", false, "display raw byte data") cmd.Flags().BoolVar(&options.Flatten, "flatten", false, "flatten the resulting kubeconfig file into self contained output (useful for creating portable kubeconfig files)") cmd.Flags().BoolVar(&options.Minify, "minify", false, "remove all information not used by current-context from the output") return cmd }
// 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: dcName := deployutil.DeploymentConfigNameFor(r) dc, err := o.oc.DeploymentConfigs(r.Namespace).Get(dcName) if err != nil { return err } if dc.Spec.Paused { return fmt.Errorf("cannot rollback a paused deployment config") } // A specific deployment was used. target = r case *deployapi.DeploymentConfig: if r.Spec.Paused { return fmt.Errorf("cannot rollback a paused deployment config") } // 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 deployment config", 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.NewDeploymentConfigDescriber(o.oc, o.kc, newConfig) description, err := describer.Describe(newConfig.Namespace, newConfig.Name, kubectl.DescriberSettings{}) 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.Status.LatestVersion, rollback.Spec.From.Name) for _, trigger := range rolledback.Spec.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 -n %s", rolledback.Name, o.Namespace) 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 }
// 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 { templateName, valueArgs := "", []string{} for _, s := range args { isValue := strings.Contains(s, "=") switch { case isValue: valueArgs = append(valueArgs, s) case !isValue && len(templateName) == 0: templateName = s case !isValue && len(templateName) > 0: return kcmdutil.UsageError(cmd, "template name must be specified only once: %s", s) } } filename := kcmdutil.GetFlagString(cmd, "filename") if len(templateName) == 0 && len(filename) == 0 { return kcmdutil.UsageError(cmd, "Must pass a filename or name of stored template") } if kcmdutil.GetFlagBool(cmd, "parameters") { for _, flag := range []string{"value", "labels", "output", "output-version", "raw", "template"} { if f := cmd.Flags().Lookup(flag); f != nil && f.Changed { return kcmdutil.UsageError(cmd, "The --parameters flag does not process the template, can't be used with --%v", flag) } } } namespace, explicit, 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, err := mapper.RESTMapping(templateapi.Kind("Template")) if err != nil { return err } // When templateName is not empty, then we fetch the template from the // server, otherwise we require to set the `-f` parameter. if len(templateName) > 0 { var ( storedTemplate, rs string sourceNamespace string ok bool ) sourceNamespace, rs, storedTemplate, ok = parseNamespaceResourceName(templateName, namespace) if !ok { return fmt.Errorf("invalid argument %q", templateName) } if len(rs) > 0 && (rs != "template" && rs != "templates") { return fmt.Errorf("unable to process invalid resource %q", rs) } if len(storedTemplate) == 0 { return fmt.Errorf("invalid value syntax %q", templateName) } templateObj, err := client.Templates(sourceNamespace).Get(storedTemplate) if err != nil { if errors.IsNotFound(err) { return fmt.Errorf("template %q could not be found", storedTemplate) } return err } templateObj.CreationTimestamp = unversioned.Now() infos = append(infos, &resource.Info{Object: templateObj}) } else { infos, err = resource.NewBuilder(mapper, typer, resource.ClientMapperFunc(f.ClientForMapping), kapi.Codecs.UniversalDecoder()). NamespaceParam(namespace).RequireNamespace(). FilenameParam(explicit, filename). Do(). Infos() if err != nil { return err } } outputFormat := kcmdutil.GetFlagString(cmd, "output") for i := range infos { obj, ok := infos[i].Object.(*templateapi.Template) if !ok { sourceName := filename if len(templateName) > 0 { sourceName = namespace + "/" + templateName } 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 { values := kcmdutil.GetFlagStringSlice(cmd, "value") injectUserVars(values, out, obj) } injectUserVars(valueArgs, out, 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 } gv := mapping.GroupVersionKind.GroupVersion() version, err := kcmdutil.OutputVersion(cmd, &gv) if err != nil { return err } p = kubectl.NewVersionedPrinter(p, kapi.Scheme, version) // 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: unversioned.ListMeta{}, Items: objects, }, out) }
// 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 { templateName, valueArgs := "", []string{} for _, s := range args { isValue := strings.Contains(s, "=") switch { case isValue: valueArgs = append(valueArgs, s) case !isValue && len(templateName) == 0: templateName = s case !isValue && len(templateName) > 0: return kcmdutil.UsageError(cmd, "template name must be specified only once: %s", s) } } keys := sets.NewString() duplicatedKeys := sets.NewString() var flagValues []string if cmd.Flag("value").Changed { flagValues = kcmdutil.GetFlagStringSlice(cmd, "value") } for _, value := range flagValues { key := strings.Split(value, "=")[0] if keys.Has(key) { duplicatedKeys.Insert(key) } keys.Insert(key) } for _, value := range valueArgs { key := strings.Split(value, "=")[0] if keys.Has(key) { duplicatedKeys.Insert(key) } keys.Insert(key) } if len(duplicatedKeys) != 0 { return kcmdutil.UsageError(cmd, fmt.Sprintf("The following values were provided more than once: %s", strings.Join(duplicatedKeys.List(), ", "))) } filename := kcmdutil.GetFlagString(cmd, "filename") if len(templateName) == 0 && len(filename) == 0 { return kcmdutil.UsageError(cmd, "Must pass a filename or name of stored template") } if kcmdutil.GetFlagBool(cmd, "parameters") { for _, flag := range []string{"value", "labels", "output", "output-version", "raw", "template"} { if f := cmd.Flags().Lookup(flag); f != nil && f.Changed { return kcmdutil.UsageError(cmd, "The --parameters flag does not process the template, can't be used with --%v", flag) } } } namespace, explicit, err := f.DefaultNamespace() if err != nil { return err } mapper, typer := f.Object(false) client, _, err := f.Clients() if err != nil { return err } var ( objects []runtime.Object infos []*resource.Info ) mapping, err := mapper.RESTMapping(templateapi.Kind("Template")) if err != nil { return err } // When templateName is not empty, then we fetch the template from the // server, otherwise we require to set the `-f` parameter. if len(templateName) > 0 { var ( storedTemplate, rs string sourceNamespace string ok bool ) sourceNamespace, rs, storedTemplate, ok = parseNamespaceResourceName(templateName, namespace) if !ok { return fmt.Errorf("invalid argument %q", templateName) } if len(rs) > 0 && (rs != "template" && rs != "templates") { return fmt.Errorf("unable to process invalid resource %q", rs) } if len(storedTemplate) == 0 { return fmt.Errorf("invalid value syntax %q", templateName) } templateObj, err := client.Templates(sourceNamespace).Get(storedTemplate) if err != nil { if errors.IsNotFound(err) { return fmt.Errorf("template %q could not be found", storedTemplate) } return err } templateObj.CreationTimestamp = unversioned.Now() infos = append(infos, &resource.Info{Object: templateObj}) } else { infos, err = resource.NewBuilder(mapper, typer, resource.ClientMapperFunc(f.ClientForMapping), kapi.Codecs.UniversalDecoder()). NamespaceParam(namespace).RequireNamespace(). FilenameParam(explicit, false, filename). Do(). Infos() if err != nil { return err } } outputFormat := kcmdutil.GetFlagString(cmd, "output") if len(infos) > 1 { // in order to run validation on the input given to us by a user, we only support the processing // of one template in a list. For instance, we want to be able to fail when a user does not give // a parameter that the template wants or when they give a parameter the template doesn't need, // as this may indicate that they have mis-used `oc process`. This is much less complicated when // we process at most one template. fmt.Fprintf(out, "%d input templates found, but only the first will be processed", len(infos)) } obj, ok := infos[0].Object.(*templateapi.Template) if !ok { sourceName := filename if len(templateName) > 0 { sourceName = namespace + "/" + templateName } return fmt.Errorf("unable to parse %q, not a valid Template but %s\n", sourceName, reflect.TypeOf(infos[0].Object)) } // If 'parameters' flag is set it does not do processing but only print // the template parameters to console for inspection. if kcmdutil.GetFlagBool(cmd, "parameters") { return describe.PrintTemplateParameters(obj.Parameters, out) } if label := kcmdutil.GetFlagString(cmd, "labels"); len(label) > 0 { lbl, err := kubectl.ParseLabels(label) if err != nil { return fmt.Errorf("error parsing labels: %v\n", err) } 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 { values := kcmdutil.GetFlagStringSlice(cmd, "value") if errs := injectUserVars(values, obj); errs != nil { return kerrors.NewAggregate(errs) } } if errs := injectUserVars(valueArgs, obj); errs != nil { return kerrors.NewAggregate(errs) } resultObj, err := client.TemplateConfigs(namespace).Create(obj) if err != nil { return fmt.Errorf("error processing the template %q: %v\n", obj.Name, err) } if outputFormat == "describe" { if s, err := (&describe.TemplateDescriber{ MetadataAccessor: meta.NewAccessor(), ObjectTyper: kapi.Scheme, ObjectDescriber: nil, }).DescribeTemplate(resultObj); err != nil { return fmt.Errorf("error describing %q: %v\n", obj.Name, err) } else { _, err := fmt.Fprintf(out, s) return err } } 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 } gv := mapping.GroupVersionKind.GroupVersion() version, err := kcmdutil.OutputVersion(cmd, &gv) if err != nil { return err } p = kubectl.NewVersionedPrinter(p, kapi.Scheme, version) // 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: unversioned.ListMeta{}, Items: objects, }, out) }