Skip to content

Commit

Permalink
(feat) templateResourceRefs namespace
Browse files Browse the repository at this point in the history
templateResourceRefs namespace can now be expressed as a template
using Cluster.metadata.namespace, Cluster.metadata.name and Cluster.kind
  • Loading branch information
mgianluc committed Dec 5, 2024
1 parent 47bf6b7 commit eef5f63
Show file tree
Hide file tree
Showing 10 changed files with 92 additions and 20 deletions.
5 changes: 3 additions & 2 deletions api/v1alpha1/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion api/v1beta1/spec.go
Original file line number Diff line number Diff line change
Expand Up @@ -518,7 +518,7 @@ type TemplateResourceRef struct {
// cluster to fetch and use during template instantiation.
// For ClusterProfile namespace can be left empty. In such a case, namespace will
// be implicit set to cluster's namespace.
// Name can be expressed as a template and instantiate using
// Name and namespace can be expressed as a template and instantiate using
// - cluster namespace: .Cluster.metadata.namespace
// - cluster name: .Cluster.metadata.name
// - cluster type: .Cluster.kind
Expand Down
5 changes: 3 additions & 2 deletions api/v1beta1/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -1818,7 +1818,7 @@ spec:
cluster to fetch and use during template instantiation.
For ClusterProfile namespace can be left empty. In such a case, namespace will
be implicit set to cluster's namespace.
Name can be expressed as a template and instantiate using
Name and namespace can be expressed as a template and instantiate using
- cluster namespace: .Cluster.metadata.namespace
- cluster name: .Cluster.metadata.name
- cluster type: .Cluster.kind
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1846,7 +1846,7 @@ spec:
cluster to fetch and use during template instantiation.
For ClusterProfile namespace can be left empty. In such a case, namespace will
be implicit set to cluster's namespace.
Name can be expressed as a template and instantiate using
Name and namespace can be expressed as a template and instantiate using
- cluster namespace: .Cluster.metadata.namespace
- cluster name: .Cluster.metadata.name
- cluster type: .Cluster.kind
Expand Down
2 changes: 1 addition & 1 deletion config/crd/bases/config.projectsveltos.io_profiles.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -1818,7 +1818,7 @@ spec:
cluster to fetch and use during template instantiation.
For ClusterProfile namespace can be left empty. In such a case, namespace will
be implicit set to cluster's namespace.
Name can be expressed as a template and instantiate using
Name and namespace can be expressed as a template and instantiate using
- cluster namespace: .Cluster.metadata.namespace
- cluster name: .Cluster.metadata.name
- cluster type: .Cluster.kind
Expand Down
13 changes: 10 additions & 3 deletions controllers/clustersummary_watchers.go
Original file line number Diff line number Diff line change
Expand Up @@ -153,10 +153,13 @@ func (m *manager) startWatcherForTemplateResourceRef(ctx context.Context, gvk sc

resource := ref.Resource

var err error
// If namespace is not defined, default to cluster namespace
resource.Namespace = getTemplateResourceNamespace(clusterSummary, ref)
resource.Namespace, err = getTemplateResourceNamespace(clusterSummary, ref)
if err != nil {
return err
}

var err error
resource.Name, err = getTemplateResourceName(clusterSummary, ref)
if err != nil {
return err
Expand Down Expand Up @@ -269,8 +272,12 @@ func (m *manager) stopStaleWatchForTemplateResourceRef(clusterSummary *configv1b
if !removeAll {
for i := range clusterSummary.Spec.ClusterProfileSpec.TemplateResourceRefs {
resource := &clusterSummary.Spec.ClusterProfileSpec.TemplateResourceRefs[i].Resource
resource.Namespace = getTemplateResourceNamespace(clusterSummary,
var err error
resource.Namespace, err = getTemplateResourceNamespace(clusterSummary,
&clusterSummary.Spec.ClusterProfileSpec.TemplateResourceRefs[i])
if err != nil {
continue
}
resource.Name, _ = getTemplateResourceName(clusterSummary,
&clusterSummary.Spec.ClusterProfileSpec.TemplateResourceRefs[i])

Expand Down
39 changes: 35 additions & 4 deletions controllers/templateresourcedef_utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,15 +33,43 @@ import (

// The TemplateResource namespace can be specified or it will inherit the cluster namespace
func getTemplateResourceNamespace(clusterSummary *configv1beta1.ClusterSummary,
ref *configv1beta1.TemplateResourceRef) string {
ref *configv1beta1.TemplateResourceRef) (string, error) {

namespace := ref.Resource.Namespace
if namespace == "" {
// Use cluster namespace
namespace = clusterSummary.Spec.ClusterNamespace
return clusterSummary.Spec.ClusterNamespace, nil
}

// Accept namespaces that are templates
templateName := getTemplateName(clusterSummary.Spec.ClusterNamespace, clusterSummary.Spec.ClusterName,
string(clusterSummary.Spec.ClusterType))
tmpl, err := template.New(templateName).Option("missingkey=error").Funcs(funcmap.SveltosFuncMap()).Parse(ref.Resource.Namespace)
if err != nil {
return "", err
}

return namespace
var buffer bytes.Buffer

// Cluster namespace and name can be used to instantiate the name of the resource that
// needs to be fetched from the management cluster. Defined an unstructured with namespace and name set
u := &unstructured.Unstructured{}
u.SetNamespace(clusterSummary.Spec.ClusterNamespace)
u.SetName(clusterSummary.Spec.ClusterName)
u.SetKind(string(clusterSummary.Spec.ClusterType))

if err := tmpl.Execute(&buffer,
struct {
Cluster map[string]interface{}
// deprecated. This used to be original format which was different than rest of templating
ClusterNamespace, ClusterName string
}{
Cluster: u.UnstructuredContent(),
ClusterNamespace: clusterSummary.Spec.ClusterNamespace,
ClusterName: clusterSummary.Spec.ClusterName}); err != nil {
return "", fmt.Errorf("error executing template: %w", err)
}
return buffer.String(), nil
}

// Resources referenced in the management cluster can have their name expressed in function
Expand Down Expand Up @@ -97,8 +125,11 @@ func collectTemplateResourceRefs(ctx context.Context, clusterSummary *configv1be
result := make(map[string]*unstructured.Unstructured)
for i := range clusterSummary.Spec.ClusterProfileSpec.TemplateResourceRefs {
ref := clusterSummary.Spec.ClusterProfileSpec.TemplateResourceRefs[i]
ref.Resource.Namespace = getTemplateResourceNamespace(clusterSummary, &ref)
var err error
ref.Resource.Namespace, err = getTemplateResourceNamespace(clusterSummary, &ref)
if err != nil {
return nil, err
}
ref.Resource.Name, err = getTemplateResourceName(clusterSummary, &ref)
if err != nil {
return nil, err
Expand Down
36 changes: 34 additions & 2 deletions controllers/templateresourcedef_utils_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -118,11 +118,43 @@ var _ = Describe("TemplateResourceDef utils ", func() {
},
}

value := controllers.GetTemplateResourceNamespace(clusterSummary, ref)
value, err := controllers.GetTemplateResourceNamespace(clusterSummary, ref)
Expect(err).To(BeNil())
Expect(value).To(Equal(cluster.Namespace))

ref.Resource.Namespace = randomString()
value = controllers.GetTemplateResourceNamespace(clusterSummary, ref)
value, err = controllers.GetTemplateResourceNamespace(clusterSummary, ref)
Expect(err).To(BeNil())
Expect(value).To(Equal(ref.Resource.Namespace))
})

It("GetTemplateResourceNamespace returns the correct namespace (template version)", func() {
ref := &configv1beta1.TemplateResourceRef{
Resource: corev1.ObjectReference{
Name: randomString(),
Namespace: "{{ .Cluster.metadata.namespace }}-foo",
},
Identifier: randomString(),
}

clusterSummary := &configv1beta1.ClusterSummary{
ObjectMeta: metav1.ObjectMeta{
Name: randomString(),
},
Spec: configv1beta1.ClusterSummarySpec{
ClusterNamespace: cluster.Namespace,
ClusterName: cluster.Name,
ClusterType: libsveltosv1beta1.ClusterTypeCapi,
},
}

value, err := controllers.GetTemplateResourceNamespace(clusterSummary, ref)
Expect(err).To(BeNil())
Expect(value).To(Equal(cluster.Namespace + "-foo"))

ref.Resource.Namespace = randomString()
value, err = controllers.GetTemplateResourceNamespace(clusterSummary, ref)
Expect(err).To(BeNil())
Expect(value).To(Equal(ref.Resource.Namespace))
})

Expand Down
6 changes: 3 additions & 3 deletions manifest/manifest.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2599,7 +2599,7 @@ spec:
cluster to fetch and use during template instantiation.
For ClusterProfile namespace can be left empty. In such a case, namespace will
be implicit set to cluster's namespace.
Name can be expressed as a template and instantiate using
Name and namespace can be expressed as a template and instantiate using
- cluster namespace: .Cluster.metadata.namespace
- cluster name: .Cluster.metadata.name
- cluster type: .Cluster.kind
Expand Down Expand Up @@ -5429,7 +5429,7 @@ spec:
cluster to fetch and use during template instantiation.
For ClusterProfile namespace can be left empty. In such a case, namespace will
be implicit set to cluster's namespace.
Name can be expressed as a template and instantiate using
Name and namespace can be expressed as a template and instantiate using
- cluster namespace: .Cluster.metadata.namespace
- cluster name: .Cluster.metadata.name
- cluster type: .Cluster.kind
Expand Down Expand Up @@ -7562,7 +7562,7 @@ spec:
cluster to fetch and use during template instantiation.
For ClusterProfile namespace can be left empty. In such a case, namespace will
be implicit set to cluster's namespace.
Name can be expressed as a template and instantiate using
Name and namespace can be expressed as a template and instantiate using
- cluster namespace: .Cluster.metadata.namespace
- cluster name: .Cluster.metadata.name
- cluster type: .Cluster.kind
Expand Down

0 comments on commit eef5f63

Please sign in to comment.