func writePreferences(configAccess ConfigAccess, newPrefs clientcmdapi.Preferences) error { if startingConfig, err := configAccess.GetStartingConfig(); err != nil { return err } else if reflect.DeepEqual(startingConfig.Preferences, newPrefs) { return nil } if configAccess.IsExplicitFile() { file := configAccess.GetExplicitFile() currConfig := getConfigFromFileOrDie(file) currConfig.Preferences = newPrefs if err := clientcmd.WriteToFile(*currConfig, file); err != nil { return err } return nil } for _, file := range configAccess.GetLoadingPrecedence() { currConfig := getConfigFromFileOrDie(file) if !reflect.DeepEqual(currConfig.Preferences, newPrefs) { currConfig.Preferences = newPrefs if err := clientcmd.WriteToFile(*currConfig, file); err != nil { return err } return nil } } return errors.New("no config found to write preferences") }
// writeCurrentContext takes three possible paths. // 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 is empty, then we find the config file that is setting the CurrentContext and clear the value from that file func writeCurrentContext(configAccess ConfigAccess, newCurrentContext string) error { if startingConfig, err := configAccess.GetStartingConfig(); err != nil { return err } else if startingConfig.CurrentContext == newCurrentContext { 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 { destinationFile := configAccess.GetDefaultFilename() config := getConfigFromFileOrDie(destinationFile) config.CurrentContext = newCurrentContext if err := clientcmd.WriteToFile(*config, destinationFile); err != nil { return err } return nil } // 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 for _, file := range configAccess.GetLoadingPrecedence() { if _, err := os.Stat(file); err == nil { currConfig := getConfigFromFileOrDie(file) if len(currConfig.CurrentContext) > 0 { currConfig.CurrentContext = newCurrentContext if err := clientcmd.WriteToFile(*currConfig, file); err != nil { return err } return nil } } } return errors.New("no config found to write context") }
func (o createClusterOptions) run() error { err := o.validate() if err != nil { return err } config, filename, err := o.pathOptions.getStartingConfig() if err != nil { return err } if config.Clusters == nil { config.Clusters = make(map[string]clientcmdapi.Cluster) } cluster := o.modifyCluster(config.Clusters[o.name]) config.Clusters[o.name] = cluster err = clientcmd.WriteToFile(*config, filename) if err != nil { return err } return nil }
func (o setOptions) run() error { err := o.validate() if err != nil { return err } config, filename, err := o.pathOptions.getStartingConfig() if err != nil { return err } if len(filename) == 0 { return errors.New("cannot set property without using a specific file") } steps, err := newNavigationSteps(o.propertyName) if err != nil { return err } err = modifyConfig(reflect.ValueOf(config), steps, o.propertyValue, false) if err != nil { return err } err = clientcmd.WriteToFile(*config, filename) if err != nil { return err } return nil }
// ChangeUser changes the user used by the current CLI session. func (c *CLI) ChangeUser(name string) *CLI { adminClientConfig, err := testutil.GetClusterAdminClientConfig(c.adminConfigPath) if err != nil { FatalErr(err) } _, _, clientConfig, err := testutil.GetClientForUser(*adminClientConfig, name) if err != nil { FatalErr(err) } kubeConfig, err := config.CreateConfig(c.Namespace(), clientConfig) if err != nil { FatalErr(err) } c.configPath = filepath.Join(c.outputDir, name+".kubeconfig") err = clientcmd.WriteToFile(*kubeConfig, c.configPath) if err != nil { FatalErr(err) } c.username = name fmt.Printf("INFO: configPath is now %q\n", c.configPath) return c }
func (o unsetOptions) run() error { err := o.validate() if err != nil { return err } config, filename, err := o.pathOptions.getStartingConfig() if err != nil { return err } if len(filename) == 0 { return errors.New("cannot set property without using a specific file") } parts := strings.Split(o.propertyName, ".") err = modifyConfig(reflect.ValueOf(config), parts, "", true) if err != nil { return err } err = clientcmd.WriteToFile(*config, filename) if err != nil { return err } return nil }
func writeClientConfigToKubeConfig(config kclient.Config, path string) error { kubeConfig := &clientcmdapi.Config{ Clusters: map[string]clientcmdapi.Cluster{"myserver": {Server: config.Host, CertificateAuthority: config.CAFile, CertificateAuthorityData: config.CAData}}, AuthInfos: map[string]clientcmdapi.AuthInfo{"myuser": {Token: config.BearerToken}}, Contexts: map[string]clientcmdapi.Context{"mycontext": {Cluster: "myserver", AuthInfo: "myuser"}}, CurrentContext: "mycontext", } if err := os.MkdirAll(filepath.Dir(path), os.FileMode(0755)); err != nil { return err } if err := clientcmd.WriteToFile(*kubeConfig, path); err != nil { return err } return nil }
func testConfigCommand(args []string, startingConfig clientcmdapi.Config) (string, clientcmdapi.Config) { fakeKubeFile, _ := ioutil.TempFile("", "") defer os.Remove(fakeKubeFile.Name()) clientcmd.WriteToFile(startingConfig, fakeKubeFile.Name()) argsToUse := make([]string, 0, 2+len(args)) argsToUse = append(argsToUse, "--kubeconfig="+fakeKubeFile.Name()) argsToUse = append(argsToUse, args...) buf := bytes.NewBuffer([]byte{}) cmd := NewCmdConfig(NewDefaultPathOptions(), buf) cmd.SetArgs(argsToUse) cmd.Execute() // outBytes, _ := ioutil.ReadFile(fakeKubeFile.Name()) config := getConfigFromFileOrDie(fakeKubeFile.Name()) return buf.String(), *config }
func (o createContextOptions) run() error { err := o.validate() if err != nil { return err } config, filename, err := o.pathOptions.getStartingConfig() if err != nil { return err } context := o.modifyContext(config.Contexts[o.name]) config.Contexts[o.name] = context err = clientcmd.WriteToFile(*config, filename) if err != nil { return err } return nil }
func (o createAuthInfoOptions) run() error { err := o.validate() if err != nil { return err } config, filename, err := o.pathOptions.getStartingConfig() if err != nil { return err } authInfo := o.authInfo() config.AuthInfos[o.name] = authInfo err = clientcmd.WriteToFile(*config, filename) if err != nil { return err } return nil }
func (o useContextOptions) run() error { err := o.validate() if err != nil { return err } config, filename, err := o.pathOptions.getStartingConfig() if err != nil { return err } if len(filename) == 0 { return errors.New("cannot set current-context without using a specific file") } config.CurrentContext = o.contextName err = clientcmd.WriteToFile(*config, filename) if err != nil { return err } return nil }
func (o CreateKubeConfigOptions) CreateKubeConfig() (*clientcmdapi.Config, error) { glog.V(4).Infof("creating a .kubeconfig with: %#v", o) // read all the referenced filenames caData, err := ioutil.ReadFile(o.APIServerCAFile) if err != nil { return nil, err } certData, err := ioutil.ReadFile(o.CertFile) if err != nil { return nil, err } keyData, err := ioutil.ReadFile(o.KeyFile) if err != nil { return nil, err } certConfig, err := crypto.GetTLSCertificateConfig(o.CertFile, o.KeyFile) if err != nil { return nil, err } // determine all the nicknames clusterNick, err := cliconfig.GetClusterNicknameFromURL(o.APIServerURL) if err != nil { return nil, err } userNick, err := cliconfig.GetUserNicknameFromCert(clusterNick, certConfig.Certs...) if err != nil { return nil, err } contextNick, err := cliconfig.GetContextNickname(o.ContextNamespace, clusterNick, userNick) if err != nil { return nil, err } credentials := make(map[string]clientcmdapi.AuthInfo) credentials[userNick] = clientcmdapi.AuthInfo{ ClientCertificateData: certData, ClientKeyData: keyData, } clusters := make(map[string]clientcmdapi.Cluster) clusters[clusterNick] = clientcmdapi.Cluster{ Server: o.APIServerURL, CertificateAuthorityData: caData, } contexts := make(map[string]clientcmdapi.Context) contexts[contextNick] = clientcmdapi.Context{Cluster: clusterNick, AuthInfo: userNick, Namespace: o.ContextNamespace} createPublic := (len(o.PublicAPIServerURL) > 0) && o.APIServerURL != o.PublicAPIServerURL if createPublic { publicClusterNick, err := cliconfig.GetClusterNicknameFromURL(o.PublicAPIServerURL) if err != nil { return nil, err } publicContextNick, err := cliconfig.GetContextNickname(o.ContextNamespace, publicClusterNick, userNick) if err != nil { return nil, err } clusters[publicClusterNick] = clientcmdapi.Cluster{ Server: o.PublicAPIServerURL, CertificateAuthorityData: caData, } contexts[publicContextNick] = clientcmdapi.Context{Cluster: publicClusterNick, AuthInfo: userNick, Namespace: o.ContextNamespace} } kubeConfig := &clientcmdapi.Config{ Clusters: clusters, AuthInfos: credentials, Contexts: contexts, CurrentContext: contextNick, } glog.V(3).Infof("Generating '%s' API client config as %s\n", userNick, o.KubeConfigFile) // Ensure the parent dir exists if err := os.MkdirAll(filepath.Dir(o.KubeConfigFile), os.FileMode(0755)); err != nil { return nil, err } if err := clientcmd.WriteToFile(*kubeConfig, o.KubeConfigFile); err != nil { return nil, err } return kubeConfig, nil }
// ModifyConfig takes a Config object, iterates through Clusters, AuthInfos, and Contexts, uses the LocationOfOrigin if specified or // uses the default destination file to write the results into. This results in multiple file reads, but it's very easy to follow. // 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 the kubeconfig cases, newConfig should have at most one difference, // that means that this code will only write into a single file. func ModifyConfig(configAccess ConfigAccess, newConfig clientcmdapi.Config) error { startingConfig, err := configAccess.GetStartingConfig() if err != nil { return err } // We need to find all differences, locate their original files, read a partial config to modify only that stanza and write out the file. // Special case the test for current context and preferences since those always write to the default file. if reflect.DeepEqual(*startingConfig, newConfig) { // nothing to do return nil } if startingConfig.CurrentContext != newConfig.CurrentContext { if err := writeCurrentContext(configAccess, newConfig.CurrentContext); err != nil { return err } } if !reflect.DeepEqual(startingConfig.Preferences, newConfig.Preferences) { if err := writePreferences(configAccess, newConfig.Preferences); err != nil { return err } } // Search every cluster, authInfo, and context. First from new to old for differences, then from old to new for deletions for key, cluster := range newConfig.Clusters { startingCluster, exists := startingConfig.Clusters[key] if !reflect.DeepEqual(cluster, startingCluster) || !exists { destinationFile := cluster.LocationOfOrigin if len(destinationFile) == 0 { destinationFile = configAccess.GetDefaultFilename() } configToWrite := getConfigFromFileOrDie(destinationFile) configToWrite.Clusters[key] = cluster if err := clientcmd.WriteToFile(*configToWrite, destinationFile); err != nil { return err } } } for key, context := range newConfig.Contexts { startingContext, exists := startingConfig.Contexts[key] if !reflect.DeepEqual(context, startingContext) || !exists { destinationFile := context.LocationOfOrigin if len(destinationFile) == 0 { destinationFile = configAccess.GetDefaultFilename() } configToWrite := getConfigFromFileOrDie(destinationFile) configToWrite.Contexts[key] = context if err := clientcmd.WriteToFile(*configToWrite, destinationFile); err != nil { return err } } } for key, authInfo := range newConfig.AuthInfos { startingAuthInfo, exists := startingConfig.AuthInfos[key] if !reflect.DeepEqual(authInfo, startingAuthInfo) || !exists { destinationFile := authInfo.LocationOfOrigin if len(destinationFile) == 0 { destinationFile = configAccess.GetDefaultFilename() } configToWrite := getConfigFromFileOrDie(destinationFile) configToWrite.AuthInfos[key] = authInfo if err := clientcmd.WriteToFile(*configToWrite, destinationFile); err != nil { return err } } } for key, cluster := range startingConfig.Clusters { if _, exists := newConfig.Clusters[key]; !exists { destinationFile := cluster.LocationOfOrigin if len(destinationFile) == 0 { destinationFile = configAccess.GetDefaultFilename() } configToWrite := getConfigFromFileOrDie(destinationFile) delete(configToWrite.Clusters, key) if err := clientcmd.WriteToFile(*configToWrite, destinationFile); err != nil { return err } } } for key, context := range startingConfig.Contexts { if _, exists := newConfig.Contexts[key]; !exists { destinationFile := context.LocationOfOrigin if len(destinationFile) == 0 { destinationFile = configAccess.GetDefaultFilename() } configToWrite := getConfigFromFileOrDie(destinationFile) delete(configToWrite.Contexts, key) if err := clientcmd.WriteToFile(*configToWrite, destinationFile); err != nil { return err } } } for key, authInfo := range startingConfig.AuthInfos { if _, exists := newConfig.AuthInfos[key]; !exists { destinationFile := authInfo.LocationOfOrigin if len(destinationFile) == 0 { destinationFile = configAccess.GetDefaultFilename() } configToWrite := getConfigFromFileOrDie(destinationFile) delete(configToWrite.AuthInfos, key) if err := clientcmd.WriteToFile(*configToWrite, destinationFile); err != nil { return err } } } return nil }