mirror of
				https://github.com/optim-enterprises-bv/kubernetes.git
				synced 2025-11-03 19:58:17 +00:00 
			
		
		
		
	Add 'kubectl set image'
This commit is contained in:
		@@ -53,6 +53,7 @@ docs/man/man1/kubectl-rollout-undo.1
 | 
				
			|||||||
docs/man/man1/kubectl-rollout.1
 | 
					docs/man/man1/kubectl-rollout.1
 | 
				
			||||||
docs/man/man1/kubectl-run.1
 | 
					docs/man/man1/kubectl-run.1
 | 
				
			||||||
docs/man/man1/kubectl-scale.1
 | 
					docs/man/man1/kubectl-scale.1
 | 
				
			||||||
 | 
					docs/man/man1/kubectl-set-image.1
 | 
				
			||||||
docs/man/man1/kubectl-set.1
 | 
					docs/man/man1/kubectl-set.1
 | 
				
			||||||
docs/man/man1/kubectl-stop.1
 | 
					docs/man/man1/kubectl-stop.1
 | 
				
			||||||
docs/man/man1/kubectl-taint.1
 | 
					docs/man/man1/kubectl-taint.1
 | 
				
			||||||
@@ -109,6 +110,7 @@ docs/user-guide/kubectl/kubectl_rollout_undo.md
 | 
				
			|||||||
docs/user-guide/kubectl/kubectl_run.md
 | 
					docs/user-guide/kubectl/kubectl_run.md
 | 
				
			||||||
docs/user-guide/kubectl/kubectl_scale.md
 | 
					docs/user-guide/kubectl/kubectl_scale.md
 | 
				
			||||||
docs/user-guide/kubectl/kubectl_set.md
 | 
					docs/user-guide/kubectl/kubectl_set.md
 | 
				
			||||||
 | 
					docs/user-guide/kubectl/kubectl_set_image.md
 | 
				
			||||||
docs/user-guide/kubectl/kubectl_taint.md
 | 
					docs/user-guide/kubectl/kubectl_taint.md
 | 
				
			||||||
docs/user-guide/kubectl/kubectl_uncordon.md
 | 
					docs/user-guide/kubectl/kubectl_uncordon.md
 | 
				
			||||||
docs/user-guide/kubectl/kubectl_version.md
 | 
					docs/user-guide/kubectl/kubectl_version.md
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -478,10 +478,78 @@ _kubectl_get()
 | 
				
			|||||||
    noun_aliases+=("thirdpartyresources")
 | 
					    noun_aliases+=("thirdpartyresources")
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					_kubectl_set_image()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    last_command="kubectl_set_image"
 | 
				
			||||||
 | 
					    commands=()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    flags=()
 | 
				
			||||||
 | 
					    two_word_flags=()
 | 
				
			||||||
 | 
					    flags_with_completion=()
 | 
				
			||||||
 | 
					    flags_completion=()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    flags+=("--all")
 | 
				
			||||||
 | 
					    flags+=("--filename=")
 | 
				
			||||||
 | 
					    flags_with_completion+=("--filename")
 | 
				
			||||||
 | 
					    flags_completion+=("__handle_filename_extension_flag json|yaml|yml")
 | 
				
			||||||
 | 
					    two_word_flags+=("-f")
 | 
				
			||||||
 | 
					    flags_with_completion+=("-f")
 | 
				
			||||||
 | 
					    flags_completion+=("__handle_filename_extension_flag json|yaml|yml")
 | 
				
			||||||
 | 
					    flags+=("--local")
 | 
				
			||||||
 | 
					    flags+=("--no-headers")
 | 
				
			||||||
 | 
					    flags+=("--output=")
 | 
				
			||||||
 | 
					    two_word_flags+=("-o")
 | 
				
			||||||
 | 
					    flags+=("--output-version=")
 | 
				
			||||||
 | 
					    flags+=("--record")
 | 
				
			||||||
 | 
					    flags+=("--recursive")
 | 
				
			||||||
 | 
					    flags+=("-R")
 | 
				
			||||||
 | 
					    flags+=("--selector=")
 | 
				
			||||||
 | 
					    two_word_flags+=("-l")
 | 
				
			||||||
 | 
					    flags+=("--show-all")
 | 
				
			||||||
 | 
					    flags+=("-a")
 | 
				
			||||||
 | 
					    flags+=("--show-labels")
 | 
				
			||||||
 | 
					    flags+=("--sort-by=")
 | 
				
			||||||
 | 
					    flags+=("--template=")
 | 
				
			||||||
 | 
					    flags_with_completion+=("--template")
 | 
				
			||||||
 | 
					    flags_completion+=("_filedir")
 | 
				
			||||||
 | 
					    flags+=("--alsologtostderr")
 | 
				
			||||||
 | 
					    flags+=("--api-version=")
 | 
				
			||||||
 | 
					    flags+=("--as=")
 | 
				
			||||||
 | 
					    flags+=("--certificate-authority=")
 | 
				
			||||||
 | 
					    flags+=("--client-certificate=")
 | 
				
			||||||
 | 
					    flags+=("--client-key=")
 | 
				
			||||||
 | 
					    flags+=("--cluster=")
 | 
				
			||||||
 | 
					    flags+=("--context=")
 | 
				
			||||||
 | 
					    flags+=("--insecure-skip-tls-verify")
 | 
				
			||||||
 | 
					    flags+=("--kubeconfig=")
 | 
				
			||||||
 | 
					    flags+=("--log-backtrace-at=")
 | 
				
			||||||
 | 
					    flags+=("--log-dir=")
 | 
				
			||||||
 | 
					    flags+=("--log-flush-frequency=")
 | 
				
			||||||
 | 
					    flags+=("--logtostderr")
 | 
				
			||||||
 | 
					    flags+=("--match-server-version")
 | 
				
			||||||
 | 
					    flags+=("--namespace=")
 | 
				
			||||||
 | 
					    flags_with_completion+=("--namespace")
 | 
				
			||||||
 | 
					    flags_completion+=("__kubectl_get_namespaces")
 | 
				
			||||||
 | 
					    flags+=("--password=")
 | 
				
			||||||
 | 
					    flags+=("--server=")
 | 
				
			||||||
 | 
					    two_word_flags+=("-s")
 | 
				
			||||||
 | 
					    flags+=("--stderrthreshold=")
 | 
				
			||||||
 | 
					    flags+=("--token=")
 | 
				
			||||||
 | 
					    flags+=("--user=")
 | 
				
			||||||
 | 
					    flags+=("--username=")
 | 
				
			||||||
 | 
					    flags+=("--v=")
 | 
				
			||||||
 | 
					    flags+=("--vmodule=")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    must_have_one_flag=()
 | 
				
			||||||
 | 
					    must_have_one_noun=()
 | 
				
			||||||
 | 
					    noun_aliases=()
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
_kubectl_set()
 | 
					_kubectl_set()
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    last_command="kubectl_set"
 | 
					    last_command="kubectl_set"
 | 
				
			||||||
    commands=()
 | 
					    commands=()
 | 
				
			||||||
 | 
					    commands+=("image")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    flags=()
 | 
					    flags=()
 | 
				
			||||||
    two_word_flags=()
 | 
					    two_word_flags=()
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -27,7 +27,7 @@ An autoscaler can automatically increase or decrease number of pods deployed wit
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
.PP
 | 
					.PP
 | 
				
			||||||
\fB\-\-dry\-run\fP=false
 | 
					\fB\-\-dry\-run\fP=false
 | 
				
			||||||
    If true, only print the object that would be sent, without creating it.
 | 
					    If true, only print the object that would be sent, without sending it.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.PP
 | 
					.PP
 | 
				
			||||||
\fB\-f\fP, \fB\-\-filename\fP=[]
 | 
					\fB\-f\fP, \fB\-\-filename\fP=[]
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -40,7 +40,7 @@ Possible resources include (case insensitive):
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
.PP
 | 
					.PP
 | 
				
			||||||
\fB\-\-dry\-run\fP=false
 | 
					\fB\-\-dry\-run\fP=false
 | 
				
			||||||
    If true, only print the object that would be sent, without creating it.
 | 
					    If true, only print the object that would be sent, without sending it.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.PP
 | 
					.PP
 | 
				
			||||||
\fB\-\-external\-ip\fP=""
 | 
					\fB\-\-external\-ip\fP=""
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -32,7 +32,7 @@ existing replication controller and overwrite at least one (common) label in its
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
.PP
 | 
					.PP
 | 
				
			||||||
\fB\-\-dry\-run\fP=false
 | 
					\fB\-\-dry\-run\fP=false
 | 
				
			||||||
    If true, print out the changes that would be made, but don't actually make them.
 | 
					    If true, only print the object that would be sent, without sending it.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.PP
 | 
					.PP
 | 
				
			||||||
\fB\-f\fP, \fB\-\-filename\fP=[]
 | 
					\fB\-f\fP, \fB\-\-filename\fP=[]
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										206
									
								
								docs/man/man1/kubectl-set-image.1
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										206
									
								
								docs/man/man1/kubectl-set-image.1
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,206 @@
 | 
				
			|||||||
 | 
					.TH "KUBERNETES" "1" " kubernetes User Manuals" "Eric Paris" "Jan 2015"  ""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.SH NAME
 | 
				
			||||||
 | 
					.PP
 | 
				
			||||||
 | 
					kubectl set image \- Update image of a pod template
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.SH SYNOPSIS
 | 
				
			||||||
 | 
					.PP
 | 
				
			||||||
 | 
					\fBkubectl set image\fP [OPTIONS]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.SH DESCRIPTION
 | 
				
			||||||
 | 
					.PP
 | 
				
			||||||
 | 
					Update existing container image(s) of resources.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.PP
 | 
				
			||||||
 | 
					Possible resources include (case insensitive):
 | 
				
			||||||
 | 
					  pod (po), replicationcontroller (rc), deployment, daemonset (ds), job, replicaset (rs)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.SH OPTIONS
 | 
				
			||||||
 | 
					.PP
 | 
				
			||||||
 | 
					\fB\-\-all\fP=false
 | 
				
			||||||
 | 
					    select all resources in the namespace of the specified resource types
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.PP
 | 
				
			||||||
 | 
					\fB\-f\fP, \fB\-\-filename\fP=[]
 | 
				
			||||||
 | 
					    Filename, directory, or URL to a file identifying the resource to get from a server.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.PP
 | 
				
			||||||
 | 
					\fB\-\-local\fP=false
 | 
				
			||||||
 | 
					    If true, set image will NOT contact api\-server but run locally.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.PP
 | 
				
			||||||
 | 
					\fB\-\-no\-headers\fP=false
 | 
				
			||||||
 | 
					    When using the default output, don't print headers.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.PP
 | 
				
			||||||
 | 
					\fB\-o\fP, \fB\-\-output\fP=""
 | 
				
			||||||
 | 
					    Output format. One of: json|yaml|wide|name|go\-template=...|go\-template\-file=...|jsonpath=...|jsonpath\-file=... See golang template [
 | 
				
			||||||
 | 
					\[la]http://golang.org/pkg/text/template/#pkg-overview\[ra]] and jsonpath template [
 | 
				
			||||||
 | 
					\[la]http://releases.k8s.io/HEAD/docs/user-guide/jsonpath.md\[ra]].
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.PP
 | 
				
			||||||
 | 
					\fB\-\-output\-version\fP=""
 | 
				
			||||||
 | 
					    Output the formatted object with the given group version (for ex: 'extensions/v1beta1').
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.PP
 | 
				
			||||||
 | 
					\fB\-\-record\fP=false
 | 
				
			||||||
 | 
					    Record current kubectl command in the resource annotation.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.PP
 | 
				
			||||||
 | 
					\fB\-R\fP, \fB\-\-recursive\fP=false
 | 
				
			||||||
 | 
					    If true, process directory recursively.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.PP
 | 
				
			||||||
 | 
					\fB\-l\fP, \fB\-\-selector\fP=""
 | 
				
			||||||
 | 
					    Selector (label query) to filter on
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.PP
 | 
				
			||||||
 | 
					\fB\-a\fP, \fB\-\-show\-all\fP=false
 | 
				
			||||||
 | 
					    When printing, show all resources (default hide terminated pods.)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.PP
 | 
				
			||||||
 | 
					\fB\-\-show\-labels\fP=false
 | 
				
			||||||
 | 
					    When printing, show all labels as the last column (default hide labels column)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.PP
 | 
				
			||||||
 | 
					\fB\-\-sort\-by\fP=""
 | 
				
			||||||
 | 
					    If non\-empty, sort list types using this field specification.  The field specification is expressed as a JSONPath expression (e.g. '{.metadata.name}'). The field in the API resource specified by this JSONPath expression must be an integer or a string.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.PP
 | 
				
			||||||
 | 
					\fB\-\-template\fP=""
 | 
				
			||||||
 | 
					    Template string or path to template file to use when \-o=go\-template, \-o=go\-template\-file. The template format is golang templates [
 | 
				
			||||||
 | 
					\[la]http://golang.org/pkg/text/template/#pkg-overview\[ra]].
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.SH OPTIONS INHERITED FROM PARENT COMMANDS
 | 
				
			||||||
 | 
					.PP
 | 
				
			||||||
 | 
					\fB\-\-alsologtostderr\fP=false
 | 
				
			||||||
 | 
					    log to standard error as well as files
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.PP
 | 
				
			||||||
 | 
					\fB\-\-api\-version\fP=""
 | 
				
			||||||
 | 
					    DEPRECATED: The API version to use when talking to the server
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.PP
 | 
				
			||||||
 | 
					\fB\-\-as\fP=""
 | 
				
			||||||
 | 
					    Username to impersonate for the operation.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.PP
 | 
				
			||||||
 | 
					\fB\-\-certificate\-authority\fP=""
 | 
				
			||||||
 | 
					    Path to a cert. file for the certificate authority.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.PP
 | 
				
			||||||
 | 
					\fB\-\-client\-certificate\fP=""
 | 
				
			||||||
 | 
					    Path to a client certificate file for TLS.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.PP
 | 
				
			||||||
 | 
					\fB\-\-client\-key\fP=""
 | 
				
			||||||
 | 
					    Path to a client key file for TLS.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.PP
 | 
				
			||||||
 | 
					\fB\-\-cluster\fP=""
 | 
				
			||||||
 | 
					    The name of the kubeconfig cluster to use
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.PP
 | 
				
			||||||
 | 
					\fB\-\-context\fP=""
 | 
				
			||||||
 | 
					    The name of the kubeconfig context to use
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.PP
 | 
				
			||||||
 | 
					\fB\-\-insecure\-skip\-tls\-verify\fP=false
 | 
				
			||||||
 | 
					    If true, the server's certificate will not be checked for validity. This will make your HTTPS connections insecure.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.PP
 | 
				
			||||||
 | 
					\fB\-\-kubeconfig\fP=""
 | 
				
			||||||
 | 
					    Path to the kubeconfig file to use for CLI requests.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.PP
 | 
				
			||||||
 | 
					\fB\-\-log\-backtrace\-at\fP=:0
 | 
				
			||||||
 | 
					    when logging hits line file:N, emit a stack trace
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.PP
 | 
				
			||||||
 | 
					\fB\-\-log\-dir\fP=""
 | 
				
			||||||
 | 
					    If non\-empty, write log files in this directory
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.PP
 | 
				
			||||||
 | 
					\fB\-\-log\-flush\-frequency\fP=5s
 | 
				
			||||||
 | 
					    Maximum number of seconds between log flushes
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.PP
 | 
				
			||||||
 | 
					\fB\-\-logtostderr\fP=true
 | 
				
			||||||
 | 
					    log to standard error instead of files
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.PP
 | 
				
			||||||
 | 
					\fB\-\-match\-server\-version\fP=false
 | 
				
			||||||
 | 
					    Require server version to match client version
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.PP
 | 
				
			||||||
 | 
					\fB\-\-namespace\fP=""
 | 
				
			||||||
 | 
					    If present, the namespace scope for this CLI request.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.PP
 | 
				
			||||||
 | 
					\fB\-\-password\fP=""
 | 
				
			||||||
 | 
					    Password for basic authentication to the API server.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.PP
 | 
				
			||||||
 | 
					\fB\-s\fP, \fB\-\-server\fP=""
 | 
				
			||||||
 | 
					    The address and port of the Kubernetes API server
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.PP
 | 
				
			||||||
 | 
					\fB\-\-stderrthreshold\fP=2
 | 
				
			||||||
 | 
					    logs at or above this threshold go to stderr
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.PP
 | 
				
			||||||
 | 
					\fB\-\-token\fP=""
 | 
				
			||||||
 | 
					    Bearer token for authentication to the API server.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.PP
 | 
				
			||||||
 | 
					\fB\-\-user\fP=""
 | 
				
			||||||
 | 
					    The name of the kubeconfig user to use
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.PP
 | 
				
			||||||
 | 
					\fB\-\-username\fP=""
 | 
				
			||||||
 | 
					    Username for basic authentication to the API server.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.PP
 | 
				
			||||||
 | 
					\fB\-\-v\fP=0
 | 
				
			||||||
 | 
					    log level for V logs
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.PP
 | 
				
			||||||
 | 
					\fB\-\-vmodule\fP=
 | 
				
			||||||
 | 
					    comma\-separated list of pattern=N settings for file\-filtered logging
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.SH EXAMPLE
 | 
				
			||||||
 | 
					.PP
 | 
				
			||||||
 | 
					.RS
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.nf
 | 
				
			||||||
 | 
					# Set a deployment's nginx container image to 'nginx:1.9.1', and its busybox container image to 'busybox'.
 | 
				
			||||||
 | 
					kubectl set image deployment/nginx busybox=busybox nginx=nginx:1.9.1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Update all deployments' and rc's nginx container's image to 'nginx:1.9.1'
 | 
				
			||||||
 | 
					kubectl set image deployments,rc nginx=nginx:1.9.1 \-\-all
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Update image of all containers of daemonset abc to 'nginx:1.9.1'
 | 
				
			||||||
 | 
					kubectl set image daemonset abc *=nginx:1.9.1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Print result (in yaml format) of updating nginx container image from local file, without hitting the server 
 | 
				
			||||||
 | 
					kubectl set image \-f path/to/file.yaml nginx=nginx:1.9.1 \-\-local \-o yaml
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.fi
 | 
				
			||||||
 | 
					.RE
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.SH SEE ALSO
 | 
				
			||||||
 | 
					.PP
 | 
				
			||||||
 | 
					\fBkubectl\-set(1)\fP,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.SH HISTORY
 | 
				
			||||||
 | 
					.PP
 | 
				
			||||||
 | 
					January 2015, Originally compiled by Eric Paris (eparis at redhat dot com) based on the kubernetes source material, but hopefully they have been automatically generated since!
 | 
				
			||||||
@@ -119,7 +119,7 @@ These commands help you make changes to existing application resources.
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
.SH SEE ALSO
 | 
					.SH SEE ALSO
 | 
				
			||||||
.PP
 | 
					.PP
 | 
				
			||||||
\fBkubectl(1)\fP,
 | 
					\fBkubectl(1)\fP, \fBkubectl\-set\-image(1)\fP,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.SH HISTORY
 | 
					.SH HISTORY
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -62,7 +62,7 @@ kubectl autoscale rc foo --max=5 --cpu-percent=80
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
      --cpu-percent=-1: The target average CPU utilization (represented as a percent of requested CPU) over all the pods. If it's not specified or negative, the server will apply a default value.
 | 
					      --cpu-percent=-1: The target average CPU utilization (represented as a percent of requested CPU) over all the pods. If it's not specified or negative, the server will apply a default value.
 | 
				
			||||||
      --dry-run[=false]: If true, only print the object that would be sent, without creating it.
 | 
					      --dry-run[=false]: If true, only print the object that would be sent, without sending it.
 | 
				
			||||||
  -f, --filename=[]: Filename, directory, or URL to a file identifying the resource to autoscale.
 | 
					  -f, --filename=[]: Filename, directory, or URL to a file identifying the resource to autoscale.
 | 
				
			||||||
      --generator="horizontalpodautoscaler/v1beta1": The name of the API generator to use. Currently there is only 1 generator.
 | 
					      --generator="horizontalpodautoscaler/v1beta1": The name of the API generator to use. Currently there is only 1 generator.
 | 
				
			||||||
      --include-extended-apis[=true]: If true, include definitions of new APIs via calls to the API server. [default true]
 | 
					      --include-extended-apis[=true]: If true, include definitions of new APIs via calls to the API server. [default true]
 | 
				
			||||||
@@ -113,7 +113,7 @@ kubectl autoscale rc foo --max=5 --cpu-percent=80
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
* [kubectl](kubectl.md)	 - kubectl controls the Kubernetes cluster manager
 | 
					* [kubectl](kubectl.md)	 - kubectl controls the Kubernetes cluster manager
 | 
				
			||||||
 | 
					
 | 
				
			||||||
###### Auto generated by spf13/cobra on 30-Mar-2016
 | 
					###### Auto generated by spf13/cobra on 13-May-2016
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<!-- BEGIN MUNGE: GENERATED_ANALYTICS -->
 | 
					<!-- BEGIN MUNGE: GENERATED_ANALYTICS -->
 | 
				
			||||||
[]()
 | 
					[]()
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -85,7 +85,7 @@ kubectl expose deployment nginx --port=80 --target-port=8000
 | 
				
			|||||||
### Options
 | 
					### Options
 | 
				
			||||||
 | 
					
 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
      --dry-run[=false]: If true, only print the object that would be sent, without creating it.
 | 
					      --dry-run[=false]: If true, only print the object that would be sent, without sending it.
 | 
				
			||||||
      --external-ip="": 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.
 | 
					      --external-ip="": 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.
 | 
				
			||||||
  -f, --filename=[]: Filename, directory, or URL to a file identifying the resource to expose a service
 | 
					  -f, --filename=[]: Filename, directory, or URL to a file identifying the resource to expose a service
 | 
				
			||||||
      --generator="service/v2": The name of the API generator to use. There are 2 generators: 'service/v1' and 'service/v2'. The only difference between them is that service port in v1 is named 'default', while it is left unnamed in v2. Default is 'service/v2'.
 | 
					      --generator="service/v2": The name of the API generator to use. There are 2 generators: 'service/v1' and 'service/v2'. The only difference between them is that service port in v1 is named 'default', while it is left unnamed in v2. Default is 'service/v2'.
 | 
				
			||||||
@@ -143,7 +143,7 @@ kubectl expose deployment nginx --port=80 --target-port=8000
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
* [kubectl](kubectl.md)	 - kubectl controls the Kubernetes cluster manager
 | 
					* [kubectl](kubectl.md)	 - kubectl controls the Kubernetes cluster manager
 | 
				
			||||||
 | 
					
 | 
				
			||||||
###### Auto generated by spf13/cobra on 11-May-2016
 | 
					###### Auto generated by spf13/cobra on 13-May-2016
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<!-- BEGIN MUNGE: GENERATED_ANALYTICS -->
 | 
					<!-- BEGIN MUNGE: GENERATED_ANALYTICS -->
 | 
				
			||||||
[]()
 | 
					[]()
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -75,7 +75,7 @@ kubectl rolling-update frontend-v1 frontend-v2 --rollback
 | 
				
			|||||||
```
 | 
					```
 | 
				
			||||||
      --container="": Container name which will have its image upgraded. Only relevant when --image is specified, ignored otherwise. Required when using --image on a multi-container pod
 | 
					      --container="": Container name which will have its image upgraded. Only relevant when --image is specified, ignored otherwise. Required when using --image on a multi-container pod
 | 
				
			||||||
      --deployment-label-key="deployment": The key to use to differentiate between two different controllers, default 'deployment'.  Only relevant when --image is specified, ignored otherwise
 | 
					      --deployment-label-key="deployment": The key to use to differentiate between two different controllers, default 'deployment'.  Only relevant when --image is specified, ignored otherwise
 | 
				
			||||||
      --dry-run[=false]: If true, print out the changes that would be made, but don't actually make them.
 | 
					      --dry-run[=false]: If true, only print the object that would be sent, without sending it.
 | 
				
			||||||
  -f, --filename=[]: Filename or URL to file to use to create the new replication controller.
 | 
					  -f, --filename=[]: Filename or URL to file to use to create the new replication controller.
 | 
				
			||||||
      --image="": Image to use for upgrading the replication controller. Must be distinct from the existing image (either new image or new image tag).  Can not be used with --filename/-f
 | 
					      --image="": Image to use for upgrading the replication controller. Must be distinct from the existing image (either new image or new image tag).  Can not be used with --filename/-f
 | 
				
			||||||
      --image-pull-policy="": Explicit policy for when to pull container images. Required when --image is same as existing image, ignored otherwise.
 | 
					      --image-pull-policy="": Explicit policy for when to pull container images. Required when --image is same as existing image, ignored otherwise.
 | 
				
			||||||
@@ -127,7 +127,7 @@ kubectl rolling-update frontend-v1 frontend-v2 --rollback
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
* [kubectl](kubectl.md)	 - kubectl controls the Kubernetes cluster manager
 | 
					* [kubectl](kubectl.md)	 - kubectl controls the Kubernetes cluster manager
 | 
				
			||||||
 | 
					
 | 
				
			||||||
###### Auto generated by spf13/cobra on 21-Apr-2016
 | 
					###### Auto generated by spf13/cobra on 13-May-2016
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<!-- BEGIN MUNGE: GENERATED_ANALYTICS -->
 | 
					<!-- BEGIN MUNGE: GENERATED_ANALYTICS -->
 | 
				
			||||||
[]()
 | 
					[]()
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -73,6 +73,7 @@ kubectl set SUBCOMMAND
 | 
				
			|||||||
### SEE ALSO
 | 
					### SEE ALSO
 | 
				
			||||||
 | 
					
 | 
				
			||||||
* [kubectl](kubectl.md)	 - kubectl controls the Kubernetes cluster manager
 | 
					* [kubectl](kubectl.md)	 - kubectl controls the Kubernetes cluster manager
 | 
				
			||||||
 | 
					* [kubectl set image](kubectl_set_image.md)	 - Update image of a pod template
 | 
				
			||||||
 | 
					
 | 
				
			||||||
###### Auto generated by spf13/cobra on 10-May-2016
 | 
					###### Auto generated by spf13/cobra on 10-May-2016
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										116
									
								
								docs/user-guide/kubectl/kubectl_set_image.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										116
									
								
								docs/user-guide/kubectl/kubectl_set_image.md
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,116 @@
 | 
				
			|||||||
 | 
					<!-- BEGIN MUNGE: UNVERSIONED_WARNING -->
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<!-- BEGIN STRIP_FOR_RELEASE -->
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<img src="http://kubernetes.io/img/warning.png" alt="WARNING"
 | 
				
			||||||
 | 
					     width="25" height="25">
 | 
				
			||||||
 | 
					<img src="http://kubernetes.io/img/warning.png" alt="WARNING"
 | 
				
			||||||
 | 
					     width="25" height="25">
 | 
				
			||||||
 | 
					<img src="http://kubernetes.io/img/warning.png" alt="WARNING"
 | 
				
			||||||
 | 
					     width="25" height="25">
 | 
				
			||||||
 | 
					<img src="http://kubernetes.io/img/warning.png" alt="WARNING"
 | 
				
			||||||
 | 
					     width="25" height="25">
 | 
				
			||||||
 | 
					<img src="http://kubernetes.io/img/warning.png" alt="WARNING"
 | 
				
			||||||
 | 
					     width="25" height="25">
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<h2>PLEASE NOTE: This document applies to the HEAD of the source tree</h2>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					If you are using a released version of Kubernetes, you should
 | 
				
			||||||
 | 
					refer to the docs that go with that version.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Documentation for other releases can be found at
 | 
				
			||||||
 | 
					[releases.k8s.io](http://releases.k8s.io).
 | 
				
			||||||
 | 
					</strong>
 | 
				
			||||||
 | 
					--
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<!-- END STRIP_FOR_RELEASE -->
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<!-- END MUNGE: UNVERSIONED_WARNING -->
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## kubectl set image
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Update image of a pod template
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### Synopsis
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Update existing container image(s) of resources.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Possible resources include (case insensitive):
 | 
				
			||||||
 | 
					  pod (po), replicationcontroller (rc), deployment, daemonset (ds), job, replicaset (rs)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					kubectl set image (-f FILENAME | TYPE NAME) CONTAINER_NAME_1=CONTAINER_IMAGE_1 ... CONTAINER_NAME_N=CONTAINER_IMAGE_N
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### Examples
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					# Set a deployment's nginx container image to 'nginx:1.9.1', and its busybox container image to 'busybox'.
 | 
				
			||||||
 | 
					kubectl set image deployment/nginx busybox=busybox nginx=nginx:1.9.1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Update all deployments' and rc's nginx container's image to 'nginx:1.9.1'
 | 
				
			||||||
 | 
					kubectl set image deployments,rc nginx=nginx:1.9.1 --all
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Update image of all containers of daemonset abc to 'nginx:1.9.1'
 | 
				
			||||||
 | 
					kubectl set image daemonset abc *=nginx:1.9.1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Print result (in yaml format) of updating nginx container image from local file, without hitting the server 
 | 
				
			||||||
 | 
					kubectl set image -f path/to/file.yaml nginx=nginx:1.9.1 --local -o yaml
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### Options
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					      --all[=false]: select all resources in the namespace of the specified resource types
 | 
				
			||||||
 | 
					  -f, --filename=[]: Filename, directory, or URL to a file identifying the resource to get from a server.
 | 
				
			||||||
 | 
					      --local[=false]: If true, set image will NOT contact api-server but run locally.
 | 
				
			||||||
 | 
					      --no-headers[=false]: When using the default output, don't print headers.
 | 
				
			||||||
 | 
					  -o, --output="": Output format. One of: json|yaml|wide|name|go-template=...|go-template-file=...|jsonpath=...|jsonpath-file=... See golang template [http://golang.org/pkg/text/template/#pkg-overview] and jsonpath template [http://releases.k8s.io/HEAD/docs/user-guide/jsonpath.md].
 | 
				
			||||||
 | 
					      --output-version="": Output the formatted object with the given group version (for ex: 'extensions/v1beta1').
 | 
				
			||||||
 | 
					      --record[=false]: Record current kubectl command in the resource annotation.
 | 
				
			||||||
 | 
					  -R, --recursive[=false]: If true, process directory recursively.
 | 
				
			||||||
 | 
					  -l, --selector="": Selector (label query) to filter on
 | 
				
			||||||
 | 
					  -a, --show-all[=false]: When printing, show all resources (default hide terminated pods.)
 | 
				
			||||||
 | 
					      --show-labels[=false]: When printing, show all labels as the last column (default hide labels column)
 | 
				
			||||||
 | 
					      --sort-by="": If non-empty, sort list types using this field specification.  The field specification is expressed as a JSONPath expression (e.g. '{.metadata.name}'). The field in the API resource specified by this JSONPath expression must be an integer or a string.
 | 
				
			||||||
 | 
					      --template="": Template string or path to template file to use when -o=go-template, -o=go-template-file. The template format is golang templates [http://golang.org/pkg/text/template/#pkg-overview].
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### Options inherited from parent commands
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					      --alsologtostderr[=false]: log to standard error as well as files
 | 
				
			||||||
 | 
					      --as="": Username to impersonate for the operation.
 | 
				
			||||||
 | 
					      --certificate-authority="": Path to a cert. file for the certificate authority.
 | 
				
			||||||
 | 
					      --client-certificate="": Path to a client certificate file for TLS.
 | 
				
			||||||
 | 
					      --client-key="": Path to a client key file for TLS.
 | 
				
			||||||
 | 
					      --cluster="": The name of the kubeconfig cluster to use
 | 
				
			||||||
 | 
					      --context="": The name of the kubeconfig context to use
 | 
				
			||||||
 | 
					      --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.
 | 
				
			||||||
 | 
					      --password="": Password for basic authentication to the API server.
 | 
				
			||||||
 | 
					  -s, --server="": The address and port of the Kubernetes API server
 | 
				
			||||||
 | 
					      --stderrthreshold=2: logs at or above this threshold go to stderr
 | 
				
			||||||
 | 
					      --token="": Bearer token for authentication to the API server.
 | 
				
			||||||
 | 
					      --user="": The name of the kubeconfig user to use
 | 
				
			||||||
 | 
					      --username="": Username for basic authentication to the API server.
 | 
				
			||||||
 | 
					      --v=0: log level for V logs
 | 
				
			||||||
 | 
					      --vmodule=: comma-separated list of pattern=N settings for file-filtered logging
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### SEE ALSO
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					* [kubectl set](kubectl_set.md)	 - Set specific features on objects
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					###### Auto generated by spf13/cobra on 17-May-2016
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<!-- BEGIN MUNGE: GENERATED_ANALYTICS -->
 | 
				
			||||||
 | 
					[]()
 | 
				
			||||||
 | 
					<!-- END MUNGE: GENERATED_ANALYTICS -->
 | 
				
			||||||
@@ -14,7 +14,7 @@ options:
 | 
				
			|||||||
- name: dry-run
 | 
					- name: dry-run
 | 
				
			||||||
  default_value: "false"
 | 
					  default_value: "false"
 | 
				
			||||||
  usage: |
 | 
					  usage: |
 | 
				
			||||||
    If true, only print the object that would be sent, without creating it.
 | 
					    If true, only print the object that would be sent, without sending it.
 | 
				
			||||||
- name: filename
 | 
					- name: filename
 | 
				
			||||||
  shorthand: f
 | 
					  shorthand: f
 | 
				
			||||||
  default_value: '[]'
 | 
					  default_value: '[]'
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -21,7 +21,7 @@ options:
 | 
				
			|||||||
- name: dry-run
 | 
					- name: dry-run
 | 
				
			||||||
  default_value: "false"
 | 
					  default_value: "false"
 | 
				
			||||||
  usage: |
 | 
					  usage: |
 | 
				
			||||||
    If true, only print the object that would be sent, without creating it.
 | 
					    If true, only print the object that would be sent, without sending it.
 | 
				
			||||||
- name: external-ip
 | 
					- name: external-ip
 | 
				
			||||||
  usage: |
 | 
					  usage: |
 | 
				
			||||||
    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.
 | 
					    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.
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -17,7 +17,7 @@ options:
 | 
				
			|||||||
- name: dry-run
 | 
					- name: dry-run
 | 
				
			||||||
  default_value: "false"
 | 
					  default_value: "false"
 | 
				
			||||||
  usage: |
 | 
					  usage: |
 | 
				
			||||||
    If true, print out the changes that would be made, but don't actually make them.
 | 
					    If true, only print the object that would be sent, without sending it.
 | 
				
			||||||
- name: filename
 | 
					- name: filename
 | 
				
			||||||
  shorthand: f
 | 
					  shorthand: f
 | 
				
			||||||
  default_value: '[]'
 | 
					  default_value: '[]'
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -65,3 +65,4 @@ inherited_options:
 | 
				
			|||||||
    comma-separated list of pattern=N settings for file-filtered logging
 | 
					    comma-separated list of pattern=N settings for file-filtered logging
 | 
				
			||||||
see_also:
 | 
					see_also:
 | 
				
			||||||
- kubectl
 | 
					- kubectl
 | 
				
			||||||
 | 
					- image
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -291,6 +291,7 @@ runTests() {
 | 
				
			|||||||
  secret_data=".data"
 | 
					  secret_data=".data"
 | 
				
			||||||
  secret_type=".type"
 | 
					  secret_type=".type"
 | 
				
			||||||
  deployment_image_field="(index .spec.template.spec.containers 0).image"
 | 
					  deployment_image_field="(index .spec.template.spec.containers 0).image"
 | 
				
			||||||
 | 
					  deployment_second_image_field="(index .spec.template.spec.containers 1).image"
 | 
				
			||||||
  change_cause_annotation='.*kubernetes.io/change-cause.*'
 | 
					  change_cause_annotation='.*kubernetes.io/change-cause.*'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  # Passing no arguments to create is an error
 | 
					  # Passing no arguments to create is an error
 | 
				
			||||||
@@ -1620,6 +1621,11 @@ __EOF__
 | 
				
			|||||||
  # Clean up
 | 
					  # Clean up
 | 
				
			||||||
  kubectl delete rc frontend "${kube_flags[@]}"
 | 
					  kubectl delete rc frontend "${kube_flags[@]}"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  ######################
 | 
				
			||||||
 | 
					  # Deployments       #
 | 
				
			||||||
 | 
					  ######################
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  ### Auto scale deployment
 | 
					  ### Auto scale deployment
 | 
				
			||||||
  # Pre-condition: no deployment exists
 | 
					  # Pre-condition: no deployment exists
 | 
				
			||||||
  kube::test::get_object_assert deployment "{{range.items}}{{$id_field}}:{{end}}" ''
 | 
					  kube::test::get_object_assert deployment "{{range.items}}{{$id_field}}:{{end}}" ''
 | 
				
			||||||
@@ -1670,6 +1676,39 @@ __EOF__
 | 
				
			|||||||
  # Clean up
 | 
					  # Clean up
 | 
				
			||||||
  kubectl delete deployment nginx-deployment "${kube_flags[@]}"
 | 
					  kubectl delete deployment nginx-deployment "${kube_flags[@]}"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  ### Set image of a deployment 
 | 
				
			||||||
 | 
					  # Pre-condition: no deployment exists
 | 
				
			||||||
 | 
					  kube::test::get_object_assert deployment "{{range.items}}{{$id_field}}:{{end}}" ''
 | 
				
			||||||
 | 
					  # Create a deployment
 | 
				
			||||||
 | 
					  kubectl create -f hack/testdata/deployment-multicontainer.yaml "${kube_flags[@]}"
 | 
				
			||||||
 | 
					  kube::test::get_object_assert deployment "{{range.items}}{{$id_field}}:{{end}}" 'nginx-deployment:'
 | 
				
			||||||
 | 
					  kube::test::get_object_assert deployment "{{range.items}}{{$deployment_image_field}}:{{end}}" "${IMAGE_DEPLOYMENT_R1}:"
 | 
				
			||||||
 | 
					  kube::test::get_object_assert deployment "{{range.items}}{{$deployment_second_image_field}}:{{end}}" "${IMAGE_PERL}:"
 | 
				
			||||||
 | 
					  # Set the deployment's image 
 | 
				
			||||||
 | 
					  kubectl set image deployment nginx-deployment nginx="${IMAGE_DEPLOYMENT_R2}" "${kube_flags[@]}"
 | 
				
			||||||
 | 
					  kube::test::get_object_assert deployment "{{range.items}}{{$deployment_image_field}}:{{end}}" "${IMAGE_DEPLOYMENT_R2}:"
 | 
				
			||||||
 | 
					  kube::test::get_object_assert deployment "{{range.items}}{{$deployment_second_image_field}}:{{end}}" "${IMAGE_PERL}:"
 | 
				
			||||||
 | 
					  # Set non-existing container should fail 
 | 
				
			||||||
 | 
					  ! kubectl set image deployment nginx-deployment redis=redis "${kube_flags[@]}"
 | 
				
			||||||
 | 
					  # Set image of deployments without specifying name 
 | 
				
			||||||
 | 
					  kubectl set image deployments --all nginx="${IMAGE_DEPLOYMENT_R1}" "${kube_flags[@]}"
 | 
				
			||||||
 | 
					  kube::test::get_object_assert deployment "{{range.items}}{{$deployment_image_field}}:{{end}}" "${IMAGE_DEPLOYMENT_R1}:"
 | 
				
			||||||
 | 
					  kube::test::get_object_assert deployment "{{range.items}}{{$deployment_second_image_field}}:{{end}}" "${IMAGE_PERL}:"
 | 
				
			||||||
 | 
					  # Set image of a deployment specified by file
 | 
				
			||||||
 | 
					  kubectl set image -f hack/testdata/deployment-multicontainer.yaml nginx="${IMAGE_DEPLOYMENT_R2}" "${kube_flags[@]}"
 | 
				
			||||||
 | 
					  kube::test::get_object_assert deployment "{{range.items}}{{$deployment_image_field}}:{{end}}" "${IMAGE_DEPLOYMENT_R2}:"
 | 
				
			||||||
 | 
					  kube::test::get_object_assert deployment "{{range.items}}{{$deployment_second_image_field}}:{{end}}" "${IMAGE_PERL}:"
 | 
				
			||||||
 | 
					  # Set image of a local file without talking to the server 
 | 
				
			||||||
 | 
					  kubectl set image -f hack/testdata/deployment-multicontainer.yaml nginx="${IMAGE_DEPLOYMENT_R1}" "${kube_flags[@]}" --local -o yaml
 | 
				
			||||||
 | 
					  kube::test::get_object_assert deployment "{{range.items}}{{$deployment_image_field}}:{{end}}" "${IMAGE_DEPLOYMENT_R2}:"
 | 
				
			||||||
 | 
					  kube::test::get_object_assert deployment "{{range.items}}{{$deployment_second_image_field}}:{{end}}" "${IMAGE_PERL}:"
 | 
				
			||||||
 | 
					  # Set image of all containers of the deployment 
 | 
				
			||||||
 | 
					  kubectl set image deployment nginx-deployment "*"="${IMAGE_DEPLOYMENT_R1}" "${kube_flags[@]}"
 | 
				
			||||||
 | 
					  kube::test::get_object_assert deployment "{{range.items}}{{$deployment_image_field}}:{{end}}" "${IMAGE_DEPLOYMENT_R1}:"
 | 
				
			||||||
 | 
					  kube::test::get_object_assert deployment "{{range.items}}{{$deployment_second_image_field}}:{{end}}" "${IMAGE_DEPLOYMENT_R1}:"
 | 
				
			||||||
 | 
					  # Clean up
 | 
				
			||||||
 | 
					  kubectl delete deployment nginx-deployment "${kube_flags[@]}"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  ######################
 | 
					  ######################
 | 
				
			||||||
  # Replica Sets       #
 | 
					  # Replica Sets       #
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										23
									
								
								hack/testdata/deployment-multicontainer.yaml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								hack/testdata/deployment-multicontainer.yaml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,23 @@
 | 
				
			|||||||
 | 
					apiVersion: extensions/v1beta1
 | 
				
			||||||
 | 
					kind: Deployment
 | 
				
			||||||
 | 
					metadata:
 | 
				
			||||||
 | 
					  name: nginx-deployment
 | 
				
			||||||
 | 
					  labels:
 | 
				
			||||||
 | 
					    name: nginx-deployment
 | 
				
			||||||
 | 
					spec:
 | 
				
			||||||
 | 
					  replicas: 3
 | 
				
			||||||
 | 
					  selector:
 | 
				
			||||||
 | 
					    matchLabels:
 | 
				
			||||||
 | 
					      name: nginx
 | 
				
			||||||
 | 
					  template:
 | 
				
			||||||
 | 
					    metadata:
 | 
				
			||||||
 | 
					      labels:
 | 
				
			||||||
 | 
					        name: nginx
 | 
				
			||||||
 | 
					    spec:
 | 
				
			||||||
 | 
					      containers:
 | 
				
			||||||
 | 
					      - name: nginx
 | 
				
			||||||
 | 
					        image: gcr.io/google-containers/nginx:test-cmd
 | 
				
			||||||
 | 
					        ports:
 | 
				
			||||||
 | 
					        - containerPort: 80
 | 
				
			||||||
 | 
					      - name: perl
 | 
				
			||||||
 | 
					        image: gcr.io/google-containers/perl
 | 
				
			||||||
@@ -148,22 +148,11 @@ func (o *AnnotateOptions) Complete(f *cmdutil.Factory, out io.Writer, cmd *cobra
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	// retrieves resource and annotation args from args
 | 
						// retrieves resource and annotation args from args
 | 
				
			||||||
	// also checks args to verify that all resources are specified before annotations
 | 
						// also checks args to verify that all resources are specified before annotations
 | 
				
			||||||
	annotationArgs := []string{}
 | 
						resources, annotationArgs, err := cmdutil.GetResourcesAndPairs(args, "annotation")
 | 
				
			||||||
	metAnnotaionArg := false
 | 
						if err != nil {
 | 
				
			||||||
	for _, s := range args {
 | 
							return err
 | 
				
			||||||
		isAnnotation := strings.Contains(s, "=") || strings.HasSuffix(s, "-")
 | 
					 | 
				
			||||||
		switch {
 | 
					 | 
				
			||||||
		case !metAnnotaionArg && isAnnotation:
 | 
					 | 
				
			||||||
			metAnnotaionArg = true
 | 
					 | 
				
			||||||
			fallthrough
 | 
					 | 
				
			||||||
		case metAnnotaionArg && isAnnotation:
 | 
					 | 
				
			||||||
			annotationArgs = append(annotationArgs, s)
 | 
					 | 
				
			||||||
		case !metAnnotaionArg && !isAnnotation:
 | 
					 | 
				
			||||||
			o.resources = append(o.resources, s)
 | 
					 | 
				
			||||||
		case metAnnotaionArg && !isAnnotation:
 | 
					 | 
				
			||||||
			return fmt.Errorf("all resources must be specified before annotation changes: %s", s)
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
						o.resources = resources
 | 
				
			||||||
	if len(o.resources) < 1 && len(o.filenames) == 0 {
 | 
						if len(o.resources) < 1 && len(o.filenames) == 0 {
 | 
				
			||||||
		return fmt.Errorf("one or more resources must be specified as <resource> <name> or <resource>/<name>")
 | 
							return fmt.Errorf("one or more resources must be specified as <resource> <name> or <resource>/<name>")
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
@@ -277,34 +266,7 @@ func (o AnnotateOptions) RunAnnotate() error {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
// parseAnnotations retrieves new and remove annotations from annotation args
 | 
					// parseAnnotations retrieves new and remove annotations from annotation args
 | 
				
			||||||
func parseAnnotations(annotationArgs []string) (map[string]string, []string, error) {
 | 
					func parseAnnotations(annotationArgs []string) (map[string]string, []string, error) {
 | 
				
			||||||
	var invalidBuf bytes.Buffer
 | 
						return cmdutil.ParsePairs(annotationArgs, "annotation", true)
 | 
				
			||||||
	newAnnotations := map[string]string{}
 | 
					 | 
				
			||||||
	removeAnnotations := []string{}
 | 
					 | 
				
			||||||
	for _, annotationArg := range annotationArgs {
 | 
					 | 
				
			||||||
		if strings.Index(annotationArg, "=") != -1 {
 | 
					 | 
				
			||||||
			parts := strings.SplitN(annotationArg, "=", 2)
 | 
					 | 
				
			||||||
			if len(parts) != 2 || len(parts[1]) == 0 {
 | 
					 | 
				
			||||||
				if invalidBuf.Len() > 0 {
 | 
					 | 
				
			||||||
					invalidBuf.WriteString(", ")
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
				invalidBuf.WriteString(fmt.Sprintf(annotationArg))
 | 
					 | 
				
			||||||
			} else {
 | 
					 | 
				
			||||||
				newAnnotations[parts[0]] = parts[1]
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		} else if strings.HasSuffix(annotationArg, "-") {
 | 
					 | 
				
			||||||
			removeAnnotations = append(removeAnnotations, annotationArg[:len(annotationArg)-1])
 | 
					 | 
				
			||||||
		} else {
 | 
					 | 
				
			||||||
			if invalidBuf.Len() > 0 {
 | 
					 | 
				
			||||||
				invalidBuf.WriteString(", ")
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			invalidBuf.WriteString(fmt.Sprintf(annotationArg))
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if invalidBuf.Len() > 0 {
 | 
					 | 
				
			||||||
		return newAnnotations, removeAnnotations, fmt.Errorf("invalid annotation format: %s", invalidBuf.String())
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return newAnnotations, removeAnnotations, nil
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// validateAnnotations checks the format of annotation args and checks removed annotations aren't in the new annotations map
 | 
					// validateAnnotations checks the format of annotation args and checks removed annotations aren't in the new annotations map
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -68,7 +68,7 @@ func NewCmdAutoscale(f *cmdutil.Factory, out io.Writer) *cobra.Command {
 | 
				
			|||||||
	cmd.MarkFlagRequired("max")
 | 
						cmd.MarkFlagRequired("max")
 | 
				
			||||||
	cmd.Flags().Int("cpu-percent", -1, fmt.Sprintf("The target average CPU utilization (represented as a percent of requested CPU) over all the pods. If it's not specified or negative, the server will apply a default value."))
 | 
						cmd.Flags().Int("cpu-percent", -1, fmt.Sprintf("The target average CPU utilization (represented as a percent of requested CPU) over all the pods. If it's not specified or negative, the server will apply a default value."))
 | 
				
			||||||
	cmd.Flags().String("name", "", "The name for the newly created object. If not specified, the name of the input resource will be used.")
 | 
						cmd.Flags().String("name", "", "The name for the newly created object. If not specified, the name of the input resource will be used.")
 | 
				
			||||||
	cmd.Flags().Bool("dry-run", false, "If true, only print the object that would be sent, without creating it.")
 | 
						cmdutil.AddDryRunFlag(cmd)
 | 
				
			||||||
	usage := "Filename, directory, or URL to a file identifying the resource to autoscale."
 | 
						usage := "Filename, directory, or URL to a file identifying the resource to autoscale."
 | 
				
			||||||
	kubectl.AddJsonFilenameFlag(cmd, &options.Filenames, usage)
 | 
						kubectl.AddJsonFilenameFlag(cmd, &options.Filenames, usage)
 | 
				
			||||||
	cmdutil.AddRecursiveFlag(cmd, &options.Recursive)
 | 
						cmdutil.AddRecursiveFlag(cmd, &options.Recursive)
 | 
				
			||||||
@@ -160,8 +160,7 @@ func RunAutoscale(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []
 | 
				
			|||||||
			}
 | 
								}
 | 
				
			||||||
			object = hpa.Object
 | 
								object = hpa.Object
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		// TODO: extract this flag to a central location, when such a location exists.
 | 
							if cmdutil.GetDryRunFlag(cmd) {
 | 
				
			||||||
		if cmdutil.GetFlagBool(cmd, "dry-run") {
 | 
					 | 
				
			||||||
			return f.PrintObject(cmd, mapper, object, out)
 | 
								return f.PrintObject(cmd, mapper, object, out)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -90,7 +90,7 @@ func CreateConfigMap(f *cmdutil.Factory, cmdOut io.Writer, cmd *cobra.Command, a
 | 
				
			|||||||
	return RunCreateSubcommand(f, cmd, cmdOut, &CreateSubcommandOptions{
 | 
						return RunCreateSubcommand(f, cmd, cmdOut, &CreateSubcommandOptions{
 | 
				
			||||||
		Name:                name,
 | 
							Name:                name,
 | 
				
			||||||
		StructuredGenerator: generator,
 | 
							StructuredGenerator: generator,
 | 
				
			||||||
		DryRun:              cmdutil.GetFlagBool(cmd, "dry-run"),
 | 
							DryRun:              cmdutil.GetDryRunFlag(cmd),
 | 
				
			||||||
		OutputFormat:        cmdutil.GetFlagString(cmd, "output"),
 | 
							OutputFormat:        cmdutil.GetFlagString(cmd, "output"),
 | 
				
			||||||
	})
 | 
						})
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -71,7 +71,7 @@ func CreateNamespace(f *cmdutil.Factory, cmdOut io.Writer, cmd *cobra.Command, a
 | 
				
			|||||||
	return RunCreateSubcommand(f, cmd, cmdOut, &CreateSubcommandOptions{
 | 
						return RunCreateSubcommand(f, cmd, cmdOut, &CreateSubcommandOptions{
 | 
				
			||||||
		Name:                name,
 | 
							Name:                name,
 | 
				
			||||||
		StructuredGenerator: generator,
 | 
							StructuredGenerator: generator,
 | 
				
			||||||
		DryRun:              cmdutil.GetFlagBool(cmd, "dry-run"),
 | 
							DryRun:              cmdutil.GetDryRunFlag(cmd),
 | 
				
			||||||
		OutputFormat:        cmdutil.GetFlagString(cmd, "output"),
 | 
							OutputFormat:        cmdutil.GetFlagString(cmd, "output"),
 | 
				
			||||||
	})
 | 
						})
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -109,7 +109,7 @@ func CreateSecretGeneric(f *cmdutil.Factory, cmdOut io.Writer, cmd *cobra.Comman
 | 
				
			|||||||
	return RunCreateSubcommand(f, cmd, cmdOut, &CreateSubcommandOptions{
 | 
						return RunCreateSubcommand(f, cmd, cmdOut, &CreateSubcommandOptions{
 | 
				
			||||||
		Name:                name,
 | 
							Name:                name,
 | 
				
			||||||
		StructuredGenerator: generator,
 | 
							StructuredGenerator: generator,
 | 
				
			||||||
		DryRun:              cmdutil.GetFlagBool(cmd, "dry-run"),
 | 
							DryRun:              cmdutil.GetDryRunFlag(cmd),
 | 
				
			||||||
		OutputFormat:        cmdutil.GetFlagString(cmd, "output"),
 | 
							OutputFormat:        cmdutil.GetFlagString(cmd, "output"),
 | 
				
			||||||
	})
 | 
						})
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -188,7 +188,7 @@ func CreateSecretDockerRegistry(f *cmdutil.Factory, cmdOut io.Writer, cmd *cobra
 | 
				
			|||||||
	return RunCreateSubcommand(f, cmd, cmdOut, &CreateSubcommandOptions{
 | 
						return RunCreateSubcommand(f, cmd, cmdOut, &CreateSubcommandOptions{
 | 
				
			||||||
		Name:                name,
 | 
							Name:                name,
 | 
				
			||||||
		StructuredGenerator: generator,
 | 
							StructuredGenerator: generator,
 | 
				
			||||||
		DryRun:              cmdutil.GetFlagBool(cmd, "dry-run"),
 | 
							DryRun:              cmdutil.GetDryRunFlag(cmd),
 | 
				
			||||||
		OutputFormat:        cmdutil.GetFlagString(cmd, "output"),
 | 
							OutputFormat:        cmdutil.GetFlagString(cmd, "output"),
 | 
				
			||||||
	})
 | 
						})
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -71,7 +71,7 @@ func CreateServiceAccount(f *cmdutil.Factory, cmdOut io.Writer, cmd *cobra.Comma
 | 
				
			|||||||
	return RunCreateSubcommand(f, cmd, cmdOut, &CreateSubcommandOptions{
 | 
						return RunCreateSubcommand(f, cmd, cmdOut, &CreateSubcommandOptions{
 | 
				
			||||||
		Name:                name,
 | 
							Name:                name,
 | 
				
			||||||
		StructuredGenerator: generator,
 | 
							StructuredGenerator: generator,
 | 
				
			||||||
		DryRun:              cmdutil.GetFlagBool(cmd, "dry-run"),
 | 
							DryRun:              cmdutil.GetDryRunFlag(cmd),
 | 
				
			||||||
		OutputFormat:        cmdutil.GetFlagString(cmd, "output"),
 | 
							OutputFormat:        cmdutil.GetFlagString(cmd, "output"),
 | 
				
			||||||
	})
 | 
						})
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -110,7 +110,6 @@ func NewCmdExposeService(f *cmdutil.Factory, out io.Writer) *cobra.Command {
 | 
				
			|||||||
	cmd.Flags().String("load-balancer-ip", "", "IP to assign to to the Load Balancer. If empty, an ephemeral IP will be created and used (cloud-provider specific).")
 | 
						cmd.Flags().String("load-balancer-ip", "", "IP to assign to to the Load Balancer. If empty, an ephemeral IP will be created and used (cloud-provider specific).")
 | 
				
			||||||
	cmd.Flags().String("selector", "", "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().String("selector", "", "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().StringP("labels", "l", "", "Labels to apply to the service created by this call.")
 | 
						cmd.Flags().StringP("labels", "l", "", "Labels to apply to the service created by this call.")
 | 
				
			||||||
	cmd.Flags().Bool("dry-run", false, "If true, only print the object that would be sent, without creating it.")
 | 
					 | 
				
			||||||
	cmd.Flags().String("container-port", "", "Synonym for --target-port")
 | 
						cmd.Flags().String("container-port", "", "Synonym for --target-port")
 | 
				
			||||||
	cmd.Flags().MarkDeprecated("container-port", "--container-port will be removed in the future, please use --target-port instead")
 | 
						cmd.Flags().MarkDeprecated("container-port", "--container-port will be removed in the future, please use --target-port instead")
 | 
				
			||||||
	cmd.Flags().String("target-port", "", "Name or number for the port on the container that the service should direct traffic to. Optional.")
 | 
						cmd.Flags().String("target-port", "", "Name or number for the port on the container that the service should direct traffic to. Optional.")
 | 
				
			||||||
@@ -121,6 +120,7 @@ func NewCmdExposeService(f *cmdutil.Factory, out io.Writer) *cobra.Command {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	usage := "Filename, directory, or URL to a file identifying the resource to expose a service"
 | 
						usage := "Filename, directory, or URL to a file identifying the resource to expose a service"
 | 
				
			||||||
	kubectl.AddJsonFilenameFlag(cmd, &options.Filenames, usage)
 | 
						kubectl.AddJsonFilenameFlag(cmd, &options.Filenames, usage)
 | 
				
			||||||
 | 
						cmdutil.AddDryRunFlag(cmd)
 | 
				
			||||||
	cmdutil.AddRecursiveFlag(cmd, &options.Recursive)
 | 
						cmdutil.AddRecursiveFlag(cmd, &options.Recursive)
 | 
				
			||||||
	cmdutil.AddApplyAnnotationFlags(cmd)
 | 
						cmdutil.AddApplyAnnotationFlags(cmd)
 | 
				
			||||||
	cmdutil.AddRecordFlag(cmd)
 | 
						cmdutil.AddRecordFlag(cmd)
 | 
				
			||||||
@@ -256,8 +256,7 @@ func RunExpose(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []str
 | 
				
			|||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		info.Refresh(object, true)
 | 
							info.Refresh(object, true)
 | 
				
			||||||
		// TODO: extract this flag to a central location, when such a location exists.
 | 
							if cmdutil.GetDryRunFlag(cmd) {
 | 
				
			||||||
		if cmdutil.GetFlagBool(cmd, "dry-run") {
 | 
					 | 
				
			||||||
			return f.PrintObject(cmd, mapper, object, out)
 | 
								return f.PrintObject(cmd, mapper, object, out)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		if err := kubectl.CreateOrUpdateAnnotation(cmdutil.GetFlagBool(cmd, cmdutil.ApplyAnnotationsFlag), info, f.JSONEncoder()); err != nil {
 | 
							if err := kubectl.CreateOrUpdateAnnotation(cmdutil.GetFlagBool(cmd, cmdutil.ApplyAnnotationsFlag), info, f.JSONEncoder()); err != nil {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -101,7 +101,7 @@ func NewCmdLabel(f *cmdutil.Factory, out io.Writer) *cobra.Command {
 | 
				
			|||||||
	usage := "Filename, directory, or URL to a file identifying the resource to update the labels"
 | 
						usage := "Filename, directory, or URL to a file identifying the resource to update the labels"
 | 
				
			||||||
	kubectl.AddJsonFilenameFlag(cmd, &options.Filenames, usage)
 | 
						kubectl.AddJsonFilenameFlag(cmd, &options.Filenames, usage)
 | 
				
			||||||
	cmdutil.AddRecursiveFlag(cmd, &options.Recursive)
 | 
						cmdutil.AddRecursiveFlag(cmd, &options.Recursive)
 | 
				
			||||||
	cmd.Flags().Bool("dry-run", false, "If true, only print the object that would be sent, without sending it.")
 | 
						cmdutil.AddDryRunFlag(cmd)
 | 
				
			||||||
	cmdutil.AddRecordFlag(cmd)
 | 
						cmdutil.AddRecordFlag(cmd)
 | 
				
			||||||
	cmdutil.AddInclude3rdPartyFlags(cmd)
 | 
						cmdutil.AddInclude3rdPartyFlags(cmd)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -176,21 +176,9 @@ func labelFunc(obj runtime.Object, overwrite bool, resourceVersion string, label
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func RunLabel(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []string, options *LabelOptions) error {
 | 
					func RunLabel(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []string, options *LabelOptions) error {
 | 
				
			||||||
	resources, labelArgs := []string{}, []string{}
 | 
						resources, labelArgs, err := cmdutil.GetResourcesAndPairs(args, "label")
 | 
				
			||||||
	first := true
 | 
						if err != nil {
 | 
				
			||||||
	for _, s := range args {
 | 
							return err
 | 
				
			||||||
		isLabel := strings.Contains(s, "=") || strings.HasSuffix(s, "-")
 | 
					 | 
				
			||||||
		switch {
 | 
					 | 
				
			||||||
		case first && isLabel:
 | 
					 | 
				
			||||||
			first = false
 | 
					 | 
				
			||||||
			fallthrough
 | 
					 | 
				
			||||||
		case !first && isLabel:
 | 
					 | 
				
			||||||
			labelArgs = append(labelArgs, s)
 | 
					 | 
				
			||||||
		case first && !isLabel:
 | 
					 | 
				
			||||||
			resources = append(resources, s)
 | 
					 | 
				
			||||||
		case !first && !isLabel:
 | 
					 | 
				
			||||||
			return cmdutil.UsageError(cmd, "all resources must be specified before label changes: %s", s)
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if len(resources) < 1 && len(options.Filenames) == 0 {
 | 
						if len(resources) < 1 && len(options.Filenames) == 0 {
 | 
				
			||||||
		return cmdutil.UsageError(cmd, "one or more resources must be specified as <resource> <name> or <resource>/<name>")
 | 
							return cmdutil.UsageError(cmd, "one or more resources must be specified as <resource> <name> or <resource>/<name>")
 | 
				
			||||||
@@ -242,7 +230,7 @@ func RunLabel(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []stri
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
		var outputObj runtime.Object
 | 
							var outputObj runtime.Object
 | 
				
			||||||
		dataChangeMsg := "not labeled"
 | 
							dataChangeMsg := "not labeled"
 | 
				
			||||||
		if cmdutil.GetFlagBool(cmd, "dry-run") {
 | 
							if cmdutil.GetDryRunFlag(cmd) {
 | 
				
			||||||
			err = labelFunc(info.Object, overwrite, resourceVersion, lbls, remove)
 | 
								err = labelFunc(info.Object, overwrite, resourceVersion, lbls, remove)
 | 
				
			||||||
			if err != nil {
 | 
								if err != nil {
 | 
				
			||||||
				return err
 | 
									return err
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -98,8 +98,8 @@ func NewCmdRollingUpdate(f *cmdutil.Factory, out io.Writer) *cobra.Command {
 | 
				
			|||||||
	cmd.Flags().String("deployment-label-key", "deployment", "The key to use to differentiate between two different controllers, default 'deployment'.  Only relevant when --image is specified, ignored otherwise")
 | 
						cmd.Flags().String("deployment-label-key", "deployment", "The key to use to differentiate between two different controllers, default 'deployment'.  Only relevant when --image is specified, ignored otherwise")
 | 
				
			||||||
	cmd.Flags().String("container", "", "Container name which will have its image upgraded. Only relevant when --image is specified, ignored otherwise. Required when using --image on a multi-container pod")
 | 
						cmd.Flags().String("container", "", "Container name which will have its image upgraded. Only relevant when --image is specified, ignored otherwise. Required when using --image on a multi-container pod")
 | 
				
			||||||
	cmd.Flags().String("image-pull-policy", "", "Explicit policy for when to pull container images. Required when --image is same as existing image, ignored otherwise.")
 | 
						cmd.Flags().String("image-pull-policy", "", "Explicit policy for when to pull container images. Required when --image is same as existing image, ignored otherwise.")
 | 
				
			||||||
	cmd.Flags().Bool("dry-run", false, "If true, print out the changes that would be made, but don't actually make them.")
 | 
					 | 
				
			||||||
	cmd.Flags().Bool("rollback", false, "If true, this is a request to abort an existing rollout that is partially rolled out. It effectively reverses current and next and runs a rollout")
 | 
						cmd.Flags().Bool("rollback", false, "If true, this is a request to abort an existing rollout that is partially rolled out. It effectively reverses current and next and runs a rollout")
 | 
				
			||||||
 | 
						cmdutil.AddDryRunFlag(cmd)
 | 
				
			||||||
	cmdutil.AddValidateFlags(cmd)
 | 
						cmdutil.AddValidateFlags(cmd)
 | 
				
			||||||
	cmdutil.AddPrinterFlags(cmd)
 | 
						cmdutil.AddPrinterFlags(cmd)
 | 
				
			||||||
	cmdutil.AddInclude3rdPartyFlags(cmd)
 | 
						cmdutil.AddInclude3rdPartyFlags(cmd)
 | 
				
			||||||
@@ -157,7 +157,7 @@ func RunRollingUpdate(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, arg
 | 
				
			|||||||
	period := cmdutil.GetFlagDuration(cmd, "update-period")
 | 
						period := cmdutil.GetFlagDuration(cmd, "update-period")
 | 
				
			||||||
	interval := cmdutil.GetFlagDuration(cmd, "poll-interval")
 | 
						interval := cmdutil.GetFlagDuration(cmd, "poll-interval")
 | 
				
			||||||
	timeout := cmdutil.GetFlagDuration(cmd, "timeout")
 | 
						timeout := cmdutil.GetFlagDuration(cmd, "timeout")
 | 
				
			||||||
	dryrun := cmdutil.GetFlagBool(cmd, "dry-run")
 | 
						dryrun := cmdutil.GetDryRunFlag(cmd)
 | 
				
			||||||
	outputFormat := cmdutil.GetFlagString(cmd, "output")
 | 
						outputFormat := cmdutil.GetFlagString(cmd, "output")
 | 
				
			||||||
	container := cmdutil.GetFlagString(cmd, "container")
 | 
						container := cmdutil.GetFlagString(cmd, "container")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -92,12 +92,12 @@ func NewCmdRun(f *cmdutil.Factory, cmdIn io.Reader, cmdOut, cmdErr io.Writer) *c
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func addRunFlags(cmd *cobra.Command) {
 | 
					func addRunFlags(cmd *cobra.Command) {
 | 
				
			||||||
 | 
						cmdutil.AddDryRunFlag(cmd)
 | 
				
			||||||
	cmd.Flags().String("generator", "", "The name of the API generator to use.  Default is 'deployment/v1beta1' if --restart=Always, otherwise the default is 'job/v1'.  This will happen only for cluster version at least 1.2, for olders we will fallback to 'run/v1' for --restart=Always, 'run-pod/v1' for others.")
 | 
						cmd.Flags().String("generator", "", "The name of the API generator to use.  Default is 'deployment/v1beta1' if --restart=Always, otherwise the default is 'job/v1'.  This will happen only for cluster version at least 1.2, for olders we will fallback to 'run/v1' for --restart=Always, 'run-pod/v1' for others.")
 | 
				
			||||||
	cmd.Flags().String("image", "", "The image for the container to run.")
 | 
						cmd.Flags().String("image", "", "The image for the container to run.")
 | 
				
			||||||
	cmd.MarkFlagRequired("image")
 | 
						cmd.MarkFlagRequired("image")
 | 
				
			||||||
	cmd.Flags().IntP("replicas", "r", 1, "Number of replicas to create for this container. Default is 1.")
 | 
						cmd.Flags().IntP("replicas", "r", 1, "Number of replicas to create for this container. Default is 1.")
 | 
				
			||||||
	cmd.Flags().Bool("rm", false, "If true, delete resources created in this command for attached containers.")
 | 
						cmd.Flags().Bool("rm", false, "If true, delete resources created in this command for attached containers.")
 | 
				
			||||||
	cmd.Flags().Bool("dry-run", false, "If true, only print the object that would be sent, without sending it.")
 | 
					 | 
				
			||||||
	cmd.Flags().String("overrides", "", "An inline JSON override for the generated object. If this is non-empty, it is 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 used to override the generated object. Requires that the object supply a valid apiVersion field.")
 | 
				
			||||||
	cmd.Flags().StringSlice("env", []string{}, "Environment variables to set in the container")
 | 
						cmd.Flags().StringSlice("env", []string{}, "Environment variables to set in the container")
 | 
				
			||||||
	cmd.Flags().Int("port", -1, "The port that this container exposes.  If --expose is true, this is also the port used by the service that is created.")
 | 
						cmd.Flags().Int("port", -1, "The port that this container exposes.  If --expose is true, this is also the port used by the service that is created.")
 | 
				
			||||||
@@ -474,8 +474,7 @@ func createGeneratedObject(f *cmdutil.Factory, cmd *cobra.Command, generator kub
 | 
				
			|||||||
			return nil, "", nil, nil, err
 | 
								return nil, "", nil, nil, err
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	// TODO: extract this flag to a central location, when such a location exists.
 | 
						if !cmdutil.GetDryRunFlag(cmd) {
 | 
				
			||||||
	if !cmdutil.GetFlagBool(cmd, "dry-run") {
 | 
					 | 
				
			||||||
		resourceMapper := &resource.Mapper{
 | 
							resourceMapper := &resource.Mapper{
 | 
				
			||||||
			ObjectTyper:  typer,
 | 
								ObjectTyper:  typer,
 | 
				
			||||||
			RESTMapper:   mapper,
 | 
								RESTMapper:   mapper,
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										151
									
								
								pkg/kubectl/cmd/set/helper.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										151
									
								
								pkg/kubectl/cmd/set/helper.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,151 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					Copyright 2016 The Kubernetes Authors 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 set
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"fmt"
 | 
				
			||||||
 | 
						"io"
 | 
				
			||||||
 | 
						"strings"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"k8s.io/kubernetes/pkg/api"
 | 
				
			||||||
 | 
						"k8s.io/kubernetes/pkg/api/errors"
 | 
				
			||||||
 | 
						"k8s.io/kubernetes/pkg/kubectl/resource"
 | 
				
			||||||
 | 
						"k8s.io/kubernetes/pkg/runtime"
 | 
				
			||||||
 | 
						"k8s.io/kubernetes/pkg/util/strategicpatch"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// selectContainers allows one or more containers to be matched against a string or wildcard
 | 
				
			||||||
 | 
					func selectContainers(containers []api.Container, spec string) ([]*api.Container, []*api.Container) {
 | 
				
			||||||
 | 
						out := []*api.Container{}
 | 
				
			||||||
 | 
						skipped := []*api.Container{}
 | 
				
			||||||
 | 
						for i, c := range containers {
 | 
				
			||||||
 | 
							if selectString(c.Name, spec) {
 | 
				
			||||||
 | 
								out = append(out, &containers[i])
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								skipped = append(skipped, &containers[i])
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return out, skipped
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// handlePodUpdateError prints a more useful error to the end user when mutating a pod.
 | 
				
			||||||
 | 
					func handlePodUpdateError(out io.Writer, err error, resource string) {
 | 
				
			||||||
 | 
						if statusError, ok := err.(*errors.StatusError); ok && errors.IsInvalid(err) {
 | 
				
			||||||
 | 
							errorDetails := statusError.Status().Details
 | 
				
			||||||
 | 
							if errorDetails.Kind == "Pod" {
 | 
				
			||||||
 | 
								all, match := true, false
 | 
				
			||||||
 | 
								for _, cause := range errorDetails.Causes {
 | 
				
			||||||
 | 
									if cause.Field == "spec" && strings.Contains(cause.Message, "may not update fields other than") {
 | 
				
			||||||
 | 
										fmt.Fprintf(out, "error: may not update %s in pod %q directly\n", resource, errorDetails.Name)
 | 
				
			||||||
 | 
										match = true
 | 
				
			||||||
 | 
									} else {
 | 
				
			||||||
 | 
										all = false
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								if all && match {
 | 
				
			||||||
 | 
									return
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						fmt.Fprintf(out, "error: %v\n", err)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// selectString returns true if the provided string matches spec, where spec is a string with
 | 
				
			||||||
 | 
					// a non-greedy '*' wildcard operator.
 | 
				
			||||||
 | 
					// TODO: turn into a regex and handle greedy matches and backtracking.
 | 
				
			||||||
 | 
					func selectString(s, spec string) bool {
 | 
				
			||||||
 | 
						if spec == "*" {
 | 
				
			||||||
 | 
							return true
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if !strings.Contains(spec, "*") {
 | 
				
			||||||
 | 
							return s == spec
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						pos := 0
 | 
				
			||||||
 | 
						match := true
 | 
				
			||||||
 | 
						parts := strings.Split(spec, "*")
 | 
				
			||||||
 | 
						for i, part := range parts {
 | 
				
			||||||
 | 
							if len(part) == 0 {
 | 
				
			||||||
 | 
								continue
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							next := strings.Index(s[pos:], part)
 | 
				
			||||||
 | 
							switch {
 | 
				
			||||||
 | 
							// next part not in string
 | 
				
			||||||
 | 
							case next < pos:
 | 
				
			||||||
 | 
								fallthrough
 | 
				
			||||||
 | 
							// first part does not match start of string
 | 
				
			||||||
 | 
							case i == 0 && pos != 0:
 | 
				
			||||||
 | 
								fallthrough
 | 
				
			||||||
 | 
							// last part does not exactly match remaining part of string
 | 
				
			||||||
 | 
							case i == (len(parts)-1) && len(s) != (len(part)+next):
 | 
				
			||||||
 | 
								match = false
 | 
				
			||||||
 | 
								break
 | 
				
			||||||
 | 
							default:
 | 
				
			||||||
 | 
								pos = next
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return match
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Patch represents the result of a mutation to an object.
 | 
				
			||||||
 | 
					type Patch struct {
 | 
				
			||||||
 | 
						Info *resource.Info
 | 
				
			||||||
 | 
						Err  error
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						Before []byte
 | 
				
			||||||
 | 
						After  []byte
 | 
				
			||||||
 | 
						Patch  []byte
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// CalculatePatches calls the mutation function on each provided info object, and generates a strategic merge patch for
 | 
				
			||||||
 | 
					// the changes in the object. Encoder must be able to encode the info into the appropriate destination type. If mutateFn
 | 
				
			||||||
 | 
					// returns false, the object is not included in the final list of patches.
 | 
				
			||||||
 | 
					func CalculatePatches(infos []*resource.Info, encoder runtime.Encoder, mutateFn func(*resource.Info) (bool, error)) []*Patch {
 | 
				
			||||||
 | 
						var patches []*Patch
 | 
				
			||||||
 | 
						for _, info := range infos {
 | 
				
			||||||
 | 
							patch := &Patch{Info: info}
 | 
				
			||||||
 | 
							patch.Before, patch.Err = runtime.Encode(encoder, info.Object)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							ok, err := mutateFn(info)
 | 
				
			||||||
 | 
							if !ok {
 | 
				
			||||||
 | 
								continue
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								patch.Err = err
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							patches = append(patches, patch)
 | 
				
			||||||
 | 
							if patch.Err != nil {
 | 
				
			||||||
 | 
								continue
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							patch.After, patch.Err = runtime.Encode(encoder, info.Object)
 | 
				
			||||||
 | 
							if patch.Err != nil {
 | 
				
			||||||
 | 
								continue
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							// TODO: should be via New
 | 
				
			||||||
 | 
							versioned, err := info.Mapping.ConvertToVersion(info.Object, info.Mapping.GroupVersionKind.GroupVersion())
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								patch.Err = err
 | 
				
			||||||
 | 
								continue
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							patch.Patch, patch.Err = strategicpatch.CreateTwoWayMergePatch(patch.Before, patch.After, versioned)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return patches
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -42,7 +42,8 @@ func NewCmdSet(f *cmdutil.Factory, out io.Writer) *cobra.Command {
 | 
				
			|||||||
		},
 | 
							},
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// TODO: add subcommands
 | 
						// add subcommands
 | 
				
			||||||
 | 
						cmd.AddCommand(NewCmdImage(f, out))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return cmd
 | 
						return cmd
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										239
									
								
								pkg/kubectl/cmd/set/set_image.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										239
									
								
								pkg/kubectl/cmd/set/set_image.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,239 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					Copyright 2016 The Kubernetes Authors 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 set
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"fmt"
 | 
				
			||||||
 | 
						"io"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"github.com/spf13/cobra"
 | 
				
			||||||
 | 
						"k8s.io/kubernetes/pkg/api"
 | 
				
			||||||
 | 
						"k8s.io/kubernetes/pkg/api/meta"
 | 
				
			||||||
 | 
						"k8s.io/kubernetes/pkg/kubectl"
 | 
				
			||||||
 | 
						cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util"
 | 
				
			||||||
 | 
						"k8s.io/kubernetes/pkg/kubectl/resource"
 | 
				
			||||||
 | 
						"k8s.io/kubernetes/pkg/runtime"
 | 
				
			||||||
 | 
						utilerrors "k8s.io/kubernetes/pkg/util/errors"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// ImageOptions is the start of the data required to perform the operation.  As new fields are added, add them here instead of
 | 
				
			||||||
 | 
					// referencing the cmd.Flags()
 | 
				
			||||||
 | 
					type ImageOptions struct {
 | 
				
			||||||
 | 
						Mapper      meta.RESTMapper
 | 
				
			||||||
 | 
						Typer       runtime.ObjectTyper
 | 
				
			||||||
 | 
						Infos       []*resource.Info
 | 
				
			||||||
 | 
						Encoder     runtime.Encoder
 | 
				
			||||||
 | 
						Selector    string
 | 
				
			||||||
 | 
						Out         io.Writer
 | 
				
			||||||
 | 
						Err         io.Writer
 | 
				
			||||||
 | 
						Filenames   []string
 | 
				
			||||||
 | 
						Recursive   bool
 | 
				
			||||||
 | 
						ShortOutput bool
 | 
				
			||||||
 | 
						All         bool
 | 
				
			||||||
 | 
						Record      bool
 | 
				
			||||||
 | 
						ChangeCause string
 | 
				
			||||||
 | 
						Local       bool
 | 
				
			||||||
 | 
						Cmd         *cobra.Command
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						PrintObject            func(cmd *cobra.Command, mapper meta.RESTMapper, obj runtime.Object, out io.Writer) error
 | 
				
			||||||
 | 
						UpdatePodSpecForObject func(obj runtime.Object, fn func(*api.PodSpec) error) (bool, error)
 | 
				
			||||||
 | 
						Resources              []string
 | 
				
			||||||
 | 
						ContainerImages        map[string]string
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const (
 | 
				
			||||||
 | 
						image_resources = `
 | 
				
			||||||
 | 
					  pod (po), replicationcontroller (rc), deployment, daemonset (ds), job, replicaset (rs)`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						image_long = `Update existing container image(s) of resources.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Possible resources include (case insensitive):` + image_resources
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						image_example = `# Set a deployment's nginx container image to 'nginx:1.9.1', and its busybox container image to 'busybox'.
 | 
				
			||||||
 | 
					kubectl set image deployment/nginx busybox=busybox nginx=nginx:1.9.1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Update all deployments' and rc's nginx container's image to 'nginx:1.9.1'
 | 
				
			||||||
 | 
					kubectl set image deployments,rc nginx=nginx:1.9.1 --all
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Update image of all containers of daemonset abc to 'nginx:1.9.1'
 | 
				
			||||||
 | 
					kubectl set image daemonset abc *=nginx:1.9.1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Print result (in yaml format) of updating nginx container image from local file, without hitting the server 
 | 
				
			||||||
 | 
					kubectl set image -f path/to/file.yaml nginx=nginx:1.9.1 --local -o yaml`
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func NewCmdImage(f *cmdutil.Factory, out io.Writer) *cobra.Command {
 | 
				
			||||||
 | 
						options := &ImageOptions{
 | 
				
			||||||
 | 
							Out: out,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						cmd := &cobra.Command{
 | 
				
			||||||
 | 
							Use:     "image (-f FILENAME | TYPE NAME) CONTAINER_NAME_1=CONTAINER_IMAGE_1 ... CONTAINER_NAME_N=CONTAINER_IMAGE_N",
 | 
				
			||||||
 | 
							Short:   "Update image of a pod template",
 | 
				
			||||||
 | 
							Long:    image_long,
 | 
				
			||||||
 | 
							Example: image_example,
 | 
				
			||||||
 | 
							Run: func(cmd *cobra.Command, args []string) {
 | 
				
			||||||
 | 
								cmdutil.CheckErr(options.Complete(f, cmd, args))
 | 
				
			||||||
 | 
								cmdutil.CheckErr(options.Validate())
 | 
				
			||||||
 | 
								cmdutil.CheckErr(options.Run())
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						cmdutil.AddPrinterFlags(cmd)
 | 
				
			||||||
 | 
						usage := "Filename, directory, or URL to a file identifying the resource to get from a server."
 | 
				
			||||||
 | 
						kubectl.AddJsonFilenameFlag(cmd, &options.Filenames, usage)
 | 
				
			||||||
 | 
						cmd.Flags().BoolVar(&options.All, "all", false, "select all resources in the namespace of the specified resource types")
 | 
				
			||||||
 | 
						cmd.Flags().StringVarP(&options.Selector, "selector", "l", "", "Selector (label query) to filter on")
 | 
				
			||||||
 | 
						cmd.Flags().BoolVar(&options.Local, "local", false, "If true, set image will NOT contact api-server but run locally.")
 | 
				
			||||||
 | 
						cmdutil.AddRecordFlag(cmd)
 | 
				
			||||||
 | 
						cmdutil.AddRecursiveFlag(cmd, &options.Recursive)
 | 
				
			||||||
 | 
						return cmd
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (o *ImageOptions) Complete(f *cmdutil.Factory, cmd *cobra.Command, args []string) error {
 | 
				
			||||||
 | 
						o.Mapper, o.Typer = f.Object(cmdutil.GetIncludeThirdPartyAPIs(cmd))
 | 
				
			||||||
 | 
						o.UpdatePodSpecForObject = f.UpdatePodSpecForObject
 | 
				
			||||||
 | 
						o.Encoder = f.JSONEncoder()
 | 
				
			||||||
 | 
						o.ShortOutput = cmdutil.GetFlagString(cmd, "output") == "name"
 | 
				
			||||||
 | 
						o.Record = cmdutil.GetRecordFlag(cmd)
 | 
				
			||||||
 | 
						o.ChangeCause = f.Command()
 | 
				
			||||||
 | 
						o.PrintObject = f.PrintObject
 | 
				
			||||||
 | 
						o.Cmd = cmd
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						cmdNamespace, enforceNamespace, err := f.DefaultNamespace()
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						o.Resources, o.ContainerImages, err = getResourcesAndImages(args)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						builder := resource.NewBuilder(o.Mapper, o.Typer, resource.ClientMapperFunc(f.ClientForMapping), f.Decoder(true)).
 | 
				
			||||||
 | 
							ContinueOnError().
 | 
				
			||||||
 | 
							NamespaceParam(cmdNamespace).DefaultNamespace().
 | 
				
			||||||
 | 
							FilenameParam(enforceNamespace, o.Recursive, o.Filenames...).
 | 
				
			||||||
 | 
							Flatten()
 | 
				
			||||||
 | 
						if !o.Local {
 | 
				
			||||||
 | 
							builder = builder.
 | 
				
			||||||
 | 
								SelectorParam(o.Selector).
 | 
				
			||||||
 | 
								ResourceTypeOrNameArgs(o.All, o.Resources...).
 | 
				
			||||||
 | 
								Latest()
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						o.Infos, err = builder.Do().Infos()
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (o *ImageOptions) Validate() error {
 | 
				
			||||||
 | 
						if len(o.Resources) < 1 && len(o.Filenames) == 0 {
 | 
				
			||||||
 | 
							return fmt.Errorf("one or more resources must be specified as <resource> <name> or <resource>/<name>")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if len(o.ContainerImages) < 1 {
 | 
				
			||||||
 | 
							return fmt.Errorf("at least one image update is required")
 | 
				
			||||||
 | 
						} else if len(o.ContainerImages) > 1 && hasWildcardKey(o.ContainerImages) {
 | 
				
			||||||
 | 
							return fmt.Errorf("all containers are already specified by *, but saw more than one container_name=container_image pairs")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (o *ImageOptions) Run() error {
 | 
				
			||||||
 | 
						allErrs := []error{}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						patches := CalculatePatches(o.Infos, o.Encoder, func(info *resource.Info) (bool, error) {
 | 
				
			||||||
 | 
							transformed := false
 | 
				
			||||||
 | 
							_, err := o.UpdatePodSpecForObject(info.Object, func(spec *api.PodSpec) error {
 | 
				
			||||||
 | 
								for name, image := range o.ContainerImages {
 | 
				
			||||||
 | 
									containerFound := false
 | 
				
			||||||
 | 
									// Find the container to update, and update its image
 | 
				
			||||||
 | 
									for i, c := range spec.Containers {
 | 
				
			||||||
 | 
										if c.Name == name || name == "*" {
 | 
				
			||||||
 | 
											spec.Containers[i].Image = image
 | 
				
			||||||
 | 
											containerFound = true
 | 
				
			||||||
 | 
											// Perform updates
 | 
				
			||||||
 | 
											transformed = true
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									// Add a new container if not found
 | 
				
			||||||
 | 
									if !containerFound {
 | 
				
			||||||
 | 
										allErrs = append(allErrs, fmt.Errorf("error: unable to find container named %q", name))
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								return nil
 | 
				
			||||||
 | 
							})
 | 
				
			||||||
 | 
							return transformed, err
 | 
				
			||||||
 | 
						})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for _, patch := range patches {
 | 
				
			||||||
 | 
							info := patch.Info
 | 
				
			||||||
 | 
							if patch.Err != nil {
 | 
				
			||||||
 | 
								allErrs = append(allErrs, fmt.Errorf("error: %s/%s %v\n", info.Mapping.Resource, info.Name, patch.Err))
 | 
				
			||||||
 | 
								continue
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							// no changes
 | 
				
			||||||
 | 
							if string(patch.Patch) == "{}" || len(patch.Patch) == 0 {
 | 
				
			||||||
 | 
								continue
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if o.Local {
 | 
				
			||||||
 | 
								fmt.Fprintln(o.Out, "running in local mode...")
 | 
				
			||||||
 | 
								return o.PrintObject(o.Cmd, o.Mapper, info.Object, o.Out)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							// patch the change
 | 
				
			||||||
 | 
							obj, err := resource.NewHelper(info.Client, info.Mapping).Patch(info.Namespace, info.Name, api.StrategicMergePatchType, patch.Patch)
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								allErrs = append(allErrs, fmt.Errorf("failed to patch image update to pod template: %v\n", err))
 | 
				
			||||||
 | 
								continue
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							info.Refresh(obj, true)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							// record this change (for rollout history)
 | 
				
			||||||
 | 
							if o.Record || cmdutil.ContainsChangeCause(info) {
 | 
				
			||||||
 | 
								if err := cmdutil.RecordChangeCause(obj, o.ChangeCause); err == nil {
 | 
				
			||||||
 | 
									if obj, err = resource.NewHelper(info.Client, info.Mapping).Replace(info.Namespace, info.Name, false, obj); err != nil {
 | 
				
			||||||
 | 
										allErrs = append(allErrs, fmt.Errorf("changes to %s/%s can't be recorded: %v\n", info.Mapping.Resource, info.Name, err))
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							info.Refresh(obj, true)
 | 
				
			||||||
 | 
							cmdutil.PrintSuccess(o.Mapper, o.ShortOutput, o.Out, info.Mapping.Resource, info.Name, "image updated")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return utilerrors.NewAggregate(allErrs)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// getResourcesAndImages retrieves resources and container name:images pair from given args
 | 
				
			||||||
 | 
					func getResourcesAndImages(args []string) (resources []string, containerImages map[string]string, err error) {
 | 
				
			||||||
 | 
						pairType := "image"
 | 
				
			||||||
 | 
						resources, imageArgs, err := cmdutil.GetResourcesAndPairs(args, pairType)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						containerImages, _, err = cmdutil.ParsePairs(imageArgs, pairType, false)
 | 
				
			||||||
 | 
						return
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func hasWildcardKey(containerImages map[string]string) bool {
 | 
				
			||||||
 | 
						_, ok := containerImages["*"]
 | 
				
			||||||
 | 
						return ok
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -139,6 +139,9 @@ type Factory struct {
 | 
				
			|||||||
	CanBeAutoscaled func(kind unversioned.GroupKind) error
 | 
						CanBeAutoscaled func(kind unversioned.GroupKind) error
 | 
				
			||||||
	// AttachablePodForObject returns the pod to which to attach given an object.
 | 
						// AttachablePodForObject returns the pod to which to attach given an object.
 | 
				
			||||||
	AttachablePodForObject func(object runtime.Object) (*api.Pod, error)
 | 
						AttachablePodForObject func(object runtime.Object) (*api.Pod, error)
 | 
				
			||||||
 | 
						// UpdatePodSpecForObject will call the provided function on the pod spec this object supports,
 | 
				
			||||||
 | 
						// return false if no pod spec is supported, or return an error.
 | 
				
			||||||
 | 
						UpdatePodSpecForObject func(obj runtime.Object, fn func(*api.PodSpec) error) (bool, error)
 | 
				
			||||||
	// EditorEnvs returns a group of environment variables that the edit command
 | 
						// EditorEnvs returns a group of environment variables that the edit command
 | 
				
			||||||
	// can range over in order to determine if the user has specified an editor
 | 
						// can range over in order to determine if the user has specified an editor
 | 
				
			||||||
	// of their choice.
 | 
						// of their choice.
 | 
				
			||||||
@@ -708,6 +711,31 @@ func NewFactory(optionalClientConfig clientcmd.ClientConfig) *Factory {
 | 
				
			|||||||
				return nil, fmt.Errorf("cannot attach to %v: not implemented", gvk)
 | 
									return nil, fmt.Errorf("cannot attach to %v: not implemented", gvk)
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
 | 
							// UpdatePodSpecForObject update the pod specification for the provided object
 | 
				
			||||||
 | 
							UpdatePodSpecForObject: func(obj runtime.Object, fn func(*api.PodSpec) error) (bool, error) {
 | 
				
			||||||
 | 
								// TODO: replace with a swagger schema based approach (identify pod template via schema introspection)
 | 
				
			||||||
 | 
								switch t := obj.(type) {
 | 
				
			||||||
 | 
								case *api.Pod:
 | 
				
			||||||
 | 
									return true, fn(&t.Spec)
 | 
				
			||||||
 | 
								case *api.ReplicationController:
 | 
				
			||||||
 | 
									if t.Spec.Template == nil {
 | 
				
			||||||
 | 
										t.Spec.Template = &api.PodTemplateSpec{}
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									return true, fn(&t.Spec.Template.Spec)
 | 
				
			||||||
 | 
								case *extensions.Deployment:
 | 
				
			||||||
 | 
									return true, fn(&t.Spec.Template.Spec)
 | 
				
			||||||
 | 
								case *extensions.DaemonSet:
 | 
				
			||||||
 | 
									return true, fn(&t.Spec.Template.Spec)
 | 
				
			||||||
 | 
								case *extensions.ReplicaSet:
 | 
				
			||||||
 | 
									return true, fn(&t.Spec.Template.Spec)
 | 
				
			||||||
 | 
								case *apps.PetSet:
 | 
				
			||||||
 | 
									return true, fn(&t.Spec.Template.Spec)
 | 
				
			||||||
 | 
								case *batch.Job:
 | 
				
			||||||
 | 
									return true, fn(&t.Spec.Template.Spec)
 | 
				
			||||||
 | 
								default:
 | 
				
			||||||
 | 
									return false, fmt.Errorf("the object is not a pod or does not have a pod template")
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
		EditorEnvs: func() []string {
 | 
							EditorEnvs: func() []string {
 | 
				
			||||||
			return []string{"KUBE_EDITOR", "EDITOR"}
 | 
								return []string{"KUBE_EDITOR", "EDITOR"}
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -336,6 +336,11 @@ func AddRecursiveFlag(cmd *cobra.Command, value *bool) {
 | 
				
			|||||||
	cmd.Flags().BoolVarP(value, "recursive", "R", *value, "If true, process directory recursively.")
 | 
						cmd.Flags().BoolVarP(value, "recursive", "R", *value, "If true, process directory recursively.")
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// AddDryRunFlag adds dry-run flag to a command. Usually used by mutations.
 | 
				
			||||||
 | 
					func AddDryRunFlag(cmd *cobra.Command) {
 | 
				
			||||||
 | 
						cmd.Flags().Bool("dry-run", false, "If true, only print the object that would be sent, without sending it.")
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func AddApplyAnnotationFlags(cmd *cobra.Command) {
 | 
					func AddApplyAnnotationFlags(cmd *cobra.Command) {
 | 
				
			||||||
	cmd.Flags().Bool(ApplyAnnotationsFlag, false, "If true, the configuration of current object will be saved in its annotation. This is useful when you want to perform kubectl apply on this object in the future.")
 | 
						cmd.Flags().Bool(ApplyAnnotationsFlag, false, "If true, the configuration of current object will be saved in its annotation. This is useful when you want to perform kubectl apply on this object in the future.")
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -344,7 +349,7 @@ func AddApplyAnnotationFlags(cmd *cobra.Command) {
 | 
				
			|||||||
// TODO: need to take a pass at other generator commands to use this set of flags
 | 
					// TODO: need to take a pass at other generator commands to use this set of flags
 | 
				
			||||||
func AddGeneratorFlags(cmd *cobra.Command, defaultGenerator string) {
 | 
					func AddGeneratorFlags(cmd *cobra.Command, defaultGenerator string) {
 | 
				
			||||||
	cmd.Flags().String("generator", defaultGenerator, "The name of the API generator to use.")
 | 
						cmd.Flags().String("generator", defaultGenerator, "The name of the API generator to use.")
 | 
				
			||||||
	cmd.Flags().Bool("dry-run", false, "If true, only print the object that would be sent, without sending it.")
 | 
						AddDryRunFlag(cmd)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func ReadConfigDataFromReader(reader io.Reader, source string) ([]byte, error) {
 | 
					func ReadConfigDataFromReader(reader io.Reader, source string) ([]byte, error) {
 | 
				
			||||||
@@ -433,6 +438,10 @@ func GetRecordFlag(cmd *cobra.Command) bool {
 | 
				
			|||||||
	return GetFlagBool(cmd, "record")
 | 
						return GetFlagBool(cmd, "record")
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func GetDryRunFlag(cmd *cobra.Command) bool {
 | 
				
			||||||
 | 
						return GetFlagBool(cmd, "dry-run")
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// RecordChangeCause annotate change-cause to input runtime object.
 | 
					// RecordChangeCause annotate change-cause to input runtime object.
 | 
				
			||||||
func RecordChangeCause(obj runtime.Object, changeCause string) error {
 | 
					func RecordChangeCause(obj runtime.Object, changeCause string) error {
 | 
				
			||||||
	accessor, err := meta.Accessor(obj)
 | 
						accessor, err := meta.Accessor(obj)
 | 
				
			||||||
@@ -528,3 +537,60 @@ func GetIncludeThirdPartyAPIs(cmd *cobra.Command) bool {
 | 
				
			|||||||
func AddInclude3rdPartyFlags(cmd *cobra.Command) {
 | 
					func AddInclude3rdPartyFlags(cmd *cobra.Command) {
 | 
				
			||||||
	cmd.Flags().Bool("include-extended-apis", true, "If true, include definitions of new APIs via calls to the API server. [default true]")
 | 
						cmd.Flags().Bool("include-extended-apis", true, "If true, include definitions of new APIs via calls to the API server. [default true]")
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// GetResourcesAndPairs retrieves resources and "KEY=VALUE or KEY-" pair args from given args
 | 
				
			||||||
 | 
					func GetResourcesAndPairs(args []string, pairType string) (resources []string, pairArgs []string, err error) {
 | 
				
			||||||
 | 
						foundPair := false
 | 
				
			||||||
 | 
						for _, s := range args {
 | 
				
			||||||
 | 
							nonResource := strings.Contains(s, "=") || strings.HasSuffix(s, "-")
 | 
				
			||||||
 | 
							switch {
 | 
				
			||||||
 | 
							case !foundPair && nonResource:
 | 
				
			||||||
 | 
								foundPair = true
 | 
				
			||||||
 | 
								fallthrough
 | 
				
			||||||
 | 
							case foundPair && nonResource:
 | 
				
			||||||
 | 
								pairArgs = append(pairArgs, s)
 | 
				
			||||||
 | 
							case !foundPair && !nonResource:
 | 
				
			||||||
 | 
								resources = append(resources, s)
 | 
				
			||||||
 | 
							case foundPair && !nonResource:
 | 
				
			||||||
 | 
								err = fmt.Errorf("all resources must be specified before %s changes: %s", pairType, s)
 | 
				
			||||||
 | 
								return
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// ParsePairs retrieves new and remove pairs (if supportRemove is true) from "KEY=VALUE or KEY-" pair args
 | 
				
			||||||
 | 
					func ParsePairs(pairArgs []string, pairType string, supportRemove bool) (newPairs map[string]string, removePairs []string, err error) {
 | 
				
			||||||
 | 
						newPairs = map[string]string{}
 | 
				
			||||||
 | 
						if supportRemove {
 | 
				
			||||||
 | 
							removePairs = []string{}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						var invalidBuf bytes.Buffer
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for _, pairArg := range pairArgs {
 | 
				
			||||||
 | 
							if strings.Index(pairArg, "=") != -1 {
 | 
				
			||||||
 | 
								parts := strings.SplitN(pairArg, "=", 2)
 | 
				
			||||||
 | 
								if len(parts) != 2 || len(parts[1]) == 0 {
 | 
				
			||||||
 | 
									if invalidBuf.Len() > 0 {
 | 
				
			||||||
 | 
										invalidBuf.WriteString(", ")
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									invalidBuf.WriteString(fmt.Sprintf(pairArg))
 | 
				
			||||||
 | 
								} else {
 | 
				
			||||||
 | 
									newPairs[parts[0]] = parts[1]
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							} else if supportRemove && strings.HasSuffix(pairArg, "-") {
 | 
				
			||||||
 | 
								removePairs = append(removePairs, pairArg[:len(pairArg)-1])
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								if invalidBuf.Len() > 0 {
 | 
				
			||||||
 | 
									invalidBuf.WriteString(", ")
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								invalidBuf.WriteString(fmt.Sprintf(pairArg))
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if invalidBuf.Len() > 0 {
 | 
				
			||||||
 | 
							err = fmt.Errorf("invalid %s format: %s", pairType, invalidBuf.String())
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user