Merge pull request #65542 from juanvallejo/jvallejo/cleanup-convert-cmd

Automatic merge from submit-queue (batch tested with PRs 66333, 65542). If you want to cherry-pick this change to another branch, please follow the instructions <a href="https://github.com/kubernetes/community/blob/master/contributors/devel/cherry-picks.md">here</a>.

cleanup / simplify convert command

Cleans up unnecessary pieces from the convert command, simplifyiing
command logic, and readability.

**Release note**:
```release-note
NONE
```

cc @soltysh @deads2k
pull/8/head
Kubernetes Submit Queue 2018-07-27 07:24:05 -07:00 committed by GitHub
commit 4d5d2664c3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 68 additions and 98 deletions

View File

@ -19,7 +19,9 @@ package cmd
import ( import (
"fmt" "fmt"
"k8s.io/apimachinery/pkg/api/meta" "github.com/golang/glog"
"github.com/spf13/cobra"
"k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/runtime/schema"
scheme "k8s.io/kubernetes/pkg/api/legacyscheme" scheme "k8s.io/kubernetes/pkg/api/legacyscheme"
@ -30,9 +32,7 @@ import (
"k8s.io/kubernetes/pkg/kubectl/genericclioptions/printers" "k8s.io/kubernetes/pkg/kubectl/genericclioptions/printers"
"k8s.io/kubernetes/pkg/kubectl/genericclioptions/resource" "k8s.io/kubernetes/pkg/kubectl/genericclioptions/resource"
"k8s.io/kubernetes/pkg/kubectl/util/i18n" "k8s.io/kubernetes/pkg/kubectl/util/i18n"
"k8s.io/kubernetes/pkg/kubectl/validation"
"github.com/golang/glog"
"github.com/spf13/cobra"
) )
var ( var (
@ -59,46 +59,20 @@ var (
kubectl convert -f . | kubectl create -f -`)) kubectl convert -f . | kubectl create -f -`))
) )
// NewCmdConvert creates a command object for the generic "convert" action, which
// translates the config file into a given version.
func NewCmdConvert(f cmdutil.Factory, ioStreams genericclioptions.IOStreams) *cobra.Command {
options := NewConvertOptions(ioStreams)
cmd := &cobra.Command{
Use: "convert -f FILENAME",
DisableFlagsInUseLine: true,
Short: i18n.T("Convert config files between different API versions"),
Long: convert_long,
Example: convert_example,
Run: func(cmd *cobra.Command, args []string) {
cmdutil.CheckErr(options.Complete(f, cmd))
cmdutil.CheckErr(options.RunConvert())
},
}
options.PrintFlags.AddFlags(cmd)
usage := "to need to get converted."
cmdutil.AddFilenameOptionFlags(cmd, &options.FilenameOptions, usage)
cmd.MarkFlagRequired("filename")
cmdutil.AddValidateFlags(cmd)
cmd.Flags().BoolVar(&options.local, "local", options.local, "If true, convert will NOT try to contact api-server but run locally.")
cmd.Flags().String("output-version", "", i18n.T("Output the formatted object with the given group version (for ex: 'extensions/v1beta1').)"))
return cmd
}
// ConvertOptions have the data required to perform the convert operation // ConvertOptions have the data required to perform the convert operation
type ConvertOptions struct { type ConvertOptions struct {
PrintFlags *genericclioptions.PrintFlags PrintFlags *genericclioptions.PrintFlags
PrintObj printers.ResourcePrinterFunc Printer printers.ResourcePrinter
OutputVersion string
Namespace string
builder func() *resource.Builder
local bool
validator func() (validation.Schema, error)
resource.FilenameOptions resource.FilenameOptions
builder *resource.Builder
local bool
genericclioptions.IOStreams genericclioptions.IOStreams
specifiedOutputVersion schema.GroupVersion
} }
func NewConvertOptions(ioStreams genericclioptions.IOStreams) *ConvertOptions { func NewConvertOptions(ioStreams genericclioptions.IOStreams) *ConvertOptions {
@ -109,57 +83,73 @@ func NewConvertOptions(ioStreams genericclioptions.IOStreams) *ConvertOptions {
} }
} }
// outputVersion returns the preferred output version for generic content (JSON, YAML, or templates) // NewCmdConvert creates a command object for the generic "convert" action, which
// defaultVersion is never mutated. Nil simply allows clean passing in common usage from client.Config // translates the config file into a given version.
func outputVersion(cmd *cobra.Command) (schema.GroupVersion, error) { func NewCmdConvert(f cmdutil.Factory, ioStreams genericclioptions.IOStreams) *cobra.Command {
outputVersionString := cmdutil.GetFlagString(cmd, "output-version") o := NewConvertOptions(ioStreams)
if len(outputVersionString) == 0 {
return schema.GroupVersion{}, nil cmd := &cobra.Command{
Use: "convert -f FILENAME",
DisableFlagsInUseLine: true,
Short: i18n.T("Convert config files between different API versions"),
Long: convert_long,
Example: convert_example,
Run: func(cmd *cobra.Command, args []string) {
cmdutil.CheckErr(o.Complete(f, cmd))
cmdutil.CheckErr(o.RunConvert())
},
} }
return schema.ParseGroupVersion(outputVersionString) cmd.Flags().BoolVar(&o.local, "local", o.local, "If true, convert will NOT try to contact api-server but run locally.")
cmd.Flags().StringVar(&o.OutputVersion, "output-version", o.OutputVersion, i18n.T("Output the formatted object with the given group version (for ex: 'extensions/v1beta1').)"))
o.PrintFlags.AddFlags(cmd)
cmdutil.AddValidateFlags(cmd)
cmdutil.AddFilenameOptionFlags(cmd, &o.FilenameOptions, "to need to get converted.")
cmd.MarkFlagRequired("filename")
return cmd
} }
// Complete collects information required to run Convert command from command line. // Complete collects information required to run Convert command from command line.
func (o *ConvertOptions) Complete(f cmdutil.Factory, cmd *cobra.Command) (err error) { func (o *ConvertOptions) Complete(f cmdutil.Factory, cmd *cobra.Command) (err error) {
o.specifiedOutputVersion, err = outputVersion(cmd) o.builder = f.NewBuilder
o.Namespace, _, err = f.ToRawKubeConfigLoader().Namespace()
if err != nil { if err != nil {
return err return err
} }
// build the builder o.validator = func() (validation.Schema, error) {
o.builder = f.NewBuilder(). return f.Validator(cmdutil.GetFlagBool(cmd, "validate"))
WithScheme(scheme.Scheme).
LocalParam(o.local)
if !o.local {
schema, err := f.Validator(cmdutil.GetFlagBool(cmd, "validate"))
if err != nil {
return err
}
o.builder.Schema(schema)
} }
cmdNamespace, _, err := f.ToRawKubeConfigLoader().Namespace()
if err != nil {
return err
}
o.builder.NamespaceParam(cmdNamespace).
ContinueOnError().
FilenameParam(false, &o.FilenameOptions).
Flatten()
// build the printer // build the printer
printer, err := o.PrintFlags.ToPrinter() o.Printer, err = o.PrintFlags.ToPrinter()
if err != nil { if err != nil {
return err return err
} }
o.PrintObj = printer.PrintObj
return nil return nil
} }
// RunConvert implements the generic Convert command // RunConvert implements the generic Convert command
func (o *ConvertOptions) RunConvert() error { func (o *ConvertOptions) RunConvert() error {
r := o.builder.Do() b := o.builder().
WithScheme(scheme.Scheme).
LocalParam(o.local)
if !o.local {
schema, err := o.validator()
if err != nil {
return err
}
b.Schema(schema)
}
r := b.NamespaceParam(o.Namespace).
ContinueOnError().
FilenameParam(false, &o.FilenameOptions).
Flatten().
Do()
err := r.Err() err := r.Err()
if err != nil { if err != nil {
return err return err
@ -175,40 +165,20 @@ func (o *ConvertOptions) RunConvert() error {
return fmt.Errorf("no objects passed to convert") return fmt.Errorf("no objects passed to convert")
} }
objects, err := asVersionedObject(infos, !singleItemImplied, o.specifiedOutputVersion, cmdutil.InternalVersionJSONEncoder()) var specifiedOutputVersion schema.GroupVersion
if len(o.OutputVersion) > 0 {
specifiedOutputVersion, err = schema.ParseGroupVersion(o.OutputVersion)
if err != nil {
return err
}
}
objects, err := asVersionedObject(infos, !singleItemImplied, specifiedOutputVersion, cmdutil.InternalVersionJSONEncoder())
if err != nil { if err != nil {
return err return err
} }
if meta.IsListType(objects) { return o.Printer.PrintObj(objects, o.Out)
listContent, err := meta.ExtractList(objects)
if err != nil {
return err
}
obj, err := objectListToVersionedObject(listContent, o.specifiedOutputVersion)
if err != nil {
return err
}
return o.PrintObj(obj, o.Out)
}
return o.PrintObj(objects, o.Out)
}
// objectListToVersionedObject receives a list of api objects and a group version
// and squashes the list's items into a single versioned runtime.Object.
func objectListToVersionedObject(objects []runtime.Object, specifiedOutputVersion schema.GroupVersion) (runtime.Object, error) {
objectList := &api.List{Items: objects}
targetVersions := []schema.GroupVersion{}
if !specifiedOutputVersion.Empty() {
targetVersions = append(targetVersions, specifiedOutputVersion)
}
targetVersions = append(targetVersions, schema.GroupVersion{Group: "", Version: "v1"})
converted, err := tryConvert(scheme.Scheme, objectList, targetVersions...)
if err != nil {
return nil, err
}
return converted, nil
} }
// asVersionedObject converts a list of infos into a single object - either a List containing // asVersionedObject converts a list of infos into a single object - either a List containing