mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-27 21:47:07 +00:00
Merge pull request #102964 from neolit123/1.22-decouple-bootstraptoken-api
kubeadm: decouple the bootstraptoken API from the kubeadm API
This commit is contained in:
commit
ce3bf862ee
21
cmd/kubeadm/app/apis/bootstraptoken/doc.go
Normal file
21
cmd/kubeadm/app/apis/bootstraptoken/doc.go
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2021 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// +groupName=bootstraptoken.kubeadm.k8s.io
|
||||||
|
|
||||||
|
// Package bootstraptoken contains an API and utilities wrapping the
|
||||||
|
// "bootstrap.kubernetes.io/token" Secret type to ease its usage in kubeadm.
|
||||||
|
package bootstraptoken // import "k8s.io/kubernetes/cmd/kubeadm/app/apis/bootstraptoken"
|
58
cmd/kubeadm/app/apis/bootstraptoken/v1/types.go
Normal file
58
cmd/kubeadm/app/apis/bootstraptoken/v1/types.go
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2021 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 v1
|
||||||
|
|
||||||
|
import (
|
||||||
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
|
)
|
||||||
|
|
||||||
|
// BootstrapToken describes one bootstrap token, stored as a Secret in the cluster
|
||||||
|
// +k8s:deepcopy-gen=true
|
||||||
|
type BootstrapToken struct {
|
||||||
|
// Token is used for establishing bidirectional trust between nodes and control-planes.
|
||||||
|
// Used for joining nodes in the cluster.
|
||||||
|
Token *BootstrapTokenString `json:"token" datapolicy:"token"`
|
||||||
|
// Description sets a human-friendly message why this token exists and what it's used
|
||||||
|
// for, so other administrators can know its purpose.
|
||||||
|
// +optional
|
||||||
|
Description string `json:"description,omitempty"`
|
||||||
|
// TTL defines the time to live for this token. Defaults to 24h.
|
||||||
|
// Expires and TTL are mutually exclusive.
|
||||||
|
// +optional
|
||||||
|
TTL *metav1.Duration `json:"ttl,omitempty"`
|
||||||
|
// Expires specifies the timestamp when this token expires. Defaults to being set
|
||||||
|
// dynamically at runtime based on the TTL. Expires and TTL are mutually exclusive.
|
||||||
|
// +optional
|
||||||
|
Expires *metav1.Time `json:"expires,omitempty"`
|
||||||
|
// Usages describes the ways in which this token can be used. Can by default be used
|
||||||
|
// for establishing bidirectional trust, but that can be changed here.
|
||||||
|
// +optional
|
||||||
|
Usages []string `json:"usages,omitempty"`
|
||||||
|
// Groups specifies the extra groups that this token will authenticate as when/if
|
||||||
|
// used for authentication
|
||||||
|
// +optional
|
||||||
|
Groups []string `json:"groups,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// BootstrapTokenString is a token of the format abcdef.abcdef0123456789 that is used
|
||||||
|
// for both validation of the practically of the API server from a joining node's point
|
||||||
|
// of view and as an authentication method for the node in the bootstrap phase of
|
||||||
|
// "kubeadm join". This token is and should be short-lived
|
||||||
|
type BootstrapTokenString struct {
|
||||||
|
ID string `json:"-"`
|
||||||
|
Secret string `json:"-" datapolicy:"token"`
|
||||||
|
}
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
Copyright 2018 The Kubernetes Authors.
|
Copyright 2021 The Kubernetes Authors.
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
you may not use this file except in compliance with the License.
|
you may not use this file except in compliance with the License.
|
||||||
@ -14,9 +14,10 @@ See the License for the specific language governing permissions and
|
|||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package kubeadm
|
package v1
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"sort"
|
"sort"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
@ -30,9 +31,61 @@ import (
|
|||||||
bootstrapsecretutil "k8s.io/cluster-bootstrap/util/secrets"
|
bootstrapsecretutil "k8s.io/cluster-bootstrap/util/secrets"
|
||||||
)
|
)
|
||||||
|
|
||||||
// ToSecret converts the given BootstrapToken object to its Secret representation that
|
// MarshalJSON implements the json.Marshaler interface.
|
||||||
|
func (bts BootstrapTokenString) MarshalJSON() ([]byte, error) {
|
||||||
|
return []byte(fmt.Sprintf(`"%s"`, bts.String())), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnmarshalJSON implements the json.Unmarshaller interface.
|
||||||
|
func (bts *BootstrapTokenString) UnmarshalJSON(b []byte) error {
|
||||||
|
// If the token is represented as "", just return quickly without an error
|
||||||
|
if len(b) == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove unnecessary " characters coming from the JSON parser
|
||||||
|
token := strings.Replace(string(b), `"`, ``, -1)
|
||||||
|
// Convert the string Token to a BootstrapTokenString object
|
||||||
|
newbts, err := NewBootstrapTokenString(token)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
bts.ID = newbts.ID
|
||||||
|
bts.Secret = newbts.Secret
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// String returns the string representation of the BootstrapTokenString
|
||||||
|
func (bts BootstrapTokenString) String() string {
|
||||||
|
if len(bts.ID) > 0 && len(bts.Secret) > 0 {
|
||||||
|
return bootstraputil.TokenFromIDAndSecret(bts.ID, bts.Secret)
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewBootstrapTokenString converts the given Bootstrap Token as a string
|
||||||
|
// to the BootstrapTokenString object used for serialization/deserialization
|
||||||
|
// and internal usage. It also automatically validates that the given token
|
||||||
|
// is of the right format
|
||||||
|
func NewBootstrapTokenString(token string) (*BootstrapTokenString, error) {
|
||||||
|
substrs := bootstraputil.BootstrapTokenRegexp.FindStringSubmatch(token)
|
||||||
|
// TODO: Add a constant for the 3 value here, and explain better why it's needed (other than because how the regexp parsin works)
|
||||||
|
if len(substrs) != 3 {
|
||||||
|
return nil, errors.Errorf("the bootstrap token %q was not of the form %q", token, bootstrapapi.BootstrapTokenPattern)
|
||||||
|
}
|
||||||
|
|
||||||
|
return &BootstrapTokenString{ID: substrs[1], Secret: substrs[2]}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewBootstrapTokenStringFromIDAndSecret is a wrapper around NewBootstrapTokenString
|
||||||
|
// that allows the caller to specify the ID and Secret separately
|
||||||
|
func NewBootstrapTokenStringFromIDAndSecret(id, secret string) (*BootstrapTokenString, error) {
|
||||||
|
return NewBootstrapTokenString(bootstraputil.TokenFromIDAndSecret(id, secret))
|
||||||
|
}
|
||||||
|
|
||||||
|
// BootstrapTokenToSecret converts the given BootstrapToken object to its Secret representation that
|
||||||
// may be submitted to the API Server in order to be stored.
|
// may be submitted to the API Server in order to be stored.
|
||||||
func (bt *BootstrapToken) ToSecret() *v1.Secret {
|
func BootstrapTokenToSecret(bt *BootstrapToken) *v1.Secret {
|
||||||
return &v1.Secret{
|
return &v1.Secret{
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
Name: bootstraputil.BootstrapTokenSecretName(bt.Token.ID),
|
Name: bootstraputil.BootstrapTokenSecretName(bt.Token.ID),
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
Copyright 2018 The Kubernetes Authors.
|
Copyright 2021 The Kubernetes Authors.
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
you may not use this file except in compliance with the License.
|
you may not use this file except in compliance with the License.
|
||||||
@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
|
|||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package kubeadm
|
package v1
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
@ -22,15 +22,239 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"k8s.io/api/core/v1"
|
"github.com/pkg/errors"
|
||||||
|
v1 "k8s.io/api/core/v1"
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
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 {
|
||||||
|
t.Run(rt.bts.ID, func(t *testing.T) {
|
||||||
|
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 {
|
||||||
|
t.Run(rt.input, func(t *testing.T) {
|
||||||
|
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 {
|
||||||
|
t.Run(rt.input, func(t *testing.T) {
|
||||||
|
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 errors.Wrap(err, "expected no unmarshal error, got error")
|
||||||
|
}
|
||||||
|
if b, err = json.Marshal(newbts); err != nil {
|
||||||
|
return errors.Wrap(err, "expected no marshal error, got error")
|
||||||
|
}
|
||||||
|
if input != string(b) {
|
||||||
|
return errors.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 errors.Wrap(err, "expected no marshal error, got error")
|
||||||
|
}
|
||||||
|
if err := json.Unmarshal(b, newbts); err != nil {
|
||||||
|
return errors.Wrap(err, "expected no unmarshal error, got error")
|
||||||
|
}
|
||||||
|
if !reflect.DeepEqual(bts, newbts) {
|
||||||
|
return errors.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 {
|
||||||
|
t.Run(rt.bts.ID, func(t *testing.T) {
|
||||||
|
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 {
|
||||||
|
t.Run(rt.token, func(t *testing.T) {
|
||||||
|
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 {
|
||||||
|
t.Run(rt.id, func(t *testing.T) {
|
||||||
|
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,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// This timestamp is used as the reference value when computing expiration dates based on TTLs in these unit tests
|
// 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)
|
var refTime = time.Date(1970, time.January, 1, 1, 1, 1, 0, time.UTC)
|
||||||
|
|
||||||
func TestToSecret(t *testing.T) {
|
func TestBootstrapTokenToSecret(t *testing.T) {
|
||||||
|
|
||||||
var tests = []struct {
|
var tests = []struct {
|
||||||
bt *BootstrapToken
|
bt *BootstrapToken
|
||||||
secret *v1.Secret
|
secret *v1.Secret
|
||||||
@ -65,10 +289,10 @@ func TestToSecret(t *testing.T) {
|
|||||||
}
|
}
|
||||||
for _, rt := range tests {
|
for _, rt := range tests {
|
||||||
t.Run(rt.bt.Token.ID, func(t *testing.T) {
|
t.Run(rt.bt.Token.ID, func(t *testing.T) {
|
||||||
actual := rt.bt.ToSecret()
|
actual := BootstrapTokenToSecret(rt.bt)
|
||||||
if !reflect.DeepEqual(actual, rt.secret) {
|
if !reflect.DeepEqual(actual, rt.secret) {
|
||||||
t.Errorf(
|
t.Errorf(
|
||||||
"failed BootstrapToken.ToSecret():\n\texpected: %v\n\t actual: %v",
|
"failed BootstrapTokenToSecret():\n\texpected: %v\n\t actual: %v",
|
||||||
rt.secret,
|
rt.secret,
|
||||||
actual,
|
actual,
|
||||||
)
|
)
|
||||||
@ -95,7 +319,7 @@ func TestBootstrapTokenToSecretRoundtrip(t *testing.T) {
|
|||||||
}
|
}
|
||||||
for _, rt := range tests {
|
for _, rt := range tests {
|
||||||
t.Run(rt.bt.Token.ID, func(t *testing.T) {
|
t.Run(rt.bt.Token.ID, func(t *testing.T) {
|
||||||
actual, err := BootstrapTokenFromSecret(rt.bt.ToSecret())
|
actual, err := BootstrapTokenFromSecret(BootstrapTokenToSecret(rt.bt))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("failed BootstrapToken to Secret roundtrip with error: %v", err)
|
t.Errorf("failed BootstrapToken to Secret roundtrip with error: %v", err)
|
||||||
}
|
}
|
65
cmd/kubeadm/app/apis/bootstraptoken/v1/zz_generated.deepcopy.go
generated
Normal file
65
cmd/kubeadm/app/apis/bootstraptoken/v1/zz_generated.deepcopy.go
generated
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
// +build !ignore_autogenerated
|
||||||
|
|
||||||
|
/*
|
||||||
|
Copyright 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Code generated by deepcopy-gen. DO NOT EDIT.
|
||||||
|
|
||||||
|
package v1
|
||||||
|
|
||||||
|
import (
|
||||||
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
|
)
|
||||||
|
|
||||||
|
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||||
|
func (in *BootstrapToken) DeepCopyInto(out *BootstrapToken) {
|
||||||
|
*out = *in
|
||||||
|
if in.Token != nil {
|
||||||
|
in, out := &in.Token, &out.Token
|
||||||
|
*out = new(BootstrapTokenString)
|
||||||
|
**out = **in
|
||||||
|
}
|
||||||
|
if in.TTL != nil {
|
||||||
|
in, out := &in.TTL, &out.TTL
|
||||||
|
*out = new(metav1.Duration)
|
||||||
|
**out = **in
|
||||||
|
}
|
||||||
|
if in.Expires != nil {
|
||||||
|
in, out := &in.Expires, &out.Expires
|
||||||
|
*out = (*in).DeepCopy()
|
||||||
|
}
|
||||||
|
if in.Usages != nil {
|
||||||
|
in, out := &in.Usages, &out.Usages
|
||||||
|
*out = make([]string, len(*in))
|
||||||
|
copy(*out, *in)
|
||||||
|
}
|
||||||
|
if in.Groups != nil {
|
||||||
|
in, out := &in.Groups, &out.Groups
|
||||||
|
*out = make([]string, len(*in))
|
||||||
|
copy(*out, *in)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new BootstrapToken.
|
||||||
|
func (in *BootstrapToken) DeepCopy() *BootstrapToken {
|
||||||
|
if in == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
out := new(BootstrapToken)
|
||||||
|
in.DeepCopyInto(out)
|
||||||
|
return out
|
||||||
|
}
|
@ -1,92 +0,0 @@
|
|||||||
/*
|
|
||||||
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 holds the internal kubeadm API types
|
|
||||||
// Note: This file should be kept in sync with the similar one for the external API
|
|
||||||
// TODO: The BootstrapTokenString object should move out to either k8s.io/client-go or k8s.io/api in the future
|
|
||||||
// (probably as part of Bootstrap Tokens going GA). It should not be staged under the kubeadm API as it is now.
|
|
||||||
package kubeadm
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/pkg/errors"
|
|
||||||
|
|
||||||
bootstrapapi "k8s.io/cluster-bootstrap/token/api"
|
|
||||||
bootstraputil "k8s.io/cluster-bootstrap/token/util"
|
|
||||||
)
|
|
||||||
|
|
||||||
// BootstrapTokenString is a token of the format abcdef.abcdef0123456789 that is used
|
|
||||||
// for both validation of the practically of the API server from a joining node's point
|
|
||||||
// of view and as an authentication method for the node in the bootstrap phase of
|
|
||||||
// "kubeadm join". This token is and should be short-lived
|
|
||||||
type BootstrapTokenString struct {
|
|
||||||
ID string
|
|
||||||
Secret string
|
|
||||||
}
|
|
||||||
|
|
||||||
// MarshalJSON implements the json.Marshaler interface.
|
|
||||||
func (bts BootstrapTokenString) MarshalJSON() ([]byte, error) {
|
|
||||||
return []byte(fmt.Sprintf(`"%s"`, bts.String())), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// UnmarshalJSON implements the json.Unmarshaller interface.
|
|
||||||
func (bts *BootstrapTokenString) UnmarshalJSON(b []byte) error {
|
|
||||||
// If the token is represented as "", just return quickly without an error
|
|
||||||
if len(b) == 0 {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Remove unnecessary " characters coming from the JSON parser
|
|
||||||
token := strings.Replace(string(b), `"`, ``, -1)
|
|
||||||
// Convert the string Token to a BootstrapTokenString object
|
|
||||||
newbts, err := NewBootstrapTokenString(token)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
bts.ID = newbts.ID
|
|
||||||
bts.Secret = newbts.Secret
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// String returns the string representation of the BootstrapTokenString
|
|
||||||
func (bts BootstrapTokenString) String() string {
|
|
||||||
if len(bts.ID) > 0 && len(bts.Secret) > 0 {
|
|
||||||
return bootstraputil.TokenFromIDAndSecret(bts.ID, bts.Secret)
|
|
||||||
}
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewBootstrapTokenString converts the given Bootstrap Token as a string
|
|
||||||
// to the BootstrapTokenString object used for serialization/deserialization
|
|
||||||
// and internal usage. It also automatically validates that the given token
|
|
||||||
// is of the right format
|
|
||||||
func NewBootstrapTokenString(token string) (*BootstrapTokenString, error) {
|
|
||||||
substrs := bootstraputil.BootstrapTokenRegexp.FindStringSubmatch(token)
|
|
||||||
// TODO: Add a constant for the 3 value here, and explain better why it's needed (other than because how the regexp parsin works)
|
|
||||||
if len(substrs) != 3 {
|
|
||||||
return nil, errors.Errorf("the bootstrap token %q was not of the form %q", token, bootstrapapi.BootstrapTokenPattern)
|
|
||||||
}
|
|
||||||
|
|
||||||
return &BootstrapTokenString{ID: substrs[1], Secret: substrs[2]}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewBootstrapTokenStringFromIDAndSecret is a wrapper around NewBootstrapTokenString
|
|
||||||
// that allows the caller to specify the ID and Secret separately
|
|
||||||
func NewBootstrapTokenStringFromIDAndSecret(id, secret string) (*BootstrapTokenString, error) {
|
|
||||||
return NewBootstrapTokenString(bootstraputil.TokenFromIDAndSecret(id, secret))
|
|
||||||
}
|
|
@ -1,249 +0,0 @@
|
|||||||
/*
|
|
||||||
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"
|
|
||||||
|
|
||||||
"github.com/pkg/errors"
|
|
||||||
)
|
|
||||||
|
|
||||||
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 {
|
|
||||||
t.Run(rt.bts.ID, func(t *testing.T) {
|
|
||||||
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 {
|
|
||||||
t.Run(rt.input, func(t *testing.T) {
|
|
||||||
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 {
|
|
||||||
t.Run(rt.input, func(t *testing.T) {
|
|
||||||
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 errors.Wrap(err, "expected no unmarshal error, got error")
|
|
||||||
}
|
|
||||||
if b, err = json.Marshal(newbts); err != nil {
|
|
||||||
return errors.Wrap(err, "expected no marshal error, got error")
|
|
||||||
}
|
|
||||||
if input != string(b) {
|
|
||||||
return errors.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 errors.Wrap(err, "expected no marshal error, got error")
|
|
||||||
}
|
|
||||||
if err := json.Unmarshal(b, newbts); err != nil {
|
|
||||||
return errors.Wrap(err, "expected no unmarshal error, got error")
|
|
||||||
}
|
|
||||||
if !reflect.DeepEqual(bts, newbts) {
|
|
||||||
return errors.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 {
|
|
||||||
t.Run(rt.bts.ID, func(t *testing.T) {
|
|
||||||
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 {
|
|
||||||
t.Run(rt.token, func(t *testing.T) {
|
|
||||||
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 {
|
|
||||||
t.Run(rt.id, func(t *testing.T) {
|
|
||||||
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,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
@ -20,6 +20,7 @@ import (
|
|||||||
fuzz "github.com/google/gofuzz"
|
fuzz "github.com/google/gofuzz"
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
runtimeserializer "k8s.io/apimachinery/pkg/runtime/serializer"
|
runtimeserializer "k8s.io/apimachinery/pkg/runtime/serializer"
|
||||||
|
bootstraptokenv1 "k8s.io/kubernetes/cmd/kubeadm/app/apis/bootstraptoken/v1"
|
||||||
"k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
|
"k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
|
||||||
"k8s.io/kubernetes/cmd/kubeadm/app/constants"
|
"k8s.io/kubernetes/cmd/kubeadm/app/constants"
|
||||||
)
|
)
|
||||||
@ -49,7 +50,7 @@ func fuzzInitConfiguration(obj *kubeadm.InitConfiguration, c fuzz.Continue) {
|
|||||||
obj.ClusterConfiguration = kubeadm.ClusterConfiguration{}
|
obj.ClusterConfiguration = kubeadm.ClusterConfiguration{}
|
||||||
|
|
||||||
// Adds the default bootstrap token to get the round trip working
|
// Adds the default bootstrap token to get the round trip working
|
||||||
obj.BootstrapTokens = []kubeadm.BootstrapToken{
|
obj.BootstrapTokens = []bootstraptokenv1.BootstrapToken{
|
||||||
{
|
{
|
||||||
Groups: []string{"foo"},
|
Groups: []string{"foo"},
|
||||||
Usages: []string{"foo"},
|
Usages: []string{"foo"},
|
||||||
|
@ -21,9 +21,9 @@ import (
|
|||||||
|
|
||||||
v1 "k8s.io/api/core/v1"
|
v1 "k8s.io/api/core/v1"
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
"k8s.io/kubernetes/cmd/kubeadm/app/features"
|
|
||||||
|
|
||||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||||
|
bootstraptokenv1 "k8s.io/kubernetes/cmd/kubeadm/app/apis/bootstraptoken/v1"
|
||||||
|
"k8s.io/kubernetes/cmd/kubeadm/app/features"
|
||||||
)
|
)
|
||||||
|
|
||||||
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
|
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
|
||||||
@ -41,7 +41,7 @@ type InitConfiguration struct {
|
|||||||
ClusterConfiguration `json:"-"`
|
ClusterConfiguration `json:"-"`
|
||||||
|
|
||||||
// BootstrapTokens is respected at `kubeadm init` time and describes a set of Bootstrap Tokens to create.
|
// BootstrapTokens is respected at `kubeadm init` time and describes a set of Bootstrap Tokens to create.
|
||||||
BootstrapTokens []BootstrapToken
|
BootstrapTokens []bootstraptokenv1.BootstrapToken
|
||||||
|
|
||||||
// NodeRegistration holds fields that relate to registering the new control-plane node to the cluster
|
// NodeRegistration holds fields that relate to registering the new control-plane node to the cluster
|
||||||
NodeRegistration NodeRegistrationOptions
|
NodeRegistration NodeRegistrationOptions
|
||||||
@ -242,30 +242,6 @@ type Networking struct {
|
|||||||
DNSDomain string
|
DNSDomain string
|
||||||
}
|
}
|
||||||
|
|
||||||
// BootstrapToken describes one bootstrap token, stored as a Secret in the cluster
|
|
||||||
// TODO: The BootstrapToken object should move out to either k8s.io/client-go or k8s.io/api in the future
|
|
||||||
// (probably as part of Bootstrap Tokens going GA). It should not be staged under the kubeadm API as it is now.
|
|
||||||
type BootstrapToken struct {
|
|
||||||
// Token is used for establishing bidirectional trust between nodes and control-planes.
|
|
||||||
// Used for joining nodes in the cluster.
|
|
||||||
Token *BootstrapTokenString
|
|
||||||
// Description sets a human-friendly message why this token exists and what it's used
|
|
||||||
// for, so other administrators can know its purpose.
|
|
||||||
Description string
|
|
||||||
// TTL defines the time to live for this token. Defaults to 24h.
|
|
||||||
// Expires and TTL are mutually exclusive.
|
|
||||||
TTL *metav1.Duration
|
|
||||||
// Expires specifies the timestamp when this token expires. Defaults to being set
|
|
||||||
// dynamically at runtime based on the TTL. Expires and TTL are mutually exclusive.
|
|
||||||
Expires *metav1.Time
|
|
||||||
// Usages describes the ways in which this token can be used. Can by default be used
|
|
||||||
// for establishing bidirectional trust, but that can be changed here.
|
|
||||||
Usages []string
|
|
||||||
// Groups specifies the extra groups that this token will authenticate as when/if
|
|
||||||
// used for authentication
|
|
||||||
Groups []string
|
|
||||||
}
|
|
||||||
|
|
||||||
// Etcd contains elements describing Etcd configuration.
|
// Etcd contains elements describing Etcd configuration.
|
||||||
type Etcd struct {
|
type Etcd struct {
|
||||||
|
|
||||||
|
@ -27,6 +27,7 @@ import (
|
|||||||
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
conversion "k8s.io/apimachinery/pkg/conversion"
|
conversion "k8s.io/apimachinery/pkg/conversion"
|
||||||
runtime "k8s.io/apimachinery/pkg/runtime"
|
runtime "k8s.io/apimachinery/pkg/runtime"
|
||||||
|
bootstraptokenv1 "k8s.io/kubernetes/cmd/kubeadm/app/apis/bootstraptoken/v1"
|
||||||
kubeadm "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
|
kubeadm "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -57,16 +58,6 @@ func RegisterConversions(s *runtime.Scheme) error {
|
|||||||
}); err != nil {
|
}); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if err := s.AddGeneratedConversionFunc((*BootstrapToken)(nil), (*kubeadm.BootstrapToken)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
|
||||||
return Convert_v1beta2_BootstrapToken_To_kubeadm_BootstrapToken(a.(*BootstrapToken), b.(*kubeadm.BootstrapToken), scope)
|
|
||||||
}); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if err := s.AddGeneratedConversionFunc((*kubeadm.BootstrapToken)(nil), (*BootstrapToken)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
|
||||||
return Convert_kubeadm_BootstrapToken_To_v1beta2_BootstrapToken(a.(*kubeadm.BootstrapToken), b.(*BootstrapToken), scope)
|
|
||||||
}); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if err := s.AddGeneratedConversionFunc((*BootstrapTokenDiscovery)(nil), (*kubeadm.BootstrapTokenDiscovery)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
if err := s.AddGeneratedConversionFunc((*BootstrapTokenDiscovery)(nil), (*kubeadm.BootstrapTokenDiscovery)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||||
return Convert_v1beta2_BootstrapTokenDiscovery_To_kubeadm_BootstrapTokenDiscovery(a.(*BootstrapTokenDiscovery), b.(*kubeadm.BootstrapTokenDiscovery), scope)
|
return Convert_v1beta2_BootstrapTokenDiscovery_To_kubeadm_BootstrapTokenDiscovery(a.(*BootstrapTokenDiscovery), b.(*kubeadm.BootstrapTokenDiscovery), scope)
|
||||||
}); err != nil {
|
}); err != nil {
|
||||||
@ -77,16 +68,6 @@ func RegisterConversions(s *runtime.Scheme) error {
|
|||||||
}); err != nil {
|
}); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if err := s.AddGeneratedConversionFunc((*BootstrapTokenString)(nil), (*kubeadm.BootstrapTokenString)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
|
||||||
return Convert_v1beta2_BootstrapTokenString_To_kubeadm_BootstrapTokenString(a.(*BootstrapTokenString), b.(*kubeadm.BootstrapTokenString), scope)
|
|
||||||
}); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if err := s.AddGeneratedConversionFunc((*kubeadm.BootstrapTokenString)(nil), (*BootstrapTokenString)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
|
||||||
return Convert_kubeadm_BootstrapTokenString_To_v1beta2_BootstrapTokenString(a.(*kubeadm.BootstrapTokenString), b.(*BootstrapTokenString), scope)
|
|
||||||
}); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if err := s.AddGeneratedConversionFunc((*kubeadm.ClusterConfiguration)(nil), (*ClusterConfiguration)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
if err := s.AddGeneratedConversionFunc((*kubeadm.ClusterConfiguration)(nil), (*ClusterConfiguration)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||||
return Convert_kubeadm_ClusterConfiguration_To_v1beta2_ClusterConfiguration(a.(*kubeadm.ClusterConfiguration), b.(*ClusterConfiguration), scope)
|
return Convert_kubeadm_ClusterConfiguration_To_v1beta2_ClusterConfiguration(a.(*kubeadm.ClusterConfiguration), b.(*ClusterConfiguration), scope)
|
||||||
}); err != nil {
|
}); err != nil {
|
||||||
@ -290,36 +271,6 @@ func Convert_kubeadm_APIServer_To_v1beta2_APIServer(in *kubeadm.APIServer, out *
|
|||||||
return autoConvert_kubeadm_APIServer_To_v1beta2_APIServer(in, out, s)
|
return autoConvert_kubeadm_APIServer_To_v1beta2_APIServer(in, out, s)
|
||||||
}
|
}
|
||||||
|
|
||||||
func autoConvert_v1beta2_BootstrapToken_To_kubeadm_BootstrapToken(in *BootstrapToken, out *kubeadm.BootstrapToken, s conversion.Scope) error {
|
|
||||||
out.Token = (*kubeadm.BootstrapTokenString)(unsafe.Pointer(in.Token))
|
|
||||||
out.Description = in.Description
|
|
||||||
out.TTL = (*v1.Duration)(unsafe.Pointer(in.TTL))
|
|
||||||
out.Expires = (*v1.Time)(unsafe.Pointer(in.Expires))
|
|
||||||
out.Usages = *(*[]string)(unsafe.Pointer(&in.Usages))
|
|
||||||
out.Groups = *(*[]string)(unsafe.Pointer(&in.Groups))
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Convert_v1beta2_BootstrapToken_To_kubeadm_BootstrapToken is an autogenerated conversion function.
|
|
||||||
func Convert_v1beta2_BootstrapToken_To_kubeadm_BootstrapToken(in *BootstrapToken, out *kubeadm.BootstrapToken, s conversion.Scope) error {
|
|
||||||
return autoConvert_v1beta2_BootstrapToken_To_kubeadm_BootstrapToken(in, out, s)
|
|
||||||
}
|
|
||||||
|
|
||||||
func autoConvert_kubeadm_BootstrapToken_To_v1beta2_BootstrapToken(in *kubeadm.BootstrapToken, out *BootstrapToken, s conversion.Scope) error {
|
|
||||||
out.Token = (*BootstrapTokenString)(unsafe.Pointer(in.Token))
|
|
||||||
out.Description = in.Description
|
|
||||||
out.TTL = (*v1.Duration)(unsafe.Pointer(in.TTL))
|
|
||||||
out.Expires = (*v1.Time)(unsafe.Pointer(in.Expires))
|
|
||||||
out.Usages = *(*[]string)(unsafe.Pointer(&in.Usages))
|
|
||||||
out.Groups = *(*[]string)(unsafe.Pointer(&in.Groups))
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Convert_kubeadm_BootstrapToken_To_v1beta2_BootstrapToken is an autogenerated conversion function.
|
|
||||||
func Convert_kubeadm_BootstrapToken_To_v1beta2_BootstrapToken(in *kubeadm.BootstrapToken, out *BootstrapToken, s conversion.Scope) error {
|
|
||||||
return autoConvert_kubeadm_BootstrapToken_To_v1beta2_BootstrapToken(in, out, s)
|
|
||||||
}
|
|
||||||
|
|
||||||
func autoConvert_v1beta2_BootstrapTokenDiscovery_To_kubeadm_BootstrapTokenDiscovery(in *BootstrapTokenDiscovery, out *kubeadm.BootstrapTokenDiscovery, s conversion.Scope) error {
|
func autoConvert_v1beta2_BootstrapTokenDiscovery_To_kubeadm_BootstrapTokenDiscovery(in *BootstrapTokenDiscovery, out *kubeadm.BootstrapTokenDiscovery, s conversion.Scope) error {
|
||||||
out.Token = in.Token
|
out.Token = in.Token
|
||||||
out.APIServerEndpoint = in.APIServerEndpoint
|
out.APIServerEndpoint = in.APIServerEndpoint
|
||||||
@ -346,28 +297,6 @@ func Convert_kubeadm_BootstrapTokenDiscovery_To_v1beta2_BootstrapTokenDiscovery(
|
|||||||
return autoConvert_kubeadm_BootstrapTokenDiscovery_To_v1beta2_BootstrapTokenDiscovery(in, out, s)
|
return autoConvert_kubeadm_BootstrapTokenDiscovery_To_v1beta2_BootstrapTokenDiscovery(in, out, s)
|
||||||
}
|
}
|
||||||
|
|
||||||
func autoConvert_v1beta2_BootstrapTokenString_To_kubeadm_BootstrapTokenString(in *BootstrapTokenString, out *kubeadm.BootstrapTokenString, s conversion.Scope) error {
|
|
||||||
out.ID = in.ID
|
|
||||||
out.Secret = in.Secret
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Convert_v1beta2_BootstrapTokenString_To_kubeadm_BootstrapTokenString is an autogenerated conversion function.
|
|
||||||
func Convert_v1beta2_BootstrapTokenString_To_kubeadm_BootstrapTokenString(in *BootstrapTokenString, out *kubeadm.BootstrapTokenString, s conversion.Scope) error {
|
|
||||||
return autoConvert_v1beta2_BootstrapTokenString_To_kubeadm_BootstrapTokenString(in, out, s)
|
|
||||||
}
|
|
||||||
|
|
||||||
func autoConvert_kubeadm_BootstrapTokenString_To_v1beta2_BootstrapTokenString(in *kubeadm.BootstrapTokenString, out *BootstrapTokenString, s conversion.Scope) error {
|
|
||||||
out.ID = in.ID
|
|
||||||
out.Secret = in.Secret
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Convert_kubeadm_BootstrapTokenString_To_v1beta2_BootstrapTokenString is an autogenerated conversion function.
|
|
||||||
func Convert_kubeadm_BootstrapTokenString_To_v1beta2_BootstrapTokenString(in *kubeadm.BootstrapTokenString, out *BootstrapTokenString, s conversion.Scope) error {
|
|
||||||
return autoConvert_kubeadm_BootstrapTokenString_To_v1beta2_BootstrapTokenString(in, out, s)
|
|
||||||
}
|
|
||||||
|
|
||||||
func autoConvert_v1beta2_ClusterConfiguration_To_kubeadm_ClusterConfiguration(in *ClusterConfiguration, out *kubeadm.ClusterConfiguration, s conversion.Scope) error {
|
func autoConvert_v1beta2_ClusterConfiguration_To_kubeadm_ClusterConfiguration(in *ClusterConfiguration, out *kubeadm.ClusterConfiguration, s conversion.Scope) error {
|
||||||
if err := Convert_v1beta2_Etcd_To_kubeadm_Etcd(&in.Etcd, &out.Etcd, s); err != nil {
|
if err := Convert_v1beta2_Etcd_To_kubeadm_Etcd(&in.Etcd, &out.Etcd, s); err != nil {
|
||||||
return err
|
return err
|
||||||
@ -625,7 +554,7 @@ func Convert_kubeadm_ImageMeta_To_v1beta2_ImageMeta(in *kubeadm.ImageMeta, out *
|
|||||||
}
|
}
|
||||||
|
|
||||||
func autoConvert_v1beta2_InitConfiguration_To_kubeadm_InitConfiguration(in *InitConfiguration, out *kubeadm.InitConfiguration, s conversion.Scope) error {
|
func autoConvert_v1beta2_InitConfiguration_To_kubeadm_InitConfiguration(in *InitConfiguration, out *kubeadm.InitConfiguration, s conversion.Scope) error {
|
||||||
out.BootstrapTokens = *(*[]kubeadm.BootstrapToken)(unsafe.Pointer(&in.BootstrapTokens))
|
out.BootstrapTokens = *(*[]bootstraptokenv1.BootstrapToken)(unsafe.Pointer(&in.BootstrapTokens))
|
||||||
if err := Convert_v1beta2_NodeRegistrationOptions_To_kubeadm_NodeRegistrationOptions(&in.NodeRegistration, &out.NodeRegistration, s); err != nil {
|
if err := Convert_v1beta2_NodeRegistrationOptions_To_kubeadm_NodeRegistrationOptions(&in.NodeRegistration, &out.NodeRegistration, s); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -1,88 +0,0 @@
|
|||||||
/*
|
|
||||||
Copyright 2021 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 v1beta3
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/pkg/errors"
|
|
||||||
|
|
||||||
bootstrapapi "k8s.io/cluster-bootstrap/token/api"
|
|
||||||
bootstraputil "k8s.io/cluster-bootstrap/token/util"
|
|
||||||
)
|
|
||||||
|
|
||||||
// BootstrapTokenString is a token of the format abcdef.abcdef0123456789 that is used
|
|
||||||
// for both validation of the practically of the API server from a joining node's point
|
|
||||||
// of view and as an authentication method for the node in the bootstrap phase of
|
|
||||||
// "kubeadm join". This token is and should be short-lived
|
|
||||||
type BootstrapTokenString struct {
|
|
||||||
ID string `json:"-"`
|
|
||||||
Secret string `json:"-" datapolicy:"token"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// MarshalJSON implements the json.Marshaler interface.
|
|
||||||
func (bts BootstrapTokenString) MarshalJSON() ([]byte, error) {
|
|
||||||
return []byte(fmt.Sprintf(`"%s"`, bts.String())), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// UnmarshalJSON implements the json.Unmarshaller interface.
|
|
||||||
func (bts *BootstrapTokenString) UnmarshalJSON(b []byte) error {
|
|
||||||
// If the token is represented as "", just return quickly without an error
|
|
||||||
if len(b) == 0 {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Remove unnecessary " characters coming from the JSON parser
|
|
||||||
token := strings.Replace(string(b), `"`, ``, -1)
|
|
||||||
// Convert the string Token to a BootstrapTokenString object
|
|
||||||
newbts, err := NewBootstrapTokenString(token)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
bts.ID = newbts.ID
|
|
||||||
bts.Secret = newbts.Secret
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// String returns the string representation of the BootstrapTokenString
|
|
||||||
func (bts BootstrapTokenString) String() string {
|
|
||||||
if len(bts.ID) > 0 && len(bts.Secret) > 0 {
|
|
||||||
return bootstraputil.TokenFromIDAndSecret(bts.ID, bts.Secret)
|
|
||||||
}
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewBootstrapTokenString converts the given Bootstrap Token as a string
|
|
||||||
// to the BootstrapTokenString object used for serialization/deserialization
|
|
||||||
// and internal usage. It also automatically validates that the given token
|
|
||||||
// is of the right format
|
|
||||||
func NewBootstrapTokenString(token string) (*BootstrapTokenString, error) {
|
|
||||||
substrs := bootstraputil.BootstrapTokenRegexp.FindStringSubmatch(token)
|
|
||||||
// TODO: Add a constant for the 3 value here, and explain better why it's needed (other than because how the regexp parsin works)
|
|
||||||
if len(substrs) != 3 {
|
|
||||||
return nil, errors.Errorf("the bootstrap token %q was not of the form %q", token, bootstrapapi.BootstrapTokenPattern)
|
|
||||||
}
|
|
||||||
|
|
||||||
return &BootstrapTokenString{ID: substrs[1], Secret: substrs[2]}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewBootstrapTokenStringFromIDAndSecret is a wrapper around NewBootstrapTokenString
|
|
||||||
// that allows the caller to specify the ID and Secret separately
|
|
||||||
func NewBootstrapTokenStringFromIDAndSecret(id, secret string) (*BootstrapTokenString, error) {
|
|
||||||
return NewBootstrapTokenString(bootstraputil.TokenFromIDAndSecret(id, secret))
|
|
||||||
}
|
|
@ -1,249 +0,0 @@
|
|||||||
/*
|
|
||||||
Copyright 2021 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 v1beta3
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/json"
|
|
||||||
"reflect"
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"github.com/pkg/errors"
|
|
||||||
)
|
|
||||||
|
|
||||||
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 {
|
|
||||||
t.Run(rt.bts.ID, func(t *testing.T) {
|
|
||||||
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 {
|
|
||||||
t.Run(rt.input, func(t *testing.T) {
|
|
||||||
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 {
|
|
||||||
t.Run(rt.input, func(t *testing.T) {
|
|
||||||
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 errors.Wrap(err, "expected no unmarshal error, got error")
|
|
||||||
}
|
|
||||||
if b, err = json.Marshal(newbts); err != nil {
|
|
||||||
return errors.Wrap(err, "expected no marshal error, got error")
|
|
||||||
}
|
|
||||||
if input != string(b) {
|
|
||||||
return errors.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 errors.Wrap(err, "expected no marshal error, got error")
|
|
||||||
}
|
|
||||||
if err := json.Unmarshal(b, newbts); err != nil {
|
|
||||||
return errors.Wrap(err, "expected no unmarshal error, got error")
|
|
||||||
}
|
|
||||||
if !reflect.DeepEqual(bts, newbts) {
|
|
||||||
return errors.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 {
|
|
||||||
t.Run(rt.bts.ID, func(t *testing.T) {
|
|
||||||
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 {
|
|
||||||
t.Run(rt.token, func(t *testing.T) {
|
|
||||||
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 {
|
|
||||||
t.Run(rt.id, func(t *testing.T) {
|
|
||||||
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,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
@ -22,6 +22,7 @@ import (
|
|||||||
|
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
"k8s.io/apimachinery/pkg/runtime"
|
"k8s.io/apimachinery/pkg/runtime"
|
||||||
|
bootstraptokenv1 "k8s.io/kubernetes/cmd/kubeadm/app/apis/bootstraptoken/v1"
|
||||||
"k8s.io/kubernetes/cmd/kubeadm/app/constants"
|
"k8s.io/kubernetes/cmd/kubeadm/app/constants"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -174,7 +175,7 @@ func SetDefaults_FileDiscovery(obj *FileDiscovery) {
|
|||||||
func SetDefaults_BootstrapTokens(obj *InitConfiguration) {
|
func SetDefaults_BootstrapTokens(obj *InitConfiguration) {
|
||||||
|
|
||||||
if obj.BootstrapTokens == nil || len(obj.BootstrapTokens) == 0 {
|
if obj.BootstrapTokens == nil || len(obj.BootstrapTokens) == 0 {
|
||||||
obj.BootstrapTokens = []BootstrapToken{{}}
|
obj.BootstrapTokens = []bootstraptokenv1.BootstrapToken{{}}
|
||||||
}
|
}
|
||||||
|
|
||||||
for i := range obj.BootstrapTokens {
|
for i := range obj.BootstrapTokens {
|
||||||
@ -183,7 +184,7 @@ func SetDefaults_BootstrapTokens(obj *InitConfiguration) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// SetDefaults_BootstrapToken sets the defaults for an individual Bootstrap Token
|
// SetDefaults_BootstrapToken sets the defaults for an individual Bootstrap Token
|
||||||
func SetDefaults_BootstrapToken(bt *BootstrapToken) {
|
func SetDefaults_BootstrapToken(bt *bootstraptokenv1.BootstrapToken) {
|
||||||
if bt.TTL == nil {
|
if bt.TTL == nil {
|
||||||
bt.TTL = &metav1.Duration{
|
bt.TTL = &metav1.Duration{
|
||||||
Duration: constants.DefaultTokenDuration,
|
Duration: constants.DefaultTokenDuration,
|
||||||
|
@ -36,6 +36,8 @@ limitations under the License.
|
|||||||
// "IfNotPresent". "IfNotPresent" is the default, which has been the existing behavior prior to this addition.
|
// "IfNotPresent". "IfNotPresent" is the default, which has been the existing behavior prior to this addition.
|
||||||
// - Add "InitConfiguration.Patches.Directory", "JoinConfiguration.Patches.Directory" to allow
|
// - Add "InitConfiguration.Patches.Directory", "JoinConfiguration.Patches.Directory" to allow
|
||||||
// the user to configure a directory from which to take patches for components deployed by kubeadm.
|
// the user to configure a directory from which to take patches for components deployed by kubeadm.
|
||||||
|
// - Move the BootstrapToken* API and related utilities out of the "kubeadm" API group to a new group
|
||||||
|
// "bootstraptoken". The kubeadm API version v1beta3 no longer contains the BootstrapToken* structures.
|
||||||
//
|
//
|
||||||
// Migration from old kubeadm config versions
|
// Migration from old kubeadm config versions
|
||||||
//
|
//
|
||||||
|
@ -17,8 +17,9 @@ limitations under the License.
|
|||||||
package v1beta3
|
package v1beta3
|
||||||
|
|
||||||
import (
|
import (
|
||||||
v1 "k8s.io/api/core/v1"
|
corev1 "k8s.io/api/core/v1"
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
|
bootstraptokenv1 "k8s.io/kubernetes/cmd/kubeadm/app/apis/bootstraptoken/v1"
|
||||||
)
|
)
|
||||||
|
|
||||||
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
|
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
|
||||||
@ -35,7 +36,7 @@ type InitConfiguration struct {
|
|||||||
// BootstrapTokens is respected at `kubeadm init` time and describes a set of Bootstrap Tokens to create.
|
// BootstrapTokens is respected at `kubeadm init` time and describes a set of Bootstrap Tokens to create.
|
||||||
// This information IS NOT uploaded to the kubeadm cluster configmap, partly because of its sensitive nature
|
// This information IS NOT uploaded to the kubeadm cluster configmap, partly because of its sensitive nature
|
||||||
// +optional
|
// +optional
|
||||||
BootstrapTokens []BootstrapToken `json:"bootstrapTokens,omitempty"`
|
BootstrapTokens []bootstraptokenv1.BootstrapToken `json:"bootstrapTokens,omitempty"`
|
||||||
|
|
||||||
// NodeRegistration holds fields that relate to registering the new control-plane node to the cluster
|
// NodeRegistration holds fields that relate to registering the new control-plane node to the cluster
|
||||||
// +optional
|
// +optional
|
||||||
@ -216,7 +217,7 @@ type NodeRegistrationOptions struct {
|
|||||||
// Taints specifies the taints the Node API object should be registered with. If this field is unset, i.e. nil, in the `kubeadm init` process
|
// Taints specifies the taints the Node API object should be registered with. If this field is unset, i.e. nil, in the `kubeadm init` process
|
||||||
// it will be defaulted to []v1.Taint{'node-role.kubernetes.io/master=""'}. If you don't want to taint your control-plane node, set this field to an
|
// it will be defaulted to []v1.Taint{'node-role.kubernetes.io/master=""'}. If you don't want to taint your control-plane node, set this field to an
|
||||||
// empty slice, i.e. `taints: []` in the YAML file. This field is solely used for Node registration.
|
// empty slice, i.e. `taints: []` in the YAML file. This field is solely used for Node registration.
|
||||||
Taints []v1.Taint `json:"taints"`
|
Taints []corev1.Taint `json:"taints"`
|
||||||
|
|
||||||
// KubeletExtraArgs passes through extra arguments to the kubelet. The arguments here are passed to the kubelet command line via the environment file
|
// KubeletExtraArgs passes through extra arguments to the kubelet. The arguments here are passed to the kubelet command line via the environment file
|
||||||
// kubeadm writes at runtime for the kubelet to source. This overrides the generic base-level configuration in the kubelet-config-1.X ConfigMap
|
// kubeadm writes at runtime for the kubelet to source. This overrides the generic base-level configuration in the kubelet-config-1.X ConfigMap
|
||||||
@ -234,7 +235,7 @@ type NodeRegistrationOptions struct {
|
|||||||
// The value of this field must be one of "Always", "IfNotPresent" or "Never".
|
// The value of this field must be one of "Always", "IfNotPresent" or "Never".
|
||||||
// If this field is unset kubeadm will default it to "IfNotPresent", or pull the required images if not present on the host.
|
// If this field is unset kubeadm will default it to "IfNotPresent", or pull the required images if not present on the host.
|
||||||
// +optional
|
// +optional
|
||||||
ImagePullPolicy v1.PullPolicy `json:"imagePullPolicy,omitempty"`
|
ImagePullPolicy corev1.PullPolicy `json:"imagePullPolicy,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// Networking contains elements describing cluster's networking configuration
|
// Networking contains elements describing cluster's networking configuration
|
||||||
@ -250,33 +251,6 @@ type Networking struct {
|
|||||||
DNSDomain string `json:"dnsDomain,omitempty"`
|
DNSDomain string `json:"dnsDomain,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// BootstrapToken describes one bootstrap token, stored as a Secret in the cluster
|
|
||||||
type BootstrapToken struct {
|
|
||||||
// Token is used for establishing bidirectional trust between nodes and control-planes.
|
|
||||||
// Used for joining nodes in the cluster.
|
|
||||||
Token *BootstrapTokenString `json:"token" datapolicy:"token"`
|
|
||||||
// Description sets a human-friendly message why this token exists and what it's used
|
|
||||||
// for, so other administrators can know its purpose.
|
|
||||||
// +optional
|
|
||||||
Description string `json:"description,omitempty"`
|
|
||||||
// TTL defines the time to live for this token. Defaults to 24h.
|
|
||||||
// Expires and TTL are mutually exclusive.
|
|
||||||
// +optional
|
|
||||||
TTL *metav1.Duration `json:"ttl,omitempty"`
|
|
||||||
// Expires specifies the timestamp when this token expires. Defaults to being set
|
|
||||||
// dynamically at runtime based on the TTL. Expires and TTL are mutually exclusive.
|
|
||||||
// +optional
|
|
||||||
Expires *metav1.Time `json:"expires,omitempty"`
|
|
||||||
// Usages describes the ways in which this token can be used. Can by default be used
|
|
||||||
// for establishing bidirectional trust, but that can be changed here.
|
|
||||||
// +optional
|
|
||||||
Usages []string `json:"usages,omitempty"`
|
|
||||||
// Groups specifies the extra groups that this token will authenticate as when/if
|
|
||||||
// used for authentication
|
|
||||||
// +optional
|
|
||||||
Groups []string `json:"groups,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// Etcd contains elements describing Etcd configuration.
|
// Etcd contains elements describing Etcd configuration.
|
||||||
type Etcd struct {
|
type Etcd struct {
|
||||||
|
|
||||||
@ -453,7 +427,7 @@ type HostPathMount struct {
|
|||||||
ReadOnly bool `json:"readOnly,omitempty"`
|
ReadOnly bool `json:"readOnly,omitempty"`
|
||||||
// PathType is the type of the HostPath.
|
// PathType is the type of the HostPath.
|
||||||
// +optional
|
// +optional
|
||||||
PathType v1.HostPathType `json:"pathType,omitempty"`
|
PathType corev1.HostPathType `json:"pathType,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// Patches contains options related to applying patches to components deployed by kubeadm.
|
// Patches contains options related to applying patches to components deployed by kubeadm.
|
||||||
|
@ -27,6 +27,7 @@ import (
|
|||||||
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
conversion "k8s.io/apimachinery/pkg/conversion"
|
conversion "k8s.io/apimachinery/pkg/conversion"
|
||||||
runtime "k8s.io/apimachinery/pkg/runtime"
|
runtime "k8s.io/apimachinery/pkg/runtime"
|
||||||
|
bootstraptokenv1 "k8s.io/kubernetes/cmd/kubeadm/app/apis/bootstraptoken/v1"
|
||||||
kubeadm "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
|
kubeadm "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -57,16 +58,6 @@ func RegisterConversions(s *runtime.Scheme) error {
|
|||||||
}); err != nil {
|
}); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if err := s.AddGeneratedConversionFunc((*BootstrapToken)(nil), (*kubeadm.BootstrapToken)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
|
||||||
return Convert_v1beta3_BootstrapToken_To_kubeadm_BootstrapToken(a.(*BootstrapToken), b.(*kubeadm.BootstrapToken), scope)
|
|
||||||
}); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if err := s.AddGeneratedConversionFunc((*kubeadm.BootstrapToken)(nil), (*BootstrapToken)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
|
||||||
return Convert_kubeadm_BootstrapToken_To_v1beta3_BootstrapToken(a.(*kubeadm.BootstrapToken), b.(*BootstrapToken), scope)
|
|
||||||
}); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if err := s.AddGeneratedConversionFunc((*BootstrapTokenDiscovery)(nil), (*kubeadm.BootstrapTokenDiscovery)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
if err := s.AddGeneratedConversionFunc((*BootstrapTokenDiscovery)(nil), (*kubeadm.BootstrapTokenDiscovery)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||||
return Convert_v1beta3_BootstrapTokenDiscovery_To_kubeadm_BootstrapTokenDiscovery(a.(*BootstrapTokenDiscovery), b.(*kubeadm.BootstrapTokenDiscovery), scope)
|
return Convert_v1beta3_BootstrapTokenDiscovery_To_kubeadm_BootstrapTokenDiscovery(a.(*BootstrapTokenDiscovery), b.(*kubeadm.BootstrapTokenDiscovery), scope)
|
||||||
}); err != nil {
|
}); err != nil {
|
||||||
@ -77,16 +68,6 @@ func RegisterConversions(s *runtime.Scheme) error {
|
|||||||
}); err != nil {
|
}); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if err := s.AddGeneratedConversionFunc((*BootstrapTokenString)(nil), (*kubeadm.BootstrapTokenString)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
|
||||||
return Convert_v1beta3_BootstrapTokenString_To_kubeadm_BootstrapTokenString(a.(*BootstrapTokenString), b.(*kubeadm.BootstrapTokenString), scope)
|
|
||||||
}); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if err := s.AddGeneratedConversionFunc((*kubeadm.BootstrapTokenString)(nil), (*BootstrapTokenString)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
|
||||||
return Convert_kubeadm_BootstrapTokenString_To_v1beta3_BootstrapTokenString(a.(*kubeadm.BootstrapTokenString), b.(*BootstrapTokenString), scope)
|
|
||||||
}); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if err := s.AddGeneratedConversionFunc((*kubeadm.ClusterConfiguration)(nil), (*ClusterConfiguration)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
if err := s.AddGeneratedConversionFunc((*kubeadm.ClusterConfiguration)(nil), (*ClusterConfiguration)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||||
return Convert_kubeadm_ClusterConfiguration_To_v1beta3_ClusterConfiguration(a.(*kubeadm.ClusterConfiguration), b.(*ClusterConfiguration), scope)
|
return Convert_kubeadm_ClusterConfiguration_To_v1beta3_ClusterConfiguration(a.(*kubeadm.ClusterConfiguration), b.(*ClusterConfiguration), scope)
|
||||||
}); err != nil {
|
}); err != nil {
|
||||||
@ -300,36 +281,6 @@ func Convert_kubeadm_APIServer_To_v1beta3_APIServer(in *kubeadm.APIServer, out *
|
|||||||
return autoConvert_kubeadm_APIServer_To_v1beta3_APIServer(in, out, s)
|
return autoConvert_kubeadm_APIServer_To_v1beta3_APIServer(in, out, s)
|
||||||
}
|
}
|
||||||
|
|
||||||
func autoConvert_v1beta3_BootstrapToken_To_kubeadm_BootstrapToken(in *BootstrapToken, out *kubeadm.BootstrapToken, s conversion.Scope) error {
|
|
||||||
out.Token = (*kubeadm.BootstrapTokenString)(unsafe.Pointer(in.Token))
|
|
||||||
out.Description = in.Description
|
|
||||||
out.TTL = (*v1.Duration)(unsafe.Pointer(in.TTL))
|
|
||||||
out.Expires = (*v1.Time)(unsafe.Pointer(in.Expires))
|
|
||||||
out.Usages = *(*[]string)(unsafe.Pointer(&in.Usages))
|
|
||||||
out.Groups = *(*[]string)(unsafe.Pointer(&in.Groups))
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Convert_v1beta3_BootstrapToken_To_kubeadm_BootstrapToken is an autogenerated conversion function.
|
|
||||||
func Convert_v1beta3_BootstrapToken_To_kubeadm_BootstrapToken(in *BootstrapToken, out *kubeadm.BootstrapToken, s conversion.Scope) error {
|
|
||||||
return autoConvert_v1beta3_BootstrapToken_To_kubeadm_BootstrapToken(in, out, s)
|
|
||||||
}
|
|
||||||
|
|
||||||
func autoConvert_kubeadm_BootstrapToken_To_v1beta3_BootstrapToken(in *kubeadm.BootstrapToken, out *BootstrapToken, s conversion.Scope) error {
|
|
||||||
out.Token = (*BootstrapTokenString)(unsafe.Pointer(in.Token))
|
|
||||||
out.Description = in.Description
|
|
||||||
out.TTL = (*v1.Duration)(unsafe.Pointer(in.TTL))
|
|
||||||
out.Expires = (*v1.Time)(unsafe.Pointer(in.Expires))
|
|
||||||
out.Usages = *(*[]string)(unsafe.Pointer(&in.Usages))
|
|
||||||
out.Groups = *(*[]string)(unsafe.Pointer(&in.Groups))
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Convert_kubeadm_BootstrapToken_To_v1beta3_BootstrapToken is an autogenerated conversion function.
|
|
||||||
func Convert_kubeadm_BootstrapToken_To_v1beta3_BootstrapToken(in *kubeadm.BootstrapToken, out *BootstrapToken, s conversion.Scope) error {
|
|
||||||
return autoConvert_kubeadm_BootstrapToken_To_v1beta3_BootstrapToken(in, out, s)
|
|
||||||
}
|
|
||||||
|
|
||||||
func autoConvert_v1beta3_BootstrapTokenDiscovery_To_kubeadm_BootstrapTokenDiscovery(in *BootstrapTokenDiscovery, out *kubeadm.BootstrapTokenDiscovery, s conversion.Scope) error {
|
func autoConvert_v1beta3_BootstrapTokenDiscovery_To_kubeadm_BootstrapTokenDiscovery(in *BootstrapTokenDiscovery, out *kubeadm.BootstrapTokenDiscovery, s conversion.Scope) error {
|
||||||
out.Token = in.Token
|
out.Token = in.Token
|
||||||
out.APIServerEndpoint = in.APIServerEndpoint
|
out.APIServerEndpoint = in.APIServerEndpoint
|
||||||
@ -356,28 +307,6 @@ func Convert_kubeadm_BootstrapTokenDiscovery_To_v1beta3_BootstrapTokenDiscovery(
|
|||||||
return autoConvert_kubeadm_BootstrapTokenDiscovery_To_v1beta3_BootstrapTokenDiscovery(in, out, s)
|
return autoConvert_kubeadm_BootstrapTokenDiscovery_To_v1beta3_BootstrapTokenDiscovery(in, out, s)
|
||||||
}
|
}
|
||||||
|
|
||||||
func autoConvert_v1beta3_BootstrapTokenString_To_kubeadm_BootstrapTokenString(in *BootstrapTokenString, out *kubeadm.BootstrapTokenString, s conversion.Scope) error {
|
|
||||||
out.ID = in.ID
|
|
||||||
out.Secret = in.Secret
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Convert_v1beta3_BootstrapTokenString_To_kubeadm_BootstrapTokenString is an autogenerated conversion function.
|
|
||||||
func Convert_v1beta3_BootstrapTokenString_To_kubeadm_BootstrapTokenString(in *BootstrapTokenString, out *kubeadm.BootstrapTokenString, s conversion.Scope) error {
|
|
||||||
return autoConvert_v1beta3_BootstrapTokenString_To_kubeadm_BootstrapTokenString(in, out, s)
|
|
||||||
}
|
|
||||||
|
|
||||||
func autoConvert_kubeadm_BootstrapTokenString_To_v1beta3_BootstrapTokenString(in *kubeadm.BootstrapTokenString, out *BootstrapTokenString, s conversion.Scope) error {
|
|
||||||
out.ID = in.ID
|
|
||||||
out.Secret = in.Secret
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Convert_kubeadm_BootstrapTokenString_To_v1beta3_BootstrapTokenString is an autogenerated conversion function.
|
|
||||||
func Convert_kubeadm_BootstrapTokenString_To_v1beta3_BootstrapTokenString(in *kubeadm.BootstrapTokenString, out *BootstrapTokenString, s conversion.Scope) error {
|
|
||||||
return autoConvert_kubeadm_BootstrapTokenString_To_v1beta3_BootstrapTokenString(in, out, s)
|
|
||||||
}
|
|
||||||
|
|
||||||
func autoConvert_v1beta3_ClusterConfiguration_To_kubeadm_ClusterConfiguration(in *ClusterConfiguration, out *kubeadm.ClusterConfiguration, s conversion.Scope) error {
|
func autoConvert_v1beta3_ClusterConfiguration_To_kubeadm_ClusterConfiguration(in *ClusterConfiguration, out *kubeadm.ClusterConfiguration, s conversion.Scope) error {
|
||||||
if err := Convert_v1beta3_Etcd_To_kubeadm_Etcd(&in.Etcd, &out.Etcd, s); err != nil {
|
if err := Convert_v1beta3_Etcd_To_kubeadm_Etcd(&in.Etcd, &out.Etcd, s); err != nil {
|
||||||
return err
|
return err
|
||||||
@ -628,7 +557,7 @@ func Convert_kubeadm_ImageMeta_To_v1beta3_ImageMeta(in *kubeadm.ImageMeta, out *
|
|||||||
}
|
}
|
||||||
|
|
||||||
func autoConvert_v1beta3_InitConfiguration_To_kubeadm_InitConfiguration(in *InitConfiguration, out *kubeadm.InitConfiguration, s conversion.Scope) error {
|
func autoConvert_v1beta3_InitConfiguration_To_kubeadm_InitConfiguration(in *InitConfiguration, out *kubeadm.InitConfiguration, s conversion.Scope) error {
|
||||||
out.BootstrapTokens = *(*[]kubeadm.BootstrapToken)(unsafe.Pointer(&in.BootstrapTokens))
|
out.BootstrapTokens = *(*[]bootstraptokenv1.BootstrapToken)(unsafe.Pointer(&in.BootstrapTokens))
|
||||||
if err := Convert_v1beta3_NodeRegistrationOptions_To_kubeadm_NodeRegistrationOptions(&in.NodeRegistration, &out.NodeRegistration, s); err != nil {
|
if err := Convert_v1beta3_NodeRegistrationOptions_To_kubeadm_NodeRegistrationOptions(&in.NodeRegistration, &out.NodeRegistration, s); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -643,7 +572,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 {
|
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
|
// WARNING: in.ClusterConfiguration requires manual conversion: does not exist in peer-type
|
||||||
out.BootstrapTokens = *(*[]BootstrapToken)(unsafe.Pointer(&in.BootstrapTokens))
|
out.BootstrapTokens = *(*[]bootstraptokenv1.BootstrapToken)(unsafe.Pointer(&in.BootstrapTokens))
|
||||||
if err := Convert_kubeadm_NodeRegistrationOptions_To_v1beta3_NodeRegistrationOptions(&in.NodeRegistration, &out.NodeRegistration, s); err != nil {
|
if err := Convert_kubeadm_NodeRegistrationOptions_To_v1beta3_NodeRegistrationOptions(&in.NodeRegistration, &out.NodeRegistration, s); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -24,6 +24,7 @@ import (
|
|||||||
corev1 "k8s.io/api/core/v1"
|
corev1 "k8s.io/api/core/v1"
|
||||||
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
runtime "k8s.io/apimachinery/pkg/runtime"
|
runtime "k8s.io/apimachinery/pkg/runtime"
|
||||||
|
bootstraptokenv1 "k8s.io/kubernetes/cmd/kubeadm/app/apis/bootstraptoken/v1"
|
||||||
)
|
)
|
||||||
|
|
||||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||||
@ -69,46 +70,6 @@ func (in *APIServer) DeepCopy() *APIServer {
|
|||||||
return out
|
return out
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
|
||||||
func (in *BootstrapToken) DeepCopyInto(out *BootstrapToken) {
|
|
||||||
*out = *in
|
|
||||||
if in.Token != nil {
|
|
||||||
in, out := &in.Token, &out.Token
|
|
||||||
*out = new(BootstrapTokenString)
|
|
||||||
**out = **in
|
|
||||||
}
|
|
||||||
if in.TTL != nil {
|
|
||||||
in, out := &in.TTL, &out.TTL
|
|
||||||
*out = new(v1.Duration)
|
|
||||||
**out = **in
|
|
||||||
}
|
|
||||||
if in.Expires != nil {
|
|
||||||
in, out := &in.Expires, &out.Expires
|
|
||||||
*out = (*in).DeepCopy()
|
|
||||||
}
|
|
||||||
if in.Usages != nil {
|
|
||||||
in, out := &in.Usages, &out.Usages
|
|
||||||
*out = make([]string, len(*in))
|
|
||||||
copy(*out, *in)
|
|
||||||
}
|
|
||||||
if in.Groups != nil {
|
|
||||||
in, out := &in.Groups, &out.Groups
|
|
||||||
*out = make([]string, len(*in))
|
|
||||||
copy(*out, *in)
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new BootstrapToken.
|
|
||||||
func (in *BootstrapToken) DeepCopy() *BootstrapToken {
|
|
||||||
if in == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
out := new(BootstrapToken)
|
|
||||||
in.DeepCopyInto(out)
|
|
||||||
return out
|
|
||||||
}
|
|
||||||
|
|
||||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||||
func (in *BootstrapTokenDiscovery) DeepCopyInto(out *BootstrapTokenDiscovery) {
|
func (in *BootstrapTokenDiscovery) DeepCopyInto(out *BootstrapTokenDiscovery) {
|
||||||
*out = *in
|
*out = *in
|
||||||
@ -130,22 +91,6 @@ func (in *BootstrapTokenDiscovery) DeepCopy() *BootstrapTokenDiscovery {
|
|||||||
return out
|
return out
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
|
||||||
func (in *BootstrapTokenString) DeepCopyInto(out *BootstrapTokenString) {
|
|
||||||
*out = *in
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new BootstrapTokenString.
|
|
||||||
func (in *BootstrapTokenString) DeepCopy() *BootstrapTokenString {
|
|
||||||
if in == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
out := new(BootstrapTokenString)
|
|
||||||
in.DeepCopyInto(out)
|
|
||||||
return out
|
|
||||||
}
|
|
||||||
|
|
||||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||||
func (in *ClusterConfiguration) DeepCopyInto(out *ClusterConfiguration) {
|
func (in *ClusterConfiguration) DeepCopyInto(out *ClusterConfiguration) {
|
||||||
*out = *in
|
*out = *in
|
||||||
@ -361,7 +306,7 @@ func (in *InitConfiguration) DeepCopyInto(out *InitConfiguration) {
|
|||||||
out.TypeMeta = in.TypeMeta
|
out.TypeMeta = in.TypeMeta
|
||||||
if in.BootstrapTokens != nil {
|
if in.BootstrapTokens != nil {
|
||||||
in, out := &in.BootstrapTokens, &out.BootstrapTokens
|
in, out := &in.BootstrapTokens, &out.BootstrapTokens
|
||||||
*out = make([]BootstrapToken, len(*in))
|
*out = make([]bootstraptokenv1.BootstrapToken, len(*in))
|
||||||
for i := range *in {
|
for i := range *in {
|
||||||
(*in)[i].DeepCopyInto(&(*out)[i])
|
(*in)[i].DeepCopyInto(&(*out)[i])
|
||||||
}
|
}
|
||||||
|
@ -33,6 +33,7 @@ import (
|
|||||||
bootstrapapi "k8s.io/cluster-bootstrap/token/api"
|
bootstrapapi "k8s.io/cluster-bootstrap/token/api"
|
||||||
bootstraputil "k8s.io/cluster-bootstrap/token/util"
|
bootstraputil "k8s.io/cluster-bootstrap/token/util"
|
||||||
"k8s.io/klog/v2"
|
"k8s.io/klog/v2"
|
||||||
|
bootstraptokenv1 "k8s.io/kubernetes/cmd/kubeadm/app/apis/bootstraptoken/v1"
|
||||||
"k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
|
"k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
|
||||||
kubeadmapiv1 "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1beta3"
|
kubeadmapiv1 "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1beta3"
|
||||||
kubeadmcmdoptions "k8s.io/kubernetes/cmd/kubeadm/app/cmd/options"
|
kubeadmcmdoptions "k8s.io/kubernetes/cmd/kubeadm/app/cmd/options"
|
||||||
@ -203,7 +204,7 @@ func ValidateDiscoveryKubeConfigPath(discoveryFile string, fldPath *field.Path)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ValidateBootstrapTokens validates a slice of BootstrapToken objects
|
// ValidateBootstrapTokens validates a slice of BootstrapToken objects
|
||||||
func ValidateBootstrapTokens(bts []kubeadm.BootstrapToken, fldPath *field.Path) field.ErrorList {
|
func ValidateBootstrapTokens(bts []bootstraptokenv1.BootstrapToken, fldPath *field.Path) field.ErrorList {
|
||||||
allErrs := field.ErrorList{}
|
allErrs := field.ErrorList{}
|
||||||
for i, bt := range bts {
|
for i, bt := range bts {
|
||||||
btPath := fldPath.Child(fmt.Sprintf("%d", i))
|
btPath := fldPath.Child(fmt.Sprintf("%d", i))
|
||||||
|
@ -24,6 +24,7 @@ import (
|
|||||||
corev1 "k8s.io/api/core/v1"
|
corev1 "k8s.io/api/core/v1"
|
||||||
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
runtime "k8s.io/apimachinery/pkg/runtime"
|
runtime "k8s.io/apimachinery/pkg/runtime"
|
||||||
|
bootstraptokenv1 "k8s.io/kubernetes/cmd/kubeadm/app/apis/bootstraptoken/v1"
|
||||||
)
|
)
|
||||||
|
|
||||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||||
@ -69,46 +70,6 @@ func (in *APIServer) DeepCopy() *APIServer {
|
|||||||
return out
|
return out
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
|
||||||
func (in *BootstrapToken) DeepCopyInto(out *BootstrapToken) {
|
|
||||||
*out = *in
|
|
||||||
if in.Token != nil {
|
|
||||||
in, out := &in.Token, &out.Token
|
|
||||||
*out = new(BootstrapTokenString)
|
|
||||||
**out = **in
|
|
||||||
}
|
|
||||||
if in.TTL != nil {
|
|
||||||
in, out := &in.TTL, &out.TTL
|
|
||||||
*out = new(v1.Duration)
|
|
||||||
**out = **in
|
|
||||||
}
|
|
||||||
if in.Expires != nil {
|
|
||||||
in, out := &in.Expires, &out.Expires
|
|
||||||
*out = (*in).DeepCopy()
|
|
||||||
}
|
|
||||||
if in.Usages != nil {
|
|
||||||
in, out := &in.Usages, &out.Usages
|
|
||||||
*out = make([]string, len(*in))
|
|
||||||
copy(*out, *in)
|
|
||||||
}
|
|
||||||
if in.Groups != nil {
|
|
||||||
in, out := &in.Groups, &out.Groups
|
|
||||||
*out = make([]string, len(*in))
|
|
||||||
copy(*out, *in)
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new BootstrapToken.
|
|
||||||
func (in *BootstrapToken) DeepCopy() *BootstrapToken {
|
|
||||||
if in == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
out := new(BootstrapToken)
|
|
||||||
in.DeepCopyInto(out)
|
|
||||||
return out
|
|
||||||
}
|
|
||||||
|
|
||||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||||
func (in *BootstrapTokenDiscovery) DeepCopyInto(out *BootstrapTokenDiscovery) {
|
func (in *BootstrapTokenDiscovery) DeepCopyInto(out *BootstrapTokenDiscovery) {
|
||||||
*out = *in
|
*out = *in
|
||||||
@ -130,22 +91,6 @@ func (in *BootstrapTokenDiscovery) DeepCopy() *BootstrapTokenDiscovery {
|
|||||||
return out
|
return out
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
|
||||||
func (in *BootstrapTokenString) DeepCopyInto(out *BootstrapTokenString) {
|
|
||||||
*out = *in
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new BootstrapTokenString.
|
|
||||||
func (in *BootstrapTokenString) DeepCopy() *BootstrapTokenString {
|
|
||||||
if in == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
out := new(BootstrapTokenString)
|
|
||||||
in.DeepCopyInto(out)
|
|
||||||
return out
|
|
||||||
}
|
|
||||||
|
|
||||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||||
func (in *ClusterConfiguration) DeepCopyInto(out *ClusterConfiguration) {
|
func (in *ClusterConfiguration) DeepCopyInto(out *ClusterConfiguration) {
|
||||||
*out = *in
|
*out = *in
|
||||||
@ -391,7 +336,7 @@ func (in *InitConfiguration) DeepCopyInto(out *InitConfiguration) {
|
|||||||
in.ClusterConfiguration.DeepCopyInto(&out.ClusterConfiguration)
|
in.ClusterConfiguration.DeepCopyInto(&out.ClusterConfiguration)
|
||||||
if in.BootstrapTokens != nil {
|
if in.BootstrapTokens != nil {
|
||||||
in, out := &in.BootstrapTokens, &out.BootstrapTokens
|
in, out := &in.BootstrapTokens, &out.BootstrapTokens
|
||||||
*out = make([]BootstrapToken, len(*in))
|
*out = make([]bootstraptokenv1.BootstrapToken, len(*in))
|
||||||
for i := range *in {
|
for i := range *in {
|
||||||
(*in)[i].DeepCopyInto(&(*out)[i])
|
(*in)[i].DeepCopyInto(&(*out)[i])
|
||||||
}
|
}
|
||||||
|
@ -23,13 +23,14 @@ import (
|
|||||||
"github.com/spf13/pflag"
|
"github.com/spf13/pflag"
|
||||||
|
|
||||||
bootstrapapi "k8s.io/cluster-bootstrap/token/api"
|
bootstrapapi "k8s.io/cluster-bootstrap/token/api"
|
||||||
|
bootstraptokenv1 "k8s.io/kubernetes/cmd/kubeadm/app/apis/bootstraptoken/v1"
|
||||||
kubeadmapiv1 "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1beta3"
|
kubeadmapiv1 "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1beta3"
|
||||||
kubeadmconstants "k8s.io/kubernetes/cmd/kubeadm/app/constants"
|
kubeadmconstants "k8s.io/kubernetes/cmd/kubeadm/app/constants"
|
||||||
)
|
)
|
||||||
|
|
||||||
// NewBootstrapTokenOptions creates a new BootstrapTokenOptions object with the default values
|
// NewBootstrapTokenOptions creates a new BootstrapTokenOptions object with the default values
|
||||||
func NewBootstrapTokenOptions() *BootstrapTokenOptions {
|
func NewBootstrapTokenOptions() *BootstrapTokenOptions {
|
||||||
bto := &BootstrapTokenOptions{&kubeadmapiv1.BootstrapToken{}, ""}
|
bto := &BootstrapTokenOptions{&bootstraptokenv1.BootstrapToken{}, ""}
|
||||||
kubeadmapiv1.SetDefaults_BootstrapToken(bto.BootstrapToken)
|
kubeadmapiv1.SetDefaults_BootstrapToken(bto.BootstrapToken)
|
||||||
return bto
|
return bto
|
||||||
}
|
}
|
||||||
@ -38,7 +39,7 @@ func NewBootstrapTokenOptions() *BootstrapTokenOptions {
|
|||||||
// and applying the parsed flags to a InitConfiguration object later at runtime
|
// and applying the parsed flags to a InitConfiguration object later at runtime
|
||||||
// TODO: In the future, we might want to group the flags in a better way than adding them all individually like this
|
// TODO: In the future, we might want to group the flags in a better way than adding them all individually like this
|
||||||
type BootstrapTokenOptions struct {
|
type BootstrapTokenOptions struct {
|
||||||
*kubeadmapiv1.BootstrapToken
|
*bootstraptokenv1.BootstrapToken
|
||||||
TokenStr string `datapolicy:"token"`
|
TokenStr string `datapolicy:"token"`
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -92,13 +93,13 @@ func (bto *BootstrapTokenOptions) AddDescriptionFlag(fs *pflag.FlagSet) {
|
|||||||
func (bto *BootstrapTokenOptions) ApplyTo(cfg *kubeadmapiv1.InitConfiguration) error {
|
func (bto *BootstrapTokenOptions) ApplyTo(cfg *kubeadmapiv1.InitConfiguration) error {
|
||||||
if len(bto.TokenStr) > 0 {
|
if len(bto.TokenStr) > 0 {
|
||||||
var err error
|
var err error
|
||||||
bto.Token, err = kubeadmapiv1.NewBootstrapTokenString(bto.TokenStr)
|
bto.Token, err = bootstraptokenv1.NewBootstrapTokenString(bto.TokenStr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set the token specified by the flags as the first and only token to create in case --config is not specified
|
// Set the token specified by the flags as the first and only token to create in case --config is not specified
|
||||||
cfg.BootstrapTokens = []kubeadmapiv1.BootstrapToken{*bto.BootstrapToken}
|
cfg.BootstrapTokens = []bootstraptokenv1.BootstrapToken{*bto.BootstrapToken}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -38,7 +38,7 @@ import (
|
|||||||
bootstrapapi "k8s.io/cluster-bootstrap/token/api"
|
bootstrapapi "k8s.io/cluster-bootstrap/token/api"
|
||||||
bootstraputil "k8s.io/cluster-bootstrap/token/util"
|
bootstraputil "k8s.io/cluster-bootstrap/token/util"
|
||||||
"k8s.io/klog/v2"
|
"k8s.io/klog/v2"
|
||||||
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
|
bootstraptokenv1 "k8s.io/kubernetes/cmd/kubeadm/app/apis/bootstraptoken/v1"
|
||||||
kubeadmscheme "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/scheme"
|
kubeadmscheme "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/scheme"
|
||||||
kubeadmapiv1beta2 "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1beta2"
|
kubeadmapiv1beta2 "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1beta2"
|
||||||
kubeadmapiv1 "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1beta3"
|
kubeadmapiv1 "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1beta3"
|
||||||
@ -383,7 +383,7 @@ func RunListTokens(out io.Writer, errW io.Writer, client clientset.Interface, pr
|
|||||||
|
|
||||||
for _, secret := range secrets.Items {
|
for _, secret := range secrets.Items {
|
||||||
// Get the BootstrapToken struct representation from the Secret object
|
// Get the BootstrapToken struct representation from the Secret object
|
||||||
token, err := kubeadmapi.BootstrapTokenFromSecret(&secret)
|
token, err := bootstraptokenv1.BootstrapTokenFromSecret(&secret)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Fprintf(errW, "%v", err)
|
fmt.Fprintf(errW, "%v", err)
|
||||||
continue
|
continue
|
||||||
@ -416,7 +416,7 @@ func RunDeleteTokens(out io.Writer, client clientset.Interface, tokenIDsOrTokens
|
|||||||
klog.V(1).Info("[token] parsing token")
|
klog.V(1).Info("[token] parsing token")
|
||||||
if !bootstraputil.IsValidBootstrapTokenID(tokenIDOrToken) {
|
if !bootstraputil.IsValidBootstrapTokenID(tokenIDOrToken) {
|
||||||
// Okay, the full token with both id and secret was probably passed. Parse it and extract the ID only
|
// Okay, the full token with both id and secret was probably passed. Parse it and extract the ID only
|
||||||
bts, err := kubeadmapiv1.NewBootstrapTokenString(tokenIDOrToken)
|
bts, err := bootstraptokenv1.NewBootstrapTokenString(tokenIDOrToken)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Errorf("given token didn't match pattern %q or %q",
|
return errors.Errorf("given token didn't match pattern %q or %q",
|
||||||
bootstrapapi.BootstrapTokenIDPattern, bootstrapapi.BootstrapTokenIDPattern)
|
bootstrapapi.BootstrapTokenIDPattern, bootstrapapi.BootstrapTokenIDPattern)
|
||||||
|
@ -31,6 +31,7 @@ import (
|
|||||||
"k8s.io/client-go/kubernetes/fake"
|
"k8s.io/client-go/kubernetes/fake"
|
||||||
core "k8s.io/client-go/testing"
|
core "k8s.io/client-go/testing"
|
||||||
"k8s.io/client-go/tools/clientcmd"
|
"k8s.io/client-go/tools/clientcmd"
|
||||||
|
bootstraptokenv1 "k8s.io/kubernetes/cmd/kubeadm/app/apis/bootstraptoken/v1"
|
||||||
kubeadmapiv1beta2 "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1beta2"
|
kubeadmapiv1beta2 "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1beta2"
|
||||||
kubeadmapiv1 "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1beta3"
|
kubeadmapiv1 "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1beta3"
|
||||||
outputapischeme "k8s.io/kubernetes/cmd/kubeadm/app/apis/output/scheme"
|
outputapischeme "k8s.io/kubernetes/cmd/kubeadm/app/apis/output/scheme"
|
||||||
@ -157,13 +158,13 @@ func TestRunCreateToken(t *testing.T) {
|
|||||||
}
|
}
|
||||||
for _, tc := range testCases {
|
for _, tc := range testCases {
|
||||||
t.Run(tc.name, func(t *testing.T) {
|
t.Run(tc.name, func(t *testing.T) {
|
||||||
bts, err := kubeadmapiv1.NewBootstrapTokenString(tc.token)
|
bts, err := bootstraptokenv1.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
|
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)
|
t.Fatalf("token couldn't be parsed for testing: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
cfg := &kubeadmapiv1.InitConfiguration{
|
cfg := &kubeadmapiv1.InitConfiguration{
|
||||||
BootstrapTokens: []kubeadmapiv1.BootstrapToken{
|
BootstrapTokens: []bootstraptokenv1.BootstrapToken{
|
||||||
{
|
{
|
||||||
Token: bts,
|
Token: bts,
|
||||||
TTL: &metav1.Duration{Duration: 0},
|
TTL: &metav1.Duration{Duration: 0},
|
||||||
|
@ -34,6 +34,7 @@ import (
|
|||||||
bootstrapapi "k8s.io/cluster-bootstrap/token/api"
|
bootstrapapi "k8s.io/cluster-bootstrap/token/api"
|
||||||
bootstrap "k8s.io/cluster-bootstrap/token/jws"
|
bootstrap "k8s.io/cluster-bootstrap/token/jws"
|
||||||
"k8s.io/klog/v2"
|
"k8s.io/klog/v2"
|
||||||
|
bootstraptokenv1 "k8s.io/kubernetes/cmd/kubeadm/app/apis/bootstraptoken/v1"
|
||||||
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
|
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
|
||||||
kubeadmapiv1 "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1beta3"
|
kubeadmapiv1 "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1beta3"
|
||||||
"k8s.io/kubernetes/cmd/kubeadm/app/constants"
|
"k8s.io/kubernetes/cmd/kubeadm/app/constants"
|
||||||
@ -54,7 +55,7 @@ func RetrieveValidatedConfigInfo(cfg *kubeadmapi.Discovery) (*clientcmdapi.Confi
|
|||||||
// retrieveValidatedConfigInfo is a private implementation of RetrieveValidatedConfigInfo.
|
// retrieveValidatedConfigInfo is a private implementation of RetrieveValidatedConfigInfo.
|
||||||
// It accepts an optional clientset that can be used for testing purposes.
|
// It accepts an optional clientset that can be used for testing purposes.
|
||||||
func retrieveValidatedConfigInfo(client clientset.Interface, cfg *kubeadmapi.Discovery, interval time.Duration) (*clientcmdapi.Config, error) {
|
func retrieveValidatedConfigInfo(client clientset.Interface, cfg *kubeadmapi.Discovery, interval time.Duration) (*clientcmdapi.Config, error) {
|
||||||
token, err := kubeadmapi.NewBootstrapTokenString(cfg.BootstrapToken.Token)
|
token, err := bootstraptokenv1.NewBootstrapTokenString(cfg.BootstrapToken.Token)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -151,7 +152,7 @@ func buildSecureBootstrapKubeConfig(endpoint string, caCert []byte, clustername
|
|||||||
}
|
}
|
||||||
|
|
||||||
// validateClusterInfoToken validates that the JWS token present in the cluster info ConfigMap is valid
|
// validateClusterInfoToken validates that the JWS token present in the cluster info ConfigMap is valid
|
||||||
func validateClusterInfoToken(insecureClusterInfo *v1.ConfigMap, token *kubeadmapi.BootstrapTokenString) ([]byte, error) {
|
func validateClusterInfoToken(insecureClusterInfo *v1.ConfigMap, token *bootstraptokenv1.BootstrapTokenString) ([]byte, error) {
|
||||||
insecureKubeconfigString, ok := insecureClusterInfo.Data[bootstrapapi.KubeConfigKey]
|
insecureKubeconfigString, ok := insecureClusterInfo.Data[bootstrapapi.KubeConfigKey]
|
||||||
if !ok || len(insecureKubeconfigString) == 0 {
|
if !ok || len(insecureKubeconfigString) == 0 {
|
||||||
return nil, errors.Errorf("there is no %s key in the %s ConfigMap. This API Server isn't set up for token bootstrapping, can't connect",
|
return nil, errors.Errorf("there is no %s key in the %s ConfigMap. This API Server isn't set up for token bootstrapping, can't connect",
|
||||||
@ -194,7 +195,7 @@ func validateClusterCA(insecureConfig *clientcmdapi.Config, pubKeyPins *pubkeypi
|
|||||||
// getClusterInfo creates a client from the given kubeconfig if the given client is nil,
|
// getClusterInfo creates a client from the given kubeconfig if the given client is nil,
|
||||||
// and requests the cluster info ConfigMap using PollImmediate.
|
// and requests the cluster info ConfigMap using PollImmediate.
|
||||||
// If a client is provided it will be used instead.
|
// If a client is provided it will be used instead.
|
||||||
func getClusterInfo(client clientset.Interface, kubeconfig *clientcmdapi.Config, token *kubeadmapi.BootstrapTokenString, interval, duration time.Duration) (*v1.ConfigMap, error) {
|
func getClusterInfo(client clientset.Interface, kubeconfig *clientcmdapi.Config, token *bootstraptokenv1.BootstrapTokenString, interval, duration time.Duration) (*v1.ConfigMap, error) {
|
||||||
var cm *v1.ConfigMap
|
var cm *v1.ConfigMap
|
||||||
var err error
|
var err error
|
||||||
|
|
||||||
|
@ -18,24 +18,23 @@ package node
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
|
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
clientset "k8s.io/client-go/kubernetes"
|
clientset "k8s.io/client-go/kubernetes"
|
||||||
bootstraputil "k8s.io/cluster-bootstrap/token/util"
|
bootstraputil "k8s.io/cluster-bootstrap/token/util"
|
||||||
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
|
bootstraptokenv1 "k8s.io/kubernetes/cmd/kubeadm/app/apis/bootstraptoken/v1"
|
||||||
"k8s.io/kubernetes/cmd/kubeadm/app/util/apiclient"
|
"k8s.io/kubernetes/cmd/kubeadm/app/util/apiclient"
|
||||||
)
|
)
|
||||||
|
|
||||||
// TODO(mattmoyer): Move CreateNewTokens, UpdateOrCreateTokens out of this package to client-go for a generic abstraction and client for a Bootstrap Token
|
|
||||||
|
|
||||||
// CreateNewTokens tries to create a token and fails if one with the same ID already exists
|
// CreateNewTokens tries to create a token and fails if one with the same ID already exists
|
||||||
func CreateNewTokens(client clientset.Interface, tokens []kubeadmapi.BootstrapToken) error {
|
func CreateNewTokens(client clientset.Interface, tokens []bootstraptokenv1.BootstrapToken) error {
|
||||||
return UpdateOrCreateTokens(client, true, tokens)
|
return UpdateOrCreateTokens(client, true, tokens)
|
||||||
}
|
}
|
||||||
|
|
||||||
// UpdateOrCreateTokens attempts to update a token with the given ID, or create if it does not already exist.
|
// UpdateOrCreateTokens attempts to update a token with the given ID, or create if it does not already exist.
|
||||||
func UpdateOrCreateTokens(client clientset.Interface, failIfExists bool, tokens []kubeadmapi.BootstrapToken) error {
|
func UpdateOrCreateTokens(client clientset.Interface, failIfExists bool, tokens []bootstraptokenv1.BootstrapToken) error {
|
||||||
|
|
||||||
for _, token := range tokens {
|
for _, token := range tokens {
|
||||||
|
|
||||||
@ -45,7 +44,7 @@ func UpdateOrCreateTokens(client clientset.Interface, failIfExists bool, tokens
|
|||||||
return errors.Errorf("a token with id %q already exists", token.Token.ID)
|
return errors.Errorf("a token with id %q already exists", token.Token.ID)
|
||||||
}
|
}
|
||||||
|
|
||||||
updatedOrNewSecret := token.ToSecret()
|
updatedOrNewSecret := bootstraptokenv1.BootstrapTokenToSecret(&token)
|
||||||
// Try to create or update the token with an exponential backoff
|
// Try to create or update the token with an exponential backoff
|
||||||
err = apiclient.TryRunCommand(func() error {
|
err = apiclient.TryRunCommand(func() error {
|
||||||
if err := apiclient.CreateOrUpdateSecret(client, updatedOrNewSecret); err != nil {
|
if err := apiclient.CreateOrUpdateSecret(client, updatedOrNewSecret); err != nil {
|
||||||
|
@ -37,6 +37,7 @@ import (
|
|||||||
keyutil "k8s.io/client-go/util/keyutil"
|
keyutil "k8s.io/client-go/util/keyutil"
|
||||||
bootstraputil "k8s.io/cluster-bootstrap/token/util"
|
bootstraputil "k8s.io/cluster-bootstrap/token/util"
|
||||||
"k8s.io/klog/v2"
|
"k8s.io/klog/v2"
|
||||||
|
bootstraptokenv1 "k8s.io/kubernetes/cmd/kubeadm/app/apis/bootstraptoken/v1"
|
||||||
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
|
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
|
||||||
kubeadmconstants "k8s.io/kubernetes/cmd/kubeadm/app/constants"
|
kubeadmconstants "k8s.io/kubernetes/cmd/kubeadm/app/constants"
|
||||||
nodebootstraptokenphase "k8s.io/kubernetes/cmd/kubeadm/app/phases/bootstraptoken/node"
|
nodebootstraptokenphase "k8s.io/kubernetes/cmd/kubeadm/app/phases/bootstraptoken/node"
|
||||||
@ -57,11 +58,11 @@ func createShortLivedBootstrapToken(client clientset.Interface) (string, error)
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return "", errors.Wrap(err, "error generating token to upload certs")
|
return "", errors.Wrap(err, "error generating token to upload certs")
|
||||||
}
|
}
|
||||||
token, err := kubeadmapi.NewBootstrapTokenString(tokenStr)
|
token, err := bootstraptokenv1.NewBootstrapTokenString(tokenStr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", errors.Wrap(err, "error creating upload certs token")
|
return "", errors.Wrap(err, "error creating upload certs token")
|
||||||
}
|
}
|
||||||
tokens := []kubeadmapi.BootstrapToken{{
|
tokens := []bootstraptokenv1.BootstrapToken{{
|
||||||
Token: token,
|
Token: token,
|
||||||
Description: "Proxy for managing TTL for the kubeadm-certs secret",
|
Description: "Proxy for managing TTL for the kubeadm-certs secret",
|
||||||
TTL: &metav1.Duration{
|
TTL: &metav1.Duration{
|
||||||
|
@ -31,6 +31,7 @@ import (
|
|||||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||||
netutil "k8s.io/apimachinery/pkg/util/net"
|
netutil "k8s.io/apimachinery/pkg/util/net"
|
||||||
bootstraputil "k8s.io/cluster-bootstrap/token/util"
|
bootstraputil "k8s.io/cluster-bootstrap/token/util"
|
||||||
|
bootstraptokenv1 "k8s.io/kubernetes/cmd/kubeadm/app/apis/bootstraptoken/v1"
|
||||||
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
|
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
|
||||||
kubeadmscheme "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/scheme"
|
kubeadmscheme "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/scheme"
|
||||||
kubeadmapiv1 "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1beta3"
|
kubeadmapiv1 "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1beta3"
|
||||||
@ -44,8 +45,8 @@ import (
|
|||||||
|
|
||||||
var (
|
var (
|
||||||
// PlaceholderToken is only set statically to make kubeadm not randomize the token on every run
|
// PlaceholderToken is only set statically to make kubeadm not randomize the token on every run
|
||||||
PlaceholderToken = kubeadmapiv1.BootstrapToken{
|
PlaceholderToken = bootstraptokenv1.BootstrapToken{
|
||||||
Token: &kubeadmapiv1.BootstrapTokenString{
|
Token: &bootstraptokenv1.BootstrapTokenString{
|
||||||
ID: "abcdef",
|
ID: "abcdef",
|
||||||
Secret: "0123456789abcdef",
|
Secret: "0123456789abcdef",
|
||||||
},
|
},
|
||||||
@ -67,7 +68,7 @@ func SetInitDynamicDefaults(cfg *kubeadmapi.InitConfiguration) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// SetBootstrapTokensDynamicDefaults checks and sets configuration values for the BootstrapTokens object
|
// SetBootstrapTokensDynamicDefaults checks and sets configuration values for the BootstrapTokens object
|
||||||
func SetBootstrapTokensDynamicDefaults(cfg *[]kubeadmapi.BootstrapToken) error {
|
func SetBootstrapTokensDynamicDefaults(cfg *[]bootstraptokenv1.BootstrapToken) error {
|
||||||
// Populate the .Token field with a random value if unset
|
// Populate the .Token field with a random value if unset
|
||||||
// We do this at this layer, and not the API defaulting layer
|
// We do this at this layer, and not the API defaulting layer
|
||||||
// because of possible security concerns, and more practically
|
// because of possible security concerns, and more practically
|
||||||
@ -82,7 +83,7 @@ func SetBootstrapTokensDynamicDefaults(cfg *[]kubeadmapi.BootstrapToken) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, "couldn't generate random token")
|
return errors.Wrap(err, "couldn't generate random token")
|
||||||
}
|
}
|
||||||
token, err := kubeadmapi.NewBootstrapTokenString(tokenStr)
|
token, err := bootstraptokenv1.NewBootstrapTokenString(tokenStr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -183,7 +184,7 @@ func SetClusterDynamicDefaults(cfg *kubeadmapi.ClusterConfiguration, localAPIEnd
|
|||||||
func DefaultedStaticInitConfiguration() (*kubeadmapi.InitConfiguration, error) {
|
func DefaultedStaticInitConfiguration() (*kubeadmapi.InitConfiguration, error) {
|
||||||
versionedInitCfg := &kubeadmapiv1.InitConfiguration{
|
versionedInitCfg := &kubeadmapiv1.InitConfiguration{
|
||||||
LocalAPIEndpoint: kubeadmapiv1.APIEndpoint{AdvertiseAddress: "1.2.3.4"},
|
LocalAPIEndpoint: kubeadmapiv1.APIEndpoint{AdvertiseAddress: "1.2.3.4"},
|
||||||
BootstrapTokens: []kubeadmapiv1.BootstrapToken{PlaceholderToken},
|
BootstrapTokens: []bootstraptokenv1.BootstrapToken{PlaceholderToken},
|
||||||
NodeRegistration: kubeadmapiv1.NodeRegistrationOptions{
|
NodeRegistration: kubeadmapiv1.NodeRegistrationOptions{
|
||||||
CRISocket: kubeadmconstants.DefaultDockerCRISocket, // avoid CRI detection
|
CRISocket: kubeadmconstants.DefaultDockerCRISocket, // avoid CRI detection
|
||||||
Name: "node",
|
Name: "node",
|
||||||
|
@ -27,6 +27,7 @@ import (
|
|||||||
"k8s.io/apimachinery/pkg/runtime"
|
"k8s.io/apimachinery/pkg/runtime"
|
||||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||||
"k8s.io/apimachinery/pkg/runtime/serializer"
|
"k8s.io/apimachinery/pkg/runtime/serializer"
|
||||||
|
bootstraptokenv1 "k8s.io/kubernetes/cmd/kubeadm/app/apis/bootstraptoken/v1"
|
||||||
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
|
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
|
||||||
kubeadmapiv1 "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1beta3"
|
kubeadmapiv1 "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1beta3"
|
||||||
"k8s.io/kubernetes/cmd/kubeadm/app/constants"
|
"k8s.io/kubernetes/cmd/kubeadm/app/constants"
|
||||||
@ -119,9 +120,9 @@ func TestMarshalUnmarshalToYamlForCodecs(t *testing.T) {
|
|||||||
Name: "testNode",
|
Name: "testNode",
|
||||||
CRISocket: "/var/run/cri.sock",
|
CRISocket: "/var/run/cri.sock",
|
||||||
},
|
},
|
||||||
BootstrapTokens: []kubeadmapiv1.BootstrapToken{
|
BootstrapTokens: []bootstraptokenv1.BootstrapToken{
|
||||||
{
|
{
|
||||||
Token: &kubeadmapiv1.BootstrapTokenString{ID: "abcdef", Secret: "abcdef0123456789"},
|
Token: &bootstraptokenv1.BootstrapTokenString{ID: "abcdef", Secret: "abcdef0123456789"},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
// NOTE: Using MarshalToYamlForCodecs and UnmarshalFromYamlForCodecs for ClusterConfiguration fields here won't work
|
// NOTE: Using MarshalToYamlForCodecs and UnmarshalFromYamlForCodecs for ClusterConfiguration fields here won't work
|
||||||
|
Loading…
Reference in New Issue
Block a user