mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-24 04:06:03 +00:00
add flattening and minifying options to config view
This commit is contained in:
parent
d02139d2b4
commit
bac5cbbe82
@ -530,9 +530,11 @@ _kubectl_config_view()
|
||||
flags_with_completion=()
|
||||
flags_completion=()
|
||||
|
||||
flags+=("--flatten")
|
||||
flags+=("--help")
|
||||
flags+=("-h")
|
||||
flags+=("--merge")
|
||||
flags+=("--minify")
|
||||
flags+=("--no-headers")
|
||||
flags+=("--output=")
|
||||
two_word_flags+=("-o")
|
||||
|
@ -66,4 +66,4 @@ kubectl
|
||||
* [kubectl update](kubectl_update.md) - Update a resource by filename or stdin.
|
||||
* [kubectl version](kubectl_version.md) - Print the client and server version information.
|
||||
|
||||
###### Auto generated by spf13/cobra at 2015-04-12 19:00:26.865844658 +0000 UTC
|
||||
###### Auto generated by spf13/cobra at 2015-04-14 14:22:51.453079685 +0000 UTC
|
||||
|
@ -50,4 +50,4 @@ kubectl api-versions
|
||||
### SEE ALSO
|
||||
* [kubectl](kubectl.md) - kubectl controls the Kubernetes cluster manager
|
||||
|
||||
###### Auto generated by spf13/cobra at 2015-04-12 19:00:26.865438603 +0000 UTC
|
||||
###### Auto generated by spf13/cobra at 2015-04-14 14:22:51.452805417 +0000 UTC
|
||||
|
@ -50,4 +50,4 @@ kubectl cluster-info
|
||||
### SEE ALSO
|
||||
* [kubectl](kubectl.md) - kubectl controls the Kubernetes cluster manager
|
||||
|
||||
###### Auto generated by spf13/cobra at 2015-04-12 19:00:26.865291243 +0000 UTC
|
||||
###### Auto generated by spf13/cobra at 2015-04-14 14:22:51.452687658 +0000 UTC
|
||||
|
@ -58,6 +58,6 @@ kubectl config SUBCOMMAND
|
||||
* [kubectl config set-credentials](kubectl_config_set-credentials.md) - Sets a user entry in kubeconfig
|
||||
* [kubectl config unset](kubectl_config_unset.md) - Unsets an individual value 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-12 19:00:26.86513156 +0000 UTC
|
||||
###### Auto generated by spf13/cobra at 2015-04-14 14:22:51.452570294 +0000 UTC
|
||||
|
@ -68,4 +68,4 @@ $ kubectl config set-cluster e2e --insecure-skip-tls-verify=true
|
||||
### SEE ALSO
|
||||
* [kubectl config](kubectl_config.md) - config modifies kubeconfig files
|
||||
|
||||
###### Auto generated by spf13/cobra at 2015-04-12 19:00:26.864096021 +0000 UTC
|
||||
###### Auto generated by spf13/cobra at 2015-04-14 14:22:51.451768559 +0000 UTC
|
||||
|
@ -61,4 +61,4 @@ $ kubectl config set-context gce --user=cluster-admin
|
||||
### SEE ALSO
|
||||
* [kubectl config](kubectl_config.md) - config modifies kubeconfig files
|
||||
|
||||
###### Auto generated by spf13/cobra at 2015-04-12 19:00:26.86442717 +0000 UTC
|
||||
###### Auto generated by spf13/cobra at 2015-04-14 14:22:51.452031181 +0000 UTC
|
||||
|
@ -81,4 +81,4 @@ $ kubectl set-credentials cluster-admin --client-certificate=~/.kube/admin.crt -
|
||||
### SEE ALSO
|
||||
* [kubectl config](kubectl_config.md) - config modifies kubeconfig files
|
||||
|
||||
###### Auto generated by spf13/cobra at 2015-04-12 19:00:26.864263862 +0000 UTC
|
||||
###### Auto generated by spf13/cobra at 2015-04-14 14:22:51.451906112 +0000 UTC
|
||||
|
@ -55,4 +55,4 @@ kubectl config set PROPERTY_NAME PROPERTY_VALUE
|
||||
### SEE ALSO
|
||||
* [kubectl config](kubectl_config.md) - config modifies kubeconfig files
|
||||
|
||||
###### Auto generated by spf13/cobra at 2015-04-12 19:00:26.864594301 +0000 UTC
|
||||
###### Auto generated by spf13/cobra at 2015-04-14 14:22:51.45217009 +0000 UTC
|
||||
|
@ -54,4 +54,4 @@ kubectl config unset PROPERTY_NAME
|
||||
### SEE ALSO
|
||||
* [kubectl config](kubectl_config.md) - config modifies kubeconfig files
|
||||
|
||||
###### Auto generated by spf13/cobra at 2015-04-12 19:00:26.864788809 +0000 UTC
|
||||
###### Auto generated by spf13/cobra at 2015-04-14 14:22:51.452318625 +0000 UTC
|
||||
|
@ -53,4 +53,4 @@ kubectl config use-context CONTEXT_NAME
|
||||
### SEE ALSO
|
||||
* [kubectl config](kubectl_config.md) - config modifies kubeconfig files
|
||||
|
||||
###### Auto generated by spf13/cobra at 2015-04-12 19:00:26.864953658 +0000 UTC
|
||||
###### Auto generated by spf13/cobra at 2015-04-14 14:22:51.452447654 +0000 UTC
|
||||
|
@ -1,11 +1,11 @@
|
||||
## kubectl config view
|
||||
|
||||
displays merged kubeconfig settings or a specified kubeconfig file.
|
||||
displays Merged kubeconfig settings or a specified kubeconfig file.
|
||||
|
||||
### Synopsis
|
||||
|
||||
|
||||
displays merged kubeconfig settings or a specified kubeconfig file.
|
||||
displays Merged kubeconfig settings or a specified kubeconfig file.
|
||||
|
||||
You can use --output=template --template=TEMPLATE to extract specific values.
|
||||
|
||||
@ -16,7 +16,7 @@ kubectl config view
|
||||
### Examples
|
||||
|
||||
```
|
||||
// Show merged kubeconfig settings.
|
||||
// Show Merged kubeconfig settings.
|
||||
$ kubectl config view
|
||||
|
||||
// Show only local kubeconfig settings
|
||||
@ -29,8 +29,10 @@ $ kubectl config view -o template --template='{{range .users}}{{ if eq .name "e2
|
||||
### Options
|
||||
|
||||
```
|
||||
--flatten=false: flatten the resulting kubeconfig file into self contained output (useful for creating portable kubeconfig files)
|
||||
-h, --help=false: help for view
|
||||
--merge=true: merge together the full hierarchy of kubeconfig files
|
||||
--minify=false: remove all information not used by current-context from the output
|
||||
--no-headers=false: When using the default output, don't print headers.
|
||||
-o, --output="": Output format. One of: json|yaml|template|templatefile.
|
||||
--output-version="": Output the formatted object with the given version (default api-version).
|
||||
@ -73,4 +75,4 @@ $ kubectl config view -o template --template='{{range .users}}{{ if eq .name "e2
|
||||
### SEE ALSO
|
||||
* [kubectl config](kubectl_config.md) - config modifies kubeconfig files
|
||||
|
||||
###### Auto generated by spf13/cobra at 2015-04-12 19:00:26.863759642 +0000 UTC
|
||||
###### Auto generated by spf13/cobra at 2015-04-14 14:22:51.451646336 +0000 UTC
|
||||
|
@ -63,4 +63,4 @@ $ cat pod.json | kubectl create -f -
|
||||
### SEE ALSO
|
||||
* [kubectl](kubectl.md) - kubectl controls the Kubernetes cluster manager
|
||||
|
||||
###### Auto generated by spf13/cobra at 2015-04-12 19:00:26.858089037 +0000 UTC
|
||||
###### Auto generated by spf13/cobra at 2015-04-14 14:22:51.44924428 +0000 UTC
|
||||
|
@ -81,4 +81,4 @@ $ kubectl delete pods --all
|
||||
### SEE ALSO
|
||||
* [kubectl](kubectl.md) - kubectl controls the Kubernetes cluster manager
|
||||
|
||||
###### Auto generated by spf13/cobra at 2015-04-12 19:00:26.858739718 +0000 UTC
|
||||
###### Auto generated by spf13/cobra at 2015-04-14 14:22:51.449502668 +0000 UTC
|
||||
|
@ -53,4 +53,4 @@ kubectl describe RESOURCE ID
|
||||
### SEE ALSO
|
||||
* [kubectl](kubectl.md) - kubectl controls the Kubernetes cluster manager
|
||||
|
||||
###### Auto generated by spf13/cobra at 2015-04-12 19:00:26.857744518 +0000 UTC
|
||||
###### Auto generated by spf13/cobra at 2015-04-14 14:22:51.449099339 +0000 UTC
|
||||
|
@ -64,4 +64,4 @@ $ kubectl exec -p 123456-7890 -c ruby-container -i -t -- bash -il
|
||||
### SEE ALSO
|
||||
* [kubectl](kubectl.md) - kubectl controls the Kubernetes cluster manager
|
||||
|
||||
###### Auto generated by spf13/cobra at 2015-04-12 19:00:26.860311374 +0000 UTC
|
||||
###### Auto generated by spf13/cobra at 2015-04-14 14:22:51.450677119 +0000 UTC
|
||||
|
@ -82,4 +82,4 @@ $ kubectl expose streamer --port=4100 --protocol=udp --service-name=video-stream
|
||||
### SEE ALSO
|
||||
* [kubectl](kubectl.md) - kubectl controls the Kubernetes cluster manager
|
||||
|
||||
###### Auto generated by spf13/cobra at 2015-04-12 19:00:26.863051668 +0000 UTC
|
||||
###### Auto generated by spf13/cobra at 2015-04-14 14:22:51.451362859 +0000 UTC
|
||||
|
@ -85,4 +85,4 @@ $ kubectl get rc/web service/frontend pods/web-pod-13je7
|
||||
### SEE ALSO
|
||||
* [kubectl](kubectl.md) - kubectl controls the Kubernetes cluster manager
|
||||
|
||||
###### Auto generated by spf13/cobra at 2015-04-12 19:00:26.836684094 +0000 UTC
|
||||
###### Auto generated by spf13/cobra at 2015-04-14 14:22:51.448937009 +0000 UTC
|
||||
|
@ -81,4 +81,4 @@ $ kubectl label pods foo bar-
|
||||
### SEE ALSO
|
||||
* [kubectl](kubectl.md) - kubectl controls the Kubernetes cluster manager
|
||||
|
||||
###### Auto generated by spf13/cobra at 2015-04-12 19:00:26.863412074 +0000 UTC
|
||||
###### Auto generated by spf13/cobra at 2015-04-14 14:22:51.45150424 +0000 UTC
|
||||
|
@ -62,4 +62,4 @@ $ kubectl log -f 123456-7890 ruby-container
|
||||
### SEE ALSO
|
||||
* [kubectl](kubectl.md) - kubectl controls the Kubernetes cluster manager
|
||||
|
||||
###### Auto generated by spf13/cobra at 2015-04-12 19:00:26.859351191 +0000 UTC
|
||||
###### Auto generated by spf13/cobra at 2015-04-14 14:22:51.450201574 +0000 UTC
|
||||
|
@ -53,4 +53,4 @@ kubectl namespace [namespace]
|
||||
### SEE ALSO
|
||||
* [kubectl](kubectl.md) - kubectl controls the Kubernetes cluster manager
|
||||
|
||||
###### Auto generated by spf13/cobra at 2015-04-12 19:00:26.859053402 +0000 UTC
|
||||
###### Auto generated by spf13/cobra at 2015-04-14 14:22:51.449618977 +0000 UTC
|
||||
|
@ -68,4 +68,4 @@ $ kubectl port-forward -p mypod 0:5000
|
||||
### SEE ALSO
|
||||
* [kubectl](kubectl.md) - kubectl controls the Kubernetes cluster manager
|
||||
|
||||
###### Auto generated by spf13/cobra at 2015-04-12 19:00:26.860596821 +0000 UTC
|
||||
###### Auto generated by spf13/cobra at 2015-04-14 14:22:51.45080362 +0000 UTC
|
||||
|
@ -65,4 +65,4 @@ $ kubectl proxy --api-prefix=k8s-api
|
||||
### SEE ALSO
|
||||
* [kubectl](kubectl.md) - kubectl controls the Kubernetes cluster manager
|
||||
|
||||
###### Auto generated by spf13/cobra at 2015-04-12 19:00:26.860912037 +0000 UTC
|
||||
###### Auto generated by spf13/cobra at 2015-04-14 14:22:51.45092701 +0000 UTC
|
||||
|
@ -68,4 +68,4 @@ $ kubectl resize --current-replicas=2 --replicas=3 replicationcontrollers foo
|
||||
### SEE ALSO
|
||||
* [kubectl](kubectl.md) - kubectl controls the Kubernetes cluster manager
|
||||
|
||||
###### Auto generated by spf13/cobra at 2015-04-12 19:00:26.859972905 +0000 UTC
|
||||
###### Auto generated by spf13/cobra at 2015-04-14 14:22:51.450528897 +0000 UTC
|
||||
|
@ -68,4 +68,4 @@ $ cat frontend-v2.json | kubectl rolling-update frontend-v1 -f -
|
||||
### SEE ALSO
|
||||
* [kubectl](kubectl.md) - kubectl controls the Kubernetes cluster manager
|
||||
|
||||
###### Auto generated by spf13/cobra at 2015-04-12 19:00:26.859654934 +0000 UTC
|
||||
###### Auto generated by spf13/cobra at 2015-04-14 14:22:51.450394023 +0000 UTC
|
||||
|
@ -78,4 +78,4 @@ $ kubectl run-container nginx --image=dockerfile/nginx --overrides='{ "apiVersio
|
||||
### SEE ALSO
|
||||
* [kubectl](kubectl.md) - kubectl controls the Kubernetes cluster manager
|
||||
|
||||
###### Auto generated by spf13/cobra at 2015-04-12 19:00:26.861280128 +0000 UTC
|
||||
###### Auto generated by spf13/cobra at 2015-04-14 14:22:51.4510703 +0000 UTC
|
||||
|
@ -72,4 +72,4 @@ $ kubectl stop -f path/to/resources
|
||||
### SEE ALSO
|
||||
* [kubectl](kubectl.md) - kubectl controls the Kubernetes cluster manager
|
||||
|
||||
###### Auto generated by spf13/cobra at 2015-04-12 19:00:26.862654585 +0000 UTC
|
||||
###### Auto generated by spf13/cobra at 2015-04-14 14:22:51.451196696 +0000 UTC
|
||||
|
@ -67,4 +67,4 @@ $ kubectl update pods my-pod --patch='{ "apiVersion": "v1beta1", "desiredState":
|
||||
### SEE ALSO
|
||||
* [kubectl](kubectl.md) - kubectl controls the Kubernetes cluster manager
|
||||
|
||||
###### Auto generated by spf13/cobra at 2015-04-12 19:00:26.858390462 +0000 UTC
|
||||
###### Auto generated by spf13/cobra at 2015-04-14 14:22:51.449377932 +0000 UTC
|
||||
|
@ -51,4 +51,4 @@ kubectl version
|
||||
### SEE ALSO
|
||||
* [kubectl](kubectl.md) - kubectl controls the Kubernetes cluster manager
|
||||
|
||||
###### Auto generated by spf13/cobra at 2015-04-12 19:00:26.865600008 +0000 UTC
|
||||
###### Auto generated by spf13/cobra at 2015-04-14 14:22:51.452926558 +0000 UTC
|
||||
|
@ -3,7 +3,7 @@
|
||||
|
||||
.SH NAME
|
||||
.PP
|
||||
kubectl config view \- displays merged kubeconfig settings or a specified kubeconfig file.
|
||||
kubectl config view \- displays Merged kubeconfig settings or a specified kubeconfig file.
|
||||
|
||||
|
||||
.SH SYNOPSIS
|
||||
@ -13,13 +13,17 @@ kubectl config view \- displays merged kubeconfig settings or a specified kubeco
|
||||
|
||||
.SH DESCRIPTION
|
||||
.PP
|
||||
displays merged kubeconfig settings or a specified kubeconfig file.
|
||||
displays Merged kubeconfig settings or a specified kubeconfig file.
|
||||
|
||||
.PP
|
||||
You can use \-\-output=template \-\-template=TEMPLATE to extract specific values.
|
||||
|
||||
|
||||
.SH OPTIONS
|
||||
.PP
|
||||
\fB\-\-flatten\fP=false
|
||||
flatten the resulting kubeconfig file into self contained output (useful for creating portable kubeconfig files)
|
||||
|
||||
.PP
|
||||
\fB\-h\fP, \fB\-\-help\fP=false
|
||||
help for view
|
||||
@ -28,6 +32,10 @@ You can use \-\-output=template \-\-template=TEMPLATE to extract specific values
|
||||
\fB\-\-merge\fP=true
|
||||
merge together the full hierarchy of kubeconfig files
|
||||
|
||||
.PP
|
||||
\fB\-\-minify\fP=false
|
||||
remove all information not used by current\-context from the output
|
||||
|
||||
.PP
|
||||
\fB\-\-no\-headers\fP=false
|
||||
When using the default output, don't print headers.
|
||||
@ -165,7 +173,7 @@ You can use \-\-output=template \-\-template=TEMPLATE to extract specific values
|
||||
.RS
|
||||
|
||||
.nf
|
||||
// Show merged kubeconfig settings.
|
||||
// Show Merged kubeconfig settings.
|
||||
$ kubectl config view
|
||||
|
||||
// Show only local kubeconfig settings
|
||||
|
149
pkg/client/clientcmd/api/helpers.go
Normal file
149
pkg/client/clientcmd/api/helpers.go
Normal file
@ -0,0 +1,149 @@
|
||||
/*
|
||||
Copyright 2015 Google Inc. All rights reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package api
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path"
|
||||
"path/filepath"
|
||||
)
|
||||
|
||||
// MinifyConfig read the current context and uses that to keep only the relevant pieces of config
|
||||
// This is useful for making secrets based on kubeconfig files
|
||||
func MinifyConfig(config *Config) error {
|
||||
if len(config.CurrentContext) == 0 {
|
||||
return errors.New("current-context must exist in order to minify")
|
||||
}
|
||||
|
||||
currContext, exists := config.Contexts[config.CurrentContext]
|
||||
if !exists {
|
||||
return fmt.Errorf("cannot locate context %v", config.CurrentContext)
|
||||
}
|
||||
|
||||
newContexts := map[string]Context{}
|
||||
newContexts[config.CurrentContext] = currContext
|
||||
|
||||
newClusters := map[string]Cluster{}
|
||||
if len(currContext.Cluster) > 0 {
|
||||
if _, exists := config.Clusters[currContext.Cluster]; !exists {
|
||||
return fmt.Errorf("cannot locate cluster %v", currContext.Cluster)
|
||||
}
|
||||
|
||||
newClusters[currContext.Cluster] = config.Clusters[currContext.Cluster]
|
||||
}
|
||||
|
||||
newAuthInfos := map[string]AuthInfo{}
|
||||
if len(currContext.AuthInfo) > 0 {
|
||||
if _, exists := config.AuthInfos[currContext.AuthInfo]; !exists {
|
||||
return fmt.Errorf("cannot locate user %v", currContext.AuthInfo)
|
||||
}
|
||||
|
||||
newAuthInfos[currContext.AuthInfo] = config.AuthInfos[currContext.AuthInfo]
|
||||
}
|
||||
|
||||
config.AuthInfos = newAuthInfos
|
||||
config.Clusters = newClusters
|
||||
config.Contexts = newContexts
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Flatten changes the config object into a self contained config (useful for making secrets)
|
||||
// AuthPath is not handled.
|
||||
func FlattenConfig(config *Config) error {
|
||||
for key, authInfo := range config.AuthInfos {
|
||||
baseDir, err := MakeAbs(path.Dir(authInfo.LocationOfOrigin), "")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if len(authInfo.AuthPath) != 0 {
|
||||
return fmt.Errorf("auth path of %v is not empty: %v", key, authInfo.AuthPath)
|
||||
}
|
||||
|
||||
if err := FlattenContent(&authInfo.ClientCertificate, &authInfo.ClientCertificateData, baseDir); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := FlattenContent(&authInfo.ClientKey, &authInfo.ClientKeyData, baseDir); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
config.AuthInfos[key] = authInfo
|
||||
}
|
||||
for key, cluster := range config.Clusters {
|
||||
baseDir, err := MakeAbs(path.Dir(cluster.LocationOfOrigin), "")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := FlattenContent(&cluster.CertificateAuthority, &cluster.CertificateAuthorityData, baseDir); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
config.Clusters[key] = cluster
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func FlattenContent(path *string, contents *[]byte, baseDir string) error {
|
||||
if len(*path) != 0 {
|
||||
if len(*contents) > 0 {
|
||||
return errors.New("cannot have values for both path and contents")
|
||||
}
|
||||
|
||||
var err error
|
||||
absPath := ResolvePath(*path, baseDir)
|
||||
*contents, err = ioutil.ReadFile(absPath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
*path = ""
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// ResolvePath returns the path as an absolute paths, relative to the given base directory
|
||||
func ResolvePath(path string, base string) string {
|
||||
// Don't resolve empty paths
|
||||
if len(path) > 0 {
|
||||
// Don't resolve absolute paths
|
||||
if !filepath.IsAbs(path) {
|
||||
return filepath.Join(base, path)
|
||||
}
|
||||
}
|
||||
|
||||
return path
|
||||
}
|
||||
|
||||
func MakeAbs(path, base string) (string, error) {
|
||||
if filepath.IsAbs(path) {
|
||||
return path, nil
|
||||
}
|
||||
if len(base) == 0 {
|
||||
cwd, err := os.Getwd()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
base = cwd
|
||||
}
|
||||
return filepath.Join(base, path), nil
|
||||
}
|
204
pkg/client/clientcmd/api/helpers_test.go
Normal file
204
pkg/client/clientcmd/api/helpers_test.go
Normal file
@ -0,0 +1,204 @@
|
||||
/*
|
||||
Copyright 2015 Google Inc. All rights reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package api
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"reflect"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func newMergedConfig(certFile, certContent, keyFile, keyContent, caFile, caContent string, t *testing.T) Config {
|
||||
if err := ioutil.WriteFile(certFile, []byte(certContent), 0644); err != nil {
|
||||
t.Errorf("unexpected error: %v", err)
|
||||
}
|
||||
if err := ioutil.WriteFile(keyFile, []byte(keyContent), 0600); err != nil {
|
||||
t.Errorf("unexpected error: %v", err)
|
||||
}
|
||||
if err := ioutil.WriteFile(caFile, []byte(caContent), 0644); err != nil {
|
||||
t.Errorf("unexpected error: %v", err)
|
||||
}
|
||||
|
||||
return Config{
|
||||
AuthInfos: map[string]AuthInfo{
|
||||
"red-user": {Token: "red-token"},
|
||||
"blue-user": {Token: "blue-token", ClientCertificate: certFile, ClientKey: keyFile}},
|
||||
Clusters: map[string]Cluster{
|
||||
"cow-cluster": {Server: "http://cow.org:8080"},
|
||||
"chicken-cluster": {Server: "http://chicken.org:8080", CertificateAuthority: caFile}},
|
||||
Contexts: map[string]Context{
|
||||
"federal-context": {AuthInfo: "red-user", Cluster: "cow-cluster"},
|
||||
"shaker-context": {AuthInfo: "blue-user", Cluster: "chicken-cluster"}},
|
||||
CurrentContext: "federal-context",
|
||||
}
|
||||
}
|
||||
|
||||
func TestMinifySuccess(t *testing.T) {
|
||||
certFile, _ := ioutil.TempFile("", "")
|
||||
defer os.Remove(certFile.Name())
|
||||
keyFile, _ := ioutil.TempFile("", "")
|
||||
defer os.Remove(keyFile.Name())
|
||||
caFile, _ := ioutil.TempFile("", "")
|
||||
defer os.Remove(caFile.Name())
|
||||
|
||||
mutatingConfig := newMergedConfig(certFile.Name(), "cert", keyFile.Name(), "key", caFile.Name(), "ca", t)
|
||||
|
||||
if err := MinifyConfig(&mutatingConfig); err != nil {
|
||||
t.Errorf("unexpected error: %v", err)
|
||||
}
|
||||
|
||||
if len(mutatingConfig.Contexts) > 1 {
|
||||
t.Errorf("unexpected contexts: %v", mutatingConfig.Contexts)
|
||||
}
|
||||
if _, exists := mutatingConfig.Contexts["federal-context"]; !exists {
|
||||
t.Errorf("missing context")
|
||||
}
|
||||
|
||||
if len(mutatingConfig.Clusters) > 1 {
|
||||
t.Errorf("unexpected clusters: %v", mutatingConfig.Clusters)
|
||||
}
|
||||
if _, exists := mutatingConfig.Clusters["cow-cluster"]; !exists {
|
||||
t.Errorf("missing cluster")
|
||||
}
|
||||
|
||||
if len(mutatingConfig.AuthInfos) > 1 {
|
||||
t.Errorf("unexpected users: %v", mutatingConfig.AuthInfos)
|
||||
}
|
||||
if _, exists := mutatingConfig.AuthInfos["red-user"]; !exists {
|
||||
t.Errorf("missing user")
|
||||
}
|
||||
}
|
||||
|
||||
func TestMinifyMissingContext(t *testing.T) {
|
||||
certFile, _ := ioutil.TempFile("", "")
|
||||
defer os.Remove(certFile.Name())
|
||||
keyFile, _ := ioutil.TempFile("", "")
|
||||
defer os.Remove(keyFile.Name())
|
||||
caFile, _ := ioutil.TempFile("", "")
|
||||
defer os.Remove(caFile.Name())
|
||||
|
||||
mutatingConfig := newMergedConfig(certFile.Name(), "cert", keyFile.Name(), "key", caFile.Name(), "ca", t)
|
||||
mutatingConfig.CurrentContext = "missing"
|
||||
|
||||
errMsg := "cannot locate context missing"
|
||||
|
||||
if err := MinifyConfig(&mutatingConfig); err == nil || err.Error() != errMsg {
|
||||
t.Errorf("expected %v, got %v", errMsg, err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestMinifyMissingCluster(t *testing.T) {
|
||||
certFile, _ := ioutil.TempFile("", "")
|
||||
defer os.Remove(certFile.Name())
|
||||
keyFile, _ := ioutil.TempFile("", "")
|
||||
defer os.Remove(keyFile.Name())
|
||||
caFile, _ := ioutil.TempFile("", "")
|
||||
defer os.Remove(caFile.Name())
|
||||
|
||||
mutatingConfig := newMergedConfig(certFile.Name(), "cert", keyFile.Name(), "key", caFile.Name(), "ca", t)
|
||||
delete(mutatingConfig.Clusters, mutatingConfig.Contexts[mutatingConfig.CurrentContext].Cluster)
|
||||
|
||||
errMsg := "cannot locate cluster cow-cluster"
|
||||
|
||||
if err := MinifyConfig(&mutatingConfig); err == nil || err.Error() != errMsg {
|
||||
t.Errorf("expected %v, got %v", errMsg, err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestMinifyMissingAuthInfo(t *testing.T) {
|
||||
certFile, _ := ioutil.TempFile("", "")
|
||||
defer os.Remove(certFile.Name())
|
||||
keyFile, _ := ioutil.TempFile("", "")
|
||||
defer os.Remove(keyFile.Name())
|
||||
caFile, _ := ioutil.TempFile("", "")
|
||||
defer os.Remove(caFile.Name())
|
||||
|
||||
mutatingConfig := newMergedConfig(certFile.Name(), "cert", keyFile.Name(), "key", caFile.Name(), "ca", t)
|
||||
delete(mutatingConfig.AuthInfos, mutatingConfig.Contexts[mutatingConfig.CurrentContext].AuthInfo)
|
||||
|
||||
errMsg := "cannot locate user red-user"
|
||||
|
||||
if err := MinifyConfig(&mutatingConfig); err == nil || err.Error() != errMsg {
|
||||
t.Errorf("expected %v, got %v", errMsg, err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestFlattenSuccess(t *testing.T) {
|
||||
certFile, _ := ioutil.TempFile("", "")
|
||||
defer os.Remove(certFile.Name())
|
||||
keyFile, _ := ioutil.TempFile("", "")
|
||||
defer os.Remove(keyFile.Name())
|
||||
caFile, _ := ioutil.TempFile("", "")
|
||||
defer os.Remove(caFile.Name())
|
||||
|
||||
certData := "cert"
|
||||
keyData := "key"
|
||||
caData := "ca"
|
||||
|
||||
unchangingCluster := "cow-cluster"
|
||||
unchangingAuthInfo := "red-user"
|
||||
changingCluster := "chicken-cluster"
|
||||
changingAuthInfo := "blue-user"
|
||||
|
||||
startingConfig := newMergedConfig(certFile.Name(), certData, keyFile.Name(), keyData, caFile.Name(), caData, t)
|
||||
mutatingConfig := startingConfig
|
||||
|
||||
if err := FlattenConfig(&mutatingConfig); err != nil {
|
||||
t.Errorf("unexpected error: %v", err)
|
||||
}
|
||||
|
||||
if len(mutatingConfig.Contexts) != 2 {
|
||||
t.Errorf("unexpected contexts: %v", mutatingConfig.Contexts)
|
||||
}
|
||||
if !reflect.DeepEqual(startingConfig.Contexts, mutatingConfig.Contexts) {
|
||||
t.Errorf("expected %v, got %v", startingConfig.Contexts, mutatingConfig.Contexts)
|
||||
}
|
||||
|
||||
if len(mutatingConfig.Clusters) != 2 {
|
||||
t.Errorf("unexpected clusters: %v", mutatingConfig.Clusters)
|
||||
}
|
||||
if !reflect.DeepEqual(startingConfig.Clusters[unchangingCluster], mutatingConfig.Clusters[unchangingCluster]) {
|
||||
t.Errorf("expected %v, got %v", startingConfig.Clusters[unchangingCluster], mutatingConfig.Clusters[unchangingCluster])
|
||||
}
|
||||
if len(mutatingConfig.Clusters[changingCluster].CertificateAuthority) != 0 {
|
||||
t.Errorf("unexpected caFile")
|
||||
}
|
||||
if string(mutatingConfig.Clusters[changingCluster].CertificateAuthorityData) != caData {
|
||||
t.Errorf("expected %v, got %v", caData, string(mutatingConfig.Clusters[changingCluster].CertificateAuthorityData))
|
||||
}
|
||||
|
||||
if len(mutatingConfig.AuthInfos) != 2 {
|
||||
t.Errorf("unexpected users: %v", mutatingConfig.AuthInfos)
|
||||
}
|
||||
if !reflect.DeepEqual(startingConfig.AuthInfos[unchangingAuthInfo], mutatingConfig.AuthInfos[unchangingAuthInfo]) {
|
||||
t.Errorf("expected %v, got %v", startingConfig.AuthInfos[unchangingAuthInfo], mutatingConfig.AuthInfos[unchangingAuthInfo])
|
||||
}
|
||||
if len(mutatingConfig.AuthInfos[changingAuthInfo].ClientCertificate) != 0 {
|
||||
t.Errorf("unexpected caFile")
|
||||
}
|
||||
if string(mutatingConfig.AuthInfos[changingAuthInfo].ClientCertificateData) != certData {
|
||||
t.Errorf("expected %v, got %v", certData, string(mutatingConfig.AuthInfos[changingAuthInfo].ClientCertificateData))
|
||||
}
|
||||
if len(mutatingConfig.AuthInfos[changingAuthInfo].ClientKey) != 0 {
|
||||
t.Errorf("unexpected caFile")
|
||||
}
|
||||
if string(mutatingConfig.AuthInfos[changingAuthInfo].ClientKeyData) != keyData {
|
||||
t.Errorf("expected %v, got %v", keyData, string(mutatingConfig.AuthInfos[changingAuthInfo].ClientKeyData))
|
||||
}
|
||||
|
||||
}
|
@ -39,6 +39,7 @@ func newRedFederalCowHammerConfig() clientcmdapi.Config {
|
||||
"cow-cluster": {Server: "http://cow.org:8080"}},
|
||||
Contexts: map[string]clientcmdapi.Context{
|
||||
"federal-context": {AuthInfo: "red-user", Cluster: "cow-cluster"}},
|
||||
CurrentContext: "federal-context",
|
||||
}
|
||||
}
|
||||
|
||||
@ -70,7 +71,7 @@ func ExampleView() {
|
||||
// cluster: cow-cluster
|
||||
// user: red-user
|
||||
// name: federal-context
|
||||
// current-context: ""
|
||||
// current-context: federal-context
|
||||
// kind: Config
|
||||
// preferences: {}
|
||||
// users:
|
||||
|
@ -31,16 +31,18 @@ import (
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/util"
|
||||
)
|
||||
|
||||
type viewOptions struct {
|
||||
pathOptions *PathOptions
|
||||
merge util.BoolFlag
|
||||
type ViewOptions struct {
|
||||
PathOptions *PathOptions
|
||||
Merge util.BoolFlag
|
||||
Flatten bool
|
||||
Minify bool
|
||||
}
|
||||
|
||||
const (
|
||||
view_long = `displays merged kubeconfig settings or a specified kubeconfig file.
|
||||
view_long = `displays Merged kubeconfig settings or a specified kubeconfig file.
|
||||
|
||||
You can use --output=template --template=TEMPLATE to extract specific values.`
|
||||
view_example = `// Show merged kubeconfig settings.
|
||||
view_example = `// Show Merged kubeconfig settings.
|
||||
$ kubectl config view
|
||||
|
||||
// Show only local kubeconfig settings
|
||||
@ -50,16 +52,16 @@ $ kubectl config view --local
|
||||
$ 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 {
|
||||
options := &viewOptions{pathOptions: pathOptions}
|
||||
func NewCmdConfigView(out io.Writer, PathOptions *PathOptions) *cobra.Command {
|
||||
options := &ViewOptions{PathOptions: PathOptions}
|
||||
|
||||
cmd := &cobra.Command{
|
||||
Use: "view",
|
||||
Short: "displays merged kubeconfig settings or a specified kubeconfig file.",
|
||||
Short: "displays Merged kubeconfig settings or a specified kubeconfig file.",
|
||||
Long: view_long,
|
||||
Example: view_example,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
options.complete()
|
||||
options.Complete()
|
||||
|
||||
printer, _, err := cmdutil.PrinterForCommand(cmd)
|
||||
if err != nil {
|
||||
@ -68,15 +70,10 @@ func NewCmdConfigView(out io.Writer, pathOptions *PathOptions) *cobra.Command {
|
||||
version := cmdutil.OutputVersion(cmd, latest.Version)
|
||||
printer = kubectl.NewVersionedPrinter(printer, clientcmdapi.Scheme, version)
|
||||
|
||||
config, err := options.loadConfig()
|
||||
if err != nil {
|
||||
if err := options.Run(out, printer); err != nil {
|
||||
glog.FatalDepth(1, err)
|
||||
}
|
||||
|
||||
err = printer.PrintObj(config, out)
|
||||
if err != nil {
|
||||
glog.FatalDepth(1, err)
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
@ -84,24 +81,52 @@ func NewCmdConfigView(out io.Writer, pathOptions *PathOptions) *cobra.Command {
|
||||
// Default to yaml
|
||||
cmd.Flags().Set("output", "yaml")
|
||||
|
||||
options.merge.Default(true)
|
||||
cmd.Flags().Var(&options.merge, "merge", "merge together the full hierarchy of kubeconfig files")
|
||||
options.Merge.Default(true)
|
||||
cmd.Flags().Var(&options.Merge, "merge", "merge together the full hierarchy of kubeconfig files")
|
||||
cmd.Flags().BoolVar(&options.Flatten, "flatten", false, "flatten the resulting kubeconfig file into self contained output (useful for creating portable kubeconfig files)")
|
||||
cmd.Flags().BoolVar(&options.Minify, "minify", false, "remove all information not used by current-context from the output")
|
||||
return cmd
|
||||
}
|
||||
|
||||
func (o *viewOptions) complete() bool {
|
||||
func (o ViewOptions) Run(out io.Writer, printer kubectl.ResourcePrinter) error {
|
||||
config, err := o.loadConfig()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if o.Minify {
|
||||
if err := clientcmdapi.MinifyConfig(config); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if o.Flatten {
|
||||
if err := clientcmdapi.FlattenConfig(config); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
err = printer.PrintObj(config, out)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
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 o.pathOptions.Global || o.pathOptions.Local || o.pathOptions.UseEnvVar {
|
||||
if !o.merge.Provided() {
|
||||
o.merge.Set("false")
|
||||
if o.PathOptions.Global || o.PathOptions.Local || o.PathOptions.UseEnvVar {
|
||||
if !o.Merge.Provided() {
|
||||
o.Merge.Set("false")
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
func (o viewOptions) loadConfig() (*clientcmdapi.Config, error) {
|
||||
err := o.validate()
|
||||
func (o ViewOptions) loadConfig() (*clientcmdapi.Config, error) {
|
||||
err := o.Validate()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -110,33 +135,33 @@ func (o viewOptions) loadConfig() (*clientcmdapi.Config, error) {
|
||||
return config, err
|
||||
}
|
||||
|
||||
func (o viewOptions) validate() error {
|
||||
return o.pathOptions.Validate()
|
||||
func (o ViewOptions) Validate() error {
|
||||
return o.PathOptions.Validate()
|
||||
}
|
||||
|
||||
// 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 {
|
||||
case !o.merge.Value():
|
||||
case !o.Merge.Value():
|
||||
switch {
|
||||
case len(o.pathOptions.LoadingRules.ExplicitPath) > 0:
|
||||
return clientcmd.LoadFromFile(o.pathOptions.LoadingRules.ExplicitPath)
|
||||
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.Global:
|
||||
return clientcmd.LoadFromFile(o.PathOptions.GlobalFile)
|
||||
|
||||
case o.pathOptions.UseEnvVar:
|
||||
return clientcmd.LoadFromFile(o.pathOptions.EnvVarFile)
|
||||
case o.PathOptions.UseEnvVar:
|
||||
return clientcmd.LoadFromFile(o.PathOptions.EnvVarFile)
|
||||
|
||||
case o.pathOptions.Local:
|
||||
return clientcmd.LoadFromFile(o.pathOptions.LocalFile)
|
||||
case o.PathOptions.Local:
|
||||
return clientcmd.LoadFromFile(o.PathOptions.LocalFile)
|
||||
|
||||
default:
|
||||
return nil, errors.New("if merge==false a precise file must to specified")
|
||||
return nil, errors.New("if Merge==false a precise file must to specified")
|
||||
|
||||
}
|
||||
|
||||
default:
|
||||
return o.pathOptions.getStartingConfig()
|
||||
return o.PathOptions.getStartingConfig()
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user