diff --git a/go.mod b/go.mod index a85f0d34a..750d98909 100644 --- a/go.mod +++ b/go.mod @@ -31,10 +31,10 @@ require ( golang.org/x/sys v0.8.0 gopkg.in/yaml.v2 v2.4.0 k8s.io/api v0.0.0-20230619010547-366128ee4928 - k8s.io/apimachinery v0.0.0-20230623170337-07fcd5d08d6c + k8s.io/apimachinery v0.0.0-20230628220152-83d6d372b1a4 k8s.io/cli-runtime v0.0.0-20230619013419-022795328092 - k8s.io/client-go v0.0.0-20230627183502-4308ca3a0ec0 - k8s.io/component-base v0.0.0-20230627011201-78502f0e934a + k8s.io/client-go v0.0.0-20230628205645-0cde78477a6d + k8s.io/component-base v0.0.0-20230629215145-b8f9f7cc1db2 k8s.io/component-helpers v0.0.0-20230619011650-92f9e3a8b815 k8s.io/klog/v2 v2.100.1 k8s.io/kube-openapi v0.0.0-20230601164746-7562a1006961 @@ -95,11 +95,11 @@ require ( replace ( k8s.io/api => k8s.io/api v0.0.0-20230619010547-366128ee4928 - k8s.io/apimachinery => k8s.io/apimachinery v0.0.0-20230623170337-07fcd5d08d6c + k8s.io/apimachinery => k8s.io/apimachinery v0.0.0-20230628220152-83d6d372b1a4 k8s.io/cli-runtime => k8s.io/cli-runtime v0.0.0-20230619013419-022795328092 - k8s.io/client-go => k8s.io/client-go v0.0.0-20230627183502-4308ca3a0ec0 + k8s.io/client-go => k8s.io/client-go v0.0.0-20230628205645-0cde78477a6d k8s.io/code-generator => k8s.io/code-generator v0.0.0-20230619010117-b510e2c81c00 - k8s.io/component-base => k8s.io/component-base v0.0.0-20230627011201-78502f0e934a + k8s.io/component-base => k8s.io/component-base v0.0.0-20230629215145-b8f9f7cc1db2 k8s.io/component-helpers => k8s.io/component-helpers v0.0.0-20230619011650-92f9e3a8b815 k8s.io/metrics => k8s.io/metrics v0.0.0-20230619013253-6df5ceaa66cf ) diff --git a/go.sum b/go.sum index 7db12be95..a8e9715b8 100644 --- a/go.sum +++ b/go.sum @@ -273,14 +273,14 @@ honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWh honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= k8s.io/api v0.0.0-20230619010547-366128ee4928 h1:VtT+X4fQgmod0SJBrnSvLvzH8Ny1UhE+mFEnKqRfdVk= k8s.io/api v0.0.0-20230619010547-366128ee4928/go.mod h1:lkmrK7wL9oZlvKTkAr8N2y0yBKuoQKhp0sT0ccuH9mM= -k8s.io/apimachinery v0.0.0-20230623170337-07fcd5d08d6c h1:xyfiohRtBubqxkP4jy+d2fbW4OKT6Tq4vugR97DoK3Q= -k8s.io/apimachinery v0.0.0-20230623170337-07fcd5d08d6c/go.mod h1:tAiIbF8KB8+Ri2DfUWwZGwNOThIwM0fhXLnOymriu+4= +k8s.io/apimachinery v0.0.0-20230628220152-83d6d372b1a4 h1:ntS2ZHGzNY/ISRKPPU937LFSwjYZ7poMcwAeu1xCnKM= +k8s.io/apimachinery v0.0.0-20230628220152-83d6d372b1a4/go.mod h1:tAiIbF8KB8+Ri2DfUWwZGwNOThIwM0fhXLnOymriu+4= k8s.io/cli-runtime v0.0.0-20230619013419-022795328092 h1:LQeJIQgnvTlqAQusdLV8zbduQHrAhBW7u8d5vfTUmuE= k8s.io/cli-runtime v0.0.0-20230619013419-022795328092/go.mod h1:w+QHMtFYb+w4QFqv4PMJm3an/Cu9WAa36ixOoLcFcwY= -k8s.io/client-go v0.0.0-20230627183502-4308ca3a0ec0 h1:ygT0BukDHziuoCiQGvO8qLaRdS1fdKfUSFYj0jgEYqU= -k8s.io/client-go v0.0.0-20230627183502-4308ca3a0ec0/go.mod h1:D0sj1M0OPP3RotGs+K5EDkYchLo6LVVTjYvrrrhpAjQ= -k8s.io/component-base v0.0.0-20230627011201-78502f0e934a h1:bElechqHLBxeHEGKGWsUiHADBa/nyY/rP9r2DLYG3uA= -k8s.io/component-base v0.0.0-20230627011201-78502f0e934a/go.mod h1:qYvrqG8B4c32ZXt363aabGabYE1w1NawkY87xW16zOs= +k8s.io/client-go v0.0.0-20230628205645-0cde78477a6d h1:QS9FOMAlIjl/S8V4fnVAYauzzDE74HBChbxyjS+nbQ4= +k8s.io/client-go v0.0.0-20230628205645-0cde78477a6d/go.mod h1:E758318z7wD+fEdLJS55XgKv/Jnl+K+/nHIw4lPlieE= +k8s.io/component-base v0.0.0-20230629215145-b8f9f7cc1db2 h1:res0K6caIh79PJuWtgXA20Z1LU1x/5HuleTMfTRK60A= +k8s.io/component-base v0.0.0-20230629215145-b8f9f7cc1db2/go.mod h1:L3xI7trKI8CnqSv3XAzcYPs5OUTxutc6qDyXt75tJvY= k8s.io/component-helpers v0.0.0-20230619011650-92f9e3a8b815 h1:cqW0HAYK2G5CfALJzimcNZ2QcxZPGQsLJMkEC3hEQCo= k8s.io/component-helpers v0.0.0-20230619011650-92f9e3a8b815/go.mod h1:hcsm30nqKRwuKMXxB9bO4KUDqGi2n4vQ4khgjsQmAS8= k8s.io/klog/v2 v2.100.1 h1:7WCHKK6K8fNhTqfBhISHQ97KrnJNFZMcQvKp7gP/tmg= diff --git a/pkg/cmd/expose/expose.go b/pkg/cmd/expose/expose.go index 81e47c1c5..565fbdaad 100644 --- a/pkg/cmd/expose/expose.go +++ b/pkg/cmd/expose/expose.go @@ -135,10 +135,33 @@ type ExposeServiceOptions struct { genericiooptions.IOStreams } -// NewExposeServiceOptions creates a new ExposeServiceOptions and return a pointer to the -// struct -func NewExposeServiceOptions(ioStreams genericiooptions.IOStreams) *ExposeServiceOptions { - return &ExposeServiceOptions{ +// exposeServiceFlags is a struct that contains the user input flags to the command. +type ExposeServiceFlags struct { + cmdutil.OverrideOptions + PrintFlags *genericclioptions.PrintFlags + RecordFlags *genericclioptions.RecordFlags + + fieldManager string + Protocol string + + // Port will be used if a user specifies --port OR the exposed object as one port + Port string + Type string + LoadBalancerIP string + Selector string + Labels string + TargetPort string + ExternalIP string + Name string + SessionAffinity string + ClusterIP string + Recorder genericclioptions.Recorder + FilenameOptions resource.FilenameOptions + genericiooptions.IOStreams +} + +func NewExposeFlags(ioStreams genericiooptions.IOStreams) *ExposeServiceFlags { + return &ExposeServiceFlags{ RecordFlags: genericclioptions.NewRecordFlags(), PrintFlags: genericclioptions.NewPrintFlags("exposed").WithTypeSetter(scheme.Scheme), @@ -149,7 +172,7 @@ func NewExposeServiceOptions(ioStreams genericiooptions.IOStreams) *ExposeServic // NewCmdExposeService is a command to expose the service from user's input func NewCmdExposeService(f cmdutil.Factory, streams genericiooptions.IOStreams) *cobra.Command { - o := NewExposeServiceOptions(streams) + flags := NewExposeFlags(streams) validArgs := []string{} resources := regexp.MustCompile(`\s*,`).Split(exposeResources, -1) @@ -165,55 +188,89 @@ func NewCmdExposeService(f cmdutil.Factory, streams genericiooptions.IOStreams) Example: exposeExample, ValidArgsFunction: completion.SpecifiedResourceTypeAndNameCompletionFunc(f, validArgs), Run: func(cmd *cobra.Command, args []string) { - cmdutil.CheckErr(o.Complete(f, cmd)) + o, err := flags.ToOptions(cmd, args) + cmdutil.CheckErr(err) + cmdutil.CheckErr(o.Complete(f)) cmdutil.CheckErr(o.RunExpose(cmd, args)) }, } - o.RecordFlags.AddFlags(cmd) - o.PrintFlags.AddFlags(cmd) - - cmd.Flags().StringVar(&o.Protocol, "protocol", o.Protocol, i18n.T("The network protocol for the service to be created. Default is 'TCP'.")) - cmd.Flags().StringVar(&o.Port, "port", o.Port, i18n.T("The port that the service should serve on. Copied from the resource being exposed, if unspecified")) - cmd.Flags().StringVar(&o.Type, "type", o.Type, i18n.T("Type for this service: ClusterIP, NodePort, LoadBalancer, or ExternalName. Default is 'ClusterIP'.")) - cmd.Flags().StringVar(&o.LoadBalancerIP, "load-balancer-ip", o.LoadBalancerIP, i18n.T("IP to assign to the LoadBalancer. If empty, an ephemeral IP will be created and used (cloud-provider specific).")) - cmd.Flags().StringVar(&o.Selector, "selector", o.Selector, i18n.T("A label selector to use for this service. Only equality-based selector requirements are supported. If empty (the default) infer the selector from the replication controller or replica set.)")) - cmd.Flags().StringVarP(&o.Labels, "labels", "l", o.Labels, "Labels to apply to the service created by this call.") - cmd.Flags().StringVar(&o.TargetPort, "target-port", o.TargetPort, i18n.T("Name or number for the port on the container that the service should direct traffic to. Optional.")) - cmd.Flags().StringVar(&o.ExternalIP, "external-ip", o.ExternalIP, i18n.T("Additional external IP address (not managed by Kubernetes) to accept for the service. If this IP is routed to a node, the service can be accessed by this IP in addition to its generated service IP.")) - cmd.Flags().StringVar(&o.Name, "name", o.Name, i18n.T("The name for the newly created object.")) - cmd.Flags().StringVar(&o.SessionAffinity, "session-affinity", o.SessionAffinity, i18n.T("If non-empty, set the session affinity for the service to this; legal values: 'None', 'ClientIP'")) - cmd.Flags().StringVar(&o.ClusterIP, "cluster-ip", o.ClusterIP, i18n.T("ClusterIP to be assigned to the service. Leave empty to auto-allocate, or set to 'None' to create a headless service.")) - cmdutil.AddFieldManagerFlagVar(cmd, &o.fieldManager, "kubectl-expose") - o.AddOverrideFlags(cmd) - - usage := "identifying the resource to expose a service" - cmdutil.AddFilenameOptionFlags(cmd, &o.FilenameOptions, usage) - cmdutil.AddDryRunFlag(cmd) - cmdutil.AddApplyAnnotationFlags(cmd) + flags.AddFlags(cmd) return cmd } +func (flags *ExposeServiceFlags) AddFlags(cmd *cobra.Command) { + flags.PrintFlags.AddFlags(cmd) + flags.RecordFlags.AddFlags(cmd) + + cmd.Flags().StringVar(&flags.Protocol, "protocol", flags.Protocol, i18n.T("The network protocol for the service to be created. Default is 'TCP'.")) + cmd.Flags().StringVar(&flags.Port, "port", flags.Port, i18n.T("The port that the service should serve on. Copied from the resource being exposed, if unspecified")) + cmd.Flags().StringVar(&flags.Type, "type", flags.Type, i18n.T("Type for this service: ClusterIP, NodePort, LoadBalancer, or ExternalName. Default is 'ClusterIP'.")) + cmd.Flags().StringVar(&flags.LoadBalancerIP, "load-balancer-ip", flags.LoadBalancerIP, i18n.T("IP to assign to the LoadBalancer. If empty, an ephemeral IP will be created and used (cloud-provider specific).")) + cmd.Flags().StringVar(&flags.Selector, "selector", flags.Selector, i18n.T("A label selector to use for this service. Only equality-based selector requirements are supported. If empty (the default) infer the selector from the replication controller or replica set.)")) + cmd.Flags().StringVarP(&flags.Labels, "labels", "l", flags.Labels, "Labels to apply to the service created by this call.") + cmd.Flags().StringVar(&flags.TargetPort, "target-port", flags.TargetPort, i18n.T("Name or number for the port on the container that the service should direct traffic to. Optional.")) + cmd.Flags().StringVar(&flags.ExternalIP, "external-ip", flags.ExternalIP, i18n.T("Additional external IP address (not managed by Kubernetes) to accept for the service. If this IP is routed to a node, the service can be accessed by this IP in addition to its generated service IP.")) + cmd.Flags().StringVar(&flags.Name, "name", flags.Name, i18n.T("The name for the newly created object.")) + cmd.Flags().StringVar(&flags.SessionAffinity, "session-affinity", flags.SessionAffinity, i18n.T("If non-empty, set the session affinity for the service to this; legal values: 'None', 'ClientIP'")) + cmd.Flags().StringVar(&flags.ClusterIP, "cluster-ip", flags.ClusterIP, i18n.T("ClusterIP to be assigned to the service. Leave empty to auto-allocate, or set to 'None' to create a headless service.")) + + cmdutil.AddFieldManagerFlagVar(cmd, &flags.fieldManager, "kubectl-expose") + flags.AddOverrideFlags(cmd) + + cmdutil.AddDryRunFlag(cmd) + cmdutil.AddApplyAnnotationFlags(cmd) + + usage := "identifying the resource to expose a service" + cmdutil.AddFilenameOptionFlags(cmd, &flags.FilenameOptions, usage) +} + +func (flags *ExposeServiceFlags) ToOptions(cmd *cobra.Command, args []string) (*ExposeServiceOptions, error) { + dryRunStratergy, err := cmdutil.GetDryRunStrategy(cmd) + if err != nil { + return nil, err + } + + cmdutil.PrintFlagsWithDryRunStrategy(flags.PrintFlags, dryRunStratergy) + printer, err := flags.PrintFlags.ToPrinter() + if err != nil { + return nil, err + } + + flags.RecordFlags.Complete(cmd) + recorder, err := flags.RecordFlags.ToRecorder() + if err != nil { + return nil, err + } + + e := &ExposeServiceOptions{ + DryRunStrategy: dryRunStratergy, + PrintObj: printer.PrintObj, + Recorder: recorder, + IOStreams: flags.IOStreams, + fieldManager: flags.fieldManager, + PrintFlags: flags.PrintFlags, + RecordFlags: flags.RecordFlags, + FilenameOptions: flags.FilenameOptions, + Protocol: flags.Protocol, + Port: flags.Port, + Type: flags.Type, + LoadBalancerIP: flags.LoadBalancerIP, + Selector: flags.Selector, + Labels: flags.Labels, + TargetPort: flags.TargetPort, + ExternalIP: flags.ExternalIP, + Name: flags.Name, + SessionAffinity: flags.SessionAffinity, + ClusterIP: flags.ClusterIP, + OverrideOptions: flags.OverrideOptions, + } + return e, nil +} + // Complete loads data from the command line environment -func (o *ExposeServiceOptions) Complete(f cmdutil.Factory, cmd *cobra.Command) error { +func (o *ExposeServiceOptions) Complete(f cmdutil.Factory) error { var err error - o.DryRunStrategy, err = cmdutil.GetDryRunStrategy(cmd) - if err != nil { - return err - } - - cmdutil.PrintFlagsWithDryRunStrategy(o.PrintFlags, o.DryRunStrategy) - printer, err := o.PrintFlags.ToPrinter() - if err != nil { - return err - } - o.PrintObj = printer.PrintObj - - o.RecordFlags.Complete(cmd) - o.Recorder, err = o.RecordFlags.ToRecorder() - if err != nil { - return err - } o.Builder = f.NewBuilder() o.ClientForMapping = f.ClientForMapping @@ -368,7 +425,6 @@ func (o *ExposeServiceOptions) RunExpose(cmd *cobra.Command, args []string) erro if err != nil { return err } - return o.PrintObj(actualObject, o.Out) }) return err