// joinFederation is the implementation of the `join federation` command. func joinFederation(f cmdutil.Factory, cmdOut io.Writer, config util.AdminConfig, cmd *cobra.Command, args []string) error { joinFlags, err := util.GetSubcommandFlags(cmd, args) if err != nil { return err } dryRun := cmdutil.GetDryRunFlag(cmd) glog.V(2).Infof("Args and flags: name %s, host: %s, host-system-namespace: %s, kubeconfig: %s, dry-run: %s", joinFlags.Name, joinFlags.Host, joinFlags.FederationSystemNamespace, joinFlags.Kubeconfig, dryRun) po := config.PathOptions() po.LoadingRules.ExplicitPath = joinFlags.Kubeconfig clientConfig, err := po.GetStartingConfig() if err != nil { return err } generator, err := clusterGenerator(clientConfig, joinFlags.Name) if err != nil { glog.V(2).Infof("Failed creating cluster generator: %v", err) return err } glog.V(2).Infof("Created cluster generator: %#v", generator) hostFactory := config.HostFactory(joinFlags.Host, joinFlags.Kubeconfig) // We are not using the `kubectl create secret` machinery through // `RunCreateSubcommand` as we do to the cluster resource below // because we have a bunch of requirements that the machinery does // not satisfy. // 1. We want to create the secret in a specific namespace, which // is neither the "default" namespace nor the one specified // via the `--namespace` flag. // 2. `SecretGeneratorV1` requires LiteralSources in a string-ified // form that it parses to generate the secret data key-value // pairs. We, however, have the key-value pairs ready without a // need for parsing. // 3. The result printing mechanism needs to be mostly quiet. We // don't have to print the created secret in the default case. // Having said that, secret generation machinery could be altered to // suit our needs, but it is far less invasive and readable this way. _, err = createSecret(hostFactory, clientConfig, joinFlags.FederationSystemNamespace, joinFlags.Name, dryRun) if err != nil { glog.V(2).Infof("Failed creating the cluster credentials secret: %v", err) return err } glog.V(2).Infof("Cluster credentials secret created") return kubectlcmd.RunCreateSubcommand(f, cmd, cmdOut, &kubectlcmd.CreateSubcommandOptions{ Name: joinFlags.Name, StructuredGenerator: generator, DryRun: dryRun, OutputFormat: cmdutil.GetFlagString(cmd, "output"), }) }
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 }