diff --git a/controlplane/kubeadm/config/rbac/role.yaml b/controlplane/kubeadm/config/rbac/role.yaml index c0d1b1a874f2..eb403e1452a6 100644 --- a/controlplane/kubeadm/config/rbac/role.yaml +++ b/controlplane/kubeadm/config/rbac/role.yaml @@ -6,6 +6,13 @@ metadata: creationTimestamp: null name: manager-role rules: +- apiGroups: + - apiextensions.k8s.io + resources: + - customresourcedefinitions + verbs: + - get + - list - apiGroups: - bootstrap.cluster.x-k8s.io - controlplane.cluster.x-k8s.io diff --git a/controlplane/kubeadm/controllers/controller.go b/controlplane/kubeadm/controllers/controller.go index 78c752368772..1fca1e2fb8f6 100644 --- a/controlplane/kubeadm/controllers/controller.go +++ b/controlplane/kubeadm/controllers/controller.go @@ -57,6 +57,7 @@ import ( // +kubebuilder:rbac:groups=infrastructure.cluster.x-k8s.io;bootstrap.cluster.x-k8s.io;controlplane.cluster.x-k8s.io,resources=*,verbs=get;list;watch;create;update;patch;delete // +kubebuilder:rbac:groups=cluster.x-k8s.io,resources=clusters;clusters/status,verbs=get;list;watch // +kubebuilder:rbac:groups=cluster.x-k8s.io,resources=machines;machines/status,verbs=get;list;watch;create;update;patch;delete +// +kubebuilder:rbac:groups=apiextensions.k8s.io,resources=customresourcedefinitions,verbs=get;list // KubeadmControlPlaneReconciler reconciles a KubeadmControlPlane object. type KubeadmControlPlaneReconciler struct { diff --git a/controlplane/kubeadm/controllers/controller_test.go b/controlplane/kubeadm/controllers/controller_test.go index abd01be327d3..d9a9ed4039e0 100644 --- a/controlplane/kubeadm/controllers/controller_test.go +++ b/controlplane/kubeadm/controllers/controller_test.go @@ -469,7 +469,7 @@ func TestKubeadmControlPlaneReconciler_adoption(t *testing.T) { Machines: collections.Machines{}, Workload: fakeWorkloadCluster{}, } - objs := []client.Object{cluster.DeepCopy(), kcp.DeepCopy(), tmpl.DeepCopy()} + objs := []client.Object{fakeGenericMachineTemplateCRD, cluster.DeepCopy(), kcp.DeepCopy(), tmpl.DeepCopy()} for i := 0; i < 3; i++ { name := fmt.Sprintf("test-%d", i) m := &clusterv1.Machine{ @@ -532,7 +532,7 @@ func TestKubeadmControlPlaneReconciler_adoption(t *testing.T) { Machines: collections.Machines{}, Workload: fakeWorkloadCluster{}, } - objs := []client.Object{cluster.DeepCopy(), kcp.DeepCopy(), tmpl.DeepCopy()} + objs := []client.Object{fakeGenericMachineTemplateCRD, cluster.DeepCopy(), kcp.DeepCopy(), tmpl.DeepCopy()} for i := 0; i < 3; i++ { name := fmt.Sprintf("test-%d", i) m := &clusterv1.Machine{ @@ -640,7 +640,7 @@ func TestKubeadmControlPlaneReconciler_adoption(t *testing.T) { Machines: collections.Machines{}, Workload: fakeWorkloadCluster{}, } - objs := []client.Object{cluster.DeepCopy(), kcp.DeepCopy(), tmpl.DeepCopy()} + objs := []client.Object{fakeGenericMachineTemplateCRD, cluster.DeepCopy(), kcp.DeepCopy(), tmpl.DeepCopy()} for i := 0; i < 3; i++ { name := fmt.Sprintf("test-%d", i) m := &clusterv1.Machine{ @@ -720,7 +720,7 @@ func TestKubeadmControlPlaneReconciler_adoption(t *testing.T) { Workload: fakeWorkloadCluster{}, } - fakeClient := newFakeClient(cluster.DeepCopy(), kcp.DeepCopy(), tmpl.DeepCopy(), fmc.Machines["test0"].DeepCopy()) + fakeClient := newFakeClient(fakeGenericMachineTemplateCRD, cluster.DeepCopy(), kcp.DeepCopy(), tmpl.DeepCopy(), fmc.Machines["test0"].DeepCopy()) fmc.Reader = fakeClient recorder := record.NewFakeRecorder(32) r := &KubeadmControlPlaneReconciler{ @@ -847,6 +847,7 @@ kubernetesVersion: metav1.16.1`, } fakeClient := newFakeClient( + fakeGenericMachineTemplateCRD, kcp.DeepCopy(), cluster.DeepCopy(), genericMachineTemplate.DeepCopy(), diff --git a/controlplane/kubeadm/controllers/helpers.go b/controlplane/kubeadm/controllers/helpers.go index d61a1d2ca0f4..dc2b5d91a20b 100644 --- a/controlplane/kubeadm/controllers/helpers.go +++ b/controlplane/kubeadm/controllers/helpers.go @@ -36,6 +36,7 @@ import ( "sigs.k8s.io/cluster-api/util" "sigs.k8s.io/cluster-api/util/certs" "sigs.k8s.io/cluster-api/util/conditions" + utilconversion "sigs.k8s.io/cluster-api/util/conversion" "sigs.k8s.io/cluster-api/util/kubeconfig" "sigs.k8s.io/cluster-api/util/patch" "sigs.k8s.io/cluster-api/util/secret" @@ -125,6 +126,10 @@ func (r *KubeadmControlPlaneReconciler) reconcileExternalReference(ctx context.C return nil } + if err := utilconversion.UpdateReferenceAPIContract(ctx, r.Client, ref); err != nil { + return err + } + obj, err := external.Get(ctx, r.Client, ref, cluster.Namespace) if err != nil { return err diff --git a/controlplane/kubeadm/controllers/helpers_test.go b/controlplane/kubeadm/controllers/helpers_test.go index 9a97a67e0e91..b872d633dae6 100644 --- a/controlplane/kubeadm/controllers/helpers_test.go +++ b/controlplane/kubeadm/controllers/helpers_test.go @@ -20,7 +20,6 @@ import ( "testing" . "github.com/onsi/gomega" - corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" diff --git a/controlplane/kubeadm/controllers/scale_test.go b/controlplane/kubeadm/controllers/scale_test.go index a31ab69ef9b7..d193e8a8dc5a 100644 --- a/controlplane/kubeadm/controllers/scale_test.go +++ b/controlplane/kubeadm/controllers/scale_test.go @@ -127,7 +127,7 @@ func TestKubeadmControlPlaneReconciler_scaleUpControlPlane(t *testing.T) { }) t.Run("does not create a control plane Machine if preflight checks fail", func(t *testing.T) { cluster, kcp, genericMachineTemplate := createClusterWithControlPlane(metav1.NamespaceDefault) - initObjs := []client.Object{cluster.DeepCopy(), kcp.DeepCopy(), genericMachineTemplate.DeepCopy()} + initObjs := []client.Object{fakeGenericMachineTemplateCRD, cluster.DeepCopy(), kcp.DeepCopy(), genericMachineTemplate.DeepCopy()} cluster.Spec.ControlPlaneEndpoint.Host = "nodomain.example.com" cluster.Spec.ControlPlaneEndpoint.Port = 6443 diff --git a/controlplane/kubeadm/controllers/suite_test.go b/controlplane/kubeadm/controllers/suite_test.go index ce90813153d0..88cd66cc4d6b 100644 --- a/controlplane/kubeadm/controllers/suite_test.go +++ b/controlplane/kubeadm/controllers/suite_test.go @@ -20,6 +20,8 @@ import ( "os" "testing" + apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "sigs.k8s.io/cluster-api/internal/envtest" ctrl "sigs.k8s.io/controller-runtime" // +kubebuilder:scaffold:imports @@ -28,6 +30,25 @@ import ( var ( env *envtest.Environment ctx = ctrl.SetupSignalHandler() + // TODO(sbueringer): move under internal/testtypes (or refactor it in a way that we don't need it anymore). + fakeGenericMachineTemplateCRD = &apiextensionsv1.CustomResourceDefinition{ + TypeMeta: metav1.TypeMeta{ + APIVersion: apiextensionsv1.SchemeGroupVersion.String(), + Kind: "CustomResourceDefinition", + }, + ObjectMeta: metav1.ObjectMeta{ + Name: "genericmachinetemplate.generic.io", + Labels: map[string]string{ + "cluster.x-k8s.io/v1alpha4": "v1", + }, + }, + Spec: apiextensionsv1.CustomResourceDefinitionSpec{ + Group: "generic.io", + Names: apiextensionsv1.CustomResourceDefinitionNames{ + Kind: "GenericMachineTemplate", + }, + }, + } ) func TestMain(m *testing.M) { diff --git a/controlplane/kubeadm/controllers/upgrade_test.go b/controlplane/kubeadm/controllers/upgrade_test.go index 6979b438bfe1..3f814545a269 100644 --- a/controlplane/kubeadm/controllers/upgrade_test.go +++ b/controlplane/kubeadm/controllers/upgrade_test.go @@ -49,7 +49,7 @@ func TestKubeadmControlPlaneReconciler_RolloutStrategy_ScaleUp(t *testing.T) { kcp.Spec.Replicas = pointer.Int32Ptr(1) setKCPHealthy(kcp) - fakeClient := newFakeClient(cluster.DeepCopy(), kcp.DeepCopy(), genericMachineTemplate.DeepCopy()) + fakeClient := newFakeClient(fakeGenericMachineTemplateCRD, cluster.DeepCopy(), kcp.DeepCopy(), genericMachineTemplate.DeepCopy()) r := &KubeadmControlPlaneReconciler{ Client: fakeClient, @@ -144,7 +144,7 @@ func TestKubeadmControlPlaneReconciler_RolloutStrategy_ScaleDown(t *testing.T) { Status: internal.ClusterStatus{Nodes: 3}, }, } - objs := []client.Object{cluster.DeepCopy(), kcp.DeepCopy(), tmpl.DeepCopy()} + objs := []client.Object{fakeGenericMachineTemplateCRD, cluster.DeepCopy(), kcp.DeepCopy(), tmpl.DeepCopy()} for i := 0; i < 3; i++ { name := fmt.Sprintf("test-%d", i) m := &clusterv1.Machine{ diff --git a/controlplane/kubeadm/main.go b/controlplane/kubeadm/main.go index 21ffbdd2978a..966520f93009 100644 --- a/controlplane/kubeadm/main.go +++ b/controlplane/kubeadm/main.go @@ -29,6 +29,7 @@ import ( "github.com/spf13/pflag" appsv1 "k8s.io/api/apps/v1" corev1 "k8s.io/api/core/v1" + apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" "k8s.io/apimachinery/pkg/runtime" clientgoscheme "k8s.io/client-go/kubernetes/scheme" cliflag "k8s.io/component-base/cli/flag" @@ -61,6 +62,7 @@ func init() { _ = kubeadmcontrolplanev1old.AddToScheme(scheme) _ = kubeadmcontrolplanev1.AddToScheme(scheme) _ = kubeadmbootstrapv1.AddToScheme(scheme) + _ = apiextensionsv1.AddToScheme(scheme) // +kubebuilder:scaffold:scheme } diff --git a/util/conversion/conversion.go b/util/conversion/conversion.go index 42016d7dc975..49a4d6bf6253 100644 --- a/util/conversion/conversion.go +++ b/util/conversion/conversion.go @@ -54,7 +54,7 @@ var ( contract = clusterv1.GroupVersion.String() ) -// ConvertReferenceAPIContract takes a client and object reference, queries the API Server for +// UpdateReferenceAPIContract takes a client and object reference, queries the API Server for // the Custom Resource Definition and looks which one is the stored version available. // // The object passed as input is modified in place if an updated compatible version is found.