Merge pull request #74025 from rosti/deprecated-configs

kubeadm: Don't load deprecated configs
pull/564/head
Kubernetes Prow Robot 2019-02-19 04:55:32 -08:00 committed by GitHub
commit 8d69dc630b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 84 additions and 67 deletions

View File

@ -1,3 +1,3 @@
apiVersion: kubeadm.k8s.io/v1alpha3
apiVersion: kubeadm.k8s.io/v1beta1
kind: ClusterConfiguration
kubernetesVersion: 1.12.0
kubernetesVersion: 1.13.0

View File

@ -48,20 +48,35 @@ func MarshalKubeadmConfigObject(obj runtime.Object) ([]byte, error) {
}
}
// ValidateSupportedVersion checks if a supplied GroupVersion is not on the list of unsupported GVs. If it is, an error is returned.
func ValidateSupportedVersion(gv schema.GroupVersion) 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 {
// 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
// v1.12: v1alpha2 read-only, writes only v1alpha3 config. Warns if the user tries to use v1alpha1
// v1.13: v1alpha3 read-only, writes only v1beta1 config. Warns if the user tries to use v1alpha1 or v1alpha2
// v1.12: v1alpha2 read-only, writes only v1alpha3 config. Errors if the user tries to use v1alpha1
// v1.13: v1alpha3 read-only, writes only v1beta1 config. Errors if the user tries to use v1alpha1 or v1alpha2
// v1.14: v1alpha3 convert only, writes only v1beta1 config. Errors if the user tries to use v1alpha1 or v1alpha2
oldKnownAPIVersions := map[string]string{
"kubeadm.k8s.io/v1alpha1": "v1.11",
"kubeadm.k8s.io/v1alpha2": "v1.12",
}
if useKubeadmVersion := oldKnownAPIVersions[gv.String()]; useKubeadmVersion != "" {
// Deprecated API versions are supported by us, but can only be used for migration.
deprecatedAPIVersions := map[string]struct{}{
"kubeadm.k8s.io/v1alpha3": {}, // Can be migrated with kubeadm 1.13+
}
gvString := gv.String()
if useKubeadmVersion := oldKnownAPIVersions[gvString]; useKubeadmVersion != "" {
return errors.Errorf("your configuration file uses an old API spec: %q. Please use kubeadm %s instead and run 'kubeadm config migrate --old-config old.yaml --new-config new.yaml', which will write the new, similar spec using a newer API version.", gv.String(), useKubeadmVersion)
}
if _, present := deprecatedAPIVersions[gvString]; present && !allowDeprecated {
return errors.Errorf("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.String())
}
return nil
}
@ -154,7 +169,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)
o, err := documentMapToInitConfiguration(gvkmap, true)
if err != nil {
return []byte{}, err
}
@ -167,7 +182,7 @@ func MigrateOldConfig(oldConfig []byte) ([]byte, error) {
// Migrate JoinConfiguration if there is any
if kubeadmutil.GroupVersionKindsHasJoinConfiguration(gvks...) {
o, err := documentMapToJoinConfiguration(gvkmap)
o, err := documentMapToJoinConfiguration(gvkmap, true)
if err != nil {
return []byte{}, err
}

View File

@ -17,6 +17,7 @@ limitations under the License.
package config
import (
"fmt"
"testing"
"github.com/lithammer/dedent"
@ -27,12 +28,13 @@ import (
kubeadmutil "k8s.io/kubernetes/cmd/kubeadm/app/util"
)
func TestValidateSupportedVersion(t *testing.T) {
const KubeadmGroupName = "kubeadm.k8s.io"
const KubeadmGroupName = "kubeadm.k8s.io"
func TestValidateSupportedVersion(t *testing.T) {
tests := []struct {
gv schema.GroupVersion
expectedErr bool
gv schema.GroupVersion
allowDeprecated bool
expectedErr bool
}{
{
gv: schema.GroupVersion{
@ -53,6 +55,14 @@ func TestValidateSupportedVersion(t *testing.T) {
Group: KubeadmGroupName,
Version: "v1alpha3",
},
expectedErr: true,
},
{
gv: schema.GroupVersion{
Group: KubeadmGroupName,
Version: "v1alpha3",
},
allowDeprecated: true,
},
{
gv: schema.GroupVersion{
@ -69,8 +79,8 @@ func TestValidateSupportedVersion(t *testing.T) {
}
for _, rt := range tests {
t.Run(rt.gv.String(), func(t *testing.T) {
err := ValidateSupportedVersion(rt.gv)
t.Run(fmt.Sprintf("%s/allowDeprecated:%t", rt.gv, rt.allowDeprecated), func(t *testing.T) {
err := validateSupportedVersion(rt.gv, rt.allowDeprecated)
if rt.expectedErr && err == nil {
t.Error("unexpected success")
} else if !rt.expectedErr && err != nil {

View File

@ -190,11 +190,7 @@ func LoadInitConfigurationFromFile(cfgPath string) (*kubeadmapi.InitConfiguratio
return nil, errors.Wrapf(err, "unable to read config from %q ", cfgPath)
}
internalcfg, err := BytesToInitConfiguration(b)
if err != nil {
return nil, err
}
return internalcfg, nil
return BytesToInitConfiguration(b)
}
// LoadOrDefaultInitConfiguration takes a path to a config file and a versioned configuration that can serve as the default config
@ -222,18 +218,18 @@ func BytesToInitConfiguration(b []byte) (*kubeadmapi.InitConfiguration, error) {
return nil, err
}
return documentMapToInitConfiguration(gvkmap)
return documentMapToInitConfiguration(gvkmap, false)
}
// documentMapToInitConfiguration converts a map of GVKs and YAML documents to defaulted and validated configuration object.
func documentMapToInitConfiguration(gvkmap map[schema.GroupVersionKind][]byte) (*kubeadmapi.InitConfiguration, error) {
func documentMapToInitConfiguration(gvkmap map[schema.GroupVersionKind][]byte, allowDeprecated bool) (*kubeadmapi.InitConfiguration, error) {
var initcfg *kubeadmapi.InitConfiguration
var clustercfg *kubeadmapi.ClusterConfiguration
decodedComponentConfigObjects := map[componentconfigs.RegistrationKind]runtime.Object{}
for gvk, fileContent := range gvkmap {
// first, check if this GVK is supported one
if err := ValidateSupportedVersion(gvk.GroupVersion()); err != nil {
// first, check if this GVK is supported and possibly not deprecated
if err := validateSupportedVersion(gvk.GroupVersion(), allowDeprecated); err != nil {
return nil, err
}

View File

@ -71,6 +71,7 @@ func TestLoadInitConfigurationFromFile(t *testing.T) {
var tests = []struct {
name string
fileContents []byte
expectErr bool
}{
{
name: "v1beta1.partial1",
@ -92,10 +93,12 @@ func TestLoadInitConfigurationFromFile(t *testing.T) {
{
name: "v1alpha3.partial1",
fileContents: cfgFiles["InitConfiguration_v1alpha3"],
expectErr: true,
},
{
name: "v1alpha3.partial2",
fileContents: cfgFiles["ClusterConfiguration_v1alpha3"],
expectErr: true,
},
{
name: "v1alpha3.full",
@ -105,6 +108,7 @@ func TestLoadInitConfigurationFromFile(t *testing.T) {
cfgFiles["Kube-proxy_componentconfig"],
cfgFiles["Kubelet_componentconfig"],
}, []byte(constants.YAMLDocumentSeparator)),
expectErr: true,
},
}
@ -118,13 +122,19 @@ func TestLoadInitConfigurationFromFile(t *testing.T) {
}
obj, err := LoadInitConfigurationFromFile(cfgPath)
if err != nil {
t.Errorf("Error reading file: %v", err)
return
}
if rt.expectErr {
if err == nil {
t.Error("Unexpected success")
}
} else {
if err != nil {
t.Errorf("Error reading file: %v", err)
return
}
if obj == nil {
t.Errorf("Unexpected nil return value")
if obj == nil {
t.Errorf("Unexpected nil return value")
}
}
})
}
@ -150,10 +160,9 @@ func TestInitConfigurationMarshallingFromFile(t *testing.T) {
// These tests are reading one file, loading it using LoadInitConfigurationFromFile that all of kubeadm is using for unmarshal of our API types,
// and then marshals the internal object to the expected groupVersion
{ // v1alpha3 -> internal
name: "v1alpha3ToInternal",
in: masterV1alpha3YAMLAbstracted,
out: masterInternalYAMLAbstracted,
groupVersion: kubeadm.SchemeGroupVersion,
name: "v1alpha3IsDeprecated",
in: masterV1alpha3YAMLAbstracted,
expectedErr: true,
},
{ // v1beta1 -> internal
name: "v1beta1ToInternal",
@ -161,12 +170,6 @@ func TestInitConfigurationMarshallingFromFile(t *testing.T) {
out: masterInternalYAMLAbstracted,
groupVersion: kubeadm.SchemeGroupVersion,
},
{ // v1alpha3 -> internal -> v1beta1
name: "v1alpha3Tov1beta1",
in: masterV1alpha3YAMLAbstracted,
out: masterV1beta1YAMLAbstracted,
groupVersion: kubeadmapiv1beta1.SchemeGroupVersion,
},
{ // v1beta1 -> internal -> v1beta1
name: "v1beta1Tov1beta1",
in: masterV1beta1YAMLAbstracted,
@ -181,7 +184,7 @@ func TestInitConfigurationMarshallingFromFile(t *testing.T) {
out: masterDefaultedYAMLAbstracted,
groupVersion: kubeadmapiv1beta1.SchemeGroupVersion,
},
{ // v1alpha3 -> validation should fail
{ // v1beta1 -> validation should fail
name: "invalidYAMLShouldFail",
in: masterInvalidYAML,
expectedErr: true,

View File

@ -84,12 +84,12 @@ func LoadJoinConfigurationFromFile(cfgPath string) (*kubeadmapi.JoinConfiguratio
return nil, err
}
return documentMapToJoinConfiguration(gvkmap)
return documentMapToJoinConfiguration(gvkmap, 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 map[schema.GroupVersionKind][]byte) (*kubeadmapi.JoinConfiguration, error) {
func documentMapToJoinConfiguration(gvkmap map[schema.GroupVersionKind][]byte, allowDeprecated bool) (*kubeadmapi.JoinConfiguration, error) {
joinBytes := []byte{}
for gvk, bytes := range gvkmap {
// not interested in anything other than JoinConfiguration
@ -97,8 +97,8 @@ func documentMapToJoinConfiguration(gvkmap map[schema.GroupVersionKind][]byte) (
continue
}
// check if this version is supported one
if err := ValidateSupportedVersion(gvk.GroupVersion()); err != nil {
// check if this version is supported and possibly not deprecated
if err := validateSupportedVersion(gvk.GroupVersion(), allowDeprecated); err != nil {
return nil, err
}

View File

@ -46,10 +46,9 @@ func TestLoadJoinConfigurationFromFile(t *testing.T) {
// These tests are reading one file, loading it using LoadJoinConfigurationFromFile that all of kubeadm is using for unmarshal of our API types,
// and then marshals the internal object to the expected groupVersion
{ // v1alpha3 -> internal
name: "v1alpha3ToInternal",
in: nodeV1alpha3YAML,
out: nodeInternalYAML,
groupVersion: kubeadm.SchemeGroupVersion,
name: "v1alpha3IsDeprecated",
in: nodeV1alpha3YAML,
expectedErr: true,
},
{ // v1beta1 -> internal
name: "v1beta1ToInternal",
@ -57,12 +56,6 @@ func TestLoadJoinConfigurationFromFile(t *testing.T) {
out: nodeInternalYAML,
groupVersion: kubeadm.SchemeGroupVersion,
},
{ // v1alpha3 -> internal -> v1beta1
name: "v1alpha3Tov1beta1",
in: nodeV1alpha3YAML,
out: nodeV1beta1YAML,
groupVersion: kubeadmapiv1beta1.SchemeGroupVersion,
},
{ // v1beta1 -> internal -> v1beta1
name: "v1beta1Tov1beta1",
in: nodeV1beta1YAML,
@ -77,7 +70,7 @@ func TestLoadJoinConfigurationFromFile(t *testing.T) {
out: nodeDefaultedYAML,
groupVersion: kubeadmapiv1beta1.SchemeGroupVersion,
},
{ // v1alpha3 -> validation should fail
{ // v1beta1 -> validation should fail
name: "invalidYAMLShouldFail",
in: nodeInvalidYAML,
expectedErr: true,

View File

@ -1,11 +1,11 @@
apiVersion: kubeadm.k8s.io/v1alpha3
discoveryToken: abcdef.0123456789abcdef
discoveryTokenAPIServers:
- kube-apiserver:6443
discoveryTokenUnsafeSkipCAVerification: true
apiVersion: kubeadm.k8s.io/v1beta1
discovery:
bootstrapToken:
apiServerEndpoint: kube-apiserver:6443
token: abcdef.0123456789abcdef
unsafeSkipCAVerification: true
tlsBootstrapToken: abcdef.0123456789abcdef
kind: JoinConfiguration
nodeRegistration:
criSocket: /var/run/dockershim.sock
name: thegopher
tlsBootstrapToken: abcdef.0123456789abcdef
token: abcdef.0123456789abcdef

View File

@ -146,19 +146,19 @@ func TestCmdInitConfig(t *testing.T) {
expected: false,
},
{
name: "can't load v1alpha1 config",
name: "can't load old v1alpha1 config",
args: "--config=testdata/init/v1alpha1.yaml",
expected: false,
},
{
name: "can't load v1alpha2 config",
name: "can't load old v1alpha2 config",
args: "--config=testdata/init/v1alpha2.yaml",
expected: false,
},
{
name: "can load v1alpha3 config",
name: "can't load deprecated v1alpha3 config",
args: "--config=testdata/init/v1alpha3.yaml",
expected: true,
expected: false,
},
{
name: "can load v1beta1 config",