Refactors explain command to split flags from options
Signed-off-by: Puneet Punamiya ppunamiy@redhat.com Signed-off-by: Maciej Szulik <soltysh@gmail.com> Kubernetes-commit: 91afef615ad918cfc364bf5e6d12a96785f2acaf
This commit is contained in:
parent
8af785f4be
commit
bcafb59748
|
@ -56,7 +56,7 @@ var (
|
||||||
|
|
||||||
# Get the documentation of a specific field of a resource
|
# Get the documentation of a specific field of a resource
|
||||||
kubectl explain pods.spec.containers
|
kubectl explain pods.spec.containers
|
||||||
|
|
||||||
# Get the documentation of resources in different format
|
# Get the documentation of resources in different format
|
||||||
kubectl explain deployment --output=plaintext-openapiv2`))
|
kubectl explain deployment --output=plaintext-openapiv2`))
|
||||||
|
|
||||||
|
@ -64,36 +64,70 @@ var (
|
||||||
plaintextOpenAPIV2TemplateName = "plaintext-openapiv2"
|
plaintextOpenAPIV2TemplateName = "plaintext-openapiv2"
|
||||||
)
|
)
|
||||||
|
|
||||||
type ExplainOptions struct {
|
type ExplainFlags struct {
|
||||||
genericiooptions.IOStreams
|
|
||||||
|
|
||||||
CmdParent string
|
|
||||||
APIVersion string
|
APIVersion string
|
||||||
Recursive bool
|
// Name of the template to use with the openapiv3 template renderer. If
|
||||||
|
// `EnableOpenAPIV3` is disabled, this does nothing
|
||||||
args []string
|
|
||||||
|
|
||||||
Mapper meta.RESTMapper
|
|
||||||
openAPIGetter openapi.OpenAPIResourcesGetter
|
|
||||||
|
|
||||||
// Name of the template to use with the openapiv3 template renderer.
|
|
||||||
OutputFormat string
|
OutputFormat string
|
||||||
|
Recursive bool
|
||||||
// Client capable of fetching openapi documents from the user's cluster
|
genericclioptions.IOStreams
|
||||||
OpenAPIV3Client openapiclient.Client
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewExplainOptions(parent string, streams genericiooptions.IOStreams) *ExplainOptions {
|
// AddFlags registers flags for a cli
|
||||||
return &ExplainOptions{
|
func (flags *ExplainFlags) AddFlags(cmd *cobra.Command) {
|
||||||
IOStreams: streams,
|
cmd.Flags().BoolVar(&flags.Recursive, "recursive", flags.Recursive, "Print the fields of fields (Currently only 1 level deep)")
|
||||||
CmdParent: parent,
|
cmd.Flags().StringVar(&flags.APIVersion, "api-version", flags.APIVersion, "Get different explanations for particular API version (API group/version)")
|
||||||
|
|
||||||
|
// Only enable --output as a valid flag if the feature is enabled
|
||||||
|
cmd.Flags().StringVar(&flags.OutputFormat, "output", plaintextTemplateName, "Format in which to render the schema (plaintext, plaintext-openapiv2)")
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewExplainFlags returns a default ExplainFlags
|
||||||
|
func NewExplainFlags(streams genericclioptions.IOStreams) *ExplainFlags {
|
||||||
|
return &ExplainFlags{
|
||||||
OutputFormat: plaintextTemplateName,
|
OutputFormat: plaintextTemplateName,
|
||||||
|
IOStreams: streams,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ToOptions converts from CLI inputs to runtime input
|
||||||
|
func (flags *ExplainFlags) ToOptions(f cmdutil.Factory, parent string, args []string) (*ExplainOptions, error) {
|
||||||
|
mapper, err := f.ToRESTMapper()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
schema, err := f.OpenAPISchema()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Only openapi v3 needs the discovery client.
|
||||||
|
openAPIV3Client, err := f.OpenAPIV3Client()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
o := &ExplainOptions{
|
||||||
|
CmdParent: parent,
|
||||||
|
Mapper: mapper,
|
||||||
|
Schema: schema,
|
||||||
|
args: args,
|
||||||
|
IOStreams: flags.IOStreams,
|
||||||
|
Recursive: flags.Recursive,
|
||||||
|
APIVersion: flags.APIVersion,
|
||||||
|
OutputFormat: plaintextTemplateName,
|
||||||
|
OpenAPIV3Client: openAPIV3Client,
|
||||||
|
}
|
||||||
|
|
||||||
|
return o, nil
|
||||||
|
}
|
||||||
|
|
||||||
// NewCmdExplain returns a cobra command for swagger docs
|
// NewCmdExplain returns a cobra command for swagger docs
|
||||||
func NewCmdExplain(parent string, f cmdutil.Factory, streams genericiooptions.IOStreams) *cobra.Command {
|
func NewCmdExplain(parent string, f cmdutil.Factory, streams genericclioptions.IOStreams) *cobra.Command {
|
||||||
o := NewExplainOptions(parent, streams)
|
// o := NewExplainOptions(parent, streams)
|
||||||
|
|
||||||
|
flags := NewExplainFlags(streams)
|
||||||
|
|
||||||
cmd := &cobra.Command{
|
cmd := &cobra.Command{
|
||||||
Use: "explain TYPE [--recursive=FALSE|TRUE] [--api-version=api-version-group] [-o|--output=plaintext|plaintext-openapiv2]",
|
Use: "explain TYPE [--recursive=FALSE|TRUE] [--api-version=api-version-group] [-o|--output=plaintext|plaintext-openapiv2]",
|
||||||
|
@ -102,39 +136,18 @@ func NewCmdExplain(parent string, f cmdutil.Factory, streams genericiooptions.IO
|
||||||
Long: explainLong + "\n\n" + cmdutil.SuggestAPIResources(parent),
|
Long: explainLong + "\n\n" + cmdutil.SuggestAPIResources(parent),
|
||||||
Example: explainExamples,
|
Example: explainExamples,
|
||||||
Run: func(cmd *cobra.Command, args []string) {
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
cmdutil.CheckErr(o.Complete(f, cmd, args))
|
o, err := flags.ToOptions(f, parent, args)
|
||||||
|
cmdutil.CheckErr(err)
|
||||||
cmdutil.CheckErr(o.Validate())
|
cmdutil.CheckErr(o.Validate())
|
||||||
cmdutil.CheckErr(o.Run())
|
cmdutil.CheckErr(o.Run())
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
cmd.Flags().BoolVar(&o.Recursive, "recursive", o.Recursive, "When true, print the name of all the fields recursively. Otherwise, print the available fields with their description.")
|
|
||||||
cmd.Flags().StringVar(&o.APIVersion, "api-version", o.APIVersion, "Use given api-version (group/version) of the resource.")
|
|
||||||
|
|
||||||
// Only enable --output as a valid flag if the feature is enabled
|
flags.AddFlags(cmd)
|
||||||
cmd.Flags().StringVarP(&o.OutputFormat, "output", "o", plaintextTemplateName, "Format in which to render the schema. Valid values are: (plaintext, plaintext-openapiv2).")
|
|
||||||
|
|
||||||
return cmd
|
return cmd
|
||||||
}
|
}
|
||||||
|
|
||||||
func (o *ExplainOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args []string) error {
|
|
||||||
var err error
|
|
||||||
o.Mapper, err = f.ToRESTMapper()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Only openapi v3 needs the discovery client.
|
|
||||||
o.OpenAPIV3Client, err = f.OpenAPIV3Client()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Lazy-load the OpenAPI V2 Resources, so they're not loaded when using OpenAPI V3.
|
|
||||||
o.openAPIGetter = f
|
|
||||||
o.args = args
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (o *ExplainOptions) Validate() error {
|
func (o *ExplainOptions) Validate() error {
|
||||||
if len(o.args) == 0 {
|
if len(o.args) == 0 {
|
||||||
return fmt.Errorf("You must specify the type of resource to explain. %s\n", cmdutil.SuggestAPIResources(o.CmdParent))
|
return fmt.Errorf("You must specify the type of resource to explain. %s\n", cmdutil.SuggestAPIResources(o.CmdParent))
|
||||||
|
@ -232,3 +245,23 @@ func (o *ExplainOptions) renderOpenAPIV2(
|
||||||
|
|
||||||
return explain.PrintModelDescription(fieldsPath, o.Out, schema, gvk, o.Recursive)
|
return explain.PrintModelDescription(fieldsPath, o.Out, schema, gvk, o.Recursive)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type ExplainOptions struct {
|
||||||
|
genericclioptions.IOStreams
|
||||||
|
|
||||||
|
CmdParent string
|
||||||
|
APIVersion string
|
||||||
|
Recursive bool
|
||||||
|
|
||||||
|
args []string
|
||||||
|
|
||||||
|
Mapper meta.RESTMapper
|
||||||
|
Schema openapi.Resources
|
||||||
|
|
||||||
|
// Name of the template to use with the openapiv3 template renderer. If
|
||||||
|
// `EnableOpenAPIV3` is disabled, this does nothing
|
||||||
|
OutputFormat string
|
||||||
|
|
||||||
|
// Client capable of fetching openapi documents from the user's cluster
|
||||||
|
OpenAPIV3Client openapiclient.Client
|
||||||
|
}
|
||||||
|
|
|
@ -57,9 +57,9 @@ func TestExplainInvalidArgs(t *testing.T) {
|
||||||
tf := cmdtesting.NewTestFactory()
|
tf := cmdtesting.NewTestFactory()
|
||||||
defer tf.Cleanup()
|
defer tf.Cleanup()
|
||||||
|
|
||||||
opts := explain.NewExplainOptions("kubectl", genericiooptions.NewTestIOStreamsDiscard())
|
flags := explain.NewExplainFlags(genericclioptions.NewTestIOStreamsDiscard())
|
||||||
cmd := explain.NewCmdExplain("kubectl", tf, genericiooptions.NewTestIOStreamsDiscard())
|
|
||||||
err := opts.Complete(tf, cmd, []string{})
|
opts, err := flags.ToOptions(tf, "kubectl", []string{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unexpected error %v", err)
|
t.Fatalf("unexpected error %v", err)
|
||||||
}
|
}
|
||||||
|
@ -69,7 +69,7 @@ func TestExplainInvalidArgs(t *testing.T) {
|
||||||
t.Error("unexpected non-error")
|
t.Error("unexpected non-error")
|
||||||
}
|
}
|
||||||
|
|
||||||
err = opts.Complete(tf, cmd, []string{"resource1", "resource2"})
|
opts, err = flags.ToOptions(tf, "kubectl", []string{"resource1", "resource2"})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unexpected error %v", err)
|
t.Fatalf("unexpected error %v", err)
|
||||||
}
|
}
|
||||||
|
@ -84,9 +84,9 @@ func TestExplainNotExistResource(t *testing.T) {
|
||||||
tf := cmdtesting.NewTestFactory()
|
tf := cmdtesting.NewTestFactory()
|
||||||
defer tf.Cleanup()
|
defer tf.Cleanup()
|
||||||
|
|
||||||
opts := explain.NewExplainOptions("kubectl", genericiooptions.NewTestIOStreamsDiscard())
|
flags := explain.NewExplainFlags(genericclioptions.NewTestIOStreamsDiscard())
|
||||||
cmd := explain.NewCmdExplain("kubectl", tf, genericiooptions.NewTestIOStreamsDiscard())
|
|
||||||
err := opts.Complete(tf, cmd, []string{"foo"})
|
opts, err := flags.ToOptions(tf, "kubectl", []string{"foo"})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unexpected error %v", err)
|
t.Fatalf("unexpected error %v", err)
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue