Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions controllers/export_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,7 @@ var (
GetInstantiatedChart = getInstantiatedChart

InstantiateTemplateValues = instantiateTemplateValues
FecthClusterObjects = fecthClusterObjects

IsCluterSummaryProvisioned = isCluterSummaryProvisioned
IsNamespaced = isNamespaced
Expand Down
29 changes: 16 additions & 13 deletions controllers/handlers_helm.go
Original file line number Diff line number Diff line change
Expand Up @@ -2426,8 +2426,14 @@ func getInstantiatedValues(ctx context.Context, clusterSummary *configv1beta1.Cl
mgmtConfig := getManagementClusterConfig()
mgmtClient := getManagementClusterClient()

objects, err := fecthClusterObjects(ctx, mgmtConfig, mgmtClient, clusterSummary.Spec.ClusterNamespace,
clusterSummary.Spec.ClusterName, clusterSummary.Spec.ClusterType, logger)
if err != nil {
return nil, err
}

instantiatedValues, err := instantiateTemplateValues(ctx, mgmtConfig, mgmtClient,
clusterSummary, requestedChart.ChartName, requestedChart.Values, mgmtResources, logger)
clusterSummary, requestedChart.ChartName, requestedChart.Values, objects, mgmtResources, logger)
if err != nil {
return nil, err
}
Expand All @@ -2446,7 +2452,7 @@ func getInstantiatedValues(ctx context.Context, clusterSummary *configv1beta1.Cl

for k := range valuesFrom {
instantiatedValuesFrom, err := instantiateTemplateValues(ctx, mgmtConfig, mgmtClient,
clusterSummary, requestedChart.ChartName, valuesFrom[k], mgmtResources, logger)
clusterSummary, requestedChart.ChartName, valuesFrom[k], objects, mgmtResources, logger)
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -3924,25 +3930,22 @@ func getInstantiatedChart(ctx context.Context, clusterSummary *configv1beta1.Clu
currentChart *configv1beta1.HelmChart, mgmtResources map[string]*unstructured.Unstructured,
logger logr.Logger) (*configv1beta1.HelmChart, error) {

// Marshal the struct to YAML
jsonData, err := yaml.Marshal(*currentChart)
if err != nil {
return nil, err
}
// Create a deep copy of the chart to avoid modifying the original.
instantiatedChart := currentChart.DeepCopy()

instantiatedChartString, err := instantiateTemplateValues(ctx, getManagementClusterConfig(),
getManagementClusterClient(), clusterSummary, currentChart.ChartName, string(jsonData), mgmtResources, logger)
objects, err := fecthClusterObjects(ctx, getManagementClusterConfig(), getManagementClusterClient(),
clusterSummary.Spec.ClusterNamespace, clusterSummary.Spec.ClusterName, clusterSummary.Spec.ClusterType, logger)
if err != nil {
return nil, err
}

var instantiatedChart configv1beta1.HelmChart
err = yaml.Unmarshal([]byte(instantiatedChartString), &instantiatedChart)
if err != nil {
// Call the new recursive helper function to instantiate all fields.
if err := instantiateStructFields(ctx, getManagementClusterConfig(), getManagementClusterClient(),
instantiatedChart, clusterSummary, objects, mgmtResources, logger); err != nil {
return nil, err
}

return &instantiatedChart, nil
return instantiatedChart, nil
}

func canManageChart(ctx context.Context, c client.Client, clusterSummary *configv1beta1.ClusterSummary,
Expand Down
10 changes: 5 additions & 5 deletions controllers/handlers_helm_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -518,11 +518,11 @@ var _ = Describe("HandlersHelm", func() {
RepositoryName: randomString(), HelmChartAction: configv1beta1.HelmChartActionInstall,
}

helmChart.ChartVersion = `{{$version := index .Cluster.metadata.labels "k8s-version" }}{{if eq $version "1.20"}}23.4.0
{{else if eq $version "1.22"}}24.1.0
{{else if eq $version "1.25"}}25.0.2
{{ else }}23.4.0
{{end}}`
helmChart.ChartVersion = `{{$version := index .Cluster.metadata.labels "k8s-version" }}{{- if eq $version "1.20"}}23.4.0
{{- else if eq $version "1.22"}}24.1.0
{{- else if eq $version "1.25"}}25.0.2
{{- else }}23.4.0
{{- end}}`

clusterSummary.Namespace = defaulNamespace
clusterSummary.Spec.ClusterNamespace = defaulNamespace
Expand Down
19 changes: 16 additions & 3 deletions controllers/handlers_kustomize.go
Original file line number Diff line number Diff line change
Expand Up @@ -493,9 +493,15 @@ func instantiateKustomizeSubstituteValues(ctx context.Context, clusterSummary *c

requestorName := clusterSummary.Namespace + clusterSummary.Name + "kustomize"

objects, err := fecthClusterObjects(ctx, getManagementClusterConfig(), getManagementClusterClient(),
clusterSummary.Spec.ClusterNamespace, clusterSummary.Spec.ClusterName, clusterSummary.Spec.ClusterType, logger)
if err != nil {
return nil, err
}

instantiatedValue, err :=
instantiateTemplateValues(ctx, getManagementClusterConfig(), getManagementClusterClient(),
clusterSummary, requestorName, stringifiedValues, mgmtResources, logger)
clusterSummary, requestorName, stringifiedValues, objects, mgmtResources, logger)
if err != nil {
logger.V(logs.LogInfo).Info(fmt.Sprintf("failed to instantiate values %v", err))
return nil, err
Expand Down Expand Up @@ -566,9 +572,15 @@ func deployKustomizeRef(ctx context.Context, c client.Client, remoteRestConfig *

defer os.RemoveAll(tmpDir)

objects, err := fecthClusterObjects(ctx, getManagementClusterConfig(), getManagementClusterClient(),
clusterSummary.Spec.ClusterNamespace, clusterSummary.Spec.ClusterName, clusterSummary.Spec.ClusterType, logger)
if err != nil {
return nil, nil, err
}

// Path can be expressed as a template and instantiate using Cluster fields.
instantiatedPath, err := instantiateTemplateValues(ctx, getManagementClusterConfig(), getManagementClusterClient(),
clusterSummary, clusterSummary.GetName(), kustomizationRef.Path, nil, logger)
clusterSummary, clusterSummary.GetName(), kustomizationRef.Path, objects, nil, logger)
if err != nil {
return nil, nil, err
}
Expand Down Expand Up @@ -1024,7 +1036,8 @@ func extractTarGz(src, dest string) error {
func instantiateResourceWithSubstituteValues(templateName string, resource []byte,
substituteValues map[string]string, useTxtFuncMap bool, logger logr.Logger) ([]byte, error) {

tmpl, err := template.New(templateName).Option("missingkey=error").Funcs(funcmap.SveltosFuncMap(useTxtFuncMap)).Parse(string(resource))
tmpl, err := template.New(templateName).Option("missingkey=error").Funcs(funcmap.SveltosFuncMap(useTxtFuncMap)).
Parse(string(resource))
if err != nil {
return nil, err
}
Expand Down
24 changes: 21 additions & 3 deletions controllers/handlers_utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -120,9 +120,15 @@ func deployContentOfSource(ctx context.Context, deployingToMgmtCluster bool, des

defer os.RemoveAll(tmpDir)

objects, err := fecthClusterObjects(ctx, getManagementClusterConfig(), getManagementClusterClient(),
clusterSummary.Spec.ClusterNamespace, clusterSummary.Spec.ClusterName, clusterSummary.Spec.ClusterType, logger)
if err != nil {
return nil, err
}

// Path can be expressed as a template and instantiate using Cluster fields.
instantiatedPath, err := instantiateTemplateValues(ctx, getManagementClusterConfig(), getManagementClusterClient(),
clusterSummary, clusterSummary.GetName(), path, nil, logger)
clusterSummary, clusterSummary.GetName(), path, objects, nil, logger)
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -526,12 +532,18 @@ func collectContent(ctx context.Context, clusterSummary *configv1beta1.ClusterSu

policies := make([]*unstructured.Unstructured, 0, len(data))

objects, err := fecthClusterObjects(ctx, getManagementClusterConfig(), getManagementClusterClient(),
clusterSummary.Spec.ClusterNamespace, clusterSummary.Spec.ClusterName, clusterSummary.Spec.ClusterType, logger)
if err != nil {
return nil, err
}

for k := range data {
section := data[k]

if instantiateTemplate {
instance, err := instantiateTemplateValues(ctx, getManagementClusterConfig(), getManagementClusterClient(),
clusterSummary, clusterSummary.GetName(), section, mgmtResources, logger)
clusterSummary, clusterSummary.GetName(), section, objects, mgmtResources, logger)
if err != nil {
logger.Error(err, fmt.Sprintf("failed to instantiate policy from Data %.100s", section))
return nil, err
Expand Down Expand Up @@ -1292,9 +1304,15 @@ func initiatePatches(ctx context.Context, clusterSummary *configv1beta1.ClusterS

instantiatedPatches = clusterSummary.Spec.ClusterProfileSpec.Patches

objects, err := fecthClusterObjects(ctx, getManagementClusterConfig(), getManagementClusterClient(),
clusterSummary.Spec.ClusterNamespace, clusterSummary.Spec.ClusterName, clusterSummary.Spec.ClusterType, logger)
if err != nil {
return nil, err
}

for k := range instantiatedPatches {
instantiatedPatch, err := instantiateTemplateValues(ctx, getManagementClusterConfig(), getManagementClusterClient(),
clusterSummary, requestor, instantiatedPatches[k].Patch, mgmtResources, logger)
clusterSummary, requestor, instantiatedPatches[k].Patch, objects, mgmtResources, logger)
if err != nil {
return nil, err
}
Expand Down
70 changes: 64 additions & 6 deletions controllers/template_instantiation.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import (
"bytes"
"context"
"fmt"
"reflect"
"strings"
"text/template"

Expand Down Expand Up @@ -155,16 +156,73 @@ func fecthClusterObjects(ctx context.Context, config *rest.Config, c client.Clie
return result, nil
}

func instantiateTemplateValues(ctx context.Context, config *rest.Config, c client.Client, //nolint: funlen,maintidx // adding few closures
clusterSummary *configv1beta1.ClusterSummary, requestorName, values string,
mgmtResources map[string]*unstructured.Unstructured, logger logr.Logger) (string, error) {
// instantiateGenericField is a helper function to instantiate a single field, regardless of type.
func instantiateGenericField(ctx context.Context, config *rest.Config, c client.Client,
field interface{}, clusterSummary *configv1beta1.ClusterSummary, objects *currentClusterObjects,
mgmtResources map[string]*unstructured.Unstructured, logger logr.Logger) (interface{}, error) {

objects, err := fecthClusterObjects(ctx, config, c, clusterSummary.Spec.ClusterNamespace,
clusterSummary.Spec.ClusterName, clusterSummary.Spec.ClusterType, logger)
// Marshal the field's value to a YAML string.
var buf bytes.Buffer
encoder := yaml.NewEncoder(&buf)
err := encoder.Encode(field)
if err != nil {
return "", err
return nil, fmt.Errorf("failed to marshal field: %w", err)
}

// Instantiate the YAML string with the template engine.
instantiatedString, err := instantiateTemplateValues(ctx, config, c,
clusterSummary, "chart-name", buf.String(), objects, mgmtResources, logger)
if err != nil {
return nil, fmt.Errorf("failed to instantiate field: %w", err)
}

// Unmarshal the instantiated string back into a new variable of the same type as the original field.
result := reflect.New(reflect.TypeOf(field)).Interface()
err = yaml.Unmarshal([]byte(instantiatedString), result)
if err != nil {
return nil, fmt.Errorf("failed to unmarshal instantiated field: %w", err)
}

return result, nil
}

// instantiateStructFields is a recursive helper function to instantiate all string fields in a struct.
func instantiateStructFields(ctx context.Context, config *rest.Config, c client.Client, s interface{},
clusterSummary *configv1beta1.ClusterSummary, objects *currentClusterObjects,
mgmtResources map[string]*unstructured.Unstructured, logger logr.Logger) error {

value := reflect.ValueOf(s)

if value.Kind() == reflect.Ptr {
value = value.Elem()
}

if value.Kind() != reflect.Struct {
return nil
}

for i := 0; i < value.NumField(); i++ {
field := value.Field(i)

if field.CanSet() {
// Use the generic instantiation helper for all fields that can be set.
instantiatedValue, err := instantiateGenericField(ctx, config, c, field.Interface(), clusterSummary,
objects, mgmtResources, logger)
if err != nil {
return fmt.Errorf("failed to instantiate field '%s': %w", value.Type().Field(i).Name, err)
}

// Set the instantiated value back to the field.
field.Set(reflect.ValueOf(instantiatedValue).Elem())
}
}
return nil
}

func instantiateTemplateValues(ctx context.Context, config *rest.Config, c client.Client, //nolint: funlen // adding few closures
clusterSummary *configv1beta1.ClusterSummary, requestorName, values string, objects *currentClusterObjects,
mgmtResources map[string]*unstructured.Unstructured, logger logr.Logger) (string, error) {

if mgmtResources != nil {
objects.MgmtResources = make(map[string]map[string]interface{})
for k := range mgmtResources {
Expand Down
Loading