
This reverts commitf4afdecef8
, reversing changes made toe633a1604f
. This also fixes a bug where Kubemark was still using the core api scheme to manipulate the Kubelet's types, which was the cause of the initial revert.
238 lines
7.8 KiB
Go
238 lines
7.8 KiB
Go
/*
|
|
Copyright 2017 The Kubernetes Authors.
|
|
|
|
Licensed under the Apache License, Version 2.0 (the "License");
|
|
you may not use this file except in compliance with the License.
|
|
You may obtain a copy of the License at
|
|
|
|
http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
Unless required by applicable law or agreed to in writing, software
|
|
distributed under the License is distributed on an "AS IS" BASIS,
|
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
See the License for the specific language governing permissions and
|
|
limitations under the License.
|
|
*/
|
|
|
|
package checkpoint
|
|
|
|
import (
|
|
"fmt"
|
|
"testing"
|
|
|
|
"github.com/davecgh/go-spew/spew"
|
|
|
|
apiv1 "k8s.io/api/core/v1"
|
|
apiequality "k8s.io/apimachinery/pkg/api/equality"
|
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
|
"k8s.io/apimachinery/pkg/types"
|
|
"k8s.io/kubernetes/pkg/kubelet/apis/kubeletconfig"
|
|
kubeletscheme "k8s.io/kubernetes/pkg/kubelet/apis/kubeletconfig/scheme"
|
|
kubeletconfigv1alpha1 "k8s.io/kubernetes/pkg/kubelet/apis/kubeletconfig/v1alpha1"
|
|
utiltest "k8s.io/kubernetes/pkg/kubelet/kubeletconfig/util/test"
|
|
)
|
|
|
|
func TestNewConfigMapCheckpoint(t *testing.T) {
|
|
cases := []struct {
|
|
desc string
|
|
cm *apiv1.ConfigMap
|
|
err string
|
|
}{
|
|
{"nil v1/ConfigMap", nil, "must be non-nil"},
|
|
{"empty v1/ConfigMap", &apiv1.ConfigMap{}, "must have a UID"},
|
|
{"populated v1/ConfigMap",
|
|
&apiv1.ConfigMap{
|
|
ObjectMeta: metav1.ObjectMeta{
|
|
Name: "name",
|
|
UID: types.UID("uid"),
|
|
},
|
|
Data: map[string]string{
|
|
"key1": "value1",
|
|
"key2": "value2",
|
|
},
|
|
}, ""},
|
|
}
|
|
|
|
for _, c := range cases {
|
|
cpt, err := NewConfigMapCheckpoint(c.cm)
|
|
if utiltest.SkipRest(t, c.desc, err, c.err) {
|
|
continue
|
|
}
|
|
// underlying object should match the object passed in
|
|
if !apiequality.Semantic.DeepEqual(cpt.object(), c.cm) {
|
|
t.Errorf("case %q, expect Checkpoint %s but got %s", c.desc, spew.Sdump(c.cm), spew.Sdump(cpt))
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestConfigMapCheckpointUID(t *testing.T) {
|
|
_, kubeletCodecs, err := kubeletscheme.NewSchemeAndCodecs()
|
|
if err != nil {
|
|
t.Fatalf("unexpected error: %v", err)
|
|
}
|
|
|
|
cases := []string{"", "uid", "376dfb73-56db-11e7-a01e-42010a800002"}
|
|
for _, uidIn := range cases {
|
|
cpt := &configMapCheckpoint{
|
|
kubeletCodecs,
|
|
&apiv1.ConfigMap{
|
|
ObjectMeta: metav1.ObjectMeta{UID: types.UID(uidIn)},
|
|
},
|
|
}
|
|
// UID method should return the correct value of the UID
|
|
uidOut := cpt.UID()
|
|
if uidIn != uidOut {
|
|
t.Errorf("expect UID() to return %q, but got %q", uidIn, uidOut)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestConfigMapCheckpointParse(t *testing.T) {
|
|
kubeletScheme, kubeletCodecs, err := kubeletscheme.NewSchemeAndCodecs()
|
|
if err != nil {
|
|
t.Fatalf("unexpected error: %v", err)
|
|
}
|
|
|
|
// get the built-in default configuration
|
|
external := &kubeletconfigv1alpha1.KubeletConfiguration{}
|
|
kubeletScheme.Default(external)
|
|
defaultConfig := &kubeletconfig.KubeletConfiguration{}
|
|
err = kubeletScheme.Convert(external, defaultConfig, nil)
|
|
if err != nil {
|
|
t.Fatalf("unexpected error: %v", err)
|
|
}
|
|
|
|
cases := []struct {
|
|
desc string
|
|
cm *apiv1.ConfigMap
|
|
expect *kubeletconfig.KubeletConfiguration
|
|
err string
|
|
}{
|
|
{"empty data", &apiv1.ConfigMap{}, nil, "config was empty"},
|
|
// missing kubelet key
|
|
{"missing kubelet key", &apiv1.ConfigMap{Data: map[string]string{
|
|
"bogus": "stuff"}}, nil, fmt.Sprintf("key %q not found", configMapConfigKey)},
|
|
// invalid format
|
|
{"invalid yaml", &apiv1.ConfigMap{Data: map[string]string{
|
|
"kubelet": "*"}}, nil, "failed to decode"},
|
|
{"invalid json", &apiv1.ConfigMap{Data: map[string]string{
|
|
"kubelet": "{*"}}, nil, "failed to decode"},
|
|
// invalid object
|
|
{"missing kind", &apiv1.ConfigMap{Data: map[string]string{
|
|
"kubelet": `{"apiVersion":"kubeletconfig/v1alpha1"}`}}, nil, "failed to decode"},
|
|
{"missing version", &apiv1.ConfigMap{Data: map[string]string{
|
|
"kubelet": `{"kind":"KubeletConfiguration"}`}}, nil, "failed to decode"},
|
|
{"unregistered kind", &apiv1.ConfigMap{Data: map[string]string{
|
|
"kubelet": `{"kind":"BogusKind","apiVersion":"kubeletconfig/v1alpha1"}`}}, nil, "failed to decode"},
|
|
{"unregistered version", &apiv1.ConfigMap{Data: map[string]string{
|
|
"kubelet": `{"kind":"KubeletConfiguration","apiVersion":"bogusversion"}`}}, nil, "failed to decode"},
|
|
// empty object with correct kind and version should result in the defaults for that kind and version
|
|
{"default from yaml", &apiv1.ConfigMap{Data: map[string]string{
|
|
"kubelet": `kind: KubeletConfiguration
|
|
apiVersion: kubeletconfig/v1alpha1`}}, defaultConfig, ""},
|
|
{"default from json", &apiv1.ConfigMap{Data: map[string]string{
|
|
"kubelet": `{"kind":"KubeletConfiguration","apiVersion":"kubeletconfig/v1alpha1"}`}}, defaultConfig, ""},
|
|
}
|
|
for _, c := range cases {
|
|
cpt := &configMapCheckpoint{kubeletCodecs, c.cm}
|
|
kc, err := cpt.Parse()
|
|
if utiltest.SkipRest(t, c.desc, err, c.err) {
|
|
continue
|
|
}
|
|
// we expect the parsed configuration to match what we described in the ConfigMap
|
|
if !apiequality.Semantic.DeepEqual(c.expect, kc) {
|
|
t.Errorf("case %q, expect config %s but got %s", c.desc, spew.Sdump(c.expect), spew.Sdump(kc))
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestConfigMapCheckpointEncode(t *testing.T) {
|
|
_, kubeletCodecs, err := kubeletscheme.NewSchemeAndCodecs()
|
|
if err != nil {
|
|
t.Fatalf("unexpected error: %v", err)
|
|
}
|
|
|
|
// only one case, based on output from the existing encoder, and since
|
|
// this is hard to test (key order isn't guaranteed), we should probably
|
|
// just stick to this test case and mostly rely on the round-trip test.
|
|
cases := []struct {
|
|
desc string
|
|
cpt *configMapCheckpoint
|
|
expect string
|
|
}{
|
|
// we expect Checkpoints to be encoded as a json representation of the underlying API object
|
|
{"one-key",
|
|
&configMapCheckpoint{kubeletCodecs, &apiv1.ConfigMap{
|
|
ObjectMeta: metav1.ObjectMeta{Name: "one-key"},
|
|
Data: map[string]string{"one": ""}}},
|
|
`{"kind":"ConfigMap","apiVersion":"v1","metadata":{"name":"one-key","creationTimestamp":null},"data":{"one":""}}
|
|
`},
|
|
}
|
|
|
|
for _, c := range cases {
|
|
data, err := c.cpt.Encode()
|
|
// we don't expect any errors from encoding
|
|
if utiltest.SkipRest(t, c.desc, err, "") {
|
|
continue
|
|
}
|
|
if string(data) != c.expect {
|
|
t.Errorf("case %q, expect encoding %q but got %q", c.desc, c.expect, string(data))
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestConfigMapCheckpointRoundTrip(t *testing.T) {
|
|
_, kubeletCodecs, err := kubeletscheme.NewSchemeAndCodecs()
|
|
if err != nil {
|
|
t.Fatalf("unexpected error: %v", err)
|
|
}
|
|
|
|
cases := []struct {
|
|
desc string
|
|
cpt *configMapCheckpoint
|
|
decodeErr string
|
|
}{
|
|
// empty data
|
|
{"empty data",
|
|
&configMapCheckpoint{kubeletCodecs, &apiv1.ConfigMap{
|
|
ObjectMeta: metav1.ObjectMeta{
|
|
Name: "empty-data-sha256-e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
|
|
UID: "uid",
|
|
},
|
|
Data: map[string]string{}}},
|
|
""},
|
|
// two keys
|
|
{"two keys",
|
|
&configMapCheckpoint{kubeletCodecs, &apiv1.ConfigMap{
|
|
ObjectMeta: metav1.ObjectMeta{
|
|
Name: "two-keys-sha256-2bff03d6249c8a9dc9a1436d087c124741361ccfac6615b81b67afcff5c42431",
|
|
UID: "uid",
|
|
},
|
|
Data: map[string]string{"one": "", "two": "2"}}},
|
|
""},
|
|
// missing uid
|
|
{"missing uid",
|
|
&configMapCheckpoint{kubeletCodecs, &apiv1.ConfigMap{
|
|
ObjectMeta: metav1.ObjectMeta{
|
|
Name: "two-keys-sha256-2bff03d6249c8a9dc9a1436d087c124741361ccfac6615b81b67afcff5c42431",
|
|
UID: "",
|
|
},
|
|
Data: map[string]string{"one": "", "two": "2"}}},
|
|
"must have a UID"},
|
|
}
|
|
for _, c := range cases {
|
|
// we don't expect any errors from encoding
|
|
data, err := c.cpt.Encode()
|
|
if utiltest.SkipRest(t, c.desc, err, "") {
|
|
continue
|
|
}
|
|
after, err := DecodeCheckpoint(data)
|
|
if utiltest.SkipRest(t, c.desc, err, c.decodeErr) {
|
|
continue
|
|
}
|
|
if !apiequality.Semantic.DeepEqual(c.cpt.object(), after.object()) {
|
|
t.Errorf("case %q, expect round-trip result %s but got %s", c.desc, spew.Sdump(c.cpt), spew.Sdump(after))
|
|
}
|
|
}
|
|
}
|