mirror of
https://github.com/stakater/Reloader.git
synced 2026-08-20 04:26:28 +00:00
refactor(reload): move resource types and reload decision structs to dedicated files and remove redundant code
This commit is contained in:
@@ -0,0 +1,39 @@
|
||||
package controller
|
||||
|
||||
import (
|
||||
"github.com/stakater/Reloader/internal/pkg/config"
|
||||
"github.com/stakater/Reloader/internal/pkg/reload"
|
||||
"sigs.k8s.io/controller-runtime/pkg/event"
|
||||
"sigs.k8s.io/controller-runtime/pkg/predicate"
|
||||
)
|
||||
|
||||
// BuildEventFilter combines a resource-specific predicate with common filters.
|
||||
func BuildEventFilter(resourcePredicate predicate.Predicate, cfg *config.Config, initialized *bool) predicate.Predicate {
|
||||
return predicate.And(
|
||||
resourcePredicate,
|
||||
reload.NamespaceFilterPredicate(cfg),
|
||||
reload.LabelSelectorPredicate(cfg),
|
||||
reload.IgnoreAnnotationPredicate(cfg),
|
||||
createEventPredicate(cfg, initialized),
|
||||
)
|
||||
}
|
||||
|
||||
func createEventPredicate(cfg *config.Config, initialized *bool) predicate.Predicate {
|
||||
return predicate.Funcs{
|
||||
CreateFunc: func(e event.CreateEvent) bool {
|
||||
if !*initialized && !cfg.SyncAfterRestart {
|
||||
return false
|
||||
}
|
||||
return cfg.ReloadOnCreate
|
||||
},
|
||||
UpdateFunc: func(e event.UpdateEvent) bool {
|
||||
return true
|
||||
},
|
||||
DeleteFunc: func(e event.DeleteEvent) bool {
|
||||
return cfg.ReloadOnDelete
|
||||
},
|
||||
GenericFunc: func(e event.GenericEvent) bool {
|
||||
return false
|
||||
},
|
||||
}
|
||||
}
|
||||
@@ -6,7 +6,6 @@ import (
|
||||
|
||||
"github.com/go-logr/logr"
|
||||
"github.com/stakater/Reloader/internal/pkg/alerting"
|
||||
"github.com/stakater/Reloader/internal/pkg/config"
|
||||
"github.com/stakater/Reloader/internal/pkg/events"
|
||||
"github.com/stakater/Reloader/internal/pkg/metrics"
|
||||
"github.com/stakater/Reloader/internal/pkg/reload"
|
||||
@@ -14,8 +13,6 @@ import (
|
||||
"github.com/stakater/Reloader/internal/pkg/workload"
|
||||
ctrl "sigs.k8s.io/controller-runtime"
|
||||
"sigs.k8s.io/controller-runtime/pkg/client"
|
||||
"sigs.k8s.io/controller-runtime/pkg/event"
|
||||
"sigs.k8s.io/controller-runtime/pkg/predicate"
|
||||
)
|
||||
|
||||
// ReloadHandler handles the common reload workflow.
|
||||
@@ -154,34 +151,3 @@ func (h *ReloadHandler) applyReloads(
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// BuildEventFilter combines a resource-specific predicate with common filters.
|
||||
func BuildEventFilter(resourcePredicate predicate.Predicate, cfg *config.Config, initialized *bool) predicate.Predicate {
|
||||
return predicate.And(
|
||||
resourcePredicate,
|
||||
reload.NamespaceFilterPredicate(cfg),
|
||||
reload.LabelSelectorPredicate(cfg),
|
||||
reload.IgnoreAnnotationPredicate(cfg),
|
||||
createEventPredicate(cfg, initialized),
|
||||
)
|
||||
}
|
||||
|
||||
func createEventPredicate(cfg *config.Config, initialized *bool) predicate.Predicate {
|
||||
return predicate.Funcs{
|
||||
CreateFunc: func(e event.CreateEvent) bool {
|
||||
if !*initialized && !cfg.SyncAfterRestart {
|
||||
return false
|
||||
}
|
||||
return cfg.ReloadOnCreate
|
||||
},
|
||||
UpdateFunc: func(e event.UpdateEvent) bool {
|
||||
return true
|
||||
},
|
||||
DeleteFunc: func(e event.DeleteEvent) bool {
|
||||
return cfg.ReloadOnDelete
|
||||
},
|
||||
GenericFunc: func(e event.GenericEvent) bool {
|
||||
return false
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,19 +3,14 @@
|
||||
package metadata
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"os"
|
||||
"runtime"
|
||||
"time"
|
||||
|
||||
"github.com/go-logr/logr"
|
||||
"github.com/stakater/Reloader/internal/pkg/config"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
"k8s.io/apimachinery/pkg/api/errors"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"sigs.k8s.io/controller-runtime/pkg/client"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -195,73 +190,6 @@ func (m *MetaInfo) ToConfigMap() *corev1.ConfigMap {
|
||||
}
|
||||
}
|
||||
|
||||
// Publisher handles creating and updating the metadata ConfigMap.
|
||||
type Publisher struct {
|
||||
client client.Client
|
||||
cfg *config.Config
|
||||
log logr.Logger
|
||||
}
|
||||
|
||||
// NewPublisher creates a new Publisher.
|
||||
func NewPublisher(c client.Client, cfg *config.Config, log logr.Logger) *Publisher {
|
||||
return &Publisher{
|
||||
client: c,
|
||||
cfg: cfg,
|
||||
log: log,
|
||||
}
|
||||
}
|
||||
|
||||
// Publish creates or updates the metadata ConfigMap.
|
||||
func (p *Publisher) Publish(ctx context.Context) error {
|
||||
namespace := os.Getenv(EnvReloaderNamespace)
|
||||
if namespace == "" {
|
||||
p.log.Info("RELOADER_NAMESPACE is not set, skipping meta info configmap creation")
|
||||
return nil
|
||||
}
|
||||
|
||||
metaInfo := NewMetaInfo(p.cfg)
|
||||
configMap := metaInfo.ToConfigMap()
|
||||
|
||||
existing := &corev1.ConfigMap{}
|
||||
err := p.client.Get(ctx, client.ObjectKey{
|
||||
Name: ConfigMapName,
|
||||
Namespace: namespace,
|
||||
}, existing)
|
||||
|
||||
if err != nil {
|
||||
if !errors.IsNotFound(err) {
|
||||
return fmt.Errorf("failed to get existing meta info configmap: %w", err)
|
||||
}
|
||||
p.log.Info("Creating meta info configmap")
|
||||
if err := p.client.Create(ctx, configMap, client.FieldOwner(FieldManager)); err != nil {
|
||||
return fmt.Errorf("failed to create meta info configmap: %w", err)
|
||||
}
|
||||
p.log.Info("Meta info configmap created successfully")
|
||||
return nil
|
||||
}
|
||||
|
||||
p.log.Info("Meta info configmap already exists, updating it")
|
||||
existing.Data = configMap.Data
|
||||
existing.Labels = configMap.Labels
|
||||
if err := p.client.Update(ctx, existing, client.FieldOwner(FieldManager)); err != nil {
|
||||
return fmt.Errorf("failed to update meta info configmap: %w", err)
|
||||
}
|
||||
p.log.Info("Meta info configmap updated successfully")
|
||||
return nil
|
||||
}
|
||||
|
||||
// PublishMetaInfoConfigMap is a convenience function that creates a Publisher and calls Publish.
|
||||
func PublishMetaInfoConfigMap(ctx context.Context, c client.Client, cfg *config.Config, log logr.Logger) error {
|
||||
publisher := NewPublisher(c, cfg, log)
|
||||
return publisher.Publish(ctx)
|
||||
}
|
||||
|
||||
// CreateOrUpdate creates or updates the metadata ConfigMap using the provided client.
|
||||
func CreateOrUpdate(c client.Client, cfg *config.Config, log logr.Logger) error {
|
||||
ctx := context.Background()
|
||||
return PublishMetaInfoConfigMap(ctx, c, cfg, log)
|
||||
}
|
||||
|
||||
func toJSON(data interface{}) string {
|
||||
jsonData, err := json.Marshal(data)
|
||||
if err != nil {
|
||||
|
||||
@@ -0,0 +1,80 @@
|
||||
package metadata
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/go-logr/logr"
|
||||
"github.com/stakater/Reloader/internal/pkg/config"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
"k8s.io/apimachinery/pkg/api/errors"
|
||||
"sigs.k8s.io/controller-runtime/pkg/client"
|
||||
)
|
||||
|
||||
// Publisher handles creating and updating the metadata ConfigMap.
|
||||
type Publisher struct {
|
||||
client client.Client
|
||||
cfg *config.Config
|
||||
log logr.Logger
|
||||
}
|
||||
|
||||
// NewPublisher creates a new Publisher.
|
||||
func NewPublisher(c client.Client, cfg *config.Config, log logr.Logger) *Publisher {
|
||||
return &Publisher{
|
||||
client: c,
|
||||
cfg: cfg,
|
||||
log: log,
|
||||
}
|
||||
}
|
||||
|
||||
// Publish creates or updates the metadata ConfigMap.
|
||||
func (p *Publisher) Publish(ctx context.Context) error {
|
||||
namespace := os.Getenv(EnvReloaderNamespace)
|
||||
if namespace == "" {
|
||||
p.log.Info("RELOADER_NAMESPACE is not set, skipping meta info configmap creation")
|
||||
return nil
|
||||
}
|
||||
|
||||
metaInfo := NewMetaInfo(p.cfg)
|
||||
configMap := metaInfo.ToConfigMap()
|
||||
|
||||
existing := &corev1.ConfigMap{}
|
||||
err := p.client.Get(ctx, client.ObjectKey{
|
||||
Name: ConfigMapName,
|
||||
Namespace: namespace,
|
||||
}, existing)
|
||||
|
||||
if err != nil {
|
||||
if !errors.IsNotFound(err) {
|
||||
return fmt.Errorf("failed to get existing meta info configmap: %w", err)
|
||||
}
|
||||
p.log.Info("Creating meta info configmap")
|
||||
if err := p.client.Create(ctx, configMap, client.FieldOwner(FieldManager)); err != nil {
|
||||
return fmt.Errorf("failed to create meta info configmap: %w", err)
|
||||
}
|
||||
p.log.Info("Meta info configmap created successfully")
|
||||
return nil
|
||||
}
|
||||
|
||||
p.log.Info("Meta info configmap already exists, updating it")
|
||||
existing.Data = configMap.Data
|
||||
existing.Labels = configMap.Labels
|
||||
if err := p.client.Update(ctx, existing, client.FieldOwner(FieldManager)); err != nil {
|
||||
return fmt.Errorf("failed to update meta info configmap: %w", err)
|
||||
}
|
||||
p.log.Info("Meta info configmap updated successfully")
|
||||
return nil
|
||||
}
|
||||
|
||||
// PublishMetaInfoConfigMap is a convenience function that creates a Publisher and calls Publish.
|
||||
func PublishMetaInfoConfigMap(ctx context.Context, c client.Client, cfg *config.Config, log logr.Logger) error {
|
||||
publisher := NewPublisher(c, cfg, log)
|
||||
return publisher.Publish(ctx)
|
||||
}
|
||||
|
||||
// CreateOrUpdate creates or updates the metadata ConfigMap using the provided client.
|
||||
func CreateOrUpdate(c client.Client, cfg *config.Config, log logr.Logger) error {
|
||||
ctx := context.Background()
|
||||
return PublishMetaInfoConfigMap(ctx, c, cfg, log)
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
package reload
|
||||
|
||||
import (
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
)
|
||||
|
||||
// EventType represents the type of change event.
|
||||
type EventType string
|
||||
|
||||
const (
|
||||
// EventTypeCreate indicates a resource was created.
|
||||
EventTypeCreate EventType = "create"
|
||||
// EventTypeUpdate indicates a resource was updated.
|
||||
EventTypeUpdate EventType = "update"
|
||||
// EventTypeDelete indicates a resource was deleted.
|
||||
EventTypeDelete EventType = "delete"
|
||||
)
|
||||
|
||||
// ResourceChange represents a change event for a ConfigMap or Secret.
|
||||
type ResourceChange interface {
|
||||
IsNil() bool
|
||||
GetEventType() EventType
|
||||
GetName() string
|
||||
GetNamespace() string
|
||||
GetAnnotations() map[string]string
|
||||
GetResourceType() ResourceType
|
||||
ComputeHash(hasher *Hasher) string
|
||||
}
|
||||
|
||||
// ConfigMapChange represents a change event for a ConfigMap.
|
||||
type ConfigMapChange struct {
|
||||
ConfigMap *corev1.ConfigMap
|
||||
EventType EventType
|
||||
}
|
||||
|
||||
func (c ConfigMapChange) IsNil() bool { return c.ConfigMap == nil }
|
||||
func (c ConfigMapChange) GetEventType() EventType { return c.EventType }
|
||||
func (c ConfigMapChange) GetName() string { return c.ConfigMap.Name }
|
||||
func (c ConfigMapChange) GetNamespace() string { return c.ConfigMap.Namespace }
|
||||
func (c ConfigMapChange) GetAnnotations() map[string]string { return c.ConfigMap.Annotations }
|
||||
func (c ConfigMapChange) GetResourceType() ResourceType { return ResourceTypeConfigMap }
|
||||
func (c ConfigMapChange) ComputeHash(h *Hasher) string { return h.HashConfigMap(c.ConfigMap) }
|
||||
|
||||
// SecretChange represents a change event for a Secret.
|
||||
type SecretChange struct {
|
||||
Secret *corev1.Secret
|
||||
EventType EventType
|
||||
}
|
||||
|
||||
func (c SecretChange) IsNil() bool { return c.Secret == nil }
|
||||
func (c SecretChange) GetEventType() EventType { return c.EventType }
|
||||
func (c SecretChange) GetName() string { return c.Secret.Name }
|
||||
func (c SecretChange) GetNamespace() string { return c.Secret.Namespace }
|
||||
func (c SecretChange) GetAnnotations() map[string]string { return c.Secret.Annotations }
|
||||
func (c SecretChange) GetResourceType() ResourceType { return ResourceTypeSecret }
|
||||
func (c SecretChange) ComputeHash(h *Hasher) string { return h.HashSecret(c.Secret) }
|
||||
@@ -0,0 +1,30 @@
|
||||
package reload
|
||||
|
||||
import (
|
||||
"github.com/stakater/Reloader/internal/pkg/workload"
|
||||
)
|
||||
|
||||
// ReloadDecision contains the result of evaluating whether to reload a workload.
|
||||
type ReloadDecision struct {
|
||||
// Workload is the workload accessor.
|
||||
Workload workload.WorkloadAccessor
|
||||
// ShouldReload indicates whether the workload should be reloaded.
|
||||
ShouldReload bool
|
||||
// AutoReload indicates if this is an auto-reload.
|
||||
AutoReload bool
|
||||
// Reason provides a human-readable explanation.
|
||||
Reason string
|
||||
// Hash is the computed hash of the resource content.
|
||||
Hash string
|
||||
}
|
||||
|
||||
// FilterDecisions returns only decisions where ShouldReload is true.
|
||||
func FilterDecisions(decisions []ReloadDecision) []ReloadDecision {
|
||||
var result []ReloadDecision
|
||||
for _, d := range decisions {
|
||||
if d.ShouldReload {
|
||||
result = append(result, d)
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
@@ -7,28 +7,6 @@ import (
|
||||
"github.com/stakater/Reloader/internal/pkg/config"
|
||||
)
|
||||
|
||||
// ResourceType represents the type of Kubernetes resource.
|
||||
type ResourceType string
|
||||
|
||||
const (
|
||||
// ResourceTypeConfigMap represents a ConfigMap resource.
|
||||
ResourceTypeConfigMap ResourceType = "configmap"
|
||||
// ResourceTypeSecret represents a Secret resource.
|
||||
ResourceTypeSecret ResourceType = "secret"
|
||||
)
|
||||
|
||||
// Kind returns the capitalized Kubernetes Kind (e.g., "ConfigMap", "Secret").
|
||||
func (r ResourceType) Kind() string {
|
||||
switch r {
|
||||
case ResourceTypeConfigMap:
|
||||
return "ConfigMap"
|
||||
case ResourceTypeSecret:
|
||||
return "Secret"
|
||||
default:
|
||||
return string(r)
|
||||
}
|
||||
}
|
||||
|
||||
// MatchResult contains the result of checking if a workload should be reloaded.
|
||||
type MatchResult struct {
|
||||
ShouldReload bool
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
package reload
|
||||
|
||||
// ResourceType represents the type of Kubernetes resource.
|
||||
type ResourceType string
|
||||
|
||||
const (
|
||||
// ResourceTypeConfigMap represents a ConfigMap resource.
|
||||
ResourceTypeConfigMap ResourceType = "configmap"
|
||||
// ResourceTypeSecret represents a Secret resource.
|
||||
ResourceTypeSecret ResourceType = "secret"
|
||||
)
|
||||
|
||||
// Kind returns the capitalized Kubernetes Kind (e.g., "ConfigMap", "Secret").
|
||||
func (r ResourceType) Kind() string {
|
||||
switch r {
|
||||
case ResourceTypeConfigMap:
|
||||
return "ConfigMap"
|
||||
case ResourceTypeSecret:
|
||||
return "Secret"
|
||||
default:
|
||||
return string(r)
|
||||
}
|
||||
}
|
||||
@@ -28,82 +28,6 @@ func NewService(cfg *config.Config) *Service {
|
||||
}
|
||||
}
|
||||
|
||||
// ResourceChange represents a change event for a ConfigMap or Secret.
|
||||
type ResourceChange interface {
|
||||
IsNil() bool
|
||||
GetEventType() EventType
|
||||
GetName() string
|
||||
GetNamespace() string
|
||||
GetAnnotations() map[string]string
|
||||
GetResourceType() ResourceType
|
||||
ComputeHash(hasher *Hasher) string
|
||||
}
|
||||
|
||||
// ConfigMapChange represents a change event for a ConfigMap.
|
||||
type ConfigMapChange struct {
|
||||
ConfigMap *corev1.ConfigMap
|
||||
EventType EventType
|
||||
}
|
||||
|
||||
func (c ConfigMapChange) IsNil() bool { return c.ConfigMap == nil }
|
||||
func (c ConfigMapChange) GetEventType() EventType { return c.EventType }
|
||||
func (c ConfigMapChange) GetName() string { return c.ConfigMap.Name }
|
||||
func (c ConfigMapChange) GetNamespace() string { return c.ConfigMap.Namespace }
|
||||
func (c ConfigMapChange) GetAnnotations() map[string]string { return c.ConfigMap.Annotations }
|
||||
func (c ConfigMapChange) GetResourceType() ResourceType { return ResourceTypeConfigMap }
|
||||
func (c ConfigMapChange) ComputeHash(h *Hasher) string { return h.HashConfigMap(c.ConfigMap) }
|
||||
|
||||
// SecretChange represents a change event for a Secret.
|
||||
type SecretChange struct {
|
||||
Secret *corev1.Secret
|
||||
EventType EventType
|
||||
}
|
||||
|
||||
func (c SecretChange) IsNil() bool { return c.Secret == nil }
|
||||
func (c SecretChange) GetEventType() EventType { return c.EventType }
|
||||
func (c SecretChange) GetName() string { return c.Secret.Name }
|
||||
func (c SecretChange) GetNamespace() string { return c.Secret.Namespace }
|
||||
func (c SecretChange) GetAnnotations() map[string]string { return c.Secret.Annotations }
|
||||
func (c SecretChange) GetResourceType() ResourceType { return ResourceTypeSecret }
|
||||
func (c SecretChange) ComputeHash(h *Hasher) string { return h.HashSecret(c.Secret) }
|
||||
|
||||
// EventType represents the type of change event.
|
||||
type EventType string
|
||||
|
||||
const (
|
||||
// EventTypeCreate indicates a resource was created.
|
||||
EventTypeCreate EventType = "create"
|
||||
// EventTypeUpdate indicates a resource was updated.
|
||||
EventTypeUpdate EventType = "update"
|
||||
// EventTypeDelete indicates a resource was deleted.
|
||||
EventTypeDelete EventType = "delete"
|
||||
)
|
||||
|
||||
// ReloadDecision contains the result of evaluating whether to reload a workload.
|
||||
type ReloadDecision struct {
|
||||
// Workload is the workload accessor.
|
||||
Workload workload.WorkloadAccessor
|
||||
// ShouldReload indicates whether the workload should be reloaded.
|
||||
ShouldReload bool
|
||||
// AutoReload indicates if this is an auto-reload.
|
||||
AutoReload bool
|
||||
// Reason provides a human-readable explanation.
|
||||
Reason string
|
||||
// Hash is the computed hash of the resource content.
|
||||
Hash string
|
||||
}
|
||||
|
||||
// FilterDecisions returns only decisions where ShouldReload is true.
|
||||
func FilterDecisions(decisions []ReloadDecision) []ReloadDecision {
|
||||
var result []ReloadDecision
|
||||
for _, d := range decisions {
|
||||
if d.ShouldReload {
|
||||
result = append(result, d)
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
// Process evaluates all workloads to determine which should be reloaded.
|
||||
func (s *Service) Process(change ResourceChange, workloads []workload.WorkloadAccessor) []ReloadDecision {
|
||||
if change.IsNil() {
|
||||
@@ -129,7 +53,6 @@ func (s *Service) Process(change ResourceChange, workloads []workload.WorkloadAc
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
func (s *Service) processResource(
|
||||
resourceName string,
|
||||
resourceNamespace string,
|
||||
|
||||
Reference in New Issue
Block a user