Skip to content

Commit

Permalink
Create hmc templates based on Release objects
Browse files Browse the repository at this point in the history
Signed-off-by: Andrei Pavlov <[email protected]>
  • Loading branch information
Kshatrix committed Sep 30, 2024
1 parent 70cb75e commit 327e2fe
Show file tree
Hide file tree
Showing 4 changed files with 108 additions and 23 deletions.
1 change: 1 addition & 0 deletions config/dev/hmc_values.yaml
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
image:
repository: hmc/controller
tag: latest
controller:
defaultRegistryURL: oci://hmc-local-registry:5000/charts
insecureRegistry: true
Expand Down
72 changes: 49 additions & 23 deletions internal/controller/release_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,10 +43,7 @@ import (
hmc "github.com/Mirantis/hmc/api/v1alpha1"
"github.com/Mirantis/hmc/internal/build"
"github.com/Mirantis/hmc/internal/helm"
)

const (
hmcTemplatesReleaseName = "hmc-templates"
"github.com/Mirantis/hmc/internal/utils"
)

// ReleaseReconciler reconciles a Template object
Expand All @@ -64,29 +61,36 @@ type ReleaseReconciler struct {
}

func (r *ReleaseReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {
l := log.FromContext(ctx).WithValues("ReleaseController", req.NamespacedName)
l := log.FromContext(ctx).WithValues("ReleaseController", req.Name)

l.Info("Reconciling Release")
defer l.Info("Release reconcile is finished")

err := r.reconcileHMCTemplates(ctx)
err := r.reconcileHMCTemplates(ctx, req)
if err != nil {
l.Error(err, "failed to reconcile HMC Templates")
return ctrl.Result{}, err
}
mgmt, err := r.getOrCreateManagement(ctx)
if err != nil {
l.Error(err, "failed to get or create Management object")
return ctrl.Result{}, err
}
err = r.ensureTemplateManagement(ctx, mgmt)
if err != nil {
l.Error(err, "failed to ensure default TemplateManagement object")
return ctrl.Result{}, err

if initialReconcile(req) {
mgmt, err := r.getOrCreateManagement(ctx)
if err != nil {
l.Error(err, "failed to get or create Management object")
return ctrl.Result{}, err
}
err = r.ensureTemplateManagement(ctx, mgmt)
if err != nil {
l.Error(err, "failed to ensure default TemplateManagement object")
return ctrl.Result{}, err
}
}
return ctrl.Result{}, nil
}

func initialReconcile(req ctrl.Request) bool {
return req.Name == ""
}

func (r *ReleaseReconciler) getOrCreateManagement(ctx context.Context) (*hmc.Management, error) {
l := log.FromContext(ctx)
mgmtObj := &hmc.Management{
Expand Down Expand Up @@ -197,27 +201,49 @@ func (r *ReleaseReconciler) ensureTemplateManagement(ctx context.Context, mgmt *
return nil
}

func (r *ReleaseReconciler) reconcileHMCTemplates(ctx context.Context) error {
func (r *ReleaseReconciler) reconcileHMCTemplates(ctx context.Context, req ctrl.Request) error {
l := log.FromContext(ctx)
if !r.CreateTemplates {
l.Info("Reconciling HMC Templates is skipped")
return nil
}
name := utils.ReleaseNameFromVersion(build.Version)
version := build.Version
var ownerRefs []metav1.OwnerReference
release := &hmc.Release{}
if !initialReconcile(req) {
if err := r.Client.Get(ctx, req.NamespacedName, release); err != nil {
l.Error(err, "failed to get Release")
return err
}
name = req.Name
version = release.Spec.Version
ownerRefs = []metav1.OwnerReference{
{
APIVersion: hmc.GroupVersion.String(),
Kind: release.Kind,
Name: release.Name,
UID: release.UID,
},
}
}

helmChart := &sourcev1.HelmChart{
ObjectMeta: metav1.ObjectMeta{
Name: r.HMCTemplatesChartName,
Name: name,
Namespace: r.SystemNamespace,
},
}

operation, err := ctrl.CreateOrUpdate(ctx, r.Client, helmChart, func() error {
helmChart.OwnerReferences = ownerRefs
if helmChart.Labels == nil {
helmChart.Labels = make(map[string]string)
}
helmChart.Labels[hmc.HMCManagedLabelKey] = hmc.HMCManagedLabelValue
helmChart.Spec = sourcev1.HelmChartSpec{
Chart: r.HMCTemplatesChartName,
Version: build.Version,
Version: version,
SourceRef: sourcev1.LocalHelmChartSourceReference{
Kind: sourcev1.HelmRepositoryKind,
Name: defaultRepoName,
Expand All @@ -230,14 +256,14 @@ func (r *ReleaseReconciler) reconcileHMCTemplates(ctx context.Context) error {
return err
}
if operation == controllerutil.OperationResultCreated || operation == controllerutil.OperationResultUpdated {
l.Info(fmt.Sprintf("Successfully %s %s/%s HelmChart", operation, r.SystemNamespace, r.HMCTemplatesChartName))
l.Info(fmt.Sprintf("Successfully %s %s/%s HelmChart", operation, r.SystemNamespace, name))
}

if _, err := helm.ArtifactReady(helmChart); err != nil {
return fmt.Errorf("HelmChart %s/%s Artifact is not ready: %w", r.SystemNamespace, r.HMCTemplatesChartName, err)
return fmt.Errorf("HelmChart %s/%s Artifact is not ready: %w", r.SystemNamespace, name, err)
}

_, operation, err = helm.ReconcileHelmRelease(ctx, r.Client, hmcTemplatesReleaseName, r.SystemNamespace, helm.ReconcileHelmReleaseOpts{
_, operation, err = helm.ReconcileHelmRelease(ctx, r.Client, name, r.SystemNamespace, helm.ReconcileHelmReleaseOpts{
ChartRef: &hcv2.CrossNamespaceSourceReference{
Kind: helmChart.Kind,
Name: helmChart.Name,
Expand All @@ -248,7 +274,7 @@ func (r *ReleaseReconciler) reconcileHMCTemplates(ctx context.Context) error {
return err
}
if operation == controllerutil.OperationResultCreated || operation == controllerutil.OperationResultUpdated {
l.Info(fmt.Sprintf("Successfully %s %s/%s HelmRelease", operation, r.SystemNamespace, hmcTemplatesReleaseName))
l.Info(fmt.Sprintf("Successfully %s %s/%s HelmRelease", operation, r.SystemNamespace, name))
}
return nil
}
Expand Down Expand Up @@ -282,7 +308,7 @@ func (r *ReleaseReconciler) SetupWithManager(mgr ctrl.Manager) error {
if !r.CreateManagement {
return nil
}
// There's no Release objects created yet and we need a way to trigger reconcile
// There's no Release objects created yet and we need to trigger reconcile
initChannel := make(chan event.GenericEvent, 1)
initChannel <- event.GenericEvent{Object: &hmc.Release{}}
return c.Watch(source.Channel(initChannel, &handler.EnqueueRequestForObject{}))
Expand Down
21 changes: 21 additions & 0 deletions internal/utils/release.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
// Copyright 2024
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package utils

import "strings"

func ReleaseNameFromVersion(version string) string {
return "hmc-" + strings.ReplaceAll(strings.TrimPrefix(version, "v"), ".", "-")
}
37 changes: 37 additions & 0 deletions internal/utils/release_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
// Copyright 2024
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package utils

import (
"testing"
)

func TestReleaseNameFromVersion(t *testing.T) {
for _, tc := range []struct {
version string
expectedName string
}{
{version: "v0.0.1", expectedName: "hmc-0-0-1"},
{version: "v0.0.1-rc", expectedName: "hmc-0-0-1-rc"},
{version: "0.0.1", expectedName: "hmc-0-0-1"},
} {
t.Run(tc.version, func(t *testing.T) {
actual := ReleaseNameFromVersion(tc.version)
if actual != tc.expectedName {
t.Errorf("expected name %s, got %s", tc.expectedName, actual)
}
})
}
}

0 comments on commit 327e2fe

Please sign in to comment.