Skip to content

Commit f6f0680

Browse files
authored
Merge pull request kubernetes#129784 from soltysh/refactor_explain
Refactors explain command to split flags from options
2 parents 5aeea45 + 8713933 commit f6f0680

File tree

3 files changed

+84
-58
lines changed

3 files changed

+84
-58
lines changed

staging/src/k8s.io/kubectl/pkg/cmd/create/create_token.go

Lines changed: 8 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -98,14 +98,10 @@ var (
9898
`)
9999
)
100100

101-
func boundObjectKindToAPIVersions() map[string]string {
102-
kinds := map[string]string{
103-
"Pod": "v1",
104-
"Secret": "v1",
105-
"Node": "v1",
106-
}
107-
108-
return kinds
101+
var boundObjectKinds = map[string]string{
102+
"Pod": "v1",
103+
"Secret": "v1",
104+
"Node": "v1",
109105
}
110106

111107
func NewTokenOpts(ioStreams genericiooptions.IOStreams) *TokenOptions {
@@ -149,7 +145,7 @@ func NewCmdCreateToken(f cmdutil.Factory, ioStreams genericiooptions.IOStreams)
149145
cmd.Flags().DurationVar(&o.Duration, "duration", o.Duration, "Requested lifetime of the issued token. If not set or if set to 0, the lifetime will be determined by the server automatically. The server may return a token with a longer or shorter lifetime.")
150146

151147
cmd.Flags().StringVar(&o.BoundObjectKind, "bound-object-kind", o.BoundObjectKind, "Kind of an object to bind the token to. "+
152-
"Supported kinds are "+strings.Join(sets.List(sets.KeySet(boundObjectKindToAPIVersions())), ", ")+". "+
148+
"Supported kinds are "+strings.Join(sets.List(sets.KeySet(boundObjectKinds)), ", ")+". "+
153149
"If set, --bound-object-name must be provided.")
154150
cmd.Flags().StringVar(&o.BoundObjectName, "bound-object-name", o.BoundObjectName, "Name of an object to bind the token to. "+
155151
"The token will expire when the object is deleted. "+
@@ -226,8 +222,8 @@ func (o *TokenOptions) Validate() error {
226222
return fmt.Errorf("--bound-object-uid can only be set if --bound-object-kind is provided")
227223
}
228224
} else {
229-
if _, ok := boundObjectKindToAPIVersions()[o.BoundObjectKind]; !ok {
230-
return fmt.Errorf("supported --bound-object-kind values are %s", strings.Join(sets.List(sets.KeySet(boundObjectKindToAPIVersions())), ", "))
225+
if _, ok := boundObjectKinds[o.BoundObjectKind]; !ok {
226+
return fmt.Errorf("supported --bound-object-kind values are %s", strings.Join(sets.List(sets.KeySet(boundObjectKinds)), ", "))
231227
}
232228
if len(o.BoundObjectName) == 0 {
233229
return fmt.Errorf("--bound-object-name is required if --bound-object-kind is provided")
@@ -250,7 +246,7 @@ func (o *TokenOptions) Run() error {
250246
if len(o.BoundObjectKind) > 0 {
251247
request.Spec.BoundObjectRef = &authenticationv1.BoundObjectReference{
252248
Kind: o.BoundObjectKind,
253-
APIVersion: boundObjectKindToAPIVersions()[o.BoundObjectKind],
249+
APIVersion: boundObjectKinds[o.BoundObjectKind],
254250
Name: o.BoundObjectName,
255251
UID: types.UID(o.BoundObjectUID),
256252
}

staging/src/k8s.io/kubectl/pkg/cmd/explain/explain.go

Lines changed: 69 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -56,44 +56,77 @@ var (
5656
5757
# Get the documentation of a specific field of a resource
5858
kubectl explain pods.spec.containers
59-
59+
6060
# Get the documentation of resources in different format
6161
kubectl explain deployment --output=plaintext-openapiv2`))
62+
)
6263

64+
const (
6365
plaintextTemplateName = "plaintext"
6466
plaintextOpenAPIV2TemplateName = "plaintext-openapiv2"
6567
)
6668

67-
type ExplainOptions struct {
69+
// ExplainFlags directly reflect the information that CLI is gathering via flags.
70+
// They will be converted to Options, which reflect the runtime requirements for
71+
// the command.
72+
type ExplainFlags struct {
73+
APIVersion string
74+
OutputFormat string
75+
Recursive bool
76+
6877
genericiooptions.IOStreams
78+
}
6979

70-
CmdParent string
71-
APIVersion string
72-
Recursive bool
80+
// NewExplainFlags returns a default ExplainFlags
81+
func NewExplainFlags(streams genericiooptions.IOStreams) *ExplainFlags {
82+
return &ExplainFlags{
83+
OutputFormat: plaintextTemplateName,
84+
IOStreams: streams,
85+
}
86+
}
7387

74-
args []string
88+
// AddFlags registers flags for a cli
89+
func (flags *ExplainFlags) AddFlags(cmd *cobra.Command) {
90+
cmd.Flags().BoolVar(&flags.Recursive, "recursive", flags.Recursive, "Print the fields of fields (Currently only 1 level deep)")
91+
cmd.Flags().StringVar(&flags.APIVersion, "api-version", flags.APIVersion, "Get different explanations for particular API version (API group/version)")
92+
cmd.Flags().StringVar(&flags.OutputFormat, "output", plaintextTemplateName, "Format in which to render the schema (plaintext, plaintext-openapiv2)")
93+
}
7594

76-
Mapper meta.RESTMapper
77-
openAPIGetter openapi.OpenAPIResourcesGetter
95+
// ToOptions converts from CLI inputs to runtime input
96+
func (flags *ExplainFlags) ToOptions(f cmdutil.Factory, parent string, args []string) (*ExplainOptions, error) {
97+
mapper, err := f.ToRESTMapper()
98+
if err != nil {
99+
return nil, err
100+
}
78101

79-
// Name of the template to use with the openapiv3 template renderer.
80-
OutputFormat string
102+
// Only openapi v3 needs the discovery client.
103+
openAPIV3Client, err := f.OpenAPIV3Client()
104+
if err != nil {
105+
return nil, err
106+
}
81107

82-
// Client capable of fetching openapi documents from the user's cluster
83-
OpenAPIV3Client openapiclient.Client
84-
}
108+
o := &ExplainOptions{
109+
IOStreams: flags.IOStreams,
85110

86-
func NewExplainOptions(parent string, streams genericiooptions.IOStreams) *ExplainOptions {
87-
return &ExplainOptions{
88-
IOStreams: streams,
89-
CmdParent: parent,
90-
OutputFormat: plaintextTemplateName,
111+
Recursive: flags.Recursive,
112+
APIVersion: flags.APIVersion,
113+
OutputFormat: flags.OutputFormat,
114+
115+
CmdParent: parent,
116+
args: args,
117+
118+
Mapper: mapper,
119+
openAPIGetter: f,
120+
121+
OpenAPIV3Client: openAPIV3Client,
91122
}
123+
124+
return o, nil
92125
}
93126

94127
// NewCmdExplain returns a cobra command for swagger docs
95128
func NewCmdExplain(parent string, f cmdutil.Factory, streams genericiooptions.IOStreams) *cobra.Command {
96-
o := NewExplainOptions(parent, streams)
129+
flags := NewExplainFlags(streams)
97130

98131
cmd := &cobra.Command{
99132
Use: "explain TYPE [--recursive=FALSE|TRUE] [--api-version=api-version-group] [-o|--output=plaintext|plaintext-openapiv2]",
@@ -102,37 +135,34 @@ func NewCmdExplain(parent string, f cmdutil.Factory, streams genericiooptions.IO
102135
Long: explainLong + "\n\n" + cmdutil.SuggestAPIResources(parent),
103136
Example: explainExamples,
104137
Run: func(cmd *cobra.Command, args []string) {
105-
cmdutil.CheckErr(o.Complete(f, cmd, args))
138+
o, err := flags.ToOptions(f, parent, args)
139+
cmdutil.CheckErr(err)
106140
cmdutil.CheckErr(o.Validate())
107141
cmdutil.CheckErr(o.Run())
108142
},
109143
}
110-
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.")
111-
cmd.Flags().StringVar(&o.APIVersion, "api-version", o.APIVersion, "Use given api-version (group/version) of the resource.")
112144

113-
// Only enable --output as a valid flag if the feature is enabled
114-
cmd.Flags().StringVarP(&o.OutputFormat, "output", "o", plaintextTemplateName, "Format in which to render the schema. Valid values are: (plaintext, plaintext-openapiv2).")
145+
flags.AddFlags(cmd)
115146

116147
return cmd
117148
}
118149

119-
func (o *ExplainOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args []string) error {
120-
var err error
121-
o.Mapper, err = f.ToRESTMapper()
122-
if err != nil {
123-
return err
124-
}
150+
type ExplainOptions struct {
151+
genericiooptions.IOStreams
125152

126-
// Only openapi v3 needs the discovery client.
127-
o.OpenAPIV3Client, err = f.OpenAPIV3Client()
128-
if err != nil {
129-
return err
130-
}
153+
Recursive bool
154+
APIVersion string
155+
// Name of the template to use with the openapiv3 template renderer.
156+
OutputFormat string
131157

132-
// Lazy-load the OpenAPI V2 Resources, so they're not loaded when using OpenAPI V3.
133-
o.openAPIGetter = f
134-
o.args = args
135-
return nil
158+
CmdParent string
159+
args []string
160+
161+
Mapper meta.RESTMapper
162+
openAPIGetter openapi.OpenAPIResourcesGetter
163+
164+
// Client capable of fetching openapi documents from the user's cluster
165+
OpenAPIV3Client openapiclient.Client
136166
}
137167

138168
func (o *ExplainOptions) Validate() error {

staging/src/k8s.io/kubectl/pkg/cmd/explain/explain_test.go

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -57,9 +57,9 @@ func TestExplainInvalidArgs(t *testing.T) {
5757
tf := cmdtesting.NewTestFactory()
5858
defer tf.Cleanup()
5959

60-
opts := explain.NewExplainOptions("kubectl", genericiooptions.NewTestIOStreamsDiscard())
61-
cmd := explain.NewCmdExplain("kubectl", tf, genericiooptions.NewTestIOStreamsDiscard())
62-
err := opts.Complete(tf, cmd, []string{})
60+
flags := explain.NewExplainFlags(genericiooptions.NewTestIOStreamsDiscard())
61+
62+
opts, err := flags.ToOptions(tf, "kubectl", []string{})
6363
if err != nil {
6464
t.Fatalf("unexpected error %v", err)
6565
}
@@ -69,7 +69,7 @@ func TestExplainInvalidArgs(t *testing.T) {
6969
t.Error("unexpected non-error")
7070
}
7171

72-
err = opts.Complete(tf, cmd, []string{"resource1", "resource2"})
72+
opts, err = flags.ToOptions(tf, "kubectl", []string{"resource1", "resource2"})
7373
if err != nil {
7474
t.Fatalf("unexpected error %v", err)
7575
}
@@ -84,9 +84,9 @@ func TestExplainNotExistResource(t *testing.T) {
8484
tf := cmdtesting.NewTestFactory()
8585
defer tf.Cleanup()
8686

87-
opts := explain.NewExplainOptions("kubectl", genericiooptions.NewTestIOStreamsDiscard())
88-
cmd := explain.NewCmdExplain("kubectl", tf, genericiooptions.NewTestIOStreamsDiscard())
89-
err := opts.Complete(tf, cmd, []string{"foo"})
87+
flags := explain.NewExplainFlags(genericiooptions.NewTestIOStreamsDiscard())
88+
89+
opts, err := flags.ToOptions(tf, "kubectl", []string{"foo"})
9090
if err != nil {
9191
t.Fatalf("unexpected error %v", err)
9292
}

0 commit comments

Comments
 (0)