mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-23 19:56:01 +00:00
Add unit tests for the new Bootstrap Token objects and functions
This commit is contained in:
parent
c473039580
commit
17adbf9b08
473
cmd/kubeadm/app/apis/kubeadm/bootstraptokenhelpers_test.go
Normal file
473
cmd/kubeadm/app/apis/kubeadm/bootstraptokenhelpers_test.go
Normal file
@ -0,0 +1,473 @@
|
||||
/*
|
||||
Copyright 2018 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 kubeadm
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"reflect"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"k8s.io/api/core/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
)
|
||||
|
||||
// This timestamp is used as the reference value when computing expiration dates based on TTLs in these unit tests
|
||||
var refTime = time.Date(1970, time.January, 1, 1, 1, 1, 0, time.UTC)
|
||||
|
||||
func TestToSecret(t *testing.T) {
|
||||
|
||||
var tests = []struct {
|
||||
bt *BootstrapToken
|
||||
secret *v1.Secret
|
||||
}{
|
||||
{
|
||||
&BootstrapToken{ // all together
|
||||
Token: &BootstrapTokenString{ID: "abcdef", Secret: "abcdef0123456789"},
|
||||
Description: "foo",
|
||||
Expires: &metav1.Time{
|
||||
Time: refTime,
|
||||
},
|
||||
Usages: []string{"signing", "authentication"},
|
||||
Groups: []string{"system:bootstrappers", "system:bootstrappers:foo"},
|
||||
},
|
||||
&v1.Secret{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "bootstrap-token-abcdef",
|
||||
Namespace: "kube-system",
|
||||
},
|
||||
Type: v1.SecretType("bootstrap.kubernetes.io/token"),
|
||||
Data: map[string][]byte{
|
||||
"token-id": []byte("abcdef"),
|
||||
"token-secret": []byte("abcdef0123456789"),
|
||||
"description": []byte("foo"),
|
||||
"expiration": []byte(refTime.Format(time.RFC3339)),
|
||||
"usage-bootstrap-signing": []byte("true"),
|
||||
"usage-bootstrap-authentication": []byte("true"),
|
||||
"auth-extra-groups": []byte("system:bootstrappers,system:bootstrappers:foo"),
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, rt := range tests {
|
||||
actual := rt.bt.ToSecret()
|
||||
if !reflect.DeepEqual(actual, rt.secret) {
|
||||
t.Errorf(
|
||||
"failed BootstrapToken.ToSecret():\n\texpected: %v\n\t actual: %v",
|
||||
rt.secret,
|
||||
actual,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestBootstrapTokenToSecretRoundtrip(t *testing.T) {
|
||||
var tests = []struct {
|
||||
bt *BootstrapToken
|
||||
}{
|
||||
{
|
||||
&BootstrapToken{
|
||||
Token: &BootstrapTokenString{ID: "abcdef", Secret: "abcdef0123456789"},
|
||||
Description: "foo",
|
||||
Expires: &metav1.Time{
|
||||
Time: refTime,
|
||||
},
|
||||
Usages: []string{"authentication", "signing"},
|
||||
Groups: []string{"system:bootstrappers", "system:bootstrappers:foo"},
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, rt := range tests {
|
||||
actual, err := BootstrapTokenFromSecret(rt.bt.ToSecret())
|
||||
if err != nil {
|
||||
t.Errorf("failed BootstrapToken to Secret roundtrip with error: %v", err)
|
||||
}
|
||||
if !reflect.DeepEqual(actual, rt.bt) {
|
||||
t.Errorf(
|
||||
"failed BootstrapToken to Secret roundtrip:\n\texpected: %v\n\t actual: %v",
|
||||
rt.bt,
|
||||
actual,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestEncodeTokenSecretData(t *testing.T) {
|
||||
var tests = []struct {
|
||||
bt *BootstrapToken
|
||||
data map[string][]byte
|
||||
}{
|
||||
{
|
||||
&BootstrapToken{ // the minimum amount of information needed to be specified
|
||||
Token: &BootstrapTokenString{ID: "abcdef", Secret: "abcdef0123456789"},
|
||||
},
|
||||
map[string][]byte{
|
||||
"token-id": []byte("abcdef"),
|
||||
"token-secret": []byte("abcdef0123456789"),
|
||||
},
|
||||
},
|
||||
{
|
||||
&BootstrapToken{ // adds description
|
||||
Token: &BootstrapTokenString{ID: "abcdef", Secret: "abcdef0123456789"},
|
||||
Description: "foo",
|
||||
},
|
||||
map[string][]byte{
|
||||
"token-id": []byte("abcdef"),
|
||||
"token-secret": []byte("abcdef0123456789"),
|
||||
"description": []byte("foo"),
|
||||
},
|
||||
},
|
||||
{
|
||||
&BootstrapToken{ // adds ttl
|
||||
Token: &BootstrapTokenString{ID: "abcdef", Secret: "abcdef0123456789"},
|
||||
TTL: &metav1.Duration{
|
||||
Duration: mustParseDuration("2h", t),
|
||||
},
|
||||
},
|
||||
map[string][]byte{
|
||||
"token-id": []byte("abcdef"),
|
||||
"token-secret": []byte("abcdef0123456789"),
|
||||
"expiration": []byte(refTime.Add(mustParseDuration("2h", t)).Format(time.RFC3339)),
|
||||
},
|
||||
},
|
||||
{
|
||||
&BootstrapToken{ // adds expiration
|
||||
Token: &BootstrapTokenString{ID: "abcdef", Secret: "abcdef0123456789"},
|
||||
Expires: &metav1.Time{
|
||||
Time: refTime,
|
||||
},
|
||||
},
|
||||
map[string][]byte{
|
||||
"token-id": []byte("abcdef"),
|
||||
"token-secret": []byte("abcdef0123456789"),
|
||||
"expiration": []byte(refTime.Format(time.RFC3339)),
|
||||
},
|
||||
},
|
||||
{
|
||||
&BootstrapToken{ // adds ttl and expiration, should favor expiration
|
||||
Token: &BootstrapTokenString{ID: "abcdef", Secret: "abcdef0123456789"},
|
||||
TTL: &metav1.Duration{
|
||||
Duration: mustParseDuration("2h", t),
|
||||
},
|
||||
Expires: &metav1.Time{
|
||||
Time: refTime,
|
||||
},
|
||||
},
|
||||
map[string][]byte{
|
||||
"token-id": []byte("abcdef"),
|
||||
"token-secret": []byte("abcdef0123456789"),
|
||||
"expiration": []byte(refTime.Format(time.RFC3339)),
|
||||
},
|
||||
},
|
||||
{
|
||||
&BootstrapToken{ // adds usages
|
||||
Token: &BootstrapTokenString{ID: "abcdef", Secret: "abcdef0123456789"},
|
||||
Usages: []string{"authentication", "signing"},
|
||||
},
|
||||
map[string][]byte{
|
||||
"token-id": []byte("abcdef"),
|
||||
"token-secret": []byte("abcdef0123456789"),
|
||||
"usage-bootstrap-signing": []byte("true"),
|
||||
"usage-bootstrap-authentication": []byte("true"),
|
||||
},
|
||||
},
|
||||
{
|
||||
&BootstrapToken{ // adds groups
|
||||
Token: &BootstrapTokenString{ID: "abcdef", Secret: "abcdef0123456789"},
|
||||
Groups: []string{"system:bootstrappers", "system:bootstrappers:foo"},
|
||||
},
|
||||
map[string][]byte{
|
||||
"token-id": []byte("abcdef"),
|
||||
"token-secret": []byte("abcdef0123456789"),
|
||||
"auth-extra-groups": []byte("system:bootstrappers,system:bootstrappers:foo"),
|
||||
},
|
||||
},
|
||||
{
|
||||
&BootstrapToken{ // all together
|
||||
Token: &BootstrapTokenString{ID: "abcdef", Secret: "abcdef0123456789"},
|
||||
Description: "foo",
|
||||
TTL: &metav1.Duration{
|
||||
Duration: mustParseDuration("2h", t),
|
||||
},
|
||||
Expires: &metav1.Time{
|
||||
Time: refTime,
|
||||
},
|
||||
Usages: []string{"authentication", "signing"},
|
||||
Groups: []string{"system:bootstrappers", "system:bootstrappers:foo"},
|
||||
},
|
||||
map[string][]byte{
|
||||
"token-id": []byte("abcdef"),
|
||||
"token-secret": []byte("abcdef0123456789"),
|
||||
"description": []byte("foo"),
|
||||
"expiration": []byte(refTime.Format(time.RFC3339)),
|
||||
"usage-bootstrap-signing": []byte("true"),
|
||||
"usage-bootstrap-authentication": []byte("true"),
|
||||
"auth-extra-groups": []byte("system:bootstrappers,system:bootstrappers:foo"),
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, rt := range tests {
|
||||
actual := encodeTokenSecretData(rt.bt, refTime)
|
||||
if !reflect.DeepEqual(actual, rt.data) {
|
||||
t.Errorf(
|
||||
"failed encodeTokenSecretData:\n\texpected: %v\n\t actual: %v",
|
||||
rt.data,
|
||||
actual,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func mustParseDuration(durationStr string, t *testing.T) time.Duration {
|
||||
d, err := time.ParseDuration(durationStr)
|
||||
if err != nil {
|
||||
t.Fatalf("couldn't parse duration %q: %v", durationStr, err)
|
||||
}
|
||||
return d
|
||||
}
|
||||
|
||||
func TestBootstrapTokenFromSecret(t *testing.T) {
|
||||
var tests = []struct {
|
||||
name string
|
||||
data map[string][]byte
|
||||
bt *BootstrapToken
|
||||
expectedError bool
|
||||
}{
|
||||
{ // minimum information
|
||||
"bootstrap-token-abcdef",
|
||||
map[string][]byte{
|
||||
"token-id": []byte("abcdef"),
|
||||
"token-secret": []byte("abcdef0123456789"),
|
||||
},
|
||||
&BootstrapToken{
|
||||
Token: &BootstrapTokenString{ID: "abcdef", Secret: "abcdef0123456789"},
|
||||
},
|
||||
false,
|
||||
},
|
||||
{ // invalid token id
|
||||
"bootstrap-token-abcdef",
|
||||
map[string][]byte{
|
||||
"token-id": []byte("abcdeF"),
|
||||
"token-secret": []byte("abcdef0123456789"),
|
||||
},
|
||||
nil,
|
||||
true,
|
||||
},
|
||||
{ // invalid secret naming
|
||||
"foo",
|
||||
map[string][]byte{
|
||||
"token-id": []byte("abcdef"),
|
||||
"token-secret": []byte("abcdef0123456789"),
|
||||
},
|
||||
nil,
|
||||
true,
|
||||
},
|
||||
{ // invalid token secret
|
||||
"bootstrap-token-abcdef",
|
||||
map[string][]byte{
|
||||
"token-id": []byte("abcdef"),
|
||||
"token-secret": []byte("ABCDEF0123456789"),
|
||||
},
|
||||
nil,
|
||||
true,
|
||||
},
|
||||
{ // adds description
|
||||
"bootstrap-token-abcdef",
|
||||
map[string][]byte{
|
||||
"token-id": []byte("abcdef"),
|
||||
"token-secret": []byte("abcdef0123456789"),
|
||||
"description": []byte("foo"),
|
||||
},
|
||||
&BootstrapToken{
|
||||
Token: &BootstrapTokenString{ID: "abcdef", Secret: "abcdef0123456789"},
|
||||
Description: "foo",
|
||||
},
|
||||
false,
|
||||
},
|
||||
{ // adds expiration
|
||||
"bootstrap-token-abcdef",
|
||||
map[string][]byte{
|
||||
"token-id": []byte("abcdef"),
|
||||
"token-secret": []byte("abcdef0123456789"),
|
||||
"expiration": []byte(refTime.Format(time.RFC3339)),
|
||||
},
|
||||
&BootstrapToken{
|
||||
Token: &BootstrapTokenString{ID: "abcdef", Secret: "abcdef0123456789"},
|
||||
Expires: &metav1.Time{
|
||||
Time: refTime,
|
||||
},
|
||||
},
|
||||
false,
|
||||
},
|
||||
{ // invalid expiration
|
||||
"bootstrap-token-abcdef",
|
||||
map[string][]byte{
|
||||
"token-id": []byte("abcdef"),
|
||||
"token-secret": []byte("abcdef0123456789"),
|
||||
"expiration": []byte("invalid date"),
|
||||
},
|
||||
nil,
|
||||
true,
|
||||
},
|
||||
{ // adds usages
|
||||
"bootstrap-token-abcdef",
|
||||
map[string][]byte{
|
||||
"token-id": []byte("abcdef"),
|
||||
"token-secret": []byte("abcdef0123456789"),
|
||||
"usage-bootstrap-signing": []byte("true"),
|
||||
"usage-bootstrap-authentication": []byte("true"),
|
||||
},
|
||||
&BootstrapToken{
|
||||
Token: &BootstrapTokenString{ID: "abcdef", Secret: "abcdef0123456789"},
|
||||
Usages: []string{"authentication", "signing"},
|
||||
},
|
||||
false,
|
||||
},
|
||||
{ // should ignore usages that aren't set to true
|
||||
"bootstrap-token-abcdef",
|
||||
map[string][]byte{
|
||||
"token-id": []byte("abcdef"),
|
||||
"token-secret": []byte("abcdef0123456789"),
|
||||
"usage-bootstrap-signing": []byte("true"),
|
||||
"usage-bootstrap-authentication": []byte("true"),
|
||||
"usage-bootstrap-foo": []byte("false"),
|
||||
"usage-bootstrap-bar": []byte(""),
|
||||
},
|
||||
&BootstrapToken{
|
||||
Token: &BootstrapTokenString{ID: "abcdef", Secret: "abcdef0123456789"},
|
||||
Usages: []string{"authentication", "signing"},
|
||||
},
|
||||
false,
|
||||
},
|
||||
{ // adds groups
|
||||
"bootstrap-token-abcdef",
|
||||
map[string][]byte{
|
||||
"token-id": []byte("abcdef"),
|
||||
"token-secret": []byte("abcdef0123456789"),
|
||||
"auth-extra-groups": []byte("system:bootstrappers,system:bootstrappers:foo"),
|
||||
},
|
||||
&BootstrapToken{
|
||||
Token: &BootstrapTokenString{ID: "abcdef", Secret: "abcdef0123456789"},
|
||||
Groups: []string{"system:bootstrappers", "system:bootstrappers:foo"},
|
||||
},
|
||||
false,
|
||||
},
|
||||
{ // all fields set
|
||||
"bootstrap-token-abcdef",
|
||||
map[string][]byte{
|
||||
"token-id": []byte("abcdef"),
|
||||
"token-secret": []byte("abcdef0123456789"),
|
||||
"description": []byte("foo"),
|
||||
"expiration": []byte(refTime.Format(time.RFC3339)),
|
||||
"usage-bootstrap-signing": []byte("true"),
|
||||
"usage-bootstrap-authentication": []byte("true"),
|
||||
"auth-extra-groups": []byte("system:bootstrappers,system:bootstrappers:foo"),
|
||||
},
|
||||
&BootstrapToken{
|
||||
Token: &BootstrapTokenString{ID: "abcdef", Secret: "abcdef0123456789"},
|
||||
Description: "foo",
|
||||
Expires: &metav1.Time{
|
||||
Time: refTime,
|
||||
},
|
||||
Usages: []string{"authentication", "signing"},
|
||||
Groups: []string{"system:bootstrappers", "system:bootstrappers:foo"},
|
||||
},
|
||||
false,
|
||||
},
|
||||
}
|
||||
for _, rt := range tests {
|
||||
actual, err := BootstrapTokenFromSecret(&v1.Secret{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: rt.name,
|
||||
Namespace: "kube-system",
|
||||
},
|
||||
Type: v1.SecretType("bootstrap.kubernetes.io/token"),
|
||||
Data: rt.data,
|
||||
})
|
||||
if (err != nil) != rt.expectedError {
|
||||
t.Errorf(
|
||||
"failed BootstrapTokenFromSecret\n\texpected error: %t\n\t actual error: %v",
|
||||
rt.expectedError,
|
||||
err,
|
||||
)
|
||||
} else {
|
||||
if actual == nil && rt.bt == nil {
|
||||
// if both pointers are nil, it's okay, just continue
|
||||
continue
|
||||
}
|
||||
// If one of the pointers is defined but the other isn't, throw error. If both pointers are defined but unequal, throw error
|
||||
if (actual == nil && rt.bt != nil) || (actual != nil && rt.bt == nil) || !reflect.DeepEqual(*actual, *rt.bt) {
|
||||
t.Errorf(
|
||||
"failed BootstrapTokenFromSecret\n\texpected: %s\n\t actual: %s",
|
||||
jsonMarshal(rt.bt),
|
||||
jsonMarshal(actual),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func jsonMarshal(bt *BootstrapToken) string {
|
||||
b, _ := json.Marshal(*bt)
|
||||
return string(b)
|
||||
}
|
||||
|
||||
func TestGetSecretString(t *testing.T) {
|
||||
var tests = []struct {
|
||||
secret *v1.Secret
|
||||
key string
|
||||
expectedVal string
|
||||
}{
|
||||
{
|
||||
secret: &v1.Secret{
|
||||
ObjectMeta: metav1.ObjectMeta{Name: "foo"},
|
||||
Data: map[string][]byte{
|
||||
"foo": []byte("bar"),
|
||||
},
|
||||
},
|
||||
key: "foo",
|
||||
expectedVal: "bar",
|
||||
},
|
||||
{
|
||||
secret: &v1.Secret{
|
||||
ObjectMeta: metav1.ObjectMeta{Name: "foo"},
|
||||
Data: map[string][]byte{
|
||||
"foo": []byte("bar"),
|
||||
},
|
||||
},
|
||||
key: "baz",
|
||||
expectedVal: "",
|
||||
},
|
||||
{
|
||||
secret: &v1.Secret{
|
||||
ObjectMeta: metav1.ObjectMeta{Name: "foo"},
|
||||
},
|
||||
key: "foo",
|
||||
expectedVal: "",
|
||||
},
|
||||
}
|
||||
for _, rt := range tests {
|
||||
actual := getSecretString(rt.secret, rt.key)
|
||||
if actual != rt.expectedVal {
|
||||
t.Errorf(
|
||||
"failed getSecretString:\n\texpected: %s\n\t actual: %s",
|
||||
rt.expectedVal,
|
||||
actual,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
236
cmd/kubeadm/app/apis/kubeadm/bootstraptokenstring_test.go
Normal file
236
cmd/kubeadm/app/apis/kubeadm/bootstraptokenstring_test.go
Normal file
@ -0,0 +1,236 @@
|
||||
/*
|
||||
Copyright 2018 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 kubeadm
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"reflect"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestMarshalJSON(t *testing.T) {
|
||||
var tests = []struct {
|
||||
bts BootstrapTokenString
|
||||
expected string
|
||||
}{
|
||||
{BootstrapTokenString{ID: "abcdef", Secret: "abcdef0123456789"}, `"abcdef.abcdef0123456789"`},
|
||||
{BootstrapTokenString{ID: "foo", Secret: "bar"}, `"foo.bar"`},
|
||||
{BootstrapTokenString{ID: "h", Secret: "b"}, `"h.b"`},
|
||||
}
|
||||
for _, rt := range tests {
|
||||
b, err := json.Marshal(rt.bts)
|
||||
if err != nil {
|
||||
t.Fatalf("json.Marshal returned an unexpected error: %v", err)
|
||||
}
|
||||
if string(b) != rt.expected {
|
||||
t.Errorf(
|
||||
"failed BootstrapTokenString.MarshalJSON:\n\texpected: %s\n\t actual: %s",
|
||||
rt.expected,
|
||||
string(b),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestUnmarshalJSON(t *testing.T) {
|
||||
var tests = []struct {
|
||||
input string
|
||||
bts *BootstrapTokenString
|
||||
expectedError bool
|
||||
}{
|
||||
{`"f.s"`, &BootstrapTokenString{}, true},
|
||||
{`"abcdef."`, &BootstrapTokenString{}, true},
|
||||
{`"abcdef:abcdef0123456789"`, &BootstrapTokenString{}, true},
|
||||
{`abcdef.abcdef0123456789`, &BootstrapTokenString{}, true},
|
||||
{`"abcdef.abcdef0123456789`, &BootstrapTokenString{}, true},
|
||||
{`"abcdef.ABCDEF0123456789"`, &BootstrapTokenString{}, true},
|
||||
{`"abcdef.abcdef0123456789"`, &BootstrapTokenString{ID: "abcdef", Secret: "abcdef0123456789"}, false},
|
||||
{`"123456.aabbccddeeffgghh"`, &BootstrapTokenString{ID: "123456", Secret: "aabbccddeeffgghh"}, false},
|
||||
}
|
||||
for _, rt := range tests {
|
||||
newbts := &BootstrapTokenString{}
|
||||
err := json.Unmarshal([]byte(rt.input), newbts)
|
||||
if (err != nil) != rt.expectedError {
|
||||
t.Errorf("failed BootstrapTokenString.UnmarshalJSON:\n\texpected error: %t\n\t actual error: %v", rt.expectedError, err)
|
||||
} else if !reflect.DeepEqual(rt.bts, newbts) {
|
||||
t.Errorf(
|
||||
"failed BootstrapTokenString.UnmarshalJSON:\n\texpected: %v\n\t actual: %v",
|
||||
rt.bts,
|
||||
newbts,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestJSONRoundtrip(t *testing.T) {
|
||||
var tests = []struct {
|
||||
input string
|
||||
bts *BootstrapTokenString
|
||||
}{
|
||||
{`"abcdef.abcdef0123456789"`, nil},
|
||||
{"", &BootstrapTokenString{ID: "abcdef", Secret: "abcdef0123456789"}},
|
||||
}
|
||||
for _, rt := range tests {
|
||||
if err := roundtrip(rt.input, rt.bts); err != nil {
|
||||
t.Errorf("failed BootstrapTokenString JSON roundtrip with error: %v", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func roundtrip(input string, bts *BootstrapTokenString) error {
|
||||
var b []byte
|
||||
var err error
|
||||
newbts := &BootstrapTokenString{}
|
||||
// If string input was specified, roundtrip like this: string -> (unmarshal) -> object -> (marshal) -> string
|
||||
if len(input) > 0 {
|
||||
if err := json.Unmarshal([]byte(input), newbts); err != nil {
|
||||
return fmt.Errorf("expected no unmarshal error, got error: %v", err)
|
||||
}
|
||||
if b, err = json.Marshal(newbts); err != nil {
|
||||
return fmt.Errorf("expected no marshal error, got error: %v", err)
|
||||
}
|
||||
if input != string(b) {
|
||||
return fmt.Errorf(
|
||||
"expected token: %s\n\t actual: %s",
|
||||
input,
|
||||
string(b),
|
||||
)
|
||||
}
|
||||
} else { // Otherwise, roundtrip like this: object -> (marshal) -> string -> (unmarshal) -> object
|
||||
if b, err = json.Marshal(bts); err != nil {
|
||||
return fmt.Errorf("expected no marshal error, got error: %v", err)
|
||||
}
|
||||
if err := json.Unmarshal(b, newbts); err != nil {
|
||||
return fmt.Errorf("expected no unmarshal error, got error: %v", err)
|
||||
}
|
||||
if !reflect.DeepEqual(bts, newbts) {
|
||||
return fmt.Errorf(
|
||||
"expected object: %v\n\t actual: %v",
|
||||
bts,
|
||||
newbts,
|
||||
)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func TestTokenFromIDAndSecret(t *testing.T) {
|
||||
var tests = []struct {
|
||||
bts BootstrapTokenString
|
||||
expected string
|
||||
}{
|
||||
{BootstrapTokenString{ID: "foo", Secret: "bar"}, "foo.bar"},
|
||||
{BootstrapTokenString{ID: "abcdef", Secret: "abcdef0123456789"}, "abcdef.abcdef0123456789"},
|
||||
{BootstrapTokenString{ID: "h", Secret: "b"}, "h.b"},
|
||||
}
|
||||
for _, rt := range tests {
|
||||
actual := rt.bts.String()
|
||||
if actual != rt.expected {
|
||||
t.Errorf(
|
||||
"failed BootstrapTokenString.String():\n\texpected: %s\n\t actual: %s",
|
||||
rt.expected,
|
||||
actual,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestNewBootstrapTokenString(t *testing.T) {
|
||||
var tests = []struct {
|
||||
token string
|
||||
expectedError bool
|
||||
bts *BootstrapTokenString
|
||||
}{
|
||||
{token: "", expectedError: true, bts: nil},
|
||||
{token: ".", expectedError: true, bts: nil},
|
||||
{token: "1234567890123456789012", expectedError: true, bts: nil}, // invalid parcel size
|
||||
{token: "12345.1234567890123456", expectedError: true, bts: nil}, // invalid parcel size
|
||||
{token: ".1234567890123456", expectedError: true, bts: nil}, // invalid parcel size
|
||||
{token: "123456.", expectedError: true, bts: nil}, // invalid parcel size
|
||||
{token: "123456:1234567890.123456", expectedError: true, bts: nil}, // invalid separation
|
||||
{token: "abcdef:1234567890123456", expectedError: true, bts: nil}, // invalid separation
|
||||
{token: "Abcdef.1234567890123456", expectedError: true, bts: nil}, // invalid token id
|
||||
{token: "123456.AABBCCDDEEFFGGHH", expectedError: true, bts: nil}, // invalid token secret
|
||||
{token: "123456.AABBCCD-EEFFGGHH", expectedError: true, bts: nil}, // invalid character
|
||||
{token: "abc*ef.1234567890123456", expectedError: true, bts: nil}, // invalid character
|
||||
{token: "abcdef.1234567890123456", expectedError: false, bts: &BootstrapTokenString{ID: "abcdef", Secret: "1234567890123456"}},
|
||||
{token: "123456.aabbccddeeffgghh", expectedError: false, bts: &BootstrapTokenString{ID: "123456", Secret: "aabbccddeeffgghh"}},
|
||||
{token: "abcdef.abcdef0123456789", expectedError: false, bts: &BootstrapTokenString{ID: "abcdef", Secret: "abcdef0123456789"}},
|
||||
{token: "123456.1234560123456789", expectedError: false, bts: &BootstrapTokenString{ID: "123456", Secret: "1234560123456789"}},
|
||||
}
|
||||
for _, rt := range tests {
|
||||
actual, err := NewBootstrapTokenString(rt.token)
|
||||
if (err != nil) != rt.expectedError {
|
||||
t.Errorf(
|
||||
"failed NewBootstrapTokenString for the token %q\n\texpected error: %t\n\t actual error: %v",
|
||||
rt.token,
|
||||
rt.expectedError,
|
||||
err,
|
||||
)
|
||||
} else if !reflect.DeepEqual(actual, rt.bts) {
|
||||
t.Errorf(
|
||||
"failed NewBootstrapTokenString for the token %q\n\texpected: %v\n\t actual: %v",
|
||||
rt.token,
|
||||
rt.bts,
|
||||
actual,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestNewBootstrapTokenStringFromIDAndSecret(t *testing.T) {
|
||||
var tests = []struct {
|
||||
id, secret string
|
||||
expectedError bool
|
||||
bts *BootstrapTokenString
|
||||
}{
|
||||
{id: "", secret: "", expectedError: true, bts: nil},
|
||||
{id: "1234567890123456789012", secret: "", expectedError: true, bts: nil}, // invalid parcel size
|
||||
{id: "12345", secret: "1234567890123456", expectedError: true, bts: nil}, // invalid parcel size
|
||||
{id: "", secret: "1234567890123456", expectedError: true, bts: nil}, // invalid parcel size
|
||||
{id: "123456", secret: "", expectedError: true, bts: nil}, // invalid parcel size
|
||||
{id: "Abcdef", secret: "1234567890123456", expectedError: true, bts: nil}, // invalid token id
|
||||
{id: "123456", secret: "AABBCCDDEEFFGGHH", expectedError: true, bts: nil}, // invalid token secret
|
||||
{id: "123456", secret: "AABBCCD-EEFFGGHH", expectedError: true, bts: nil}, // invalid character
|
||||
{id: "abc*ef", secret: "1234567890123456", expectedError: true, bts: nil}, // invalid character
|
||||
{id: "abcdef", secret: "1234567890123456", expectedError: false, bts: &BootstrapTokenString{ID: "abcdef", Secret: "1234567890123456"}},
|
||||
{id: "123456", secret: "aabbccddeeffgghh", expectedError: false, bts: &BootstrapTokenString{ID: "123456", Secret: "aabbccddeeffgghh"}},
|
||||
{id: "abcdef", secret: "abcdef0123456789", expectedError: false, bts: &BootstrapTokenString{ID: "abcdef", Secret: "abcdef0123456789"}},
|
||||
{id: "123456", secret: "1234560123456789", expectedError: false, bts: &BootstrapTokenString{ID: "123456", Secret: "1234560123456789"}},
|
||||
}
|
||||
for _, rt := range tests {
|
||||
actual, err := NewBootstrapTokenStringFromIDAndSecret(rt.id, rt.secret)
|
||||
if (err != nil) != rt.expectedError {
|
||||
t.Errorf(
|
||||
"failed NewBootstrapTokenStringFromIDAndSecret for the token with id %q and secret %q\n\texpected error: %t\n\t actual error: %v",
|
||||
rt.id,
|
||||
rt.secret,
|
||||
rt.expectedError,
|
||||
err,
|
||||
)
|
||||
} else if !reflect.DeepEqual(actual, rt.bts) {
|
||||
t.Errorf(
|
||||
"failed NewBootstrapTokenStringFromIDAndSecret for the token with id %q and secret %q\n\texpected: %v\n\t actual: %v",
|
||||
rt.id,
|
||||
rt.secret,
|
||||
rt.bts,
|
||||
actual,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,236 @@
|
||||
/*
|
||||
Copyright 2018 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 v1alpha2
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"reflect"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestMarshalJSON(t *testing.T) {
|
||||
var tests = []struct {
|
||||
bts BootstrapTokenString
|
||||
expected string
|
||||
}{
|
||||
{BootstrapTokenString{ID: "abcdef", Secret: "abcdef0123456789"}, `"abcdef.abcdef0123456789"`},
|
||||
{BootstrapTokenString{ID: "foo", Secret: "bar"}, `"foo.bar"`},
|
||||
{BootstrapTokenString{ID: "h", Secret: "b"}, `"h.b"`},
|
||||
}
|
||||
for _, rt := range tests {
|
||||
b, err := json.Marshal(rt.bts)
|
||||
if err != nil {
|
||||
t.Fatalf("json.Marshal returned an unexpected error: %v", err)
|
||||
}
|
||||
if string(b) != rt.expected {
|
||||
t.Errorf(
|
||||
"failed BootstrapTokenString.MarshalJSON:\n\texpected: %s\n\t actual: %s",
|
||||
rt.expected,
|
||||
string(b),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestUnmarshalJSON(t *testing.T) {
|
||||
var tests = []struct {
|
||||
input string
|
||||
bts *BootstrapTokenString
|
||||
expectedError bool
|
||||
}{
|
||||
{`"f.s"`, &BootstrapTokenString{}, true},
|
||||
{`"abcdef."`, &BootstrapTokenString{}, true},
|
||||
{`"abcdef:abcdef0123456789"`, &BootstrapTokenString{}, true},
|
||||
{`abcdef.abcdef0123456789`, &BootstrapTokenString{}, true},
|
||||
{`"abcdef.abcdef0123456789`, &BootstrapTokenString{}, true},
|
||||
{`"abcdef.ABCDEF0123456789"`, &BootstrapTokenString{}, true},
|
||||
{`"abcdef.abcdef0123456789"`, &BootstrapTokenString{ID: "abcdef", Secret: "abcdef0123456789"}, false},
|
||||
{`"123456.aabbccddeeffgghh"`, &BootstrapTokenString{ID: "123456", Secret: "aabbccddeeffgghh"}, false},
|
||||
}
|
||||
for _, rt := range tests {
|
||||
newbts := &BootstrapTokenString{}
|
||||
err := json.Unmarshal([]byte(rt.input), newbts)
|
||||
if (err != nil) != rt.expectedError {
|
||||
t.Errorf("failed BootstrapTokenString.UnmarshalJSON:\n\texpected error: %t\n\t actual error: %v", rt.expectedError, err)
|
||||
} else if !reflect.DeepEqual(rt.bts, newbts) {
|
||||
t.Errorf(
|
||||
"failed BootstrapTokenString.UnmarshalJSON:\n\texpected: %v\n\t actual: %v",
|
||||
rt.bts,
|
||||
newbts,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestJSONRoundtrip(t *testing.T) {
|
||||
var tests = []struct {
|
||||
input string
|
||||
bts *BootstrapTokenString
|
||||
}{
|
||||
{`"abcdef.abcdef0123456789"`, nil},
|
||||
{"", &BootstrapTokenString{ID: "abcdef", Secret: "abcdef0123456789"}},
|
||||
}
|
||||
for _, rt := range tests {
|
||||
if err := roundtrip(rt.input, rt.bts); err != nil {
|
||||
t.Errorf("failed BootstrapTokenString JSON roundtrip with error: %v", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func roundtrip(input string, bts *BootstrapTokenString) error {
|
||||
var b []byte
|
||||
var err error
|
||||
newbts := &BootstrapTokenString{}
|
||||
// If string input was specified, roundtrip like this: string -> (unmarshal) -> object -> (marshal) -> string
|
||||
if len(input) > 0 {
|
||||
if err := json.Unmarshal([]byte(input), newbts); err != nil {
|
||||
return fmt.Errorf("expected no unmarshal error, got error: %v", err)
|
||||
}
|
||||
if b, err = json.Marshal(newbts); err != nil {
|
||||
return fmt.Errorf("expected no marshal error, got error: %v", err)
|
||||
}
|
||||
if input != string(b) {
|
||||
return fmt.Errorf(
|
||||
"expected token: %s\n\t actual: %s",
|
||||
input,
|
||||
string(b),
|
||||
)
|
||||
}
|
||||
} else { // Otherwise, roundtrip like this: object -> (marshal) -> string -> (unmarshal) -> object
|
||||
if b, err = json.Marshal(bts); err != nil {
|
||||
return fmt.Errorf("expected no marshal error, got error: %v", err)
|
||||
}
|
||||
if err := json.Unmarshal(b, newbts); err != nil {
|
||||
return fmt.Errorf("expected no unmarshal error, got error: %v", err)
|
||||
}
|
||||
if !reflect.DeepEqual(bts, newbts) {
|
||||
return fmt.Errorf(
|
||||
"expected object: %v\n\t actual: %v",
|
||||
bts,
|
||||
newbts,
|
||||
)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func TestTokenFromIDAndSecret(t *testing.T) {
|
||||
var tests = []struct {
|
||||
bts BootstrapTokenString
|
||||
expected string
|
||||
}{
|
||||
{BootstrapTokenString{ID: "foo", Secret: "bar"}, "foo.bar"},
|
||||
{BootstrapTokenString{ID: "abcdef", Secret: "abcdef0123456789"}, "abcdef.abcdef0123456789"},
|
||||
{BootstrapTokenString{ID: "h", Secret: "b"}, "h.b"},
|
||||
}
|
||||
for _, rt := range tests {
|
||||
actual := rt.bts.String()
|
||||
if actual != rt.expected {
|
||||
t.Errorf(
|
||||
"failed BootstrapTokenString.String():\n\texpected: %s\n\t actual: %s",
|
||||
rt.expected,
|
||||
actual,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestNewBootstrapTokenString(t *testing.T) {
|
||||
var tests = []struct {
|
||||
token string
|
||||
expectedError bool
|
||||
bts *BootstrapTokenString
|
||||
}{
|
||||
{token: "", expectedError: true, bts: nil},
|
||||
{token: ".", expectedError: true, bts: nil},
|
||||
{token: "1234567890123456789012", expectedError: true, bts: nil}, // invalid parcel size
|
||||
{token: "12345.1234567890123456", expectedError: true, bts: nil}, // invalid parcel size
|
||||
{token: ".1234567890123456", expectedError: true, bts: nil}, // invalid parcel size
|
||||
{token: "123456.", expectedError: true, bts: nil}, // invalid parcel size
|
||||
{token: "123456:1234567890.123456", expectedError: true, bts: nil}, // invalid separation
|
||||
{token: "abcdef:1234567890123456", expectedError: true, bts: nil}, // invalid separation
|
||||
{token: "Abcdef.1234567890123456", expectedError: true, bts: nil}, // invalid token id
|
||||
{token: "123456.AABBCCDDEEFFGGHH", expectedError: true, bts: nil}, // invalid token secret
|
||||
{token: "123456.AABBCCD-EEFFGGHH", expectedError: true, bts: nil}, // invalid character
|
||||
{token: "abc*ef.1234567890123456", expectedError: true, bts: nil}, // invalid character
|
||||
{token: "abcdef.1234567890123456", expectedError: false, bts: &BootstrapTokenString{ID: "abcdef", Secret: "1234567890123456"}},
|
||||
{token: "123456.aabbccddeeffgghh", expectedError: false, bts: &BootstrapTokenString{ID: "123456", Secret: "aabbccddeeffgghh"}},
|
||||
{token: "abcdef.abcdef0123456789", expectedError: false, bts: &BootstrapTokenString{ID: "abcdef", Secret: "abcdef0123456789"}},
|
||||
{token: "123456.1234560123456789", expectedError: false, bts: &BootstrapTokenString{ID: "123456", Secret: "1234560123456789"}},
|
||||
}
|
||||
for _, rt := range tests {
|
||||
actual, err := NewBootstrapTokenString(rt.token)
|
||||
if (err != nil) != rt.expectedError {
|
||||
t.Errorf(
|
||||
"failed NewBootstrapTokenString for the token %q\n\texpected error: %t\n\t actual error: %v",
|
||||
rt.token,
|
||||
rt.expectedError,
|
||||
err,
|
||||
)
|
||||
} else if !reflect.DeepEqual(actual, rt.bts) {
|
||||
t.Errorf(
|
||||
"failed NewBootstrapTokenString for the token %q\n\texpected: %v\n\t actual: %v",
|
||||
rt.token,
|
||||
rt.bts,
|
||||
actual,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestNewBootstrapTokenStringFromIDAndSecret(t *testing.T) {
|
||||
var tests = []struct {
|
||||
id, secret string
|
||||
expectedError bool
|
||||
bts *BootstrapTokenString
|
||||
}{
|
||||
{id: "", secret: "", expectedError: true, bts: nil},
|
||||
{id: "1234567890123456789012", secret: "", expectedError: true, bts: nil}, // invalid parcel size
|
||||
{id: "12345", secret: "1234567890123456", expectedError: true, bts: nil}, // invalid parcel size
|
||||
{id: "", secret: "1234567890123456", expectedError: true, bts: nil}, // invalid parcel size
|
||||
{id: "123456", secret: "", expectedError: true, bts: nil}, // invalid parcel size
|
||||
{id: "Abcdef", secret: "1234567890123456", expectedError: true, bts: nil}, // invalid token id
|
||||
{id: "123456", secret: "AABBCCDDEEFFGGHH", expectedError: true, bts: nil}, // invalid token secret
|
||||
{id: "123456", secret: "AABBCCD-EEFFGGHH", expectedError: true, bts: nil}, // invalid character
|
||||
{id: "abc*ef", secret: "1234567890123456", expectedError: true, bts: nil}, // invalid character
|
||||
{id: "abcdef", secret: "1234567890123456", expectedError: false, bts: &BootstrapTokenString{ID: "abcdef", Secret: "1234567890123456"}},
|
||||
{id: "123456", secret: "aabbccddeeffgghh", expectedError: false, bts: &BootstrapTokenString{ID: "123456", Secret: "aabbccddeeffgghh"}},
|
||||
{id: "abcdef", secret: "abcdef0123456789", expectedError: false, bts: &BootstrapTokenString{ID: "abcdef", Secret: "abcdef0123456789"}},
|
||||
{id: "123456", secret: "1234560123456789", expectedError: false, bts: &BootstrapTokenString{ID: "123456", Secret: "1234560123456789"}},
|
||||
}
|
||||
for _, rt := range tests {
|
||||
actual, err := NewBootstrapTokenStringFromIDAndSecret(rt.id, rt.secret)
|
||||
if (err != nil) != rt.expectedError {
|
||||
t.Errorf(
|
||||
"failed NewBootstrapTokenStringFromIDAndSecret for the token with id %q and secret %q\n\texpected error: %t\n\t actual error: %v",
|
||||
rt.id,
|
||||
rt.secret,
|
||||
rt.expectedError,
|
||||
err,
|
||||
)
|
||||
} else if !reflect.DeepEqual(actual, rt.bts) {
|
||||
t.Errorf(
|
||||
"failed NewBootstrapTokenStringFromIDAndSecret for the token with id %q and secret %q\n\texpected: %v\n\t actual: %v",
|
||||
rt.id,
|
||||
rt.secret,
|
||||
rt.bts,
|
||||
actual,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
@ -33,7 +33,7 @@ import (
|
||||
utilpointer "k8s.io/kubernetes/pkg/util/pointer"
|
||||
)
|
||||
|
||||
func TestValidateTokenDiscovery(t *testing.T) {
|
||||
func TestValidateToken(t *testing.T) {
|
||||
var tests = []struct {
|
||||
c *kubeadm.NodeConfiguration
|
||||
f *field.Path
|
||||
@ -51,7 +51,7 @@ func TestValidateTokenDiscovery(t *testing.T) {
|
||||
err := ValidateToken(rt.c.Token, rt.f).ToAggregate()
|
||||
if (err == nil) != rt.expected {
|
||||
t.Errorf(
|
||||
"failed ValidateTokenDiscovery:\n\texpected: %t\n\t actual: %t",
|
||||
"failed ValidateToken:\n\texpected: %t\n\t actual: %t",
|
||||
rt.expected,
|
||||
(err == nil),
|
||||
)
|
||||
@ -434,7 +434,6 @@ func TestValidateMasterConfiguration(t *testing.T) {
|
||||
DNSDomain: "cluster.local",
|
||||
},
|
||||
CertificatesDir: "/some/other/cert/dir",
|
||||
Token: "abcdef.0123456789abcdef",
|
||||
}, false},
|
||||
{"valid master configuration with incorrect IPv4 pod subnet",
|
||||
&kubeadm.MasterConfiguration{
|
||||
@ -448,7 +447,6 @@ func TestValidateMasterConfiguration(t *testing.T) {
|
||||
PodSubnet: "10.0.1.15",
|
||||
},
|
||||
CertificatesDir: "/some/other/cert/dir",
|
||||
Token: "abcdef.0123456789abcdef",
|
||||
NodeRegistration: kubeadm.NodeRegistrationOptions{Name: nodename, CRISocket: "/some/path"},
|
||||
}, false},
|
||||
{"valid master configuration with IPv4 service subnet",
|
||||
@ -494,7 +492,6 @@ func TestValidateMasterConfiguration(t *testing.T) {
|
||||
PodSubnet: "10.0.1.15/16",
|
||||
},
|
||||
CertificatesDir: "/some/other/cert/dir",
|
||||
Token: "abcdef.0123456789abcdef",
|
||||
NodeRegistration: kubeadm.NodeRegistrationOptions{Name: nodename, CRISocket: "/some/path"},
|
||||
}, true},
|
||||
{"valid master configuration using IPv6 service subnet",
|
||||
@ -539,7 +536,6 @@ func TestValidateMasterConfiguration(t *testing.T) {
|
||||
DNSDomain: "cluster.local",
|
||||
},
|
||||
CertificatesDir: "/some/other/cert/dir",
|
||||
Token: "abcdef.0123456789abcdef",
|
||||
NodeRegistration: kubeadm.NodeRegistrationOptions{Name: nodename, CRISocket: "/some/path"},
|
||||
}, true},
|
||||
}
|
||||
|
@ -135,13 +135,6 @@ func TestRunCreateToken(t *testing.T) {
|
||||
extraGroups: []string{},
|
||||
expectedError: false,
|
||||
},
|
||||
{
|
||||
name: "invalid: incorrect token",
|
||||
token: "123456.AABBCCDDEEFFGGHH",
|
||||
usages: []string{"signing", "authentication"},
|
||||
extraGroups: []string{},
|
||||
expectedError: true,
|
||||
},
|
||||
{
|
||||
name: "invalid: incorrect extraGroups",
|
||||
token: "abcdef.1234567890123456",
|
||||
@ -180,18 +173,27 @@ func TestRunCreateToken(t *testing.T) {
|
||||
},
|
||||
}
|
||||
for _, tc := range testCases {
|
||||
bts, err := kubeadmapiv1alpha2.NewBootstrapTokenString(tc.token)
|
||||
if err != nil && len(tc.token) != 0 { // if tc.token is "" it's okay as it will be generated later at runtime
|
||||
t.Fatalf("token couldn't be parsed for testing: %v", err)
|
||||
}
|
||||
|
||||
cfg := &kubeadmapiv1alpha2.MasterConfiguration{
|
||||
|
||||
// KubernetesVersion is not used by bootstrap-token, but we set this explicitly to avoid
|
||||
// the lookup of the version from the internet when executing ConfigFileAndDefaultsToInternalConfig
|
||||
KubernetesVersion: "v1.10.0",
|
||||
Token: tc.token,
|
||||
TokenTTL: &metav1.Duration{Duration: 0},
|
||||
TokenUsages: tc.usages,
|
||||
TokenGroups: tc.extraGroups,
|
||||
BootstrapTokens: []kubeadmapiv1alpha2.BootstrapToken{
|
||||
{
|
||||
Token: bts,
|
||||
TTL: &metav1.Duration{Duration: 0},
|
||||
Usages: tc.usages,
|
||||
Groups: tc.extraGroups,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
err := RunCreateToken(&buf, fakeClient, "", cfg, "", tc.printJoin, "")
|
||||
err = RunCreateToken(&buf, fakeClient, "", cfg, tc.printJoin, "")
|
||||
if (err != nil) != tc.expectedError {
|
||||
t.Errorf("Test case %s: RunCreateToken expected error: %v, saw: %v", tc.name, tc.expectedError, (err != nil))
|
||||
}
|
||||
@ -277,22 +279,6 @@ func TestNewCmdToken(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetSecretString(t *testing.T) {
|
||||
secret := v1.Secret{}
|
||||
key := "test-key"
|
||||
if str := getSecretString(&secret, key); str != "" {
|
||||
t.Errorf("getSecretString() did not return empty string for a nil v1.Secret.Data")
|
||||
}
|
||||
secret.Data = make(map[string][]byte)
|
||||
if str := getSecretString(&secret, key); str != "" {
|
||||
t.Errorf("getSecretString() did not return empty string for missing v1.Secret.Data key")
|
||||
}
|
||||
secret.Data[key] = []byte("test-value")
|
||||
if str := getSecretString(&secret, key); str == "" {
|
||||
t.Errorf("getSecretString() failed for a valid v1.Secret.Data key")
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetClientset(t *testing.T) {
|
||||
testConfigTokenFile := "test-config-file"
|
||||
|
||||
|
@ -68,7 +68,6 @@ func TestPrintConfiguration(t *testing.T) {
|
||||
nodeRegistration:
|
||||
criSocket: ""
|
||||
name: ""
|
||||
token: ""
|
||||
unifiedControlPlaneImage: ""
|
||||
`),
|
||||
},
|
||||
@ -113,7 +112,6 @@ func TestPrintConfiguration(t *testing.T) {
|
||||
nodeRegistration:
|
||||
criSocket: ""
|
||||
name: ""
|
||||
token: ""
|
||||
unifiedControlPlaneImage: ""
|
||||
`),
|
||||
},
|
||||
|
@ -1,59 +0,0 @@
|
||||
/*
|
||||
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 node
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
|
||||
)
|
||||
|
||||
func TestEncodeTokenSecretData(t *testing.T) {
|
||||
var tests = []struct {
|
||||
token *kubeadmapi.TokenDiscovery
|
||||
t time.Duration
|
||||
}{
|
||||
{token: &kubeadmapi.TokenDiscovery{ID: "foo", Secret: "bar"}}, // should use default
|
||||
{token: &kubeadmapi.TokenDiscovery{ID: "foo", Secret: "bar"}, t: time.Second}, // should use default
|
||||
}
|
||||
for _, rt := range tests {
|
||||
actual, _ := encodeTokenSecretData(rt.token.ID, rt.token.Secret, rt.t, []string{}, []string{}, "")
|
||||
if !bytes.Equal(actual["token-id"], []byte(rt.token.ID)) {
|
||||
t.Errorf(
|
||||
"failed EncodeTokenSecretData:\n\texpected: %s\n\t actual: %s",
|
||||
rt.token.ID,
|
||||
actual["token-id"],
|
||||
)
|
||||
}
|
||||
if !bytes.Equal(actual["token-secret"], []byte(rt.token.Secret)) {
|
||||
t.Errorf(
|
||||
"failed EncodeTokenSecretData:\n\texpected: %s\n\t actual: %s",
|
||||
rt.token.Secret,
|
||||
actual["token-secret"],
|
||||
)
|
||||
}
|
||||
if rt.t > 0 {
|
||||
if actual["expiration"] == nil {
|
||||
t.Errorf(
|
||||
"failed EncodeTokenSecretData, duration was not added to time",
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -63,8 +63,15 @@ func TestUploadConfiguration(t *testing.T) {
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
cfg := &kubeadmapi.MasterConfiguration{
|
||||
KubernetesVersion: "1.7.3",
|
||||
Token: "1234567",
|
||||
KubernetesVersion: "v1.10.3",
|
||||
BootstrapTokens: []kubeadmapi.BootstrapToken{
|
||||
{
|
||||
Token: &kubeadmapi.BootstrapTokenString{
|
||||
ID: "abcdef",
|
||||
Secret: "abcdef0123456789",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
client := clientsetfake.NewSimpleClientset()
|
||||
if tt.errOnCreate != nil {
|
||||
@ -110,8 +117,9 @@ func TestUploadConfiguration(t *testing.T) {
|
||||
t.Errorf("Decoded value doesn't match, decoded = %#v, expected = %#v", decodedCfg.KubernetesVersion, cfg.KubernetesVersion)
|
||||
}
|
||||
|
||||
if decodedCfg.Token != "" {
|
||||
t.Errorf("Decoded value contains token (sensitive info), decoded = %#v, expected = empty", decodedCfg.Token)
|
||||
// If the decoded cfg has a BootstrapTokens array, verify the sensitive information we had isn't still there.
|
||||
if len(decodedCfg.BootstrapTokens) > 0 && decodedCfg.BootstrapTokens[0].Token != nil && decodedCfg.BootstrapTokens[0].Token.String() == cfg.BootstrapTokens[0].Token.String() {
|
||||
t.Errorf("Decoded value contains .BootstrapTokens (sensitive info), decoded = %#v, expected = empty", decodedCfg.BootstrapTokens)
|
||||
}
|
||||
|
||||
if decodedExtCfg.Kind != "MasterConfiguration" {
|
||||
|
@ -1,173 +0,0 @@
|
||||
/*
|
||||
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 token
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
|
||||
)
|
||||
|
||||
func TestTokenParse(t *testing.T) {
|
||||
var tests = []struct {
|
||||
token string
|
||||
expected bool
|
||||
}{
|
||||
{token: "1234567890123456789012", expected: false}, // invalid parcel size
|
||||
{token: "12345.1234567890123456", expected: false}, // invalid parcel size
|
||||
{token: ".1234567890123456", expected: false}, // invalid parcel size
|
||||
{token: "123456:1234567890.123456", expected: false}, // invalid separation
|
||||
{token: "abcdef:1234567890123456", expected: false}, // invalid separation
|
||||
{token: "Abcdef.1234567890123456", expected: false}, // invalid token id
|
||||
{token: "123456.AABBCCDDEEFFGGHH", expected: false}, // invalid token secret
|
||||
{token: "abcdef.1234567890123456", expected: true},
|
||||
{token: "123456.aabbccddeeffgghh", expected: true},
|
||||
}
|
||||
|
||||
for _, rt := range tests {
|
||||
_, _, actual := ParseToken(rt.token)
|
||||
if (actual == nil) != rt.expected {
|
||||
t.Errorf(
|
||||
"failed ParseToken for this token: [%s]\n\texpected: %t\n\t actual: %t",
|
||||
rt.token,
|
||||
rt.expected,
|
||||
(actual == nil),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func TestParseTokenID(t *testing.T) {
|
||||
var tests = []struct {
|
||||
tokenID string
|
||||
expected bool
|
||||
}{
|
||||
{tokenID: "", expected: false},
|
||||
{tokenID: "1234567890123456789012", expected: false},
|
||||
{tokenID: "12345", expected: false},
|
||||
{tokenID: "Abcdef", expected: false},
|
||||
{tokenID: "abcdef", expected: true},
|
||||
{tokenID: "123456", expected: true},
|
||||
}
|
||||
for _, rt := range tests {
|
||||
actual := ParseTokenID(rt.tokenID)
|
||||
if (actual == nil) != rt.expected {
|
||||
t.Errorf(
|
||||
"failed ParseTokenID for this token ID: [%s]\n\texpected: %t\n\t actual: %t",
|
||||
rt.tokenID,
|
||||
rt.expected,
|
||||
(actual == nil),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestValidateToken(t *testing.T) {
|
||||
var tests = []struct {
|
||||
token *kubeadmapi.TokenDiscovery
|
||||
expected bool
|
||||
}{
|
||||
{token: &kubeadmapi.TokenDiscovery{ID: "", Secret: ""}, expected: false},
|
||||
{token: &kubeadmapi.TokenDiscovery{ID: "1234567890123456789012", Secret: ""}, expected: false},
|
||||
{token: &kubeadmapi.TokenDiscovery{ID: "", Secret: "1234567890123456789012"}, expected: false},
|
||||
{token: &kubeadmapi.TokenDiscovery{ID: "12345", Secret: "1234567890123456"}, expected: false},
|
||||
{token: &kubeadmapi.TokenDiscovery{ID: "Abcdef", Secret: "1234567890123456"}, expected: false},
|
||||
{token: &kubeadmapi.TokenDiscovery{ID: "123456", Secret: "AABBCCDDEEFFGGHH"}, expected: false},
|
||||
{token: &kubeadmapi.TokenDiscovery{ID: "abc*ef", Secret: "1234567890123456"}, expected: false},
|
||||
{token: &kubeadmapi.TokenDiscovery{ID: "abcdef", Secret: "123456789*123456"}, expected: false},
|
||||
{token: &kubeadmapi.TokenDiscovery{ID: "abcdef", Secret: "1234567890123456"}, expected: true},
|
||||
{token: &kubeadmapi.TokenDiscovery{ID: "123456", Secret: "aabbccddeeffgghh"}, expected: true},
|
||||
{token: &kubeadmapi.TokenDiscovery{ID: "abc456", Secret: "1234567890123456"}, expected: true},
|
||||
{token: &kubeadmapi.TokenDiscovery{ID: "abcdef", Secret: "123456ddeeffgghh"}, expected: true},
|
||||
}
|
||||
for _, rt := range tests {
|
||||
valid, actual := ValidateToken(rt.token)
|
||||
if (actual == nil) != rt.expected {
|
||||
t.Errorf(
|
||||
"failed ValidateToken for this token ID: [%s]\n\texpected: %t\n\t actual: %t",
|
||||
rt.token,
|
||||
rt.expected,
|
||||
(actual == nil),
|
||||
)
|
||||
}
|
||||
if (valid == true) != rt.expected {
|
||||
t.Errorf(
|
||||
"failed ValidateToken for this token ID: [%s]\n\texpected: %t\n\t actual: %t",
|
||||
rt.token,
|
||||
rt.expected,
|
||||
(actual == nil),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestGenerateToken(t *testing.T) {
|
||||
token, err := GenerateToken()
|
||||
if err != nil {
|
||||
t.Fatalf("GenerateToken returned an unexpected error: %+v", err)
|
||||
}
|
||||
tokenID, tokenSecret, err := ParseToken(token)
|
||||
if err != nil {
|
||||
t.Fatalf("GenerateToken returned an unexpected error: %+v", err)
|
||||
}
|
||||
if len(tokenID) != 6 {
|
||||
t.Errorf("failed GenerateToken first part length:\n\texpected: 6\n\t actual: %d", len(tokenID))
|
||||
}
|
||||
if len(tokenSecret) != 16 {
|
||||
t.Errorf("failed GenerateToken second part length:\n\texpected: 16\n\t actual: %d", len(tokenSecret))
|
||||
}
|
||||
}
|
||||
|
||||
func TestRandBytes(t *testing.T) {
|
||||
var randTest = []int{
|
||||
0,
|
||||
1,
|
||||
2,
|
||||
3,
|
||||
100,
|
||||
}
|
||||
|
||||
for _, rt := range randTest {
|
||||
actual, err := randBytes(rt)
|
||||
if err != nil {
|
||||
t.Errorf("failed randBytes: %v", err)
|
||||
}
|
||||
if len(actual) != rt {
|
||||
t.Errorf("failed randBytes:\n\texpected: %d\n\t actual: %d\n", rt, len(actual))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestBearerToken(t *testing.T) {
|
||||
var tests = []struct {
|
||||
token *kubeadmapi.TokenDiscovery
|
||||
expected string
|
||||
}{
|
||||
{token: &kubeadmapi.TokenDiscovery{ID: "foo", Secret: "bar"}, expected: "foo.bar"}, // should use default
|
||||
}
|
||||
for _, rt := range tests {
|
||||
actual := BearerToken(rt.token)
|
||||
if actual != rt.expected {
|
||||
t.Errorf(
|
||||
"failed BearerToken:\n\texpected: %s\n\t actual: %s",
|
||||
rt.expected,
|
||||
actual,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user