From f344bb3dc43216047eca1e1df6a6d34ef8da56ac Mon Sep 17 00:00:00 2001 From: Daniel Lipovetsky Date: Tue, 23 Apr 2024 10:21:32 -0700 Subject: [PATCH 1/4] feat: Support creating namespace with metadata on remote cluster --- pkg/handlers/generic/lifecycle/utils/utils.go | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/pkg/handlers/generic/lifecycle/utils/utils.go b/pkg/handlers/generic/lifecycle/utils/utils.go index 251b0d069..3ae03f7f1 100644 --- a/pkg/handlers/generic/lifecycle/utils/utils.go +++ b/pkg/handlers/generic/lifecycle/utils/utils.go @@ -108,6 +108,29 @@ func EnsureNamespaceWithName(ctx context.Context, c ctrlclient.Client, name stri return EnsureNamespace(ctx, c, ns) } +// EnsureNamespaceWithMetadata will create the namespace with the specified name, +// labels, and/or annotations, if it does not exist. +func EnsureNamespaceWithMetadata(ctx context.Context, + c ctrlclient.Client, + name string, + labels, + annotations map[string]string, +) error { + ns := &corev1.Namespace{ + TypeMeta: metav1.TypeMeta{ + APIVersion: corev1.SchemeGroupVersion.String(), + Kind: "Namespace", + }, + ObjectMeta: metav1.ObjectMeta{ + Name: name, + Annotations: annotations, + Labels: labels, + }, + } + + return EnsureNamespace(ctx, c, ns) +} + // EnsureNamespace will create the namespace if it does not exist. func EnsureNamespace(ctx context.Context, c ctrlclient.Client, ns *corev1.Namespace) error { if ns.TypeMeta.APIVersion == "" { From 649a21bcda477eba48cf329d86d98cfb643182b2 Mon Sep 17 00:00:00 2001 From: Daniel Lipovetsky Date: Fri, 26 Apr 2024 11:17:53 -0700 Subject: [PATCH 2/4] feat: Add the ServiceLoadbalancer Addon, with MetalLB as first provider --- api/v1alpha1/addon_types.go | 12 ++ api/v1alpha1/constants.go | 2 + .../caren.nutanix.com_awsclusterconfigs.yaml | 12 ++ ...aren.nutanix.com_dockerclusterconfigs.yaml | 12 ++ ...ren.nutanix.com_nutanixclusterconfigs.yaml | 12 ++ api/v1alpha1/zz_generated.deepcopy.go | 20 +++ .../README.md | 2 + .../templates/helm-config.yaml | 4 + .../metallb/helm-addon-installation.yaml | 31 ++++ .../values.yaml | 6 +- .../kustomize/metallb/kustomization.yaml.tmpl | 27 +++ make/addons.mk | 2 + pkg/handlers/generic/lifecycle/config/cm.go | 1 + pkg/handlers/generic/lifecycle/handlers.go | 13 ++ .../lifecycle/serviceloadbalancer/handler.go | 131 +++++++++++++++ .../serviceloadbalancer/metallb/handler.go | 155 ++++++++++++++++++ 16 files changed, 441 insertions(+), 1 deletion(-) create mode 100644 charts/cluster-api-runtime-extensions-nutanix/templates/serviceloadbalancer/metallb/helm-addon-installation.yaml create mode 100644 hack/addons/kustomize/metallb/kustomization.yaml.tmpl create mode 100644 pkg/handlers/generic/lifecycle/serviceloadbalancer/handler.go create mode 100644 pkg/handlers/generic/lifecycle/serviceloadbalancer/metallb/handler.go diff --git a/api/v1alpha1/addon_types.go b/api/v1alpha1/addon_types.go index ccc376c5e..37e52cb98 100644 --- a/api/v1alpha1/addon_types.go +++ b/api/v1alpha1/addon_types.go @@ -24,6 +24,8 @@ const ( VirtualIPProviderKubeVIP = "KubeVIP" + ServiceLoadbalancerProviderMetalLB = "MetalLB" + AddonStrategyClusterResourceSet AddonStrategy = "ClusterResourceSet" AddonStrategyHelmAddon AddonStrategy = "HelmAddon" @@ -69,6 +71,9 @@ type Addons struct { // +optional CSIProviders *CSI `json:"csi,omitempty"` + + // +optional + ServiceLoadbalancer *ServiceLoadbalancer `json:"serviceLoadbalancer,omitempty"` } type AddonStrategy string @@ -160,3 +165,10 @@ type CCM struct { // +optional Credentials *corev1.LocalObjectReference `json:"credentials,omitempty"` } + +type ServiceLoadbalancer struct { + // The Loadbalancer-type Service provider to deploy. Not required in infrastructures where + // the CCM acts as the provider. + // +kubebuilder:validation:Enum=MetalLB + Provider string `json:"provider"` +} diff --git a/api/v1alpha1/constants.go b/api/v1alpha1/constants.go index de4b8b1f6..cf109febc 100644 --- a/api/v1alpha1/constants.go +++ b/api/v1alpha1/constants.go @@ -14,4 +14,6 @@ const ( AWSVariableName = "aws" // NutanixVariableName is the Nutanix config patch variable name. NutanixVariableName = "nutanix" + // ServiceLoadbalancerName is the Service Loadbalancer config patch variable name. + ServiceLoadbalancerVariableName = "serviceLoadbalancer" ) diff --git a/api/v1alpha1/crds/caren.nutanix.com_awsclusterconfigs.yaml b/api/v1alpha1/crds/caren.nutanix.com_awsclusterconfigs.yaml index 14ec91fc4..cc67e057f 100644 --- a/api/v1alpha1/crds/caren.nutanix.com_awsclusterconfigs.yaml +++ b/api/v1alpha1/crds/caren.nutanix.com_awsclusterconfigs.yaml @@ -201,6 +201,18 @@ spec: required: - strategy type: object + serviceLoadbalancer: + properties: + provider: + description: |- + The Loadbalancer-type Service provider to deploy. Not required in infrastructures where + the CCM acts as the provider. + enum: + - MetalLB + type: string + required: + - provider + type: object type: object aws: description: AWS cluster configuration. diff --git a/api/v1alpha1/crds/caren.nutanix.com_dockerclusterconfigs.yaml b/api/v1alpha1/crds/caren.nutanix.com_dockerclusterconfigs.yaml index 0086d1894..76daa812b 100644 --- a/api/v1alpha1/crds/caren.nutanix.com_dockerclusterconfigs.yaml +++ b/api/v1alpha1/crds/caren.nutanix.com_dockerclusterconfigs.yaml @@ -202,6 +202,18 @@ spec: required: - strategy type: object + serviceLoadbalancer: + properties: + provider: + description: |- + The Loadbalancer-type Service provider to deploy. Not required in infrastructures where + the CCM acts as the provider. + enum: + - MetalLB + type: string + required: + - provider + type: object type: object controlPlane: description: DockerNodeConfigSpec defines the desired state of DockerNodeSpec. diff --git a/api/v1alpha1/crds/caren.nutanix.com_nutanixclusterconfigs.yaml b/api/v1alpha1/crds/caren.nutanix.com_nutanixclusterconfigs.yaml index 632aa9193..c3bb3e6c4 100644 --- a/api/v1alpha1/crds/caren.nutanix.com_nutanixclusterconfigs.yaml +++ b/api/v1alpha1/crds/caren.nutanix.com_nutanixclusterconfigs.yaml @@ -202,6 +202,18 @@ spec: required: - strategy type: object + serviceLoadbalancer: + properties: + provider: + description: |- + The Loadbalancer-type Service provider to deploy. Not required in infrastructures where + the CCM acts as the provider. + enum: + - MetalLB + type: string + required: + - provider + type: object type: object controlPlane: description: NutanixNodeSpec defines the desired state of NutanixNodeSpec. diff --git a/api/v1alpha1/zz_generated.deepcopy.go b/api/v1alpha1/zz_generated.deepcopy.go index 9986f1357..ffe936967 100644 --- a/api/v1alpha1/zz_generated.deepcopy.go +++ b/api/v1alpha1/zz_generated.deepcopy.go @@ -350,6 +350,11 @@ func (in *Addons) DeepCopyInto(out *Addons) { *out = new(CSI) (*in).DeepCopyInto(*out) } + if in.ServiceLoadbalancer != nil { + in, out := &in.ServiceLoadbalancer, &out.ServiceLoadbalancer + *out = new(ServiceLoadbalancer) + **out = **in + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Addons. @@ -1119,6 +1124,21 @@ func (in *SecurityGroup) DeepCopy() *SecurityGroup { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ServiceLoadbalancer) DeepCopyInto(out *ServiceLoadbalancer) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ServiceLoadbalancer. +func (in *ServiceLoadbalancer) DeepCopy() *ServiceLoadbalancer { + if in == nil { + return nil + } + out := new(ServiceLoadbalancer) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *StorageClassConfig) DeepCopyInto(out *StorageClassConfig) { *out = *in diff --git a/charts/cluster-api-runtime-extensions-nutanix/README.md b/charts/cluster-api-runtime-extensions-nutanix/README.md index 4c63dd9bd..95addabd1 100644 --- a/charts/cluster-api-runtime-extensions-nutanix/README.md +++ b/charts/cluster-api-runtime-extensions-nutanix/README.md @@ -62,6 +62,8 @@ A Helm chart for cluster-api-runtime-extensions-nutanix | hooks.nfd.crsStrategy.defaultInstallationConfigMap.name | string | `"node-feature-discovery"` | | | hooks.nfd.helmAddonStrategy.defaultValueTemplateConfigMap.create | bool | `true` | | | hooks.nfd.helmAddonStrategy.defaultValueTemplateConfigMap.name | string | `"default-nfd-helm-values-template"` | | +| hooks.serviceLoadbalancer.metalLB.defaultValueTemplateConfigMap.create | bool | `true` | | +| hooks.serviceLoadbalancer.metalLB.defaultValueTemplateConfigMap.name | string | `"default-metallb-helm-values-template"` | | | hooks.virtualIP.kubeVip.defaultTemplateConfigMap.create | bool | `true` | | | hooks.virtualIP.kubeVip.defaultTemplateConfigMap.name | string | `"default-kube-vip-template"` | | | image.pullPolicy | string | `"IfNotPresent"` | | diff --git a/charts/cluster-api-runtime-extensions-nutanix/templates/helm-config.yaml b/charts/cluster-api-runtime-extensions-nutanix/templates/helm-config.yaml index 84a4292e6..62ae1ad10 100644 --- a/charts/cluster-api-runtime-extensions-nutanix/templates/helm-config.yaml +++ b/charts/cluster-api-runtime-extensions-nutanix/templates/helm-config.yaml @@ -15,6 +15,10 @@ data: ChartName: cluster-autoscaler ChartVersion: 9.35.0 RepositoryURL: https://kubernetes.github.io/autoscaler + metallb: | + ChartName: metallb + ChartVersion: v0.14.5 + RepositoryURL: https://metallb.github.io/metallb nfd: | ChartName: node-feature-discovery ChartVersion: 0.15.2 diff --git a/charts/cluster-api-runtime-extensions-nutanix/templates/serviceloadbalancer/metallb/helm-addon-installation.yaml b/charts/cluster-api-runtime-extensions-nutanix/templates/serviceloadbalancer/metallb/helm-addon-installation.yaml new file mode 100644 index 000000000..1ddba8cb3 --- /dev/null +++ b/charts/cluster-api-runtime-extensions-nutanix/templates/serviceloadbalancer/metallb/helm-addon-installation.yaml @@ -0,0 +1,31 @@ +# Copyright 2023 D2iQ, Inc. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 + +{{- if .Values.hooks.serviceLoadbalancer.metalLB.defaultValueTemplateConfigMap.create }} +apiVersion: v1 +kind: ConfigMap +metadata: + name: '{{ .Values.hooks.serviceLoadbalancer.metalLB.defaultValueTemplateConfigMap.name }}' +data: + values.yaml: |- + controller: + tolerations: + - key: node-role.kubernetes.io/control-plane + effect: NoSchedule + operator: Exists + - key: CriticalAddonsOnly + operator: Exists + - effect: NoExecute + operator: Exists + tolerationSeconds: 300 + speaker: + tolerations: + - key: node-role.kubernetes.io/control-plane + effect: NoSchedule + operator: Exists + - key: CriticalAddonsOnly + operator: Exists + - effect: NoExecute + operator: Exists + tolerationSeconds: 300 +{{- end -}} diff --git a/charts/cluster-api-runtime-extensions-nutanix/values.yaml b/charts/cluster-api-runtime-extensions-nutanix/values.yaml index dfc59c36c..39aadf53e 100644 --- a/charts/cluster-api-runtime-extensions-nutanix/values.yaml +++ b/charts/cluster-api-runtime-extensions-nutanix/values.yaml @@ -71,7 +71,11 @@ hooks: defaultValueTemplateConfigMap: create: true name: default-cluster-autoscaler-helm-values-template - + serviceLoadbalancer: + metalLB: + defaultValueTemplateConfigMap: + create: true + name: default-metallb-helm-values-template virtualIP: kubeVip: defaultTemplateConfigMap: diff --git a/hack/addons/kustomize/metallb/kustomization.yaml.tmpl b/hack/addons/kustomize/metallb/kustomization.yaml.tmpl new file mode 100644 index 000000000..4c36e3ffd --- /dev/null +++ b/hack/addons/kustomize/metallb/kustomization.yaml.tmpl @@ -0,0 +1,27 @@ +# Copyright 2024 D2iQ, Inc. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 + +# NOTE This file is used by the tool in `hack/tools/helm-cm` to add +# metallb chart metadata to the "helm-addons" ConfigMap. The tool takes +# a kustomization as input. We do not use this file with kustomize. + +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization + +metadata: + name: metallb + +sortOptions: + order: fifo + +helmCharts: +- name: metallb + repo: https://metallb.github.io/metallb + releaseName: metallb + version: ${METALLB_CHART_VERSION} + valuesFile: helm-values.yaml + includeCRDs: true + skipTests: true + namespace: metallb-system + +namespace: metallb-system diff --git a/make/addons.mk b/make/addons.mk index e4124eaa3..907fa882d 100644 --- a/make/addons.mk +++ b/make/addons.mk @@ -21,6 +21,8 @@ export NUTANIX_CCM_CHART_VERSION := 0.3.3 export KUBE_VIP_VERSION := v0.8.0 +export METALLB_CHART_VERSION := v0.14.5 + .PHONY: addons.sync addons.sync: $(addprefix update-addon.,calico cilium nfd cluster-autoscaler aws-ebs-csi aws-ccm.127 aws-ccm.128 aws-ccm.129 kube-vip) diff --git a/pkg/handlers/generic/lifecycle/config/cm.go b/pkg/handlers/generic/lifecycle/config/cm.go index 89b44fa20..6aad57e9e 100644 --- a/pkg/handlers/generic/lifecycle/config/cm.go +++ b/pkg/handlers/generic/lifecycle/config/cm.go @@ -24,6 +24,7 @@ const ( NutanixStorageCSI Component = "nutanix-storage-csi" NutanixSnapshotCSI Component = "nutanix-snapshot-csi" NutanixCCM Component = "nutanix-ccm" + MetalLB Component = "metallb" ) type HelmChartGetter struct { diff --git a/pkg/handlers/generic/lifecycle/handlers.go b/pkg/handlers/generic/lifecycle/handlers.go index d34ffcf5a..bc2233a88 100644 --- a/pkg/handlers/generic/lifecycle/handlers.go +++ b/pkg/handlers/generic/lifecycle/handlers.go @@ -21,6 +21,8 @@ import ( nutanixcsi "github.com/nutanix-cloud-native/cluster-api-runtime-extensions-nutanix/pkg/handlers/generic/lifecycle/csi/nutanix-csi" "github.com/nutanix-cloud-native/cluster-api-runtime-extensions-nutanix/pkg/handlers/generic/lifecycle/nfd" "github.com/nutanix-cloud-native/cluster-api-runtime-extensions-nutanix/pkg/handlers/generic/lifecycle/servicelbgc" + "github.com/nutanix-cloud-native/cluster-api-runtime-extensions-nutanix/pkg/handlers/generic/lifecycle/serviceloadbalancer" + "github.com/nutanix-cloud-native/cluster-api-runtime-extensions-nutanix/pkg/handlers/generic/lifecycle/serviceloadbalancer/metallb" "github.com/nutanix-cloud-native/cluster-api-runtime-extensions-nutanix/pkg/handlers/options" ) @@ -34,6 +36,7 @@ type Handlers struct { nutnaixCSIConfig *nutanixcsi.NutanixCSIConfig awsccmConfig *awsccm.AWSCCMConfig nutanixCCMConfig *nutanixccm.Config + metalLBConfig *metallb.Config } func New( @@ -51,6 +54,7 @@ func New( awsccmConfig: &awsccm.AWSCCMConfig{GlobalOptions: globalOptions}, nutnaixCSIConfig: &nutanixcsi.NutanixCSIConfig{GlobalOptions: globalOptions}, nutanixCCMConfig: &nutanixccm.Config{GlobalOptions: globalOptions}, + metalLBConfig: &metallb.Config{GlobalOptions: globalOptions}, } } @@ -76,6 +80,13 @@ func (h *Handlers) AllHandlers(mgr manager.Manager) []handlers.Named { helmChartInfoGetter, ), } + serviceLoadbalancerHandlers := map[string]serviceloadbalancer.ServiceLoadbalancerProvider{ + v1alpha1.ServiceLoadbalancerProviderMetalLB: metallb.New( + mgr.GetClient(), + h.metalLBConfig, + helmChartInfoGetter, + ), + } return []handlers.Named{ calico.New(mgr.GetClient(), h.calicoCNIConfig, helmChartInfoGetter), cilium.New(mgr.GetClient(), h.ciliumCNIConfig, helmChartInfoGetter), @@ -84,6 +95,7 @@ func (h *Handlers) AllHandlers(mgr manager.Manager) []handlers.Named { servicelbgc.New(mgr.GetClient()), csi.New(mgr.GetClient(), csiHandlers), ccm.New(mgr.GetClient(), ccmHandlers), + serviceloadbalancer.New(mgr.GetClient(), serviceLoadbalancerHandlers), } } @@ -96,4 +108,5 @@ func (h *Handlers) AddFlags(flagSet *pflag.FlagSet) { h.awsccmConfig.AddFlags("awsccm", pflag.CommandLine) h.nutnaixCSIConfig.AddFlags("nutanixcsi", flagSet) h.nutanixCCMConfig.AddFlags("nutanixccm", flagSet) + h.metalLBConfig.AddFlags("metallb", flagSet) } diff --git a/pkg/handlers/generic/lifecycle/serviceloadbalancer/handler.go b/pkg/handlers/generic/lifecycle/serviceloadbalancer/handler.go new file mode 100644 index 000000000..8067da081 --- /dev/null +++ b/pkg/handlers/generic/lifecycle/serviceloadbalancer/handler.go @@ -0,0 +1,131 @@ +// Copyright 2023 D2iQ, Inc. All rights reserved. +// SPDX-License-Identifier: Apache-2.0 + +package serviceloadbalancer + +import ( + "context" + "fmt" + + "github.com/go-logr/logr" + clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1" + runtimehooksv1 "sigs.k8s.io/cluster-api/exp/runtime/hooks/api/v1alpha1" + ctrl "sigs.k8s.io/controller-runtime" + ctrlclient "sigs.k8s.io/controller-runtime/pkg/client" + + "github.com/nutanix-cloud-native/cluster-api-runtime-extensions-nutanix/api/v1alpha1" + commonhandlers "github.com/nutanix-cloud-native/cluster-api-runtime-extensions-nutanix/common/pkg/capi/clustertopology/handlers" + "github.com/nutanix-cloud-native/cluster-api-runtime-extensions-nutanix/common/pkg/capi/clustertopology/handlers/lifecycle" + "github.com/nutanix-cloud-native/cluster-api-runtime-extensions-nutanix/common/pkg/capi/clustertopology/variables" + "github.com/nutanix-cloud-native/cluster-api-runtime-extensions-nutanix/pkg/handlers/generic/clusterconfig" +) + +type ServiceLoadbalancerProvider interface { + Apply( + ctx context.Context, + cluster *clusterv1.Cluster, + log logr.Logger, + ) error +} + +type ServiceLoadbalancerHandler struct { + client ctrlclient.Client + variableName string + variablePath []string + ProviderHandler map[string]ServiceLoadbalancerProvider +} + +var ( + _ commonhandlers.Named = &ServiceLoadbalancerHandler{} + _ lifecycle.AfterControlPlaneInitialized = &ServiceLoadbalancerHandler{} +) + +func New( + c ctrlclient.Client, + handlers map[string]ServiceLoadbalancerProvider, +) *ServiceLoadbalancerHandler { + return &ServiceLoadbalancerHandler{ + client: c, + variableName: clusterconfig.MetaVariableName, + variablePath: []string{"addons", v1alpha1.ServiceLoadbalancerVariableName}, + ProviderHandler: handlers, + } +} + +func (c *ServiceLoadbalancerHandler) Name() string { + return "ServiceLoadbalancerHandler" +} + +func (c *ServiceLoadbalancerHandler) AfterControlPlaneInitialized( + ctx context.Context, + req *runtimehooksv1.AfterControlPlaneInitializedRequest, + resp *runtimehooksv1.AfterControlPlaneInitializedResponse, +) { + clusterKey := ctrlclient.ObjectKeyFromObject(&req.Cluster) + + log := ctrl.LoggerFrom(ctx).WithValues( + "cluster", + clusterKey, + ) + + varMap := variables.ClusterVariablesToVariablesMap(req.Cluster.Spec.Topology.Variables) + + slb, err := variables.Get[v1alpha1.ServiceLoadbalancer]( + varMap, + c.variableName, + c.variablePath...) + if err != nil { + log.Error( + err, + "failed to read ServiceLoadbalancer provider from cluster definition", + ) + resp.SetStatus(runtimehooksv1.ResponseStatusFailure) + resp.SetMessage( + fmt.Sprintf("failed to read ServiceLoadbalancer provider from cluster definition: %v", + err, + ), + ) + return + } + + handler, ok := c.ProviderHandler[slb.Provider] + if !ok { + err = fmt.Errorf("unknown ServiceLoadbalancer Provider") + log.Error(err, "provider", slb.Provider) + resp.SetStatus(runtimehooksv1.ResponseStatusFailure) + resp.SetMessage( + fmt.Sprintf("%s %s", err, slb.Provider), + ) + return + } + + log.Info(fmt.Sprintf("Deploying ServiceLoadbalancer provider %s", slb.Provider)) + err = handler.Apply( + ctx, + &req.Cluster, + log, + ) + if err != nil { + log.Error( + err, + fmt.Sprintf( + "failed to deploy ServiceLoadbalancer provider %s", + slb.Provider, + ), + ) + resp.SetStatus(runtimehooksv1.ResponseStatusFailure) + resp.SetMessage( + fmt.Sprintf( + "failed to deploy ServiceLoadbalancer provider: %v", + err, + ), + ) + } + + resp.SetStatus(runtimehooksv1.ResponseStatusSuccess) + resp.SetMessage( + fmt.Sprintf( + "deployed ServiceLoadbalancer provider %s", + slb.Provider), + ) +} diff --git a/pkg/handlers/generic/lifecycle/serviceloadbalancer/metallb/handler.go b/pkg/handlers/generic/lifecycle/serviceloadbalancer/metallb/handler.go new file mode 100644 index 000000000..5f81981d8 --- /dev/null +++ b/pkg/handlers/generic/lifecycle/serviceloadbalancer/metallb/handler.go @@ -0,0 +1,155 @@ +// Copyright 2023 D2iQ, Inc. All rights reserved. +// SPDX-License-Identifier: Apache-2.0 + +package metallb + +import ( + "context" + "fmt" + + "github.com/go-logr/logr" + "github.com/spf13/pflag" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1" + "sigs.k8s.io/cluster-api/controllers/remote" + ctrlclient "sigs.k8s.io/controller-runtime/pkg/client" + "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" + + caaphv1 "github.com/nutanix-cloud-native/cluster-api-runtime-extensions-nutanix/api/external/sigs.k8s.io/cluster-api-addon-provider-helm/api/v1alpha1" + "github.com/nutanix-cloud-native/cluster-api-runtime-extensions-nutanix/common/pkg/k8s/client" + "github.com/nutanix-cloud-native/cluster-api-runtime-extensions-nutanix/pkg/handlers/generic/lifecycle/config" + lifecycleutils "github.com/nutanix-cloud-native/cluster-api-runtime-extensions-nutanix/pkg/handlers/generic/lifecycle/utils" + "github.com/nutanix-cloud-native/cluster-api-runtime-extensions-nutanix/pkg/handlers/options" +) + +const ( + defaultHelmReleaseName = "metallb" + defaultHelmReleaseNamespace = "metallb-system" +) + +// These labels allow the MetalLB speaker pod to obtain elevated permissions, +// which it requires in order to perform its network functionalities. +var podSecurityReleaseNamespaceLabels = map[string]string{ + "pod-security.kubernetes.io/enforce": "privileged", + "pod-security.kubernetes.io/audit": "privileged", + "pod-security.kubernetes.io/warn": "privileged", +} + +type Config struct { + *options.GlobalOptions + + defaultValuesTemplateConfigMapName string +} + +func (c *Config) AddFlags(prefix string, flags *pflag.FlagSet) { + flags.StringVar( + &c.defaultValuesTemplateConfigMapName, + prefix+".default-values-template-configmap-name", + "default-metallb-helm-values-template", + "default values ConfigMap name", + ) +} + +type MetalLB struct { + client ctrlclient.Client + config *Config + helmChartInfoGetter *config.HelmChartGetter +} + +func New( + c ctrlclient.Client, + cfg *Config, + helmChartInfoGetter *config.HelmChartGetter, +) *MetalLB { + return &MetalLB{ + client: c, + config: cfg, + helmChartInfoGetter: helmChartInfoGetter, + } +} + +func (n *MetalLB) Apply( + ctx context.Context, + cluster *clusterv1.Cluster, + log logr.Logger, +) error { + log.Info("Applying MetalLB installation") + + values, err := lifecycleutils.RetrieveValuesTemplate( + ctx, + n.client, + n.config.defaultValuesTemplateConfigMapName, + n.config.DefaultsNamespace(), + ) + if err != nil { + return fmt.Errorf( + "failed to retrieve MetalLB installation values template ConfigMap for cluster: %w", + err, + ) + } + + remoteClient, err := remote.NewClusterClient( + ctx, + "", + n.client, + ctrlclient.ObjectKeyFromObject(cluster), + ) + if err != nil { + return fmt.Errorf("error creating remote cluster client: %w", err) + } + + err = lifecycleutils.EnsureNamespaceWithMetadata( + ctx, + remoteClient, + defaultHelmReleaseNamespace, + podSecurityReleaseNamespaceLabels, + nil, + ) + if err != nil { + return fmt.Errorf( + "failed to ensure release namespace %q exists: %w", + defaultHelmReleaseName, + err, + ) + } + + helmChartInfo, err := n.helmChartInfoGetter.For(ctx, log, config.MetalLB) + if err != nil { + return fmt.Errorf("failed to get MetalLB helm chart: %w", err) + } + + hcp := &caaphv1.HelmChartProxy{ + TypeMeta: metav1.TypeMeta{ + APIVersion: caaphv1.GroupVersion.String(), + Kind: "HelmChartProxy", + }, + ObjectMeta: metav1.ObjectMeta{ + Namespace: cluster.Namespace, + Name: "metallb-" + cluster.Name, + }, + Spec: caaphv1.HelmChartProxySpec{ + RepoURL: helmChartInfo.Repository, + ChartName: helmChartInfo.Name, + ClusterSelector: metav1.LabelSelector{ + MatchLabels: map[string]string{clusterv1.ClusterNameLabel: cluster.Name}, + }, + ReleaseNamespace: defaultHelmReleaseNamespace, + ReleaseName: defaultHelmReleaseName, + Version: helmChartInfo.Version, + ValuesTemplate: values, + }, + } + + if err = controllerutil.SetOwnerReference(cluster, hcp, n.client.Scheme()); err != nil { + return fmt.Errorf( + "failed to set owner reference on MetalLB installation HelmChartProxy: %w", + err, + ) + } + + if err = client.ServerSideApply(ctx, n.client, hcp); err != nil { + return fmt.Errorf("failed to apply MetalLB installation HelmChartProxy: %w", err) + } + + return nil +} From 1bfcc18121e66ea383a9f73c9828dbfdda3a71fa Mon Sep 17 00:00:00 2001 From: Daniel Lipovetsky Date: Wed, 1 May 2024 09:34:35 -0700 Subject: [PATCH 3/4] docs: Document the ServiceLoadbalancer Addon --- docs/content/addons/serviceloadbalancer.md | 40 ++++++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 docs/content/addons/serviceloadbalancer.md diff --git a/docs/content/addons/serviceloadbalancer.md b/docs/content/addons/serviceloadbalancer.md new file mode 100644 index 000000000..40de218a1 --- /dev/null +++ b/docs/content/addons/serviceloadbalancer.md @@ -0,0 +1,40 @@ ++++ +title = "Service Loadbalancer" ++++ + +When an application running in a cluster needs to be exposed outside of the cluster, one option is +to use an [external loadbalancer][external-loadbalancer], by creating a Kubernetes Service of the +LoadBalancer type. + +The Service Loadbalancer is the component that backs this Kubernetes Service, either by creating +a Virtual IP, creating a machine that runs loadbalancer software, by delegating to APIs, such as +the underlying infrastructure, or a hardware load balancer. + +CAREN currently supports the following Service Loadbalancers: + +- [MetalLB][metallb] + +## Example + +To enable deployment of MetalLB on a cluster, specify the following values: + +```yaml +apiVersion: cluster.x-k8s.io/v1beta1 +kind: Cluster +metadata: + name: +spec: + topology: + variables: + - name: clusterConfig + value: + addons: + serviceLoadbalancer: + provider: MetalLB +``` + +See [MetalLB documentation][metallb-configuration] for details on configuration. + +[external-loadbalancer]: https://kubernetes.io/docs/tasks/access-application-cluster/create-external-load-balancer/ +[metallb]: https://metallb.org +[metallb-configuration]: https://metallb.org/configuration/ From 410c70174b0968e7a5d77531b6a37d6c5fa0816d Mon Sep 17 00:00:00 2001 From: Jimmi Dyson Date: Thu, 2 May 2024 09:15:51 +0100 Subject: [PATCH 4/4] fixup! refactor: Consistently refer to LoadBalancer rather than Loadbalancer --- api/v1alpha1/addon_types.go | 8 ++-- api/v1alpha1/constants.go | 4 +- .../caren.nutanix.com_awsclusterconfigs.yaml | 4 +- ...aren.nutanix.com_dockerclusterconfigs.yaml | 4 +- ...ren.nutanix.com_nutanixclusterconfigs.yaml | 4 +- api/v1alpha1/zz_generated.deepcopy.go | 14 +++---- .../README.md | 4 +- .../metallb/helm-addon-installation.yaml | 4 +- .../values.yaml | 2 +- docs/content/addons/serviceloadbalancer.md | 24 +++++------ .../controlplaneloadbalancer/inject_test.go | 4 +- pkg/handlers/generic/lifecycle/handlers.go | 6 +-- .../lifecycle/serviceloadbalancer/handler.go | 40 +++++++++---------- 13 files changed, 61 insertions(+), 61 deletions(-) diff --git a/api/v1alpha1/addon_types.go b/api/v1alpha1/addon_types.go index 37e52cb98..1fab8f983 100644 --- a/api/v1alpha1/addon_types.go +++ b/api/v1alpha1/addon_types.go @@ -24,7 +24,7 @@ const ( VirtualIPProviderKubeVIP = "KubeVIP" - ServiceLoadbalancerProviderMetalLB = "MetalLB" + ServiceLoadBalancerProviderMetalLB = "MetalLB" AddonStrategyClusterResourceSet AddonStrategy = "ClusterResourceSet" AddonStrategyHelmAddon AddonStrategy = "HelmAddon" @@ -73,7 +73,7 @@ type Addons struct { CSIProviders *CSI `json:"csi,omitempty"` // +optional - ServiceLoadbalancer *ServiceLoadbalancer `json:"serviceLoadbalancer,omitempty"` + ServiceLoadBalancer *ServiceLoadBalancer `json:"serviceLoadBalancer,omitempty"` } type AddonStrategy string @@ -166,8 +166,8 @@ type CCM struct { Credentials *corev1.LocalObjectReference `json:"credentials,omitempty"` } -type ServiceLoadbalancer struct { - // The Loadbalancer-type Service provider to deploy. Not required in infrastructures where +type ServiceLoadBalancer struct { + // The LoadBalancer-type Service provider to deploy. Not required in infrastructures where // the CCM acts as the provider. // +kubebuilder:validation:Enum=MetalLB Provider string `json:"provider"` diff --git a/api/v1alpha1/constants.go b/api/v1alpha1/constants.go index cf109febc..9f4ea4d95 100644 --- a/api/v1alpha1/constants.go +++ b/api/v1alpha1/constants.go @@ -14,6 +14,6 @@ const ( AWSVariableName = "aws" // NutanixVariableName is the Nutanix config patch variable name. NutanixVariableName = "nutanix" - // ServiceLoadbalancerName is the Service Loadbalancer config patch variable name. - ServiceLoadbalancerVariableName = "serviceLoadbalancer" + // ServiceLoadBalancerName is the Service LoadBalancer config patch variable name. + ServiceLoadBalancerVariableName = "serviceLoadBalancer" ) diff --git a/api/v1alpha1/crds/caren.nutanix.com_awsclusterconfigs.yaml b/api/v1alpha1/crds/caren.nutanix.com_awsclusterconfigs.yaml index cc67e057f..0d9087ec8 100644 --- a/api/v1alpha1/crds/caren.nutanix.com_awsclusterconfigs.yaml +++ b/api/v1alpha1/crds/caren.nutanix.com_awsclusterconfigs.yaml @@ -201,11 +201,11 @@ spec: required: - strategy type: object - serviceLoadbalancer: + serviceLoadBalancer: properties: provider: description: |- - The Loadbalancer-type Service provider to deploy. Not required in infrastructures where + The LoadBalancer-type Service provider to deploy. Not required in infrastructures where the CCM acts as the provider. enum: - MetalLB diff --git a/api/v1alpha1/crds/caren.nutanix.com_dockerclusterconfigs.yaml b/api/v1alpha1/crds/caren.nutanix.com_dockerclusterconfigs.yaml index 76daa812b..60025cfb4 100644 --- a/api/v1alpha1/crds/caren.nutanix.com_dockerclusterconfigs.yaml +++ b/api/v1alpha1/crds/caren.nutanix.com_dockerclusterconfigs.yaml @@ -202,11 +202,11 @@ spec: required: - strategy type: object - serviceLoadbalancer: + serviceLoadBalancer: properties: provider: description: |- - The Loadbalancer-type Service provider to deploy. Not required in infrastructures where + The LoadBalancer-type Service provider to deploy. Not required in infrastructures where the CCM acts as the provider. enum: - MetalLB diff --git a/api/v1alpha1/crds/caren.nutanix.com_nutanixclusterconfigs.yaml b/api/v1alpha1/crds/caren.nutanix.com_nutanixclusterconfigs.yaml index c3bb3e6c4..318799881 100644 --- a/api/v1alpha1/crds/caren.nutanix.com_nutanixclusterconfigs.yaml +++ b/api/v1alpha1/crds/caren.nutanix.com_nutanixclusterconfigs.yaml @@ -202,11 +202,11 @@ spec: required: - strategy type: object - serviceLoadbalancer: + serviceLoadBalancer: properties: provider: description: |- - The Loadbalancer-type Service provider to deploy. Not required in infrastructures where + The LoadBalancer-type Service provider to deploy. Not required in infrastructures where the CCM acts as the provider. enum: - MetalLB diff --git a/api/v1alpha1/zz_generated.deepcopy.go b/api/v1alpha1/zz_generated.deepcopy.go index ffe936967..bbb8c1734 100644 --- a/api/v1alpha1/zz_generated.deepcopy.go +++ b/api/v1alpha1/zz_generated.deepcopy.go @@ -350,9 +350,9 @@ func (in *Addons) DeepCopyInto(out *Addons) { *out = new(CSI) (*in).DeepCopyInto(*out) } - if in.ServiceLoadbalancer != nil { - in, out := &in.ServiceLoadbalancer, &out.ServiceLoadbalancer - *out = new(ServiceLoadbalancer) + if in.ServiceLoadBalancer != nil { + in, out := &in.ServiceLoadBalancer, &out.ServiceLoadBalancer + *out = new(ServiceLoadBalancer) **out = **in } } @@ -1125,16 +1125,16 @@ func (in *SecurityGroup) DeepCopy() *SecurityGroup { } // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *ServiceLoadbalancer) DeepCopyInto(out *ServiceLoadbalancer) { +func (in *ServiceLoadBalancer) DeepCopyInto(out *ServiceLoadBalancer) { *out = *in } -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ServiceLoadbalancer. -func (in *ServiceLoadbalancer) DeepCopy() *ServiceLoadbalancer { +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ServiceLoadBalancer. +func (in *ServiceLoadBalancer) DeepCopy() *ServiceLoadBalancer { if in == nil { return nil } - out := new(ServiceLoadbalancer) + out := new(ServiceLoadBalancer) in.DeepCopyInto(out) return out } diff --git a/charts/cluster-api-runtime-extensions-nutanix/README.md b/charts/cluster-api-runtime-extensions-nutanix/README.md index 95addabd1..03d53d671 100644 --- a/charts/cluster-api-runtime-extensions-nutanix/README.md +++ b/charts/cluster-api-runtime-extensions-nutanix/README.md @@ -62,8 +62,8 @@ A Helm chart for cluster-api-runtime-extensions-nutanix | hooks.nfd.crsStrategy.defaultInstallationConfigMap.name | string | `"node-feature-discovery"` | | | hooks.nfd.helmAddonStrategy.defaultValueTemplateConfigMap.create | bool | `true` | | | hooks.nfd.helmAddonStrategy.defaultValueTemplateConfigMap.name | string | `"default-nfd-helm-values-template"` | | -| hooks.serviceLoadbalancer.metalLB.defaultValueTemplateConfigMap.create | bool | `true` | | -| hooks.serviceLoadbalancer.metalLB.defaultValueTemplateConfigMap.name | string | `"default-metallb-helm-values-template"` | | +| hooks.serviceLoadBalancer.metalLB.defaultValueTemplateConfigMap.create | bool | `true` | | +| hooks.serviceLoadBalancer.metalLB.defaultValueTemplateConfigMap.name | string | `"default-metallb-helm-values-template"` | | | hooks.virtualIP.kubeVip.defaultTemplateConfigMap.create | bool | `true` | | | hooks.virtualIP.kubeVip.defaultTemplateConfigMap.name | string | `"default-kube-vip-template"` | | | image.pullPolicy | string | `"IfNotPresent"` | | diff --git a/charts/cluster-api-runtime-extensions-nutanix/templates/serviceloadbalancer/metallb/helm-addon-installation.yaml b/charts/cluster-api-runtime-extensions-nutanix/templates/serviceloadbalancer/metallb/helm-addon-installation.yaml index 1ddba8cb3..c0bc2e238 100644 --- a/charts/cluster-api-runtime-extensions-nutanix/templates/serviceloadbalancer/metallb/helm-addon-installation.yaml +++ b/charts/cluster-api-runtime-extensions-nutanix/templates/serviceloadbalancer/metallb/helm-addon-installation.yaml @@ -1,11 +1,11 @@ # Copyright 2023 D2iQ, Inc. All rights reserved. # SPDX-License-Identifier: Apache-2.0 -{{- if .Values.hooks.serviceLoadbalancer.metalLB.defaultValueTemplateConfigMap.create }} +{{- if .Values.hooks.serviceLoadBalancer.metalLB.defaultValueTemplateConfigMap.create }} apiVersion: v1 kind: ConfigMap metadata: - name: '{{ .Values.hooks.serviceLoadbalancer.metalLB.defaultValueTemplateConfigMap.name }}' + name: '{{ .Values.hooks.serviceLoadBalancer.metalLB.defaultValueTemplateConfigMap.name }}' data: values.yaml: |- controller: diff --git a/charts/cluster-api-runtime-extensions-nutanix/values.yaml b/charts/cluster-api-runtime-extensions-nutanix/values.yaml index 39aadf53e..4db472071 100644 --- a/charts/cluster-api-runtime-extensions-nutanix/values.yaml +++ b/charts/cluster-api-runtime-extensions-nutanix/values.yaml @@ -71,7 +71,7 @@ hooks: defaultValueTemplateConfigMap: create: true name: default-cluster-autoscaler-helm-values-template - serviceLoadbalancer: + serviceLoadBalancer: metalLB: defaultValueTemplateConfigMap: create: true diff --git a/docs/content/addons/serviceloadbalancer.md b/docs/content/addons/serviceloadbalancer.md index 40de218a1..cc767c146 100644 --- a/docs/content/addons/serviceloadbalancer.md +++ b/docs/content/addons/serviceloadbalancer.md @@ -1,18 +1,18 @@ +++ -title = "Service Loadbalancer" +title = "Service LoadBalancer" +++ When an application running in a cluster needs to be exposed outside of the cluster, one option is -to use an [external loadbalancer][external-loadbalancer], by creating a Kubernetes Service of the -LoadBalancer type. +to use an [external load balancer], by creating a Kubernetes Service of the +`LoadBalancer` type. -The Service Loadbalancer is the component that backs this Kubernetes Service, either by creating -a Virtual IP, creating a machine that runs loadbalancer software, by delegating to APIs, such as +The Service Load Balancer is the component that backs this Kubernetes Service, either by creating +a Virtual IP, creating a machine that runs load balancer software, by delegating to APIs, such as the underlying infrastructure, or a hardware load balancer. -CAREN currently supports the following Service Loadbalancers: +CAREN currently supports the following Service Load Balancers: -- [MetalLB][metallb] +- [MetalLB] ## Example @@ -29,12 +29,12 @@ spec: - name: clusterConfig value: addons: - serviceLoadbalancer: + serviceLoadBalancer: provider: MetalLB ``` -See [MetalLB documentation][metallb-configuration] for details on configuration. +See [MetalLB documentation] for details on configuration. -[external-loadbalancer]: https://kubernetes.io/docs/tasks/access-application-cluster/create-external-load-balancer/ -[metallb]: https://metallb.org -[metallb-configuration]: https://metallb.org/configuration/ +[external load balancer]: https://kubernetes.io/docs/tasks/access-application-cluster/create-external-load-balancer/ +[MetalLB]: https://metallb.org +[MetalLB documentation]: https://metallb.org/configuration/ diff --git a/pkg/handlers/aws/mutation/controlplaneloadbalancer/inject_test.go b/pkg/handlers/aws/mutation/controlplaneloadbalancer/inject_test.go index 030d5fb7b..161221045 100644 --- a/pkg/handlers/aws/mutation/controlplaneloadbalancer/inject_test.go +++ b/pkg/handlers/aws/mutation/controlplaneloadbalancer/inject_test.go @@ -34,7 +34,7 @@ var _ = Describe("Generate AWS ControlPlane LoadBalancer patches", func() { Name: "unset variable", }, { - Name: "ControlPlaneLoadbalancer scheme set to internet-facing", + Name: "ControlPlaneLoadBalancer scheme set to internet-facing", Vars: []runtimehooksv1.Variable{ capitest.VariableWithValue( clusterconfig.MetaVariableName, @@ -55,7 +55,7 @@ var _ = Describe("Generate AWS ControlPlane LoadBalancer patches", func() { }}, }, { - Name: "ControlPlaneLoadbalancer scheme set to internal", + Name: "ControlPlaneLoadBalancer scheme set to internal", Vars: []runtimehooksv1.Variable{ capitest.VariableWithValue( clusterconfig.MetaVariableName, diff --git a/pkg/handlers/generic/lifecycle/handlers.go b/pkg/handlers/generic/lifecycle/handlers.go index bc2233a88..97f891986 100644 --- a/pkg/handlers/generic/lifecycle/handlers.go +++ b/pkg/handlers/generic/lifecycle/handlers.go @@ -80,8 +80,8 @@ func (h *Handlers) AllHandlers(mgr manager.Manager) []handlers.Named { helmChartInfoGetter, ), } - serviceLoadbalancerHandlers := map[string]serviceloadbalancer.ServiceLoadbalancerProvider{ - v1alpha1.ServiceLoadbalancerProviderMetalLB: metallb.New( + serviceLoadBalancerHandlers := map[string]serviceloadbalancer.ServiceLoadBalancerProvider{ + v1alpha1.ServiceLoadBalancerProviderMetalLB: metallb.New( mgr.GetClient(), h.metalLBConfig, helmChartInfoGetter, @@ -95,7 +95,7 @@ func (h *Handlers) AllHandlers(mgr manager.Manager) []handlers.Named { servicelbgc.New(mgr.GetClient()), csi.New(mgr.GetClient(), csiHandlers), ccm.New(mgr.GetClient(), ccmHandlers), - serviceloadbalancer.New(mgr.GetClient(), serviceLoadbalancerHandlers), + serviceloadbalancer.New(mgr.GetClient(), serviceLoadBalancerHandlers), } } diff --git a/pkg/handlers/generic/lifecycle/serviceloadbalancer/handler.go b/pkg/handlers/generic/lifecycle/serviceloadbalancer/handler.go index 8067da081..bc377f5a9 100644 --- a/pkg/handlers/generic/lifecycle/serviceloadbalancer/handler.go +++ b/pkg/handlers/generic/lifecycle/serviceloadbalancer/handler.go @@ -20,7 +20,7 @@ import ( "github.com/nutanix-cloud-native/cluster-api-runtime-extensions-nutanix/pkg/handlers/generic/clusterconfig" ) -type ServiceLoadbalancerProvider interface { +type ServiceLoadBalancerProvider interface { Apply( ctx context.Context, cluster *clusterv1.Cluster, @@ -28,35 +28,35 @@ type ServiceLoadbalancerProvider interface { ) error } -type ServiceLoadbalancerHandler struct { +type ServiceLoadBalancerHandler struct { client ctrlclient.Client variableName string variablePath []string - ProviderHandler map[string]ServiceLoadbalancerProvider + ProviderHandler map[string]ServiceLoadBalancerProvider } var ( - _ commonhandlers.Named = &ServiceLoadbalancerHandler{} - _ lifecycle.AfterControlPlaneInitialized = &ServiceLoadbalancerHandler{} + _ commonhandlers.Named = &ServiceLoadBalancerHandler{} + _ lifecycle.AfterControlPlaneInitialized = &ServiceLoadBalancerHandler{} ) func New( c ctrlclient.Client, - handlers map[string]ServiceLoadbalancerProvider, -) *ServiceLoadbalancerHandler { - return &ServiceLoadbalancerHandler{ + handlers map[string]ServiceLoadBalancerProvider, +) *ServiceLoadBalancerHandler { + return &ServiceLoadBalancerHandler{ client: c, variableName: clusterconfig.MetaVariableName, - variablePath: []string{"addons", v1alpha1.ServiceLoadbalancerVariableName}, + variablePath: []string{"addons", v1alpha1.ServiceLoadBalancerVariableName}, ProviderHandler: handlers, } } -func (c *ServiceLoadbalancerHandler) Name() string { - return "ServiceLoadbalancerHandler" +func (c *ServiceLoadBalancerHandler) Name() string { + return "ServiceLoadBalancerHandler" } -func (c *ServiceLoadbalancerHandler) AfterControlPlaneInitialized( +func (c *ServiceLoadBalancerHandler) AfterControlPlaneInitialized( ctx context.Context, req *runtimehooksv1.AfterControlPlaneInitializedRequest, resp *runtimehooksv1.AfterControlPlaneInitializedResponse, @@ -70,18 +70,18 @@ func (c *ServiceLoadbalancerHandler) AfterControlPlaneInitialized( varMap := variables.ClusterVariablesToVariablesMap(req.Cluster.Spec.Topology.Variables) - slb, err := variables.Get[v1alpha1.ServiceLoadbalancer]( + slb, err := variables.Get[v1alpha1.ServiceLoadBalancer]( varMap, c.variableName, c.variablePath...) if err != nil { log.Error( err, - "failed to read ServiceLoadbalancer provider from cluster definition", + "failed to read ServiceLoadBalancer provider from cluster definition", ) resp.SetStatus(runtimehooksv1.ResponseStatusFailure) resp.SetMessage( - fmt.Sprintf("failed to read ServiceLoadbalancer provider from cluster definition: %v", + fmt.Sprintf("failed to read ServiceLoadBalancer provider from cluster definition: %v", err, ), ) @@ -90,7 +90,7 @@ func (c *ServiceLoadbalancerHandler) AfterControlPlaneInitialized( handler, ok := c.ProviderHandler[slb.Provider] if !ok { - err = fmt.Errorf("unknown ServiceLoadbalancer Provider") + err = fmt.Errorf("unknown ServiceLoadBalancer Provider") log.Error(err, "provider", slb.Provider) resp.SetStatus(runtimehooksv1.ResponseStatusFailure) resp.SetMessage( @@ -99,7 +99,7 @@ func (c *ServiceLoadbalancerHandler) AfterControlPlaneInitialized( return } - log.Info(fmt.Sprintf("Deploying ServiceLoadbalancer provider %s", slb.Provider)) + log.Info(fmt.Sprintf("Deploying ServiceLoadBalancer provider %s", slb.Provider)) err = handler.Apply( ctx, &req.Cluster, @@ -109,14 +109,14 @@ func (c *ServiceLoadbalancerHandler) AfterControlPlaneInitialized( log.Error( err, fmt.Sprintf( - "failed to deploy ServiceLoadbalancer provider %s", + "failed to deploy ServiceLoadBalancer provider %s", slb.Provider, ), ) resp.SetStatus(runtimehooksv1.ResponseStatusFailure) resp.SetMessage( fmt.Sprintf( - "failed to deploy ServiceLoadbalancer provider: %v", + "failed to deploy ServiceLoadBalancer provider: %v", err, ), ) @@ -125,7 +125,7 @@ func (c *ServiceLoadbalancerHandler) AfterControlPlaneInitialized( resp.SetStatus(runtimehooksv1.ResponseStatusSuccess) resp.SetMessage( fmt.Sprintf( - "deployed ServiceLoadbalancer provider %s", + "deployed ServiceLoadBalancer provider %s", slb.Provider), ) }