mirror of
				https://github.com/optim-enterprises-bv/kubernetes.git
				synced 2025-11-04 04:08:16 +00:00 
			
		
		
		
	resolve relative paths in kubeconfig
This commit is contained in:
		@@ -19,6 +19,7 @@ package clientcmd
 | 
				
			|||||||
import (
 | 
					import (
 | 
				
			||||||
	"io/ioutil"
 | 
						"io/ioutil"
 | 
				
			||||||
	"os"
 | 
						"os"
 | 
				
			||||||
 | 
						"path/filepath"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"github.com/ghodss/yaml"
 | 
						"github.com/ghodss/yaml"
 | 
				
			||||||
	"github.com/imdario/mergo"
 | 
						"github.com/imdario/mergo"
 | 
				
			||||||
@@ -59,13 +60,22 @@ func NewClientConfigLoadingRules() *ClientConfigLoadingRules {
 | 
				
			|||||||
// 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
 | 
				
			||||||
// that if two files specify a "red-user", only values from the first file's red-user are used.  Even
 | 
					// 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.
 | 
					// non-conflicting entries from the second file's "red-user" are discarded.
 | 
				
			||||||
 | 
					// Relative paths inside of the .kubeconfig files are resolved against the .kubeconfig file's parent folder
 | 
				
			||||||
 | 
					// and only absolute file paths are returned.
 | 
				
			||||||
func (rules *ClientConfigLoadingRules) Load() (*clientcmdapi.Config, error) {
 | 
					func (rules *ClientConfigLoadingRules) Load() (*clientcmdapi.Config, error) {
 | 
				
			||||||
	config := clientcmdapi.NewConfig()
 | 
						config := clientcmdapi.NewConfig()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	mergeConfigWithFile(config, rules.CommandLinePath)
 | 
						mergeConfigWithFile(config, rules.CommandLinePath)
 | 
				
			||||||
 | 
						resolveLocalPaths(rules.CommandLinePath, config)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	mergeConfigWithFile(config, rules.EnvVarPath)
 | 
						mergeConfigWithFile(config, rules.EnvVarPath)
 | 
				
			||||||
 | 
						resolveLocalPaths(rules.EnvVarPath, config)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	mergeConfigWithFile(config, rules.CurrentDirectoryPath)
 | 
						mergeConfigWithFile(config, rules.CurrentDirectoryPath)
 | 
				
			||||||
 | 
						resolveLocalPaths(rules.CurrentDirectoryPath, config)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	mergeConfigWithFile(config, rules.HomeDirectoryPath)
 | 
						mergeConfigWithFile(config, rules.HomeDirectoryPath)
 | 
				
			||||||
 | 
						resolveLocalPaths(rules.HomeDirectoryPath, config)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return config, nil
 | 
						return config, nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -86,6 +96,50 @@ func mergeConfigWithFile(startingConfig *clientcmdapi.Config, filename string) e
 | 
				
			|||||||
	return nil
 | 
						return nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// resolveLocalPaths resolves all relative paths in the config object with respect to the parent directory of the filename
 | 
				
			||||||
 | 
					// this cannot be done directly inside of LoadFromFile because doing so there would make it impossible to load a file without
 | 
				
			||||||
 | 
					// modification of its contents.
 | 
				
			||||||
 | 
					func resolveLocalPaths(filename string, config *clientcmdapi.Config) error {
 | 
				
			||||||
 | 
						if len(filename) == 0 {
 | 
				
			||||||
 | 
							return nil
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						configDir, err := filepath.Abs(filepath.Dir(filename))
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						resolvedClusters := make(map[string]clientcmdapi.Cluster)
 | 
				
			||||||
 | 
						for key, cluster := range config.Clusters {
 | 
				
			||||||
 | 
							cluster.CertificateAuthority = resolveLocalPath(configDir, cluster.CertificateAuthority)
 | 
				
			||||||
 | 
							resolvedClusters[key] = cluster
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						config.Clusters = resolvedClusters
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						resolvedAuthInfos := make(map[string]clientcmdapi.AuthInfo)
 | 
				
			||||||
 | 
						for key, authInfo := range config.AuthInfos {
 | 
				
			||||||
 | 
							authInfo.AuthPath = resolveLocalPath(configDir, authInfo.AuthPath)
 | 
				
			||||||
 | 
							authInfo.ClientCertificate = resolveLocalPath(configDir, authInfo.ClientCertificate)
 | 
				
			||||||
 | 
							authInfo.ClientKey = resolveLocalPath(configDir, authInfo.ClientKey)
 | 
				
			||||||
 | 
							resolvedAuthInfos[key] = authInfo
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						config.AuthInfos = resolvedAuthInfos
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// resolveLocalPath makes the path absolute with respect to the startingDir
 | 
				
			||||||
 | 
					func resolveLocalPath(startingDir, path string) string {
 | 
				
			||||||
 | 
						if len(path) == 0 {
 | 
				
			||||||
 | 
							return path
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if filepath.IsAbs(path) {
 | 
				
			||||||
 | 
							return path
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return filepath.Join(startingDir, path)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// LoadFromFile takes a filename and deserializes the contents into Config object
 | 
					// LoadFromFile takes a filename and deserializes the contents into Config object
 | 
				
			||||||
func LoadFromFile(filename string) (*clientcmdapi.Config, error) {
 | 
					func LoadFromFile(filename string) (*clientcmdapi.Config, error) {
 | 
				
			||||||
	config := &clientcmdapi.Config{}
 | 
						config := &clientcmdapi.Config{}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -20,6 +20,9 @@ import (
 | 
				
			|||||||
	"fmt"
 | 
						"fmt"
 | 
				
			||||||
	"io/ioutil"
 | 
						"io/ioutil"
 | 
				
			||||||
	"os"
 | 
						"os"
 | 
				
			||||||
 | 
						"path"
 | 
				
			||||||
 | 
						"path/filepath"
 | 
				
			||||||
 | 
						"testing"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"github.com/ghodss/yaml"
 | 
						"github.com/ghodss/yaml"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -71,6 +74,107 @@ var (
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TestResolveRelativePaths(t *testing.T) {
 | 
				
			||||||
 | 
						pathResolutionConfig1 := clientcmdapi.Config{
 | 
				
			||||||
 | 
							AuthInfos: map[string]clientcmdapi.AuthInfo{
 | 
				
			||||||
 | 
								"relative-user-1": {ClientCertificate: "relative/client/cert", ClientKey: "../relative/client/key", AuthPath: "../../relative/auth/path"},
 | 
				
			||||||
 | 
								"absolute-user-1": {ClientCertificate: "/absolute/client/cert", ClientKey: "/absolute/client/key", AuthPath: "/absolute/auth/path"},
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							Clusters: map[string]clientcmdapi.Cluster{
 | 
				
			||||||
 | 
								"relative-server-1": {CertificateAuthority: "../relative/ca"},
 | 
				
			||||||
 | 
								"absolute-server-1": {CertificateAuthority: "/absolute/ca"},
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						pathResolutionConfig2 := clientcmdapi.Config{
 | 
				
			||||||
 | 
							AuthInfos: map[string]clientcmdapi.AuthInfo{
 | 
				
			||||||
 | 
								"relative-user-2": {ClientCertificate: "relative/client/cert2", ClientKey: "../relative/client/key2", AuthPath: "../../relative/auth/path2"},
 | 
				
			||||||
 | 
								"absolute-user-2": {ClientCertificate: "/absolute/client/cert2", ClientKey: "/absolute/client/key2", AuthPath: "/absolute/auth/path2"},
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							Clusters: map[string]clientcmdapi.Cluster{
 | 
				
			||||||
 | 
								"relative-server-2": {CertificateAuthority: "../relative/ca2"},
 | 
				
			||||||
 | 
								"absolute-server-2": {CertificateAuthority: "/absolute/ca2"},
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						configDir1, _ := ioutil.TempDir("", "")
 | 
				
			||||||
 | 
						configFile1 := path.Join(configDir1, ".kubeconfig")
 | 
				
			||||||
 | 
						configDir1, _ = filepath.Abs(configDir1)
 | 
				
			||||||
 | 
						defer os.Remove(configFile1)
 | 
				
			||||||
 | 
						configDir2, _ := ioutil.TempDir("", "")
 | 
				
			||||||
 | 
						configDir2, _ = ioutil.TempDir(configDir2, "")
 | 
				
			||||||
 | 
						configFile2 := path.Join(configDir2, ".kubeconfig")
 | 
				
			||||||
 | 
						configDir2, _ = filepath.Abs(configDir2)
 | 
				
			||||||
 | 
						defer os.Remove(configFile2)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						WriteToFile(pathResolutionConfig1, configFile1)
 | 
				
			||||||
 | 
						WriteToFile(pathResolutionConfig2, configFile2)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						loadingRules := ClientConfigLoadingRules{
 | 
				
			||||||
 | 
							CommandLinePath: configFile1,
 | 
				
			||||||
 | 
							EnvVarPath:      configFile2,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						mergedConfig, err := loadingRules.Load()
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							t.Errorf("Unexpected error: %v", err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						foundClusterCount := 0
 | 
				
			||||||
 | 
						for key, cluster := range mergedConfig.Clusters {
 | 
				
			||||||
 | 
							if key == "relative-server-1" {
 | 
				
			||||||
 | 
								foundClusterCount++
 | 
				
			||||||
 | 
								matchStringArg(path.Join(configDir1, pathResolutionConfig1.Clusters["relative-server-1"].CertificateAuthority), cluster.CertificateAuthority, t)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if key == "relative-server-2" {
 | 
				
			||||||
 | 
								foundClusterCount++
 | 
				
			||||||
 | 
								matchStringArg(path.Join(configDir2, pathResolutionConfig2.Clusters["relative-server-2"].CertificateAuthority), cluster.CertificateAuthority, t)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if key == "absolute-server-1" {
 | 
				
			||||||
 | 
								foundClusterCount++
 | 
				
			||||||
 | 
								matchStringArg(pathResolutionConfig1.Clusters["absolute-server-1"].CertificateAuthority, cluster.CertificateAuthority, t)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if key == "absolute-server-2" {
 | 
				
			||||||
 | 
								foundClusterCount++
 | 
				
			||||||
 | 
								matchStringArg(pathResolutionConfig2.Clusters["absolute-server-2"].CertificateAuthority, cluster.CertificateAuthority, t)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if foundClusterCount != 4 {
 | 
				
			||||||
 | 
							t.Errorf("Expected 4 clusters, found %v: %v", foundClusterCount, mergedConfig.Clusters)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						foundAuthInfoCount := 0
 | 
				
			||||||
 | 
						for key, authInfo := range mergedConfig.AuthInfos {
 | 
				
			||||||
 | 
							if key == "relative-user-1" {
 | 
				
			||||||
 | 
								foundAuthInfoCount++
 | 
				
			||||||
 | 
								matchStringArg(path.Join(configDir1, pathResolutionConfig1.AuthInfos["relative-user-1"].ClientCertificate), authInfo.ClientCertificate, t)
 | 
				
			||||||
 | 
								matchStringArg(path.Join(configDir1, pathResolutionConfig1.AuthInfos["relative-user-1"].ClientKey), authInfo.ClientKey, t)
 | 
				
			||||||
 | 
								matchStringArg(path.Join(configDir1, pathResolutionConfig1.AuthInfos["relative-user-1"].AuthPath), authInfo.AuthPath, t)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if key == "relative-user-2" {
 | 
				
			||||||
 | 
								foundAuthInfoCount++
 | 
				
			||||||
 | 
								matchStringArg(path.Join(configDir2, pathResolutionConfig2.AuthInfos["relative-user-2"].ClientCertificate), authInfo.ClientCertificate, t)
 | 
				
			||||||
 | 
								matchStringArg(path.Join(configDir2, pathResolutionConfig2.AuthInfos["relative-user-2"].ClientKey), authInfo.ClientKey, t)
 | 
				
			||||||
 | 
								matchStringArg(path.Join(configDir2, pathResolutionConfig2.AuthInfos["relative-user-2"].AuthPath), authInfo.AuthPath, t)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if key == "absolute-user-1" {
 | 
				
			||||||
 | 
								foundAuthInfoCount++
 | 
				
			||||||
 | 
								matchStringArg(pathResolutionConfig1.AuthInfos["absolute-user-1"].ClientCertificate, authInfo.ClientCertificate, t)
 | 
				
			||||||
 | 
								matchStringArg(pathResolutionConfig1.AuthInfos["absolute-user-1"].ClientKey, authInfo.ClientKey, t)
 | 
				
			||||||
 | 
								matchStringArg(pathResolutionConfig1.AuthInfos["absolute-user-1"].AuthPath, authInfo.AuthPath, t)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if key == "absolute-user-2" {
 | 
				
			||||||
 | 
								foundAuthInfoCount++
 | 
				
			||||||
 | 
								matchStringArg(pathResolutionConfig2.AuthInfos["absolute-user-2"].ClientCertificate, authInfo.ClientCertificate, t)
 | 
				
			||||||
 | 
								matchStringArg(pathResolutionConfig2.AuthInfos["absolute-user-2"].ClientKey, authInfo.ClientKey, t)
 | 
				
			||||||
 | 
								matchStringArg(pathResolutionConfig2.AuthInfos["absolute-user-2"].AuthPath, authInfo.AuthPath, t)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if foundAuthInfoCount != 4 {
 | 
				
			||||||
 | 
							t.Errorf("Expected 4 users, found %v: %v", foundAuthInfoCount, mergedConfig.AuthInfos)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func ExampleMergingSomeWithConflict() {
 | 
					func ExampleMergingSomeWithConflict() {
 | 
				
			||||||
	commandLineFile, _ := ioutil.TempFile("", "")
 | 
						commandLineFile, _ := ioutil.TempFile("", "")
 | 
				
			||||||
	defer os.Remove(commandLineFile.Name())
 | 
						defer os.Remove(commandLineFile.Name())
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user