Remove the dependency between create priorityclass command and generators

This commit is contained in:
Aurélien Baumann 2020-09-18 11:00:29 -04:00
parent ac62c47889
commit 9fff7f70e6
3 changed files with 135 additions and 43 deletions

View File

@ -31,6 +31,7 @@ go_library(
"//staging/src/k8s.io/api/core/v1:go_default_library", "//staging/src/k8s.io/api/core/v1:go_default_library",
"//staging/src/k8s.io/api/networking/v1:go_default_library", "//staging/src/k8s.io/api/networking/v1:go_default_library",
"//staging/src/k8s.io/api/rbac/v1:go_default_library", "//staging/src/k8s.io/api/rbac/v1:go_default_library",
"//staging/src/k8s.io/api/scheduling/v1:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/api/meta:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/api/meta:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/api/resource:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/api/resource:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
@ -50,6 +51,7 @@ go_library(
"//staging/src/k8s.io/client-go/kubernetes/typed/core/v1:go_default_library", "//staging/src/k8s.io/client-go/kubernetes/typed/core/v1:go_default_library",
"//staging/src/k8s.io/client-go/kubernetes/typed/networking/v1:go_default_library", "//staging/src/k8s.io/client-go/kubernetes/typed/networking/v1:go_default_library",
"//staging/src/k8s.io/client-go/kubernetes/typed/rbac/v1:go_default_library", "//staging/src/k8s.io/client-go/kubernetes/typed/rbac/v1:go_default_library",
"//staging/src/k8s.io/client-go/kubernetes/typed/scheduling/v1:go_default_library",
"//staging/src/k8s.io/component-base/cli/flag:go_default_library", "//staging/src/k8s.io/component-base/cli/flag:go_default_library",
"//staging/src/k8s.io/kubectl/pkg/cmd/util:go_default_library", "//staging/src/k8s.io/kubectl/pkg/cmd/util:go_default_library",
"//staging/src/k8s.io/kubectl/pkg/cmd/util/editor:go_default_library", "//staging/src/k8s.io/kubectl/pkg/cmd/util/editor:go_default_library",

View File

@ -17,13 +17,21 @@ limitations under the License.
package create package create
import ( import (
"context"
"fmt"
"github.com/spf13/cobra" "github.com/spf13/cobra"
apiv1 "k8s.io/api/core/v1" corev1 "k8s.io/api/core/v1"
schedulingv1 "k8s.io/api/scheduling/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/cli-runtime/pkg/genericclioptions" "k8s.io/cli-runtime/pkg/genericclioptions"
"k8s.io/cli-runtime/pkg/resource"
schedulingv1client "k8s.io/client-go/kubernetes/typed/scheduling/v1"
cmdutil "k8s.io/kubectl/pkg/cmd/util" cmdutil "k8s.io/kubectl/pkg/cmd/util"
"k8s.io/kubectl/pkg/generate" "k8s.io/kubectl/pkg/scheme"
generateversioned "k8s.io/kubectl/pkg/generate/versioned" "k8s.io/kubectl/pkg/util"
"k8s.io/kubectl/pkg/util/i18n" "k8s.io/kubectl/pkg/util/i18n"
"k8s.io/kubectl/pkg/util/templates" "k8s.io/kubectl/pkg/util/templates"
) )
@ -43,16 +51,38 @@ var (
kubectl create priorityclass high-priority --value=1000 --description="high priority" --preemption-policy="Never"`)) kubectl create priorityclass high-priority --value=1000 --description="high priority" --preemption-policy="Never"`))
) )
// PriorityClassOpts holds the options for 'create priorityclass' sub command // PriorityClassOptions holds the options for 'create priorityclass' sub command
type PriorityClassOpts struct { type PriorityClassOptions struct {
CreateSubcommandOptions *CreateSubcommandOptions PrintFlags *genericclioptions.PrintFlags
PrintObj func(obj runtime.Object) error
Name string
Value int32
GlobalDefault bool
Description string
PreemptionPolicy string
FieldManager string
CreateAnnotation bool
Client *schedulingv1client.SchedulingV1Client
DryRunStrategy cmdutil.DryRunStrategy
DryRunVerifier *resource.DryRunVerifier
genericclioptions.IOStreams
}
func NewPriorityClassOptions(ioStreams genericclioptions.IOStreams) *PriorityClassOptions {
return &PriorityClassOptions{
Value: 0,
PreemptionPolicy: "PreemptLowerPriority",
PrintFlags: genericclioptions.NewPrintFlags("created").WithTypeSetter(scheme.Scheme),
IOStreams: ioStreams,
}
} }
// NewCmdCreatePriorityClass is a macro command to create a new priorityClass. // NewCmdCreatePriorityClass is a macro command to create a new priorityClass.
func NewCmdCreatePriorityClass(f cmdutil.Factory, ioStreams genericclioptions.IOStreams) *cobra.Command { func NewCmdCreatePriorityClass(f cmdutil.Factory, ioStreams genericclioptions.IOStreams) *cobra.Command {
options := &PriorityClassOpts{ o := NewPriorityClassOptions(ioStreams)
CreateSubcommandOptions: NewCreateSubcommandOptions(ioStreams),
}
cmd := &cobra.Command{ cmd := &cobra.Command{
Use: "priorityclass NAME --value=VALUE --global-default=BOOL [--dry-run=server|client|none]", Use: "priorityclass NAME --value=VALUE --global-default=BOOL [--dry-run=server|client|none]",
@ -62,50 +92,112 @@ func NewCmdCreatePriorityClass(f cmdutil.Factory, ioStreams genericclioptions.IO
Long: pcLong, Long: pcLong,
Example: pcExample, Example: pcExample,
Run: func(cmd *cobra.Command, args []string) { Run: func(cmd *cobra.Command, args []string) {
cmdutil.CheckErr(options.Complete(f, cmd, args)) cmdutil.CheckErr(o.Complete(f, cmd, args))
cmdutil.CheckErr(options.Run()) cmdutil.CheckErr(o.Run())
}, },
} }
options.CreateSubcommandOptions.PrintFlags.AddFlags(cmd) o.PrintFlags.AddFlags(cmd)
cmdutil.AddApplyAnnotationFlags(cmd) cmdutil.AddApplyAnnotationFlags(cmd)
cmdutil.AddValidateFlags(cmd) cmdutil.AddValidateFlags(cmd)
cmdutil.AddGeneratorFlags(cmd, generateversioned.PriorityClassV1GeneratorName) cmdutil.AddDryRunFlag(cmd)
cmd.Flags().Int32Var(&o.Value, "value", o.Value, i18n.T("the value of this priority class."))
cmd.Flags().Int32("value", 0, i18n.T("the value of this priority class.")) cmd.Flags().BoolVar(&o.GlobalDefault, "global-default", o.GlobalDefault, i18n.T("global-default specifies whether this PriorityClass should be considered as the default priority."))
cmd.Flags().Bool("global-default", false, i18n.T("global-default specifies whether this PriorityClass should be considered as the default priority.")) cmd.Flags().StringVar(&o.Description, "description", o.Description, i18n.T("description is an arbitrary string that usually provides guidelines on when this priority class should be used."))
cmd.Flags().String("description", "", i18n.T("description is an arbitrary string that usually provides guidelines on when this priority class should be used.")) cmd.Flags().StringVar(&o.PreemptionPolicy, "preemption-policy", o.PreemptionPolicy, i18n.T("preemption-policy is the policy for preempting pods with lower priority."))
cmd.Flags().String("preemption-policy", "PreemptLowerPriority", i18n.T("preemption-policy is the policy for preempting pods with lower priority.")) cmdutil.AddFieldManagerFlagVar(cmd, &o.FieldManager, "kubectl-create")
cmdutil.AddFieldManagerFlagVar(cmd, &options.CreateSubcommandOptions.FieldManager, "kubectl-create")
return cmd return cmd
} }
// Complete completes all the required options // Complete completes all the required options
func (o *PriorityClassOpts) Complete(f cmdutil.Factory, cmd *cobra.Command, args []string) error { func (o *PriorityClassOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args []string) error {
name, err := NameFromCommandArgs(cmd, args) var err error
o.Name, err = NameFromCommandArgs(cmd, args)
if err != nil { if err != nil {
return err return err
} }
var generator generate.StructuredGenerator restConfig, err := f.ToRESTConfig()
switch generatorName := cmdutil.GetFlagString(cmd, "generator"); generatorName { if err != nil {
case generateversioned.PriorityClassV1GeneratorName: return err
generator = &generateversioned.PriorityClassV1Generator{ }
Name: name, o.Client, err = schedulingv1client.NewForConfig(restConfig)
Value: cmdutil.GetFlagInt32(cmd, "value"), if err != nil {
GlobalDefault: cmdutil.GetFlagBool(cmd, "global-default"), return err
Description: cmdutil.GetFlagString(cmd, "description"),
PreemptionPolicy: apiv1.PreemptionPolicy(cmdutil.GetFlagString(cmd, "preemption-policy")),
}
default:
return errUnsupportedGenerator(cmd, generatorName)
} }
return o.CreateSubcommandOptions.Complete(f, cmd, args, generator) o.CreateAnnotation = cmdutil.GetFlagBool(cmd, cmdutil.ApplyAnnotationsFlag)
o.DryRunStrategy, err = cmdutil.GetDryRunStrategy(cmd)
if err != nil {
return err
}
dynamicClient, err := f.DynamicClient()
if err != nil {
return err
}
discoveryClient, err := f.ToDiscoveryClient()
if err != nil {
return err
}
o.DryRunVerifier = resource.NewDryRunVerifier(dynamicClient, discoveryClient)
cmdutil.PrintFlagsWithDryRunStrategy(o.PrintFlags, o.DryRunStrategy)
printer, err := o.PrintFlags.ToPrinter()
if err != nil {
return err
}
o.PrintObj = func(obj runtime.Object) error {
return printer.PrintObj(obj, o.Out)
}
return nil
} }
// Run calls the CreateSubcommandOptions.Run in the PriorityClassOpts instance // Run calls the CreateSubcommandOptions.Run in the PriorityClassOptions instance
func (o *PriorityClassOpts) Run() error { func (o *PriorityClassOptions) Run() error {
return o.CreateSubcommandOptions.Run() priorityClass, err := o.createPriorityClass()
if err != nil {
return err
}
if err := util.CreateOrUpdateAnnotation(o.CreateAnnotation, priorityClass, scheme.DefaultJSONEncoder()); err != nil {
return err
}
if o.DryRunStrategy != cmdutil.DryRunClient {
createOptions := metav1.CreateOptions{}
if o.FieldManager != "" {
createOptions.FieldManager = o.FieldManager
}
if o.DryRunStrategy == cmdutil.DryRunServer {
if err := o.DryRunVerifier.HasSupport(priorityClass.GroupVersionKind()); err != nil {
return err
}
createOptions.DryRun = []string{metav1.DryRunAll}
}
var err error
priorityClass, err = o.Client.PriorityClasses().Create(context.TODO(), priorityClass, createOptions)
if err != nil {
return fmt.Errorf("failed to create clusterrolebinding: %v", err)
}
}
return o.PrintObj(priorityClass)
}
func (o *PriorityClassOptions) createPriorityClass() (*schedulingv1.PriorityClass, error) {
preemptionPolicy := corev1.PreemptionPolicy(o.PreemptionPolicy)
return &schedulingv1.PriorityClass{
// this is ok because we know exactly how we want to be serialized
TypeMeta: metav1.TypeMeta{APIVersion: schedulingv1.SchemeGroupVersion.String(), Kind: "PriorityClass"},
ObjectMeta: metav1.ObjectMeta{
Name: o.Name,
},
Value: o.Value,
GlobalDefault: o.GlobalDefault,
Description: o.Description,
PreemptionPolicy: &preemptionPolicy,
}, nil
} }

View File

@ -63,12 +63,10 @@ func TestCreatePriorityClass(t *testing.T) {
printFlags := genericclioptions.NewPrintFlags("created").WithTypeSetter(scheme.Scheme) printFlags := genericclioptions.NewPrintFlags("created").WithTypeSetter(scheme.Scheme)
printFlags.OutputFormat = &outputFormat printFlags.OutputFormat = &outputFormat
options := &PriorityClassOpts{ options := &PriorityClassOptions{
CreateSubcommandOptions: &CreateSubcommandOptions{ PrintFlags: printFlags,
PrintFlags: printFlags, Name: pcName,
Name: pcName, IOStreams: ioStreams,
IOStreams: ioStreams,
},
} }
err := options.Complete(tf, cmd, []string{pcName}) err := options.Complete(tf, cmd, []string{pcName})
if err != nil { if err != nil {