mirror of
				https://github.com/optim-enterprises-bv/kubernetes.git
				synced 2025-11-04 04:08:16 +00:00 
			
		
		
		
	Merge pull request #3592 from brendandburns/cli
Add a service generator and a command to easily expose services.
This commit is contained in:
		@@ -395,6 +395,7 @@ Additional help topics:
 | 
				
			|||||||
  kubectl resize        Set a new size for a resizable resource (currently only Replication Controllers)
 | 
					  kubectl resize        Set a new size for a resizable resource (currently only Replication Controllers)
 | 
				
			||||||
  kubectl run-container Run a particular image on the cluster.
 | 
					  kubectl run-container Run a particular image on the cluster.
 | 
				
			||||||
  kubectl stop          Gracefully shutdown a resource
 | 
					  kubectl stop          Gracefully shutdown a resource
 | 
				
			||||||
 | 
					  kubectl expose        Take a replicated application and expose it as Kubernetes Service
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Use "kubectl help [command]" for more information about that command.
 | 
					Use "kubectl help [command]" for more information about that command.
 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
@@ -899,7 +900,7 @@ Examples:
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
Usage:
 | 
					Usage:
 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
  kubectl run-container <name> --image=<image> [--replicas=replicas] [--dry-run=<bool>] [--overrides=<inline-json>] [flags]
 | 
					  kubectl run-container <name> --image=<image> [--port=<port>] [--replicas=replicas] [--dry-run=<bool>] [--overrides=<inline-json>] [flags]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 Available Flags:
 | 
					 Available Flags:
 | 
				
			||||||
      --alsologtostderr=false: log to standard error as well as files
 | 
					      --alsologtostderr=false: log to standard error as well as files
 | 
				
			||||||
@@ -911,12 +912,12 @@ Usage:
 | 
				
			|||||||
      --cluster="": The name of the kubeconfig cluster to use
 | 
					      --cluster="": The name of the kubeconfig cluster to use
 | 
				
			||||||
      --context="": The name of the kubeconfig context to use
 | 
					      --context="": The name of the kubeconfig context to use
 | 
				
			||||||
      --dry-run=false: If true, only print the object that would be sent, don't actually do anything
 | 
					      --dry-run=false: If true, only print the object that would be sent, don't actually do anything
 | 
				
			||||||
      --generator="run-container/v1": The name of the api generator that you want to use.  Default 'run-container-controller-v1'
 | 
					      --generator="run-container/v1": The name of the api generator that you want to use.  Default 'run-container-controller/v1'
 | 
				
			||||||
  -h, --help=false: help for run-container
 | 
					  -h, --help=false: help for run-container
 | 
				
			||||||
      --image="": The image for the container you wish to run.
 | 
					      --image="": The image for the container you wish to run.
 | 
				
			||||||
      --insecure-skip-tls-verify=false: If true, the server's certificate will not be checked for validity. This will make your HTTPS connections insecure.
 | 
					      --insecure-skip-tls-verify=false: If true, the server's certificate will not be checked for validity. This will make your HTTPS connections insecure.
 | 
				
			||||||
      --kubeconfig="": Path to the kubeconfig file to use for CLI requests.
 | 
					      --kubeconfig="": Path to the kubeconfig file to use for CLI requests.
 | 
				
			||||||
  -l, --labels="": Labels to apply to the pod(s) created by this call to run.
 | 
					  -l, --labels="": Labels to apply to the pod(s) created by this call to run-container.
 | 
				
			||||||
      --log_backtrace_at=:0: when logging hits line file:N, emit a stack trace
 | 
					      --log_backtrace_at=:0: when logging hits line file:N, emit a stack trace
 | 
				
			||||||
      --log_dir=: If non-empty, write log files in this directory
 | 
					      --log_dir=: If non-empty, write log files in this directory
 | 
				
			||||||
      --log_flush_frequency=5s: Maximum number of seconds between log flushes
 | 
					      --log_flush_frequency=5s: Maximum number of seconds between log flushes
 | 
				
			||||||
@@ -928,6 +929,7 @@ Usage:
 | 
				
			|||||||
  -o, --output="": Output format: json|yaml|template|templatefile
 | 
					  -o, --output="": Output format: json|yaml|template|templatefile
 | 
				
			||||||
      --output-version="": Output the formatted object with the given version (default api-version)
 | 
					      --output-version="": Output the formatted object with the given version (default api-version)
 | 
				
			||||||
      --overrides="": An inline JSON override for the generated object.  If this is non-empty, it is parsed used to override the generated object.  Requires that the object supply a valid apiVersion field.
 | 
					      --overrides="": An inline JSON override for the generated object.  If this is non-empty, it is parsed used to override the generated object.  Requires that the object supply a valid apiVersion field.
 | 
				
			||||||
 | 
					      --port=-1: The port that this container exposes.
 | 
				
			||||||
  -r, --replicas=1: Number of replicas to create for this container. Default 1
 | 
					  -r, --replicas=1: Number of replicas to create for this container. Default 1
 | 
				
			||||||
  -s, --server="": The address of the Kubernetes API server
 | 
					  -s, --server="": The address of the Kubernetes API server
 | 
				
			||||||
      --stderrthreshold=2: logs at or above this threshold go to stderr
 | 
					      --stderrthreshold=2: logs at or above this threshold go to stderr
 | 
				
			||||||
@@ -983,3 +985,64 @@ Usage:
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#### expose
 | 
				
			||||||
 | 
					Take a replicated application and expose it as Kubernetes Service.
 | 
				
			||||||
 | 
							
 | 
				
			||||||
 | 
					Looks up a ReplicationController named <name>, and uses the selector for that replication controller
 | 
				
			||||||
 | 
					as the selector for a new Service which services on <port>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Examples:
 | 
				
			||||||
 | 
					$ kubectl expose nginx --port=80 --container-port=8000
 | 
				
			||||||
 | 
					<creates a service for a replicated nginx, which serves on port 80 and connects to the containers on port 8000>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					$ kubectl expose streamer --port=4100 --protocol=udp --service-name=video-stream
 | 
				
			||||||
 | 
					<create a service for a replicated streaming application on port 4100 balancing UDP traffic and is named 'video-stream'>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Usage:
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					  kubectl expose <name> --port=<port> [--protocol=TCP|UDP] [--container-port=<number-or-name>] [--service-name=<name>] [--public-ip=<ip>] [--create-external-load-balancer] [flags]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 Available Flags:
 | 
				
			||||||
 | 
					      --alsologtostderr=false: log to standard error as well as files
 | 
				
			||||||
 | 
					      --api-version="": The API version to use when talking to the server
 | 
				
			||||||
 | 
					  -a, --auth-path="": Path to the auth info file. If missing, prompt the user. Only used if using https.
 | 
				
			||||||
 | 
					      --certificate-authority="": Path to a cert. file for the certificate authority.
 | 
				
			||||||
 | 
					      --client-certificate="": Path to a client key file for TLS.
 | 
				
			||||||
 | 
					      --client-key="": Path to a client key file for TLS.
 | 
				
			||||||
 | 
					      --cluster="": The name of the kubeconfig cluster to use
 | 
				
			||||||
 | 
					      --container-port="": Name or number for the port on the container that the service should direct traffic to. Optional.
 | 
				
			||||||
 | 
					      --context="": The name of the kubeconfig context to use
 | 
				
			||||||
 | 
					      --create-external-load-balancer=false: If true, create an external load balancer for this service. Implementation is cloud provider dependent. Default false
 | 
				
			||||||
 | 
					      --dry-run=false: If true, only print the object that would be sent, don't actually do anything
 | 
				
			||||||
 | 
					      --generator="service/v1": The name of the api generator that you want to use.  Default 'service/v1'
 | 
				
			||||||
 | 
					  -h, --help=false: help for expose
 | 
				
			||||||
 | 
					      --insecure-skip-tls-verify=false: If true, the server's certificate will not be checked for validity. This will make your HTTPS connections insecure.
 | 
				
			||||||
 | 
					      --kubeconfig="": Path to the kubeconfig file to use for CLI requests.
 | 
				
			||||||
 | 
					      --log_backtrace_at=:0: when logging hits line file:N, emit a stack trace
 | 
				
			||||||
 | 
					      --log_dir=: If non-empty, write log files in this directory
 | 
				
			||||||
 | 
					      --log_flush_frequency=5s: Maximum number of seconds between log flushes
 | 
				
			||||||
 | 
					      --logtostderr=true: log to standard error instead of files
 | 
				
			||||||
 | 
					      --match-server-version=false: Require server version to match client version
 | 
				
			||||||
 | 
					      --namespace="": If present, the namespace scope for this CLI request.
 | 
				
			||||||
 | 
					      --no-headers=false: When using the default output, don't print headers
 | 
				
			||||||
 | 
					      --ns-path="": Path to the namespace info file that holds the namespace context to use for CLI requests.
 | 
				
			||||||
 | 
					  -o, --output="": Output format: json|yaml|template|templatefile
 | 
				
			||||||
 | 
					      --output-version="": Output the formatted object with the given version (default api-version)
 | 
				
			||||||
 | 
					      --overrides="": An inline JSON override for the generated object.  If this is non-empty, it is parsed used to override the generated object.  Requires that the object supply a valid apiVersion field.
 | 
				
			||||||
 | 
					      --port=-1: The port that the service should serve on. Required.
 | 
				
			||||||
 | 
					      --protocol="TCP": The network protocol for the service you want to be created. Default 'tcp'
 | 
				
			||||||
 | 
					      --public-ip="": Name of a public ip address to set for the service.  The service will be assigned this IP in addition to its generated service IP.
 | 
				
			||||||
 | 
					      --selector="": A label selector to use for this service.  If empty (the default) infer the selector from the replication controller
 | 
				
			||||||
 | 
					  -s, --server="": The address of the Kubernetes API server
 | 
				
			||||||
 | 
					      --service-name="": The name for the newly created service.
 | 
				
			||||||
 | 
					      --stderrthreshold=2: logs at or above this threshold go to stderr
 | 
				
			||||||
 | 
					  -t, --template="": Template string or path to template file to use when -o=template or -o=templatefile.
 | 
				
			||||||
 | 
					      --token="": Bearer token for authentication to the API server.
 | 
				
			||||||
 | 
					      --user="": The name of the kubeconfig user to use
 | 
				
			||||||
 | 
					      --v=0: log level for V logs
 | 
				
			||||||
 | 
					      --validate=false: If true, use a schema to validate the input before sending it
 | 
				
			||||||
 | 
					      --vmodule=: comma-separated list of pattern=N settings for file-filtered logging
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -212,6 +212,7 @@ Find more information at https://github.com/GoogleCloudPlatform/kubernetes.`,
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	cmds.AddCommand(f.NewCmdRunContainer(out))
 | 
						cmds.AddCommand(f.NewCmdRunContainer(out))
 | 
				
			||||||
	cmds.AddCommand(f.NewCmdStop(out))
 | 
						cmds.AddCommand(f.NewCmdStop(out))
 | 
				
			||||||
 | 
						cmds.AddCommand(f.NewCmdExposeService(out))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return cmds
 | 
						return cmds
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										112
									
								
								pkg/kubectl/cmd/expose.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										112
									
								
								pkg/kubectl/cmd/expose.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,112 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					Copyright 2014 Google Inc. All rights reserved.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Licensed under the Apache License, Version 2.0 (the "License");
 | 
				
			||||||
 | 
					you may not use this file except in compliance with the License.
 | 
				
			||||||
 | 
					You may obtain a copy of the License at
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    http://www.apache.org/licenses/LICENSE-2.0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Unless required by applicable law or agreed to in writing, software
 | 
				
			||||||
 | 
					distributed under the License is distributed on an "AS IS" BASIS,
 | 
				
			||||||
 | 
					WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
				
			||||||
 | 
					See the License for the specific language governing permissions and
 | 
				
			||||||
 | 
					limitations under the License.
 | 
				
			||||||
 | 
					*/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					package cmd
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"fmt"
 | 
				
			||||||
 | 
						"io"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
 | 
				
			||||||
 | 
						"github.com/GoogleCloudPlatform/kubernetes/pkg/kubectl"
 | 
				
			||||||
 | 
						"github.com/spf13/cobra"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (f *Factory) NewCmdExposeService(out io.Writer) *cobra.Command {
 | 
				
			||||||
 | 
						cmd := &cobra.Command{
 | 
				
			||||||
 | 
							Use:   "expose <name> --port=<port> [--protocol=TCP|UDP] [--container-port=<number-or-name>] [--service-name=<name>] [--public-ip=<ip>] [--create-external-load-balancer]",
 | 
				
			||||||
 | 
							Short: "Take a replicated application and expose it as Kubernetes Service",
 | 
				
			||||||
 | 
							Long: `Take a replicated application and expose it as Kubernetes Service.
 | 
				
			||||||
 | 
							
 | 
				
			||||||
 | 
					Looks up a ReplicationController named <name>, and uses the selector for that replication controller
 | 
				
			||||||
 | 
					as the selector for a new Service which services on <port>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Examples:
 | 
				
			||||||
 | 
					$ kubectl expose nginx --port=80 --container-port=8000
 | 
				
			||||||
 | 
					<creates a service for a replicated nginx, which serves on port 80 and connects to the containers on port 8000>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					$ kubectl expose streamer --port=4100 --protocol=udp --service-name=video-stream
 | 
				
			||||||
 | 
					<create a service for a replicated streaming application on port 4100 balancing UDP traffic and is named 'video-stream'>
 | 
				
			||||||
 | 
					`,
 | 
				
			||||||
 | 
							Run: func(cmd *cobra.Command, args []string) {
 | 
				
			||||||
 | 
								if len(args) != 1 {
 | 
				
			||||||
 | 
									usageError(cmd, "<name> is required for expose")
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								namespace, err := f.DefaultNamespace(cmd)
 | 
				
			||||||
 | 
								checkErr(err)
 | 
				
			||||||
 | 
								client, err := f.Client(cmd)
 | 
				
			||||||
 | 
								checkErr(err)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								rc, err := client.ReplicationControllers(namespace).Get(args[0])
 | 
				
			||||||
 | 
								checkErr(err)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								generatorName := GetFlagString(cmd, "generator")
 | 
				
			||||||
 | 
								generator, found := kubectl.Generators[generatorName]
 | 
				
			||||||
 | 
								if !found {
 | 
				
			||||||
 | 
									usageError(cmd, fmt.Sprintf("Generator: %s not found.", generator))
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								if GetFlagInt(cmd, "port") < 1 {
 | 
				
			||||||
 | 
									usageError(cmd, "--port is required and must be a positive integer.")
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								names := generator.ParamNames()
 | 
				
			||||||
 | 
								params := kubectl.MakeParams(cmd, names)
 | 
				
			||||||
 | 
								if len(GetFlagString(cmd, "service-name")) == 0 {
 | 
				
			||||||
 | 
									params["name"] = args[0]
 | 
				
			||||||
 | 
								} else {
 | 
				
			||||||
 | 
									params["name"] = GetFlagString(cmd, "service-name")
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								if _, found := params["selector"]; !found {
 | 
				
			||||||
 | 
									params["selector"] = kubectl.MakeLabels(rc.Spec.Selector)
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								if GetFlagBool(cmd, "create-external-load-balancer") {
 | 
				
			||||||
 | 
									params["create-external-load-balancer"] = "true"
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								err = kubectl.ValidateParams(names, params)
 | 
				
			||||||
 | 
								checkErr(err)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								service, err := generator.Generate(params)
 | 
				
			||||||
 | 
								checkErr(err)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								inline := GetFlagString(cmd, "overrides")
 | 
				
			||||||
 | 
								if len(inline) > 0 {
 | 
				
			||||||
 | 
									Merge(service, inline, "Service")
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								// TODO: extract this flag to a central location, when such a location exists.
 | 
				
			||||||
 | 
								if !GetFlagBool(cmd, "dry-run") {
 | 
				
			||||||
 | 
									service, err = client.Services(namespace).Create(service.(*api.Service))
 | 
				
			||||||
 | 
									checkErr(err)
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								err = PrintObject(cmd, service, f, out)
 | 
				
			||||||
 | 
								checkErr(err)
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						AddPrinterFlags(cmd)
 | 
				
			||||||
 | 
						cmd.Flags().String("generator", "service/v1", "The name of the api generator that you want to use.  Default 'service/v1'")
 | 
				
			||||||
 | 
						cmd.Flags().String("protocol", "TCP", "The network protocol for the service you want to be created. Default 'tcp'")
 | 
				
			||||||
 | 
						cmd.Flags().Int("port", -1, "The port that the service should serve on. Required.")
 | 
				
			||||||
 | 
						cmd.Flags().Bool("create-external-load-balancer", false, "If true, create an external load balancer for this service. Implementation is cloud provider dependent. Default false")
 | 
				
			||||||
 | 
						cmd.Flags().String("selector", "", "A label selector to use for this service.  If empty (the default) infer the selector from the replication controller")
 | 
				
			||||||
 | 
						cmd.Flags().Bool("dry-run", false, "If true, only print the object that would be sent, don't actually do anything")
 | 
				
			||||||
 | 
						cmd.Flags().String("container-port", "", "Name or number for the port on the container that the service should direct traffic to. Optional.")
 | 
				
			||||||
 | 
						cmd.Flags().String("public-ip", "", "Name of a public ip address to set for the service.  The service will be assigned this IP in addition to its generated service IP.")
 | 
				
			||||||
 | 
						cmd.Flags().String("overrides", "", "An inline JSON override for the generated object.  If this is non-empty, it is parsed used to override the generated object.  Requires that the object supply a valid apiVersion field.")
 | 
				
			||||||
 | 
						cmd.Flags().String("service-name", "", "The name for the newly created service.")
 | 
				
			||||||
 | 
						return cmd
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -27,7 +27,7 @@ import (
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
func (f *Factory) NewCmdRunContainer(out io.Writer) *cobra.Command {
 | 
					func (f *Factory) NewCmdRunContainer(out io.Writer) *cobra.Command {
 | 
				
			||||||
	cmd := &cobra.Command{
 | 
						cmd := &cobra.Command{
 | 
				
			||||||
		Use:   "run-container <name> --image=<image> [--replicas=replicas] [--dry-run=<bool>] [--overrides=<inline-json>]",
 | 
							Use:   "run-container <name> --image=<image> [--port=<port>] [--replicas=replicas] [--dry-run=<bool>] [--overrides=<inline-json>]",
 | 
				
			||||||
		Short: "Run a particular image on the cluster.",
 | 
							Short: "Run a particular image on the cluster.",
 | 
				
			||||||
		Long: `Create and run a particular image, possibly replicated.
 | 
							Long: `Create and run a particular image, possibly replicated.
 | 
				
			||||||
Creates a replication controller to manage the created container(s)
 | 
					Creates a replication controller to manage the created container(s)
 | 
				
			||||||
@@ -46,7 +46,7 @@ Examples:
 | 
				
			|||||||
  <start a single instance of nginx, but overload the desired state with a partial set of values parsed from JSON`,
 | 
					  <start a single instance of nginx, but overload the desired state with a partial set of values parsed from JSON`,
 | 
				
			||||||
		Run: func(cmd *cobra.Command, args []string) {
 | 
							Run: func(cmd *cobra.Command, args []string) {
 | 
				
			||||||
			if len(args) != 1 {
 | 
								if len(args) != 1 {
 | 
				
			||||||
				usageError(cmd, "<name> is required for run")
 | 
									usageError(cmd, "<name> is required for run-container")
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			namespace, err := f.DefaultNamespace(cmd)
 | 
								namespace, err := f.DefaultNamespace(cmd)
 | 
				
			||||||
@@ -86,11 +86,12 @@ Examples:
 | 
				
			|||||||
		},
 | 
							},
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	AddPrinterFlags(cmd)
 | 
						AddPrinterFlags(cmd)
 | 
				
			||||||
	cmd.Flags().String("generator", "run-container/v1", "The name of the api generator that you want to use.  Default 'run-container-controller-v1'")
 | 
						cmd.Flags().String("generator", "run-container/v1", "The name of the api generator that you want to use.  Default 'run-container-controller/v1'")
 | 
				
			||||||
	cmd.Flags().String("image", "", "The image for the container you wish to run.")
 | 
						cmd.Flags().String("image", "", "The image for the container you wish to run.")
 | 
				
			||||||
	cmd.Flags().IntP("replicas", "r", 1, "Number of replicas to create for this container. Default 1")
 | 
						cmd.Flags().IntP("replicas", "r", 1, "Number of replicas to create for this container. Default 1")
 | 
				
			||||||
	cmd.Flags().Bool("dry-run", false, "If true, only print the object that would be sent, don't actually do anything")
 | 
						cmd.Flags().Bool("dry-run", false, "If true, only print the object that would be sent, don't actually do anything")
 | 
				
			||||||
	cmd.Flags().StringP("labels", "l", "", "Labels to apply to the pod(s) created by this call to run.")
 | 
					 | 
				
			||||||
	cmd.Flags().String("overrides", "", "An inline JSON override for the generated object.  If this is non-empty, it is parsed used to override the generated object.  Requires that the object supply a valid apiVersion field.")
 | 
						cmd.Flags().String("overrides", "", "An inline JSON override for the generated object.  If this is non-empty, it is parsed used to override the generated object.  Requires that the object supply a valid apiVersion field.")
 | 
				
			||||||
 | 
						cmd.Flags().Int("port", -1, "The port that this container exposes.")
 | 
				
			||||||
 | 
						cmd.Flags().StringP("labels", "l", "", "Labels to apply to the pod(s) created by this call to run-container.")
 | 
				
			||||||
	return cmd
 | 
						return cmd
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -18,8 +18,10 @@ package kubectl
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
	"fmt"
 | 
						"fmt"
 | 
				
			||||||
 | 
						"strings"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
 | 
						"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
 | 
				
			||||||
 | 
						"github.com/golang/glog"
 | 
				
			||||||
	"github.com/spf13/cobra"
 | 
						"github.com/spf13/cobra"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -42,6 +44,7 @@ type Generator interface {
 | 
				
			|||||||
// TODO: Dynamically create this from a list of template files?
 | 
					// TODO: Dynamically create this from a list of template files?
 | 
				
			||||||
var Generators map[string]Generator = map[string]Generator{
 | 
					var Generators map[string]Generator = map[string]Generator{
 | 
				
			||||||
	"run-container/v1": BasicReplicationController{},
 | 
						"run-container/v1": BasicReplicationController{},
 | 
				
			||||||
 | 
						"service/v1":       ServiceGenerator{},
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// ValidateParams ensures that all required params are present in the params map
 | 
					// ValidateParams ensures that all required params are present in the params map
 | 
				
			||||||
@@ -68,3 +71,29 @@ func MakeParams(cmd *cobra.Command, params []GeneratorParam) map[string]string {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
	return result
 | 
						return result
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func MakeLabels(labels map[string]string) string {
 | 
				
			||||||
 | 
						out := []string{}
 | 
				
			||||||
 | 
						for key, value := range labels {
 | 
				
			||||||
 | 
							out = append(out, fmt.Sprintf("%s=%s", key, value))
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return strings.Join(out, ",")
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// ParseLabels turns a string representation of a label set into a map[string]string
 | 
				
			||||||
 | 
					func ParseLabels(labelString string) map[string]string {
 | 
				
			||||||
 | 
						if len(labelString) == 0 {
 | 
				
			||||||
 | 
							return nil
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						labels := map[string]string{}
 | 
				
			||||||
 | 
						labelSpecs := strings.Split(labelString, ",")
 | 
				
			||||||
 | 
						for ix := range labelSpecs {
 | 
				
			||||||
 | 
							labelSpec := strings.Split(labelSpecs[ix], "=")
 | 
				
			||||||
 | 
							if len(labelSpec) != 2 {
 | 
				
			||||||
 | 
								glog.Errorf("unexpected label spec: %s", labelSpecs[ix])
 | 
				
			||||||
 | 
								continue
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							labels[labelSpec[0]] = labelSpec[1]
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return labels
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -18,11 +18,9 @@ package kubectl
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
	"strconv"
 | 
						"strconv"
 | 
				
			||||||
	"strings"
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
 | 
						"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
 | 
				
			||||||
	"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
 | 
						"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
 | 
				
			||||||
	"github.com/golang/glog"
 | 
					 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type BasicReplicationController struct{}
 | 
					type BasicReplicationController struct{}
 | 
				
			||||||
@@ -33,6 +31,7 @@ func (BasicReplicationController) ParamNames() []GeneratorParam {
 | 
				
			|||||||
		{"name", true},
 | 
							{"name", true},
 | 
				
			||||||
		{"replicas", true},
 | 
							{"replicas", true},
 | 
				
			||||||
		{"image", true},
 | 
							{"image", true},
 | 
				
			||||||
 | 
							{"port", false},
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -74,23 +73,17 @@ func (BasicReplicationController) Generate(params map[string]string) (runtime.Ob
 | 
				
			|||||||
			},
 | 
								},
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if len(params["port"]) > 0 {
 | 
				
			||||||
 | 
							port, err := strconv.Atoi(params["port"])
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								return nil, err
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							controller.Spec.Template.Spec.Containers[0].Ports = []api.Port{
 | 
				
			||||||
 | 
								{
 | 
				
			||||||
 | 
									ContainerPort: port,
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
	return &controller, nil
 | 
						return &controller, nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					 | 
				
			||||||
// TODO: extract this to a common location.
 | 
					 | 
				
			||||||
func ParseLabels(labelString string) map[string]string {
 | 
					 | 
				
			||||||
	if len(labelString) == 0 {
 | 
					 | 
				
			||||||
		return nil
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	labels := map[string]string{}
 | 
					 | 
				
			||||||
	labelSpecs := strings.Split(labelString, ",")
 | 
					 | 
				
			||||||
	for ix := range labelSpecs {
 | 
					 | 
				
			||||||
		labelSpec := strings.Split(labelSpecs[ix], "=")
 | 
					 | 
				
			||||||
		if len(labelSpec) != 2 {
 | 
					 | 
				
			||||||
			glog.Errorf("unexpected label spec: %s", labelSpecs[ix])
 | 
					 | 
				
			||||||
			continue
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		labels[labelSpec[0]] = labelSpec[1]
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return labels
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 
 | 
				
			|||||||
@@ -59,6 +59,42 @@ func TestGenerate(t *testing.T) {
 | 
				
			|||||||
				},
 | 
									},
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								params: map[string]string{
 | 
				
			||||||
 | 
									"name":     "foo",
 | 
				
			||||||
 | 
									"image":    "someimage",
 | 
				
			||||||
 | 
									"replicas": "1",
 | 
				
			||||||
 | 
									"port":     "80",
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
								expected: &api.ReplicationController{
 | 
				
			||||||
 | 
									ObjectMeta: api.ObjectMeta{
 | 
				
			||||||
 | 
										Name:   "foo",
 | 
				
			||||||
 | 
										Labels: map[string]string{"run-container": "foo"},
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
 | 
									Spec: api.ReplicationControllerSpec{
 | 
				
			||||||
 | 
										Replicas: 1,
 | 
				
			||||||
 | 
										Selector: map[string]string{"run-container": "foo"},
 | 
				
			||||||
 | 
										Template: &api.PodTemplateSpec{
 | 
				
			||||||
 | 
											ObjectMeta: api.ObjectMeta{
 | 
				
			||||||
 | 
												Labels: map[string]string{"run-container": "foo"},
 | 
				
			||||||
 | 
											},
 | 
				
			||||||
 | 
											Spec: api.PodSpec{
 | 
				
			||||||
 | 
												Containers: []api.Container{
 | 
				
			||||||
 | 
													{
 | 
				
			||||||
 | 
														Name:  "foo",
 | 
				
			||||||
 | 
														Image: "someimage",
 | 
				
			||||||
 | 
														Ports: []api.Port{
 | 
				
			||||||
 | 
															{
 | 
				
			||||||
 | 
																ContainerPort: 80,
 | 
				
			||||||
 | 
															},
 | 
				
			||||||
 | 
														},
 | 
				
			||||||
 | 
													},
 | 
				
			||||||
 | 
												},
 | 
				
			||||||
 | 
											},
 | 
				
			||||||
 | 
										},
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			params: map[string]string{
 | 
								params: map[string]string{
 | 
				
			||||||
				"name":     "foo",
 | 
									"name":     "foo",
 | 
				
			||||||
@@ -97,8 +133,8 @@ func TestGenerate(t *testing.T) {
 | 
				
			|||||||
		if !test.expectErr && err != nil {
 | 
							if !test.expectErr && err != nil {
 | 
				
			||||||
			t.Errorf("unexpected error: %v", err)
 | 
								t.Errorf("unexpected error: %v", err)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		if !reflect.DeepEqual(obj, test.expected) {
 | 
							if !reflect.DeepEqual(obj.(*api.ReplicationController).Spec.Template, test.expected.Spec.Template) {
 | 
				
			||||||
			t.Errorf("\nexpected:\n%v\nsaw:\n%v", test.expected, obj)
 | 
								t.Errorf("\nexpected:\n%#v\nsaw:\n%#v", test.expected.Spec.Template, obj.(*api.ReplicationController).Spec.Template)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										84
									
								
								pkg/kubectl/service.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										84
									
								
								pkg/kubectl/service.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,84 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					Copyright 2014 Google Inc. All rights reserved.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Licensed under the Apache License, Version 2.0 (the "License");
 | 
				
			||||||
 | 
					you may not use this file except in compliance with the License.
 | 
				
			||||||
 | 
					You may obtain a copy of the License at
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    http://www.apache.org/licenses/LICENSE-2.0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Unless required by applicable law or agreed to in writing, software
 | 
				
			||||||
 | 
					distributed under the License is distributed on an "AS IS" BASIS,
 | 
				
			||||||
 | 
					WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
				
			||||||
 | 
					See the License for the specific language governing permissions and
 | 
				
			||||||
 | 
					limitations under the License.
 | 
				
			||||||
 | 
					*/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					package kubectl
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"fmt"
 | 
				
			||||||
 | 
						"strconv"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
 | 
				
			||||||
 | 
						"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
 | 
				
			||||||
 | 
						"github.com/GoogleCloudPlatform/kubernetes/pkg/util"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type ServiceGenerator struct{}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (ServiceGenerator) ParamNames() []GeneratorParam {
 | 
				
			||||||
 | 
						return []GeneratorParam{
 | 
				
			||||||
 | 
							{"name", true},
 | 
				
			||||||
 | 
							{"selector", true},
 | 
				
			||||||
 | 
							{"port", true},
 | 
				
			||||||
 | 
							{"public-ip", false},
 | 
				
			||||||
 | 
							{"create-external-load-balancer", false},
 | 
				
			||||||
 | 
							{"protocol", false},
 | 
				
			||||||
 | 
							{"container-port", false},
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (ServiceGenerator) Generate(params map[string]string) (runtime.Object, error) {
 | 
				
			||||||
 | 
						selectorString, found := params["selector"]
 | 
				
			||||||
 | 
						if !found || len(selectorString) == 0 {
 | 
				
			||||||
 | 
							return nil, fmt.Errorf("'selector' is a required parameter.")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						selector := ParseLabels(selectorString)
 | 
				
			||||||
 | 
						name, found := params["name"]
 | 
				
			||||||
 | 
						if !found {
 | 
				
			||||||
 | 
							return nil, fmt.Errorf("'name' is a required parameter.")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						port, err := strconv.Atoi(params["port"])
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return nil, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						service := api.Service{
 | 
				
			||||||
 | 
							ObjectMeta: api.ObjectMeta{
 | 
				
			||||||
 | 
								Name: name,
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							Spec: api.ServiceSpec{
 | 
				
			||||||
 | 
								Port:     port,
 | 
				
			||||||
 | 
								Protocol: api.Protocol(params["protocol"]),
 | 
				
			||||||
 | 
								Selector: selector,
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						containerPort, found := params["container-port"]
 | 
				
			||||||
 | 
						if found && len(containerPort) > 0 {
 | 
				
			||||||
 | 
							cPort, err := strconv.Atoi(containerPort)
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								service.Spec.ContainerPort = util.NewIntOrStringFromInt(cPort)
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								service.Spec.ContainerPort = util.NewIntOrStringFromString(containerPort)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							service.Spec.ContainerPort = util.NewIntOrStringFromInt(port)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if params["create-external-load-balancer"] == "true" {
 | 
				
			||||||
 | 
							service.Spec.CreateExternalLoadBalancer = true
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if len(params["public-ip"]) == 0 {
 | 
				
			||||||
 | 
							service.Spec.PublicIPs = []string{params["public-ip"]}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return &service, nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
		Reference in New Issue
	
	Block a user