From 2c5aef90367b0fcdbf50b88cd545f849c6549ed2 Mon Sep 17 00:00:00 2001 From: SataQiu Date: Wed, 9 Feb 2022 12:58:02 +0800 Subject: [PATCH] kubeadm: fix the bug that 'kubeadm init --dry-run --upload-certs' command failed with 'secret not found' error --- cmd/kubeadm/app/util/apiclient/dryrunclient.go | 17 ++++++++++++++++- cmd/kubeadm/app/util/apiclient/init_dryrun.go | 15 --------------- .../app/util/apiclient/init_dryrun_test.go | 14 -------------- 3 files changed, 16 insertions(+), 30 deletions(-) diff --git a/cmd/kubeadm/app/util/apiclient/dryrunclient.go b/cmd/kubeadm/app/util/apiclient/dryrunclient.go index fabda0a9c34..6dccc5b8794 100644 --- a/cmd/kubeadm/app/util/apiclient/dryrunclient.go +++ b/cmd/kubeadm/app/util/apiclient/dryrunclient.go @@ -25,11 +25,14 @@ import ( "github.com/pkg/errors" + v1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime/schema" clientset "k8s.io/client-go/kubernetes" fakeclientset "k8s.io/client-go/kubernetes/fake" core "k8s.io/client-go/testing" + bootstrapapi "k8s.io/cluster-bootstrap/token/api" kubeadmutil "k8s.io/kubernetes/cmd/kubeadm/app/util" ) @@ -162,7 +165,19 @@ func NewDryRunClientWithOpts(opts DryRunClientOptions) clientset.Interface { &core.SimpleReactor{ Verb: "create", Resource: "*", - Reaction: successfulModificationReactorFunc, + Reaction: func(action core.Action) (bool, runtime.Object, error) { + objAction, ok := action.(actionWithObject) + if obj := objAction.GetObject(); ok && obj != nil { + if secret, ok := obj.(*v1.Secret); ok { + if secret.Namespace == metav1.NamespaceSystem && strings.HasPrefix(secret.Name, bootstrapapi.BootstrapTokenSecretPrefix) { + // bypass bootstrap token secret create event so that it can be persisted to the backing data store + // this secret should be readable during the uploadcerts init phase if it has already been created + return false, nil, nil + } + } + } + return successfulModificationReactorFunc(action) + }, }, &core.SimpleReactor{ Verb: "update", diff --git a/cmd/kubeadm/app/util/apiclient/init_dryrun.go b/cmd/kubeadm/app/util/apiclient/init_dryrun.go index 16d117177e4..3cc64fabe90 100644 --- a/cmd/kubeadm/app/util/apiclient/init_dryrun.go +++ b/cmd/kubeadm/app/util/apiclient/init_dryrun.go @@ -17,8 +17,6 @@ limitations under the License. package apiclient import ( - "strings" - "github.com/pkg/errors" v1 "k8s.io/api/core/v1" @@ -36,7 +34,6 @@ import ( // Need to handle these routes in a special manner: // - GET /default/services/kubernetes -- must return a valid Service // - GET /clusterrolebindings/system:nodes -- can safely return a NotFound error -// - GET /kube-system/secrets/bootstrap-token-* -- can safely return a NotFound error // - GET /nodes/ -- must return a valid Node // - ...all other, unknown GETs/LISTs will be logged type InitDryRunGetter struct { @@ -61,7 +58,6 @@ func (idr *InitDryRunGetter) HandleGetAction(action core.GetAction) (bool, runti idr.handleKubernetesService, idr.handleGetNode, idr.handleSystemNodesClusterRoleBinding, - idr.handleGetBootstrapToken, } for _, f := range funcs { handled, obj, err := f(action) @@ -148,14 +144,3 @@ func (idr *InitDryRunGetter) handleSystemNodesClusterRoleBinding(action core.Get // This can only happen on an upgrade; and in that case the ClientBackedDryRunGetter impl will be used return true, nil, apierrors.NewNotFound(action.GetResource().GroupResource(), "clusterrolebinding not found") } - -// handleGetBootstrapToken handles the case where kubeadm init creates the default token; and the token code GETs the -// bootstrap token secret first in order to check if it already exists -func (idr *InitDryRunGetter) handleGetBootstrapToken(action core.GetAction) (bool, runtime.Object, error) { - if !strings.HasPrefix(action.GetName(), "bootstrap-token-") || action.GetNamespace() != metav1.NamespaceSystem || action.GetResource().Resource != "secrets" { - // We can't handle this event - return false, nil, nil - } - // We can safely return a NotFound error here as the code will just proceed normally and create the Bootstrap Token - return true, nil, apierrors.NewNotFound(action.GetResource().GroupResource(), "secret not found") -} diff --git a/cmd/kubeadm/app/util/apiclient/init_dryrun_test.go b/cmd/kubeadm/app/util/apiclient/init_dryrun_test.go index e3393b417cb..451e810c47e 100644 --- a/cmd/kubeadm/app/util/apiclient/init_dryrun_test.go +++ b/cmd/kubeadm/app/util/apiclient/init_dryrun_test.go @@ -59,13 +59,6 @@ func TestHandleGetAction(t *testing.T) { expectedObjectJSON: []byte(``), expectedErr: true, // we expect a NotFound error here }, - { - name: "get kube-system secret bootstrap-token-abcdef", - action: core.NewGetAction(schema.GroupVersionResource{Version: "v1", Resource: "secrets"}, "kube-system", "bootstrap-token-abcdef"), - expectedHandled: true, - expectedObjectJSON: []byte(``), - expectedErr: true, // we expect a NotFound error here - }, { // an ask for a kubernetes service in the _kube-system_ ns should not be answered name: "get kube-system services", action: core.NewGetAction(schema.GroupVersionResource{Version: "v1", Resource: "services"}, "kube-system", "kubernetes"), @@ -87,13 +80,6 @@ func TestHandleGetAction(t *testing.T) { expectedObjectJSON: []byte(``), expectedErr: false, }, - { // an ask for a secret in any other ns than kube-system should not be answered - name: "get default secret bootstrap-token-abcdef", - action: core.NewGetAction(schema.GroupVersionResource{Version: "v1", Resource: "secrets"}, "default", "bootstrap-token-abcdef"), - expectedHandled: false, - expectedObjectJSON: []byte(``), - expectedErr: false, - }, } for _, rt := range tests { t.Run(rt.name, func(t *testing.T) {