func runDeleteContext(out io.Writer, configAccess clientcmd.ConfigAccess, cmd *cobra.Command) error { config, err := configAccess.GetStartingConfig() if err != nil { return err } args := cmd.Flags().Args() if len(args) != 1 { cmd.Help() return nil } configFile := configAccess.GetDefaultFilename() if configAccess.IsExplicitFile() { configFile = configAccess.GetExplicitFile() } name := args[0] _, ok := config.Contexts[name] if !ok { return fmt.Errorf("cannot delete context %s, not in %s", name, configFile) } delete(config.Contexts, name) if err := clientcmd.ModifyConfig(configAccess, *config, true); err != nil { return err } fmt.Fprintf(out, "deleted context %s from %s", name, configFile) return nil }
func (o LogoutOptions) RunLogout() error { token := o.Config.BearerToken client, err := client.New(o.Config) if err != nil { return err } userInfo, err := whoAmI(client) if err != nil { return err } if err := client.OAuthAccessTokens().Delete(token); err != nil { return err } newConfig := *o.StartingKubeConfig for key, value := range newConfig.AuthInfos { if value.Token == token { value.Token = "" newConfig.AuthInfos[key] = value // don't break, its possible that more than one user stanza has the same token. } } if err := kclientcmd.ModifyConfig(o.PathOptions, newConfig, true); err != nil { return err } fmt.Fprintf(o.Out, "Logged %q out on %q\n", userInfo.Name, o.Config.Host) return nil }
func (o setOptions) run() error { err := o.validate() if err != nil { return err } config, err := o.configAccess.GetStartingConfig() if err != nil { return err } steps, err := newNavigationSteps(o.propertyName) if err != nil { return err } setRawBytes := false if o.setRawBytes.Provided() { setRawBytes = o.setRawBytes.Value() } err = modifyConfig(reflect.ValueOf(config), steps, o.propertyValue, false, setRawBytes) if err != nil { return err } if err := clientcmd.ModifyConfig(o.configAccess, *config, false); err != nil { return err } return nil }
func (o unsetOptions) run() error { err := o.validate() if err != nil { return err } config, err := o.configAccess.GetStartingConfig() if err != nil { return err } steps, err := newNavigationSteps(o.propertyName) if err != nil { return err } err = modifyConfig(reflect.ValueOf(config), steps, "", true, true) if err != nil { return err } if err := clientcmd.ModifyConfig(o.configAccess, *config, false); err != nil { return err } return nil }
// Save all the information present in this helper to a config file. An explicit config // file path can be provided, if not use the established conventions about config // loading rules. Will create a new config file if one can't be found at all. Will only // succeed if all required info is present. func (o *LoginOptions) SaveConfig() (bool, error) { if len(o.Username) == 0 { return false, fmt.Errorf("Insufficient data to merge configuration.") } globalExistedBefore := true if _, err := os.Stat(o.PathOptions.GlobalFile); os.IsNotExist(err) { globalExistedBefore = false } newConfig, err := config.CreateConfig(o.Project, o.Config) if err != nil { return false, err } cwd, err := os.Getwd() if err != nil { return false, err } baseDir, err := cmdutil.MakeAbs(filepath.Dir(o.PathOptions.GetDefaultFilename()), cwd) if err != nil { return false, err } if err := config.RelativizeClientConfigPaths(newConfig, baseDir); err != nil { return false, err } configToWrite, err := config.MergeConfig(*o.StartingKubeConfig, *newConfig) if err != nil { return false, err } if err := kclientcmd.ModifyConfig(o.PathOptions, *configToWrite, true); err != nil { if !os.IsPermission(err) { return false, err } out := &bytes.Buffer{} cmderr.PrintError(errors.ErrKubeConfigNotWriteable(o.PathOptions.GetDefaultFilename(), o.PathOptions.IsExplicitFile(), err), out) return false, fmt.Errorf("%v", out) } created := false if _, err := os.Stat(o.PathOptions.GlobalFile); err == nil { created = created || !globalExistedBefore } return created, nil }
func (o useContextOptions) run() error { config, err := o.configAccess.GetStartingConfig() if err != nil { return err } err = o.validate(config) if err != nil { return err } config.CurrentContext = o.contextName if err := clientcmd.ModifyConfig(o.configAccess, *config, true); err != nil { return err } return nil }
func updateKubeconfig(config util.AdminConfig, name, endpoint string, entKeyPairs *entityKeyPairs, dryRun bool) error { po := config.PathOptions() kubeconfig, err := po.GetStartingConfig() if err != nil { return err } // Populate API server endpoint info. cluster := clientcmdapi.NewCluster() // Prefix "https" as the URL scheme to endpoint. if !strings.HasPrefix(endpoint, "https://") { endpoint = fmt.Sprintf("https://%s", endpoint) } cluster.Server = endpoint cluster.CertificateAuthorityData = certutil.EncodeCertPEM(entKeyPairs.ca.Cert) // Populate credentials. authInfo := clientcmdapi.NewAuthInfo() authInfo.ClientCertificateData = certutil.EncodeCertPEM(entKeyPairs.admin.Cert) authInfo.ClientKeyData = certutil.EncodePrivateKeyPEM(entKeyPairs.admin.Key) authInfo.Username = AdminCN // Populate context. context := clientcmdapi.NewContext() context.Cluster = name context.AuthInfo = name // Update the config struct with API server endpoint info, // credentials and context. kubeconfig.Clusters[name] = cluster kubeconfig.AuthInfos[name] = authInfo kubeconfig.Contexts[name] = context if !dryRun { // Write the update kubeconfig. if err := clientcmd.ModifyConfig(po, *kubeconfig, true); err != nil { return err } } return nil }
func (o createClusterOptions) run() error { err := o.validate() if err != nil { return err } config, err := o.configAccess.GetStartingConfig() if err != nil { return err } startingStanza, exists := config.Clusters[o.name] if !exists { startingStanza = clientcmdapi.NewCluster() } cluster := o.modifyCluster(*startingStanza) config.Clusters[o.name] = &cluster if err := clientcmd.ModifyConfig(o.configAccess, *config, true); err != nil { return err } return nil }
func (o createAuthInfoOptions) run() error { err := o.validate() if err != nil { return err } config, err := o.configAccess.GetStartingConfig() if err != nil { return err } startingStanza, exists := config.AuthInfos[o.name] if !exists { startingStanza = clientcmdapi.NewAuthInfo() } authInfo := o.modifyAuthInfo(*startingStanza) config.AuthInfos[o.name] = &authInfo if err := clientcmd.ModifyConfig(o.configAccess, *config, true); err != nil { return err } return nil }
// RunProject contains all the necessary functionality for the OpenShift cli project command func (o ProjectOptions) RunProject() error { config := o.Config clientCfg := o.ClientConfig out := o.Out var currentProject string currentContext := config.Contexts[config.CurrentContext] if currentContext != nil { currentProject = currentContext.Namespace } // No argument provided, we will just print info if len(o.ProjectName) == 0 { if len(currentProject) > 0 { if o.DisplayShort { fmt.Fprintln(out, currentProject) return nil } client, kubeclient, err := o.ClientFn() if err != nil { return err } switch err := confirmProjectAccess(currentProject, client, kubeclient); { case clientcmd.IsForbidden(err): return fmt.Errorf("you do not have rights to view project %q.", currentProject) case kapierrors.IsNotFound(err): return fmt.Errorf("the project %q specified in your config does not exist.", currentProject) case err != nil: return err } defaultContextName := cliconfig.GetContextNickname(currentContext.Namespace, currentContext.Cluster, currentContext.AuthInfo) // if they specified a project name and got a generated context, then only show the information they care about. They won't recognize // a context name they didn't choose if config.CurrentContext == defaultContextName { fmt.Fprintf(out, "Using project %q on server %q.\n", currentProject, clientCfg.Host) } else { fmt.Fprintf(out, "Using project %q from context named %q on server %q.\n", currentProject, config.CurrentContext, clientCfg.Host) } } else { if o.DisplayShort { return fmt.Errorf("no project has been set") } fmt.Fprintf(out, "No project has been set. Pass a project name to make that the default.\n") } return nil } // We have an argument that can be either a context or project argument := o.ProjectName contextInUse := "" namespaceInUse := "" // Check if argument is an existing context, if so just set it as the context in use. // If not a context then we will try to handle it as a project. if context, contextExists := config.Contexts[argument]; !o.ProjectOnly && contextExists { contextInUse = argument namespaceInUse = context.Namespace config.CurrentContext = argument } else { if !o.SkipAccessValidation { client, kubeclient, err := o.ClientFn() if err != nil { return err } if err := confirmProjectAccess(argument, client, kubeclient); err != nil { if isNotFound, isForbidden := kapierrors.IsNotFound(err), clientcmd.IsForbidden(err); isNotFound || isForbidden { var msg string if isForbidden { msg = fmt.Sprintf("You are not a member of project %q.", argument) } else { msg = fmt.Sprintf("A project named %q does not exist on %q.", argument, clientCfg.Host) } projects, err := getProjects(client, kubeclient) if err == nil { switch len(projects) { case 0: msg += "\nYou are not a member of any projects. You can request a project to be created with the 'new-project' command." case 1: msg += fmt.Sprintf("\nYou have one project on this server: %s", api.DisplayNameAndNameForProject(&projects[0])) default: msg += "\nYour projects are:" for _, project := range projects { msg += fmt.Sprintf("\n* %s", api.DisplayNameAndNameForProject(&project)) } } } if hasMultipleServers(config) { msg += "\nTo see projects on another server, pass '--server=<server>'." } return errors.New(msg) } return err } } projectName := argument kubeconfig, err := cliconfig.CreateConfig(projectName, o.ClientConfig) if err != nil { return err } merged, err := cliconfig.MergeConfig(config, *kubeconfig) if err != nil { return err } config = *merged namespaceInUse = projectName contextInUse = merged.CurrentContext } if err := kclientcmd.ModifyConfig(o.PathOptions, config, true); err != nil { return err } if o.DisplayShort { fmt.Fprintln(out, namespaceInUse) return nil } // calculate what name we'd generate for the context. If the context has the same name, don't drop it into the output, because the user won't // recognize the name since they didn't choose it. defaultContextName := cliconfig.GetContextNickname(namespaceInUse, config.Contexts[contextInUse].Cluster, config.Contexts[contextInUse].AuthInfo) switch { // if there is no namespace, then the only information we can provide is the context and server case (len(namespaceInUse) == 0): fmt.Fprintf(out, "Now using context named %q on server %q.\n", contextInUse, clientCfg.Host) // inform them that they are already in the project they are trying to switch to case currentProject == namespaceInUse: fmt.Fprintf(out, "Already on project %q on server %q.\n", currentProject, clientCfg.Host) // if they specified a project name and got a generated context, then only show the information they care about. They won't recognize // a context name they didn't choose case (argument == namespaceInUse) && (contextInUse == defaultContextName): fmt.Fprintf(out, "Now using project %q on server %q.\n", namespaceInUse, clientCfg.Host) // in all other cases, display all information default: fmt.Fprintf(out, "Now using project %q from context named %q on server %q.\n", namespaceInUse, contextInUse, clientCfg.Host) } return nil }
func modifyConfig(configAccess clientcmd.ConfigAccess, suppliedConfig *clientcmdapi.Config) error { config, err := configAccess.GetStartingConfig() if err != nil { return err } for name, authInfo := range suppliedConfig.AuthInfos { initial, ok := config.AuthInfos[name] if !ok { initial = clientcmdapi.NewAuthInfo() } modifiedAuthInfo := *initial var setToken, setBasic bool if len(authInfo.ClientCertificate) > 0 { modifiedAuthInfo.ClientCertificate = authInfo.ClientCertificate } if len(authInfo.ClientCertificateData) > 0 { modifiedAuthInfo.ClientCertificateData = authInfo.ClientCertificateData } if len(authInfo.ClientKey) > 0 { modifiedAuthInfo.ClientKey = authInfo.ClientKey } if len(authInfo.ClientKeyData) > 0 { modifiedAuthInfo.ClientKeyData = authInfo.ClientKeyData } if len(authInfo.Token) > 0 { modifiedAuthInfo.Token = authInfo.Token setToken = len(modifiedAuthInfo.Token) > 0 } if len(authInfo.Username) > 0 { modifiedAuthInfo.Username = authInfo.Username setBasic = setBasic || len(modifiedAuthInfo.Username) > 0 } if len(authInfo.Password) > 0 { modifiedAuthInfo.Password = authInfo.Password setBasic = setBasic || len(modifiedAuthInfo.Password) > 0 } // If any auth info was set, make sure any other existing auth types are cleared if setToken || setBasic { if !setToken { modifiedAuthInfo.Token = "" } if !setBasic { modifiedAuthInfo.Username = "" modifiedAuthInfo.Password = "" } } config.AuthInfos[name] = &modifiedAuthInfo } for name, cluster := range suppliedConfig.Clusters { initial, ok := config.Clusters[name] if !ok { initial = clientcmdapi.NewCluster() } modifiedCluster := *initial if len(cluster.Server) > 0 { modifiedCluster.Server = cluster.Server } if cluster.InsecureSkipTLSVerify { modifiedCluster.InsecureSkipTLSVerify = cluster.InsecureSkipTLSVerify // Specifying insecure mode clears any certificate authority if modifiedCluster.InsecureSkipTLSVerify { modifiedCluster.CertificateAuthority = "" modifiedCluster.CertificateAuthorityData = nil } } if len(cluster.CertificateAuthorityData) > 0 { modifiedCluster.CertificateAuthorityData = cluster.CertificateAuthorityData modifiedCluster.InsecureSkipTLSVerify = false } if len(cluster.CertificateAuthority) > 0 { modifiedCluster.CertificateAuthority = cluster.CertificateAuthority modifiedCluster.InsecureSkipTLSVerify = false } config.Clusters[name] = &modifiedCluster } for name, context := range suppliedConfig.Contexts { initial, ok := config.Contexts[name] if !ok { initial = clientcmdapi.NewContext() } modifiedContext := *initial if len(context.Cluster) > 0 { modifiedContext.Cluster = context.Cluster } if len(context.AuthInfo) > 0 { modifiedContext.AuthInfo = context.AuthInfo } if len(context.Namespace) > 0 { modifiedContext.Namespace = context.Namespace } config.Contexts[name] = &modifiedContext } if err := clientcmd.ModifyConfig(configAccess, *config, true); err != nil { return err } return nil }