create_service.go 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343
  1. /*
  2. Copyright 2016 The Kubernetes Authors.
  3. Licensed under the Apache License, Version 2.0 (the "License");
  4. you may not use this file except in compliance with the License.
  5. You may obtain a copy of the License at
  6. http://www.apache.org/licenses/LICENSE-2.0
  7. Unless required by applicable law or agreed to in writing, software
  8. distributed under the License is distributed on an "AS IS" BASIS,
  9. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  10. See the License for the specific language governing permissions and
  11. limitations under the License.
  12. */
  13. package create
  14. import (
  15. "github.com/spf13/cobra"
  16. "k8s.io/api/core/v1"
  17. "k8s.io/cli-runtime/pkg/genericclioptions"
  18. cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util"
  19. "k8s.io/kubernetes/pkg/kubectl/generate"
  20. generateversioned "k8s.io/kubernetes/pkg/kubectl/generate/versioned"
  21. "k8s.io/kubernetes/pkg/kubectl/util/i18n"
  22. "k8s.io/kubernetes/pkg/kubectl/util/templates"
  23. )
  24. // NewCmdCreateService is a macro command to create a new service
  25. func NewCmdCreateService(f cmdutil.Factory, ioStreams genericclioptions.IOStreams) *cobra.Command {
  26. cmd := &cobra.Command{
  27. Use: "service",
  28. Aliases: []string{"svc"},
  29. Short: i18n.T("Create a service using specified subcommand."),
  30. Long: "Create a service using specified subcommand.",
  31. Run: cmdutil.DefaultSubCommandRun(ioStreams.ErrOut),
  32. }
  33. cmd.AddCommand(NewCmdCreateServiceClusterIP(f, ioStreams))
  34. cmd.AddCommand(NewCmdCreateServiceNodePort(f, ioStreams))
  35. cmd.AddCommand(NewCmdCreateServiceLoadBalancer(f, ioStreams))
  36. cmd.AddCommand(NewCmdCreateServiceExternalName(f, ioStreams))
  37. return cmd
  38. }
  39. var (
  40. serviceClusterIPLong = templates.LongDesc(i18n.T(`
  41. Create a ClusterIP service with the specified name.`))
  42. serviceClusterIPExample = templates.Examples(i18n.T(`
  43. # Create a new ClusterIP service named my-cs
  44. kubectl create service clusterip my-cs --tcp=5678:8080
  45. # Create a new ClusterIP service named my-cs (in headless mode)
  46. kubectl create service clusterip my-cs --clusterip="None"`))
  47. )
  48. func addPortFlags(cmd *cobra.Command) {
  49. cmd.Flags().StringSlice("tcp", []string{}, "Port pairs can be specified as '<port>:<targetPort>'.")
  50. }
  51. // ServiceClusterIPOpts holds the options for 'create service clusterip' sub command
  52. type ServiceClusterIPOpts struct {
  53. CreateSubcommandOptions *CreateSubcommandOptions
  54. }
  55. // NewCmdCreateServiceClusterIP is a command to create a ClusterIP service
  56. func NewCmdCreateServiceClusterIP(f cmdutil.Factory, ioStreams genericclioptions.IOStreams) *cobra.Command {
  57. options := &ServiceClusterIPOpts{
  58. CreateSubcommandOptions: NewCreateSubcommandOptions(ioStreams),
  59. }
  60. cmd := &cobra.Command{
  61. Use: "clusterip NAME [--tcp=<port>:<targetPort>] [--dry-run]",
  62. DisableFlagsInUseLine: true,
  63. Short: i18n.T("Create a ClusterIP service."),
  64. Long: serviceClusterIPLong,
  65. Example: serviceClusterIPExample,
  66. Run: func(cmd *cobra.Command, args []string) {
  67. cmdutil.CheckErr(options.Complete(f, cmd, args))
  68. cmdutil.CheckErr(options.Run())
  69. },
  70. }
  71. options.CreateSubcommandOptions.PrintFlags.AddFlags(cmd)
  72. cmdutil.AddApplyAnnotationFlags(cmd)
  73. cmdutil.AddValidateFlags(cmd)
  74. cmdutil.AddGeneratorFlags(cmd, generateversioned.ServiceClusterIPGeneratorV1Name)
  75. addPortFlags(cmd)
  76. cmd.Flags().String("clusterip", "", i18n.T("Assign your own ClusterIP or set to 'None' for a 'headless' service (no loadbalancing)."))
  77. return cmd
  78. }
  79. func errUnsupportedGenerator(cmd *cobra.Command, generatorName string) error {
  80. return cmdutil.UsageErrorf(cmd, "Generator %s not supported. ", generatorName)
  81. }
  82. // Complete completes all the required options
  83. func (o *ServiceClusterIPOpts) Complete(f cmdutil.Factory, cmd *cobra.Command, args []string) error {
  84. name, err := NameFromCommandArgs(cmd, args)
  85. if err != nil {
  86. return err
  87. }
  88. var generator generate.StructuredGenerator
  89. switch generatorName := cmdutil.GetFlagString(cmd, "generator"); generatorName {
  90. case generateversioned.ServiceClusterIPGeneratorV1Name:
  91. generator = &generateversioned.ServiceCommonGeneratorV1{
  92. Name: name,
  93. TCP: cmdutil.GetFlagStringSlice(cmd, "tcp"),
  94. Type: v1.ServiceTypeClusterIP,
  95. ClusterIP: cmdutil.GetFlagString(cmd, "clusterip"),
  96. }
  97. default:
  98. return errUnsupportedGenerator(cmd, generatorName)
  99. }
  100. return o.CreateSubcommandOptions.Complete(f, cmd, args, generator)
  101. }
  102. // Run calls the CreateSubcommandOptions.Run in ServiceClusterIPOpts instance
  103. func (o *ServiceClusterIPOpts) Run() error {
  104. return o.CreateSubcommandOptions.Run()
  105. }
  106. var (
  107. serviceNodePortLong = templates.LongDesc(i18n.T(`
  108. Create a NodePort service with the specified name.`))
  109. serviceNodePortExample = templates.Examples(i18n.T(`
  110. # Create a new NodePort service named my-ns
  111. kubectl create service nodeport my-ns --tcp=5678:8080`))
  112. )
  113. // ServiceNodePortOpts holds the options for 'create service nodeport' sub command
  114. type ServiceNodePortOpts struct {
  115. CreateSubcommandOptions *CreateSubcommandOptions
  116. }
  117. // NewCmdCreateServiceNodePort is a macro command for creating a NodePort service
  118. func NewCmdCreateServiceNodePort(f cmdutil.Factory, ioStreams genericclioptions.IOStreams) *cobra.Command {
  119. options := &ServiceNodePortOpts{
  120. CreateSubcommandOptions: NewCreateSubcommandOptions(ioStreams),
  121. }
  122. cmd := &cobra.Command{
  123. Use: "nodeport NAME [--tcp=port:targetPort] [--dry-run]",
  124. DisableFlagsInUseLine: true,
  125. Short: i18n.T("Create a NodePort service."),
  126. Long: serviceNodePortLong,
  127. Example: serviceNodePortExample,
  128. Run: func(cmd *cobra.Command, args []string) {
  129. cmdutil.CheckErr(options.Complete(f, cmd, args))
  130. cmdutil.CheckErr(options.Run())
  131. },
  132. }
  133. options.CreateSubcommandOptions.PrintFlags.AddFlags(cmd)
  134. cmdutil.AddApplyAnnotationFlags(cmd)
  135. cmdutil.AddValidateFlags(cmd)
  136. cmdutil.AddGeneratorFlags(cmd, generateversioned.ServiceNodePortGeneratorV1Name)
  137. cmd.Flags().Int("node-port", 0, "Port used to expose the service on each node in a cluster.")
  138. addPortFlags(cmd)
  139. return cmd
  140. }
  141. // Complete completes all the required options
  142. func (o *ServiceNodePortOpts) Complete(f cmdutil.Factory, cmd *cobra.Command, args []string) error {
  143. name, err := NameFromCommandArgs(cmd, args)
  144. if err != nil {
  145. return err
  146. }
  147. var generator generate.StructuredGenerator
  148. switch generatorName := cmdutil.GetFlagString(cmd, "generator"); generatorName {
  149. case generateversioned.ServiceNodePortGeneratorV1Name:
  150. generator = &generateversioned.ServiceCommonGeneratorV1{
  151. Name: name,
  152. TCP: cmdutil.GetFlagStringSlice(cmd, "tcp"),
  153. Type: v1.ServiceTypeNodePort,
  154. ClusterIP: "",
  155. NodePort: cmdutil.GetFlagInt(cmd, "node-port"),
  156. }
  157. default:
  158. return errUnsupportedGenerator(cmd, generatorName)
  159. }
  160. return o.CreateSubcommandOptions.Complete(f, cmd, args, generator)
  161. }
  162. // Run calls the CreateSubcommandOptions.Run in ServiceNodePortOpts instance
  163. func (o *ServiceNodePortOpts) Run() error {
  164. return o.CreateSubcommandOptions.Run()
  165. }
  166. var (
  167. serviceLoadBalancerLong = templates.LongDesc(i18n.T(`
  168. Create a LoadBalancer service with the specified name.`))
  169. serviceLoadBalancerExample = templates.Examples(i18n.T(`
  170. # Create a new LoadBalancer service named my-lbs
  171. kubectl create service loadbalancer my-lbs --tcp=5678:8080`))
  172. )
  173. // ServiceLoadBalancerOpts holds the options for 'create service loadbalancer' sub command
  174. type ServiceLoadBalancerOpts struct {
  175. CreateSubcommandOptions *CreateSubcommandOptions
  176. }
  177. // NewCmdCreateServiceLoadBalancer is a macro command for creating a LoadBalancer service
  178. func NewCmdCreateServiceLoadBalancer(f cmdutil.Factory, ioStreams genericclioptions.IOStreams) *cobra.Command {
  179. options := &ServiceLoadBalancerOpts{
  180. CreateSubcommandOptions: NewCreateSubcommandOptions(ioStreams),
  181. }
  182. cmd := &cobra.Command{
  183. Use: "loadbalancer NAME [--tcp=port:targetPort] [--dry-run]",
  184. DisableFlagsInUseLine: true,
  185. Short: i18n.T("Create a LoadBalancer service."),
  186. Long: serviceLoadBalancerLong,
  187. Example: serviceLoadBalancerExample,
  188. Run: func(cmd *cobra.Command, args []string) {
  189. cmdutil.CheckErr(options.Complete(f, cmd, args))
  190. cmdutil.CheckErr(options.Run())
  191. },
  192. }
  193. options.CreateSubcommandOptions.PrintFlags.AddFlags(cmd)
  194. cmdutil.AddApplyAnnotationFlags(cmd)
  195. cmdutil.AddValidateFlags(cmd)
  196. cmdutil.AddGeneratorFlags(cmd, generateversioned.ServiceLoadBalancerGeneratorV1Name)
  197. addPortFlags(cmd)
  198. return cmd
  199. }
  200. // Complete completes all the required options
  201. func (o *ServiceLoadBalancerOpts) Complete(f cmdutil.Factory, cmd *cobra.Command, args []string) error {
  202. name, err := NameFromCommandArgs(cmd, args)
  203. if err != nil {
  204. return err
  205. }
  206. var generator generate.StructuredGenerator
  207. switch generatorName := cmdutil.GetFlagString(cmd, "generator"); generatorName {
  208. case generateversioned.ServiceLoadBalancerGeneratorV1Name:
  209. generator = &generateversioned.ServiceCommonGeneratorV1{
  210. Name: name,
  211. TCP: cmdutil.GetFlagStringSlice(cmd, "tcp"),
  212. Type: v1.ServiceTypeLoadBalancer,
  213. ClusterIP: "",
  214. }
  215. default:
  216. return errUnsupportedGenerator(cmd, generatorName)
  217. }
  218. return o.CreateSubcommandOptions.Complete(f, cmd, args, generator)
  219. }
  220. // Run calls the CreateSubcommandOptions.Run in ServiceLoadBalancerOpts instance
  221. func (o *ServiceLoadBalancerOpts) Run() error {
  222. return o.CreateSubcommandOptions.Run()
  223. }
  224. var (
  225. serviceExternalNameLong = templates.LongDesc(i18n.T(`
  226. Create an ExternalName service with the specified name.
  227. ExternalName service references to an external DNS address instead of
  228. only pods, which will allow application authors to reference services
  229. that exist off platform, on other clusters, or locally.`))
  230. serviceExternalNameExample = templates.Examples(i18n.T(`
  231. # Create a new ExternalName service named my-ns
  232. kubectl create service externalname my-ns --external-name bar.com`))
  233. )
  234. // ServiceExternalNameOpts holds the options for 'create service externalname' sub command
  235. type ServiceExternalNameOpts struct {
  236. CreateSubcommandOptions *CreateSubcommandOptions
  237. }
  238. // NewCmdCreateServiceExternalName is a macro command for creating an ExternalName service
  239. func NewCmdCreateServiceExternalName(f cmdutil.Factory, ioStreams genericclioptions.IOStreams) *cobra.Command {
  240. options := &ServiceExternalNameOpts{
  241. CreateSubcommandOptions: NewCreateSubcommandOptions(ioStreams),
  242. }
  243. cmd := &cobra.Command{
  244. Use: "externalname NAME --external-name external.name [--dry-run]",
  245. DisableFlagsInUseLine: true,
  246. Short: i18n.T("Create an ExternalName service."),
  247. Long: serviceExternalNameLong,
  248. Example: serviceExternalNameExample,
  249. Run: func(cmd *cobra.Command, args []string) {
  250. cmdutil.CheckErr(options.Complete(f, cmd, args))
  251. cmdutil.CheckErr(options.Run())
  252. },
  253. }
  254. options.CreateSubcommandOptions.PrintFlags.AddFlags(cmd)
  255. cmdutil.AddApplyAnnotationFlags(cmd)
  256. cmdutil.AddValidateFlags(cmd)
  257. cmdutil.AddGeneratorFlags(cmd, generateversioned.ServiceExternalNameGeneratorV1Name)
  258. addPortFlags(cmd)
  259. cmd.Flags().String("external-name", "", i18n.T("External name of service"))
  260. cmd.MarkFlagRequired("external-name")
  261. return cmd
  262. }
  263. // Complete completes all the required options
  264. func (o *ServiceExternalNameOpts) Complete(f cmdutil.Factory, cmd *cobra.Command, args []string) error {
  265. name, err := NameFromCommandArgs(cmd, args)
  266. if err != nil {
  267. return err
  268. }
  269. var generator generate.StructuredGenerator
  270. switch generatorName := cmdutil.GetFlagString(cmd, "generator"); generatorName {
  271. case generateversioned.ServiceExternalNameGeneratorV1Name:
  272. generator = &generateversioned.ServiceCommonGeneratorV1{
  273. Name: name,
  274. Type: v1.ServiceTypeExternalName,
  275. ExternalName: cmdutil.GetFlagString(cmd, "external-name"),
  276. ClusterIP: "",
  277. }
  278. default:
  279. return errUnsupportedGenerator(cmd, generatorName)
  280. }
  281. return o.CreateSubcommandOptions.Complete(f, cmd, args, generator)
  282. }
  283. // Run calls the CreateSubcommandOptions.Run in ServiceExternalNameOpts instance
  284. func (o *ServiceExternalNameOpts) Run() error {
  285. return o.CreateSubcommandOptions.Run()
  286. }