mirror of
https://github.com/stakater/Reloader.git
synced 2026-08-20 12:36:26 +00:00
Merge pull request #1191 from stakater/refactor/public-config-reload-metadata
Expose the reload decision API in a public package (v2)
This commit is contained in:
@@ -49,7 +49,6 @@ jobs:
|
||||
ref: ${{github.event.pull_request.head.sha}}
|
||||
fetch-depth: 0
|
||||
|
||||
# Setting up helm binary
|
||||
- name: Set up Helm
|
||||
uses: azure/setup-helm@dda3372f752e03dde6b3237bc9431cdc2f7a02a2 # v5
|
||||
with:
|
||||
|
||||
@@ -26,6 +26,7 @@ RUN go mod download
|
||||
# Copy the go source
|
||||
COPY cmd/ cmd/
|
||||
COPY internal/ internal/
|
||||
COPY pkg/ pkg/
|
||||
|
||||
# Build
|
||||
RUN CGO_ENABLED=0 \
|
||||
|
||||
@@ -17,12 +17,13 @@ import (
|
||||
"k8s.io/client-go/discovery"
|
||||
controllerruntime "sigs.k8s.io/controller-runtime"
|
||||
|
||||
"github.com/stakater/Reloader/internal/pkg/config"
|
||||
"github.com/stakater/Reloader/internal/pkg/config/flags"
|
||||
"github.com/stakater/Reloader/internal/pkg/controller"
|
||||
"github.com/stakater/Reloader/internal/pkg/csi"
|
||||
"github.com/stakater/Reloader/internal/pkg/metadata"
|
||||
"github.com/stakater/Reloader/internal/pkg/metrics"
|
||||
"github.com/stakater/Reloader/internal/pkg/openshift"
|
||||
"github.com/stakater/Reloader/pkg/config"
|
||||
"github.com/stakater/Reloader/pkg/metadata"
|
||||
)
|
||||
|
||||
// Environment variable names for pod identity in HA mode.
|
||||
@@ -49,20 +50,20 @@ func newReloaderCommand() *cobra.Command {
|
||||
RunE: run,
|
||||
}
|
||||
|
||||
config.BindFlags(cmd.PersistentFlags(), cfg)
|
||||
flags.BindFlags(cmd.PersistentFlags(), cfg)
|
||||
return cmd
|
||||
}
|
||||
|
||||
func run(cmd *cobra.Command, args []string) error {
|
||||
// Configure logging first so ApplyFlags can surface namespace-scope warnings
|
||||
// through a ready logger instead of returning them to the caller.
|
||||
log, err := configureLogging(config.LoggingFlags())
|
||||
log, err := configureLogging(flags.LoggingFlags())
|
||||
if err != nil {
|
||||
return fmt.Errorf("configuring logging: %w", err)
|
||||
}
|
||||
controllerruntime.SetLogger(log)
|
||||
|
||||
if err := config.ApplyFlags(cfg, log); err != nil {
|
||||
if err := flags.ApplyFlags(cfg, log); err != nil {
|
||||
return fmt.Errorf("applying flags: %w", err)
|
||||
}
|
||||
|
||||
@@ -116,7 +117,7 @@ func run(cmd *cobra.Command, args []string) error {
|
||||
log.V(1).Info("Failed to create discovery client", "error", discErr)
|
||||
}
|
||||
|
||||
if config.ShouldAutoDetectOpenShift() {
|
||||
if flags.ShouldAutoDetectOpenShift() {
|
||||
if discoveryClient != nil && openshift.HasDeploymentConfigSupport(discoveryClient, log) {
|
||||
cfg.DeploymentConfigEnabled = true
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@ import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
"github.com/stakater/Reloader/internal/pkg/config"
|
||||
"github.com/stakater/Reloader/pkg/config"
|
||||
)
|
||||
|
||||
// AlertMessage contains the details of a reload event to be sent as an alert.
|
||||
|
||||
@@ -10,7 +10,7 @@ import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/stakater/Reloader/internal/pkg/config"
|
||||
"github.com/stakater/Reloader/pkg/config"
|
||||
)
|
||||
|
||||
// testServer creates a test HTTP server that captures the request body.
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package config
|
||||
package flags
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
@@ -9,6 +9,8 @@ import (
|
||||
"github.com/spf13/pflag"
|
||||
"github.com/spf13/viper"
|
||||
"k8s.io/apimachinery/pkg/labels"
|
||||
|
||||
"github.com/stakater/Reloader/pkg/config"
|
||||
)
|
||||
|
||||
// v is the viper instance for configuration.
|
||||
@@ -23,7 +25,7 @@ func init() {
|
||||
|
||||
// BindFlags binds configuration flags to the provided flag set.
|
||||
// Call this before parsing flags, then call ApplyFlags after parsing.
|
||||
func BindFlags(fs *pflag.FlagSet, cfg *Config) {
|
||||
func BindFlags(fs *pflag.FlagSet, cfg *config.Config) {
|
||||
// Auto reload
|
||||
fs.Bool(
|
||||
"auto-reload-all", cfg.AutoReloadAll,
|
||||
@@ -275,7 +277,7 @@ func LoggingFlags() (format, level string) {
|
||||
// ApplyFlags applies flag values from viper to the config struct. Call this
|
||||
// after parsing flags. It finalizes namespace scope and logs any warnings it
|
||||
// produces through the given logger.
|
||||
func ApplyFlags(cfg *Config, log logr.Logger) error {
|
||||
func ApplyFlags(cfg *config.Config, log logr.Logger) error {
|
||||
// Boolean flags
|
||||
cfg.AutoReloadAll = v.GetBool("auto-reload-all")
|
||||
cfg.SyncAfterRestart = v.GetBool("sync-after-restart")
|
||||
@@ -297,7 +299,7 @@ func ApplyFlags(cfg *Config, log logr.Logger) error {
|
||||
}
|
||||
|
||||
// String flags
|
||||
cfg.ReloadStrategy = ReloadStrategy(v.GetString("reload-strategy"))
|
||||
cfg.ReloadStrategy = config.ReloadStrategy(v.GetString("reload-strategy"))
|
||||
cfg.WebhookURL = v.GetString("webhook-url")
|
||||
cfg.LogFormat = v.GetString("log-format")
|
||||
cfg.LogLevel = v.GetString("log-level")
|
||||
@@ -1,4 +1,4 @@
|
||||
package config
|
||||
package flags
|
||||
|
||||
import (
|
||||
"strings"
|
||||
@@ -7,6 +7,8 @@ import (
|
||||
"github.com/go-logr/logr"
|
||||
"github.com/spf13/pflag"
|
||||
"github.com/spf13/viper"
|
||||
|
||||
"github.com/stakater/Reloader/pkg/config"
|
||||
)
|
||||
|
||||
// resetViper resets the viper instance for testing.
|
||||
@@ -18,7 +20,7 @@ func resetViper() {
|
||||
|
||||
func TestBindFlags(t *testing.T) {
|
||||
resetViper()
|
||||
cfg := NewDefault()
|
||||
cfg := config.NewDefault()
|
||||
fs := pflag.NewFlagSet("test", pflag.ContinueOnError)
|
||||
|
||||
BindFlags(fs, cfg)
|
||||
@@ -84,7 +86,7 @@ func TestBindFlags(t *testing.T) {
|
||||
|
||||
func TestBindFlags_DefaultValues(t *testing.T) {
|
||||
resetViper()
|
||||
cfg := NewDefault()
|
||||
cfg := config.NewDefault()
|
||||
fs := pflag.NewFlagSet("test", pflag.ContinueOnError)
|
||||
|
||||
BindFlags(fs, cfg)
|
||||
@@ -97,8 +99,8 @@ func TestBindFlags_DefaultValues(t *testing.T) {
|
||||
t.Fatalf("ApplyFlags() error = %v", err)
|
||||
}
|
||||
|
||||
if cfg.ReloadStrategy != ReloadStrategyEnvVars {
|
||||
t.Errorf("ReloadStrategy = %v, want %v", cfg.ReloadStrategy, ReloadStrategyEnvVars)
|
||||
if cfg.ReloadStrategy != config.ReloadStrategyEnvVars {
|
||||
t.Errorf("ReloadStrategy = %v, want %v", cfg.ReloadStrategy, config.ReloadStrategyEnvVars)
|
||||
}
|
||||
|
||||
if cfg.LogLevel != "info" {
|
||||
@@ -108,7 +110,7 @@ func TestBindFlags_DefaultValues(t *testing.T) {
|
||||
|
||||
func TestBindFlags_CustomValues(t *testing.T) {
|
||||
resetViper()
|
||||
cfg := NewDefault()
|
||||
cfg := config.NewDefault()
|
||||
fs := pflag.NewFlagSet("test", pflag.ContinueOnError)
|
||||
|
||||
BindFlags(fs, cfg)
|
||||
@@ -135,8 +137,8 @@ func TestBindFlags_CustomValues(t *testing.T) {
|
||||
t.Error("AutoReloadAll should be true")
|
||||
}
|
||||
|
||||
if cfg.ReloadStrategy != ReloadStrategyAnnotations {
|
||||
t.Errorf("ReloadStrategy = %v, want %v", cfg.ReloadStrategy, ReloadStrategyAnnotations)
|
||||
if cfg.ReloadStrategy != config.ReloadStrategyAnnotations {
|
||||
t.Errorf("ReloadStrategy = %v, want %v", cfg.ReloadStrategy, config.ReloadStrategyAnnotations)
|
||||
}
|
||||
|
||||
if cfg.LogLevel != "debug" {
|
||||
@@ -163,7 +165,7 @@ func TestBindFlags_CustomValues(t *testing.T) {
|
||||
func TestApplyFlags_SecretProviderClassAnnotations(t *testing.T) {
|
||||
// Defaults are preserved when the flags are not provided.
|
||||
resetViper()
|
||||
cfg := NewDefault()
|
||||
cfg := config.NewDefault()
|
||||
fs := pflag.NewFlagSet("test", pflag.ContinueOnError)
|
||||
BindFlags(fs, cfg)
|
||||
if err := fs.Parse(nil); err != nil {
|
||||
@@ -172,7 +174,7 @@ func TestApplyFlags_SecretProviderClassAnnotations(t *testing.T) {
|
||||
if err := ApplyFlags(cfg, logr.Discard()); err != nil {
|
||||
t.Fatalf("ApplyFlags() error = %v", err)
|
||||
}
|
||||
defaults := DefaultAnnotations()
|
||||
defaults := config.DefaultAnnotations()
|
||||
if cfg.Annotations.SecretProviderClassAuto != defaults.SecretProviderClassAuto {
|
||||
t.Errorf("SecretProviderClassAuto = %q, want default %q", cfg.Annotations.SecretProviderClassAuto, defaults.SecretProviderClassAuto)
|
||||
}
|
||||
@@ -185,7 +187,7 @@ func TestApplyFlags_SecretProviderClassAnnotations(t *testing.T) {
|
||||
|
||||
// Custom values are applied from the flags.
|
||||
resetViper()
|
||||
cfg = NewDefault()
|
||||
cfg = config.NewDefault()
|
||||
fs = pflag.NewFlagSet("test", pflag.ContinueOnError)
|
||||
BindFlags(fs, cfg)
|
||||
args := []string{
|
||||
@@ -213,7 +215,7 @@ func TestApplyFlags_SecretProviderClassAnnotations(t *testing.T) {
|
||||
func TestApplyFlags_ExcludeAnnotations(t *testing.T) {
|
||||
// Defaults are preserved when the flags are not provided.
|
||||
resetViper()
|
||||
cfg := NewDefault()
|
||||
cfg := config.NewDefault()
|
||||
fs := pflag.NewFlagSet("test", pflag.ContinueOnError)
|
||||
BindFlags(fs, cfg)
|
||||
if err := fs.Parse(nil); err != nil {
|
||||
@@ -222,7 +224,7 @@ func TestApplyFlags_ExcludeAnnotations(t *testing.T) {
|
||||
if err := ApplyFlags(cfg, logr.Discard()); err != nil {
|
||||
t.Fatalf("ApplyFlags() error = %v", err)
|
||||
}
|
||||
defaults := DefaultAnnotations()
|
||||
defaults := config.DefaultAnnotations()
|
||||
if cfg.Annotations.ConfigmapExclude != defaults.ConfigmapExclude {
|
||||
t.Errorf("ConfigmapExclude = %q, want default %q", cfg.Annotations.ConfigmapExclude, defaults.ConfigmapExclude)
|
||||
}
|
||||
@@ -232,7 +234,7 @@ func TestApplyFlags_ExcludeAnnotations(t *testing.T) {
|
||||
|
||||
// Custom values are applied from the flags.
|
||||
resetViper()
|
||||
cfg = NewDefault()
|
||||
cfg = config.NewDefault()
|
||||
fs = pflag.NewFlagSet("test", pflag.ContinueOnError)
|
||||
BindFlags(fs, cfg)
|
||||
args := []string{
|
||||
@@ -256,7 +258,7 @@ func TestApplyFlags_ExcludeAnnotations(t *testing.T) {
|
||||
func TestApplyFlags_IgnoreAnnotation(t *testing.T) {
|
||||
// Default is preserved when the flag is not provided.
|
||||
resetViper()
|
||||
cfg := NewDefault()
|
||||
cfg := config.NewDefault()
|
||||
fs := pflag.NewFlagSet("test", pflag.ContinueOnError)
|
||||
BindFlags(fs, cfg)
|
||||
if err := fs.Parse(nil); err != nil {
|
||||
@@ -265,13 +267,13 @@ func TestApplyFlags_IgnoreAnnotation(t *testing.T) {
|
||||
if err := ApplyFlags(cfg, logr.Discard()); err != nil {
|
||||
t.Fatalf("ApplyFlags() error = %v", err)
|
||||
}
|
||||
if cfg.Annotations.Ignore != DefaultAnnotations().Ignore {
|
||||
t.Errorf("Ignore = %q, want default %q", cfg.Annotations.Ignore, DefaultAnnotations().Ignore)
|
||||
if cfg.Annotations.Ignore != config.DefaultAnnotations().Ignore {
|
||||
t.Errorf("Ignore = %q, want default %q", cfg.Annotations.Ignore, config.DefaultAnnotations().Ignore)
|
||||
}
|
||||
|
||||
// Custom value is applied from the flag.
|
||||
resetViper()
|
||||
cfg = NewDefault()
|
||||
cfg = config.NewDefault()
|
||||
fs = pflag.NewFlagSet("test", pflag.ContinueOnError)
|
||||
BindFlags(fs, cfg)
|
||||
if err := fs.Parse([]string{"--ignore-annotation=my.company.com/reloader-ignore"}); err != nil {
|
||||
@@ -306,7 +308,7 @@ func TestApplyFlags_BooleanStrings(t *testing.T) {
|
||||
t.Run(
|
||||
tt.name, func(t *testing.T) {
|
||||
resetViper()
|
||||
cfg := NewDefault()
|
||||
cfg := config.NewDefault()
|
||||
fs := pflag.NewFlagSet("test", pflag.ContinueOnError)
|
||||
BindFlags(fs, cfg)
|
||||
|
||||
@@ -330,7 +332,7 @@ func TestApplyFlags_BooleanStrings(t *testing.T) {
|
||||
|
||||
func TestApplyFlags_CommaSeparatedLists(t *testing.T) {
|
||||
resetViper()
|
||||
cfg := NewDefault()
|
||||
cfg := config.NewDefault()
|
||||
fs := pflag.NewFlagSet("test", pflag.ContinueOnError)
|
||||
BindFlags(fs, cfg)
|
||||
|
||||
@@ -366,7 +368,7 @@ func TestApplyFlags_CommaSeparatedLists(t *testing.T) {
|
||||
|
||||
func TestApplyFlags_Selectors(t *testing.T) {
|
||||
resetViper()
|
||||
cfg := NewDefault()
|
||||
cfg := config.NewDefault()
|
||||
fs := pflag.NewFlagSet("test", pflag.ContinueOnError)
|
||||
BindFlags(fs, cfg)
|
||||
|
||||
@@ -398,7 +400,7 @@ func TestApplyFlags_Selectors(t *testing.T) {
|
||||
|
||||
func TestApplyFlags_InvalidSelector(t *testing.T) {
|
||||
resetViper()
|
||||
cfg := NewDefault()
|
||||
cfg := config.NewDefault()
|
||||
fs := pflag.NewFlagSet("test", pflag.ContinueOnError)
|
||||
BindFlags(fs, cfg)
|
||||
|
||||
@@ -454,7 +456,7 @@ func TestApplyFlags_AlertingEnvVars(t *testing.T) {
|
||||
t.Setenv(k, val)
|
||||
}
|
||||
|
||||
cfg := NewDefault()
|
||||
cfg := config.NewDefault()
|
||||
fs := pflag.NewFlagSet("test", pflag.ContinueOnError)
|
||||
BindFlags(fs, cfg)
|
||||
|
||||
@@ -487,7 +489,7 @@ func TestApplyFlags_LegacyProxyEnvVar(t *testing.T) {
|
||||
|
||||
t.Setenv("ALERT_WEBHOOK_PROXY", "http://legacy-proxy:8080")
|
||||
|
||||
cfg := NewDefault()
|
||||
cfg := config.NewDefault()
|
||||
fs := pflag.NewFlagSet("test", pflag.ContinueOnError)
|
||||
BindFlags(fs, cfg)
|
||||
|
||||
@@ -506,7 +508,7 @@ func TestApplyFlags_LegacyProxyEnvVar(t *testing.T) {
|
||||
|
||||
func TestApplyFlagsCSIIntegration(t *testing.T) {
|
||||
resetViper()
|
||||
cfg := NewDefault()
|
||||
cfg := config.NewDefault()
|
||||
fs := pflag.NewFlagSet("test", pflag.ContinueOnError)
|
||||
BindFlags(fs, cfg)
|
||||
if err := fs.Parse([]string{"--enable-csi-integration=true"}); err != nil {
|
||||
@@ -586,7 +588,7 @@ func TestSplitAndTrim(t *testing.T) {
|
||||
|
||||
func TestApplyFlags_NamespacesScoped(t *testing.T) {
|
||||
resetViper()
|
||||
cfg := NewDefault()
|
||||
cfg := config.NewDefault()
|
||||
fs := pflag.NewFlagSet("test", pflag.ContinueOnError)
|
||||
BindFlags(fs, cfg)
|
||||
|
||||
@@ -611,7 +613,7 @@ func TestApplyFlags_NamespacesScoped(t *testing.T) {
|
||||
func TestApplyFlags_NamespacesFromEnv(t *testing.T) {
|
||||
resetViper()
|
||||
t.Setenv("KUBERNETES_NAMESPACE", "single-ns")
|
||||
cfg := NewDefault()
|
||||
cfg := config.NewDefault()
|
||||
fs := pflag.NewFlagSet("test", pflag.ContinueOnError)
|
||||
BindFlags(fs, cfg)
|
||||
|
||||
@@ -630,7 +632,7 @@ func TestApplyFlags_NamespacesFromEnv(t *testing.T) {
|
||||
func TestApplyFlags_NamespacesGlobal(t *testing.T) {
|
||||
resetViper()
|
||||
t.Setenv("KUBERNETES_NAMESPACE", "")
|
||||
cfg := NewDefault()
|
||||
cfg := config.NewDefault()
|
||||
fs := pflag.NewFlagSet("test", pflag.ContinueOnError)
|
||||
BindFlags(fs, cfg)
|
||||
|
||||
@@ -651,7 +653,7 @@ func TestApplyFlags_NamespacesGlobal(t *testing.T) {
|
||||
|
||||
func TestApplyFlags_NamespacesTrimsEmptyEntries(t *testing.T) {
|
||||
resetViper()
|
||||
cfg := NewDefault()
|
||||
cfg := config.NewDefault()
|
||||
fs := pflag.NewFlagSet("test", pflag.ContinueOnError)
|
||||
BindFlags(fs, cfg)
|
||||
|
||||
@@ -676,7 +678,7 @@ func TestApplyFlags_NamespacesTrimsEmptyEntries(t *testing.T) {
|
||||
func TestApplyFlags_NamespacesAllEmptyIsGlobal(t *testing.T) {
|
||||
resetViper()
|
||||
t.Setenv("KUBERNETES_NAMESPACE", "")
|
||||
cfg := NewDefault()
|
||||
cfg := config.NewDefault()
|
||||
fs := pflag.NewFlagSet("test", pflag.ContinueOnError)
|
||||
BindFlags(fs, cfg)
|
||||
|
||||
@@ -700,7 +702,7 @@ func TestApplyFlags_NamespacesAllEmptyIsGlobal(t *testing.T) {
|
||||
// for each dropped setting.
|
||||
func TestApplyFlags_ScopedClearsSelectorsAndIgnores(t *testing.T) {
|
||||
resetViper()
|
||||
cfg := NewDefault()
|
||||
cfg := config.NewDefault()
|
||||
fs := pflag.NewFlagSet("test", pflag.ContinueOnError)
|
||||
BindFlags(fs, cfg)
|
||||
|
||||
@@ -726,7 +728,7 @@ func TestApplyFlags_ScopedClearsSelectorsAndIgnores(t *testing.T) {
|
||||
func TestApplyFlags_GlobalKeepsSelectorsNoWarnings(t *testing.T) {
|
||||
resetViper()
|
||||
t.Setenv("KUBERNETES_NAMESPACE", "")
|
||||
cfg := NewDefault()
|
||||
cfg := config.NewDefault()
|
||||
fs := pflag.NewFlagSet("test", pflag.ContinueOnError)
|
||||
BindFlags(fs, cfg)
|
||||
|
||||
@@ -9,12 +9,13 @@ import (
|
||||
"sigs.k8s.io/controller-runtime/pkg/reconcile"
|
||||
|
||||
"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"
|
||||
"github.com/stakater/Reloader/internal/pkg/webhook"
|
||||
"github.com/stakater/Reloader/internal/pkg/workload"
|
||||
"github.com/stakater/Reloader/pkg/config"
|
||||
"github.com/stakater/Reloader/pkg/matcher"
|
||||
)
|
||||
|
||||
// ConfigMapReconciler watches ConfigMaps and triggers workload reloads.
|
||||
@@ -49,7 +50,7 @@ func NewConfigMapReconciler(
|
||||
NamespaceCache: nsCache,
|
||||
},
|
||||
ResourceConfig[*corev1.ConfigMap]{
|
||||
ResourceType: reload.ResourceTypeConfigMap,
|
||||
ResourceType: matcher.ResourceTypeConfigMap,
|
||||
NewResource: func() *corev1.ConfigMap { return &corev1.ConfigMap{} },
|
||||
CreateChange: func(cm *corev1.ConfigMap, eventType reload.EventType) reload.ResourceChange {
|
||||
return reload.ConfigMapChange{ConfigMap: cm, EventType: eventType}
|
||||
|
||||
@@ -3,8 +3,8 @@ package controller_test
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stakater/Reloader/internal/pkg/config"
|
||||
"github.com/stakater/Reloader/internal/pkg/testutil"
|
||||
"github.com/stakater/Reloader/pkg/config"
|
||||
)
|
||||
|
||||
func TestConfigMapReconciler_NotFound(t *testing.T) {
|
||||
|
||||
@@ -10,8 +10,8 @@ import (
|
||||
"sigs.k8s.io/controller-runtime/pkg/client"
|
||||
"sigs.k8s.io/controller-runtime/pkg/predicate"
|
||||
|
||||
"github.com/stakater/Reloader/internal/pkg/config"
|
||||
"github.com/stakater/Reloader/internal/pkg/reload"
|
||||
"github.com/stakater/Reloader/pkg/config"
|
||||
)
|
||||
|
||||
// DeploymentReconciler reconciles Deployment objects to handle pause expiration.
|
||||
|
||||
@@ -6,8 +6,8 @@ import (
|
||||
"sigs.k8s.io/controller-runtime/pkg/event"
|
||||
"sigs.k8s.io/controller-runtime/pkg/predicate"
|
||||
|
||||
"github.com/stakater/Reloader/internal/pkg/config"
|
||||
"github.com/stakater/Reloader/internal/pkg/reload"
|
||||
"github.com/stakater/Reloader/pkg/config"
|
||||
)
|
||||
|
||||
// BuildEventFilter combines a resource-specific predicate with common filters.
|
||||
|
||||
@@ -8,7 +8,7 @@ import (
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"sigs.k8s.io/controller-runtime/pkg/event"
|
||||
|
||||
"github.com/stakater/Reloader/internal/pkg/config"
|
||||
"github.com/stakater/Reloader/pkg/config"
|
||||
)
|
||||
|
||||
func TestCreateEventPredicate_CreateEvent(t *testing.T) {
|
||||
|
||||
@@ -14,6 +14,7 @@ import (
|
||||
"github.com/stakater/Reloader/internal/pkg/reload"
|
||||
"github.com/stakater/Reloader/internal/pkg/webhook"
|
||||
"github.com/stakater/Reloader/internal/pkg/workload"
|
||||
"github.com/stakater/Reloader/pkg/matcher"
|
||||
)
|
||||
|
||||
// ReloadHandler handles the common reload workflow.
|
||||
@@ -32,7 +33,7 @@ type ReloadHandler struct {
|
||||
func (h *ReloadHandler) Process(
|
||||
ctx context.Context,
|
||||
namespace, resourceName string,
|
||||
resourceType reload.ResourceType,
|
||||
resourceType matcher.ResourceType,
|
||||
getDecisions func([]workload.Workload) []reload.ReloadDecision,
|
||||
log logr.Logger,
|
||||
) (ctrl.Result, error) {
|
||||
@@ -76,7 +77,7 @@ func (h *ReloadHandler) Process(
|
||||
func (h *ReloadHandler) sendWebhook(
|
||||
ctx context.Context,
|
||||
resourceName, namespace string,
|
||||
resourceType reload.ResourceType,
|
||||
resourceType matcher.ResourceType,
|
||||
decisions []reload.ReloadDecision,
|
||||
log logr.Logger,
|
||||
) (ctrl.Result, error) {
|
||||
@@ -127,7 +128,7 @@ func (h *ReloadHandler) sendWebhook(
|
||||
func (h *ReloadHandler) applyReloads(
|
||||
ctx context.Context,
|
||||
resourceName, resourceNamespace string,
|
||||
resourceType reload.ResourceType,
|
||||
resourceType matcher.ResourceType,
|
||||
decisions []reload.ReloadDecision,
|
||||
log logr.Logger,
|
||||
) {
|
||||
|
||||
@@ -18,12 +18,12 @@ import (
|
||||
csiv1 "sigs.k8s.io/secrets-store-csi-driver/apis/v1"
|
||||
|
||||
"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"
|
||||
"github.com/stakater/Reloader/internal/pkg/webhook"
|
||||
"github.com/stakater/Reloader/internal/pkg/workload"
|
||||
"github.com/stakater/Reloader/pkg/config"
|
||||
)
|
||||
|
||||
var runtimeScheme = runtime.NewScheme()
|
||||
|
||||
@@ -11,8 +11,8 @@ import (
|
||||
"sigs.k8s.io/controller-runtime/pkg/client"
|
||||
"sigs.k8s.io/controller-runtime/pkg/reconcile"
|
||||
|
||||
"github.com/stakater/Reloader/internal/pkg/config"
|
||||
"github.com/stakater/Reloader/internal/pkg/reload"
|
||||
"github.com/stakater/Reloader/pkg/config"
|
||||
)
|
||||
|
||||
// NamespaceCache provides thread-safe access to the set of namespaces
|
||||
|
||||
@@ -5,9 +5,9 @@ import (
|
||||
|
||||
"k8s.io/apimachinery/pkg/labels"
|
||||
|
||||
"github.com/stakater/Reloader/internal/pkg/config"
|
||||
"github.com/stakater/Reloader/internal/pkg/controller"
|
||||
"github.com/stakater/Reloader/internal/pkg/testutil"
|
||||
"github.com/stakater/Reloader/pkg/config"
|
||||
)
|
||||
|
||||
func TestNamespaceCache_Basic(t *testing.T) {
|
||||
|
||||
@@ -11,12 +11,13 @@ import (
|
||||
"sigs.k8s.io/controller-runtime/pkg/predicate"
|
||||
|
||||
"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"
|
||||
"github.com/stakater/Reloader/internal/pkg/webhook"
|
||||
"github.com/stakater/Reloader/internal/pkg/workload"
|
||||
"github.com/stakater/Reloader/pkg/config"
|
||||
"github.com/stakater/Reloader/pkg/matcher"
|
||||
)
|
||||
|
||||
// ResourceReconcilerDeps holds shared dependencies for resource reconcilers.
|
||||
@@ -39,7 +40,7 @@ type ResourceReconcilerDeps struct {
|
||||
// ResourceConfig provides type-specific configuration for a resource reconciler.
|
||||
type ResourceConfig[T client.Object] struct {
|
||||
// ResourceType identifies the type of resource (configmap or secret).
|
||||
ResourceType reload.ResourceType
|
||||
ResourceType matcher.ResourceType
|
||||
|
||||
// NewResource creates a new instance of the resource type.
|
||||
NewResource func() T
|
||||
|
||||
@@ -9,6 +9,7 @@ import (
|
||||
|
||||
"github.com/stakater/Reloader/internal/pkg/reload"
|
||||
"github.com/stakater/Reloader/internal/pkg/workload"
|
||||
"github.com/stakater/Reloader/pkg/matcher"
|
||||
)
|
||||
|
||||
// UpdateObjectWithRetry updates a Kubernetes object with retry on conflict.
|
||||
@@ -58,7 +59,7 @@ func UpdateWorkloadWithRetry(
|
||||
pauseHandler *reload.PauseHandler,
|
||||
wl workload.Workload,
|
||||
resourceName string,
|
||||
resourceType reload.ResourceType,
|
||||
resourceType matcher.ResourceType,
|
||||
namespace string,
|
||||
hash string,
|
||||
autoReload bool,
|
||||
@@ -83,7 +84,7 @@ func retryWithReload(
|
||||
reloadService *reload.Service,
|
||||
wl workload.Workload,
|
||||
resourceName string,
|
||||
resourceType reload.ResourceType,
|
||||
resourceType matcher.ResourceType,
|
||||
namespace string,
|
||||
hash string,
|
||||
autoReload bool,
|
||||
@@ -131,7 +132,7 @@ func updateStandardWorkload(
|
||||
reloadService *reload.Service,
|
||||
wl workload.Workload,
|
||||
resourceName string,
|
||||
resourceType reload.ResourceType,
|
||||
resourceType matcher.ResourceType,
|
||||
namespace string,
|
||||
hash string,
|
||||
autoReload bool,
|
||||
@@ -152,7 +153,7 @@ func updateDeploymentWithPause(
|
||||
pauseHandler *reload.PauseHandler,
|
||||
wl workload.Workload,
|
||||
resourceName string,
|
||||
resourceType reload.ResourceType,
|
||||
resourceType matcher.ResourceType,
|
||||
namespace string,
|
||||
hash string,
|
||||
autoReload bool,
|
||||
@@ -180,7 +181,7 @@ func updateWithSpecialStrategy(
|
||||
reloadService *reload.Service,
|
||||
wl workload.Workload,
|
||||
resourceName string,
|
||||
resourceType reload.ResourceType,
|
||||
resourceType matcher.ResourceType,
|
||||
namespace string,
|
||||
hash string,
|
||||
autoReload bool,
|
||||
|
||||
@@ -13,11 +13,12 @@ import (
|
||||
"sigs.k8s.io/controller-runtime/pkg/client"
|
||||
"sigs.k8s.io/controller-runtime/pkg/client/fake"
|
||||
|
||||
"github.com/stakater/Reloader/internal/pkg/config"
|
||||
"github.com/stakater/Reloader/internal/pkg/controller"
|
||||
"github.com/stakater/Reloader/internal/pkg/reload"
|
||||
"github.com/stakater/Reloader/internal/pkg/testutil"
|
||||
"github.com/stakater/Reloader/internal/pkg/workload"
|
||||
"github.com/stakater/Reloader/pkg/config"
|
||||
"github.com/stakater/Reloader/pkg/matcher"
|
||||
)
|
||||
|
||||
func TestUpdateWorkloadWithRetry_WorkloadTypes(t *testing.T) {
|
||||
@@ -25,7 +26,7 @@ func TestUpdateWorkloadWithRetry_WorkloadTypes(t *testing.T) {
|
||||
name string
|
||||
object runtime.Object
|
||||
workload func(runtime.Object) workload.Workload
|
||||
resourceType reload.ResourceType
|
||||
resourceType matcher.ResourceType
|
||||
verify func(t *testing.T, c client.Client)
|
||||
}{
|
||||
{
|
||||
@@ -34,7 +35,7 @@ func TestUpdateWorkloadWithRetry_WorkloadTypes(t *testing.T) {
|
||||
workload: func(o runtime.Object) workload.Workload {
|
||||
return workload.NewDeploymentWorkload(o.(*appsv1.Deployment))
|
||||
},
|
||||
resourceType: reload.ResourceTypeConfigMap,
|
||||
resourceType: matcher.ResourceTypeConfigMap,
|
||||
verify: func(t *testing.T, c client.Client) {
|
||||
var result appsv1.Deployment
|
||||
if err := c.Get(context.Background(), types.NamespacedName{Name: "test-deployment", Namespace: "default"}, &result); err != nil {
|
||||
@@ -51,7 +52,7 @@ func TestUpdateWorkloadWithRetry_WorkloadTypes(t *testing.T) {
|
||||
workload: func(o runtime.Object) workload.Workload {
|
||||
return workload.NewDaemonSetWorkload(o.(*appsv1.DaemonSet))
|
||||
},
|
||||
resourceType: reload.ResourceTypeSecret,
|
||||
resourceType: matcher.ResourceTypeSecret,
|
||||
verify: func(t *testing.T, c client.Client) {
|
||||
var result appsv1.DaemonSet
|
||||
if err := c.Get(context.Background(), types.NamespacedName{Name: "test-daemonset", Namespace: "default"}, &result); err != nil {
|
||||
@@ -68,7 +69,7 @@ func TestUpdateWorkloadWithRetry_WorkloadTypes(t *testing.T) {
|
||||
workload: func(o runtime.Object) workload.Workload {
|
||||
return workload.NewStatefulSetWorkload(o.(*appsv1.StatefulSet))
|
||||
},
|
||||
resourceType: reload.ResourceTypeConfigMap,
|
||||
resourceType: matcher.ResourceTypeConfigMap,
|
||||
verify: func(t *testing.T, c client.Client) {
|
||||
var result appsv1.StatefulSet
|
||||
if err := c.Get(context.Background(), types.NamespacedName{Name: "test-statefulset", Namespace: "default"}, &result); err != nil {
|
||||
@@ -85,7 +86,7 @@ func TestUpdateWorkloadWithRetry_WorkloadTypes(t *testing.T) {
|
||||
workload: func(o runtime.Object) workload.Workload {
|
||||
return workload.NewJobWorkload(o.(*batchv1.Job))
|
||||
},
|
||||
resourceType: reload.ResourceTypeConfigMap,
|
||||
resourceType: matcher.ResourceTypeConfigMap,
|
||||
verify: func(t *testing.T, c client.Client) {
|
||||
var jobs batchv1.JobList
|
||||
if err := c.List(context.Background(), &jobs, client.InNamespace("default")); err != nil {
|
||||
@@ -102,7 +103,7 @@ func TestUpdateWorkloadWithRetry_WorkloadTypes(t *testing.T) {
|
||||
workload: func(o runtime.Object) workload.Workload {
|
||||
return workload.NewCronJobWorkload(o.(*batchv1.CronJob))
|
||||
},
|
||||
resourceType: reload.ResourceTypeSecret,
|
||||
resourceType: matcher.ResourceTypeSecret,
|
||||
verify: func(t *testing.T, c client.Client) {
|
||||
var jobs batchv1.JobList
|
||||
if err := c.List(context.Background(), &jobs, client.InNamespace("default")); err != nil {
|
||||
@@ -220,7 +221,7 @@ func TestUpdateWorkloadWithRetry_Strategies(t *testing.T) {
|
||||
nil, // no pause handler for this test
|
||||
wl,
|
||||
"test-cm",
|
||||
reload.ResourceTypeConfigMap,
|
||||
matcher.ResourceTypeConfigMap,
|
||||
"default",
|
||||
"abc123",
|
||||
false,
|
||||
@@ -272,7 +273,7 @@ func TestUpdateWorkloadWithRetry_NoUpdate(t *testing.T) {
|
||||
nil, // no pause handler
|
||||
wl,
|
||||
"test-cm",
|
||||
reload.ResourceTypeConfigMap,
|
||||
matcher.ResourceTypeConfigMap,
|
||||
"default",
|
||||
"abc123", // Same hash as already set
|
||||
false,
|
||||
@@ -288,11 +289,11 @@ func TestUpdateWorkloadWithRetry_NoUpdate(t *testing.T) {
|
||||
|
||||
func TestResourceTypeKind(t *testing.T) {
|
||||
tests := []struct {
|
||||
resourceType reload.ResourceType
|
||||
resourceType matcher.ResourceType
|
||||
expectedKind string
|
||||
}{
|
||||
{reload.ResourceTypeConfigMap, "ConfigMap"},
|
||||
{reload.ResourceTypeSecret, "Secret"},
|
||||
{matcher.ResourceTypeConfigMap, "ConfigMap"},
|
||||
{matcher.ResourceTypeSecret, "Secret"},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
@@ -332,7 +333,7 @@ func TestUpdateWorkloadWithRetry_PauseDeployment(t *testing.T) {
|
||||
pauseHandler,
|
||||
wl,
|
||||
"test-cm",
|
||||
reload.ResourceTypeConfigMap,
|
||||
matcher.ResourceTypeConfigMap,
|
||||
"default",
|
||||
"abc123",
|
||||
true,
|
||||
@@ -393,7 +394,7 @@ func TestUpdateWorkloadWithRetry_PauseWithExplicitAnnotation(t *testing.T) {
|
||||
pauseHandler,
|
||||
wl,
|
||||
"test-cm",
|
||||
reload.ResourceTypeConfigMap,
|
||||
matcher.ResourceTypeConfigMap,
|
||||
"default",
|
||||
"abc123",
|
||||
false, // NOT auto reload
|
||||
@@ -454,7 +455,7 @@ func TestUpdateWorkloadWithRetry_PauseWithSecretReload(t *testing.T) {
|
||||
pauseHandler,
|
||||
wl,
|
||||
"test-secret",
|
||||
reload.ResourceTypeSecret,
|
||||
matcher.ResourceTypeSecret,
|
||||
"default",
|
||||
"abc123",
|
||||
false,
|
||||
@@ -511,7 +512,7 @@ func TestUpdateWorkloadWithRetry_PauseWithAutoSecret(t *testing.T) {
|
||||
pauseHandler,
|
||||
wl,
|
||||
"test-secret",
|
||||
reload.ResourceTypeSecret,
|
||||
matcher.ResourceTypeSecret,
|
||||
"default",
|
||||
"abc123",
|
||||
true,
|
||||
@@ -561,7 +562,7 @@ func TestUpdateWorkloadWithRetry_NoPauseWithoutAnnotation(t *testing.T) {
|
||||
pauseHandler,
|
||||
wl,
|
||||
"test-cm",
|
||||
reload.ResourceTypeConfigMap,
|
||||
matcher.ResourceTypeConfigMap,
|
||||
"default",
|
||||
"abc123",
|
||||
true,
|
||||
|
||||
@@ -9,12 +9,13 @@ import (
|
||||
"sigs.k8s.io/controller-runtime/pkg/reconcile"
|
||||
|
||||
"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"
|
||||
"github.com/stakater/Reloader/internal/pkg/webhook"
|
||||
"github.com/stakater/Reloader/internal/pkg/workload"
|
||||
"github.com/stakater/Reloader/pkg/config"
|
||||
"github.com/stakater/Reloader/pkg/matcher"
|
||||
)
|
||||
|
||||
// SecretReconciler watches Secrets and triggers workload reloads.
|
||||
@@ -49,7 +50,7 @@ func NewSecretReconciler(
|
||||
NamespaceCache: nsCache,
|
||||
},
|
||||
ResourceConfig[*corev1.Secret]{
|
||||
ResourceType: reload.ResourceTypeSecret,
|
||||
ResourceType: matcher.ResourceTypeSecret,
|
||||
NewResource: func() *corev1.Secret { return &corev1.Secret{} },
|
||||
CreateChange: func(s *corev1.Secret, eventType reload.EventType) reload.ResourceChange {
|
||||
return reload.SecretChange{Secret: s, EventType: eventType}
|
||||
|
||||
@@ -3,8 +3,8 @@ package controller_test
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stakater/Reloader/internal/pkg/config"
|
||||
"github.com/stakater/Reloader/internal/pkg/testutil"
|
||||
"github.com/stakater/Reloader/pkg/config"
|
||||
)
|
||||
|
||||
func TestSecretReconciler_NotFound(t *testing.T) {
|
||||
|
||||
@@ -8,8 +8,8 @@ import (
|
||||
"sigs.k8s.io/controller-runtime/pkg/event"
|
||||
csiv1 "sigs.k8s.io/secrets-store-csi-driver/apis/v1"
|
||||
|
||||
"github.com/stakater/Reloader/internal/pkg/config"
|
||||
"github.com/stakater/Reloader/internal/pkg/reload"
|
||||
"github.com/stakater/Reloader/pkg/config"
|
||||
)
|
||||
|
||||
// TestSecretProviderClassReconciler_FilterIgnoresResourceLabelSelector pins the
|
||||
|
||||
@@ -12,8 +12,9 @@ import (
|
||||
"sigs.k8s.io/controller-runtime/pkg/reconcile"
|
||||
csiv1 "sigs.k8s.io/secrets-store-csi-driver/apis/v1"
|
||||
|
||||
"github.com/stakater/Reloader/internal/pkg/config"
|
||||
"github.com/stakater/Reloader/internal/pkg/reload"
|
||||
"github.com/stakater/Reloader/pkg/config"
|
||||
"github.com/stakater/Reloader/pkg/matcher"
|
||||
)
|
||||
|
||||
// SecretProviderClassReconciler watches SecretProviderClassPodStatus (the per-pod
|
||||
@@ -28,7 +29,7 @@ func NewSecretProviderClassReconciler(deps ResourceReconcilerDeps, apiReader cli
|
||||
return NewResourceReconciler(
|
||||
deps,
|
||||
ResourceConfig[*csiv1.SecretProviderClassPodStatus]{
|
||||
ResourceType: reload.ResourceTypeSecretProviderClass,
|
||||
ResourceType: matcher.ResourceTypeSecretProviderClass,
|
||||
NewResource: func() *csiv1.SecretProviderClassPodStatus { return &csiv1.SecretProviderClassPodStatus{} },
|
||||
ResolveChange: resolveSecretProviderClassChange,
|
||||
SkipOnNotFound: true,
|
||||
|
||||
@@ -10,10 +10,10 @@ import (
|
||||
"sigs.k8s.io/controller-runtime/pkg/client"
|
||||
csiv1 "sigs.k8s.io/secrets-store-csi-driver/apis/v1"
|
||||
|
||||
"github.com/stakater/Reloader/internal/pkg/config"
|
||||
"github.com/stakater/Reloader/internal/pkg/controller"
|
||||
"github.com/stakater/Reloader/internal/pkg/reload"
|
||||
"github.com/stakater/Reloader/internal/pkg/testutil"
|
||||
"github.com/stakater/Reloader/pkg/config"
|
||||
)
|
||||
|
||||
// newSecretProviderClassReconcilerWithClient creates a SecretProviderClassReconciler for
|
||||
|
||||
@@ -13,7 +13,6 @@ import (
|
||||
"sigs.k8s.io/controller-runtime/pkg/client/fake"
|
||||
|
||||
"github.com/stakater/Reloader/internal/pkg/alerting"
|
||||
"github.com/stakater/Reloader/internal/pkg/config"
|
||||
"github.com/stakater/Reloader/internal/pkg/controller"
|
||||
"github.com/stakater/Reloader/internal/pkg/events"
|
||||
"github.com/stakater/Reloader/internal/pkg/metrics"
|
||||
@@ -21,6 +20,7 @@ import (
|
||||
"github.com/stakater/Reloader/internal/pkg/testutil"
|
||||
"github.com/stakater/Reloader/internal/pkg/webhook"
|
||||
"github.com/stakater/Reloader/internal/pkg/workload"
|
||||
"github.com/stakater/Reloader/pkg/config"
|
||||
)
|
||||
|
||||
// testDeps holds shared test dependencies.
|
||||
|
||||
@@ -3,6 +3,8 @@ package reload
|
||||
import (
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
csiv1 "sigs.k8s.io/secrets-store-csi-driver/apis/v1"
|
||||
|
||||
"github.com/stakater/Reloader/pkg/matcher"
|
||||
)
|
||||
|
||||
// EventType represents the type of change event.
|
||||
@@ -24,7 +26,7 @@ type ResourceChange interface {
|
||||
GetName() string
|
||||
GetNamespace() string
|
||||
GetAnnotations() map[string]string
|
||||
GetResourceType() ResourceType
|
||||
GetResourceType() matcher.ResourceType
|
||||
ComputeHash(hasher *Hasher) string
|
||||
}
|
||||
|
||||
@@ -34,13 +36,13 @@ type ConfigMapChange struct {
|
||||
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) }
|
||||
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() matcher.ResourceType { return matcher.ResourceTypeConfigMap }
|
||||
func (c ConfigMapChange) ComputeHash(h *Hasher) string { return h.HashConfigMap(c.ConfigMap) }
|
||||
|
||||
// SecretChange represents a change event for a Secret.
|
||||
type SecretChange struct {
|
||||
@@ -48,13 +50,13 @@ type SecretChange struct {
|
||||
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) }
|
||||
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() matcher.ResourceType { return matcher.ResourceTypeSecret }
|
||||
func (c SecretChange) ComputeHash(h *Hasher) string { return h.HashSecret(c.Secret) }
|
||||
|
||||
// SecretProviderClassChange represents a change event derived from a
|
||||
// SecretProviderClassPodStatus update. Name/Annotations refer to the resolved
|
||||
@@ -74,8 +76,8 @@ func (c SecretProviderClassChange) GetNamespace() string { return c.Namespace
|
||||
func (c SecretProviderClassChange) GetAnnotations() map[string]string {
|
||||
return c.Annotations
|
||||
}
|
||||
func (c SecretProviderClassChange) GetResourceType() ResourceType {
|
||||
return ResourceTypeSecretProviderClass
|
||||
func (c SecretProviderClassChange) GetResourceType() matcher.ResourceType {
|
||||
return matcher.ResourceTypeSecretProviderClass
|
||||
}
|
||||
func (c SecretProviderClassChange) ComputeHash(h *Hasher) string {
|
||||
return h.HashSecretProviderClass(c.Status)
|
||||
|
||||
@@ -4,6 +4,8 @@ import (
|
||||
"testing"
|
||||
|
||||
csiv1 "sigs.k8s.io/secrets-store-csi-driver/apis/v1"
|
||||
|
||||
"github.com/stakater/Reloader/pkg/matcher"
|
||||
)
|
||||
|
||||
func TestSecretProviderClassChange(t *testing.T) {
|
||||
@@ -28,7 +30,7 @@ func TestSecretProviderClassChange(t *testing.T) {
|
||||
if c.GetNamespace() != "ns1" {
|
||||
t.Fatalf("GetNamespace() = %q", c.GetNamespace())
|
||||
}
|
||||
if c.GetResourceType() != ResourceTypeSecretProviderClass {
|
||||
if c.GetResourceType() != matcher.ResourceTypeSecretProviderClass {
|
||||
t.Fatalf("GetResourceType() = %q", c.GetResourceType())
|
||||
}
|
||||
if c.GetEventType() != EventTypeUpdate {
|
||||
|
||||
@@ -5,6 +5,7 @@ import (
|
||||
)
|
||||
|
||||
// ReloadDecision contains the result of evaluating whether to reload a workload.
|
||||
// External, decision-only consumers should use the public matcher package instead.
|
||||
type ReloadDecision struct {
|
||||
// Workload is the workload accessor.
|
||||
Workload workload.Workload
|
||||
|
||||
@@ -6,8 +6,8 @@ import (
|
||||
|
||||
appsv1 "k8s.io/api/apps/v1"
|
||||
|
||||
"github.com/stakater/Reloader/internal/pkg/config"
|
||||
"github.com/stakater/Reloader/internal/pkg/workload"
|
||||
"github.com/stakater/Reloader/pkg/config"
|
||||
)
|
||||
|
||||
// PauseHandler handles pause deployment logic.
|
||||
|
||||
@@ -7,8 +7,8 @@ import (
|
||||
appsv1 "k8s.io/api/apps/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
|
||||
"github.com/stakater/Reloader/internal/pkg/config"
|
||||
"github.com/stakater/Reloader/internal/pkg/workload"
|
||||
"github.com/stakater/Reloader/pkg/config"
|
||||
)
|
||||
|
||||
func TestPauseHandler_ShouldPause(t *testing.T) {
|
||||
|
||||
@@ -7,7 +7,7 @@ import (
|
||||
"sigs.k8s.io/controller-runtime/pkg/predicate"
|
||||
csiv1 "sigs.k8s.io/secrets-store-csi-driver/apis/v1"
|
||||
|
||||
"github.com/stakater/Reloader/internal/pkg/config"
|
||||
"github.com/stakater/Reloader/pkg/config"
|
||||
)
|
||||
|
||||
// resourcePredicates returns predicates for filtering resource events.
|
||||
|
||||
@@ -9,7 +9,7 @@ import (
|
||||
"sigs.k8s.io/controller-runtime/pkg/event"
|
||||
csiv1 "sigs.k8s.io/secrets-store-csi-driver/apis/v1"
|
||||
|
||||
"github.com/stakater/Reloader/internal/pkg/config"
|
||||
"github.com/stakater/Reloader/pkg/config"
|
||||
)
|
||||
|
||||
func TestNamespaceFilterPredicate_Create(t *testing.T) {
|
||||
|
||||
@@ -9,16 +9,18 @@ import (
|
||||
"github.com/go-logr/logr"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
|
||||
"github.com/stakater/Reloader/internal/pkg/config"
|
||||
"github.com/stakater/Reloader/internal/pkg/workload"
|
||||
"github.com/stakater/Reloader/pkg/config"
|
||||
"github.com/stakater/Reloader/pkg/matcher"
|
||||
)
|
||||
|
||||
// Service orchestrates the reload logic for ConfigMaps and Secrets.
|
||||
// External, decision-only consumers should use the public matcher package instead.
|
||||
type Service struct {
|
||||
cfg *config.Config
|
||||
log logr.Logger
|
||||
hasher *Hasher
|
||||
matcher *Matcher
|
||||
matcher *matcher.Matcher
|
||||
strategy Strategy
|
||||
}
|
||||
|
||||
@@ -28,7 +30,7 @@ func NewService(cfg *config.Config, log logr.Logger) *Service {
|
||||
cfg: cfg,
|
||||
log: log,
|
||||
hasher: NewHasher(),
|
||||
matcher: NewMatcher(cfg),
|
||||
matcher: matcher.NewMatcher(cfg),
|
||||
strategy: NewStrategy(cfg),
|
||||
}
|
||||
}
|
||||
@@ -62,7 +64,7 @@ func (s *Service) processResource(
|
||||
resourceName string,
|
||||
resourceNamespace string,
|
||||
resourceAnnotations map[string]string,
|
||||
resourceType ResourceType,
|
||||
resourceType matcher.ResourceType,
|
||||
hash string,
|
||||
workloads []workload.Workload,
|
||||
) []ReloadDecision {
|
||||
@@ -79,17 +81,17 @@ func (s *Service) processResource(
|
||||
|
||||
var usesResource bool
|
||||
switch resourceType {
|
||||
case ResourceTypeConfigMap:
|
||||
case matcher.ResourceTypeConfigMap:
|
||||
usesResource = wl.UsesConfigMap(resourceName)
|
||||
case ResourceTypeSecret:
|
||||
case matcher.ResourceTypeSecret:
|
||||
usesResource = wl.UsesSecret(resourceName)
|
||||
case ResourceTypeSecretProviderClass:
|
||||
case matcher.ResourceTypeSecretProviderClass:
|
||||
// Annotation-only matching (parity with master): the workload's
|
||||
// annotations alone decide the reload; no volume-uses scan.
|
||||
usesResource = true
|
||||
}
|
||||
|
||||
input := MatchInput{
|
||||
input := matcher.MatchInput{
|
||||
ResourceName: resourceName,
|
||||
ResourceNamespace: resourceNamespace,
|
||||
ResourceType: resourceType,
|
||||
@@ -137,7 +139,7 @@ func (s *Service) ApplyReload(
|
||||
ctx context.Context,
|
||||
wl workload.Workload,
|
||||
resourceName string,
|
||||
resourceType ResourceType,
|
||||
resourceType matcher.ResourceType,
|
||||
namespace string,
|
||||
hash string,
|
||||
autoReload bool,
|
||||
@@ -172,7 +174,7 @@ func (s *Service) ApplyReload(
|
||||
func (s *Service) setAttributionAnnotation(
|
||||
wl workload.Workload,
|
||||
resourceName string,
|
||||
resourceType ResourceType,
|
||||
resourceType matcher.ResourceType,
|
||||
namespace string,
|
||||
hash string,
|
||||
container *corev1.Container,
|
||||
@@ -203,7 +205,7 @@ func (s *Service) setAttributionAnnotation(
|
||||
func (s *Service) findTargetContainer(
|
||||
wl workload.Workload,
|
||||
resourceName string,
|
||||
resourceType ResourceType,
|
||||
resourceType matcher.ResourceType,
|
||||
autoReload bool,
|
||||
) *corev1.Container {
|
||||
containers := wl.GetContainers()
|
||||
@@ -243,10 +245,10 @@ func (s *Service) findTargetContainer(
|
||||
return &containers[0]
|
||||
}
|
||||
|
||||
func (s *Service) findVolumeUsingResource(volumes []corev1.Volume, resourceName string, resourceType ResourceType) string {
|
||||
func (s *Service) findVolumeUsingResource(volumes []corev1.Volume, resourceName string, resourceType matcher.ResourceType) string {
|
||||
for _, vol := range volumes {
|
||||
switch resourceType {
|
||||
case ResourceTypeConfigMap:
|
||||
case matcher.ResourceTypeConfigMap:
|
||||
if vol.ConfigMap != nil && vol.ConfigMap.Name == resourceName {
|
||||
return vol.Name
|
||||
}
|
||||
@@ -257,7 +259,7 @@ func (s *Service) findVolumeUsingResource(volumes []corev1.Volume, resourceName
|
||||
}
|
||||
}
|
||||
}
|
||||
case ResourceTypeSecret:
|
||||
case matcher.ResourceTypeSecret:
|
||||
if vol.Secret != nil && vol.Secret.SecretName == resourceName {
|
||||
return vol.Name
|
||||
}
|
||||
@@ -268,7 +270,7 @@ func (s *Service) findVolumeUsingResource(volumes []corev1.Volume, resourceName
|
||||
}
|
||||
}
|
||||
}
|
||||
case ResourceTypeSecretProviderClass:
|
||||
case matcher.ResourceTypeSecretProviderClass:
|
||||
// Match the CSI volume that references this SPC.
|
||||
if vol.CSI != nil && vol.CSI.VolumeAttributes["secretProviderClass"] == resourceName {
|
||||
return vol.Name
|
||||
@@ -289,18 +291,18 @@ func (s *Service) findContainerWithVolumeMount(containers []corev1.Container, vo
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *Service) findContainerWithEnvRef(containers []corev1.Container, resourceName string, resourceType ResourceType) *corev1.Container {
|
||||
func (s *Service) findContainerWithEnvRef(containers []corev1.Container, resourceName string, resourceType matcher.ResourceType) *corev1.Container {
|
||||
for i := range containers {
|
||||
for _, env := range containers[i].Env {
|
||||
if env.ValueFrom == nil {
|
||||
continue
|
||||
}
|
||||
switch resourceType {
|
||||
case ResourceTypeConfigMap:
|
||||
case matcher.ResourceTypeConfigMap:
|
||||
if env.ValueFrom.ConfigMapKeyRef != nil && env.ValueFrom.ConfigMapKeyRef.Name == resourceName {
|
||||
return &containers[i]
|
||||
}
|
||||
case ResourceTypeSecret:
|
||||
case matcher.ResourceTypeSecret:
|
||||
if env.ValueFrom.SecretKeyRef != nil && env.ValueFrom.SecretKeyRef.Name == resourceName {
|
||||
return &containers[i]
|
||||
}
|
||||
@@ -309,11 +311,11 @@ func (s *Service) findContainerWithEnvRef(containers []corev1.Container, resourc
|
||||
|
||||
for _, envFrom := range containers[i].EnvFrom {
|
||||
switch resourceType {
|
||||
case ResourceTypeConfigMap:
|
||||
case matcher.ResourceTypeConfigMap:
|
||||
if envFrom.ConfigMapRef != nil && envFrom.ConfigMapRef.Name == resourceName {
|
||||
return &containers[i]
|
||||
}
|
||||
case ResourceTypeSecret:
|
||||
case matcher.ResourceTypeSecret:
|
||||
if envFrom.SecretRef != nil && envFrom.SecretRef.Name == resourceName {
|
||||
return &containers[i]
|
||||
}
|
||||
|
||||
@@ -10,9 +10,10 @@ import (
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
csiv1 "sigs.k8s.io/secrets-store-csi-driver/apis/v1"
|
||||
|
||||
"github.com/stakater/Reloader/internal/pkg/config"
|
||||
"github.com/stakater/Reloader/internal/pkg/testutil"
|
||||
"github.com/stakater/Reloader/internal/pkg/workload"
|
||||
"github.com/stakater/Reloader/pkg/config"
|
||||
"github.com/stakater/Reloader/pkg/matcher"
|
||||
)
|
||||
|
||||
func TestService_ProcessConfigMap_AutoReload(t *testing.T) {
|
||||
@@ -319,7 +320,7 @@ func TestService_ApplyReload_EnvVarStrategy(t *testing.T) {
|
||||
accessor := workload.NewDeploymentWorkload(deploy)
|
||||
|
||||
ctx := context.Background()
|
||||
updated, err := svc.ApplyReload(ctx, accessor, "test-cm", ResourceTypeConfigMap, "default", "abc123hash", false)
|
||||
updated, err := svc.ApplyReload(ctx, accessor, "test-cm", matcher.ResourceTypeConfigMap, "default", "abc123hash", false)
|
||||
|
||||
if err != nil {
|
||||
t.Fatalf("ApplyReload failed: %v", err)
|
||||
@@ -363,7 +364,7 @@ func TestService_ApplyReload_AnnotationStrategy(t *testing.T) {
|
||||
accessor := workload.NewDeploymentWorkload(deploy)
|
||||
|
||||
ctx := context.Background()
|
||||
updated, err := svc.ApplyReload(ctx, accessor, "test-cm", ResourceTypeConfigMap, "default", "abc123hash", false)
|
||||
updated, err := svc.ApplyReload(ctx, accessor, "test-cm", matcher.ResourceTypeConfigMap, "default", "abc123hash", false)
|
||||
|
||||
if err != nil {
|
||||
t.Fatalf("ApplyReload failed: %v", err)
|
||||
@@ -395,7 +396,7 @@ func TestService_ApplyReload_EnvVarDeletion(t *testing.T) {
|
||||
|
||||
ctx := context.Background()
|
||||
// Empty hash signals deletion
|
||||
updated, err := svc.ApplyReload(ctx, accessor, "test-cm", ResourceTypeConfigMap, "default", "", false)
|
||||
updated, err := svc.ApplyReload(ctx, accessor, "test-cm", matcher.ResourceTypeConfigMap, "default", "", false)
|
||||
|
||||
if err != nil {
|
||||
t.Fatalf("ApplyReload failed: %v", err)
|
||||
@@ -439,7 +440,7 @@ func TestService_ApplyReload_NoChangeIfSameHash(t *testing.T) {
|
||||
accessor := workload.NewDeploymentWorkload(deploy)
|
||||
|
||||
ctx := context.Background()
|
||||
updated, err := svc.ApplyReload(ctx, accessor, "test-cm", ResourceTypeConfigMap, "default", "abc123hash", false)
|
||||
updated, err := svc.ApplyReload(ctx, accessor, "test-cm", matcher.ResourceTypeConfigMap, "default", "abc123hash", false)
|
||||
|
||||
if err != nil {
|
||||
t.Fatalf("ApplyReload failed: %v", err)
|
||||
@@ -673,7 +674,7 @@ func TestService_findVolumeUsingResource_ConfigMap(t *testing.T) {
|
||||
name string
|
||||
volumes []corev1.Volume
|
||||
resourceName string
|
||||
resourceType ResourceType
|
||||
resourceType matcher.ResourceType
|
||||
wantVolume string
|
||||
}{
|
||||
{
|
||||
@@ -689,7 +690,7 @@ func TestService_findVolumeUsingResource_ConfigMap(t *testing.T) {
|
||||
},
|
||||
},
|
||||
resourceName: "my-cm",
|
||||
resourceType: ResourceTypeConfigMap,
|
||||
resourceType: matcher.ResourceTypeConfigMap,
|
||||
wantVolume: "config-vol",
|
||||
},
|
||||
{
|
||||
@@ -711,7 +712,7 @@ func TestService_findVolumeUsingResource_ConfigMap(t *testing.T) {
|
||||
},
|
||||
},
|
||||
resourceName: "projected-cm",
|
||||
resourceType: ResourceTypeConfigMap,
|
||||
resourceType: matcher.ResourceTypeConfigMap,
|
||||
wantVolume: "projected-vol",
|
||||
},
|
||||
{
|
||||
@@ -727,14 +728,14 @@ func TestService_findVolumeUsingResource_ConfigMap(t *testing.T) {
|
||||
},
|
||||
},
|
||||
resourceName: "my-cm",
|
||||
resourceType: ResourceTypeConfigMap,
|
||||
resourceType: matcher.ResourceTypeConfigMap,
|
||||
wantVolume: "",
|
||||
},
|
||||
{
|
||||
name: "empty volumes",
|
||||
volumes: []corev1.Volume{},
|
||||
resourceName: "my-cm",
|
||||
resourceType: ResourceTypeConfigMap,
|
||||
resourceType: matcher.ResourceTypeConfigMap,
|
||||
wantVolume: "",
|
||||
},
|
||||
}
|
||||
@@ -817,7 +818,7 @@ func TestService_findVolumeUsingResource_Secret(t *testing.T) {
|
||||
for _, tt := range tests {
|
||||
t.Run(
|
||||
tt.name, func(t *testing.T) {
|
||||
got := svc.findVolumeUsingResource(tt.volumes, tt.resourceName, ResourceTypeSecret)
|
||||
got := svc.findVolumeUsingResource(tt.volumes, tt.resourceName, matcher.ResourceTypeSecret)
|
||||
if got != tt.wantVolume {
|
||||
t.Errorf("findVolumeUsingResource() = %q, want %q", got, tt.wantVolume)
|
||||
}
|
||||
@@ -995,7 +996,7 @@ func TestService_findContainerWithEnvRef_ConfigMap(t *testing.T) {
|
||||
for _, tt := range tests {
|
||||
t.Run(
|
||||
tt.name, func(t *testing.T) {
|
||||
got := svc.findContainerWithEnvRef(tt.containers, tt.resourceName, ResourceTypeConfigMap)
|
||||
got := svc.findContainerWithEnvRef(tt.containers, tt.resourceName, matcher.ResourceTypeConfigMap)
|
||||
if tt.shouldMatch {
|
||||
if got == nil {
|
||||
t.Error("Expected to find a container, got nil")
|
||||
@@ -1084,7 +1085,7 @@ func TestService_findContainerWithEnvRef_Secret(t *testing.T) {
|
||||
for _, tt := range tests {
|
||||
t.Run(
|
||||
tt.name, func(t *testing.T) {
|
||||
got := svc.findContainerWithEnvRef(tt.containers, tt.resourceName, ResourceTypeSecret)
|
||||
got := svc.findContainerWithEnvRef(tt.containers, tt.resourceName, matcher.ResourceTypeSecret)
|
||||
if tt.shouldMatch {
|
||||
if got == nil {
|
||||
t.Error("Expected to find a container, got nil")
|
||||
@@ -1128,7 +1129,7 @@ func TestService_findTargetContainer_AutoReload(t *testing.T) {
|
||||
}
|
||||
accessor := workload.NewDeploymentWorkload(deploy)
|
||||
|
||||
container := svc.findTargetContainer(accessor, "my-cm", ResourceTypeConfigMap, true)
|
||||
container := svc.findTargetContainer(accessor, "my-cm", matcher.ResourceTypeConfigMap, true)
|
||||
if container == nil {
|
||||
t.Fatal("Expected to find a container")
|
||||
}
|
||||
@@ -1166,7 +1167,7 @@ func TestService_findTargetContainer_AutoReload_EnvRef(t *testing.T) {
|
||||
}
|
||||
accessor := workload.NewDeploymentWorkload(deploy)
|
||||
|
||||
container := svc.findTargetContainer(accessor, "my-cm", ResourceTypeConfigMap, true)
|
||||
container := svc.findTargetContainer(accessor, "my-cm", matcher.ResourceTypeConfigMap, true)
|
||||
if container == nil {
|
||||
t.Fatal("Expected to find a container")
|
||||
}
|
||||
@@ -1208,7 +1209,7 @@ func TestService_findTargetContainer_AutoReload_InitContainer(t *testing.T) {
|
||||
}
|
||||
accessor := workload.NewDeploymentWorkload(deploy)
|
||||
|
||||
container := svc.findTargetContainer(accessor, "my-cm", ResourceTypeConfigMap, true)
|
||||
container := svc.findTargetContainer(accessor, "my-cm", matcher.ResourceTypeConfigMap, true)
|
||||
if container == nil {
|
||||
t.Fatal("Expected to find a container")
|
||||
}
|
||||
@@ -1249,7 +1250,7 @@ func TestService_findTargetContainer_AutoReload_InitContainerEnvRef(t *testing.T
|
||||
}
|
||||
accessor := workload.NewDeploymentWorkload(deploy)
|
||||
|
||||
container := svc.findTargetContainer(accessor, "my-cm", ResourceTypeConfigMap, true)
|
||||
container := svc.findTargetContainer(accessor, "my-cm", matcher.ResourceTypeConfigMap, true)
|
||||
if container == nil {
|
||||
t.Fatal("Expected to find a container")
|
||||
}
|
||||
@@ -1267,7 +1268,7 @@ func TestService_findTargetContainer_NoContainers(t *testing.T) {
|
||||
deploy.Spec.Template.Spec.Containers = []corev1.Container{}
|
||||
accessor := workload.NewDeploymentWorkload(deploy)
|
||||
|
||||
container := svc.findTargetContainer(accessor, "my-cm", ResourceTypeConfigMap, false)
|
||||
container := svc.findTargetContainer(accessor, "my-cm", matcher.ResourceTypeConfigMap, false)
|
||||
if container != nil {
|
||||
t.Error("Expected nil container for empty container list")
|
||||
}
|
||||
@@ -1285,7 +1286,7 @@ func TestService_findTargetContainer_NonAutoReload(t *testing.T) {
|
||||
accessor := workload.NewDeploymentWorkload(deploy)
|
||||
|
||||
// Without autoReload, should return first container
|
||||
container := svc.findTargetContainer(accessor, "my-cm", ResourceTypeConfigMap, false)
|
||||
container := svc.findTargetContainer(accessor, "my-cm", matcher.ResourceTypeConfigMap, false)
|
||||
if container == nil {
|
||||
t.Fatal("Expected to find a container")
|
||||
}
|
||||
@@ -1306,7 +1307,7 @@ func TestService_findTargetContainer_AutoReload_FallbackToFirst(t *testing.T) {
|
||||
}
|
||||
accessor := workload.NewDeploymentWorkload(deploy)
|
||||
|
||||
container := svc.findTargetContainer(accessor, "non-existent", ResourceTypeConfigMap, true)
|
||||
container := svc.findTargetContainer(accessor, "non-existent", matcher.ResourceTypeConfigMap, true)
|
||||
if container == nil {
|
||||
t.Fatal("Expected to find a container")
|
||||
}
|
||||
@@ -1420,7 +1421,7 @@ func TestService_ApplyReload_SPC_TargetsMountingContainer(t *testing.T) {
|
||||
accessor := workload.NewDeploymentWorkload(dep)
|
||||
|
||||
// autoReload=true exercises volume-based container targeting.
|
||||
updated, err := svc.ApplyReload(context.Background(), accessor, "my-spc", ResourceTypeSecretProviderClass, "default", "spchash", true)
|
||||
updated, err := svc.ApplyReload(context.Background(), accessor, "my-spc", matcher.ResourceTypeSecretProviderClass, "default", "spchash", true)
|
||||
if err != nil {
|
||||
t.Fatalf("ApplyReload failed: %v", err)
|
||||
}
|
||||
|
||||
@@ -9,7 +9,8 @@ import (
|
||||
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
|
||||
"github.com/stakater/Reloader/internal/pkg/config"
|
||||
"github.com/stakater/Reloader/pkg/config"
|
||||
"github.com/stakater/Reloader/pkg/matcher"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -32,7 +33,7 @@ type Strategy interface {
|
||||
// StrategyInput contains the information needed to apply a reload strategy.
|
||||
type StrategyInput struct {
|
||||
ResourceName string
|
||||
ResourceType ResourceType
|
||||
ResourceType matcher.ResourceType
|
||||
Namespace string
|
||||
Hash string
|
||||
Container *corev1.Container
|
||||
@@ -103,14 +104,14 @@ func (s *EnvVarStrategy) removeEnvVar(container *corev1.Container, name string)
|
||||
return false
|
||||
}
|
||||
|
||||
func (s *EnvVarStrategy) envVarName(resourceName string, resourceType ResourceType) string {
|
||||
func (s *EnvVarStrategy) envVarName(resourceName string, resourceType matcher.ResourceType) string {
|
||||
var postfix string
|
||||
switch resourceType {
|
||||
case ResourceTypeConfigMap:
|
||||
case matcher.ResourceTypeConfigMap:
|
||||
postfix = ConfigmapEnvVarPostfix
|
||||
case ResourceTypeSecret:
|
||||
case matcher.ResourceTypeSecret:
|
||||
postfix = SecretEnvVarPostfix
|
||||
case ResourceTypeSecretProviderClass:
|
||||
case matcher.ResourceTypeSecretProviderClass:
|
||||
postfix = SecretProviderClassEnvVarPostfix
|
||||
}
|
||||
return EnvVarPrefix + convertToEnvVarName(resourceName) + "_" + postfix
|
||||
|
||||
@@ -6,7 +6,8 @@ import (
|
||||
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
|
||||
"github.com/stakater/Reloader/internal/pkg/config"
|
||||
"github.com/stakater/Reloader/pkg/config"
|
||||
"github.com/stakater/Reloader/pkg/matcher"
|
||||
)
|
||||
|
||||
func TestEnvVarStrategy_Apply(t *testing.T) {
|
||||
@@ -20,7 +21,7 @@ func TestEnvVarStrategy_Apply(t *testing.T) {
|
||||
|
||||
input := StrategyInput{
|
||||
ResourceName: "my-config",
|
||||
ResourceType: ResourceTypeConfigMap,
|
||||
ResourceType: matcher.ResourceTypeConfigMap,
|
||||
Namespace: "default",
|
||||
Hash: "abc123",
|
||||
Container: container,
|
||||
@@ -57,7 +58,7 @@ func TestEnvVarStrategy_Apply(t *testing.T) {
|
||||
|
||||
input := StrategyInput{
|
||||
ResourceName: "my-config",
|
||||
ResourceType: ResourceTypeConfigMap,
|
||||
ResourceType: matcher.ResourceTypeConfigMap,
|
||||
Namespace: "default",
|
||||
Hash: "new-hash",
|
||||
Container: container,
|
||||
@@ -87,7 +88,7 @@ func TestEnvVarStrategy_Apply(t *testing.T) {
|
||||
|
||||
input := StrategyInput{
|
||||
ResourceName: "my-config",
|
||||
ResourceType: ResourceTypeConfigMap,
|
||||
ResourceType: matcher.ResourceTypeConfigMap,
|
||||
Namespace: "default",
|
||||
Hash: "same-hash",
|
||||
Container: container,
|
||||
@@ -105,7 +106,7 @@ func TestEnvVarStrategy_Apply(t *testing.T) {
|
||||
t.Run("error when container is nil", func(t *testing.T) {
|
||||
input := StrategyInput{
|
||||
ResourceName: "my-config",
|
||||
ResourceType: ResourceTypeConfigMap,
|
||||
ResourceType: matcher.ResourceTypeConfigMap,
|
||||
Namespace: "default",
|
||||
Hash: "abc123",
|
||||
Container: nil,
|
||||
@@ -125,7 +126,7 @@ func TestEnvVarStrategy_Apply(t *testing.T) {
|
||||
|
||||
input := StrategyInput{
|
||||
ResourceName: "my-secret",
|
||||
ResourceType: ResourceTypeSecret,
|
||||
ResourceType: matcher.ResourceTypeSecret,
|
||||
Namespace: "default",
|
||||
Hash: "abc123",
|
||||
Container: container,
|
||||
@@ -158,15 +159,15 @@ func TestEnvVarStrategy_EnvVarName(t *testing.T) {
|
||||
|
||||
tests := []struct {
|
||||
resourceName string
|
||||
resourceType ResourceType
|
||||
resourceType matcher.ResourceType
|
||||
expected string
|
||||
}{
|
||||
{"my-config", ResourceTypeConfigMap, "STAKATER_MY_CONFIG_CONFIGMAP"},
|
||||
{"my-secret", ResourceTypeSecret, "STAKATER_MY_SECRET_SECRET"},
|
||||
{"app-config-v2", ResourceTypeConfigMap, "STAKATER_APP_CONFIG_V2_CONFIGMAP"},
|
||||
{"my.dotted.config", ResourceTypeConfigMap, "STAKATER_MY_DOTTED_CONFIG_CONFIGMAP"},
|
||||
{"MyMixedCase", ResourceTypeConfigMap, "STAKATER_MYMIXEDCASE_CONFIGMAP"},
|
||||
{"config-with-123-numbers", ResourceTypeConfigMap, "STAKATER_CONFIG_WITH_123_NUMBERS_CONFIGMAP"},
|
||||
{"my-config", matcher.ResourceTypeConfigMap, "STAKATER_MY_CONFIG_CONFIGMAP"},
|
||||
{"my-secret", matcher.ResourceTypeSecret, "STAKATER_MY_SECRET_SECRET"},
|
||||
{"app-config-v2", matcher.ResourceTypeConfigMap, "STAKATER_APP_CONFIG_V2_CONFIGMAP"},
|
||||
{"my.dotted.config", matcher.ResourceTypeConfigMap, "STAKATER_MY_DOTTED_CONFIG_CONFIGMAP"},
|
||||
{"MyMixedCase", matcher.ResourceTypeConfigMap, "STAKATER_MYMIXEDCASE_CONFIGMAP"},
|
||||
{"config-with-123-numbers", matcher.ResourceTypeConfigMap, "STAKATER_CONFIG_WITH_123_NUMBERS_CONFIGMAP"},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
@@ -218,7 +219,7 @@ func TestAnnotationStrategy_Apply(t *testing.T) {
|
||||
|
||||
input := StrategyInput{
|
||||
ResourceName: "my-config",
|
||||
ResourceType: ResourceTypeConfigMap,
|
||||
ResourceType: matcher.ResourceTypeConfigMap,
|
||||
Namespace: "default",
|
||||
Hash: "abc123",
|
||||
Container: container,
|
||||
@@ -244,8 +245,8 @@ func TestAnnotationStrategy_Apply(t *testing.T) {
|
||||
if err := json.Unmarshal([]byte(annotationValue), &source); err != nil {
|
||||
t.Fatalf("failed to unmarshal annotation: %v", err)
|
||||
}
|
||||
if source.Kind != string(ResourceTypeConfigMap) {
|
||||
t.Errorf("expected kind=%s, got %s", ResourceTypeConfigMap, source.Kind)
|
||||
if source.Kind != string(matcher.ResourceTypeConfigMap) {
|
||||
t.Errorf("expected kind=%s, got %s", matcher.ResourceTypeConfigMap, source.Kind)
|
||||
}
|
||||
if source.Name != "my-config" {
|
||||
t.Errorf("expected name=my-config, got %s", source.Name)
|
||||
@@ -259,7 +260,7 @@ func TestAnnotationStrategy_Apply(t *testing.T) {
|
||||
annotations := make(map[string]string)
|
||||
input := StrategyInput{
|
||||
ResourceName: "my-config",
|
||||
ResourceType: ResourceTypeConfigMap,
|
||||
ResourceType: matcher.ResourceTypeConfigMap,
|
||||
Namespace: "default",
|
||||
Hash: "abc123",
|
||||
Container: &corev1.Container{Name: "c"},
|
||||
@@ -302,7 +303,7 @@ func TestAnnotationStrategy_Apply(t *testing.T) {
|
||||
t.Run("error when annotations map is nil", func(t *testing.T) {
|
||||
input := StrategyInput{
|
||||
ResourceName: "my-config",
|
||||
ResourceType: ResourceTypeConfigMap,
|
||||
ResourceType: matcher.ResourceTypeConfigMap,
|
||||
Namespace: "default",
|
||||
Hash: "abc123",
|
||||
PodAnnotations: nil,
|
||||
@@ -338,7 +339,7 @@ func TestNewStrategy(t *testing.T) {
|
||||
|
||||
func TestEnvVarNameSecretProviderClass(t *testing.T) {
|
||||
s := NewEnvVarStrategy()
|
||||
got := s.envVarName("my-vault-spc", ResourceTypeSecretProviderClass)
|
||||
got := s.envVarName("my-vault-spc", matcher.ResourceTypeSecretProviderClass)
|
||||
want := "STAKATER_MY_VAULT_SPC_SECRETPROVIDERCLASS"
|
||||
if got != want {
|
||||
t.Fatalf("envVarName = %q, want %q", got, want)
|
||||
|
||||
@@ -1,10 +1,14 @@
|
||||
package reload
|
||||
// Package matcher provides the annotation-based reload decision API. Given a
|
||||
// changed resource and a workload's annotations, Matcher reports whether the
|
||||
// workload should be reloaded. It is workload-type agnostic and safe to import
|
||||
// from outside this module.
|
||||
package matcher
|
||||
|
||||
import (
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
"github.com/stakater/Reloader/internal/pkg/config"
|
||||
"github.com/stakater/Reloader/pkg/config"
|
||||
)
|
||||
|
||||
// MatchResult contains the result of checking if a workload should be reloaded.
|
||||
@@ -1,9 +1,9 @@
|
||||
package reload
|
||||
package matcher
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stakater/Reloader/internal/pkg/config"
|
||||
"github.com/stakater/Reloader/pkg/config"
|
||||
)
|
||||
|
||||
func TestMatcher_ShouldReload(t *testing.T) {
|
||||
@@ -1,4 +1,4 @@
|
||||
package reload
|
||||
package matcher
|
||||
|
||||
// ResourceType represents the type of Kubernetes resource.
|
||||
type ResourceType string
|
||||
@@ -1,4 +1,4 @@
|
||||
package reload
|
||||
package matcher
|
||||
|
||||
import (
|
||||
"testing"
|
||||
@@ -11,7 +11,7 @@ import (
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
|
||||
"github.com/stakater/Reloader/internal/pkg/config"
|
||||
"github.com/stakater/Reloader/pkg/config"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -20,7 +20,7 @@ const (
|
||||
// ConfigMapLabelKey is the label key for the metadata ConfigMap.
|
||||
ConfigMapLabelKey = "reloader.stakater.com/meta-info"
|
||||
// ConfigMapLabelValue is the label value for the metadata ConfigMap.
|
||||
ConfigMapLabelValue = "reloader-oss"
|
||||
ConfigMapLabelValue = "reloader"
|
||||
|
||||
// Environment variables for deployment info.
|
||||
EnvReloaderNamespace = "RELOADER_NAMESPACE"
|
||||
@@ -11,7 +11,7 @@ import (
|
||||
"sigs.k8s.io/controller-runtime/pkg/client"
|
||||
"sigs.k8s.io/controller-runtime/pkg/client/fake"
|
||||
|
||||
"github.com/stakater/Reloader/internal/pkg/config"
|
||||
"github.com/stakater/Reloader/pkg/config"
|
||||
)
|
||||
|
||||
// testLogger returns a no-op logger for testing.
|
||||
@@ -12,8 +12,8 @@ import (
|
||||
"k8s.io/client-go/rest"
|
||||
"sigs.k8s.io/controller-runtime/pkg/client"
|
||||
|
||||
"github.com/stakater/Reloader/internal/pkg/config"
|
||||
"github.com/stakater/Reloader/internal/pkg/workload"
|
||||
"github.com/stakater/Reloader/pkg/config"
|
||||
)
|
||||
|
||||
// Publisher handles creating and updating the metadata ConfigMap.
|
||||
@@ -106,8 +106,8 @@ func UndeployReloader(namespace, releaseName string) error {
|
||||
kind string
|
||||
name string
|
||||
}{
|
||||
{"clusterrole", releaseName + "-reloader-role"},
|
||||
{"clusterrolebinding", releaseName + "-reloader-role-binding"},
|
||||
{"clusterrole", ReloaderDeploymentName(releaseName) + "-role"},
|
||||
{"clusterrolebinding", ReloaderDeploymentName(releaseName) + "-role-binding"},
|
||||
}
|
||||
|
||||
for _, res := range clusterResources {
|
||||
@@ -144,8 +144,8 @@ func cleanupClusterResources(releaseName string) {
|
||||
kind string
|
||||
name string
|
||||
}{
|
||||
{"clusterrole", releaseName + "-reloader-role"},
|
||||
{"clusterrolebinding", releaseName + "-reloader-role-binding"},
|
||||
{"clusterrole", ReloaderDeploymentName(releaseName) + "-role"},
|
||||
{"clusterrolebinding", ReloaderDeploymentName(releaseName) + "-role-binding"},
|
||||
}
|
||||
|
||||
for _, res := range clusterResources {
|
||||
@@ -207,7 +207,10 @@ func ReloaderDeploymentName(releaseName string) string {
|
||||
if releaseName == "" {
|
||||
releaseName = DefaultHelmReleaseName
|
||||
}
|
||||
return releaseName + "-reloader"
|
||||
// The chart is named "reloader-v2", so the fullname template renders
|
||||
// <release>-reloader-v2. Keep this the single source of truth; the
|
||||
// cluster-role and pod-selector helpers derive their names from it.
|
||||
return releaseName + "-reloader-v2"
|
||||
}
|
||||
|
||||
// ReloaderPodSelector returns the label selector for Reloader pods.
|
||||
@@ -215,5 +218,5 @@ func ReloaderPodSelector(releaseName string) string {
|
||||
if releaseName == "" {
|
||||
releaseName = DefaultHelmReleaseName
|
||||
}
|
||||
return "app=" + releaseName + "-reloader"
|
||||
return "app=" + ReloaderDeploymentName(releaseName)
|
||||
}
|
||||
|
||||
@@ -124,12 +124,12 @@ func TestReloaderDeploymentName(t *testing.T) {
|
||||
{
|
||||
name: "default release name",
|
||||
releaseName: "",
|
||||
expected: "reloader-reloader",
|
||||
expected: "reloader-reloader-v2",
|
||||
},
|
||||
{
|
||||
name: "custom release name",
|
||||
releaseName: "my-reloader",
|
||||
expected: "my-reloader-reloader",
|
||||
expected: "my-reloader-reloader-v2",
|
||||
},
|
||||
}
|
||||
|
||||
@@ -152,12 +152,12 @@ func TestReloaderPodSelector(t *testing.T) {
|
||||
{
|
||||
name: "default release name",
|
||||
releaseName: "",
|
||||
expected: "app=reloader-reloader",
|
||||
expected: "app=reloader-reloader-v2",
|
||||
},
|
||||
{
|
||||
name: "custom release name",
|
||||
releaseName: "my-reloader",
|
||||
expected: "app=my-reloader-reloader",
|
||||
expected: "app=my-reloader-reloader-v2",
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user