mirror of
				https://github.com/optim-enterprises-bv/kubernetes.git
				synced 2025-11-04 12:18:16 +00:00 
			
		
		
		
	change kubeconfig loading order
This commit is contained in:
		@@ -747,12 +747,9 @@ _kubectl_config()
 | 
				
			|||||||
    flags_with_completion=()
 | 
					    flags_with_completion=()
 | 
				
			||||||
    flags_completion=()
 | 
					    flags_completion=()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    flags+=("--envvar")
 | 
					 | 
				
			||||||
    flags+=("--global")
 | 
					 | 
				
			||||||
    flags+=("--help")
 | 
					    flags+=("--help")
 | 
				
			||||||
    flags+=("-h")
 | 
					    flags+=("-h")
 | 
				
			||||||
    flags+=("--kubeconfig=")
 | 
					    flags+=("--kubeconfig=")
 | 
				
			||||||
    flags+=("--local")
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    must_have_one_flag=()
 | 
					    must_have_one_flag=()
 | 
				
			||||||
    must_have_one_noun=()
 | 
					    must_have_one_noun=()
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -84,15 +84,20 @@ If the contents of the kubernetes_auth file conflict with entries in .kubeconfig
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
## Loading and merging rules
 | 
					## Loading and merging rules
 | 
				
			||||||
The rules for loading and merging the .kubeconfig files are straightforward, but there are a lot of them.  The final config is built in this order:
 | 
					The rules for loading and merging the .kubeconfig files are straightforward, but there are a lot of them.  The final config is built in this order:
 | 
				
			||||||
  1.  Merge together the kubeconfig itself.  This is done with the following hierarchy and merge rules:
 | 
					  1.  Get the kubeconfig  from disk.  This is done with the following hierarchy and merge rules:
 | 
				
			||||||
      
 | 
					      
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      If the CommandLineLocation (the value of the `kubeconfig` command line option) is set, use this file only.  No merging.  Only one instance of this flag is allowed.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      Else, if EnvVarLocation (the value of $KUBECONFIG) is available, use it as a list of files that should be merged.  
 | 
				
			||||||
 | 
					      Merge files together based on the following rules.
 | 
				
			||||||
      Empty filenames are ignored.  Files with non-deserializable content produced errors.
 | 
					      Empty filenames are ignored.  Files with non-deserializable content produced errors.
 | 
				
			||||||
      The first file to set a particular value or map key wins and the value or map key is never changed.
 | 
					      The first file to set a particular value or map key wins and the value or map key is never changed.
 | 
				
			||||||
      This means that the first file to set CurrentContext will have its context preserved.  It also means that if two files specify a "red-user", only values from the first file's red-user are used.  Even non-conflicting entries from the second file's "red-user" are discarded.
 | 
					      This means that the first file to set CurrentContext will have its context preserved.  It also means that if two files specify a "red-user", only values from the first file's red-user are used.  Even non-conflicting entries from the second file's "red-user" are discarded.
 | 
				
			||||||
      1.  CommandLineLocation - the value of the `kubeconfig` command line option
 | 
					
 | 
				
			||||||
      1.  EnvVarLocation - the value of $KUBECONFIG
 | 
					
 | 
				
			||||||
      1.  CurrentDirectoryLocation - ``pwd``/.kubeconfig
 | 
					      Otherwise, use HomeDirectoryLocation (~/.kube/config) with no merging.
 | 
				
			||||||
      1.  HomeDirectoryLocation = ~/.kube/.kubeconfig
 | 
					 | 
				
			||||||
  1.  Determine the context to use based on the first hit in this chain
 | 
					  1.  Determine the context to use based on the first hit in this chain
 | 
				
			||||||
      1.  command line argument - the value of the `context` command line option
 | 
					      1.  command line argument - the value of the `context` command line option
 | 
				
			||||||
      1.  current-context from the merged kubeconfig file
 | 
					      1.  current-context from the merged kubeconfig file
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -66,4 +66,4 @@ kubectl
 | 
				
			|||||||
* [kubectl update](kubectl_update.md)	 - Update a resource by filename or stdin.
 | 
					* [kubectl update](kubectl_update.md)	 - Update a resource by filename or stdin.
 | 
				
			||||||
* [kubectl version](kubectl_version.md)	 - Print the client and server version information.
 | 
					* [kubectl version](kubectl_version.md)	 - Print the client and server version information.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
###### Auto generated by spf13/cobra at 2015-04-14 19:53:16.641789142 +0000 UTC
 | 
					###### Auto generated by spf13/cobra at 2015-04-16 17:04:37.392549632 +0000 UTC
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -50,4 +50,4 @@ kubectl api-versions
 | 
				
			|||||||
### SEE ALSO
 | 
					### SEE ALSO
 | 
				
			||||||
* [kubectl](kubectl.md)	 - kubectl controls the Kubernetes cluster manager
 | 
					* [kubectl](kubectl.md)	 - kubectl controls the Kubernetes cluster manager
 | 
				
			||||||
 | 
					
 | 
				
			||||||
###### Auto generated by spf13/cobra at 2015-04-14 19:53:16.641051929 +0000 UTC
 | 
					###### Auto generated by spf13/cobra at 2015-04-16 17:04:37.39227534 +0000 UTC
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -50,4 +50,4 @@ kubectl cluster-info
 | 
				
			|||||||
### SEE ALSO
 | 
					### SEE ALSO
 | 
				
			||||||
* [kubectl](kubectl.md)	 - kubectl controls the Kubernetes cluster manager
 | 
					* [kubectl](kubectl.md)	 - kubectl controls the Kubernetes cluster manager
 | 
				
			||||||
 | 
					
 | 
				
			||||||
###### Auto generated by spf13/cobra at 2015-04-14 19:53:16.640723377 +0000 UTC
 | 
					###### Auto generated by spf13/cobra at 2015-04-16 17:04:37.392162759 +0000 UTC
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -7,6 +7,12 @@ config modifies kubeconfig files
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
config modifies kubeconfig files using subcommands like "kubectl config set current-context my-context"
 | 
					config modifies kubeconfig files using subcommands like "kubectl config set current-context my-context"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The loading order follows these rules:
 | 
				
			||||||
 | 
					    1. If the --kubeconfig flag is set, then only that file is loaded.  The flag may only be set once and no merging takes place.
 | 
				
			||||||
 | 
					    2. If $KUBECONFIG environment variable is set, then it is used a list of paths (normal path delimitting rules for your system).  These paths are merged together.  When a value is modified, it is modified in the file that defines the stanza.  When a value is created, it is created in the first file that exists.  If no files in the chain exist, then it creates the last file in the list.
 | 
				
			||||||
 | 
					    3. Otherwise, ${HOME}/.kube/config is used and no merging takes place.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
kubectl config SUBCOMMAND
 | 
					kubectl config SUBCOMMAND
 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
@@ -14,11 +20,8 @@ kubectl config SUBCOMMAND
 | 
				
			|||||||
### Options
 | 
					### Options
 | 
				
			||||||
 | 
					
 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
      --envvar=false: use the kubeconfig from $KUBECONFIG
 | 
					 | 
				
			||||||
      --global=false: use the kubeconfig from /home/username/.kube/.kubeconfig
 | 
					 | 
				
			||||||
  -h, --help=false: help for config
 | 
					  -h, --help=false: help for config
 | 
				
			||||||
      --kubeconfig="": use a particular kubeconfig file
 | 
					      --kubeconfig="": use a particular kubeconfig file
 | 
				
			||||||
      --local=false: use the kubeconfig in the current directory
 | 
					 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
### Options inherrited from parent commands
 | 
					### Options inherrited from parent commands
 | 
				
			||||||
@@ -60,4 +63,4 @@ kubectl config SUBCOMMAND
 | 
				
			|||||||
* [kubectl config use-context](kubectl_config_use-context.md)	 - Sets the current-context in a kubeconfig file
 | 
					* [kubectl config use-context](kubectl_config_use-context.md)	 - Sets the current-context in a kubeconfig file
 | 
				
			||||||
* [kubectl config view](kubectl_config_view.md)	 - displays Merged kubeconfig settings or a specified kubeconfig file.
 | 
					* [kubectl config view](kubectl_config_view.md)	 - displays Merged kubeconfig settings or a specified kubeconfig file.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
###### Auto generated by spf13/cobra at 2015-04-14 19:53:16.640323684 +0000 UTC
 | 
					###### Auto generated by spf13/cobra at 2015-04-16 17:04:37.392043616 +0000 UTC
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -45,10 +45,7 @@ $ kubectl config set-cluster e2e --insecure-skip-tls-verify=true
 | 
				
			|||||||
      --client-key="": Path to a client key file for TLS.
 | 
					      --client-key="": Path to a client key file for TLS.
 | 
				
			||||||
      --cluster="": The name of the kubeconfig cluster to use
 | 
					      --cluster="": The name of the kubeconfig cluster to use
 | 
				
			||||||
      --context="": The name of the kubeconfig context to use
 | 
					      --context="": The name of the kubeconfig context to use
 | 
				
			||||||
      --envvar=false: use the kubeconfig from $KUBECONFIG
 | 
					 | 
				
			||||||
      --global=false: use the kubeconfig from /home/username/.kube/.kubeconfig
 | 
					 | 
				
			||||||
      --kubeconfig="": use a particular kubeconfig file
 | 
					      --kubeconfig="": use a particular kubeconfig file
 | 
				
			||||||
      --local=false: use the kubeconfig in the current directory
 | 
					 | 
				
			||||||
      --log_backtrace_at=:0: when logging hits line file:N, emit a stack trace
 | 
					      --log_backtrace_at=:0: when logging hits line file:N, emit a stack trace
 | 
				
			||||||
      --log_dir=: If non-empty, write log files in this directory
 | 
					      --log_dir=: If non-empty, write log files in this directory
 | 
				
			||||||
      --log_flush_frequency=5s: Maximum number of seconds between log flushes
 | 
					      --log_flush_frequency=5s: Maximum number of seconds between log flushes
 | 
				
			||||||
@@ -68,4 +65,4 @@ $ kubectl config set-cluster e2e --insecure-skip-tls-verify=true
 | 
				
			|||||||
### SEE ALSO
 | 
					### SEE ALSO
 | 
				
			||||||
* [kubectl config](kubectl_config.md)	 - config modifies kubeconfig files
 | 
					* [kubectl config](kubectl_config.md)	 - config modifies kubeconfig files
 | 
				
			||||||
 | 
					
 | 
				
			||||||
###### Auto generated by spf13/cobra at 2015-04-14 19:53:16.637680508 +0000 UTC
 | 
					###### Auto generated by spf13/cobra at 2015-04-16 17:04:37.39119629 +0000 UTC
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -38,11 +38,8 @@ $ kubectl config set-context gce --user=cluster-admin
 | 
				
			|||||||
      --client-certificate="": Path to a client key file for TLS.
 | 
					      --client-certificate="": Path to a client key file for TLS.
 | 
				
			||||||
      --client-key="": Path to a client key file for TLS.
 | 
					      --client-key="": Path to a client key file for TLS.
 | 
				
			||||||
      --context="": The name of the kubeconfig context to use
 | 
					      --context="": The name of the kubeconfig context to use
 | 
				
			||||||
      --envvar=false: use the kubeconfig from $KUBECONFIG
 | 
					 | 
				
			||||||
      --global=false: use the kubeconfig from /home/username/.kube/.kubeconfig
 | 
					 | 
				
			||||||
      --insecure-skip-tls-verify=false: If true, the server's certificate will not be checked for validity. This will make your HTTPS connections insecure.
 | 
					      --insecure-skip-tls-verify=false: If true, the server's certificate will not be checked for validity. This will make your HTTPS connections insecure.
 | 
				
			||||||
      --kubeconfig="": use a particular kubeconfig file
 | 
					      --kubeconfig="": use a particular kubeconfig file
 | 
				
			||||||
      --local=false: use the kubeconfig in the current directory
 | 
					 | 
				
			||||||
      --log_backtrace_at=:0: when logging hits line file:N, emit a stack trace
 | 
					      --log_backtrace_at=:0: when logging hits line file:N, emit a stack trace
 | 
				
			||||||
      --log_dir=: If non-empty, write log files in this directory
 | 
					      --log_dir=: If non-empty, write log files in this directory
 | 
				
			||||||
      --log_flush_frequency=5s: Maximum number of seconds between log flushes
 | 
					      --log_flush_frequency=5s: Maximum number of seconds between log flushes
 | 
				
			||||||
@@ -61,4 +58,4 @@ $ kubectl config set-context gce --user=cluster-admin
 | 
				
			|||||||
### SEE ALSO
 | 
					### SEE ALSO
 | 
				
			||||||
* [kubectl config](kubectl_config.md)	 - config modifies kubeconfig files
 | 
					* [kubectl config](kubectl_config.md)	 - config modifies kubeconfig files
 | 
				
			||||||
 | 
					
 | 
				
			||||||
###### Auto generated by spf13/cobra at 2015-04-14 19:53:16.638371771 +0000 UTC
 | 
					###### Auto generated by spf13/cobra at 2015-04-16 17:04:37.391488399 +0000 UTC
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -59,11 +59,8 @@ $ kubectl set-credentials cluster-admin --client-certificate=~/.kube/admin.crt -
 | 
				
			|||||||
      --certificate-authority="": Path to a cert. file for the certificate authority.
 | 
					      --certificate-authority="": Path to a cert. file for the certificate authority.
 | 
				
			||||||
      --cluster="": The name of the kubeconfig cluster to use
 | 
					      --cluster="": The name of the kubeconfig cluster to use
 | 
				
			||||||
      --context="": The name of the kubeconfig context to use
 | 
					      --context="": The name of the kubeconfig context to use
 | 
				
			||||||
      --envvar=false: use the kubeconfig from $KUBECONFIG
 | 
					 | 
				
			||||||
      --global=false: use the kubeconfig from /home/username/.kube/.kubeconfig
 | 
					 | 
				
			||||||
      --insecure-skip-tls-verify=false: If true, the server's certificate will not be checked for validity. This will make your HTTPS connections insecure.
 | 
					      --insecure-skip-tls-verify=false: If true, the server's certificate will not be checked for validity. This will make your HTTPS connections insecure.
 | 
				
			||||||
      --kubeconfig="": use a particular kubeconfig file
 | 
					      --kubeconfig="": use a particular kubeconfig file
 | 
				
			||||||
      --local=false: use the kubeconfig in the current directory
 | 
					 | 
				
			||||||
      --log_backtrace_at=:0: when logging hits line file:N, emit a stack trace
 | 
					      --log_backtrace_at=:0: when logging hits line file:N, emit a stack trace
 | 
				
			||||||
      --log_dir=: If non-empty, write log files in this directory
 | 
					      --log_dir=: If non-empty, write log files in this directory
 | 
				
			||||||
      --log_flush_frequency=5s: Maximum number of seconds between log flushes
 | 
					      --log_flush_frequency=5s: Maximum number of seconds between log flushes
 | 
				
			||||||
@@ -81,4 +78,4 @@ $ kubectl set-credentials cluster-admin --client-certificate=~/.kube/admin.crt -
 | 
				
			|||||||
### SEE ALSO
 | 
					### SEE ALSO
 | 
				
			||||||
* [kubectl config](kubectl_config.md)	 - config modifies kubeconfig files
 | 
					* [kubectl config](kubectl_config.md)	 - config modifies kubeconfig files
 | 
				
			||||||
 | 
					
 | 
				
			||||||
###### Auto generated by spf13/cobra at 2015-04-14 19:53:16.638019407 +0000 UTC
 | 
					###### Auto generated by spf13/cobra at 2015-04-16 17:04:37.391323192 +0000 UTC
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -30,11 +30,8 @@ kubectl config set PROPERTY_NAME PROPERTY_VALUE
 | 
				
			|||||||
      --client-key="": Path to a client key file for TLS.
 | 
					      --client-key="": Path to a client key file for TLS.
 | 
				
			||||||
      --cluster="": The name of the kubeconfig cluster to use
 | 
					      --cluster="": The name of the kubeconfig cluster to use
 | 
				
			||||||
      --context="": The name of the kubeconfig context to use
 | 
					      --context="": The name of the kubeconfig context to use
 | 
				
			||||||
      --envvar=false: use the kubeconfig from $KUBECONFIG
 | 
					 | 
				
			||||||
      --global=false: use the kubeconfig from /home/username/.kube/.kubeconfig
 | 
					 | 
				
			||||||
      --insecure-skip-tls-verify=false: If true, the server's certificate will not be checked for validity. This will make your HTTPS connections insecure.
 | 
					      --insecure-skip-tls-verify=false: If true, the server's certificate will not be checked for validity. This will make your HTTPS connections insecure.
 | 
				
			||||||
      --kubeconfig="": use a particular kubeconfig file
 | 
					      --kubeconfig="": use a particular kubeconfig file
 | 
				
			||||||
      --local=false: use the kubeconfig in the current directory
 | 
					 | 
				
			||||||
      --log_backtrace_at=:0: when logging hits line file:N, emit a stack trace
 | 
					      --log_backtrace_at=:0: when logging hits line file:N, emit a stack trace
 | 
				
			||||||
      --log_dir=: If non-empty, write log files in this directory
 | 
					      --log_dir=: If non-empty, write log files in this directory
 | 
				
			||||||
      --log_flush_frequency=5s: Maximum number of seconds between log flushes
 | 
					      --log_flush_frequency=5s: Maximum number of seconds between log flushes
 | 
				
			||||||
@@ -55,4 +52,4 @@ kubectl config set PROPERTY_NAME PROPERTY_VALUE
 | 
				
			|||||||
### SEE ALSO
 | 
					### SEE ALSO
 | 
				
			||||||
* [kubectl config](kubectl_config.md)	 - config modifies kubeconfig files
 | 
					* [kubectl config](kubectl_config.md)	 - config modifies kubeconfig files
 | 
				
			||||||
 | 
					
 | 
				
			||||||
###### Auto generated by spf13/cobra at 2015-04-14 19:53:16.638724317 +0000 UTC
 | 
					###### Auto generated by spf13/cobra at 2015-04-16 17:04:37.391618859 +0000 UTC
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -29,11 +29,8 @@ kubectl config unset PROPERTY_NAME
 | 
				
			|||||||
      --client-key="": Path to a client key file for TLS.
 | 
					      --client-key="": Path to a client key file for TLS.
 | 
				
			||||||
      --cluster="": The name of the kubeconfig cluster to use
 | 
					      --cluster="": The name of the kubeconfig cluster to use
 | 
				
			||||||
      --context="": The name of the kubeconfig context to use
 | 
					      --context="": The name of the kubeconfig context to use
 | 
				
			||||||
      --envvar=false: use the kubeconfig from $KUBECONFIG
 | 
					 | 
				
			||||||
      --global=false: use the kubeconfig from /home/username/.kube/.kubeconfig
 | 
					 | 
				
			||||||
      --insecure-skip-tls-verify=false: If true, the server's certificate will not be checked for validity. This will make your HTTPS connections insecure.
 | 
					      --insecure-skip-tls-verify=false: If true, the server's certificate will not be checked for validity. This will make your HTTPS connections insecure.
 | 
				
			||||||
      --kubeconfig="": use a particular kubeconfig file
 | 
					      --kubeconfig="": use a particular kubeconfig file
 | 
				
			||||||
      --local=false: use the kubeconfig in the current directory
 | 
					 | 
				
			||||||
      --log_backtrace_at=:0: when logging hits line file:N, emit a stack trace
 | 
					      --log_backtrace_at=:0: when logging hits line file:N, emit a stack trace
 | 
				
			||||||
      --log_dir=: If non-empty, write log files in this directory
 | 
					      --log_dir=: If non-empty, write log files in this directory
 | 
				
			||||||
      --log_flush_frequency=5s: Maximum number of seconds between log flushes
 | 
					      --log_flush_frequency=5s: Maximum number of seconds between log flushes
 | 
				
			||||||
@@ -54,4 +51,4 @@ kubectl config unset PROPERTY_NAME
 | 
				
			|||||||
### SEE ALSO
 | 
					### SEE ALSO
 | 
				
			||||||
* [kubectl config](kubectl_config.md)	 - config modifies kubeconfig files
 | 
					* [kubectl config](kubectl_config.md)	 - config modifies kubeconfig files
 | 
				
			||||||
 | 
					
 | 
				
			||||||
###### Auto generated by spf13/cobra at 2015-04-14 19:53:16.639325332 +0000 UTC
 | 
					###### Auto generated by spf13/cobra at 2015-04-16 17:04:37.391735806 +0000 UTC
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -28,11 +28,8 @@ kubectl config use-context CONTEXT_NAME
 | 
				
			|||||||
      --client-key="": Path to a client key file for TLS.
 | 
					      --client-key="": Path to a client key file for TLS.
 | 
				
			||||||
      --cluster="": The name of the kubeconfig cluster to use
 | 
					      --cluster="": The name of the kubeconfig cluster to use
 | 
				
			||||||
      --context="": The name of the kubeconfig context to use
 | 
					      --context="": The name of the kubeconfig context to use
 | 
				
			||||||
      --envvar=false: use the kubeconfig from $KUBECONFIG
 | 
					 | 
				
			||||||
      --global=false: use the kubeconfig from /home/username/.kube/.kubeconfig
 | 
					 | 
				
			||||||
      --insecure-skip-tls-verify=false: If true, the server's certificate will not be checked for validity. This will make your HTTPS connections insecure.
 | 
					      --insecure-skip-tls-verify=false: If true, the server's certificate will not be checked for validity. This will make your HTTPS connections insecure.
 | 
				
			||||||
      --kubeconfig="": use a particular kubeconfig file
 | 
					      --kubeconfig="": use a particular kubeconfig file
 | 
				
			||||||
      --local=false: use the kubeconfig in the current directory
 | 
					 | 
				
			||||||
      --log_backtrace_at=:0: when logging hits line file:N, emit a stack trace
 | 
					      --log_backtrace_at=:0: when logging hits line file:N, emit a stack trace
 | 
				
			||||||
      --log_dir=: If non-empty, write log files in this directory
 | 
					      --log_dir=: If non-empty, write log files in this directory
 | 
				
			||||||
      --log_flush_frequency=5s: Maximum number of seconds between log flushes
 | 
					      --log_flush_frequency=5s: Maximum number of seconds between log flushes
 | 
				
			||||||
@@ -53,4 +50,4 @@ kubectl config use-context CONTEXT_NAME
 | 
				
			|||||||
### SEE ALSO
 | 
					### SEE ALSO
 | 
				
			||||||
* [kubectl config](kubectl_config.md)	 - config modifies kubeconfig files
 | 
					* [kubectl config](kubectl_config.md)	 - config modifies kubeconfig files
 | 
				
			||||||
 | 
					
 | 
				
			||||||
###### Auto generated by spf13/cobra at 2015-04-14 19:53:16.639859272 +0000 UTC
 | 
					###### Auto generated by spf13/cobra at 2015-04-16 17:04:37.391848246 +0000 UTC
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -50,11 +50,8 @@ $ kubectl config view -o template --template='{{range .users}}{{ if eq .name "e2
 | 
				
			|||||||
      --client-key="": Path to a client key file for TLS.
 | 
					      --client-key="": Path to a client key file for TLS.
 | 
				
			||||||
      --cluster="": The name of the kubeconfig cluster to use
 | 
					      --cluster="": The name of the kubeconfig cluster to use
 | 
				
			||||||
      --context="": The name of the kubeconfig context to use
 | 
					      --context="": The name of the kubeconfig context to use
 | 
				
			||||||
      --envvar=false: use the kubeconfig from $KUBECONFIG
 | 
					 | 
				
			||||||
      --global=false: use the kubeconfig from /home/username/.kube/.kubeconfig
 | 
					 | 
				
			||||||
      --insecure-skip-tls-verify=false: If true, the server's certificate will not be checked for validity. This will make your HTTPS connections insecure.
 | 
					      --insecure-skip-tls-verify=false: If true, the server's certificate will not be checked for validity. This will make your HTTPS connections insecure.
 | 
				
			||||||
      --kubeconfig="": use a particular kubeconfig file
 | 
					      --kubeconfig="": use a particular kubeconfig file
 | 
				
			||||||
      --local=false: use the kubeconfig in the current directory
 | 
					 | 
				
			||||||
      --log_backtrace_at=:0: when logging hits line file:N, emit a stack trace
 | 
					      --log_backtrace_at=:0: when logging hits line file:N, emit a stack trace
 | 
				
			||||||
      --log_dir=: If non-empty, write log files in this directory
 | 
					      --log_dir=: If non-empty, write log files in this directory
 | 
				
			||||||
      --log_flush_frequency=5s: Maximum number of seconds between log flushes
 | 
					      --log_flush_frequency=5s: Maximum number of seconds between log flushes
 | 
				
			||||||
@@ -75,4 +72,4 @@ $ kubectl config view -o template --template='{{range .users}}{{ if eq .name "e2
 | 
				
			|||||||
### SEE ALSO
 | 
					### SEE ALSO
 | 
				
			||||||
* [kubectl config](kubectl_config.md)	 - config modifies kubeconfig files
 | 
					* [kubectl config](kubectl_config.md)	 - config modifies kubeconfig files
 | 
				
			||||||
 | 
					
 | 
				
			||||||
###### Auto generated by spf13/cobra at 2015-04-14 19:53:16.637312729 +0000 UTC
 | 
					###### Auto generated by spf13/cobra at 2015-04-16 17:04:37.391073075 +0000 UTC
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -63,4 +63,4 @@ $ cat pod.json | kubectl create -f -
 | 
				
			|||||||
### SEE ALSO
 | 
					### SEE ALSO
 | 
				
			||||||
* [kubectl](kubectl.md)	 - kubectl controls the Kubernetes cluster manager
 | 
					* [kubectl](kubectl.md)	 - kubectl controls the Kubernetes cluster manager
 | 
				
			||||||
 | 
					
 | 
				
			||||||
###### Auto generated by spf13/cobra at 2015-04-14 19:53:16.629142674 +0000 UTC
 | 
					###### Auto generated by spf13/cobra at 2015-04-16 17:04:37.388588064 +0000 UTC
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -81,4 +81,4 @@ $ kubectl delete pods --all
 | 
				
			|||||||
### SEE ALSO
 | 
					### SEE ALSO
 | 
				
			||||||
* [kubectl](kubectl.md)	 - kubectl controls the Kubernetes cluster manager
 | 
					* [kubectl](kubectl.md)	 - kubectl controls the Kubernetes cluster manager
 | 
				
			||||||
 | 
					
 | 
				
			||||||
###### Auto generated by spf13/cobra at 2015-04-14 19:53:16.630884641 +0000 UTC
 | 
					###### Auto generated by spf13/cobra at 2015-04-16 17:04:37.389412973 +0000 UTC
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -53,4 +53,4 @@ kubectl describe RESOURCE ID
 | 
				
			|||||||
### SEE ALSO
 | 
					### SEE ALSO
 | 
				
			||||||
* [kubectl](kubectl.md)	 - kubectl controls the Kubernetes cluster manager
 | 
					* [kubectl](kubectl.md)	 - kubectl controls the Kubernetes cluster manager
 | 
				
			||||||
 | 
					
 | 
				
			||||||
###### Auto generated by spf13/cobra at 2015-04-14 19:53:16.628735136 +0000 UTC
 | 
					###### Auto generated by spf13/cobra at 2015-04-16 17:04:37.388410556 +0000 UTC
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -64,4 +64,4 @@ $ kubectl exec -p 123456-7890 -c ruby-container -i -t -- bash -il
 | 
				
			|||||||
### SEE ALSO
 | 
					### SEE ALSO
 | 
				
			||||||
* [kubectl](kubectl.md)	 - kubectl controls the Kubernetes cluster manager
 | 
					* [kubectl](kubectl.md)	 - kubectl controls the Kubernetes cluster manager
 | 
				
			||||||
 | 
					
 | 
				
			||||||
###### Auto generated by spf13/cobra at 2015-04-14 19:53:16.632991694 +0000 UTC
 | 
					###### Auto generated by spf13/cobra at 2015-04-16 17:04:37.390127525 +0000 UTC
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -82,4 +82,4 @@ $ kubectl expose streamer --port=4100 --protocol=udp --service-name=video-stream
 | 
				
			|||||||
### SEE ALSO
 | 
					### SEE ALSO
 | 
				
			||||||
* [kubectl](kubectl.md)	 - kubectl controls the Kubernetes cluster manager
 | 
					* [kubectl](kubectl.md)	 - kubectl controls the Kubernetes cluster manager
 | 
				
			||||||
 | 
					
 | 
				
			||||||
###### Auto generated by spf13/cobra at 2015-04-14 19:53:16.636399596 +0000 UTC
 | 
					###### Auto generated by spf13/cobra at 2015-04-16 17:04:37.390792874 +0000 UTC
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -85,4 +85,4 @@ $ kubectl get rc/web service/frontend pods/web-pod-13je7
 | 
				
			|||||||
### SEE ALSO
 | 
					### SEE ALSO
 | 
				
			||||||
* [kubectl](kubectl.md)	 - kubectl controls the Kubernetes cluster manager
 | 
					* [kubectl](kubectl.md)	 - kubectl controls the Kubernetes cluster manager
 | 
				
			||||||
 | 
					
 | 
				
			||||||
###### Auto generated by spf13/cobra at 2015-04-14 19:53:16.620151758 +0000 UTC
 | 
					###### Auto generated by spf13/cobra at 2015-04-16 17:04:37.387483074 +0000 UTC
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -81,4 +81,4 @@ $ kubectl label pods foo bar-
 | 
				
			|||||||
### SEE ALSO
 | 
					### SEE ALSO
 | 
				
			||||||
* [kubectl](kubectl.md)	 - kubectl controls the Kubernetes cluster manager
 | 
					* [kubectl](kubectl.md)	 - kubectl controls the Kubernetes cluster manager
 | 
				
			||||||
 | 
					
 | 
				
			||||||
###### Auto generated by spf13/cobra at 2015-04-14 19:53:16.636842283 +0000 UTC
 | 
					###### Auto generated by spf13/cobra at 2015-04-16 17:04:37.390937166 +0000 UTC
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -62,4 +62,4 @@ $ kubectl log -f 123456-7890 ruby-container
 | 
				
			|||||||
### SEE ALSO
 | 
					### SEE ALSO
 | 
				
			||||||
* [kubectl](kubectl.md)	 - kubectl controls the Kubernetes cluster manager
 | 
					* [kubectl](kubectl.md)	 - kubectl controls the Kubernetes cluster manager
 | 
				
			||||||
 | 
					
 | 
				
			||||||
###### Auto generated by spf13/cobra at 2015-04-14 19:53:16.631637812 +0000 UTC
 | 
					###### Auto generated by spf13/cobra at 2015-04-16 17:04:37.389728881 +0000 UTC
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -53,4 +53,4 @@ kubectl namespace [namespace]
 | 
				
			|||||||
### SEE ALSO
 | 
					### SEE ALSO
 | 
				
			||||||
* [kubectl](kubectl.md)	 - kubectl controls the Kubernetes cluster manager
 | 
					* [kubectl](kubectl.md)	 - kubectl controls the Kubernetes cluster manager
 | 
				
			||||||
 | 
					
 | 
				
			||||||
###### Auto generated by spf13/cobra at 2015-04-14 19:53:16.63128386 +0000 UTC
 | 
					###### Auto generated by spf13/cobra at 2015-04-16 17:04:37.389609191 +0000 UTC
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -68,4 +68,4 @@ $ kubectl port-forward -p mypod 0:5000
 | 
				
			|||||||
### SEE ALSO
 | 
					### SEE ALSO
 | 
				
			||||||
* [kubectl](kubectl.md)	 - kubectl controls the Kubernetes cluster manager
 | 
					* [kubectl](kubectl.md)	 - kubectl controls the Kubernetes cluster manager
 | 
				
			||||||
 | 
					
 | 
				
			||||||
###### Auto generated by spf13/cobra at 2015-04-14 19:53:16.633423694 +0000 UTC
 | 
					###### Auto generated by spf13/cobra at 2015-04-16 17:04:37.390241417 +0000 UTC
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -65,4 +65,4 @@ $ kubectl proxy --api-prefix=k8s-api
 | 
				
			|||||||
### SEE ALSO
 | 
					### SEE ALSO
 | 
				
			||||||
* [kubectl](kubectl.md)	 - kubectl controls the Kubernetes cluster manager
 | 
					* [kubectl](kubectl.md)	 - kubectl controls the Kubernetes cluster manager
 | 
				
			||||||
 | 
					
 | 
				
			||||||
###### Auto generated by spf13/cobra at 2015-04-14 19:53:16.633829265 +0000 UTC
 | 
					###### Auto generated by spf13/cobra at 2015-04-16 17:04:37.390360738 +0000 UTC
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -68,4 +68,4 @@ $ kubectl resize --current-replicas=2 --replicas=3 replicationcontrollers foo
 | 
				
			|||||||
### SEE ALSO
 | 
					### SEE ALSO
 | 
				
			||||||
* [kubectl](kubectl.md)	 - kubectl controls the Kubernetes cluster manager
 | 
					* [kubectl](kubectl.md)	 - kubectl controls the Kubernetes cluster manager
 | 
				
			||||||
 | 
					
 | 
				
			||||||
###### Auto generated by spf13/cobra at 2015-04-14 19:53:16.632560634 +0000 UTC
 | 
					###### Auto generated by spf13/cobra at 2015-04-16 17:04:37.389989377 +0000 UTC
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -68,4 +68,4 @@ $ cat frontend-v2.json | kubectl rolling-update frontend-v1 -f -
 | 
				
			|||||||
### SEE ALSO
 | 
					### SEE ALSO
 | 
				
			||||||
* [kubectl](kubectl.md)	 - kubectl controls the Kubernetes cluster manager
 | 
					* [kubectl](kubectl.md)	 - kubectl controls the Kubernetes cluster manager
 | 
				
			||||||
 | 
					
 | 
				
			||||||
###### Auto generated by spf13/cobra at 2015-04-14 19:53:16.632023561 +0000 UTC
 | 
					###### Auto generated by spf13/cobra at 2015-04-16 17:04:37.38985117 +0000 UTC
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -78,4 +78,4 @@ $ kubectl run-container nginx --image=dockerfile/nginx --overrides='{ "apiVersio
 | 
				
			|||||||
### SEE ALSO
 | 
					### SEE ALSO
 | 
				
			||||||
* [kubectl](kubectl.md)	 - kubectl controls the Kubernetes cluster manager
 | 
					* [kubectl](kubectl.md)	 - kubectl controls the Kubernetes cluster manager
 | 
				
			||||||
 | 
					
 | 
				
			||||||
###### Auto generated by spf13/cobra at 2015-04-14 19:53:16.634391744 +0000 UTC
 | 
					###### Auto generated by spf13/cobra at 2015-04-16 17:04:37.390501802 +0000 UTC
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -72,4 +72,4 @@ $ kubectl stop -f path/to/resources
 | 
				
			|||||||
### SEE ALSO
 | 
					### SEE ALSO
 | 
				
			||||||
* [kubectl](kubectl.md)	 - kubectl controls the Kubernetes cluster manager
 | 
					* [kubectl](kubectl.md)	 - kubectl controls the Kubernetes cluster manager
 | 
				
			||||||
 | 
					
 | 
				
			||||||
###### Auto generated by spf13/cobra at 2015-04-14 19:53:16.635920945 +0000 UTC
 | 
					###### Auto generated by spf13/cobra at 2015-04-16 17:04:37.390631789 +0000 UTC
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -67,4 +67,4 @@ $ kubectl update pods my-pod --patch='{ "apiVersion": "v1beta1", "desiredState":
 | 
				
			|||||||
### SEE ALSO
 | 
					### SEE ALSO
 | 
				
			||||||
* [kubectl](kubectl.md)	 - kubectl controls the Kubernetes cluster manager
 | 
					* [kubectl](kubectl.md)	 - kubectl controls the Kubernetes cluster manager
 | 
				
			||||||
 | 
					
 | 
				
			||||||
###### Auto generated by spf13/cobra at 2015-04-14 19:53:16.630218109 +0000 UTC
 | 
					###### Auto generated by spf13/cobra at 2015-04-16 17:04:37.388743178 +0000 UTC
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -51,4 +51,4 @@ kubectl version
 | 
				
			|||||||
### SEE ALSO
 | 
					### SEE ALSO
 | 
				
			||||||
* [kubectl](kubectl.md)	 - kubectl controls the Kubernetes cluster manager
 | 
					* [kubectl](kubectl.md)	 - kubectl controls the Kubernetes cluster manager
 | 
				
			||||||
 | 
					
 | 
				
			||||||
###### Auto generated by spf13/cobra at 2015-04-14 19:53:16.641381587 +0000 UTC
 | 
					###### Auto generated by spf13/cobra at 2015-04-16 17:04:37.392395408 +0000 UTC
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -68,22 +68,10 @@ Specifying a name that already exists will merge new fields on top of existing v
 | 
				
			|||||||
\fB\-\-context\fP=""
 | 
					\fB\-\-context\fP=""
 | 
				
			||||||
    The name of the kubeconfig context to use
 | 
					    The name of the kubeconfig context to use
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.PP
 | 
					 | 
				
			||||||
\fB\-\-envvar\fP=false
 | 
					 | 
				
			||||||
    use the kubeconfig from $KUBECONFIG
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
.PP
 | 
					 | 
				
			||||||
\fB\-\-global\fP=false
 | 
					 | 
				
			||||||
    use the kubeconfig from /home/username/.kube/.kubeconfig
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
.PP
 | 
					.PP
 | 
				
			||||||
\fB\-\-kubeconfig\fP=""
 | 
					\fB\-\-kubeconfig\fP=""
 | 
				
			||||||
    use a particular kubeconfig file
 | 
					    use a particular kubeconfig file
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.PP
 | 
					 | 
				
			||||||
\fB\-\-local\fP=false
 | 
					 | 
				
			||||||
    use the kubeconfig in the current directory
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
.PP
 | 
					.PP
 | 
				
			||||||
\fB\-\-log\_backtrace\_at\fP=:0
 | 
					\fB\-\-log\_backtrace\_at\fP=:0
 | 
				
			||||||
    when logging hits line file:N, emit a stack trace
 | 
					    when logging hits line file:N, emit a stack trace
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -64,14 +64,6 @@ Specifying a name that already exists will merge new fields on top of existing v
 | 
				
			|||||||
\fB\-\-context\fP=""
 | 
					\fB\-\-context\fP=""
 | 
				
			||||||
    The name of the kubeconfig context to use
 | 
					    The name of the kubeconfig context to use
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.PP
 | 
					 | 
				
			||||||
\fB\-\-envvar\fP=false
 | 
					 | 
				
			||||||
    use the kubeconfig from $KUBECONFIG
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
.PP
 | 
					 | 
				
			||||||
\fB\-\-global\fP=false
 | 
					 | 
				
			||||||
    use the kubeconfig from /home/username/.kube/.kubeconfig
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
.PP
 | 
					.PP
 | 
				
			||||||
\fB\-\-insecure\-skip\-tls\-verify\fP=false
 | 
					\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.
 | 
					    If true, the server's certificate will not be checked for validity. This will make your HTTPS connections insecure.
 | 
				
			||||||
@@ -80,10 +72,6 @@ Specifying a name that already exists will merge new fields on top of existing v
 | 
				
			|||||||
\fB\-\-kubeconfig\fP=""
 | 
					\fB\-\-kubeconfig\fP=""
 | 
				
			||||||
    use a particular kubeconfig file
 | 
					    use a particular kubeconfig file
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.PP
 | 
					 | 
				
			||||||
\fB\-\-local\fP=false
 | 
					 | 
				
			||||||
    use the kubeconfig in the current directory
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
.PP
 | 
					.PP
 | 
				
			||||||
\fB\-\-log\_backtrace\_at\fP=:0
 | 
					\fB\-\-log\_backtrace\_at\fP=:0
 | 
				
			||||||
    when logging hits line file:N, emit a stack trace
 | 
					    when logging hits line file:N, emit a stack trace
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -87,14 +87,6 @@ Bearer token and basic auth are mutually exclusive.
 | 
				
			|||||||
\fB\-\-context\fP=""
 | 
					\fB\-\-context\fP=""
 | 
				
			||||||
    The name of the kubeconfig context to use
 | 
					    The name of the kubeconfig context to use
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.PP
 | 
					 | 
				
			||||||
\fB\-\-envvar\fP=false
 | 
					 | 
				
			||||||
    use the kubeconfig from $KUBECONFIG
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
.PP
 | 
					 | 
				
			||||||
\fB\-\-global\fP=false
 | 
					 | 
				
			||||||
    use the kubeconfig from /home/username/.kube/.kubeconfig
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
.PP
 | 
					.PP
 | 
				
			||||||
\fB\-\-insecure\-skip\-tls\-verify\fP=false
 | 
					\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.
 | 
					    If true, the server's certificate will not be checked for validity. This will make your HTTPS connections insecure.
 | 
				
			||||||
@@ -103,10 +95,6 @@ Bearer token and basic auth are mutually exclusive.
 | 
				
			|||||||
\fB\-\-kubeconfig\fP=""
 | 
					\fB\-\-kubeconfig\fP=""
 | 
				
			||||||
    use a particular kubeconfig file
 | 
					    use a particular kubeconfig file
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.PP
 | 
					 | 
				
			||||||
\fB\-\-local\fP=false
 | 
					 | 
				
			||||||
    use the kubeconfig in the current directory
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
.PP
 | 
					.PP
 | 
				
			||||||
\fB\-\-log\_backtrace\_at\fP=:0
 | 
					\fB\-\-log\_backtrace\_at\fP=:0
 | 
				
			||||||
    when logging hits line file:N, emit a stack trace
 | 
					    when logging hits line file:N, emit a stack trace
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -57,14 +57,6 @@ PROPERTY\_VALUE is the new value you wish to set.
 | 
				
			|||||||
\fB\-\-context\fP=""
 | 
					\fB\-\-context\fP=""
 | 
				
			||||||
    The name of the kubeconfig context to use
 | 
					    The name of the kubeconfig context to use
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.PP
 | 
					 | 
				
			||||||
\fB\-\-envvar\fP=false
 | 
					 | 
				
			||||||
    use the kubeconfig from $KUBECONFIG
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
.PP
 | 
					 | 
				
			||||||
\fB\-\-global\fP=false
 | 
					 | 
				
			||||||
    use the kubeconfig from /home/username/.kube/.kubeconfig
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
.PP
 | 
					.PP
 | 
				
			||||||
\fB\-\-insecure\-skip\-tls\-verify\fP=false
 | 
					\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.
 | 
					    If true, the server's certificate will not be checked for validity. This will make your HTTPS connections insecure.
 | 
				
			||||||
@@ -73,10 +65,6 @@ PROPERTY\_VALUE is the new value you wish to set.
 | 
				
			|||||||
\fB\-\-kubeconfig\fP=""
 | 
					\fB\-\-kubeconfig\fP=""
 | 
				
			||||||
    use a particular kubeconfig file
 | 
					    use a particular kubeconfig file
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.PP
 | 
					 | 
				
			||||||
\fB\-\-local\fP=false
 | 
					 | 
				
			||||||
    use the kubeconfig in the current directory
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
.PP
 | 
					.PP
 | 
				
			||||||
\fB\-\-log\_backtrace\_at\fP=:0
 | 
					\fB\-\-log\_backtrace\_at\fP=:0
 | 
				
			||||||
    when logging hits line file:N, emit a stack trace
 | 
					    when logging hits line file:N, emit a stack trace
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -56,14 +56,6 @@ PROPERTY\_NAME is a dot delimited name where each token represents either a attr
 | 
				
			|||||||
\fB\-\-context\fP=""
 | 
					\fB\-\-context\fP=""
 | 
				
			||||||
    The name of the kubeconfig context to use
 | 
					    The name of the kubeconfig context to use
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.PP
 | 
					 | 
				
			||||||
\fB\-\-envvar\fP=false
 | 
					 | 
				
			||||||
    use the kubeconfig from $KUBECONFIG
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
.PP
 | 
					 | 
				
			||||||
\fB\-\-global\fP=false
 | 
					 | 
				
			||||||
    use the kubeconfig from /home/username/.kube/.kubeconfig
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
.PP
 | 
					.PP
 | 
				
			||||||
\fB\-\-insecure\-skip\-tls\-verify\fP=false
 | 
					\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.
 | 
					    If true, the server's certificate will not be checked for validity. This will make your HTTPS connections insecure.
 | 
				
			||||||
@@ -72,10 +64,6 @@ PROPERTY\_NAME is a dot delimited name where each token represents either a attr
 | 
				
			|||||||
\fB\-\-kubeconfig\fP=""
 | 
					\fB\-\-kubeconfig\fP=""
 | 
				
			||||||
    use a particular kubeconfig file
 | 
					    use a particular kubeconfig file
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.PP
 | 
					 | 
				
			||||||
\fB\-\-local\fP=false
 | 
					 | 
				
			||||||
    use the kubeconfig in the current directory
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
.PP
 | 
					.PP
 | 
				
			||||||
\fB\-\-log\_backtrace\_at\fP=:0
 | 
					\fB\-\-log\_backtrace\_at\fP=:0
 | 
				
			||||||
    when logging hits line file:N, emit a stack trace
 | 
					    when logging hits line file:N, emit a stack trace
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -55,14 +55,6 @@ Sets the current\-context in a kubeconfig file
 | 
				
			|||||||
\fB\-\-context\fP=""
 | 
					\fB\-\-context\fP=""
 | 
				
			||||||
    The name of the kubeconfig context to use
 | 
					    The name of the kubeconfig context to use
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.PP
 | 
					 | 
				
			||||||
\fB\-\-envvar\fP=false
 | 
					 | 
				
			||||||
    use the kubeconfig from $KUBECONFIG
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
.PP
 | 
					 | 
				
			||||||
\fB\-\-global\fP=false
 | 
					 | 
				
			||||||
    use the kubeconfig from /home/username/.kube/.kubeconfig
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
.PP
 | 
					.PP
 | 
				
			||||||
\fB\-\-insecure\-skip\-tls\-verify\fP=false
 | 
					\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.
 | 
					    If true, the server's certificate will not be checked for validity. This will make your HTTPS connections insecure.
 | 
				
			||||||
@@ -71,10 +63,6 @@ Sets the current\-context in a kubeconfig file
 | 
				
			|||||||
\fB\-\-kubeconfig\fP=""
 | 
					\fB\-\-kubeconfig\fP=""
 | 
				
			||||||
    use a particular kubeconfig file
 | 
					    use a particular kubeconfig file
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.PP
 | 
					 | 
				
			||||||
\fB\-\-local\fP=false
 | 
					 | 
				
			||||||
    use the kubeconfig in the current directory
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
.PP
 | 
					.PP
 | 
				
			||||||
\fB\-\-log\_backtrace\_at\fP=:0
 | 
					\fB\-\-log\_backtrace\_at\fP=:0
 | 
				
			||||||
    when logging hits line file:N, emit a stack trace
 | 
					    when logging hits line file:N, emit a stack trace
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -87,14 +87,6 @@ You can use \-\-output=template \-\-template=TEMPLATE to extract specific values
 | 
				
			|||||||
\fB\-\-context\fP=""
 | 
					\fB\-\-context\fP=""
 | 
				
			||||||
    The name of the kubeconfig context to use
 | 
					    The name of the kubeconfig context to use
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.PP
 | 
					 | 
				
			||||||
\fB\-\-envvar\fP=false
 | 
					 | 
				
			||||||
    use the kubeconfig from $KUBECONFIG
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
.PP
 | 
					 | 
				
			||||||
\fB\-\-global\fP=false
 | 
					 | 
				
			||||||
    use the kubeconfig from /home/username/.kube/.kubeconfig
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
.PP
 | 
					.PP
 | 
				
			||||||
\fB\-\-insecure\-skip\-tls\-verify\fP=false
 | 
					\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.
 | 
					    If true, the server's certificate will not be checked for validity. This will make your HTTPS connections insecure.
 | 
				
			||||||
@@ -103,10 +95,6 @@ You can use \-\-output=template \-\-template=TEMPLATE to extract specific values
 | 
				
			|||||||
\fB\-\-kubeconfig\fP=""
 | 
					\fB\-\-kubeconfig\fP=""
 | 
				
			||||||
    use a particular kubeconfig file
 | 
					    use a particular kubeconfig file
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.PP
 | 
					 | 
				
			||||||
\fB\-\-local\fP=false
 | 
					 | 
				
			||||||
    use the kubeconfig in the current directory
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
.PP
 | 
					.PP
 | 
				
			||||||
\fB\-\-log\_backtrace\_at\fP=:0
 | 
					\fB\-\-log\_backtrace\_at\fP=:0
 | 
				
			||||||
    when logging hits line file:N, emit a stack trace
 | 
					    when logging hits line file:N, emit a stack trace
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -15,16 +15,14 @@ kubectl config \- config modifies kubeconfig files
 | 
				
			|||||||
.PP
 | 
					.PP
 | 
				
			||||||
config modifies kubeconfig files using subcommands like "kubectl config set current\-context my\-context"
 | 
					config modifies kubeconfig files using subcommands like "kubectl config set current\-context my\-context"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.PP
 | 
				
			||||||
 | 
					The loading order follows these rules:
 | 
				
			||||||
 | 
					    1. If the \-\-kubeconfig flag is set, then only that file is loaded.  The flag may only be set once and no merging takes place.
 | 
				
			||||||
 | 
					    2. If $KUBECONFIG environment variable is set, then it is used a list of paths (normal path delimitting rules for your system).  These paths are merged together.  When a value is modified, it is modified in the file that defines the stanza.  When a value is created, it is created in the first file that exists.  If no files in the chain exist, then it creates the last file in the list.
 | 
				
			||||||
 | 
					    3. Otherwise, $\{HOME\}/.kube/config is used and no merging takes place.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.SH OPTIONS
 | 
					.SH OPTIONS
 | 
				
			||||||
.PP
 | 
					 | 
				
			||||||
\fB\-\-envvar\fP=false
 | 
					 | 
				
			||||||
    use the kubeconfig from $KUBECONFIG
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
.PP
 | 
					 | 
				
			||||||
\fB\-\-global\fP=false
 | 
					 | 
				
			||||||
    use the kubeconfig from /home/username/.kube/.kubeconfig
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
.PP
 | 
					.PP
 | 
				
			||||||
\fB\-h\fP, \fB\-\-help\fP=false
 | 
					\fB\-h\fP, \fB\-\-help\fP=false
 | 
				
			||||||
    help for config
 | 
					    help for config
 | 
				
			||||||
@@ -33,10 +31,6 @@ config modifies kubeconfig files using subcommands like "kubectl config set curr
 | 
				
			|||||||
\fB\-\-kubeconfig\fP=""
 | 
					\fB\-\-kubeconfig\fP=""
 | 
				
			||||||
    use a particular kubeconfig file
 | 
					    use a particular kubeconfig file
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.PP
 | 
					 | 
				
			||||||
\fB\-\-local\fP=false
 | 
					 | 
				
			||||||
    use the kubeconfig in the current directory
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
.SH OPTIONS INHERITED FROM PARENT COMMANDS
 | 
					.SH OPTIONS INHERITED FROM PARENT COMMANDS
 | 
				
			||||||
.PP
 | 
					.PP
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -18,8 +18,10 @@ package clientcmd
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
	"fmt"
 | 
						"fmt"
 | 
				
			||||||
 | 
						"io"
 | 
				
			||||||
	"io/ioutil"
 | 
						"io/ioutil"
 | 
				
			||||||
	"os"
 | 
						"os"
 | 
				
			||||||
 | 
						"path"
 | 
				
			||||||
	"path/filepath"
 | 
						"path/filepath"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"github.com/ghodss/yaml"
 | 
						"github.com/ghodss/yaml"
 | 
				
			||||||
@@ -33,22 +35,24 @@ import (
 | 
				
			|||||||
const (
 | 
					const (
 | 
				
			||||||
	RecommendedConfigPathFlag   = "kubeconfig"
 | 
						RecommendedConfigPathFlag   = "kubeconfig"
 | 
				
			||||||
	RecommendedConfigPathEnvVar = "KUBECONFIG"
 | 
						RecommendedConfigPathEnvVar = "KUBECONFIG"
 | 
				
			||||||
 | 
						RecommendedHomeFileName     = "/.kube/config"
 | 
				
			||||||
	DefaultEnvVarIndex     = 0
 | 
					 | 
				
			||||||
	DefaultCurrentDirIndex = 1
 | 
					 | 
				
			||||||
	DefaultHomeDirIndex    = 2
 | 
					 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var OldRecommendedHomeFile = path.Join(os.Getenv("HOME"), "/.kube/.kubeconfig")
 | 
				
			||||||
 | 
					var RecommendedHomeFile = path.Join(os.Getenv("HOME"), RecommendedHomeFileName)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// ClientConfigLoadingRules is an ExplicitPath and string slice of specific locations that are used for merging together a Config
 | 
					// ClientConfigLoadingRules is an ExplicitPath and string slice of specific locations that are used for merging together a Config
 | 
				
			||||||
// Callers can put the chain together however they want, but we'd recommend:
 | 
					// Callers can put the chain together however they want, but we'd recommend:
 | 
				
			||||||
// [0] = EnvVarPath
 | 
					// EnvVarPathFiles if set (a list of files if set) OR the HomeDirectoryPath
 | 
				
			||||||
// [1] = CurrentDirectoryPath
 | 
					 | 
				
			||||||
// [2] = HomeDirectoryPath
 | 
					 | 
				
			||||||
// ExplicitPath is special, because if a user specifically requests a certain file be used and error is reported if thie file is not present
 | 
					// ExplicitPath is special, because if a user specifically requests a certain file be used and error is reported if thie file is not present
 | 
				
			||||||
type ClientConfigLoadingRules struct {
 | 
					type ClientConfigLoadingRules struct {
 | 
				
			||||||
	ExplicitPath string
 | 
						ExplicitPath string
 | 
				
			||||||
	Precedence   []string
 | 
						Precedence   []string
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// MigrationRules is a map of destination files to source files.  If a destination file is not present, then the source file is checked.
 | 
				
			||||||
 | 
						// If the source file is present, then it is copied to the destination file BEFORE any further loading happens.
 | 
				
			||||||
 | 
						MigrationRules map[string]string
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// DoNotResolvePaths indicates whether or not to resolve paths with respect to the originating files.  This is phrased as a negative so
 | 
						// DoNotResolvePaths indicates whether or not to resolve paths with respect to the originating files.  This is phrased as a negative so
 | 
				
			||||||
	// that a default object that doesn't set this will usually get the behavior it wants.
 | 
						// that a default object that doesn't set this will usually get the behavior it wants.
 | 
				
			||||||
	DoNotResolvePaths bool
 | 
						DoNotResolvePaths bool
 | 
				
			||||||
@@ -57,14 +61,29 @@ type ClientConfigLoadingRules struct {
 | 
				
			|||||||
// NewDefaultClientConfigLoadingRules returns a ClientConfigLoadingRules object with default fields filled in.  You are not required to
 | 
					// NewDefaultClientConfigLoadingRules returns a ClientConfigLoadingRules object with default fields filled in.  You are not required to
 | 
				
			||||||
// use this constructor
 | 
					// use this constructor
 | 
				
			||||||
func NewDefaultClientConfigLoadingRules() *ClientConfigLoadingRules {
 | 
					func NewDefaultClientConfigLoadingRules() *ClientConfigLoadingRules {
 | 
				
			||||||
 | 
						chain := []string{}
 | 
				
			||||||
 | 
						migrationRules := map[string]string{}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						envVarFiles := os.Getenv(RecommendedConfigPathEnvVar)
 | 
				
			||||||
 | 
						if len(envVarFiles) != 0 {
 | 
				
			||||||
 | 
							chain = append(chain, filepath.SplitList(envVarFiles)...)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							chain = append(chain, RecommendedHomeFile)
 | 
				
			||||||
 | 
							migrationRules[RecommendedHomeFile] = OldRecommendedHomeFile
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return &ClientConfigLoadingRules{
 | 
						return &ClientConfigLoadingRules{
 | 
				
			||||||
		Precedence: []string{os.Getenv(RecommendedConfigPathEnvVar), ".kubeconfig", os.Getenv("HOME") + "/.kube/.kubeconfig"},
 | 
							Precedence:     chain,
 | 
				
			||||||
 | 
							MigrationRules: migrationRules,
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Load takes the loading rules and merges together a Config object based on following order.
 | 
					// Load starts by running the MigrationRules and then
 | 
				
			||||||
//   1.  ExplicitPath
 | 
					// takes the loading rules and returns a Config object based on following rules.
 | 
				
			||||||
//   2.  Precedence slice
 | 
					//   if the ExplicitPath, return the unmerged explicit file
 | 
				
			||||||
 | 
					//   Otherwise, return a merged config based on the Precedence slice
 | 
				
			||||||
// A missing ExplicitPath file produces an error. Empty filenames or other missing files are ignored.
 | 
					// A missing ExplicitPath file produces an error. Empty filenames or other missing files are ignored.
 | 
				
			||||||
// Read errors or files with non-deserializable content produce errors.
 | 
					// Read errors or files with non-deserializable content produce errors.
 | 
				
			||||||
// The first file to set a particular map key wins and map key's value is never changed.
 | 
					// The first file to set a particular map key wins and map key's value is never changed.
 | 
				
			||||||
@@ -75,18 +94,26 @@ func NewDefaultClientConfigLoadingRules() *ClientConfigLoadingRules {
 | 
				
			|||||||
// Relative paths inside of the .kubeconfig files are resolved against the .kubeconfig file's parent folder
 | 
					// Relative paths inside of the .kubeconfig files are resolved against the .kubeconfig file's parent folder
 | 
				
			||||||
// and only absolute file paths are returned.
 | 
					// and only absolute file paths are returned.
 | 
				
			||||||
func (rules *ClientConfigLoadingRules) Load() (*clientcmdapi.Config, error) {
 | 
					func (rules *ClientConfigLoadingRules) Load() (*clientcmdapi.Config, error) {
 | 
				
			||||||
 | 
						if err := rules.Migrate(); err != nil {
 | 
				
			||||||
 | 
							return nil, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	errlist := []error{}
 | 
						errlist := []error{}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						kubeConfigFiles := []string{}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Make sure a file we were explicitly told to use exists
 | 
						// Make sure a file we were explicitly told to use exists
 | 
				
			||||||
	if len(rules.ExplicitPath) > 0 {
 | 
						if len(rules.ExplicitPath) > 0 {
 | 
				
			||||||
		if _, err := os.Stat(rules.ExplicitPath); os.IsNotExist(err) {
 | 
							if _, err := os.Stat(rules.ExplicitPath); os.IsNotExist(err) {
 | 
				
			||||||
			errlist = append(errlist, fmt.Errorf("The config file %v does not exist", rules.ExplicitPath))
 | 
								return nil, err
 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
							kubeConfigFiles = append(kubeConfigFiles, rules.ExplicitPath)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	kubeConfigFiles := []string{rules.ExplicitPath}
 | 
						} else {
 | 
				
			||||||
		kubeConfigFiles = append(kubeConfigFiles, rules.Precedence...)
 | 
							kubeConfigFiles = append(kubeConfigFiles, rules.Precedence...)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// first merge all of our maps
 | 
						// first merge all of our maps
 | 
				
			||||||
	mapConfig := clientcmdapi.NewConfig()
 | 
						mapConfig := clientcmdapi.NewConfig()
 | 
				
			||||||
	for _, file := range kubeConfigFiles {
 | 
						for _, file := range kubeConfigFiles {
 | 
				
			||||||
@@ -120,6 +147,53 @@ func (rules *ClientConfigLoadingRules) Load() (*clientcmdapi.Config, error) {
 | 
				
			|||||||
	return config, errors.NewAggregate(errlist)
 | 
						return config, errors.NewAggregate(errlist)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Migrate uses the MigrationRules map.  If a destination file is not present, then the source file is checked.
 | 
				
			||||||
 | 
					// If the source file is present, then it is copied to the destination file BEFORE any further loading happens.
 | 
				
			||||||
 | 
					func (rules *ClientConfigLoadingRules) Migrate() error {
 | 
				
			||||||
 | 
						if rules.MigrationRules == nil {
 | 
				
			||||||
 | 
							return nil
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for destination, source := range rules.MigrationRules {
 | 
				
			||||||
 | 
							if _, err := os.Stat(destination); err == nil {
 | 
				
			||||||
 | 
								// if the destination already exists, do nothing
 | 
				
			||||||
 | 
								continue
 | 
				
			||||||
 | 
							} else if !os.IsNotExist(err) {
 | 
				
			||||||
 | 
								// if we had an error other than non-existence, fail
 | 
				
			||||||
 | 
								return err
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if sourceInfo, err := os.Stat(source); err != nil {
 | 
				
			||||||
 | 
								if os.IsNotExist(err) {
 | 
				
			||||||
 | 
									// if the source file doesn't exist, there's no work to do.
 | 
				
			||||||
 | 
									continue
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								// if we had an error other than non-existence, fail
 | 
				
			||||||
 | 
								return err
 | 
				
			||||||
 | 
							} else if sourceInfo.IsDir() {
 | 
				
			||||||
 | 
								return fmt.Errorf("cannot migrate %v to %v because it is a directory", source, destination)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							in, err := os.Open(source)
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								return err
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							defer in.Close()
 | 
				
			||||||
 | 
							out, err := os.Create(destination)
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								return err
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							defer out.Close()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if _, err = io.Copy(out, in); err != nil {
 | 
				
			||||||
 | 
								return err
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func mergeConfigWithFile(startingConfig *clientcmdapi.Config, filename string) error {
 | 
					func mergeConfigWithFile(startingConfig *clientcmdapi.Config, filename string) error {
 | 
				
			||||||
	if len(filename) == 0 {
 | 
						if len(filename) == 0 {
 | 
				
			||||||
		// no work to do
 | 
							// no work to do
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -22,6 +22,7 @@ import (
 | 
				
			|||||||
	"os"
 | 
						"os"
 | 
				
			||||||
	"path"
 | 
						"path"
 | 
				
			||||||
	"path/filepath"
 | 
						"path/filepath"
 | 
				
			||||||
 | 
						"reflect"
 | 
				
			||||||
	"strings"
 | 
						"strings"
 | 
				
			||||||
	"testing"
 | 
						"testing"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -209,8 +210,7 @@ func TestResolveRelativePaths(t *testing.T) {
 | 
				
			|||||||
	WriteToFile(pathResolutionConfig2, configFile2)
 | 
						WriteToFile(pathResolutionConfig2, configFile2)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	loadingRules := ClientConfigLoadingRules{
 | 
						loadingRules := ClientConfigLoadingRules{
 | 
				
			||||||
		ExplicitPath: configFile1,
 | 
							Precedence: []string{configFile1, configFile2},
 | 
				
			||||||
		Precedence:   []string{configFile2},
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	mergedConfig, err := loadingRules.Load()
 | 
						mergedConfig, err := loadingRules.Load()
 | 
				
			||||||
@@ -274,7 +274,86 @@ func TestResolveRelativePaths(t *testing.T) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func ExampleMergingSomeWithConflict() {
 | 
					func TestMigratingFile(t *testing.T) {
 | 
				
			||||||
 | 
						sourceFile, _ := ioutil.TempFile("", "")
 | 
				
			||||||
 | 
						defer os.Remove(sourceFile.Name())
 | 
				
			||||||
 | 
						destinationFile, _ := ioutil.TempFile("", "")
 | 
				
			||||||
 | 
						// delete the file so that we'll write to it
 | 
				
			||||||
 | 
						os.Remove(destinationFile.Name())
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						WriteToFile(testConfigAlfa, sourceFile.Name())
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						loadingRules := ClientConfigLoadingRules{
 | 
				
			||||||
 | 
							MigrationRules: map[string]string{destinationFile.Name(): sourceFile.Name()},
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if _, err := loadingRules.Load(); err != nil {
 | 
				
			||||||
 | 
							t.Errorf("unexpected error %v", err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// the load should have recreated this file
 | 
				
			||||||
 | 
						defer os.Remove(destinationFile.Name())
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						sourceContent, err := ioutil.ReadFile(sourceFile.Name())
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							t.Errorf("unexpected error %v", err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						destinationContent, err := ioutil.ReadFile(destinationFile.Name())
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							t.Errorf("unexpected error %v", err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if !reflect.DeepEqual(sourceContent, destinationContent) {
 | 
				
			||||||
 | 
							t.Errorf("source and destination do not match")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TestMigratingFileLeaveExistingFileAlone(t *testing.T) {
 | 
				
			||||||
 | 
						sourceFile, _ := ioutil.TempFile("", "")
 | 
				
			||||||
 | 
						defer os.Remove(sourceFile.Name())
 | 
				
			||||||
 | 
						destinationFile, _ := ioutil.TempFile("", "")
 | 
				
			||||||
 | 
						defer os.Remove(destinationFile.Name())
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						WriteToFile(testConfigAlfa, sourceFile.Name())
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						loadingRules := ClientConfigLoadingRules{
 | 
				
			||||||
 | 
							MigrationRules: map[string]string{destinationFile.Name(): sourceFile.Name()},
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if _, err := loadingRules.Load(); err != nil {
 | 
				
			||||||
 | 
							t.Errorf("unexpected error %v", err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						destinationContent, err := ioutil.ReadFile(destinationFile.Name())
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							t.Errorf("unexpected error %v", err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if len(destinationContent) > 0 {
 | 
				
			||||||
 | 
							t.Errorf("destination should not have been touched")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TestMigratingFileSourceMissingSkip(t *testing.T) {
 | 
				
			||||||
 | 
						sourceFilename := "some-missing-file"
 | 
				
			||||||
 | 
						destinationFile, _ := ioutil.TempFile("", "")
 | 
				
			||||||
 | 
						// delete the file so that we'll write to it
 | 
				
			||||||
 | 
						os.Remove(destinationFile.Name())
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						loadingRules := ClientConfigLoadingRules{
 | 
				
			||||||
 | 
							MigrationRules: map[string]string{destinationFile.Name(): sourceFilename},
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if _, err := loadingRules.Load(); err != nil {
 | 
				
			||||||
 | 
							t.Errorf("unexpected error %v", err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if _, err := os.Stat(destinationFile.Name()); !os.IsNotExist(err) {
 | 
				
			||||||
 | 
							t.Errorf("destination should not exist")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func ExampleNoMergingOnExplicitPaths() {
 | 
				
			||||||
	commandLineFile, _ := ioutil.TempFile("", "")
 | 
						commandLineFile, _ := ioutil.TempFile("", "")
 | 
				
			||||||
	defer os.Remove(commandLineFile.Name())
 | 
						defer os.Remove(commandLineFile.Name())
 | 
				
			||||||
	envVarFile, _ := ioutil.TempFile("", "")
 | 
						envVarFile, _ := ioutil.TempFile("", "")
 | 
				
			||||||
@@ -299,6 +378,52 @@ func ExampleMergingSomeWithConflict() {
 | 
				
			|||||||
		fmt.Printf("Unexpected error: %v", err)
 | 
							fmt.Printf("Unexpected error: %v", err)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						fmt.Printf("%v", string(output))
 | 
				
			||||||
 | 
						// Output:
 | 
				
			||||||
 | 
						// apiVersion: v1
 | 
				
			||||||
 | 
						// clusters:
 | 
				
			||||||
 | 
						// - cluster:
 | 
				
			||||||
 | 
						//     server: http://cow.org:8080
 | 
				
			||||||
 | 
						//   name: cow-cluster
 | 
				
			||||||
 | 
						// contexts:
 | 
				
			||||||
 | 
						// - context:
 | 
				
			||||||
 | 
						//     cluster: cow-cluster
 | 
				
			||||||
 | 
						//     namespace: hammer-ns
 | 
				
			||||||
 | 
						//     user: red-user
 | 
				
			||||||
 | 
						//   name: federal-context
 | 
				
			||||||
 | 
						// current-context: ""
 | 
				
			||||||
 | 
						// kind: Config
 | 
				
			||||||
 | 
						// preferences: {}
 | 
				
			||||||
 | 
						// users:
 | 
				
			||||||
 | 
						// - name: red-user
 | 
				
			||||||
 | 
						//   user:
 | 
				
			||||||
 | 
						//     token: red-token
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func ExampleMergingSomeWithConflict() {
 | 
				
			||||||
 | 
						commandLineFile, _ := ioutil.TempFile("", "")
 | 
				
			||||||
 | 
						defer os.Remove(commandLineFile.Name())
 | 
				
			||||||
 | 
						envVarFile, _ := ioutil.TempFile("", "")
 | 
				
			||||||
 | 
						defer os.Remove(envVarFile.Name())
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						WriteToFile(testConfigAlfa, commandLineFile.Name())
 | 
				
			||||||
 | 
						WriteToFile(testConfigConflictAlfa, envVarFile.Name())
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						loadingRules := ClientConfigLoadingRules{
 | 
				
			||||||
 | 
							Precedence: []string{commandLineFile.Name(), envVarFile.Name()},
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						mergedConfig, err := loadingRules.Load()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						json, err := clientcmdlatest.Codec.Encode(mergedConfig)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							fmt.Printf("Unexpected error: %v", err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						output, err := yaml.JSONToYAML(json)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							fmt.Printf("Unexpected error: %v", err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	fmt.Printf("%v", string(output))
 | 
						fmt.Printf("%v", string(output))
 | 
				
			||||||
	// Output:
 | 
						// Output:
 | 
				
			||||||
	// apiVersion: v1
 | 
						// apiVersion: v1
 | 
				
			||||||
@@ -344,8 +469,7 @@ func ExampleMergingEverythingNoConflicts() {
 | 
				
			|||||||
	WriteToFile(testConfigDelta, homeDirFile.Name())
 | 
						WriteToFile(testConfigDelta, homeDirFile.Name())
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	loadingRules := ClientConfigLoadingRules{
 | 
						loadingRules := ClientConfigLoadingRules{
 | 
				
			||||||
		ExplicitPath: commandLineFile.Name(),
 | 
							Precedence: []string{commandLineFile.Name(), envVarFile.Name(), currentDirFile.Name(), homeDirFile.Name()},
 | 
				
			||||||
		Precedence:   []string{envVarFile.Name(), currentDirFile.Name(), homeDirFile.Name()},
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	mergedConfig, err := loadingRules.Load()
 | 
						mergedConfig, err := loadingRules.Load()
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -78,10 +78,7 @@ func testWriteAuthInfoFile(auth clientauth.Info, filename string) error {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func testBindClientConfig(cmd *cobra.Command) ClientConfig {
 | 
					func testBindClientConfig(cmd *cobra.Command) ClientConfig {
 | 
				
			||||||
	loadingRules := NewDefaultClientConfigLoadingRules()
 | 
						loadingRules := &ClientConfigLoadingRules{}
 | 
				
			||||||
	loadingRules.Precedence[DefaultEnvVarIndex] = ""
 | 
					 | 
				
			||||||
	loadingRules.Precedence[DefaultCurrentDirIndex] = ""
 | 
					 | 
				
			||||||
	loadingRules.Precedence[DefaultHomeDirIndex] = ""
 | 
					 | 
				
			||||||
	cmd.PersistentFlags().StringVar(&loadingRules.ExplicitPath, "kubeconfig", "", "Path to the kubeconfig file to use for CLI requests.")
 | 
						cmd.PersistentFlags().StringVar(&loadingRules.ExplicitPath, "kubeconfig", "", "Path to the kubeconfig file to use for CLI requests.")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	overrides := &ConfigOverrides{}
 | 
						overrides := &ConfigOverrides{}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -18,10 +18,10 @@ package config
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
	"errors"
 | 
						"errors"
 | 
				
			||||||
	"fmt"
 | 
					 | 
				
			||||||
	"io"
 | 
						"io"
 | 
				
			||||||
	"os"
 | 
						"os"
 | 
				
			||||||
	"path"
 | 
						"path"
 | 
				
			||||||
 | 
						"path/filepath"
 | 
				
			||||||
	"reflect"
 | 
						"reflect"
 | 
				
			||||||
	"strconv"
 | 
						"strconv"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -33,41 +33,54 @@ import (
 | 
				
			|||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type PathOptions struct {
 | 
					type PathOptions struct {
 | 
				
			||||||
	Local     bool
 | 
						// GlobalFile is the full path to the file to load as the global (final) option
 | 
				
			||||||
	Global    bool
 | 
					 | 
				
			||||||
	UseEnvVar bool
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	LocalFile  string
 | 
					 | 
				
			||||||
	GlobalFile string
 | 
						GlobalFile string
 | 
				
			||||||
	EnvVarFile string
 | 
						// EnvVar is the env var name that points to the list of kubeconfig files to load
 | 
				
			||||||
 | 
					 | 
				
			||||||
	EnvVar string
 | 
						EnvVar string
 | 
				
			||||||
 | 
						// ExplicitFileFlag is the name of the flag to use for prompting for the kubeconfig file
 | 
				
			||||||
	ExplicitFileFlag string
 | 
						ExplicitFileFlag string
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// GlobalFileSubpath is an optional value used for displaying help
 | 
				
			||||||
 | 
						GlobalFileSubpath string
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	LoadingRules *clientcmd.ClientConfigLoadingRules
 | 
						LoadingRules *clientcmd.ClientConfigLoadingRules
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// ConfigAccess is used by subcommands and methods in this package to load and modify the appropriate config files
 | 
				
			||||||
 | 
					type ConfigAccess interface {
 | 
				
			||||||
 | 
						// GetLoadingPrecedence returns the slice of files that should be used for loading and inspecting the config
 | 
				
			||||||
 | 
						GetLoadingPrecedence() []string
 | 
				
			||||||
 | 
						// GetStartingConfig returns the config that subcommands should being operating against.  It may or may not be merged depending on loading rules
 | 
				
			||||||
 | 
						GetStartingConfig() (*clientcmdapi.Config, error)
 | 
				
			||||||
 | 
						// GetDefaultFilename returns the name of the file you should write into (create if necessary), if you're trying to create a new stanza as opposed to updating an existing one.
 | 
				
			||||||
 | 
						GetDefaultFilename() string
 | 
				
			||||||
 | 
						// IsExplicitFile indicates whether or not this command is interested in exactly one file.  This implementation only ever does that  via a flag, but implementations that handle local, global, and flags may have more
 | 
				
			||||||
 | 
						IsExplicitFile() bool
 | 
				
			||||||
 | 
						// GetExplicitFile returns the particular file this command is operating against.  This implementation only ever has one, but implementations that handle local, global, and flags may have more
 | 
				
			||||||
 | 
						GetExplicitFile() string
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func NewCmdConfig(pathOptions *PathOptions, out io.Writer) *cobra.Command {
 | 
					func NewCmdConfig(pathOptions *PathOptions, out io.Writer) *cobra.Command {
 | 
				
			||||||
	if len(pathOptions.ExplicitFileFlag) == 0 {
 | 
						if len(pathOptions.ExplicitFileFlag) == 0 {
 | 
				
			||||||
		pathOptions.ExplicitFileFlag = clientcmd.RecommendedConfigPathFlag
 | 
							pathOptions.ExplicitFileFlag = clientcmd.RecommendedConfigPathFlag
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if len(pathOptions.EnvVar) > 0 {
 | 
					 | 
				
			||||||
		pathOptions.EnvVarFile = os.Getenv(pathOptions.EnvVar)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	cmd := &cobra.Command{
 | 
						cmd := &cobra.Command{
 | 
				
			||||||
		Use:   "config SUBCOMMAND",
 | 
							Use:   "config SUBCOMMAND",
 | 
				
			||||||
		Short: "config modifies kubeconfig files",
 | 
							Short: "config modifies kubeconfig files",
 | 
				
			||||||
		Long:  `config modifies kubeconfig files using subcommands like "kubectl config set current-context my-context"`,
 | 
							Long: `config modifies kubeconfig files using subcommands like "kubectl config set current-context my-context"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The loading order follows these rules:
 | 
				
			||||||
 | 
					    1. If the --` + pathOptions.ExplicitFileFlag + ` flag is set, then only that file is loaded.  The flag may only be set once and no merging takes place.
 | 
				
			||||||
 | 
					    2. If $` + pathOptions.EnvVar + ` environment variable is set, then it is used a list of paths (normal path delimitting rules for your system).  These paths are merged together.  When a value is modified, it is modified in the file that defines the stanza.  When a value is created, it is created in the first file that exists.  If no files in the chain exist, then it creates the last file in the list.
 | 
				
			||||||
 | 
					    3. Otherwise, ` + path.Join("${HOME}", pathOptions.GlobalFileSubpath) + ` is used and no merging takes place.
 | 
				
			||||||
 | 
					`,
 | 
				
			||||||
		Run: func(cmd *cobra.Command, args []string) {
 | 
							Run: func(cmd *cobra.Command, args []string) {
 | 
				
			||||||
			cmd.Help()
 | 
								cmd.Help()
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// file paths are common to all sub commands
 | 
						// file paths are common to all sub commands
 | 
				
			||||||
	cmd.PersistentFlags().BoolVar(&pathOptions.Local, "local", pathOptions.Local, "use the kubeconfig in the current directory")
 | 
					 | 
				
			||||||
	cmd.PersistentFlags().BoolVar(&pathOptions.Global, "global", pathOptions.Global, "use the kubeconfig from "+pathOptions.GlobalFile)
 | 
					 | 
				
			||||||
	cmd.PersistentFlags().BoolVar(&pathOptions.UseEnvVar, "envvar", pathOptions.UseEnvVar, "use the kubeconfig from $"+pathOptions.EnvVar)
 | 
					 | 
				
			||||||
	cmd.PersistentFlags().StringVar(&pathOptions.LoadingRules.ExplicitPath, pathOptions.ExplicitFileFlag, pathOptions.LoadingRules.ExplicitPath, "use a particular kubeconfig file")
 | 
						cmd.PersistentFlags().StringVar(&pathOptions.LoadingRules.ExplicitPath, pathOptions.ExplicitFileFlag, pathOptions.LoadingRules.ExplicitPath, "use a particular kubeconfig file")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	cmd.AddCommand(NewCmdConfigView(out, pathOptions))
 | 
						cmd.AddCommand(NewCmdConfigView(out, pathOptions))
 | 
				
			||||||
@@ -83,13 +96,12 @@ func NewCmdConfig(pathOptions *PathOptions, out io.Writer) *cobra.Command {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
func NewDefaultPathOptions() *PathOptions {
 | 
					func NewDefaultPathOptions() *PathOptions {
 | 
				
			||||||
	ret := &PathOptions{
 | 
						ret := &PathOptions{
 | 
				
			||||||
		LocalFile:  ".kubeconfig",
 | 
							GlobalFile:       clientcmd.RecommendedHomeFile,
 | 
				
			||||||
		GlobalFile: path.Join(os.Getenv("HOME"), "/.kube/.kubeconfig"),
 | 
					 | 
				
			||||||
		EnvVar:           clientcmd.RecommendedConfigPathEnvVar,
 | 
							EnvVar:           clientcmd.RecommendedConfigPathEnvVar,
 | 
				
			||||||
		EnvVarFile: os.Getenv(clientcmd.RecommendedConfigPathEnvVar),
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		ExplicitFileFlag: clientcmd.RecommendedConfigPathFlag,
 | 
							ExplicitFileFlag: clientcmd.RecommendedConfigPathFlag,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							GlobalFileSubpath: clientcmd.RecommendedHomeFileName,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		LoadingRules: clientcmd.NewDefaultClientConfigLoadingRules(),
 | 
							LoadingRules: clientcmd.NewDefaultClientConfigLoadingRules(),
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	ret.LoadingRules.DoNotResolvePaths = true
 | 
						ret.LoadingRules.DoNotResolvePaths = true
 | 
				
			||||||
@@ -97,125 +109,78 @@ func NewDefaultPathOptions() *PathOptions {
 | 
				
			|||||||
	return ret
 | 
						return ret
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (o PathOptions) Validate() error {
 | 
					func (o *PathOptions) GetEnvVarFiles() []string {
 | 
				
			||||||
	if len(o.LoadingRules.ExplicitPath) > 0 {
 | 
						if len(o.EnvVar) == 0 {
 | 
				
			||||||
		if o.Global {
 | 
							return []string{}
 | 
				
			||||||
			return errors.New("cannot specify both --" + o.ExplicitFileFlag + " and --global")
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		if o.Local {
 | 
					 | 
				
			||||||
			return errors.New("cannot specify both --" + o.ExplicitFileFlag + " and --local")
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		if o.UseEnvVar {
 | 
					 | 
				
			||||||
			return errors.New("cannot specify both --" + o.ExplicitFileFlag + " and --envvar")
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if o.Global {
 | 
						envVarValue := os.Getenv(o.EnvVar)
 | 
				
			||||||
		if o.Local {
 | 
						if len(envVarValue) == 0 {
 | 
				
			||||||
			return errors.New("cannot specify both --global and --local")
 | 
							return []string{}
 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		if o.UseEnvVar {
 | 
					 | 
				
			||||||
			return errors.New("cannot specify both --global and --envvar")
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if o.Local {
 | 
						return filepath.SplitList(envVarValue)
 | 
				
			||||||
		if o.UseEnvVar {
 | 
					 | 
				
			||||||
			return errors.New("cannot specify both --local and --envvar")
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if o.UseEnvVar {
 | 
					 | 
				
			||||||
		if len(o.EnvVarFile) == 0 {
 | 
					 | 
				
			||||||
			return fmt.Errorf("environment variable %v does not have a value", o.EnvVar)
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return nil
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (o *PathOptions) getStartingConfig() (*clientcmdapi.Config, error) {
 | 
					func (o *PathOptions) GetLoadingPrecedence() []string {
 | 
				
			||||||
	if err := o.Validate(); err != nil {
 | 
						if envVarFiles := o.GetEnvVarFiles(); len(envVarFiles) > 0 {
 | 
				
			||||||
		return nil, err
 | 
							return envVarFiles
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	config := clientcmdapi.NewConfig()
 | 
						return []string{o.GlobalFile}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	switch {
 | 
					func (o *PathOptions) GetStartingConfig() (*clientcmdapi.Config, error) {
 | 
				
			||||||
	case o.Global:
 | 
						// don't mutate the original
 | 
				
			||||||
		config = getConfigFromFileOrDie(o.GlobalFile)
 | 
						loadingRules := *o.LoadingRules
 | 
				
			||||||
 | 
						loadingRules.Precedence = o.GetLoadingPrecedence()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	case o.UseEnvVar:
 | 
						clientConfig := clientcmd.NewNonInteractiveDeferredLoadingClientConfig(&loadingRules, &clientcmd.ConfigOverrides{})
 | 
				
			||||||
		config = getConfigFromFileOrDie(o.EnvVarFile)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	case o.Local:
 | 
					 | 
				
			||||||
		config = getConfigFromFileOrDie(o.LocalFile)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		// no specific flag was set, load according to the loading rules
 | 
					 | 
				
			||||||
	default:
 | 
					 | 
				
			||||||
		clientConfig := clientcmd.NewNonInteractiveDeferredLoadingClientConfig(o.LoadingRules, &clientcmd.ConfigOverrides{})
 | 
					 | 
				
			||||||
	rawConfig, err := clientConfig.RawConfig()
 | 
						rawConfig, err := clientConfig.RawConfig()
 | 
				
			||||||
 | 
						if os.IsNotExist(err) {
 | 
				
			||||||
 | 
							return clientcmdapi.NewConfig(), nil
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return nil, err
 | 
							return nil, err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
		config = &rawConfig
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	}
 | 
						return &rawConfig, nil
 | 
				
			||||||
 | 
					 | 
				
			||||||
	return config, nil
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// GetDefaultFilename returns the name of the file you should write into (create if necessary), if you're trying to create
 | 
					 | 
				
			||||||
// a new stanza as opposed to updating an existing one.
 | 
					 | 
				
			||||||
func (o *PathOptions) GetDefaultFilename() string {
 | 
					func (o *PathOptions) GetDefaultFilename() string {
 | 
				
			||||||
	if o.IsExplicitFile() {
 | 
						if o.IsExplicitFile() {
 | 
				
			||||||
		return o.GetExplicitFile()
 | 
							return o.GetExplicitFile()
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if len(o.EnvVarFile) > 0 {
 | 
						if envVarFiles := o.GetEnvVarFiles(); len(envVarFiles) > 0 {
 | 
				
			||||||
		return o.EnvVarFile
 | 
							if len(envVarFiles) == 1 {
 | 
				
			||||||
 | 
								return envVarFiles[0]
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if _, err := os.Stat(o.LocalFile); err == nil {
 | 
							// if any of the envvar files already exists, return it
 | 
				
			||||||
		return o.LocalFile
 | 
							for _, envVarFile := range envVarFiles {
 | 
				
			||||||
 | 
								if _, err := os.Stat(envVarFile); err == nil {
 | 
				
			||||||
 | 
									return envVarFile
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							// otherwise, return the last one in the list
 | 
				
			||||||
 | 
							return envVarFiles[len(envVarFiles)-1]
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return o.GlobalFile
 | 
						return o.GlobalFile
 | 
				
			||||||
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (o *PathOptions) IsExplicitFile() bool {
 | 
					func (o *PathOptions) IsExplicitFile() bool {
 | 
				
			||||||
	switch {
 | 
						if len(o.LoadingRules.ExplicitPath) > 0 {
 | 
				
			||||||
	case len(o.LoadingRules.ExplicitPath) > 0 ||
 | 
					 | 
				
			||||||
		o.Global ||
 | 
					 | 
				
			||||||
		o.UseEnvVar ||
 | 
					 | 
				
			||||||
		o.Local:
 | 
					 | 
				
			||||||
		return true
 | 
							return true
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return false
 | 
						return false
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (o *PathOptions) GetExplicitFile() string {
 | 
					func (o *PathOptions) GetExplicitFile() string {
 | 
				
			||||||
	if !o.IsExplicitFile() {
 | 
					 | 
				
			||||||
		return ""
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	switch {
 | 
					 | 
				
			||||||
	case len(o.LoadingRules.ExplicitPath) > 0:
 | 
					 | 
				
			||||||
	return o.LoadingRules.ExplicitPath
 | 
						return o.LoadingRules.ExplicitPath
 | 
				
			||||||
 | 
					 | 
				
			||||||
	case o.Global:
 | 
					 | 
				
			||||||
		return o.GlobalFile
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	case o.UseEnvVar:
 | 
					 | 
				
			||||||
		return o.EnvVarFile
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	case o.Local:
 | 
					 | 
				
			||||||
		return o.LocalFile
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return ""
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// ModifyConfig takes a Config object, iterates through Clusters, AuthInfos, and Contexts, uses the LocationOfOrigin if specified or
 | 
					// ModifyConfig takes a Config object, iterates through Clusters, AuthInfos, and Contexts, uses the LocationOfOrigin if specified or
 | 
				
			||||||
@@ -223,8 +188,8 @@ func (o *PathOptions) GetExplicitFile() string {
 | 
				
			|||||||
// Preferences and CurrentContext should always be set in the default destination file.  Since we can't distinguish between empty and missing values
 | 
					// Preferences and CurrentContext should always be set in the default destination file.  Since we can't distinguish between empty and missing values
 | 
				
			||||||
// (no nil strings), we're forced have separate handling for them.  In all the currently known cases, newConfig should have, at most, one difference,
 | 
					// (no nil strings), we're forced have separate handling for them.  In all the currently known cases, newConfig should have, at most, one difference,
 | 
				
			||||||
// that means that this code will only write into a single file.
 | 
					// that means that this code will only write into a single file.
 | 
				
			||||||
func (o *PathOptions) ModifyConfig(newConfig clientcmdapi.Config) error {
 | 
					func ModifyConfig(configAccess ConfigAccess, newConfig clientcmdapi.Config) error {
 | 
				
			||||||
	startingConfig, err := o.getStartingConfig()
 | 
						startingConfig, err := configAccess.GetStartingConfig()
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return err
 | 
							return err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
@@ -237,12 +202,12 @@ func (o *PathOptions) ModifyConfig(newConfig clientcmdapi.Config) error {
 | 
				
			|||||||
		// nothing to do
 | 
							// nothing to do
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	case startingConfig.CurrentContext != newConfig.CurrentContext:
 | 
						case startingConfig.CurrentContext != newConfig.CurrentContext:
 | 
				
			||||||
		if err := o.writeCurrentContext(newConfig.CurrentContext); err != nil {
 | 
							if err := writeCurrentContext(configAccess, newConfig.CurrentContext); err != nil {
 | 
				
			||||||
			return err
 | 
								return err
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	case !reflect.DeepEqual(startingConfig.Preferences, newConfig.Preferences):
 | 
						case !reflect.DeepEqual(startingConfig.Preferences, newConfig.Preferences):
 | 
				
			||||||
		if err := o.writePreferences(newConfig.Preferences); err != nil {
 | 
							if err := writePreferences(configAccess, newConfig.Preferences); err != nil {
 | 
				
			||||||
			return err
 | 
								return err
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -253,7 +218,7 @@ func (o *PathOptions) ModifyConfig(newConfig clientcmdapi.Config) error {
 | 
				
			|||||||
			if !reflect.DeepEqual(cluster, startingCluster) || !exists {
 | 
								if !reflect.DeepEqual(cluster, startingCluster) || !exists {
 | 
				
			||||||
				destinationFile := cluster.LocationOfOrigin
 | 
									destinationFile := cluster.LocationOfOrigin
 | 
				
			||||||
				if len(destinationFile) == 0 {
 | 
									if len(destinationFile) == 0 {
 | 
				
			||||||
					destinationFile = o.GetDefaultFilename()
 | 
										destinationFile = configAccess.GetDefaultFilename()
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				configToWrite := getConfigFromFileOrDie(destinationFile)
 | 
									configToWrite := getConfigFromFileOrDie(destinationFile)
 | 
				
			||||||
@@ -270,7 +235,7 @@ func (o *PathOptions) ModifyConfig(newConfig clientcmdapi.Config) error {
 | 
				
			|||||||
			if !reflect.DeepEqual(context, startingContext) || !exists {
 | 
								if !reflect.DeepEqual(context, startingContext) || !exists {
 | 
				
			||||||
				destinationFile := context.LocationOfOrigin
 | 
									destinationFile := context.LocationOfOrigin
 | 
				
			||||||
				if len(destinationFile) == 0 {
 | 
									if len(destinationFile) == 0 {
 | 
				
			||||||
					destinationFile = o.GetDefaultFilename()
 | 
										destinationFile = configAccess.GetDefaultFilename()
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				configToWrite := getConfigFromFileOrDie(destinationFile)
 | 
									configToWrite := getConfigFromFileOrDie(destinationFile)
 | 
				
			||||||
@@ -287,7 +252,7 @@ func (o *PathOptions) ModifyConfig(newConfig clientcmdapi.Config) error {
 | 
				
			|||||||
			if !reflect.DeepEqual(authInfo, startingAuthInfo) || !exists {
 | 
								if !reflect.DeepEqual(authInfo, startingAuthInfo) || !exists {
 | 
				
			||||||
				destinationFile := authInfo.LocationOfOrigin
 | 
									destinationFile := authInfo.LocationOfOrigin
 | 
				
			||||||
				if len(destinationFile) == 0 {
 | 
									if len(destinationFile) == 0 {
 | 
				
			||||||
					destinationFile = o.GetDefaultFilename()
 | 
										destinationFile = configAccess.GetDefaultFilename()
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				configToWrite := getConfigFromFileOrDie(destinationFile)
 | 
									configToWrite := getConfigFromFileOrDie(destinationFile)
 | 
				
			||||||
@@ -303,7 +268,7 @@ func (o *PathOptions) ModifyConfig(newConfig clientcmdapi.Config) error {
 | 
				
			|||||||
			if _, exists := newConfig.Clusters[key]; !exists {
 | 
								if _, exists := newConfig.Clusters[key]; !exists {
 | 
				
			||||||
				destinationFile := cluster.LocationOfOrigin
 | 
									destinationFile := cluster.LocationOfOrigin
 | 
				
			||||||
				if len(destinationFile) == 0 {
 | 
									if len(destinationFile) == 0 {
 | 
				
			||||||
					destinationFile = o.GetDefaultFilename()
 | 
										destinationFile = configAccess.GetDefaultFilename()
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				configToWrite := getConfigFromFileOrDie(destinationFile)
 | 
									configToWrite := getConfigFromFileOrDie(destinationFile)
 | 
				
			||||||
@@ -319,7 +284,7 @@ func (o *PathOptions) ModifyConfig(newConfig clientcmdapi.Config) error {
 | 
				
			|||||||
			if _, exists := newConfig.Contexts[key]; !exists {
 | 
								if _, exists := newConfig.Contexts[key]; !exists {
 | 
				
			||||||
				destinationFile := context.LocationOfOrigin
 | 
									destinationFile := context.LocationOfOrigin
 | 
				
			||||||
				if len(destinationFile) == 0 {
 | 
									if len(destinationFile) == 0 {
 | 
				
			||||||
					destinationFile = o.GetDefaultFilename()
 | 
										destinationFile = configAccess.GetDefaultFilename()
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				configToWrite := getConfigFromFileOrDie(destinationFile)
 | 
									configToWrite := getConfigFromFileOrDie(destinationFile)
 | 
				
			||||||
@@ -335,7 +300,7 @@ func (o *PathOptions) ModifyConfig(newConfig clientcmdapi.Config) error {
 | 
				
			|||||||
			if _, exists := newConfig.AuthInfos[key]; !exists {
 | 
								if _, exists := newConfig.AuthInfos[key]; !exists {
 | 
				
			||||||
				destinationFile := authInfo.LocationOfOrigin
 | 
									destinationFile := authInfo.LocationOfOrigin
 | 
				
			||||||
				if len(destinationFile) == 0 {
 | 
									if len(destinationFile) == 0 {
 | 
				
			||||||
					destinationFile = o.GetDefaultFilename()
 | 
										destinationFile = configAccess.GetDefaultFilename()
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				configToWrite := getConfigFromFileOrDie(destinationFile)
 | 
									configToWrite := getConfigFromFileOrDie(destinationFile)
 | 
				
			||||||
@@ -356,15 +321,26 @@ func (o *PathOptions) ModifyConfig(newConfig clientcmdapi.Config) error {
 | 
				
			|||||||
// If newCurrentContext is the same as the startingConfig's current context, then we exit.
 | 
					// If newCurrentContext is the same as the startingConfig's current context, then we exit.
 | 
				
			||||||
// If newCurrentContext has a value, then that value is written into the default destination file.
 | 
					// If newCurrentContext has a value, then that value is written into the default destination file.
 | 
				
			||||||
// If newCurrentContext is empty, then we find the config file that is setting the CurrentContext and clear the value from that file
 | 
					// If newCurrentContext is empty, then we find the config file that is setting the CurrentContext and clear the value from that file
 | 
				
			||||||
func (o *PathOptions) writeCurrentContext(newCurrentContext string) error {
 | 
					func writeCurrentContext(configAccess ConfigAccess, newCurrentContext string) error {
 | 
				
			||||||
	if startingConfig, err := o.getStartingConfig(); err != nil {
 | 
						if startingConfig, err := configAccess.GetStartingConfig(); err != nil {
 | 
				
			||||||
		return err
 | 
							return err
 | 
				
			||||||
	} else if startingConfig.CurrentContext == newCurrentContext {
 | 
						} else if startingConfig.CurrentContext == newCurrentContext {
 | 
				
			||||||
		return nil
 | 
							return nil
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if configAccess.IsExplicitFile() {
 | 
				
			||||||
 | 
							file := configAccess.GetExplicitFile()
 | 
				
			||||||
 | 
							currConfig := getConfigFromFileOrDie(file)
 | 
				
			||||||
 | 
							currConfig.CurrentContext = newCurrentContext
 | 
				
			||||||
 | 
							if err := clientcmd.WriteToFile(*currConfig, file); err != nil {
 | 
				
			||||||
 | 
								return err
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							return nil
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if len(newCurrentContext) > 0 {
 | 
						if len(newCurrentContext) > 0 {
 | 
				
			||||||
		destinationFile := o.GetDefaultFilename()
 | 
							destinationFile := configAccess.GetDefaultFilename()
 | 
				
			||||||
		config := getConfigFromFileOrDie(destinationFile)
 | 
							config := getConfigFromFileOrDie(destinationFile)
 | 
				
			||||||
		config.CurrentContext = newCurrentContext
 | 
							config.CurrentContext = newCurrentContext
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -375,22 +351,9 @@ func (o *PathOptions) writeCurrentContext(newCurrentContext string) error {
 | 
				
			|||||||
		return nil
 | 
							return nil
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if o.IsExplicitFile() {
 | 
						// we're supposed to be clearing the current context.  We need to find the first spot in the chain that is setting it and clear it
 | 
				
			||||||
		file := o.GetExplicitFile()
 | 
						for _, file := range configAccess.GetLoadingPrecedence() {
 | 
				
			||||||
		currConfig := getConfigFromFileOrDie(file)
 | 
							if _, err := os.Stat(file); err == nil {
 | 
				
			||||||
		currConfig.CurrentContext = newCurrentContext
 | 
					 | 
				
			||||||
		if err := clientcmd.WriteToFile(*currConfig, file); err != nil {
 | 
					 | 
				
			||||||
			return err
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		return nil
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	filesToCheck := make([]string, 0, len(o.LoadingRules.Precedence)+1)
 | 
					 | 
				
			||||||
	filesToCheck = append(filesToCheck, o.LoadingRules.ExplicitPath)
 | 
					 | 
				
			||||||
	filesToCheck = append(filesToCheck, o.LoadingRules.Precedence...)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	for _, file := range filesToCheck {
 | 
					 | 
				
			||||||
			currConfig := getConfigFromFileOrDie(file)
 | 
								currConfig := getConfigFromFileOrDie(file)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			if len(currConfig.CurrentContext) > 0 {
 | 
								if len(currConfig.CurrentContext) > 0 {
 | 
				
			||||||
@@ -402,19 +365,20 @@ func (o *PathOptions) writeCurrentContext(newCurrentContext string) error {
 | 
				
			|||||||
				return nil
 | 
									return nil
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return nil
 | 
						return errors.New("no config found to write context")
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (o *PathOptions) writePreferences(newPrefs clientcmdapi.Preferences) error {
 | 
					func writePreferences(configAccess ConfigAccess, newPrefs clientcmdapi.Preferences) error {
 | 
				
			||||||
	if startingConfig, err := o.getStartingConfig(); err != nil {
 | 
						if startingConfig, err := configAccess.GetStartingConfig(); err != nil {
 | 
				
			||||||
		return err
 | 
							return err
 | 
				
			||||||
	} else if reflect.DeepEqual(startingConfig.Preferences, newPrefs) {
 | 
						} else if reflect.DeepEqual(startingConfig.Preferences, newPrefs) {
 | 
				
			||||||
		return nil
 | 
							return nil
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if o.IsExplicitFile() {
 | 
						if configAccess.IsExplicitFile() {
 | 
				
			||||||
		file := o.GetExplicitFile()
 | 
							file := configAccess.GetExplicitFile()
 | 
				
			||||||
		currConfig := getConfigFromFileOrDie(file)
 | 
							currConfig := getConfigFromFileOrDie(file)
 | 
				
			||||||
		currConfig.Preferences = newPrefs
 | 
							currConfig.Preferences = newPrefs
 | 
				
			||||||
		if err := clientcmd.WriteToFile(*currConfig, file); err != nil {
 | 
							if err := clientcmd.WriteToFile(*currConfig, file); err != nil {
 | 
				
			||||||
@@ -424,11 +388,7 @@ func (o *PathOptions) writePreferences(newPrefs clientcmdapi.Preferences) error
 | 
				
			|||||||
		return nil
 | 
							return nil
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	filesToCheck := make([]string, 0, len(o.LoadingRules.Precedence)+1)
 | 
						for _, file := range configAccess.GetLoadingPrecedence() {
 | 
				
			||||||
	filesToCheck = append(filesToCheck, o.LoadingRules.ExplicitPath)
 | 
					 | 
				
			||||||
	filesToCheck = append(filesToCheck, o.LoadingRules.Precedence...)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	for _, file := range filesToCheck {
 | 
					 | 
				
			||||||
		currConfig := getConfigFromFileOrDie(file)
 | 
							currConfig := getConfigFromFileOrDie(file)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if !reflect.DeepEqual(currConfig.Preferences, newPrefs) {
 | 
							if !reflect.DeepEqual(currConfig.Preferences, newPrefs) {
 | 
				
			||||||
@@ -441,7 +401,7 @@ func (o *PathOptions) writePreferences(newPrefs clientcmdapi.Preferences) error
 | 
				
			|||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return nil
 | 
						return errors.New("no config found to write preferences")
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// getConfigFromFileOrDie tries to read a kubeconfig file and if it can't, it calls exit.  One exception, missing files result in empty configs, not an exit
 | 
					// getConfigFromFileOrDie tries to read a kubeconfig file and if it can't, it calls exit.  One exception, missing files result in empty configs, not an exit
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -31,7 +31,7 @@ import (
 | 
				
			|||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type createAuthInfoOptions struct {
 | 
					type createAuthInfoOptions struct {
 | 
				
			||||||
	pathOptions       *PathOptions
 | 
						configAccess      ConfigAccess
 | 
				
			||||||
	name              string
 | 
						name              string
 | 
				
			||||||
	authPath          util.StringFlag
 | 
						authPath          util.StringFlag
 | 
				
			||||||
	clientCertificate util.StringFlag
 | 
						clientCertificate util.StringFlag
 | 
				
			||||||
@@ -67,8 +67,8 @@ $ kubectl set-credentials cluster-admin --username=admin --password=uXFGweU9l35q
 | 
				
			|||||||
// Embed client certificate data in the "cluster-admin" entry
 | 
					// Embed client certificate data in the "cluster-admin" entry
 | 
				
			||||||
$ kubectl set-credentials cluster-admin --client-certificate=~/.kube/admin.crt --embed-certs=true`
 | 
					$ kubectl set-credentials cluster-admin --client-certificate=~/.kube/admin.crt --embed-certs=true`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func NewCmdConfigSetAuthInfo(out io.Writer, pathOptions *PathOptions) *cobra.Command {
 | 
					func NewCmdConfigSetAuthInfo(out io.Writer, configAccess ConfigAccess) *cobra.Command {
 | 
				
			||||||
	options := &createAuthInfoOptions{pathOptions: pathOptions}
 | 
						options := &createAuthInfoOptions{configAccess: configAccess}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	cmd := &cobra.Command{
 | 
						cmd := &cobra.Command{
 | 
				
			||||||
		Use:     fmt.Sprintf("set-credentials NAME [--%v=/path/to/authfile] [--%v=path/to/certfile] [--%v=path/to/keyfile] [--%v=bearer_token] [--%v=basic_user] [--%v=basic_password]", clientcmd.FlagAuthPath, clientcmd.FlagCertFile, clientcmd.FlagKeyFile, clientcmd.FlagBearerToken, clientcmd.FlagUsername, clientcmd.FlagPassword),
 | 
							Use:     fmt.Sprintf("set-credentials NAME [--%v=/path/to/authfile] [--%v=path/to/certfile] [--%v=path/to/keyfile] [--%v=bearer_token] [--%v=basic_user] [--%v=basic_password]", clientcmd.FlagAuthPath, clientcmd.FlagCertFile, clientcmd.FlagKeyFile, clientcmd.FlagBearerToken, clientcmd.FlagUsername, clientcmd.FlagPassword),
 | 
				
			||||||
@@ -104,7 +104,7 @@ func (o createAuthInfoOptions) run() error {
 | 
				
			|||||||
		return err
 | 
							return err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	config, err := o.pathOptions.getStartingConfig()
 | 
						config, err := o.configAccess.GetStartingConfig()
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return err
 | 
							return err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
@@ -112,7 +112,7 @@ func (o createAuthInfoOptions) run() error {
 | 
				
			|||||||
	authInfo := o.modifyAuthInfo(config.AuthInfos[o.name])
 | 
						authInfo := o.modifyAuthInfo(config.AuthInfos[o.name])
 | 
				
			||||||
	config.AuthInfos[o.name] = authInfo
 | 
						config.AuthInfos[o.name] = authInfo
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if err := o.pathOptions.ModifyConfig(*config); err != nil {
 | 
						if err := ModifyConfig(o.configAccess, *config); err != nil {
 | 
				
			||||||
		return err
 | 
							return err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -225,5 +225,5 @@ func (o createAuthInfoOptions) validate() error {
 | 
				
			|||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return o.pathOptions.Validate()
 | 
						return nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -30,7 +30,7 @@ import (
 | 
				
			|||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type createClusterOptions struct {
 | 
					type createClusterOptions struct {
 | 
				
			||||||
	pathOptions           *PathOptions
 | 
						configAccess          ConfigAccess
 | 
				
			||||||
	name                  string
 | 
						name                  string
 | 
				
			||||||
	server                util.StringFlag
 | 
						server                util.StringFlag
 | 
				
			||||||
	apiVersion            util.StringFlag
 | 
						apiVersion            util.StringFlag
 | 
				
			||||||
@@ -52,8 +52,8 @@ $ kubectl config set-cluster e2e --certificate-authority=~/.kube/e2e/kubernetes.
 | 
				
			|||||||
$ kubectl config set-cluster e2e --insecure-skip-tls-verify=true`
 | 
					$ kubectl config set-cluster e2e --insecure-skip-tls-verify=true`
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func NewCmdConfigSetCluster(out io.Writer, pathOptions *PathOptions) *cobra.Command {
 | 
					func NewCmdConfigSetCluster(out io.Writer, configAccess ConfigAccess) *cobra.Command {
 | 
				
			||||||
	options := &createClusterOptions{pathOptions: pathOptions}
 | 
						options := &createClusterOptions{configAccess: configAccess}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	cmd := &cobra.Command{
 | 
						cmd := &cobra.Command{
 | 
				
			||||||
		Use:     fmt.Sprintf("set-cluster NAME [--%v=server] [--%v=path/to/certficate/authority] [--%v=apiversion] [--%v=true]", clientcmd.FlagAPIServer, clientcmd.FlagCAFile, clientcmd.FlagAPIVersion, clientcmd.FlagInsecure),
 | 
							Use:     fmt.Sprintf("set-cluster NAME [--%v=server] [--%v=path/to/certficate/authority] [--%v=apiversion] [--%v=true]", clientcmd.FlagAPIServer, clientcmd.FlagCAFile, clientcmd.FlagAPIVersion, clientcmd.FlagInsecure),
 | 
				
			||||||
@@ -89,7 +89,7 @@ func (o createClusterOptions) run() error {
 | 
				
			|||||||
		return err
 | 
							return err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	config, err := o.pathOptions.getStartingConfig()
 | 
						config, err := o.configAccess.GetStartingConfig()
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return err
 | 
							return err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
@@ -97,7 +97,7 @@ func (o createClusterOptions) run() error {
 | 
				
			|||||||
	cluster := o.modifyCluster(config.Clusters[o.name])
 | 
						cluster := o.modifyCluster(config.Clusters[o.name])
 | 
				
			||||||
	config.Clusters[o.name] = cluster
 | 
						config.Clusters[o.name] = cluster
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if err := o.pathOptions.ModifyConfig(*config); err != nil {
 | 
						if err := ModifyConfig(o.configAccess, *config); err != nil {
 | 
				
			||||||
		return err
 | 
							return err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -169,5 +169,5 @@ func (o createClusterOptions) validate() error {
 | 
				
			|||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return o.pathOptions.Validate()
 | 
						return nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -29,7 +29,7 @@ import (
 | 
				
			|||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type createContextOptions struct {
 | 
					type createContextOptions struct {
 | 
				
			||||||
	pathOptions *PathOptions
 | 
						configAccess ConfigAccess
 | 
				
			||||||
	name         string
 | 
						name         string
 | 
				
			||||||
	cluster      util.StringFlag
 | 
						cluster      util.StringFlag
 | 
				
			||||||
	authInfo     util.StringFlag
 | 
						authInfo     util.StringFlag
 | 
				
			||||||
@@ -43,8 +43,8 @@ Specifying a name that already exists will merge new fields on top of existing v
 | 
				
			|||||||
$ kubectl config set-context gce --user=cluster-admin`
 | 
					$ kubectl config set-context gce --user=cluster-admin`
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func NewCmdConfigSetContext(out io.Writer, pathOptions *PathOptions) *cobra.Command {
 | 
					func NewCmdConfigSetContext(out io.Writer, configAccess ConfigAccess) *cobra.Command {
 | 
				
			||||||
	options := &createContextOptions{pathOptions: pathOptions}
 | 
						options := &createContextOptions{configAccess: configAccess}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	cmd := &cobra.Command{
 | 
						cmd := &cobra.Command{
 | 
				
			||||||
		Use:     fmt.Sprintf("set-context NAME [--%v=cluster_nickname] [--%v=user_nickname] [--%v=namespace]", clientcmd.FlagClusterName, clientcmd.FlagAuthInfoName, clientcmd.FlagNamespace),
 | 
							Use:     fmt.Sprintf("set-context NAME [--%v=cluster_nickname] [--%v=user_nickname] [--%v=namespace]", clientcmd.FlagClusterName, clientcmd.FlagAuthInfoName, clientcmd.FlagNamespace),
 | 
				
			||||||
@@ -76,7 +76,7 @@ func (o createContextOptions) run() error {
 | 
				
			|||||||
		return err
 | 
							return err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	config, err := o.pathOptions.getStartingConfig()
 | 
						config, err := o.configAccess.GetStartingConfig()
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return err
 | 
							return err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
@@ -84,7 +84,7 @@ func (o createContextOptions) run() error {
 | 
				
			|||||||
	context := o.modifyContext(config.Contexts[o.name])
 | 
						context := o.modifyContext(config.Contexts[o.name])
 | 
				
			||||||
	config.Contexts[o.name] = context
 | 
						config.Contexts[o.name] = context
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if err := o.pathOptions.ModifyConfig(*config); err != nil {
 | 
						if err := ModifyConfig(o.configAccess, *config); err != nil {
 | 
				
			||||||
		return err
 | 
							return err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -123,5 +123,5 @@ func (o createContextOptions) validate() error {
 | 
				
			|||||||
		return errors.New("You must specify a non-empty context name")
 | 
							return errors.New("You must specify a non-empty context name")
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return o.pathOptions.Validate()
 | 
						return nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -32,7 +32,7 @@ const (
 | 
				
			|||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type setOptions struct {
 | 
					type setOptions struct {
 | 
				
			||||||
	pathOptions   *PathOptions
 | 
						configAccess  ConfigAccess
 | 
				
			||||||
	propertyName  string
 | 
						propertyName  string
 | 
				
			||||||
	propertyValue string
 | 
						propertyValue string
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -41,8 +41,8 @@ const set_long = `Sets an individual value in a kubeconfig file
 | 
				
			|||||||
PROPERTY_NAME is a dot delimited name where each token represents either a attribute name or a map key.  Map keys may not contain dots.
 | 
					PROPERTY_NAME is a dot delimited name where each token represents either a attribute name or a map key.  Map keys may not contain dots.
 | 
				
			||||||
PROPERTY_VALUE is the new value you wish to set.`
 | 
					PROPERTY_VALUE is the new value you wish to set.`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func NewCmdConfigSet(out io.Writer, pathOptions *PathOptions) *cobra.Command {
 | 
					func NewCmdConfigSet(out io.Writer, configAccess ConfigAccess) *cobra.Command {
 | 
				
			||||||
	options := &setOptions{pathOptions: pathOptions}
 | 
						options := &setOptions{configAccess: configAccess}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	cmd := &cobra.Command{
 | 
						cmd := &cobra.Command{
 | 
				
			||||||
		Use:   "set PROPERTY_NAME PROPERTY_VALUE",
 | 
							Use:   "set PROPERTY_NAME PROPERTY_VALUE",
 | 
				
			||||||
@@ -69,7 +69,7 @@ func (o setOptions) run() error {
 | 
				
			|||||||
		return err
 | 
							return err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	config, err := o.pathOptions.getStartingConfig()
 | 
						config, err := o.configAccess.GetStartingConfig()
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return err
 | 
							return err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
@@ -82,7 +82,7 @@ func (o setOptions) run() error {
 | 
				
			|||||||
		return err
 | 
							return err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if err := o.pathOptions.ModifyConfig(*config); err != nil {
 | 
						if err := ModifyConfig(o.configAccess, *config); err != nil {
 | 
				
			||||||
		return err
 | 
							return err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -110,7 +110,7 @@ func (o setOptions) validate() error {
 | 
				
			|||||||
		return errors.New("You must specify a property")
 | 
							return errors.New("You must specify a property")
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return o.pathOptions.Validate()
 | 
						return nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func modifyConfig(curr reflect.Value, steps *navigationSteps, propertyValue string, unset bool) error {
 | 
					func modifyConfig(curr reflect.Value, steps *navigationSteps, propertyValue string, unset bool) error {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -26,15 +26,15 @@ import (
 | 
				
			|||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type unsetOptions struct {
 | 
					type unsetOptions struct {
 | 
				
			||||||
	pathOptions  *PathOptions
 | 
						configAccess ConfigAccess
 | 
				
			||||||
	propertyName string
 | 
						propertyName string
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const unset_long = `Unsets an individual value in a kubeconfig file
 | 
					const unset_long = `Unsets an individual value in a kubeconfig file
 | 
				
			||||||
PROPERTY_NAME is a dot delimited name where each token represents either a attribute name or a map key.  Map keys may not contain dots.`
 | 
					PROPERTY_NAME is a dot delimited name where each token represents either a attribute name or a map key.  Map keys may not contain dots.`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func NewCmdConfigUnset(out io.Writer, pathOptions *PathOptions) *cobra.Command {
 | 
					func NewCmdConfigUnset(out io.Writer, configAccess ConfigAccess) *cobra.Command {
 | 
				
			||||||
	options := &unsetOptions{pathOptions: pathOptions}
 | 
						options := &unsetOptions{configAccess: configAccess}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	cmd := &cobra.Command{
 | 
						cmd := &cobra.Command{
 | 
				
			||||||
		Use:   "unset PROPERTY_NAME",
 | 
							Use:   "unset PROPERTY_NAME",
 | 
				
			||||||
@@ -61,7 +61,7 @@ func (o unsetOptions) run() error {
 | 
				
			|||||||
		return err
 | 
							return err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	config, err := o.pathOptions.getStartingConfig()
 | 
						config, err := o.configAccess.GetStartingConfig()
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return err
 | 
							return err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
@@ -75,7 +75,7 @@ func (o unsetOptions) run() error {
 | 
				
			|||||||
		return err
 | 
							return err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if err := o.pathOptions.ModifyConfig(*config); err != nil {
 | 
						if err := ModifyConfig(o.configAccess, *config); err != nil {
 | 
				
			||||||
		return err
 | 
							return err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -98,5 +98,5 @@ func (o unsetOptions) validate() error {
 | 
				
			|||||||
		return errors.New("You must specify a property")
 | 
							return errors.New("You must specify a property")
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return o.pathOptions.Validate()
 | 
						return nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -25,12 +25,12 @@ import (
 | 
				
			|||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type useContextOptions struct {
 | 
					type useContextOptions struct {
 | 
				
			||||||
	pathOptions *PathOptions
 | 
						configAccess ConfigAccess
 | 
				
			||||||
	contextName  string
 | 
						contextName  string
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func NewCmdConfigUseContext(out io.Writer, pathOptions *PathOptions) *cobra.Command {
 | 
					func NewCmdConfigUseContext(out io.Writer, configAccess ConfigAccess) *cobra.Command {
 | 
				
			||||||
	options := &useContextOptions{pathOptions: pathOptions}
 | 
						options := &useContextOptions{configAccess: configAccess}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	cmd := &cobra.Command{
 | 
						cmd := &cobra.Command{
 | 
				
			||||||
		Use:   "use-context CONTEXT_NAME",
 | 
							Use:   "use-context CONTEXT_NAME",
 | 
				
			||||||
@@ -57,14 +57,14 @@ func (o useContextOptions) run() error {
 | 
				
			|||||||
		return err
 | 
							return err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	config, err := o.pathOptions.getStartingConfig()
 | 
						config, err := o.configAccess.GetStartingConfig()
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return err
 | 
							return err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	config.CurrentContext = o.contextName
 | 
						config.CurrentContext = o.contextName
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if err := o.pathOptions.ModifyConfig(*config); err != nil {
 | 
						if err := ModifyConfig(o.configAccess, *config); err != nil {
 | 
				
			||||||
		return err
 | 
							return err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -87,5 +87,5 @@ func (o useContextOptions) validate() error {
 | 
				
			|||||||
		return errors.New("You must specify a current-context")
 | 
							return errors.New("You must specify a current-context")
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return o.pathOptions.Validate()
 | 
						return nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -32,7 +32,7 @@ import (
 | 
				
			|||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type ViewOptions struct {
 | 
					type ViewOptions struct {
 | 
				
			||||||
	PathOptions *PathOptions
 | 
						ConfigAccess ConfigAccess
 | 
				
			||||||
	Merge        util.BoolFlag
 | 
						Merge        util.BoolFlag
 | 
				
			||||||
	Flatten      bool
 | 
						Flatten      bool
 | 
				
			||||||
	Minify       bool
 | 
						Minify       bool
 | 
				
			||||||
@@ -52,8 +52,8 @@ $ kubectl config view --local
 | 
				
			|||||||
$ kubectl config view -o template --template='{{range .users}}{{ if eq .name "e2e" }}{{ index .user.password }}{{end}}{{end}}'`
 | 
					$ kubectl config view -o template --template='{{range .users}}{{ if eq .name "e2e" }}{{ index .user.password }}{{end}}{{end}}'`
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func NewCmdConfigView(out io.Writer, PathOptions *PathOptions) *cobra.Command {
 | 
					func NewCmdConfigView(out io.Writer, ConfigAccess ConfigAccess) *cobra.Command {
 | 
				
			||||||
	options := &ViewOptions{PathOptions: PathOptions}
 | 
						options := &ViewOptions{ConfigAccess: ConfigAccess}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	cmd := &cobra.Command{
 | 
						cmd := &cobra.Command{
 | 
				
			||||||
		Use:     "view",
 | 
							Use:     "view",
 | 
				
			||||||
@@ -116,7 +116,7 @@ func (o ViewOptions) Run(out io.Writer, printer kubectl.ResourcePrinter) error {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
func (o *ViewOptions) Complete() bool {
 | 
					func (o *ViewOptions) Complete() bool {
 | 
				
			||||||
	// if --kubeconfig, --global, or --local is specified, then merging doesn't make sense since you're declaring precise intent
 | 
						// if --kubeconfig, --global, or --local is specified, then merging doesn't make sense since you're declaring precise intent
 | 
				
			||||||
	if o.PathOptions.Global || o.PathOptions.Local || o.PathOptions.UseEnvVar {
 | 
						if o.ConfigAccess.IsExplicitFile() {
 | 
				
			||||||
		if !o.Merge.Provided() {
 | 
							if !o.Merge.Provided() {
 | 
				
			||||||
			o.Merge.Set("false")
 | 
								o.Merge.Set("false")
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
@@ -136,32 +136,20 @@ func (o ViewOptions) loadConfig() (*clientcmdapi.Config, error) {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (o ViewOptions) Validate() error {
 | 
					func (o ViewOptions) Validate() error {
 | 
				
			||||||
	return o.PathOptions.Validate()
 | 
						if !o.Merge.Value() && !o.ConfigAccess.IsExplicitFile() {
 | 
				
			||||||
 | 
							return errors.New("if merge==false a precise file must to specified")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// getStartingConfig returns the Config object built from the sources specified by the options, the filename read (only if it was a single file), and an error if something goes wrong
 | 
					// getStartingConfig returns the Config object built from the sources specified by the options, the filename read (only if it was a single file), and an error if something goes wrong
 | 
				
			||||||
func (o *ViewOptions) getStartingConfig() (*clientcmdapi.Config, error) {
 | 
					func (o *ViewOptions) getStartingConfig() (*clientcmdapi.Config, error) {
 | 
				
			||||||
	switch {
 | 
						switch {
 | 
				
			||||||
	case !o.Merge.Value():
 | 
						case !o.Merge.Value():
 | 
				
			||||||
		switch {
 | 
							return clientcmd.LoadFromFile(o.ConfigAccess.GetExplicitFile())
 | 
				
			||||||
		case len(o.PathOptions.LoadingRules.ExplicitPath) > 0:
 | 
					 | 
				
			||||||
			return clientcmd.LoadFromFile(o.PathOptions.LoadingRules.ExplicitPath)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		case o.PathOptions.Global:
 | 
					 | 
				
			||||||
			return clientcmd.LoadFromFile(o.PathOptions.GlobalFile)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		case o.PathOptions.UseEnvVar:
 | 
					 | 
				
			||||||
			return clientcmd.LoadFromFile(o.PathOptions.EnvVarFile)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		case o.PathOptions.Local:
 | 
					 | 
				
			||||||
			return clientcmd.LoadFromFile(o.PathOptions.LocalFile)
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	default:
 | 
						default:
 | 
				
			||||||
			return nil, errors.New("if Merge==false a precise file must to specified")
 | 
							return o.ConfigAccess.GetStartingConfig()
 | 
				
			||||||
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	default:
 | 
					 | 
				
			||||||
		return o.PathOptions.getStartingConfig()
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -286,11 +286,11 @@ func (c *clientSwaggerSchema) ValidateBytes(data []byte) error {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
// DefaultClientConfig creates a clientcmd.ClientConfig with the following hierarchy:
 | 
					// DefaultClientConfig creates a clientcmd.ClientConfig with the following hierarchy:
 | 
				
			||||||
//   1.  Use the kubeconfig builder.  The number of merges and overrides here gets a little crazy.  Stay with me.
 | 
					//   1.  Use the kubeconfig builder.  The number of merges and overrides here gets a little crazy.  Stay with me.
 | 
				
			||||||
//       1.  Merge together the kubeconfig itself.  This is done with the following hierarchy and merge rules:
 | 
					//       1.  Merge together the kubeconfig itself.  This is done with the following hierarchy rules:
 | 
				
			||||||
//           1.  CommandLineLocation - this parsed from the command line, so it must be late bound
 | 
					//           1.  CommandLineLocation - this parsed from the command line, so it must be late bound.  If you specify this,
 | 
				
			||||||
//           2.  EnvVarLocation
 | 
					//               then no other kubeconfig files are merged.  This file must exist.
 | 
				
			||||||
//           3.  CurrentDirectoryLocation
 | 
					//           2.  If $KUBECONFIG is set, then it is treated as a list of files that should be merged.
 | 
				
			||||||
//           4.  HomeDirectoryLocation
 | 
					//			 3.  HomeDirectoryLocation
 | 
				
			||||||
//           Empty filenames are ignored.  Files with non-deserializable content produced errors.
 | 
					//           Empty filenames are ignored.  Files with non-deserializable content produced errors.
 | 
				
			||||||
//           The first file to set a particular value or map key wins and the value or map key is never changed.
 | 
					//           The first file to set a particular value or map key wins and the value or map key is never changed.
 | 
				
			||||||
//           This means that the first file to set CurrentContext will have its context preserved.  It also means
 | 
					//           This means that the first file to set CurrentContext will have its context preserved.  It also means
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user