Skip to content

Commit

Permalink
Install Sveltos as a Provider Template (k0rdent#294)
Browse files Browse the repository at this point in the history
  • Loading branch information
wahabmk authored Sep 13, 2024
1 parent 36a832a commit 512c3eb
Show file tree
Hide file tree
Showing 10 changed files with 169 additions and 70 deletions.
32 changes: 32 additions & 0 deletions api/v1alpha1/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,3 +23,35 @@ type Providers struct {
// ControlPlaneProviders is the list of CAPI control plane providers
ControlPlaneProviders []string `json:"controlPlane,omitempty"`
}

const (
// Provider CAPA
ProviderCAPAName = "cluster-api-provider-aws"
ProviderCAPASecretName = "aws-variables"
// Provider Azure
ProviderAzureName = "cluster-api-provider-azure"
// Provider K0smotron
ProviderK0smotronName = "k0smotron"
// Provider Sveltos
ProviderSveltosName = "projectsveltos"
ProviderSveltosTargetNamespace = "projectsveltos"
ProviderSveltosCreateNamespace = true
)

var (
// DefaultProviders is a map of providers that are
// installed by default, each with its default config.
DefaultProviders = map[string]map[string]interface{}{
ProviderCAPAName: {
"configSecret": map[string]interface{}{
"name": ProviderCAPASecretName,
},
},
ProviderAzureName: nil,
ProviderK0smotronName: nil,
ProviderSveltosName: {
"targetNamespace": ProviderSveltosTargetNamespace,
"createNamespace": ProviderSveltosCreateNamespace,
},
}
)
47 changes: 25 additions & 22 deletions api/v1alpha1/management_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@
package v1alpha1

import (
"encoding/json"
"fmt"

apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/util/yaml"
Expand All @@ -24,14 +27,7 @@ const (
DefaultCoreHMCTemplate = "hmc"
DefaultCoreCAPITemplate = "cluster-api"

DefaultCAPAConfig = `{
"configSecret": {
"name": "aws-variables"
}
}`

ManagementName = "hmc"

ManagementName = "hmc"
ManagementFinalizer = "hmc.mirantis.com/management"
)

Expand Down Expand Up @@ -92,21 +88,28 @@ func (m *ManagementSpec) SetDefaults() bool {
return true
}

func (m *ManagementSpec) SetProvidersDefaults() {
m.Providers = []Component{
{
Template: "k0smotron",
},
{
Template: "cluster-api-provider-aws",
Config: &apiextensionsv1.JSON{
Raw: []byte(DefaultCAPAConfig),
},
},
{
Template: "cluster-api-provider-azure",
},
func (m *ManagementSpec) SetProvidersDefaults() error {
providers := []Component{}

for name, cfg := range DefaultProviders {
c := Component{
Template: name,
}

if len(cfg) > 0 {
b, err := json.Marshal(cfg)
if err != nil {
return fmt.Errorf("failed to marshal config for %s provider: %w", name, err)
}

c.Config = &apiextensionsv1.JSON{Raw: b}
}

providers = append(providers, c)
}

m.Providers = providers
return nil
}

// ManagementStatus defines the observed state of Management
Expand Down
19 changes: 10 additions & 9 deletions internal/controller/managedcluster_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -248,15 +248,16 @@ func (r *ManagedClusterReconciler) Update(ctx context.Context, l logr.Logger, ma
})

if !managedCluster.Spec.DryRun {
ownerRef := &metav1.OwnerReference{
APIVersion: hmc.GroupVersion.String(),
Kind: hmc.ManagedClusterKind,
Name: managedCluster.Name,
UID: managedCluster.UID,
}

hr, _, err := helm.ReconcileHelmRelease(ctx, r.Client, managedCluster.Name, managedCluster.Namespace, managedCluster.Spec.Config,
ownerRef, template.Status.ChartRef, defaultReconcileInterval, nil)
hr, _, err := helm.ReconcileHelmRelease(ctx, r.Client, managedCluster.Name, managedCluster.Namespace, helm.ReconcileHelmReleaseOpts{
Values: managedCluster.Spec.Config,
OwnerReference: &metav1.OwnerReference{
APIVersion: hmc.GroupVersion.String(),
Kind: hmc.ManagedClusterKind,
Name: managedCluster.Name,
UID: managedCluster.UID,
},
ChartRef: template.Status.ChartRef,
})
if err != nil {
apimeta.SetStatusCondition(managedCluster.GetConditions(), metav1.Condition{
Type: hmc.HelmReleaseReadyCondition,
Expand Down
26 changes: 21 additions & 5 deletions internal/controller/management_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -117,8 +117,13 @@ func (r *ManagementReconciler) Update(ctx context.Context, management *hmc.Manag
continue
}

_, _, err = helm.ReconcileHelmRelease(ctx, r.Client, component.HelmReleaseName(), r.SystemNamespace, component.Config,
nil, template.Status.ChartRef, defaultReconcileInterval, component.dependsOn)
_, _, err = helm.ReconcileHelmRelease(ctx, r.Client, component.HelmReleaseName(), r.SystemNamespace, helm.ReconcileHelmReleaseOpts{
Values: component.Config,
ChartRef: template.Status.ChartRef,
DependsOn: component.dependsOn,
TargetNamespace: component.targetNamespace,
CreateNamespace: component.createNamespace,
})
if err != nil {
errMsg := fmt.Sprintf("error reconciling HelmRelease %s/%s: %s", r.SystemNamespace, component.Template, err)
updateComponentsStatus(detectedComponents, &detectedProviders, component.Template, template.Status, errMsg)
Expand Down Expand Up @@ -213,18 +218,29 @@ func (r *ManagementReconciler) removeHelmRepositories(ctx context.Context, opts
type component struct {
hmc.Component
// helm release dependencies
dependsOn []meta.NamespacedObjectReference
dependsOn []meta.NamespacedObjectReference
targetNamespace string
createNamespace bool
}

func wrappedComponents(mgmt *hmc.Management) (components []component) {
if mgmt.Spec.Core == nil {
return
}

components = append(components, component{Component: mgmt.Spec.Core.HMC})
components = append(components, component{Component: mgmt.Spec.Core.CAPI, dependsOn: []meta.NamespacedObjectReference{{Name: mgmt.Spec.Core.HMC.Template}}})
for provider := range mgmt.Spec.Providers {
components = append(components, component{Component: mgmt.Spec.Providers[provider], dependsOn: []meta.NamespacedObjectReference{{Name: mgmt.Spec.Core.CAPI.Template}}})

for i := range mgmt.Spec.Providers {
c := component{Component: mgmt.Spec.Providers[i], dependsOn: []meta.NamespacedObjectReference{{Name: mgmt.Spec.Core.CAPI.Template}}}

if mgmt.Spec.Providers[i].Template == hmc.ProviderSveltosName {
c.targetNamespace = hmc.ProviderSveltosTargetNamespace
c.createNamespace = hmc.ProviderSveltosCreateNamespace
}
components = append(components, c)
}

return
}

Expand Down
22 changes: 13 additions & 9 deletions internal/controller/release_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,10 @@ func (p *Poller) ensureManagement(ctx context.Context) error {
if !apierrors.IsNotFound(err) {
return fmt.Errorf("failed to get %s Management object", hmc.ManagementName)
}
mgmtObj.Spec.SetProvidersDefaults()

if err := mgmtObj.Spec.SetProvidersDefaults(); err != nil {
return err
}

getter := helm.NewMemoryRESTClientGetter(p.Config, p.RESTMapper())
actionConfig := new(action.Configuration)
Expand Down Expand Up @@ -190,7 +193,7 @@ func (p *Poller) reconcileDefaultHelmRepo(ctx context.Context) error {
helmRepo.Spec = sourcev1.HelmRepositorySpec{
Type: p.DefaultRepoType,
URL: p.DefaultRegistryURL,
Interval: metav1.Duration{Duration: defaultReconcileInterval},
Interval: metav1.Duration{Duration: helm.DefaultReconcileInterval},
Insecure: p.InsecureRegistry,
}
if p.RegistryCredentialsSecret != "" {
Expand Down Expand Up @@ -234,7 +237,7 @@ func (p *Poller) reconcileHMCTemplates(ctx context.Context) error {
Kind: sourcev1.HelmRepositoryKind,
Name: defaultRepoName,
},
Interval: metav1.Duration{Duration: defaultReconcileInterval},
Interval: metav1.Duration{Duration: helm.DefaultReconcileInterval},
}
return nil
})
Expand All @@ -250,12 +253,13 @@ func (p *Poller) reconcileHMCTemplates(ctx context.Context) error {
return fmt.Errorf("HelmChart %s/%s Artifact is not ready: %w", p.SystemNamespace, p.HMCTemplatesChartName, err)
}

chartRef := &hcv2.CrossNamespaceSourceReference{
Kind: helmChart.Kind,
Name: helmChart.Name,
Namespace: helmChart.Namespace,
}
_, operation, err = helm.ReconcileHelmRelease(ctx, p.Client, hmcTemplatesReleaseName, p.SystemNamespace, nil, nil, chartRef, defaultReconcileInterval, nil)
_, operation, err = helm.ReconcileHelmRelease(ctx, p.Client, hmcTemplatesReleaseName, p.SystemNamespace, helm.ReconcileHelmReleaseOpts{
ChartRef: &hcv2.CrossNamespaceSourceReference{
Kind: helmChart.Kind,
Name: helmChart.Name,
Namespace: helmChart.Namespace,
},
})
if err != nil {
return err
}
Expand Down
6 changes: 2 additions & 4 deletions internal/controller/template_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ import (
"encoding/json"
"fmt"
"strings"
"time"

helmcontrollerv2 "github.com/fluxcd/helm-controller/api/v2"
v2 "github.com/fluxcd/helm-controller/api/v2"
Expand All @@ -39,8 +38,7 @@ import (
)

const (
defaultRepoName = "hmc-templates"
defaultReconcileInterval = 10 * time.Minute
defaultRepoName = "hmc-templates"
)

// TemplateReconciler reconciles a Template object
Expand Down Expand Up @@ -291,7 +289,7 @@ func (r *TemplateReconciler) reconcileHelmChart(ctx context.Context, template Te
Kind: sourcev1.HelmRepositoryKind,
Name: defaultRepoName,
},
Interval: metav1.Duration{Duration: defaultReconcileInterval},
Interval: metav1.Duration{Duration: helm.DefaultReconcileInterval},
}
return nil
})
Expand Down
61 changes: 40 additions & 21 deletions internal/helm/release.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,45 +29,64 @@ import (
hmc "github.com/Mirantis/hmc/api/v1alpha1"
)

func ReconcileHelmRelease(
ctx context.Context,
const (
DefaultReconcileInterval = 10 * time.Minute
)

type ReconcileHelmReleaseOpts struct {
Values *apiextensionsv1.JSON
OwnerReference *metav1.OwnerReference
ChartRef *hcv2.CrossNamespaceSourceReference
ReconcileInterval *time.Duration
DependsOn []meta.NamespacedObjectReference
TargetNamespace string
CreateNamespace bool
}

func ReconcileHelmRelease(ctx context.Context,
cl client.Client,
name string,
namespace string,
values *apiextensionsv1.JSON,
ownerReference *metav1.OwnerReference,
chartRef *hcv2.CrossNamespaceSourceReference,
reconcileInterval time.Duration,
dependsOn []meta.NamespacedObjectReference,
opts ReconcileHelmReleaseOpts,
) (*hcv2.HelmRelease, controllerutil.OperationResult, error) {
helmRelease := &hcv2.HelmRelease{
hr := &hcv2.HelmRelease{
ObjectMeta: metav1.ObjectMeta{
Name: name,
Namespace: namespace,
},
}

operation, err := ctrl.CreateOrUpdate(ctx, cl, helmRelease, func() error {
if helmRelease.Labels == nil {
helmRelease.Labels = make(map[string]string)
operation, err := ctrl.CreateOrUpdate(ctx, cl, hr, func() error {
if hr.Labels == nil {
hr.Labels = make(map[string]string)
}
helmRelease.Labels[hmc.HMCManagedLabelKey] = hmc.HMCManagedLabelValue
if ownerReference != nil {
helmRelease.OwnerReferences = []metav1.OwnerReference{*ownerReference}
hr.Labels[hmc.HMCManagedLabelKey] = hmc.HMCManagedLabelValue
if opts.OwnerReference != nil {
hr.OwnerReferences = []metav1.OwnerReference{*opts.OwnerReference}
}
helmRelease.Spec = hcv2.HelmReleaseSpec{
ChartRef: chartRef,
Interval: metav1.Duration{Duration: reconcileInterval},
ReleaseName: name,
Values: values,
DependsOn: dependsOn,
hr.Spec = hcv2.HelmReleaseSpec{
ChartRef: opts.ChartRef,
Interval: metav1.Duration{Duration: func() time.Duration {
if opts.ReconcileInterval != nil {
return *opts.ReconcileInterval
}
return DefaultReconcileInterval
}()},
ReleaseName: name,
Values: opts.Values,
DependsOn: opts.DependsOn,
TargetNamespace: opts.TargetNamespace,
Install: &hcv2.Install{
CreateNamespace: opts.CreateNamespace,
},
}
return nil
})
if err != nil {
return nil, operation, err
}
return helmRelease, operation, nil

return hr, operation, nil
}

func DeleteHelmRelease(ctx context.Context, cl client.Client, name string, namespace string) error {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
apiVersion: hmc.mirantis.com/v1alpha1
kind: ProviderTemplate
metadata:
name: projectsveltos
spec:
helm:
chartName: projectsveltos
chartVersion: 0.38.1
6 changes: 6 additions & 0 deletions templates/provider/projectsveltos/Chart.lock
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
dependencies:
- name: projectsveltos
repository: https://projectsveltos.github.io/helm-charts
version: 0.38.1
digest: sha256:6fae3801c4b89a99b64a8185d21d6b12ec7cf4f40b15c5555985afa88894f4a8
generated: "2024-09-13T11:52:06.517657-04:00"
12 changes: 12 additions & 0 deletions templates/provider/projectsveltos/Chart.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
apiVersion: v2
name: projectsveltos
description: A Helm chart to refer the official projectsveltos helm chart
type: application
version: 0.38.1
appVersion: "0.38.1"
dependencies:
- name: projectsveltos
version: 0.38.1
repository: https://projectsveltos.github.io/helm-charts
annotations:
hmc.mirantis.com/type: provider

0 comments on commit 512c3eb

Please sign in to comment.