From 683c35bd071820055e2469203051e5b7b9f03d32 Mon Sep 17 00:00:00 2001 From: Christian Schlotter Date: Fri, 21 Jun 2024 11:59:29 +0200 Subject: [PATCH] fixes --- .../flavors/clusterclass_generators.go | 6 +- packaging/flavorgen/flavors/kubevip/files.go | 2 +- .../flavorgen/flavors/kubevip/kubevip.go | 2 +- .../flavorgen/flavors/kubevip/topology.go | 2 +- .../patch-test-extension.yaml | 14 +- .../patch-test-extension.yaml | 14 +- .../topologymutation/handler.go | 134 +++++++++++++++--- 7 files changed, 147 insertions(+), 27 deletions(-) diff --git a/packaging/flavorgen/flavors/clusterclass_generators.go b/packaging/flavorgen/flavors/clusterclass_generators.go index 0e5382b10c..30d08444ff 100644 --- a/packaging/flavorgen/flavors/clusterclass_generators.go +++ b/packaging/flavorgen/flavors/clusterclass_generators.go @@ -55,7 +55,7 @@ func newClusterClass() clusterv1.ClusterClass { }, ControlPlane: getControlPlaneClass(), Workers: getWorkersClass(), - Variables: getClusterClassVariables(false), + Variables: GetClusterClassVariables(false), Patches: getClusterClassPatches(), }, } @@ -81,7 +81,7 @@ func newVMWareClusterClass() clusterv1.ClusterClass { }, ControlPlane: getVMWareControlPlaneClass(), Workers: getVMWareWorkersClass(), - Variables: getClusterClassVariables(true), + Variables: GetClusterClassVariables(true), Patches: getVMWareClusterClassPatches(), }, } @@ -238,7 +238,7 @@ func getEnableSSHIntoNodesTemplate() *string { return ptr.To(string(templateStr)) } -func getClusterClassVariables(supervisorMode bool) []clusterv1.ClusterClassVariable { +func GetClusterClassVariables(supervisorMode bool) []clusterv1.ClusterClassVariable { variables := []clusterv1.ClusterClassVariable{ { Name: "sshKey", diff --git a/packaging/flavorgen/flavors/kubevip/files.go b/packaging/flavorgen/flavors/kubevip/files.go index ee0ce3bb0d..ae918aacd6 100644 --- a/packaging/flavorgen/flavors/kubevip/files.go +++ b/packaging/flavorgen/flavors/kubevip/files.go @@ -38,7 +38,7 @@ var ( kubeVipPodRaw string ) -func newKubeVIPFiles() []bootstrapv1.File { +func NewKubeVIPFiles() []bootstrapv1.File { return []bootstrapv1.File{ { Owner: "root:root", diff --git a/packaging/flavorgen/flavors/kubevip/kubevip.go b/packaging/flavorgen/flavors/kubevip/kubevip.go index c18ead9c79..7a20a9949f 100644 --- a/packaging/flavorgen/flavors/kubevip/kubevip.go +++ b/packaging/flavorgen/flavors/kubevip/kubevip.go @@ -23,5 +23,5 @@ import ( // PatchControlPlane adds kube-vip to a KubeadmControlPlane object. func PatchControlPlane(cp *controlplanev1.KubeadmControlPlane) { - cp.Spec.KubeadmConfigSpec.Files = append(cp.Spec.KubeadmConfigSpec.Files, newKubeVIPFiles()...) + cp.Spec.KubeadmConfigSpec.Files = append(cp.Spec.KubeadmConfigSpec.Files, NewKubeVIPFiles()...) } diff --git a/packaging/flavorgen/flavors/kubevip/topology.go b/packaging/flavorgen/flavors/kubevip/topology.go index 5d15bbb7fb..1eed43aa65 100644 --- a/packaging/flavorgen/flavors/kubevip/topology.go +++ b/packaging/flavorgen/flavors/kubevip/topology.go @@ -52,7 +52,7 @@ func TopologyVariable() (*clusterv1.ClusterVariable, error) { func TopologyPatch() clusterv1.ClusterClassPatch { patches := []clusterv1.JSONPatch{} - for _, f := range newKubeVIPFiles() { + for _, f := range NewKubeVIPFiles() { p := clusterv1.JSONPatch{ Op: "add", Path: "/spec/template/spec/kubeadmConfigSpec/files/-", diff --git a/test/e2e/data/infrastructure-vsphere-govmomi/main/clusterclass-runtimesdk/patch-test-extension.yaml b/test/e2e/data/infrastructure-vsphere-govmomi/main/clusterclass-runtimesdk/patch-test-extension.yaml index 9e62202926..2073d31220 100644 --- a/test/e2e/data/infrastructure-vsphere-govmomi/main/clusterclass-runtimesdk/patch-test-extension.yaml +++ b/test/e2e/data/infrastructure-vsphere-govmomi/main/clusterclass-runtimesdk/patch-test-extension.yaml @@ -1,8 +1,18 @@ +- op: remove + path: /spec/patches/0 +- op: remove + path: /spec/patches/0 +- op: remove + path: /spec/patches/0 +- op: remove + path: /spec/patches/0 - op: add - path: /spec/patches/- + path: /spec/patches/0 value: - name: test-patch + - name: test-patch external: generateExtension: generate-patches.capv-test-extension validateExtension: validate-topology.capv-test-extension discoverVariablesExtension: discover-variables.capv-test-extension +- op: remove + path: /spec/variables diff --git a/test/e2e/data/infrastructure-vsphere-supervisor/main/clusterclass-runtimesdk/patch-test-extension.yaml b/test/e2e/data/infrastructure-vsphere-supervisor/main/clusterclass-runtimesdk/patch-test-extension.yaml index 9e62202926..2073d31220 100644 --- a/test/e2e/data/infrastructure-vsphere-supervisor/main/clusterclass-runtimesdk/patch-test-extension.yaml +++ b/test/e2e/data/infrastructure-vsphere-supervisor/main/clusterclass-runtimesdk/patch-test-extension.yaml @@ -1,8 +1,18 @@ +- op: remove + path: /spec/patches/0 +- op: remove + path: /spec/patches/0 +- op: remove + path: /spec/patches/0 +- op: remove + path: /spec/patches/0 - op: add - path: /spec/patches/- + path: /spec/patches/0 value: - name: test-patch + - name: test-patch external: generateExtension: generate-patches.capv-test-extension validateExtension: validate-topology.capv-test-extension discoverVariablesExtension: discover-variables.capv-test-extension +- op: remove + path: /spec/variables diff --git a/test/infrastructure/test-extension/topologymutation/handler.go b/test/infrastructure/test-extension/topologymutation/handler.go index e4cc5b4db0..dec62c3f50 100644 --- a/test/infrastructure/test-extension/topologymutation/handler.go +++ b/test/infrastructure/test-extension/topologymutation/handler.go @@ -23,12 +23,14 @@ package topologymutation import ( "context" + "fmt" + "regexp" "github.com/pkg/errors" apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime/serializer" - clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1" + "k8s.io/utils/ptr" bootstrapv1 "sigs.k8s.io/cluster-api/bootstrap/kubeadm/api/v1beta1" controlplanev1 "sigs.k8s.io/cluster-api/controlplane/kubeadm/api/v1beta1" runtimehooksv1 "sigs.k8s.io/cluster-api/exp/runtime/hooks/api/v1alpha1" @@ -37,6 +39,8 @@ import ( infrav1 "sigs.k8s.io/cluster-api-provider-vsphere/apis/v1beta1" vmwarev1 "sigs.k8s.io/cluster-api-provider-vsphere/apis/vmware/v1beta1" + "sigs.k8s.io/cluster-api-provider-vsphere/packaging/flavorgen/flavors" + "sigs.k8s.io/cluster-api-provider-vsphere/packaging/flavorgen/flavors/kubevip" ) // +kubebuilder:rbac:groups="",resources=configmaps,verbs=get;list;watch;patch;update;create @@ -78,6 +82,16 @@ func (h *ExtensionHandlers) GeneratePatches(ctx context.Context, req *runtimehoo log := ctrl.LoggerFrom(ctx) switch obj := obj.(type) { + case *controlplanev1.KubeadmControlPlaneTemplate: + if err := patchKubeadmControlPlaneTemplate(ctx, obj, variables); err != nil { + log.Error(err, "Error patching KubeadmControlPlaneTemplate") + return errors.Wrap(err, "error patching KubeadmControlPlaneTemplate") + } + case *bootstrapv1.KubeadmConfigTemplate: + if err := patchKubeadmConfigTemplate(ctx, obj, variables); err != nil { + log.Error(err, "Error patching KubeadmConfigTemplate") + return errors.Wrap(err, "error patching KubeadmConfigTemplate") + } case *infrav1.VSphereClusterTemplate: if err := patchGovmomiClusterTemplate(ctx, obj, variables); err != nil { log.Error(err, "Error patching VSphereClusterTemplate") @@ -103,10 +117,108 @@ func (h *ExtensionHandlers) GeneratePatches(ctx context.Context, req *runtimehoo }) } +// patchKubeadmControlPlaneTemplate patches the KubeadmControlPlaneTemplate. +func patchKubeadmControlPlaneTemplate(_ context.Context, tpl *controlplanev1.KubeadmControlPlaneTemplate, templateVariables map[string]apiextensionsv1.JSON) error { + // patch enableSSHIntoNodes + if err := patchUsers(&tpl.Spec.Template.Spec.KubeadmConfigSpec, templateVariables); err != nil { + return err + } + + // patch kubeVipPodManifest + kubeVipPodManifest, err := topologymutation.GetStringVariable(templateVariables, "kubeVipPodManifest") + if err != nil { + // Skip patch if sshKey variable is not set + if topologymutation.IsNotFoundError(err) { + return nil + } + return err + } + controlPlaneIPAddr, err := topologymutation.GetStringVariable(templateVariables, "controlPlaneIpAddr") + if err != nil { + return err + } + kubeVipPodManifestModified := regexp.MustCompile("(name: address\n +value:).*").ReplaceAll([]byte(kubeVipPodManifest), []byte(fmt.Sprintf("$1 %s", controlPlaneIPAddr))) + + for _, file := range kubevip.NewKubeVIPFiles() { + if file.Path == "/etc/kubernetes/manifests/kube-vip.yaml" { + file.Content = string(kubeVipPodManifestModified) + } + tpl.Spec.Template.Spec.KubeadmConfigSpec.Files = append(tpl.Spec.Template.Spec.KubeadmConfigSpec.Files, file) + } + + return nil +} + +// KubeadmConfigTemplate patches the KubeadmConfigTemplate. +func patchKubeadmConfigTemplate(_ context.Context, tpl *bootstrapv1.KubeadmConfigTemplate, templateVariables map[string]apiextensionsv1.JSON) error { + // patch enableSSHIntoNodes + //nolint:revive + if err := patchUsers(&tpl.Spec.Template.Spec, templateVariables); err != nil { + return err + } + + return nil +} + +func patchUsers(kubeadmConfigSpec *bootstrapv1.KubeadmConfigSpec, templateVariables map[string]apiextensionsv1.JSON) error { + sshKey, err := topologymutation.GetStringVariable(templateVariables, "sshKey") + if err != nil { + // Skip patch if sshKey variable is not set + if topologymutation.IsNotFoundError(err) { + return nil + } + return err + } + + kubeadmConfigSpec.Users = append(kubeadmConfigSpec.Users, + bootstrapv1.User{ + Name: "capv", + SSHAuthorizedKeys: []string{sshKey}, + Sudo: ptr.To("ALL=(ALL) NOPASSWD:ALL"), + }) + return nil +} + // patchGovmomiClusterTemplate patches the govmomi VSphereClusterTemplate. // NOTE: this patch is not required for any special reason, it is used for testing the patch machinery itself. -func patchGovmomiClusterTemplate(_ context.Context, _ *infrav1.VSphereClusterTemplate, _ map[string]apiextensionsv1.JSON) error { - // TODO(chrischdi): implement some patch +func patchGovmomiClusterTemplate(_ context.Context, vsphereCluster *infrav1.VSphereClusterTemplate, templateVariables map[string]apiextensionsv1.JSON) error { + // patch infraClusterSubstitutions + controlPlaneIPAddr, err := topologymutation.GetStringVariable(templateVariables, "controlPlaneIpAddr") + if err != nil { + return err + } + var controlPlanePort int32 + if err := topologymutation.GetObjectVariableInto(templateVariables, "controlPlanePort", &controlPlanePort); err != nil { + return err + } + + vsphereCluster.Spec.Template.Spec.ControlPlaneEndpoint.Host = controlPlaneIPAddr + vsphereCluster.Spec.Template.Spec.ControlPlaneEndpoint.Port = controlPlanePort + + credsSecretName, err := topologymutation.GetStringVariable(templateVariables, "credsSecretName") + if err != nil { + return err + } + + vsphereCluster.Spec.Template.Spec.IdentityRef = &infrav1.VSphereIdentityReference{ + Kind: infrav1.SecretKind, + Name: credsSecretName, + } + + infraServerURL, err := topologymutation.GetStringVariable(templateVariables, "infraServer.url") + if err != nil { + return err + } + + vsphereCluster.Spec.Template.Spec.Server = infraServerURL + + infraServerThumbprint, err := topologymutation.GetStringVariable(templateVariables, "infraServer.thumbprint") + if err != nil { + return err + } + + vsphereCluster.Spec.Template.Spec.Thumbprint = infraServerThumbprint + return nil } @@ -147,18 +259,6 @@ func (h *ExtensionHandlers) DiscoverVariables(ctx context.Context, _ *runtimehoo log.Info("DiscoverVariables called") resp.Status = runtimehooksv1.ResponseStatusSuccess - resp.Variables = []clusterv1.ClusterClassVariable{ - { - Name: "unusedTest", - Required: false, - Schema: clusterv1.VariableSchema{ - OpenAPIV3Schema: clusterv1.JSONSchemaProps{ - Type: "string", - Default: &apiextensionsv1.JSON{Raw: []byte(`""`)}, - Example: &apiextensionsv1.JSON{Raw: []byte(`""`)}, - Description: "unusedTest is not used.", - }, - }, - }, - } + // Using false to get all variables. When patching supervisor templates we just won't use the additional variables. + resp.Variables = flavors.GetClusterClassVariables(false) }