mirror of https://github.com/k3s-io/k3s
Merge pull request #70098 from fabriziopandini/kubeadm-graduate-kubeconfig
Kubeadm graduate kubeconfig phasepull/58/head
commit
739998f8fe
|
@ -50,7 +50,6 @@ import (
|
|||
certsphase "k8s.io/kubernetes/cmd/kubeadm/app/phases/certs"
|
||||
controlplanephase "k8s.io/kubernetes/cmd/kubeadm/app/phases/controlplane"
|
||||
etcdphase "k8s.io/kubernetes/cmd/kubeadm/app/phases/etcd"
|
||||
kubeconfigphase "k8s.io/kubernetes/cmd/kubeadm/app/phases/kubeconfig"
|
||||
kubeletphase "k8s.io/kubernetes/cmd/kubeadm/app/phases/kubelet"
|
||||
markmasterphase "k8s.io/kubernetes/cmd/kubeadm/app/phases/markmaster"
|
||||
patchnodephase "k8s.io/kubernetes/cmd/kubeadm/app/phases/patchnode"
|
||||
|
@ -130,6 +129,7 @@ type initData struct {
|
|||
ignorePreflightErrors sets.String
|
||||
certificatesDir string
|
||||
dryRunDir string
|
||||
externalCA bool
|
||||
client clientset.Interface
|
||||
}
|
||||
|
||||
|
@ -146,7 +146,7 @@ func NewCmdInit(out io.Writer) *cobra.Command {
|
|||
kubeadmutil.CheckErr(err)
|
||||
|
||||
data := c.(initData)
|
||||
fmt.Printf("[init] using Kubernetes version: %s\n", data.cfg.KubernetesVersion)
|
||||
fmt.Printf("[init] Using Kubernetes version: %s\n", data.cfg.KubernetesVersion)
|
||||
|
||||
err = initRunner.Run()
|
||||
kubeadmutil.CheckErr(err)
|
||||
|
@ -166,8 +166,9 @@ func NewCmdInit(out io.Writer) *cobra.Command {
|
|||
|
||||
// initialize the workflow runner with the list of phases
|
||||
initRunner.AppendPhase(phases.NewPreflightMasterPhase())
|
||||
initRunner.AppendPhase(phases.NewCertsPhase())
|
||||
initRunner.AppendPhase(phases.NewKubeletStartPhase())
|
||||
initRunner.AppendPhase(phases.NewCertsPhase())
|
||||
initRunner.AppendPhase(phases.NewKubeConfigPhase())
|
||||
// TODO: add other phases to the runner.
|
||||
|
||||
// sets the data builder function, that will be used by the runner
|
||||
|
@ -313,6 +314,9 @@ func newInitData(cmd *cobra.Command, options *initOptions) (initData, error) {
|
|||
}
|
||||
}
|
||||
|
||||
// Checks if an external CA is provided by the user.
|
||||
externalCA, _ := certsphase.UsingExternalCA(cfg)
|
||||
|
||||
return initData{
|
||||
cfg: cfg,
|
||||
certificatesDir: cfg.CertificatesDir,
|
||||
|
@ -320,6 +324,7 @@ func newInitData(cmd *cobra.Command, options *initOptions) (initData, error) {
|
|||
dryRun: options.dryRun,
|
||||
dryRunDir: dryRunDir,
|
||||
ignorePreflightErrors: ignorePreflightErrorsSet,
|
||||
externalCA: externalCA,
|
||||
}, nil
|
||||
}
|
||||
|
||||
|
@ -380,6 +385,11 @@ func (d initData) KubeletDir() string {
|
|||
return kubeadmconstants.KubeletRunDirectory
|
||||
}
|
||||
|
||||
// ExternalCA returns true if an external CA is provided by the user.
|
||||
func (d initData) ExternalCA() bool {
|
||||
return d.externalCA
|
||||
}
|
||||
|
||||
// Client returns a Kubernetes client to be used by kubeadm.
|
||||
// This function is implemented as a singleton, thus avoiding to recreate the client when it is used by different phases.
|
||||
// Important. This function must be called after the admin.conf kubeconfig file is created.
|
||||
|
@ -426,18 +436,6 @@ func runInit(i *initData, out io.Writer) error {
|
|||
|
||||
adminKubeConfigPath := filepath.Join(kubeConfigDir, kubeadmconstants.AdminKubeConfigFileName)
|
||||
|
||||
if res, _ := certsphase.UsingExternalCA(i.cfg); !res {
|
||||
|
||||
// PHASE 2: Generate kubeconfig files for the admin and the kubelet
|
||||
glog.V(2).Infof("[init] generating kubeconfig files")
|
||||
if err := kubeconfigphase.CreateInitKubeConfigFiles(kubeConfigDir, i.cfg); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
} else {
|
||||
fmt.Println("[externalca] the file 'ca.key' was not found, yet all other certificates are present. Using external CA mode - certificates or kubeconfig will not be generated")
|
||||
}
|
||||
|
||||
if features.Enabled(i.cfg.FeatureGates, features.Auditing) {
|
||||
// Setup the AuditPolicy (either it was passed in and exists or it wasn't passed in and generate a default policy)
|
||||
if i.cfg.AuditPolicyConfiguration.Path != "" {
|
||||
|
|
|
@ -76,7 +76,6 @@ go_test(
|
|||
],
|
||||
embed = [":go_default_library"],
|
||||
deps = [
|
||||
"//cmd/kubeadm/app/apis/kubeadm:go_default_library",
|
||||
"//cmd/kubeadm/app/apis/kubeadm/v1beta1:go_default_library",
|
||||
"//cmd/kubeadm/app/constants:go_default_library",
|
||||
"//cmd/kubeadm/app/phases/certs/pkiutil:go_default_library",
|
||||
|
|
|
@ -22,7 +22,6 @@ import (
|
|||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
|
||||
kubeadmscheme "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/scheme"
|
||||
kubeadmapiv1beta1 "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1beta1"
|
||||
|
@ -36,23 +35,6 @@ import (
|
|||
)
|
||||
|
||||
var (
|
||||
allCertsLongDesc = normalizer.LongDesc(`
|
||||
Generates a self-signed CA to provision identities for each component in the cluster (including nodes)
|
||||
and client certificates to be used by various components.
|
||||
|
||||
If a given certificate and private key pair both exist, kubeadm skips the generation step and
|
||||
existing files will be used.
|
||||
` + cmdutil.AlphaDisclaimer)
|
||||
|
||||
allCertsExample = normalizer.Examples(`
|
||||
# Creates all PKI assets necessary to establish the control plane,
|
||||
# functionally equivalent to what generated by kubeadm init.
|
||||
kubeadm alpha phase certs all
|
||||
|
||||
# Creates all PKI assets using options read from a configuration file.
|
||||
kubeadm alpha phase certs all --config masterconfiguration.yaml
|
||||
`)
|
||||
|
||||
saKeyLongDesc = fmt.Sprintf(normalizer.LongDesc(`
|
||||
Generates the private key for signing service account tokens along with its public key, and saves them into
|
||||
%s and %s files.
|
||||
|
@ -71,6 +53,7 @@ var (
|
|||
// (and thus with different runtime data struct, all of them requested to be compliant to this interface)
|
||||
type certsData interface {
|
||||
Cfg() *kubeadmapi.InitConfiguration
|
||||
ExternalCA() bool
|
||||
CertificateDir() string
|
||||
CertificateWriteDir() string
|
||||
}
|
||||
|
@ -80,7 +63,8 @@ func NewCertsPhase() workflow.Phase {
|
|||
return workflow.Phase{
|
||||
Name: "certs",
|
||||
Short: "Certificate generation",
|
||||
Phases: getCertsSubPhases(),
|
||||
Phases: newCertSubPhases(),
|
||||
Run: runCerts,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -102,8 +86,8 @@ func getCertsSubCommands() []*cobra.Command {
|
|||
return []*cobra.Command{certscmdphase.NewCmdCertsRenewal()}
|
||||
}
|
||||
|
||||
// getCertsSubPhases returns sub phases for certs phase
|
||||
func getCertsSubPhases() []workflow.Phase {
|
||||
// newCertSubPhases returns sub phases for certs phase
|
||||
func newCertSubPhases() []workflow.Phase {
|
||||
subPhases := []workflow.Phase{}
|
||||
|
||||
certTree, _ := certsphase.GetDefaultCertList().AsMap().CertTree()
|
||||
|
@ -116,8 +100,6 @@ func getCertsSubPhases() []workflow.Phase {
|
|||
certPhase := newCertSubPhase(cert, runCertPhase(cert, ca))
|
||||
subPhases = append(subPhases, certPhase)
|
||||
}
|
||||
|
||||
subPhases = append(subPhases, caPhase)
|
||||
}
|
||||
|
||||
// SA creates the private/public key pair, which doesn't use x509 at all
|
||||
|
@ -133,19 +115,6 @@ func getCertsSubPhases() []workflow.Phase {
|
|||
return subPhases
|
||||
}
|
||||
|
||||
func runCertsSa(c workflow.RunData) error {
|
||||
data, ok := c.(certsData)
|
||||
if !ok {
|
||||
return errors.New("certs phase invoked with an invalid data struct")
|
||||
}
|
||||
|
||||
cfg := data.Cfg()
|
||||
cfg.CertificatesDir = data.CertificateWriteDir()
|
||||
defer func() { cfg.CertificatesDir = data.CertificateDir() }()
|
||||
|
||||
return certsphase.CreateServiceAccountKeyAndPublicKeyFiles(cfg)
|
||||
}
|
||||
|
||||
func newCertSubPhase(certSpec *certsphase.KubeadmCert, run func(c workflow.RunData) error) workflow.Phase {
|
||||
phase := workflow.Phase{
|
||||
Name: certSpec.Name,
|
||||
|
@ -195,6 +164,37 @@ func getSANDescription(certSpec *certsphase.KubeadmCert) string {
|
|||
return fmt.Sprintf("\n\nDefault SANs are %s", strings.Join(sans, ", "))
|
||||
}
|
||||
|
||||
func runCertsSa(c workflow.RunData) error {
|
||||
data, ok := c.(certsData)
|
||||
if !ok {
|
||||
return errors.New("certs phase invoked with an invalid data struct")
|
||||
}
|
||||
|
||||
// if external CA mode, skip service account key generation
|
||||
if data.ExternalCA() {
|
||||
fmt.Printf("[certs] External CA mode: Using existing sa keys\n")
|
||||
return nil
|
||||
}
|
||||
|
||||
// if dryrunning, write certificates to a temporary folder (and defer restore to the path originally specified by the user)
|
||||
cfg := data.Cfg()
|
||||
cfg.CertificatesDir = data.CertificateWriteDir()
|
||||
defer func() { cfg.CertificatesDir = data.CertificateDir() }()
|
||||
|
||||
// create the new service account key (or use existing)
|
||||
return certsphase.CreateServiceAccountKeyAndPublicKeyFiles(cfg)
|
||||
}
|
||||
|
||||
func runCerts(c workflow.RunData) error {
|
||||
data, ok := c.(certsData)
|
||||
if !ok {
|
||||
return errors.New("certs phase invoked with an invalid data struct")
|
||||
}
|
||||
|
||||
fmt.Printf("[certs] Using certificateDir folder %q\n", data.CertificateWriteDir())
|
||||
return nil
|
||||
}
|
||||
|
||||
func runCAPhase(ca *certsphase.KubeadmCert) func(c workflow.RunData) error {
|
||||
return func(c workflow.RunData) error {
|
||||
data, ok := c.(certsData)
|
||||
|
@ -202,10 +202,24 @@ func runCAPhase(ca *certsphase.KubeadmCert) func(c workflow.RunData) error {
|
|||
return errors.New("certs phase invoked with an invalid data struct")
|
||||
}
|
||||
|
||||
// if external CA mode, skips certificate authority generation
|
||||
if data.ExternalCA() {
|
||||
fmt.Printf("[certs] External CA mode: Using existing %s certificate authority\n", ca.BaseName)
|
||||
return nil
|
||||
}
|
||||
|
||||
// if using external etcd, skips etcd certificate authority generation
|
||||
if data.Cfg().Etcd.External != nil && ca.Name == "etcd-ca" {
|
||||
fmt.Printf("[certs] External etcd mode: Skipping %s certificate authority generation\n", ca.BaseName)
|
||||
return nil
|
||||
}
|
||||
|
||||
// if dryrunning, write certificates authority to a temporary folder (and defer restore to the path originally specified by the user)
|
||||
cfg := data.Cfg()
|
||||
cfg.CertificatesDir = data.CertificateWriteDir()
|
||||
defer func() { cfg.CertificatesDir = data.CertificateDir() }()
|
||||
|
||||
// create the new certificate authority (or use existing)
|
||||
return certsphase.CreateCACertAndKeyFiles(ca, cfg)
|
||||
}
|
||||
}
|
||||
|
@ -217,10 +231,24 @@ func runCertPhase(cert *certsphase.KubeadmCert, caCert *certsphase.KubeadmCert)
|
|||
return errors.New("certs phase invoked with an invalid data struct")
|
||||
}
|
||||
|
||||
// if external CA mode, skip certificate generation
|
||||
if data.ExternalCA() {
|
||||
fmt.Printf("[certs] External CA mode: Using existing %s certificate\n", cert.BaseName)
|
||||
return nil
|
||||
}
|
||||
|
||||
// if using external etcd, skips etcd certificates generation
|
||||
if data.Cfg().Etcd.External != nil && cert.CAName == "etcd-ca" {
|
||||
fmt.Printf("[certs] External etcd mode: Skipping %s certificate authority generation\n", cert.BaseName)
|
||||
return nil
|
||||
}
|
||||
|
||||
// if dryrunning, write certificates to a temporary folder (and defer restore to the path originally specified by the user)
|
||||
cfg := data.Cfg()
|
||||
cfg.CertificatesDir = data.CertificateWriteDir()
|
||||
defer func() { cfg.CertificatesDir = data.CertificateDir() }()
|
||||
|
||||
// create the new certificate (or use existing)
|
||||
return certsphase.CreateCertAndKeyFilesWithCA(cert, caCert, cfg)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,14 +19,13 @@ package phases
|
|||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
|
||||
kubeadmscheme "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/scheme"
|
||||
kubeadmapiv1beta1 "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1beta1"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/cmd/phases/workflow"
|
||||
cmdutil "k8s.io/kubernetes/cmd/kubeadm/app/cmd/util"
|
||||
kubeadmconstants "k8s.io/kubernetes/cmd/kubeadm/app/constants"
|
||||
kubeconfigphase "k8s.io/kubernetes/cmd/kubeadm/app/phases/kubeconfig"
|
||||
|
@ -34,62 +33,136 @@ import (
|
|||
)
|
||||
|
||||
var (
|
||||
allKubeconfigLongDesc = normalizer.LongDesc(`
|
||||
Generates all kubeconfig files necessary to establish the control plane and the admin kubeconfig file.
|
||||
` + cmdutil.AlphaDisclaimer)
|
||||
|
||||
allKubeconfigExample = normalizer.Examples(`
|
||||
# Generates all kubeconfig files, functionally equivalent to what generated
|
||||
# by kubeadm init.
|
||||
kubeadm alpha phase kubeconfig all
|
||||
|
||||
# Generates all kubeconfig files using options read from a configuration file.
|
||||
kubeadm alpha phase kubeconfig all --config masterconfiguration.yaml
|
||||
`)
|
||||
|
||||
adminKubeconfigLongDesc = fmt.Sprintf(normalizer.LongDesc(`
|
||||
Generates the kubeconfig file for the admin and for kubeadm itself, and saves it to %s file.
|
||||
`+cmdutil.AlphaDisclaimer), kubeadmconstants.AdminKubeConfigFileName)
|
||||
|
||||
kubeletKubeconfigLongDesc = fmt.Sprintf(normalizer.LongDesc(`
|
||||
Generates the kubeconfig file for the kubelet to use and saves it to %s file.
|
||||
|
||||
Please note that this should *only* be used for bootstrapping purposes. After your control plane is up,
|
||||
you should request all kubelet credentials from the CSR API.
|
||||
`+cmdutil.AlphaDisclaimer), filepath.Join(kubeadmconstants.KubernetesDir, kubeadmconstants.KubeletKubeConfigFileName))
|
||||
|
||||
controllerManagerKubeconfigLongDesc = fmt.Sprintf(normalizer.LongDesc(`
|
||||
Generates the kubeconfig file for the controller manager to use and saves it to %s file.
|
||||
`+cmdutil.AlphaDisclaimer), filepath.Join(kubeadmconstants.KubernetesDir, kubeadmconstants.ControllerManagerKubeConfigFileName))
|
||||
|
||||
schedulerKubeconfigLongDesc = fmt.Sprintf(normalizer.LongDesc(`
|
||||
Generates the kubeconfig file for the scheduler to use and saves it to %s file.
|
||||
`+cmdutil.AlphaDisclaimer), filepath.Join(kubeadmconstants.KubernetesDir, kubeadmconstants.SchedulerKubeConfigFileName))
|
||||
kubeconfigLongDesc = normalizer.LongDesc(`
|
||||
kubeconfig file utilities.
|
||||
` + cmdutil.AlphaDisclaimer)
|
||||
|
||||
userKubeconfigLongDesc = normalizer.LongDesc(`
|
||||
Outputs a kubeconfig file for an additional user.
|
||||
` + cmdutil.AlphaDisclaimer)
|
||||
Outputs a kubeconfig file for an additional user.
|
||||
` + cmdutil.AlphaDisclaimer)
|
||||
|
||||
userKubeconfigExample = normalizer.Examples(`
|
||||
# Outputs a kubeconfig file for an additional user named foo
|
||||
kubeadm alpha phase kubeconfig user --client-name=foo
|
||||
`)
|
||||
# Outputs a kubeconfig file for an additional user named foo
|
||||
kubeadm alpha kubeconfig user --client-name=foo
|
||||
`)
|
||||
|
||||
kubeconfigFilePhaseProperties = map[string]struct {
|
||||
name string
|
||||
short string
|
||||
long string
|
||||
}{
|
||||
kubeadmconstants.AdminKubeConfigFileName: {
|
||||
name: "admin",
|
||||
short: "Generates a kubeconfig file for the admin to use and for kubeadm itself",
|
||||
long: "Generates the kubeconfig file for the admin and for kubeadm itself, and saves it to %s file.",
|
||||
},
|
||||
kubeadmconstants.KubeletKubeConfigFileName: {
|
||||
name: "kubelet",
|
||||
short: "Generates a kubeconfig file for the kubelet to use *only* for cluster bootstrapping purposes",
|
||||
long: normalizer.LongDesc(`
|
||||
Generates the kubeconfig file for the kubelet to use and saves it to %s file.
|
||||
|
||||
Please note that this should *only* be used for cluster bootstrapping purposes. After your control plane is up,
|
||||
you should request all kubelet credentials from the CSR API.`),
|
||||
},
|
||||
kubeadmconstants.ControllerManagerKubeConfigFileName: {
|
||||
name: "controller-manager",
|
||||
short: "Generates a kubeconfig file for the controller manager to use",
|
||||
long: "Generates the kubeconfig file for the controller manager to use and saves it to %s file",
|
||||
},
|
||||
kubeadmconstants.SchedulerKubeConfigFileName: {
|
||||
name: "scheduler",
|
||||
short: "Generates a kubeconfig file for the scheduler to use",
|
||||
long: "Generates the kubeconfig file for the scheduler to use and saves it to %s file.",
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
// kubeConfigData defines the behavior that a runtime data struct passed to the kubeconfig phase
|
||||
// should have. Please note that we are using an interface in order to make this phase reusable in different workflows
|
||||
// (and thus with different runtime data struct, all of them requested to be compliant to this interface)
|
||||
type kubeConfigData interface {
|
||||
Cfg() *kubeadmapi.InitConfiguration
|
||||
ExternalCA() bool
|
||||
CertificateDir() string
|
||||
CertificateWriteDir() string
|
||||
KubeConfigDir() string
|
||||
}
|
||||
|
||||
// NewKubeConfigPhase creates a kubeadm workflow phase that creates all kubeconfig files necessary to establish the control plane and the admin kubeconfig file.
|
||||
func NewKubeConfigPhase() workflow.Phase {
|
||||
return workflow.Phase{
|
||||
Name: "kubeconfig",
|
||||
Short: "Generates all kubeconfig files necessary to establish the control plane and the admin kubeconfig file",
|
||||
Phases: []workflow.Phase{
|
||||
NewKubeConfigFilePhase(kubeadmconstants.AdminKubeConfigFileName),
|
||||
NewKubeConfigFilePhase(kubeadmconstants.KubeletKubeConfigFileName),
|
||||
NewKubeConfigFilePhase(kubeadmconstants.ControllerManagerKubeConfigFileName),
|
||||
NewKubeConfigFilePhase(kubeadmconstants.SchedulerKubeConfigFileName),
|
||||
},
|
||||
Run: runKubeConfig,
|
||||
}
|
||||
}
|
||||
|
||||
// NewKubeConfigFilePhase creates a kubeadm workflow phase that creates a kubeconfig file.
|
||||
func NewKubeConfigFilePhase(kubeConfigFileName string) workflow.Phase {
|
||||
return workflow.Phase{
|
||||
Name: kubeconfigFilePhaseProperties[kubeConfigFileName].name,
|
||||
Short: kubeconfigFilePhaseProperties[kubeConfigFileName].short,
|
||||
Long: fmt.Sprintf(kubeconfigFilePhaseProperties[kubeConfigFileName].long, kubeConfigFileName),
|
||||
Run: runKubeConfigFile(kubeConfigFileName),
|
||||
}
|
||||
}
|
||||
|
||||
func runKubeConfig(c workflow.RunData) error {
|
||||
data, ok := c.(kubeConfigData)
|
||||
if !ok {
|
||||
return errors.New("kubeconfig phase invoked with an invalid data struct")
|
||||
}
|
||||
|
||||
fmt.Printf("[kubeconfig] Using kubeconfig folder %q\n", data.KubeConfigDir())
|
||||
return nil
|
||||
}
|
||||
|
||||
// runKubeConfigFile executes kubeconfig creation logic.
|
||||
func runKubeConfigFile(kubeConfigFileName string) func(workflow.RunData) error {
|
||||
return func(c workflow.RunData) error {
|
||||
data, ok := c.(kubeConfigData)
|
||||
if !ok {
|
||||
return errors.New("kubeconfig phase invoked with an invalid data struct")
|
||||
}
|
||||
|
||||
// if external CA mode, skip certificate authority generation
|
||||
if data.ExternalCA() {
|
||||
//TODO: implement validation of existing kubeconfig files
|
||||
fmt.Printf("[kubeconfig] External CA mode: Using user provided %s\n", kubeConfigFileName)
|
||||
return nil
|
||||
}
|
||||
|
||||
// if dryrunning, reads certificates from a temporary folder (and defer restore to the path originally specified by the user)
|
||||
cfg := data.Cfg()
|
||||
cfg.CertificatesDir = data.CertificateWriteDir()
|
||||
defer func() { cfg.CertificatesDir = data.CertificateDir() }()
|
||||
|
||||
// creates the KubeConfig file (or use existing)
|
||||
return kubeconfigphase.CreateKubeConfigFile(kubeConfigFileName, data.KubeConfigDir(), data.Cfg())
|
||||
}
|
||||
}
|
||||
|
||||
// NewCmdKubeConfig returns main command for kubeconfig phase
|
||||
func NewCmdKubeConfig(out io.Writer) *cobra.Command {
|
||||
cmd := &cobra.Command{
|
||||
Use: "kubeconfig",
|
||||
Short: "Generates all kubeconfig files necessary to establish the control plane and the admin kubeconfig file",
|
||||
Long: cmdutil.MacroCommandLongDescription,
|
||||
Short: "kubeconfig file utilities",
|
||||
Long: kubeconfigLongDesc,
|
||||
}
|
||||
|
||||
cmd.AddCommand(getKubeConfigSubCommands(out, kubeadmconstants.KubernetesDir, "")...)
|
||||
cmd.AddCommand(NewCmdUserKubeConfig(out, kubeadmconstants.KubernetesDir, ""))
|
||||
return cmd
|
||||
}
|
||||
|
||||
// getKubeConfigSubCommands returns sub commands for kubeconfig phase
|
||||
func getKubeConfigSubCommands(out io.Writer, outDir, defaultKubernetesVersion string) []*cobra.Command {
|
||||
// NewCmdUserKubeConfig returns sub commands for kubeconfig phase
|
||||
func NewCmdUserKubeConfig(out io.Writer, outDir, defaultKubernetesVersion string) *cobra.Command {
|
||||
|
||||
cfg := &kubeadmapiv1beta1.InitConfiguration{}
|
||||
|
||||
|
@ -98,96 +171,36 @@ func getKubeConfigSubCommands(out io.Writer, outDir, defaultKubernetesVersion st
|
|||
|
||||
var cfgPath, token, clientName string
|
||||
var organizations []string
|
||||
var subCmds []*cobra.Command
|
||||
|
||||
subCmdProperties := []struct {
|
||||
use string
|
||||
short string
|
||||
long string
|
||||
examples string
|
||||
cmdFunc func(outDir string, cfg *kubeadmapi.InitConfiguration) error
|
||||
}{
|
||||
{
|
||||
use: "all",
|
||||
short: "Generates all kubeconfig files necessary to establish the control plane and the admin kubeconfig file",
|
||||
long: allKubeconfigLongDesc,
|
||||
examples: allKubeconfigExample,
|
||||
cmdFunc: kubeconfigphase.CreateInitKubeConfigFiles,
|
||||
},
|
||||
{
|
||||
use: "admin",
|
||||
short: "Generates a kubeconfig file for the admin to use and for kubeadm itself",
|
||||
long: adminKubeconfigLongDesc,
|
||||
cmdFunc: kubeconfigphase.CreateAdminKubeConfigFile,
|
||||
},
|
||||
{
|
||||
use: "kubelet",
|
||||
short: "Generates a kubeconfig file for the kubelet to use. Please note that this should be used *only* for bootstrapping purposes",
|
||||
long: kubeletKubeconfigLongDesc,
|
||||
cmdFunc: kubeconfigphase.CreateKubeletKubeConfigFile,
|
||||
},
|
||||
{
|
||||
use: "controller-manager",
|
||||
short: "Generates a kubeconfig file for the controller manager to use",
|
||||
long: controllerManagerKubeconfigLongDesc,
|
||||
cmdFunc: kubeconfigphase.CreateControllerManagerKubeConfigFile,
|
||||
},
|
||||
{
|
||||
use: "scheduler",
|
||||
short: "Generates a kubeconfig file for the scheduler to use",
|
||||
long: schedulerKubeconfigLongDesc,
|
||||
cmdFunc: kubeconfigphase.CreateSchedulerKubeConfigFile,
|
||||
},
|
||||
{
|
||||
use: "user",
|
||||
short: "Outputs a kubeconfig file for an additional user",
|
||||
long: userKubeconfigLongDesc,
|
||||
examples: userKubeconfigExample,
|
||||
cmdFunc: func(outDir string, cfg *kubeadmapi.InitConfiguration) error {
|
||||
if clientName == "" {
|
||||
return errors.New("missing required argument --client-name")
|
||||
}
|
||||
// Creates the UX Command
|
||||
cmd := &cobra.Command{
|
||||
Use: "user",
|
||||
Short: "Outputs a kubeconfig file for an additional user",
|
||||
Long: userKubeconfigLongDesc,
|
||||
Example: userKubeconfigExample,
|
||||
Run: runCmdPhase(func(outDir string, cfg *kubeadmapi.InitConfiguration) error {
|
||||
if clientName == "" {
|
||||
return errors.New("missing required argument --client-name")
|
||||
}
|
||||
|
||||
// if the kubeconfig file for an additional user has to use a token, use it
|
||||
if token != "" {
|
||||
return kubeconfigphase.WriteKubeConfigWithToken(out, cfg, clientName, token)
|
||||
}
|
||||
// if the kubeconfig file for an additional user has to use a token, use it
|
||||
if token != "" {
|
||||
return kubeconfigphase.WriteKubeConfigWithToken(out, cfg, clientName, token)
|
||||
}
|
||||
|
||||
// Otherwise, write a kubeconfig file with a generate client cert
|
||||
return kubeconfigphase.WriteKubeConfigWithClientCert(out, cfg, clientName, organizations)
|
||||
},
|
||||
},
|
||||
// Otherwise, write a kubeconfig file with a generate client cert
|
||||
return kubeconfigphase.WriteKubeConfigWithClientCert(out, cfg, clientName, organizations)
|
||||
}, &outDir, &cfgPath, cfg, defaultKubernetesVersion),
|
||||
}
|
||||
|
||||
for _, properties := range subCmdProperties {
|
||||
// Creates the UX Command
|
||||
cmd := &cobra.Command{
|
||||
Use: properties.use,
|
||||
Short: properties.short,
|
||||
Long: properties.long,
|
||||
Example: properties.examples,
|
||||
Run: runCmdPhase(properties.cmdFunc, &outDir, &cfgPath, cfg, defaultKubernetesVersion),
|
||||
}
|
||||
// Add flags to the command
|
||||
cmd.Flags().StringVar(&cfg.CertificatesDir, "cert-dir", cfg.CertificatesDir, "The path where certificates are stored")
|
||||
cmd.Flags().StringVar(&cfg.APIEndpoint.AdvertiseAddress, "apiserver-advertise-address", cfg.APIEndpoint.AdvertiseAddress, "The IP address the API server is accessible on")
|
||||
cmd.Flags().Int32Var(&cfg.APIEndpoint.BindPort, "apiserver-bind-port", cfg.APIEndpoint.BindPort, "The port the API server is accessible on")
|
||||
cmd.Flags().StringVar(&outDir, "kubeconfig-dir", outDir, "The path where to save the kubeconfig file")
|
||||
cmd.Flags().StringVar(&token, "token", token, "The token that should be used as the authentication mechanism for this kubeconfig, instead of client certificates")
|
||||
cmd.Flags().StringVar(&clientName, "client-name", clientName, "The name of user. It will be used as the CN if client certificates are created")
|
||||
cmd.Flags().StringSliceVar(&organizations, "org", organizations, "The orgnizations of the client certificate. It will be used as the O if client certificates are created")
|
||||
|
||||
// Add flags to the command
|
||||
if properties.use != "user" {
|
||||
cmd.Flags().StringVar(&cfgPath, "config", cfgPath, "Path to kubeadm config file. WARNING: Usage of a configuration file is experimental")
|
||||
}
|
||||
cmd.Flags().StringVar(&cfg.CertificatesDir, "cert-dir", cfg.CertificatesDir, "The path where certificates are stored")
|
||||
cmd.Flags().StringVar(&cfg.APIEndpoint.AdvertiseAddress, "apiserver-advertise-address", cfg.APIEndpoint.AdvertiseAddress, "The IP address the API server is accessible on")
|
||||
cmd.Flags().Int32Var(&cfg.APIEndpoint.BindPort, "apiserver-bind-port", cfg.APIEndpoint.BindPort, "The port the API server is accessible on")
|
||||
cmd.Flags().StringVar(&outDir, "kubeconfig-dir", outDir, "The path where to save the kubeconfig file")
|
||||
if properties.use == "all" || properties.use == "kubelet" {
|
||||
cmd.Flags().StringVar(&cfg.NodeRegistration.Name, "node-name", cfg.NodeRegistration.Name, `The node name that should be used for the kubelet client certificate`)
|
||||
}
|
||||
if properties.use == "user" {
|
||||
cmd.Flags().StringVar(&token, "token", token, "The token that should be used as the authentication mechanism for this kubeconfig, instead of client certificates")
|
||||
cmd.Flags().StringVar(&clientName, "client-name", clientName, "The name of user. It will be used as the CN if client certificates are created")
|
||||
cmd.Flags().StringSliceVar(&organizations, "org", organizations, "The orgnizations of the client certificate. It will be used as the O if client certificates are created")
|
||||
}
|
||||
|
||||
subCmds = append(subCmds, cmd)
|
||||
}
|
||||
|
||||
return subCmds
|
||||
return cmd
|
||||
}
|
||||
|
|
|
@ -20,299 +20,30 @@ import (
|
|||
"bytes"
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
"k8s.io/client-go/tools/clientcmd"
|
||||
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
|
||||
kubeadmconstants "k8s.io/kubernetes/cmd/kubeadm/app/constants"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/phases/certs/pkiutil"
|
||||
|
||||
testutil "k8s.io/kubernetes/cmd/kubeadm/test"
|
||||
cmdtestutil "k8s.io/kubernetes/cmd/kubeadm/test/cmd"
|
||||
kubeconfigtestutil "k8s.io/kubernetes/cmd/kubeadm/test/kubeconfig"
|
||||
)
|
||||
|
||||
func TestKubeConfigCSubCommandsHasFlags(t *testing.T) {
|
||||
cmd := NewCmdUserKubeConfig(nil, "", phaseTestK8sVersion)
|
||||
|
||||
subCmds := getKubeConfigSubCommands(nil, "", phaseTestK8sVersion)
|
||||
|
||||
commonFlags := []string{
|
||||
flags := []string{
|
||||
"cert-dir",
|
||||
"apiserver-advertise-address",
|
||||
"apiserver-bind-port",
|
||||
"kubeconfig-dir",
|
||||
"token",
|
||||
"client-name",
|
||||
}
|
||||
|
||||
var tests = []struct {
|
||||
command string
|
||||
additionalFlags []string
|
||||
}{
|
||||
{
|
||||
command: "all",
|
||||
additionalFlags: []string{
|
||||
"config",
|
||||
"node-name",
|
||||
},
|
||||
},
|
||||
{
|
||||
command: "admin",
|
||||
additionalFlags: []string{
|
||||
"config",
|
||||
},
|
||||
},
|
||||
{
|
||||
command: "kubelet",
|
||||
additionalFlags: []string{
|
||||
"config",
|
||||
"node-name",
|
||||
},
|
||||
},
|
||||
{
|
||||
command: "controller-manager",
|
||||
additionalFlags: []string{
|
||||
"config",
|
||||
},
|
||||
},
|
||||
{
|
||||
command: "scheduler",
|
||||
additionalFlags: []string{
|
||||
"config",
|
||||
},
|
||||
},
|
||||
{
|
||||
command: "user",
|
||||
additionalFlags: []string{
|
||||
"token",
|
||||
"client-name",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
expectedFlags := append(commonFlags, test.additionalFlags...)
|
||||
cmdtestutil.AssertSubCommandHasFlags(t, subCmds, test.command, expectedFlags...)
|
||||
}
|
||||
}
|
||||
|
||||
func TestKubeConfigSubCommandsThatCreateFilesWithFlags(t *testing.T) {
|
||||
|
||||
commonFlags := []string{
|
||||
"--apiserver-advertise-address=1.2.3.4",
|
||||
"--apiserver-bind-port=1234",
|
||||
}
|
||||
|
||||
var tests = []struct {
|
||||
command string
|
||||
additionalFlags []string
|
||||
expectedFiles []string
|
||||
}{
|
||||
{
|
||||
command: "all",
|
||||
additionalFlags: []string{"--node-name=valid-nome-name"},
|
||||
expectedFiles: []string{
|
||||
kubeadmconstants.AdminKubeConfigFileName,
|
||||
kubeadmconstants.KubeletKubeConfigFileName,
|
||||
kubeadmconstants.ControllerManagerKubeConfigFileName,
|
||||
kubeadmconstants.SchedulerKubeConfigFileName,
|
||||
},
|
||||
},
|
||||
{
|
||||
command: "admin",
|
||||
expectedFiles: []string{kubeadmconstants.AdminKubeConfigFileName},
|
||||
},
|
||||
{
|
||||
command: "kubelet",
|
||||
additionalFlags: []string{"--node-name=valid-nome-name"},
|
||||
expectedFiles: []string{kubeadmconstants.KubeletKubeConfigFileName},
|
||||
},
|
||||
{
|
||||
command: "controller-manager",
|
||||
expectedFiles: []string{kubeadmconstants.ControllerManagerKubeConfigFileName},
|
||||
},
|
||||
{
|
||||
command: "scheduler",
|
||||
expectedFiles: []string{kubeadmconstants.SchedulerKubeConfigFileName},
|
||||
},
|
||||
}
|
||||
|
||||
var kubeConfigAssertions = map[string]struct {
|
||||
clientName string
|
||||
organizations []string
|
||||
}{
|
||||
kubeadmconstants.AdminKubeConfigFileName: {
|
||||
clientName: "kubernetes-admin",
|
||||
organizations: []string{kubeadmconstants.MastersGroup},
|
||||
},
|
||||
kubeadmconstants.KubeletKubeConfigFileName: {
|
||||
clientName: "system:node:valid-nome-name",
|
||||
organizations: []string{kubeadmconstants.NodesGroup},
|
||||
},
|
||||
kubeadmconstants.ControllerManagerKubeConfigFileName: {
|
||||
clientName: kubeadmconstants.ControllerManagerUser,
|
||||
},
|
||||
kubeadmconstants.SchedulerKubeConfigFileName: {
|
||||
clientName: kubeadmconstants.SchedulerUser,
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
|
||||
// Create temp folder for the test case
|
||||
tmpdir := testutil.SetupTempDir(t)
|
||||
defer os.RemoveAll(tmpdir)
|
||||
|
||||
// Adds a pki folder with a ca certs to the temp folder
|
||||
pkidir := testutil.SetupPkiDirWithCertificateAuthorithy(t, tmpdir)
|
||||
|
||||
outputdir := tmpdir
|
||||
|
||||
// Retrieves ca cert for assertions
|
||||
caCert, _, err := pkiutil.TryLoadCertAndKeyFromDisk(pkidir, kubeadmconstants.CACertAndKeyBaseName)
|
||||
if err != nil {
|
||||
t.Fatalf("couldn't retrieve ca cert: %v", err)
|
||||
}
|
||||
|
||||
// Get subcommands working in the temporary directory
|
||||
subCmds := getKubeConfigSubCommands(nil, tmpdir, phaseTestK8sVersion)
|
||||
|
||||
// Execute the subcommand
|
||||
certDirFlag := fmt.Sprintf("--cert-dir=%s", pkidir)
|
||||
outputDirFlag := fmt.Sprintf("--kubeconfig-dir=%s", outputdir)
|
||||
allFlags := append(commonFlags, certDirFlag)
|
||||
allFlags = append(allFlags, outputDirFlag)
|
||||
allFlags = append(allFlags, test.additionalFlags...)
|
||||
cmdtestutil.RunSubCommand(t, subCmds, test.command, allFlags...)
|
||||
|
||||
// Checks that requested files are there
|
||||
testutil.AssertFileExists(t, tmpdir, test.expectedFiles...)
|
||||
|
||||
// Checks contents of generated files
|
||||
for _, file := range test.expectedFiles {
|
||||
|
||||
// reads generated files
|
||||
config, err := clientcmd.LoadFromFile(filepath.Join(tmpdir, file))
|
||||
if err != nil {
|
||||
t.Errorf("couldn't load generated kubeconfig file: %v", err)
|
||||
}
|
||||
|
||||
// checks that CLI flags are properly propagated and kubeconfig properties are correct
|
||||
kubeconfigtestutil.AssertKubeConfigCurrentCluster(t, config, "https://1.2.3.4:1234", caCert)
|
||||
|
||||
expectedClientName := kubeConfigAssertions[file].clientName
|
||||
expectedOrganizations := kubeConfigAssertions[file].organizations
|
||||
kubeconfigtestutil.AssertKubeConfigCurrentAuthInfoWithClientCert(t, config, caCert, expectedClientName, expectedOrganizations...)
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestKubeConfigSubCommandsThatCreateFilesWithConfigFile(t *testing.T) {
|
||||
|
||||
var tests = []struct {
|
||||
command string
|
||||
expectedFiles []string
|
||||
}{
|
||||
{
|
||||
command: "all",
|
||||
expectedFiles: []string{
|
||||
kubeadmconstants.AdminKubeConfigFileName,
|
||||
kubeadmconstants.KubeletKubeConfigFileName,
|
||||
kubeadmconstants.ControllerManagerKubeConfigFileName,
|
||||
kubeadmconstants.SchedulerKubeConfigFileName,
|
||||
},
|
||||
},
|
||||
{
|
||||
command: "admin",
|
||||
expectedFiles: []string{kubeadmconstants.AdminKubeConfigFileName},
|
||||
},
|
||||
{
|
||||
command: "kubelet",
|
||||
expectedFiles: []string{kubeadmconstants.KubeletKubeConfigFileName},
|
||||
},
|
||||
{
|
||||
command: "controller-manager",
|
||||
expectedFiles: []string{kubeadmconstants.ControllerManagerKubeConfigFileName},
|
||||
},
|
||||
{
|
||||
command: "scheduler",
|
||||
expectedFiles: []string{kubeadmconstants.SchedulerKubeConfigFileName},
|
||||
},
|
||||
}
|
||||
|
||||
var kubeConfigAssertions = map[string]struct {
|
||||
clientName string
|
||||
organizations []string
|
||||
}{
|
||||
kubeadmconstants.AdminKubeConfigFileName: {
|
||||
clientName: "kubernetes-admin",
|
||||
organizations: []string{kubeadmconstants.MastersGroup},
|
||||
},
|
||||
kubeadmconstants.KubeletKubeConfigFileName: {
|
||||
clientName: "system:node:valid-node-name",
|
||||
organizations: []string{kubeadmconstants.NodesGroup},
|
||||
},
|
||||
kubeadmconstants.ControllerManagerKubeConfigFileName: {
|
||||
clientName: kubeadmconstants.ControllerManagerUser,
|
||||
},
|
||||
kubeadmconstants.SchedulerKubeConfigFileName: {
|
||||
clientName: kubeadmconstants.SchedulerUser,
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
|
||||
// Create temp folder for the test case
|
||||
tmpdir := testutil.SetupTempDir(t)
|
||||
defer os.RemoveAll(tmpdir)
|
||||
|
||||
// Adds a pki folder with a ca certs to the temp folder
|
||||
pkidir := testutil.SetupPkiDirWithCertificateAuthorithy(t, tmpdir)
|
||||
|
||||
// Retrieves ca cert for assertions
|
||||
caCert, _, err := pkiutil.TryLoadCertAndKeyFromDisk(pkidir, kubeadmconstants.CACertAndKeyBaseName)
|
||||
if err != nil {
|
||||
t.Fatalf("couldn't retrieve ca cert: %v", err)
|
||||
}
|
||||
|
||||
// Adds a master configuration file
|
||||
cfg := &kubeadmapi.InitConfiguration{
|
||||
APIEndpoint: kubeadmapi.APIEndpoint{AdvertiseAddress: "1.2.3.4", BindPort: 1234},
|
||||
ClusterConfiguration: kubeadmapi.ClusterConfiguration{
|
||||
CertificatesDir: pkidir,
|
||||
},
|
||||
NodeRegistration: kubeadmapi.NodeRegistrationOptions{Name: "valid-node-name"},
|
||||
}
|
||||
cfgPath := testutil.SetupInitConfigurationFile(t, tmpdir, cfg)
|
||||
|
||||
// Get subcommands working in the temporary directory
|
||||
subCmds := getKubeConfigSubCommands(nil, tmpdir, phaseTestK8sVersion)
|
||||
|
||||
// Execute the subcommand
|
||||
configFlag := fmt.Sprintf("--config=%s", cfgPath)
|
||||
cmdtestutil.RunSubCommand(t, subCmds, test.command, configFlag)
|
||||
|
||||
// Checks that requested files are there
|
||||
testutil.AssertFileExists(t, tmpdir, test.expectedFiles...)
|
||||
|
||||
// Checks contents of generated files
|
||||
for _, file := range test.expectedFiles {
|
||||
|
||||
// reads generated files
|
||||
config, err := clientcmd.LoadFromFile(filepath.Join(tmpdir, file))
|
||||
if err != nil {
|
||||
t.Errorf("couldn't load generated kubeconfig file: %v", err)
|
||||
}
|
||||
|
||||
// checks that config file properties are properly propagated and kubeconfig properties are correct
|
||||
kubeconfigtestutil.AssertKubeConfigCurrentCluster(t, config, "https://1.2.3.4:1234", caCert)
|
||||
|
||||
expectedClientName := kubeConfigAssertions[file].clientName
|
||||
expectedOrganizations := kubeConfigAssertions[file].organizations
|
||||
kubeconfigtestutil.AssertKubeConfigCurrentAuthInfoWithClientCert(t, config, caCert, expectedClientName, expectedOrganizations...)
|
||||
|
||||
}
|
||||
}
|
||||
cmdtestutil.AssertSubCommandHasFlags(t, []*cobra.Command{cmd}, "user", flags...)
|
||||
}
|
||||
|
||||
func TestKubeConfigSubCommandsThatWritesToOut(t *testing.T) {
|
||||
|
@ -361,11 +92,11 @@ func TestKubeConfigSubCommandsThatWritesToOut(t *testing.T) {
|
|||
buf := new(bytes.Buffer)
|
||||
|
||||
// Get subcommands working in the temporary directory
|
||||
subCmds := getKubeConfigSubCommands(buf, tmpdir, phaseTestK8sVersion)
|
||||
cmd := NewCmdUserKubeConfig(buf, tmpdir, phaseTestK8sVersion)
|
||||
|
||||
// Execute the subcommand
|
||||
allFlags := append(commonFlags, test.additionalFlags...)
|
||||
cmdtestutil.RunSubCommand(t, subCmds, test.command, allFlags...)
|
||||
cmdtestutil.RunSubCommand(t, []*cobra.Command{cmd}, test.command, allFlags...)
|
||||
|
||||
// reads kubeconfig written to stdout
|
||||
config, err := clientcmd.Load(buf.Bytes())
|
||||
|
|
|
@ -81,7 +81,7 @@ func runPreflightMaster(c workflow.RunData) error {
|
|||
return errors.New("preflight phase invoked with an invalid data struct")
|
||||
}
|
||||
|
||||
fmt.Println("[preflight] running pre-flight checks")
|
||||
fmt.Println("[preflight] Running pre-flight checks")
|
||||
if err := preflight.RunInitMasterChecks(utilsexec.New(), data.Cfg(), data.IgnorePreflightErrors()); err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
|
@ -25,7 +25,6 @@ import (
|
|||
|
||||
"github.com/golang/glog"
|
||||
"github.com/pkg/errors"
|
||||
|
||||
certutil "k8s.io/client-go/util/cert"
|
||||
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
|
||||
kubeadmconstants "k8s.io/kubernetes/cmd/kubeadm/app/constants"
|
||||
|
@ -57,7 +56,7 @@ func CreatePKIAssets(cfg *kubeadmapi.InitConfiguration) error {
|
|||
return errors.Wrap(err, "error creating PKI assets")
|
||||
}
|
||||
|
||||
fmt.Printf("[certificates] valid certificates and keys now exist in %q\n", cfg.CertificatesDir)
|
||||
fmt.Printf("[certs] valid certificates and keys now exist in %q\n", cfg.CertificatesDir)
|
||||
|
||||
// Service accounts are not x509 certs, so handled separately
|
||||
if err := CreateServiceAccountKeyAndPublicKeyFiles(cfg); err != nil {
|
||||
|
@ -190,15 +189,14 @@ func writeCertificateAuthorithyFilesIfNotExist(pkiDir string, baseName string, c
|
|||
// kubeadm doesn't validate the existing certificate Authority more than this;
|
||||
// Basically, if we find a certificate file with the same path; and it is a CA
|
||||
// kubeadm thinks those files are equal and doesn't bother writing a new file
|
||||
fmt.Printf("[certificates] Using the existing %s certificate and key.\n", baseName)
|
||||
fmt.Printf("[certs] Using the existing %q certificate and key\n", baseName)
|
||||
} else {
|
||||
|
||||
// Write .crt and .key files to disk
|
||||
fmt.Printf("[certs] Generating %q certificate and key\n", baseName)
|
||||
|
||||
if err := pkiutil.WriteCertAndKey(pkiDir, baseName, caCert, caKey); err != nil {
|
||||
return errors.Wrapf(err, "failure while saving %s certificate and key", baseName)
|
||||
}
|
||||
|
||||
fmt.Printf("[certificates] Generated %s certificate and key.\n", baseName)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
@ -226,17 +224,16 @@ func writeCertificateFilesIfNotExist(pkiDir string, baseName string, signingCert
|
|||
// Basically, if we find a certificate file with the same path; and it is signed by
|
||||
// the expected certificate authority, kubeadm thinks those files are equal and
|
||||
// doesn't bother writing a new file
|
||||
fmt.Printf("[certificates] Using the existing %s certificate and key.\n", baseName)
|
||||
fmt.Printf("[certs] Using the existing %q certificate and key\n", baseName)
|
||||
} else {
|
||||
|
||||
// Write .crt and .key files to disk
|
||||
fmt.Printf("[certs] Generating %q certificate and key\n", baseName)
|
||||
|
||||
if err := pkiutil.WriteCertAndKey(pkiDir, baseName, cert, key); err != nil {
|
||||
return errors.Wrapf(err, "failure while saving %s certificate and key", baseName)
|
||||
}
|
||||
|
||||
fmt.Printf("[certificates] Generated %s certificate and key.\n", baseName)
|
||||
if pkiutil.HasServerAuth(cert) {
|
||||
fmt.Printf("[certificates] %s serving cert is signed for DNS names %v and IPs %v\n", baseName, cert.DNSNames, cert.IPAddresses)
|
||||
fmt.Printf("[certs] %s serving cert is signed for DNS names %v and IPs %v\n", baseName, cert.DNSNames, cert.IPAddresses)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -261,10 +258,12 @@ func writeKeyFilesIfNotExist(pkiDir string, baseName string, key *rsa.PrivateKey
|
|||
// kubeadm doesn't validate the existing certificate key more than this;
|
||||
// Basically, if we find a key file with the same path kubeadm thinks those files
|
||||
// are equal and doesn't bother writing a new file
|
||||
fmt.Printf("[certificates] Using the existing %s key.\n", baseName)
|
||||
fmt.Printf("[certs] Using the existing %q key\n", baseName)
|
||||
} else {
|
||||
|
||||
// Write .key and .pub files to disk
|
||||
fmt.Printf("[certs] Generating %q key and public key\n", baseName)
|
||||
|
||||
if err := pkiutil.WriteKey(pkiDir, baseName, key); err != nil {
|
||||
return errors.Wrapf(err, "failure while saving %s key", baseName)
|
||||
}
|
||||
|
@ -272,7 +271,6 @@ func writeKeyFilesIfNotExist(pkiDir string, baseName string, key *rsa.PrivateKey
|
|||
if err := pkiutil.WritePublicKey(pkiDir, baseName, &key.PublicKey); err != nil {
|
||||
return errors.Wrapf(err, "failure while saving %s public key", baseName)
|
||||
}
|
||||
fmt.Printf("[certificates] Generated %s key and public key.\n", baseName)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
|
|
@ -18,17 +18,15 @@ package kubeconfig
|
|||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/rsa"
|
||||
"crypto/x509"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"crypto/rsa"
|
||||
|
||||
"github.com/golang/glog"
|
||||
"github.com/pkg/errors"
|
||||
|
||||
"k8s.io/client-go/tools/clientcmd"
|
||||
clientcmdapi "k8s.io/client-go/tools/clientcmd/api"
|
||||
certutil "k8s.io/client-go/util/cert"
|
||||
|
@ -88,32 +86,11 @@ func CreateJoinControlPlaneKubeConfigFiles(outDir string, cfg *kubeadmapi.InitCo
|
|||
)
|
||||
}
|
||||
|
||||
// CreateAdminKubeConfigFile create a kubeconfig file for the admin to use and for kubeadm itself.
|
||||
// CreateKubeConfigFile creates a kubeconfig file.
|
||||
// If the kubeconfig file already exists, it is used only if evaluated equal; otherwise an error is returned.
|
||||
func CreateAdminKubeConfigFile(outDir string, cfg *kubeadmapi.InitConfiguration) error {
|
||||
glog.V(1).Infoln("create a kubeconfig file for the admin and for kubeadm itself")
|
||||
return createKubeConfigFiles(outDir, cfg, kubeadmconstants.AdminKubeConfigFileName)
|
||||
}
|
||||
|
||||
// CreateKubeletKubeConfigFile create a kubeconfig file for the Kubelet to use.
|
||||
// If the kubeconfig file already exists, it is used only if evaluated equal; otherwise an error is returned.
|
||||
func CreateKubeletKubeConfigFile(outDir string, cfg *kubeadmapi.InitConfiguration) error {
|
||||
glog.V(1).Infoln("creating a kubeconfig file for the Kubelet")
|
||||
return createKubeConfigFiles(outDir, cfg, kubeadmconstants.KubeletKubeConfigFileName)
|
||||
}
|
||||
|
||||
// CreateControllerManagerKubeConfigFile create a kubeconfig file for the ControllerManager to use.
|
||||
// If the kubeconfig file already exists, it is used only if evaluated equal; otherwise an error is returned.
|
||||
func CreateControllerManagerKubeConfigFile(outDir string, cfg *kubeadmapi.InitConfiguration) error {
|
||||
glog.V(1).Infoln("creating kubeconfig file for the ControllerManager")
|
||||
return createKubeConfigFiles(outDir, cfg, kubeadmconstants.ControllerManagerKubeConfigFileName)
|
||||
}
|
||||
|
||||
// CreateSchedulerKubeConfigFile create a create a kubeconfig file for the Scheduler to use.
|
||||
// If the kubeconfig file already exists, it is used only if evaluated equal; otherwise an error is returned.
|
||||
func CreateSchedulerKubeConfigFile(outDir string, cfg *kubeadmapi.InitConfiguration) error {
|
||||
glog.V(1).Infoln("creating kubeconfig file for Scheduler")
|
||||
return createKubeConfigFiles(outDir, cfg, kubeadmconstants.SchedulerKubeConfigFileName)
|
||||
func CreateKubeConfigFile(kubeConfigFileName string, outDir string, cfg *kubeadmapi.InitConfiguration) error {
|
||||
glog.V(1).Infof("creating kubeconfig file for %s", kubeConfigFileName)
|
||||
return createKubeConfigFiles(outDir, cfg, kubeConfigFileName)
|
||||
}
|
||||
|
||||
// createKubeConfigFiles creates all the requested kubeconfig files.
|
||||
|
@ -248,12 +225,12 @@ func createKubeConfigFileIfNotExists(outDir, filename string, config *clientcmda
|
|||
|
||||
// Check if the file exist, and if it doesn't, just write it to disk
|
||||
if _, err := os.Stat(kubeConfigFilePath); os.IsNotExist(err) {
|
||||
fmt.Printf("[kubeconfig] Writing %q kubeconfig file\n", filename)
|
||||
|
||||
err = kubeconfigutil.WriteToDisk(kubeConfigFilePath, config)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "failed to save kubeconfig file %s on disk", kubeConfigFilePath)
|
||||
}
|
||||
|
||||
fmt.Printf("[kubeconfig] Wrote KubeConfig file to disk: %q\n", kubeConfigFilePath)
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
|
@ -292,22 +292,6 @@ func TestCreateKubeconfigFilesAndWrappers(t *testing.T) {
|
|||
kubeadmconstants.SchedulerKubeConfigFileName,
|
||||
},
|
||||
},
|
||||
{ // Test CreateAdminKubeConfigFile (wrapper to createKubeConfigFile)
|
||||
createKubeConfigFunction: CreateAdminKubeConfigFile,
|
||||
expectedFiles: []string{kubeadmconstants.AdminKubeConfigFileName},
|
||||
},
|
||||
{ // Test CreateKubeletKubeConfigFile (wrapper to createKubeConfigFile)
|
||||
createKubeConfigFunction: CreateKubeletKubeConfigFile,
|
||||
expectedFiles: []string{kubeadmconstants.KubeletKubeConfigFileName},
|
||||
},
|
||||
{ // Test CreateControllerManagerKubeConfigFile (wrapper to createKubeConfigFile)
|
||||
createKubeConfigFunction: CreateControllerManagerKubeConfigFile,
|
||||
expectedFiles: []string{kubeadmconstants.ControllerManagerKubeConfigFileName},
|
||||
},
|
||||
{ // Test createKubeConfigFile (wrapper to createKubeConfigFile)
|
||||
createKubeConfigFunction: CreateSchedulerKubeConfigFile,
|
||||
expectedFiles: []string{kubeadmconstants.SchedulerKubeConfigFileName},
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
|
|
|
@ -40,18 +40,16 @@ func TestCmdInitToken(t *testing.T) {
|
|||
args string
|
||||
expected bool
|
||||
}{
|
||||
/*
|
||||
{
|
||||
name: "invalid token size",
|
||||
args: "--token=abcd:1234567890abcd",
|
||||
expected: false,
|
||||
},
|
||||
{
|
||||
name: "invalid token non-lowercase",
|
||||
args: "--token=Abcdef:1234567890abcdef",
|
||||
expected: false,
|
||||
},
|
||||
*/
|
||||
{
|
||||
name: "invalid token size",
|
||||
args: "--token=abcd:1234567890abcd",
|
||||
expected: false,
|
||||
},
|
||||
{
|
||||
name: "invalid token non-lowercase",
|
||||
args: "--token=Abcdef:1234567890abcdef",
|
||||
expected: false,
|
||||
},
|
||||
{
|
||||
name: "valid token is accepted",
|
||||
args: "--token=abcdef.0123456789abcdef",
|
||||
|
|
|
@ -36,11 +36,6 @@ docs/admin/kubeadm_alpha_phase_controlplane_scheduler.md
|
|||
docs/admin/kubeadm_alpha_phase_etcd.md
|
||||
docs/admin/kubeadm_alpha_phase_etcd_local.md
|
||||
docs/admin/kubeadm_alpha_phase_kubeconfig.md
|
||||
docs/admin/kubeadm_alpha_phase_kubeconfig_admin.md
|
||||
docs/admin/kubeadm_alpha_phase_kubeconfig_all.md
|
||||
docs/admin/kubeadm_alpha_phase_kubeconfig_controller-manager.md
|
||||
docs/admin/kubeadm_alpha_phase_kubeconfig_kubelet.md
|
||||
docs/admin/kubeadm_alpha_phase_kubeconfig_scheduler.md
|
||||
docs/admin/kubeadm_alpha_phase_kubeconfig_user.md
|
||||
docs/admin/kubeadm_alpha_phase_kubelet.md
|
||||
docs/admin/kubeadm_alpha_phase_kubelet_config.md
|
||||
|
@ -81,6 +76,11 @@ docs/admin/kubeadm_init_phase_certs_etcd-server.md
|
|||
docs/admin/kubeadm_init_phase_certs_front-proxy-ca.md
|
||||
docs/admin/kubeadm_init_phase_certs_front-proxy-client.md
|
||||
docs/admin/kubeadm_init_phase_certs_sa.md
|
||||
docs/admin/kubeadm_init_phase_kubeconfig.md
|
||||
docs/admin/kubeadm_init_phase_kubeconfig_admin.md
|
||||
docs/admin/kubeadm_init_phase_kubeconfig_controller-manager.md
|
||||
docs/admin/kubeadm_init_phase_kubeconfig_kubelet.md
|
||||
docs/admin/kubeadm_init_phase_kubeconfig_scheduler.md
|
||||
docs/admin/kubeadm_init_phase_kubelet-start.md
|
||||
docs/admin/kubeadm_init_phase_preflight.md
|
||||
docs/admin/kubeadm_join.md
|
||||
|
@ -132,11 +132,6 @@ docs/man/man1/kubeadm-alpha-phase-controlplane-scheduler.1
|
|||
docs/man/man1/kubeadm-alpha-phase-controlplane.1
|
||||
docs/man/man1/kubeadm-alpha-phase-etcd-local.1
|
||||
docs/man/man1/kubeadm-alpha-phase-etcd.1
|
||||
docs/man/man1/kubeadm-alpha-phase-kubeconfig-admin.1
|
||||
docs/man/man1/kubeadm-alpha-phase-kubeconfig-all.1
|
||||
docs/man/man1/kubeadm-alpha-phase-kubeconfig-controller-manager.1
|
||||
docs/man/man1/kubeadm-alpha-phase-kubeconfig-kubelet.1
|
||||
docs/man/man1/kubeadm-alpha-phase-kubeconfig-scheduler.1
|
||||
docs/man/man1/kubeadm-alpha-phase-kubeconfig-user.1
|
||||
docs/man/man1/kubeadm-alpha-phase-kubeconfig.1
|
||||
docs/man/man1/kubeadm-alpha-phase-kubelet-config-annotate-cri.1
|
||||
|
@ -179,6 +174,11 @@ docs/man/man1/kubeadm-init-phase-certs-front-proxy-ca.1
|
|||
docs/man/man1/kubeadm-init-phase-certs-front-proxy-client.1
|
||||
docs/man/man1/kubeadm-init-phase-certs-sa.1
|
||||
docs/man/man1/kubeadm-init-phase-certs.1
|
||||
docs/man/man1/kubeadm-init-phase-kubeconfig-admin.1
|
||||
docs/man/man1/kubeadm-init-phase-kubeconfig-controller-manager.1
|
||||
docs/man/man1/kubeadm-init-phase-kubeconfig-kubelet.1
|
||||
docs/man/man1/kubeadm-init-phase-kubeconfig-scheduler.1
|
||||
docs/man/man1/kubeadm-init-phase-kubeconfig.1
|
||||
docs/man/man1/kubeadm-init-phase-kubelet-start.1
|
||||
docs/man/man1/kubeadm-init-phase-preflight.1
|
||||
docs/man/man1/kubeadm-init-phase.1
|
||||
|
|
Loading…
Reference in New Issue