Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

When Generators change, reconcile the EventTrigger #280

Merged
merged 1 commit into from
Nov 21, 2024
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
2 changes: 1 addition & 1 deletion api/v1beta1/eventtrigger_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ const (

type GeneratorReference struct {
// Namespace of the referenced resource.
// Nnamespace can be left empty. In such a case, namespace will
// Namespace can be left empty. In such a case, namespace will
// be implicit set to cluster's namespace.
// +optional
Namespace string `json:"namespace,omitempty"`
Expand Down
4 changes: 2 additions & 2 deletions config/crd/bases/lib.projectsveltos.io_eventtriggers.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -969,7 +969,7 @@ spec:
namespace:
description: |-
Namespace of the referenced resource.
Nnamespace can be left empty. In such a case, namespace will
Namespace can be left empty. In such a case, namespace will
be implicit set to cluster's namespace.
type: string
required:
Expand Down Expand Up @@ -1783,7 +1783,7 @@ spec:
namespace:
description: |-
Namespace of the referenced resource.
Nnamespace can be left empty. In such a case, namespace will
Namespace can be left empty. In such a case, namespace will
be implicit set to cluster's namespace.
type: string
required:
Expand Down
53 changes: 15 additions & 38 deletions controllers/eventtrigger_deployer.go
Original file line number Diff line number Diff line change
Expand Up @@ -310,35 +310,6 @@ func eventTriggerHash(ctx context.Context, c client.Client,
}
}

clusterType := clusterproxy.GetClusterType(cluster)
clusterObj, err := fecthClusterObjects(ctx, c, cluster.Namespace, cluster.Name, clusterType, logger)
if err == nil {
objects := currentObjects{
Cluster: clusterObj,
}

templateName := getTemplateName(cluster.Namespace, cluster.Name, e.Name)
local, remote, _ := fetchPolicyRefs(ctx, c, e, cluster, objects, templateName, logger)
for i := range local {
config += render.AsCode(local[i])
}
for i := range remote {
config += render.AsCode(remote[i])
}

for i := range e.Spec.HelmCharts {
valuesFromHash := getValuesFromHash(ctx, c, e.Spec.HelmCharts[i].ValuesFrom, cluster.Namespace,
templateName, objects, logger)
config += render.AsCode(valuesFromHash)
}

for i := range e.Spec.KustomizationRefs {
valuesFromHash := getValuesFromHash(ctx, c, e.Spec.KustomizationRefs[i].ValuesFrom, cluster.Namespace,
templateName, objects, logger)
config += render.AsCode(valuesFromHash)
}
}

h := sha256.New()
h.Write([]byte(config))
return h.Sum(nil), nil
Expand Down Expand Up @@ -2336,11 +2307,20 @@ func instantiateResourceFromGenerator(ctx context.Context, c client.Client, gene
if apierrors.IsNotFound(err) {
logger.V(logs.LogInfo).Info(fmt.Sprintf("%s %s/%s does not exist yet",
kind, namespace, referencedName))
return nil, nil
return nil, fmt.Errorf("referenced resource %s %s/%s does not exist yet",
kind, namespace, referencedName)
}
return nil, err
}

// Keep track of all referenced Generators. When those changes, EventTrigger will be reconciled.
resourceTracker := getTrackerInstance()
resourceTracker.trackResourceForConsumer(
&corev1.ObjectReference{Kind: referencedResource.GetObjectKind().GroupVersionKind().Kind,
Namespace: referencedResource.GetNamespace(), Name: referencedResource.GetName(), APIVersion: "v1"},
&corev1.ObjectReference{Kind: v1beta1.EventTriggerKind, Name: e.GetName(), APIVersion: v1beta1.GroupVersion.String()},
)

instantiatedName, err := instantiateSection(templateName, []byte(generator.InstantiatedResourceNameFormat), data, logger)
if err != nil {
logger.V(logs.LogInfo).Info(fmt.Sprintf("failed to instantiate %q: %v", generator.InstantiatedResourceNameFormat, err))
Expand All @@ -2355,10 +2335,10 @@ func instantiateResourceFromGenerator(ctx context.Context, c client.Client, gene
return info, nil
}

func getValuesFromHash(ctx context.Context, c client.Client, valuesFrom []configv1beta1.ValueFrom,
clusterNamespace, templateName string, data any, logger logr.Logger) []byte {
func getValuesFrom(ctx context.Context, c client.Client, valuesFrom []configv1beta1.ValueFrom,
clusterNamespace, templateName string, data any, logger logr.Logger) []client.Object {

hash := ""
result := make([]client.Object, 0, len(valuesFrom))
for i := range valuesFrom {
ref := &valuesFrom[i]

Expand All @@ -2379,10 +2359,7 @@ func getValuesFromHash(ctx context.Context, c client.Client, valuesFrom []config
continue
}

hash += render.AsCode(resource)
result = append(result, resource)
}

h := sha256.New()
h.Write([]byte(hash))
return h.Sum(nil)
return result
}
6 changes: 4 additions & 2 deletions controllers/eventtrigger_deployer_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -343,8 +343,9 @@ var _ = Describe("EventTrigger deployer", func() {

initObjects := []client.Object{
secret,
configMap,
cluster,
e,
configMap,
eventSource,
eventReport,
}
Expand All @@ -353,7 +354,8 @@ var _ = Describe("EventTrigger deployer", func() {
config += render.AsCode(e.Labels)
config += render.AsCode(eventSource.Spec)
config += render.AsCode(eventReport.Spec)
// Content of referenced resources in PolicyRef/ValuesFrom is not included
config += render.AsCode(configMap.Data)
config += render.AsCode(secret.Data)
h := sha256.New()
h.Write([]byte(config))
expectedHash := h.Sum(nil)
Expand Down
102 changes: 96 additions & 6 deletions controllers/fetcher.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ import (
// fetchReferencedResources fetches resources referenced by EventTrigger.
// This includes:
// - EventSource and corresponding EventReports (from the passed in cluster only);
// - ConfigMaps referenced in the ConfigMapGenerator section, in the PolicyRefs section and ValuesFrom
// - Secrets referenced in the SecretGenerator section, in the PolicyRefs section and ValuesFrom
func fetchReferencedResources(ctx context.Context, c client.Client,
e *v1beta1.EventTrigger, cluster *corev1.ObjectReference, logger logr.Logger) ([]client.Object, error) {

Expand Down Expand Up @@ -66,20 +68,108 @@ func fetchReferencedResources(ctx context.Context, c client.Client,
if err != nil {
return nil, err
}

for i := range eventReports.Items {
result = append(result, &eventReports.Items[i])
}

// Resources references in PolicyRefs and/or ValuesFrom are not
// considered. Those resource namespace/name info can be expressed
// as template and so for different clusters/events different resources
// might be used.
// Also, EventTrigger should deploy ClusterProfile based on the state
// in the cluster when the event happened.
clusterType := clusterproxy.GetClusterType(cluster)
clusterObj, err := fecthClusterObjects(ctx, c, cluster.Namespace, cluster.Name, clusterType, logger)
if err == nil {
objects := currentObjects{
Cluster: clusterObj,
}

templateName := getTemplateName(cluster.Namespace, cluster.Name, e.Name)

referencedResources, err := collectResourcesFromConfigMapGenerators(ctx, c, objects, e,
cluster.Namespace, templateName, logger)
if err != nil {
return nil, err
}
result = append(result, referencedResources...)

referencedResources, err = collectResourcesFromSecretGenerators(ctx, c, objects, e,
cluster.Namespace, templateName, logger)
if err != nil {
return nil, err
}
result = append(result, referencedResources...)

local, remote, _ := fetchPolicyRefs(ctx, c, e, cluster, objects, templateName, logger)
result = append(result, local...)
result = append(result, remote...)

for i := range e.Spec.HelmCharts {
valuesFrom := getValuesFrom(ctx, c, e.Spec.HelmCharts[i].ValuesFrom, cluster.Namespace,
templateName, objects, logger)
result = append(result, valuesFrom...)
}

for i := range e.Spec.KustomizationRefs {
valuesFrom := getValuesFrom(ctx, c, e.Spec.KustomizationRefs[i].ValuesFrom, cluster.Namespace,
templateName, objects, logger)
result = append(result, valuesFrom...)
}
}

return result, nil
}

func collectResourcesFromConfigMapGenerators(ctx context.Context, c client.Client, objects any,
e *v1beta1.EventTrigger, templateName, clusterNamespace string, logger logr.Logger) ([]client.Object, error) {

results := make([]client.Object, len(e.Spec.ConfigMapGenerator))

for i := range e.Spec.ConfigMapGenerator {
generator := &e.Spec.ConfigMapGenerator[i]
namespace := libsveltostemplate.GetReferenceResourceNamespace(clusterNamespace, generator.Namespace)

// The name of the referenced resource can be expressed as a template
referencedName, err := instantiateSection(templateName, []byte(generator.Name), objects, logger)
if err != nil {
return nil, err
}

var referencedResource client.Object
referencedResource, err = getConfigMap(ctx, c, types.NamespacedName{Namespace: namespace, Name: string(referencedName)})
if err != nil {
return nil, err
}

results[i] = referencedResource
}

return results, nil
}

func collectResourcesFromSecretGenerators(ctx context.Context, c client.Client, objects any,
e *v1beta1.EventTrigger, templateName, clusterNamespace string, logger logr.Logger) ([]client.Object, error) {

results := make([]client.Object, len(e.Spec.SecretGenerator))

for i := range e.Spec.SecretGenerator {
generator := &e.Spec.SecretGenerator[i]
namespace := libsveltostemplate.GetReferenceResourceNamespace(clusterNamespace, generator.Namespace)

// The name of the referenced resource can be expressed as a template
referencedName, err := instantiateSection(templateName, []byte(generator.Name), objects, logger)
if err != nil {
return nil, err
}

var referencedResource client.Object
referencedResource, err = getSecret(ctx, c, types.NamespacedName{Namespace: namespace, Name: string(referencedName)})
if err != nil {
return nil, err
}

results[i] = referencedResource
}

return results, nil
}

// fetchEventSource fetches referenced EventSource
func fetchEventSource(ctx context.Context, c client.Client,
clusterNamespace, clusterName, eventSourceName string, clusterType libsveltosv1beta1.ClusterType,
Expand Down
3 changes: 2 additions & 1 deletion controllers/fetcher_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -358,6 +358,7 @@ var _ = Describe("Fetcher", func() {

initObjects := []client.Object{
secret,
cluster,
configMap,
e,
eventSource,
Expand All @@ -370,6 +371,6 @@ var _ = Describe("Fetcher", func() {

result, err := controllers.FetchReferencedResources(context.TODO(), c, e, getClusterRef(cluster), logger)
Expect(err).To(BeNil())
Expect(len(result)).To(Equal(2)) // EventSource + EventReport (no referenced resources)
Expect(len(result)).To(Equal(4)) // EventSource + EventReport + Referenced Resources
})
})
4 changes: 2 additions & 2 deletions manifest/manifest.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -984,7 +984,7 @@ spec:
namespace:
description: |-
Namespace of the referenced resource.
Nnamespace can be left empty. In such a case, namespace will
Namespace can be left empty. In such a case, namespace will
be implicit set to cluster's namespace.
type: string
required:
Expand Down Expand Up @@ -1798,7 +1798,7 @@ spec:
namespace:
description: |-
Namespace of the referenced resource.
Nnamespace can be left empty. In such a case, namespace will
Namespace can be left empty. In such a case, namespace will
be implicit set to cluster's namespace.
type: string
required:
Expand Down
Loading