diff --git a/cmd/kubeadm/app/apis/kubeadm/fuzzer/fuzzer.go b/cmd/kubeadm/app/apis/kubeadm/fuzzer/fuzzer.go index e6ac80a88c5..e73495384e9 100644 --- a/cmd/kubeadm/app/apis/kubeadm/fuzzer/fuzzer.go +++ b/cmd/kubeadm/app/apis/kubeadm/fuzzer/fuzzer.go @@ -64,6 +64,7 @@ func fuzzInitConfiguration(obj *kubeadm.InitConfiguration, c fuzz.Continue) { obj.SkipPhases = nil obj.NodeRegistration.ImagePullPolicy = corev1.PullIfNotPresent obj.Patches = nil + obj.DryRun = false } func fuzzNodeRegistration(obj *kubeadm.NodeRegistrationOptions, c fuzz.Continue) { @@ -129,6 +130,7 @@ func fuzzJoinConfiguration(obj *kubeadm.JoinConfiguration, c fuzz.Continue) { obj.SkipPhases = nil obj.NodeRegistration.ImagePullPolicy = corev1.PullIfNotPresent obj.Patches = nil + obj.DryRun = false } func fuzzJoinControlPlane(obj *kubeadm.JoinControlPlane, c fuzz.Continue) { diff --git a/cmd/kubeadm/app/apis/kubeadm/types.go b/cmd/kubeadm/app/apis/kubeadm/types.go index 00671e43b4c..63c7285cd03 100644 --- a/cmd/kubeadm/app/apis/kubeadm/types.go +++ b/cmd/kubeadm/app/apis/kubeadm/types.go @@ -44,6 +44,9 @@ type InitConfiguration struct { // BootstrapTokens is respected at `kubeadm init` time and describes a set of Bootstrap Tokens to create. BootstrapTokens []bootstraptokenv1.BootstrapToken + // DryRun tells if the dry run mode is enabled, don't apply any change if it is and just output what would be done. + DryRun bool + // NodeRegistration holds fields that relate to registering the new control-plane node to the cluster NodeRegistration NodeRegistrationOptions @@ -299,6 +302,9 @@ type ExternalEtcd struct { type JoinConfiguration struct { metav1.TypeMeta + // DryRun tells if the dry run mode is enabled, don't apply any change if it is and just output what would be done. + DryRun bool + // NodeRegistration holds fields that relate to registering the new control-plane node to the cluster NodeRegistration NodeRegistrationOptions diff --git a/cmd/kubeadm/app/apis/kubeadm/v1beta3/conversion.go b/cmd/kubeadm/app/apis/kubeadm/v1beta3/conversion.go index b77842990c1..8e0c079809c 100644 --- a/cmd/kubeadm/app/apis/kubeadm/v1beta3/conversion.go +++ b/cmd/kubeadm/app/apis/kubeadm/v1beta3/conversion.go @@ -27,6 +27,10 @@ func Convert_kubeadm_InitConfiguration_To_v1beta3_InitConfiguration(in *kubeadm. return autoConvert_kubeadm_InitConfiguration_To_v1beta3_InitConfiguration(in, out, s) } +func Convert_kubeadm_JoinConfiguration_To_v1beta3_JoinConfiguration(in *kubeadm.JoinConfiguration, out *JoinConfiguration, s conversion.Scope) error { + return autoConvert_kubeadm_JoinConfiguration_To_v1beta3_JoinConfiguration(in, out, s) +} + func Convert_v1beta3_InitConfiguration_To_kubeadm_InitConfiguration(in *InitConfiguration, out *kubeadm.InitConfiguration, s conversion.Scope) error { err := autoConvert_v1beta3_InitConfiguration_To_kubeadm_InitConfiguration(in, out, s) if err != nil { diff --git a/cmd/kubeadm/app/apis/kubeadm/v1beta3/zz_generated.conversion.go b/cmd/kubeadm/app/apis/kubeadm/v1beta3/zz_generated.conversion.go index e9f6c0cf6fa..881434d2ae1 100644 --- a/cmd/kubeadm/app/apis/kubeadm/v1beta3/zz_generated.conversion.go +++ b/cmd/kubeadm/app/apis/kubeadm/v1beta3/zz_generated.conversion.go @@ -154,11 +154,6 @@ func RegisterConversions(s *runtime.Scheme) error { }); err != nil { return err } - if err := s.AddGeneratedConversionFunc((*kubeadm.JoinConfiguration)(nil), (*JoinConfiguration)(nil), func(a, b interface{}, scope conversion.Scope) error { - return Convert_kubeadm_JoinConfiguration_To_v1beta3_JoinConfiguration(a.(*kubeadm.JoinConfiguration), b.(*JoinConfiguration), scope) - }); err != nil { - return err - } if err := s.AddGeneratedConversionFunc((*JoinControlPlane)(nil), (*kubeadm.JoinControlPlane)(nil), func(a, b interface{}, scope conversion.Scope) error { return Convert_v1beta3_JoinControlPlane_To_kubeadm_JoinControlPlane(a.(*JoinControlPlane), b.(*kubeadm.JoinControlPlane), scope) }); err != nil { @@ -209,6 +204,11 @@ func RegisterConversions(s *runtime.Scheme) error { }); err != nil { return err } + if err := s.AddConversionFunc((*kubeadm.JoinConfiguration)(nil), (*JoinConfiguration)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_kubeadm_JoinConfiguration_To_v1beta3_JoinConfiguration(a.(*kubeadm.JoinConfiguration), b.(*JoinConfiguration), scope) + }); err != nil { + return err + } if err := s.AddConversionFunc((*kubeadm.LocalEtcd)(nil), (*LocalEtcd)(nil), func(a, b interface{}, scope conversion.Scope) error { return Convert_kubeadm_LocalEtcd_To_v1beta3_LocalEtcd(a.(*kubeadm.LocalEtcd), b.(*LocalEtcd), scope) }); err != nil { @@ -591,6 +591,7 @@ func autoConvert_v1beta3_InitConfiguration_To_kubeadm_InitConfiguration(in *Init func autoConvert_kubeadm_InitConfiguration_To_v1beta3_InitConfiguration(in *kubeadm.InitConfiguration, out *InitConfiguration, s conversion.Scope) error { // WARNING: in.ClusterConfiguration requires manual conversion: does not exist in peer-type out.BootstrapTokens = *(*[]bootstraptokenv1.BootstrapToken)(unsafe.Pointer(&in.BootstrapTokens)) + // WARNING: in.DryRun requires manual conversion: does not exist in peer-type if err := Convert_kubeadm_NodeRegistrationOptions_To_v1beta3_NodeRegistrationOptions(&in.NodeRegistration, &out.NodeRegistration, s); err != nil { return err } @@ -623,6 +624,7 @@ func Convert_v1beta3_JoinConfiguration_To_kubeadm_JoinConfiguration(in *JoinConf } func autoConvert_kubeadm_JoinConfiguration_To_v1beta3_JoinConfiguration(in *kubeadm.JoinConfiguration, out *JoinConfiguration, s conversion.Scope) error { + // WARNING: in.DryRun requires manual conversion: does not exist in peer-type if err := Convert_kubeadm_NodeRegistrationOptions_To_v1beta3_NodeRegistrationOptions(&in.NodeRegistration, &out.NodeRegistration, s); err != nil { return err } @@ -636,11 +638,6 @@ func autoConvert_kubeadm_JoinConfiguration_To_v1beta3_JoinConfiguration(in *kube return nil } -// Convert_kubeadm_JoinConfiguration_To_v1beta3_JoinConfiguration is an autogenerated conversion function. -func Convert_kubeadm_JoinConfiguration_To_v1beta3_JoinConfiguration(in *kubeadm.JoinConfiguration, out *JoinConfiguration, s conversion.Scope) error { - return autoConvert_kubeadm_JoinConfiguration_To_v1beta3_JoinConfiguration(in, out, s) -} - func autoConvert_v1beta3_JoinControlPlane_To_kubeadm_JoinControlPlane(in *JoinControlPlane, out *kubeadm.JoinControlPlane, s conversion.Scope) error { if err := Convert_v1beta3_APIEndpoint_To_kubeadm_APIEndpoint(&in.LocalAPIEndpoint, &out.LocalAPIEndpoint, s); err != nil { return err diff --git a/cmd/kubeadm/app/apis/kubeadm/v1beta4/doc.go b/cmd/kubeadm/app/apis/kubeadm/v1beta4/doc.go index e22dd4f04e7..f87f92f83ce 100644 --- a/cmd/kubeadm/app/apis/kubeadm/v1beta4/doc.go +++ b/cmd/kubeadm/app/apis/kubeadm/v1beta4/doc.go @@ -28,6 +28,7 @@ limitations under the License. // - Support custom environment variables in control plane components under `ClusterConfiguration`. // Use `APIServer.ExtraEnvs`, `ControllerManager.ExtraEnvs`, `Scheduler.ExtraEnvs`, `Etcd.Local.ExtraEnvs`. // - The ResetConfiguration API type is now supported in v1beta4. Users are able to reset a node by passing a --config file to "kubeadm reset". +// - `dry-run` mode in is now configurable in InitConfiguration and JoinConfiguration config files. // // Migration from old kubeadm config versions // diff --git a/cmd/kubeadm/app/apis/kubeadm/v1beta4/types.go b/cmd/kubeadm/app/apis/kubeadm/v1beta4/types.go index 5be7195e6f6..b91863971ae 100644 --- a/cmd/kubeadm/app/apis/kubeadm/v1beta4/types.go +++ b/cmd/kubeadm/app/apis/kubeadm/v1beta4/types.go @@ -39,6 +39,10 @@ type InitConfiguration struct { // +optional BootstrapTokens []bootstraptokenv1.BootstrapToken `json:"bootstrapTokens,omitempty"` + // DryRun tells if the dry run mode is enabled, don't apply any change if it is and just output what would be done. + // +optional + DryRun bool `json:"dryRun,omitempty"` + // NodeRegistration holds fields that relate to registering the new control-plane node to the cluster // +optional NodeRegistration NodeRegistrationOptions `json:"nodeRegistration,omitempty"` @@ -326,6 +330,10 @@ type ExternalEtcd struct { type JoinConfiguration struct { metav1.TypeMeta `json:",inline"` + // DryRun tells if the dry run mode is enabled, don't apply any change if it is and just output what would be done. + // +optional + DryRun bool `json:"dryRun,omitempty"` + // NodeRegistration holds fields that relate to registering the new control-plane node to the cluster // +optional NodeRegistration NodeRegistrationOptions `json:"nodeRegistration,omitempty"` diff --git a/cmd/kubeadm/app/apis/kubeadm/v1beta4/zz_generated.conversion.go b/cmd/kubeadm/app/apis/kubeadm/v1beta4/zz_generated.conversion.go index 62b3e335f8e..6db00601463 100644 --- a/cmd/kubeadm/app/apis/kubeadm/v1beta4/zz_generated.conversion.go +++ b/cmd/kubeadm/app/apis/kubeadm/v1beta4/zz_generated.conversion.go @@ -581,6 +581,7 @@ func Convert_kubeadm_ImageMeta_To_v1beta4_ImageMeta(in *kubeadm.ImageMeta, out * func autoConvert_v1beta4_InitConfiguration_To_kubeadm_InitConfiguration(in *InitConfiguration, out *kubeadm.InitConfiguration, s conversion.Scope) error { out.BootstrapTokens = *(*[]bootstraptokenv1.BootstrapToken)(unsafe.Pointer(&in.BootstrapTokens)) + out.DryRun = in.DryRun if err := Convert_v1beta4_NodeRegistrationOptions_To_kubeadm_NodeRegistrationOptions(&in.NodeRegistration, &out.NodeRegistration, s); err != nil { return err } @@ -596,6 +597,7 @@ func autoConvert_v1beta4_InitConfiguration_To_kubeadm_InitConfiguration(in *Init func autoConvert_kubeadm_InitConfiguration_To_v1beta4_InitConfiguration(in *kubeadm.InitConfiguration, out *InitConfiguration, s conversion.Scope) error { // WARNING: in.ClusterConfiguration requires manual conversion: does not exist in peer-type out.BootstrapTokens = *(*[]bootstraptokenv1.BootstrapToken)(unsafe.Pointer(&in.BootstrapTokens)) + out.DryRun = in.DryRun if err := Convert_kubeadm_NodeRegistrationOptions_To_v1beta4_NodeRegistrationOptions(&in.NodeRegistration, &out.NodeRegistration, s); err != nil { return err } @@ -609,6 +611,7 @@ func autoConvert_kubeadm_InitConfiguration_To_v1beta4_InitConfiguration(in *kube } func autoConvert_v1beta4_JoinConfiguration_To_kubeadm_JoinConfiguration(in *JoinConfiguration, out *kubeadm.JoinConfiguration, s conversion.Scope) error { + out.DryRun = in.DryRun if err := Convert_v1beta4_NodeRegistrationOptions_To_kubeadm_NodeRegistrationOptions(&in.NodeRegistration, &out.NodeRegistration, s); err != nil { return err } @@ -628,6 +631,7 @@ func Convert_v1beta4_JoinConfiguration_To_kubeadm_JoinConfiguration(in *JoinConf } func autoConvert_kubeadm_JoinConfiguration_To_v1beta4_JoinConfiguration(in *kubeadm.JoinConfiguration, out *JoinConfiguration, s conversion.Scope) error { + out.DryRun = in.DryRun if err := Convert_kubeadm_NodeRegistrationOptions_To_v1beta4_NodeRegistrationOptions(&in.NodeRegistration, &out.NodeRegistration, s); err != nil { return err } diff --git a/cmd/kubeadm/app/cmd/init.go b/cmd/kubeadm/app/cmd/init.go index 06f64a91565..1b3940cd38e 100644 --- a/cmd/kubeadm/app/cmd/init.go +++ b/cmd/kubeadm/app/cmd/init.go @@ -279,15 +279,15 @@ func newInitOptions() *initOptions { // newInitData returns a new initData struct to be used for the execution of the kubeadm init workflow. // This func takes care of validating initOptions passed to the command, and then it converts // options into the internal InitConfiguration type that is used as input all the phases in the kubeadm init workflow -func newInitData(cmd *cobra.Command, args []string, options *initOptions, out io.Writer) (*initData, error) { +func newInitData(cmd *cobra.Command, args []string, initOptions *initOptions, out io.Writer) (*initData, error) { // Re-apply defaults to the public kubeadm API (this will set only values not exposed/not set as a flags) - kubeadmscheme.Scheme.Default(options.externalInitCfg) - kubeadmscheme.Scheme.Default(options.externalClusterCfg) + kubeadmscheme.Scheme.Default(initOptions.externalInitCfg) + kubeadmscheme.Scheme.Default(initOptions.externalClusterCfg) // Validate standalone flags values and/or combination of flags and then assigns // validated values to the public kubeadm config API when applicable var err error - if options.externalClusterCfg.FeatureGates, err = features.NewFeatureGate(&features.InitFeatureGates, options.featureGatesString); err != nil { + if initOptions.externalClusterCfg.FeatureGates, err = features.NewFeatureGate(&features.InitFeatureGates, initOptions.featureGatesString); err != nil { return nil, err } @@ -295,18 +295,18 @@ func newInitData(cmd *cobra.Command, args []string, options *initOptions, out io return nil, err } - if err = options.bto.ApplyTo(options.externalInitCfg); err != nil { + if err = initOptions.bto.ApplyTo(initOptions.externalInitCfg); err != nil { return nil, err } // Either use the config file if specified, or convert public kubeadm API to the internal InitConfiguration // and validates InitConfiguration - cfg, err := configutil.LoadOrDefaultInitConfiguration(options.cfgPath, options.externalInitCfg, options.externalClusterCfg) + cfg, err := configutil.LoadOrDefaultInitConfiguration(initOptions.cfgPath, initOptions.externalInitCfg, initOptions.externalClusterCfg) if err != nil { return nil, err } - ignorePreflightErrorsSet, err := validation.ValidateIgnorePreflightErrors(options.ignorePreflightErrors, cfg.NodeRegistration.IgnorePreflightErrors) + ignorePreflightErrorsSet, err := validation.ValidateIgnorePreflightErrors(initOptions.ignorePreflightErrors, cfg.NodeRegistration.IgnorePreflightErrors) if err != nil { return nil, err } @@ -314,8 +314,8 @@ func newInitData(cmd *cobra.Command, args []string, options *initOptions, out io cfg.NodeRegistration.IgnorePreflightErrors = sets.List(ignorePreflightErrorsSet) // override node name from the command line option - if options.externalInitCfg.NodeRegistration.Name != "" { - cfg.NodeRegistration.Name = options.externalInitCfg.NodeRegistration.Name + if initOptions.externalInitCfg.NodeRegistration.Name != "" { + cfg.NodeRegistration.Name = initOptions.externalInitCfg.NodeRegistration.Name } if err := configutil.VerifyAPIServerBindAddress(cfg.LocalAPIEndpoint.AdvertiseAddress); err != nil { @@ -327,7 +327,7 @@ func newInitData(cmd *cobra.Command, args []string, options *initOptions, out io // if dry running creates a temporary folder for saving kubeadm generated files dryRunDir := "" - if options.dryRun { + if initOptions.dryRun || cfg.DryRun { // the KUBEADM_INIT_DRYRUN_DIR environment variable allows overriding the dry-run temporary // directory from the command line. This makes it possible to run "kubeadm init" integration // tests without root. @@ -347,7 +347,7 @@ func newInitData(cmd *cobra.Command, args []string, options *initOptions, out io // Validate that also the required kubeconfig files exists and are invalid, because // kubeadm can't regenerate them without the CA Key - kubeconfigDir := options.kubeconfigDir + kubeconfigDir := initOptions.kubeconfigDir if err := kubeconfigphase.ValidateKubeconfigsForExternalCA(kubeconfigDir, cfg); err != nil { return nil, err } @@ -363,24 +363,24 @@ func newInitData(cmd *cobra.Command, args []string, options *initOptions, out io } } - if options.uploadCerts && (externalCA || externalFrontProxyCA) { + if initOptions.uploadCerts && (externalCA || externalFrontProxyCA) { return nil, errors.New("can't use upload-certs with an external CA or an external front-proxy CA") } return &initData{ cfg: cfg, certificatesDir: cfg.CertificatesDir, - skipTokenPrint: options.skipTokenPrint, - dryRun: options.dryRun, + skipTokenPrint: initOptions.skipTokenPrint, + dryRun: cmdutil.ValueFromFlagsOrConfig(cmd.Flags(), options.DryRun, cfg.DryRun, initOptions.dryRun).(bool), dryRunDir: dryRunDir, - kubeconfigDir: options.kubeconfigDir, - kubeconfigPath: options.kubeconfigPath, + kubeconfigDir: initOptions.kubeconfigDir, + kubeconfigPath: initOptions.kubeconfigPath, ignorePreflightErrors: ignorePreflightErrorsSet, externalCA: externalCA, outputWriter: out, - uploadCerts: options.uploadCerts, - skipCertificateKeyPrint: options.skipCertificateKeyPrint, - patchesDir: options.patchesDir, + uploadCerts: initOptions.uploadCerts, + skipCertificateKeyPrint: initOptions.skipCertificateKeyPrint, + patchesDir: initOptions.patchesDir, }, nil } diff --git a/cmd/kubeadm/app/cmd/join.go b/cmd/kubeadm/app/cmd/join.go index ff43aa4e64f..efde491ad64 100644 --- a/cmd/kubeadm/app/cmd/join.go +++ b/cmd/kubeadm/app/cmd/join.go @@ -454,7 +454,7 @@ func newJoinData(cmd *cobra.Command, args []string, opt *joinOptions, out io.Wri // if dry running, creates a temporary folder to save kubeadm generated files dryRunDir := "" - if opt.dryRun { + if opt.dryRun || cfg.DryRun { if dryRunDir, err = kubeadmconstants.CreateTempDirForKubeadm("", "kubeadm-join-dryrun"); err != nil { return nil, errors.Wrap(err, "couldn't create a temporary directory on dryrun") } @@ -462,11 +462,11 @@ func newJoinData(cmd *cobra.Command, args []string, opt *joinOptions, out io.Wri return &joinData{ cfg: cfg, + dryRun: cmdutil.ValueFromFlagsOrConfig(cmd.Flags(), options.DryRun, cfg.DryRun, opt.dryRun).(bool), tlsBootstrapCfg: tlsBootstrapCfg, ignorePreflightErrors: ignorePreflightErrorsSet, outputWriter: out, patchesDir: opt.patchesDir, - dryRun: opt.dryRun, dryRunDir: dryRunDir, }, nil }