Merge pull request #118866 from neolit123/1.28-add-v1beta4-to-scheme

kubeadm: add v1beta4 to scheme; add --allow-experimental-api flag
This commit is contained in:
Kubernetes Prow Robot 2023-06-27 08:56:44 -07:00 committed by GitHub
commit 1c32c3bd9f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 60 additions and 21 deletions

View File

@ -25,6 +25,7 @@ import (
"k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
"k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1beta3"
"k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1beta4"
)
// Scheme is the runtime.Scheme to which all kubeadm api types are registered.
@ -42,5 +43,8 @@ func init() {
func AddToScheme(scheme *runtime.Scheme) {
utilruntime.Must(kubeadm.AddToScheme(scheme))
utilruntime.Must(v1beta3.AddToScheme(scheme))
utilruntime.Must(scheme.SetVersionPriority(v1beta3.SchemeGroupVersion))
utilruntime.Must(v1beta4.AddToScheme(scheme))
// TODO: https://github.com/kubernetes/kubeadm/issues/2890
// make v1beta4 highest priority
utilruntime.Must(scheme.SetVersionPriority(v1beta3.SchemeGroupVersion, v1beta4.SchemeGroupVersion))
}

View File

@ -225,6 +225,8 @@ func getDefaultNodeConfigBytes() ([]byte, error) {
// newCmdConfigMigrate returns cobra.Command for "kubeadm config migrate" command
func newCmdConfigMigrate(out io.Writer) *cobra.Command {
var oldCfgPath, newCfgPath string
var allowExperimental bool
cmd := &cobra.Command{
Use: "migrate",
Short: "Read an older version of the kubeadm configuration API types from a file, and output the similar config object for the newer version",
@ -252,7 +254,7 @@ func newCmdConfigMigrate(out io.Writer) *cobra.Command {
return err
}
outputBytes, err := configutil.MigrateOldConfig(oldCfgBytes)
outputBytes, err := configutil.MigrateOldConfig(oldCfgBytes, allowExperimental)
if err != nil {
return err
}
@ -270,12 +272,14 @@ func newCmdConfigMigrate(out io.Writer) *cobra.Command {
}
cmd.Flags().StringVar(&oldCfgPath, "old-config", "", "Path to the kubeadm config file that is using an old API version and should be converted. This flag is mandatory.")
cmd.Flags().StringVar(&newCfgPath, "new-config", "", "Path to the resulting equivalent kubeadm config file using the new API version. Optional, if not specified output will be sent to STDOUT.")
cmd.Flags().BoolVar(&allowExperimental, options.AllowExperimentalAPI, false, "Allow migration to experimental, unreleased APIs.")
return cmd
}
// newCmdConfigValidate returns cobra.Command for the "kubeadm config validate" command
func newCmdConfigValidate(out io.Writer) *cobra.Command {
var cfgPath string
var allowExperimental bool
cmd := &cobra.Command{
Use: "validate",
@ -300,7 +304,7 @@ func newCmdConfigValidate(out io.Writer) *cobra.Command {
return err
}
if err := configutil.ValidateConfig(cfgBytes); err != nil {
if err := configutil.ValidateConfig(cfgBytes, allowExperimental); err != nil {
return err
}
fmt.Fprintln(out, "ok")
@ -310,6 +314,7 @@ func newCmdConfigValidate(out io.Writer) *cobra.Command {
Args: cobra.NoArgs,
}
options.AddConfigFlag(cmd.Flags(), &cfgPath)
cmd.Flags().BoolVar(&allowExperimental, options.AllowExperimentalAPI, false, "Allow validation of experimental, unreleased APIs.")
return cmd
}

View File

@ -142,4 +142,7 @@ const (
// CleanupTmpDir flag indicates whether reset will cleanup the tmp dir
CleanupTmpDir = "cleanup-tmp-dir"
// AllowExperimentalAPI flag can be used to allow experimental / work in progress APIs
AllowExperimentalAPI = "allow-experimental-api"
)

View File

@ -37,6 +37,7 @@ import (
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
kubeadmscheme "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/scheme"
kubeadmapiv1 "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1beta3"
"k8s.io/kubernetes/cmd/kubeadm/app/cmd/options"
"k8s.io/kubernetes/cmd/kubeadm/app/componentconfigs"
"k8s.io/kubernetes/cmd/kubeadm/app/constants"
kubeadmutil "k8s.io/kubernetes/cmd/kubeadm/app/util"
@ -54,7 +55,7 @@ func MarshalKubeadmConfigObject(obj runtime.Object) ([]byte, error) {
// validateSupportedVersion checks if the supplied GroupVersion is not on the lists of old unsupported or deprecated GVs.
// If it is, an error is returned.
func validateSupportedVersion(gv schema.GroupVersion, allowDeprecated bool) error {
func validateSupportedVersion(gv schema.GroupVersion, allowDeprecated, allowExperimental bool) error {
// The support matrix will look something like this now and in the future:
// v1.10 and earlier: v1alpha1
// v1.11: v1alpha1 read-only, writes only v1alpha2 config
@ -72,6 +73,13 @@ func validateSupportedVersion(gv schema.GroupVersion, allowDeprecated bool) erro
"kubeadm.k8s.io/v1beta2": "v1.22",
}
// v1.28: v1beta4 is released as experimental
experimentalAPIVersions := map[string]string{
// TODO: https://github.com/kubernetes/kubeadm/issues/2890
// remove this from experimental once v1beta4 is released
"kubeadm.k8s.io/v1beta4": "v1.28",
}
// Deprecated API versions are supported by us, but can only be used for migration.
deprecatedAPIVersions := map[string]struct{}{}
@ -85,6 +93,10 @@ func validateSupportedVersion(gv schema.GroupVersion, allowDeprecated bool) erro
klog.Warningf("your configuration file uses a deprecated API spec: %q. Please use 'kubeadm config migrate --old-config old.yaml --new-config new.yaml', which will write the new, similar spec using a newer API version.", gv)
}
if _, present := experimentalAPIVersions[gvString]; present && !allowExperimental {
return errors.Errorf("experimental API spec: %q is not allowed. You can use the --%s flag if the command supports it.", gv, options.AllowExperimentalAPI)
}
return nil
}
@ -205,7 +217,7 @@ func validateKnownGVKs(gvks []schema.GroupVersionKind) error {
// Skip legacy known GVs so that they don't return errors.
// This makes the function return errors only for GVs that where never known.
if err := validateSupportedVersion(gvk.GroupVersion(), true); err != nil {
if err := validateSupportedVersion(gvk.GroupVersion(), true, true); err != nil {
continue
}
@ -229,7 +241,7 @@ func validateKnownGVKs(gvks []schema.GroupVersionKind) error {
// MigrateOldConfig migrates an old configuration from a byte slice into a new one (returned again as a byte slice).
// Only kubeadm kinds are migrated.
func MigrateOldConfig(oldConfig []byte) ([]byte, error) {
func MigrateOldConfig(oldConfig []byte, allowExperimental bool) ([]byte, error) {
newConfig := [][]byte{}
gvkmap, err := kubeadmutil.SplitYAMLDocuments(oldConfig)
@ -248,7 +260,7 @@ func MigrateOldConfig(oldConfig []byte) ([]byte, error) {
// Migrate InitConfiguration and ClusterConfiguration if there are any in the config
if kubeadmutil.GroupVersionKindsHasInitConfiguration(gvks...) || kubeadmutil.GroupVersionKindsHasClusterConfiguration(gvks...) {
o, err := documentMapToInitConfiguration(gvkmap, true, true)
o, err := documentMapToInitConfiguration(gvkmap, true, allowExperimental, true)
if err != nil {
return []byte{}, err
}
@ -261,7 +273,7 @@ func MigrateOldConfig(oldConfig []byte) ([]byte, error) {
// Migrate JoinConfiguration if there is any
if kubeadmutil.GroupVersionKindsHasJoinConfiguration(gvks...) {
o, err := documentMapToJoinConfiguration(gvkmap, true, true)
o, err := documentMapToJoinConfiguration(gvkmap, true, allowExperimental, true)
if err != nil {
return []byte{}, err
}
@ -277,7 +289,7 @@ func MigrateOldConfig(oldConfig []byte) ([]byte, error) {
// ValidateConfig takes a byte slice containing a kubeadm configuration and performs conversion
// to internal types and validation.
func ValidateConfig(oldConfig []byte) error {
func ValidateConfig(oldConfig []byte, allowExperimental bool) error {
gvkmap, err := kubeadmutil.SplitYAMLDocuments(oldConfig)
if err != nil {
return err
@ -294,14 +306,14 @@ func ValidateConfig(oldConfig []byte) error {
// Validate InitConfiguration and ClusterConfiguration if there are any in the config
if kubeadmutil.GroupVersionKindsHasInitConfiguration(gvks...) || kubeadmutil.GroupVersionKindsHasClusterConfiguration(gvks...) {
if _, err := documentMapToInitConfiguration(gvkmap, true, true); err != nil {
if _, err := documentMapToInitConfiguration(gvkmap, true, allowExperimental, true); err != nil {
return err
}
}
// Validate JoinConfiguration if there is any
if kubeadmutil.GroupVersionKindsHasJoinConfiguration(gvks...) {
if _, err := documentMapToJoinConfiguration(gvkmap, true, true); err != nil {
if _, err := documentMapToJoinConfiguration(gvkmap, true, allowExperimental, true); err != nil {
return err
}
}

View File

@ -34,9 +34,10 @@ const KubeadmGroupName = "kubeadm.k8s.io"
func TestValidateSupportedVersion(t *testing.T) {
tests := []struct {
gv schema.GroupVersion
allowDeprecated bool
expectedErr bool
gv schema.GroupVersion
allowDeprecated bool
allowExperimental bool
expectedErr bool
}{
{
gv: schema.GroupVersion{
@ -85,11 +86,25 @@ func TestValidateSupportedVersion(t *testing.T) {
Version: "v1",
},
},
{
gv: schema.GroupVersion{
Group: KubeadmGroupName,
Version: "v1beta4",
},
allowExperimental: true,
},
{
gv: schema.GroupVersion{
Group: KubeadmGroupName,
Version: "v1beta4",
},
expectedErr: true,
},
}
for _, rt := range tests {
t.Run(fmt.Sprintf("%s/allowDeprecated:%t", rt.gv, rt.allowDeprecated), func(t *testing.T) {
err := validateSupportedVersion(rt.gv, rt.allowDeprecated)
err := validateSupportedVersion(rt.gv, rt.allowDeprecated, rt.allowExperimental)
if rt.expectedErr && err == nil {
t.Error("unexpected success")
} else if !rt.expectedErr && err != nil {

View File

@ -287,17 +287,17 @@ func BytesToInitConfiguration(b []byte) (*kubeadmapi.InitConfiguration, error) {
return nil, err
}
return documentMapToInitConfiguration(gvkmap, false, false)
return documentMapToInitConfiguration(gvkmap, false, false, false)
}
// documentMapToInitConfiguration converts a map of GVKs and YAML documents to defaulted and validated configuration object.
func documentMapToInitConfiguration(gvkmap kubeadmapi.DocumentMap, allowDeprecated, strictErrors bool) (*kubeadmapi.InitConfiguration, error) {
func documentMapToInitConfiguration(gvkmap kubeadmapi.DocumentMap, allowDeprecated, allowExperimental, strictErrors bool) (*kubeadmapi.InitConfiguration, error) {
var initcfg *kubeadmapi.InitConfiguration
var clustercfg *kubeadmapi.ClusterConfiguration
for gvk, fileContent := range gvkmap {
// first, check if this GVK is supported and possibly not deprecated
if err := validateSupportedVersion(gvk.GroupVersion(), allowDeprecated); err != nil {
if err := validateSupportedVersion(gvk.GroupVersion(), allowDeprecated, allowExperimental); err != nil {
return nil, err
}

View File

@ -85,12 +85,12 @@ func LoadJoinConfigurationFromFile(cfgPath string) (*kubeadmapi.JoinConfiguratio
return nil, err
}
return documentMapToJoinConfiguration(gvkmap, false, false)
return documentMapToJoinConfiguration(gvkmap, false, false, false)
}
// documentMapToJoinConfiguration takes a map between GVKs and YAML documents (as returned by SplitYAMLDocuments),
// finds a JoinConfiguration, decodes it, dynamically defaults it and then validates it prior to return.
func documentMapToJoinConfiguration(gvkmap kubeadmapi.DocumentMap, allowDeprecated, strictErrors bool) (*kubeadmapi.JoinConfiguration, error) {
func documentMapToJoinConfiguration(gvkmap kubeadmapi.DocumentMap, allowDeprecated, allowExperimental, strictErrors bool) (*kubeadmapi.JoinConfiguration, error) {
joinBytes := []byte{}
for gvk, bytes := range gvkmap {
// not interested in anything other than JoinConfiguration
@ -99,7 +99,7 @@ func documentMapToJoinConfiguration(gvkmap kubeadmapi.DocumentMap, allowDeprecat
}
// check if this version is supported and possibly not deprecated
if err := validateSupportedVersion(gvk.GroupVersion(), allowDeprecated); err != nil {
if err := validateSupportedVersion(gvk.GroupVersion(), allowDeprecated, allowExperimental); err != nil {
return nil, err
}