Fix conflicts

Signed-off-by: faizanahmad055 <faizan.ahmad55@outlook.com>
This commit is contained in:
faizanahmad055
2026-05-11 10:55:54 +02:00
89 changed files with 16907 additions and 8021 deletions

View File

@@ -4,6 +4,6 @@ import "github.com/stakater/Reloader/internal/pkg/cmd"
// Run runs the command
func Run() error {
cmd := cmd.NewReloaderCommand()
return cmd.Execute()
rootCmd := cmd.NewReloaderCommand()
return rootCmd.Execute()
}

View File

@@ -7,8 +7,6 @@ import (
"time"
"github.com/sirupsen/logrus"
"github.com/stakater/Reloader/internal/pkg/options"
"github.com/stakater/Reloader/pkg/kube"
appsv1 "k8s.io/api/apps/v1"
batchv1 "k8s.io/api/batch/v1"
v1 "k8s.io/api/core/v1"
@@ -16,6 +14,9 @@ import (
"k8s.io/apimachinery/pkg/runtime"
patchtypes "k8s.io/apimachinery/pkg/types"
"github.com/stakater/Reloader/internal/pkg/options"
"github.com/stakater/Reloader/pkg/kube"
"maps"
argorolloutv1alpha1 "github.com/argoproj/argo-rollouts/pkg/apis/rollouts/v1alpha1"
@@ -265,158 +266,254 @@ func GetRolloutItems(clients kube.Clients, namespace string) []runtime.Object {
// GetDeploymentAnnotations returns the annotations of given deployment
func GetDeploymentAnnotations(item runtime.Object) map[string]string {
if item.(*appsv1.Deployment).Annotations == nil {
item.(*appsv1.Deployment).Annotations = make(map[string]string)
deployment, ok := item.(*appsv1.Deployment)
if !ok {
return nil
}
return item.(*appsv1.Deployment).Annotations
if deployment.Annotations == nil {
deployment.Annotations = make(map[string]string)
}
return deployment.Annotations
}
// GetCronJobAnnotations returns the annotations of given cronjob
func GetCronJobAnnotations(item runtime.Object) map[string]string {
if item.(*batchv1.CronJob).Annotations == nil {
item.(*batchv1.CronJob).Annotations = make(map[string]string)
cronJob, ok := item.(*batchv1.CronJob)
if !ok {
return nil
}
return item.(*batchv1.CronJob).Annotations
if cronJob.Annotations == nil {
cronJob.Annotations = make(map[string]string)
}
return cronJob.Annotations
}
// GetJobAnnotations returns the annotations of given job
func GetJobAnnotations(item runtime.Object) map[string]string {
if item.(*batchv1.Job).Annotations == nil {
item.(*batchv1.Job).Annotations = make(map[string]string)
job, ok := item.(*batchv1.Job)
if !ok {
return nil
}
return item.(*batchv1.Job).Annotations
if job.Annotations == nil {
job.Annotations = make(map[string]string)
}
return job.Annotations
}
// GetDaemonSetAnnotations returns the annotations of given daemonSet
func GetDaemonSetAnnotations(item runtime.Object) map[string]string {
if item.(*appsv1.DaemonSet).Annotations == nil {
item.(*appsv1.DaemonSet).Annotations = make(map[string]string)
daemonSet, ok := item.(*appsv1.DaemonSet)
if !ok {
return nil
}
return item.(*appsv1.DaemonSet).Annotations
if daemonSet.Annotations == nil {
daemonSet.Annotations = make(map[string]string)
}
return daemonSet.Annotations
}
// GetStatefulSetAnnotations returns the annotations of given statefulSet
func GetStatefulSetAnnotations(item runtime.Object) map[string]string {
if item.(*appsv1.StatefulSet).Annotations == nil {
item.(*appsv1.StatefulSet).Annotations = make(map[string]string)
statefulSet, ok := item.(*appsv1.StatefulSet)
if !ok {
return nil
}
return item.(*appsv1.StatefulSet).Annotations
if statefulSet.Annotations == nil {
statefulSet.Annotations = make(map[string]string)
}
return statefulSet.Annotations
}
// GetRolloutAnnotations returns the annotations of given rollout
func GetRolloutAnnotations(item runtime.Object) map[string]string {
if item.(*argorolloutv1alpha1.Rollout).Annotations == nil {
item.(*argorolloutv1alpha1.Rollout).Annotations = make(map[string]string)
rollout, ok := item.(*argorolloutv1alpha1.Rollout)
if !ok {
return nil
}
return item.(*argorolloutv1alpha1.Rollout).Annotations
if rollout.Annotations == nil {
rollout.Annotations = make(map[string]string)
}
return rollout.Annotations
}
// GetDeploymentPodAnnotations returns the pod's annotations of given deployment
func GetDeploymentPodAnnotations(item runtime.Object) map[string]string {
if item.(*appsv1.Deployment).Spec.Template.Annotations == nil {
item.(*appsv1.Deployment).Spec.Template.Annotations = make(map[string]string)
deployment, ok := item.(*appsv1.Deployment)
if !ok {
return nil
}
return item.(*appsv1.Deployment).Spec.Template.Annotations
if deployment.Spec.Template.Annotations == nil {
deployment.Spec.Template.Annotations = make(map[string]string)
}
return deployment.Spec.Template.Annotations
}
// GetCronJobPodAnnotations returns the pod's annotations of given cronjob
func GetCronJobPodAnnotations(item runtime.Object) map[string]string {
if item.(*batchv1.CronJob).Spec.JobTemplate.Spec.Template.Annotations == nil {
item.(*batchv1.CronJob).Spec.JobTemplate.Spec.Template.Annotations = make(map[string]string)
cronJob, ok := item.(*batchv1.CronJob)
if !ok {
return nil
}
return item.(*batchv1.CronJob).Spec.JobTemplate.Spec.Template.Annotations
if cronJob.Spec.JobTemplate.Spec.Template.Annotations == nil {
cronJob.Spec.JobTemplate.Spec.Template.Annotations = make(map[string]string)
}
return cronJob.Spec.JobTemplate.Spec.Template.Annotations
}
// GetJobPodAnnotations returns the pod's annotations of given job
func GetJobPodAnnotations(item runtime.Object) map[string]string {
if item.(*batchv1.Job).Spec.Template.Annotations == nil {
item.(*batchv1.Job).Spec.Template.Annotations = make(map[string]string)
job, ok := item.(*batchv1.Job)
if !ok {
return nil
}
return item.(*batchv1.Job).Spec.Template.Annotations
if job.Spec.Template.Annotations == nil {
job.Spec.Template.Annotations = make(map[string]string)
}
return job.Spec.Template.Annotations
}
// GetDaemonSetPodAnnotations returns the pod's annotations of given daemonSet
func GetDaemonSetPodAnnotations(item runtime.Object) map[string]string {
if item.(*appsv1.DaemonSet).Spec.Template.Annotations == nil {
item.(*appsv1.DaemonSet).Spec.Template.Annotations = make(map[string]string)
daemonSet, ok := item.(*appsv1.DaemonSet)
if !ok {
return nil
}
return item.(*appsv1.DaemonSet).Spec.Template.Annotations
if daemonSet.Spec.Template.Annotations == nil {
daemonSet.Spec.Template.Annotations = make(map[string]string)
}
return daemonSet.Spec.Template.Annotations
}
// GetStatefulSetPodAnnotations returns the pod's annotations of given statefulSet
func GetStatefulSetPodAnnotations(item runtime.Object) map[string]string {
if item.(*appsv1.StatefulSet).Spec.Template.Annotations == nil {
item.(*appsv1.StatefulSet).Spec.Template.Annotations = make(map[string]string)
statefulSet, ok := item.(*appsv1.StatefulSet)
if !ok {
return nil
}
return item.(*appsv1.StatefulSet).Spec.Template.Annotations
if statefulSet.Spec.Template.Annotations == nil {
statefulSet.Spec.Template.Annotations = make(map[string]string)
}
return statefulSet.Spec.Template.Annotations
}
// GetRolloutPodAnnotations returns the pod's annotations of given rollout
func GetRolloutPodAnnotations(item runtime.Object) map[string]string {
if item.(*argorolloutv1alpha1.Rollout).Spec.Template.Annotations == nil {
item.(*argorolloutv1alpha1.Rollout).Spec.Template.Annotations = make(map[string]string)
rollout, ok := item.(*argorolloutv1alpha1.Rollout)
if !ok {
return nil
}
return item.(*argorolloutv1alpha1.Rollout).Spec.Template.Annotations
if rollout.Spec.Template.Annotations == nil {
rollout.Spec.Template.Annotations = make(map[string]string)
}
return rollout.Spec.Template.Annotations
}
// GetDeploymentContainers returns the containers of given deployment
func GetDeploymentContainers(item runtime.Object) []v1.Container {
return item.(*appsv1.Deployment).Spec.Template.Spec.Containers
deployment, ok := item.(*appsv1.Deployment)
if !ok {
return []v1.Container{}
}
return deployment.Spec.Template.Spec.Containers
}
// GetCronJobContainers returns the containers of given cronjob
func GetCronJobContainers(item runtime.Object) []v1.Container {
return item.(*batchv1.CronJob).Spec.JobTemplate.Spec.Template.Spec.Containers
cronJob, ok := item.(*batchv1.CronJob)
if !ok {
return []v1.Container{}
}
return cronJob.Spec.JobTemplate.Spec.Template.Spec.Containers
}
// GetJobContainers returns the containers of given job
func GetJobContainers(item runtime.Object) []v1.Container {
return item.(*batchv1.Job).Spec.Template.Spec.Containers
job, ok := item.(*batchv1.Job)
if !ok {
return []v1.Container{}
}
return job.Spec.Template.Spec.Containers
}
// GetDaemonSetContainers returns the containers of given daemonSet
func GetDaemonSetContainers(item runtime.Object) []v1.Container {
return item.(*appsv1.DaemonSet).Spec.Template.Spec.Containers
daemonSet, ok := item.(*appsv1.DaemonSet)
if !ok {
return []v1.Container{}
}
return daemonSet.Spec.Template.Spec.Containers
}
// GetStatefulSetContainers returns the containers of given statefulSet
func GetStatefulSetContainers(item runtime.Object) []v1.Container {
return item.(*appsv1.StatefulSet).Spec.Template.Spec.Containers
statefulSet, ok := item.(*appsv1.StatefulSet)
if !ok {
return []v1.Container{}
}
return statefulSet.Spec.Template.Spec.Containers
}
// GetRolloutContainers returns the containers of given rollout
func GetRolloutContainers(item runtime.Object) []v1.Container {
return item.(*argorolloutv1alpha1.Rollout).Spec.Template.Spec.Containers
rollout, ok := item.(*argorolloutv1alpha1.Rollout)
if !ok {
return []v1.Container{}
}
return rollout.Spec.Template.Spec.Containers
}
// GetDeploymentInitContainers returns the containers of given deployment
func GetDeploymentInitContainers(item runtime.Object) []v1.Container {
return item.(*appsv1.Deployment).Spec.Template.Spec.InitContainers
deployment, ok := item.(*appsv1.Deployment)
if !ok {
return []v1.Container{}
}
return deployment.Spec.Template.Spec.InitContainers
}
// GetCronJobInitContainers returns the containers of given cronjob
func GetCronJobInitContainers(item runtime.Object) []v1.Container {
return item.(*batchv1.CronJob).Spec.JobTemplate.Spec.Template.Spec.InitContainers
cronJob, ok := item.(*batchv1.CronJob)
if !ok {
return []v1.Container{}
}
return cronJob.Spec.JobTemplate.Spec.Template.Spec.InitContainers
}
// GetJobInitContainers returns the containers of given job
func GetJobInitContainers(item runtime.Object) []v1.Container {
return item.(*batchv1.Job).Spec.Template.Spec.InitContainers
job, ok := item.(*batchv1.Job)
if !ok {
return []v1.Container{}
}
return job.Spec.Template.Spec.InitContainers
}
// GetDaemonSetInitContainers returns the containers of given daemonSet
func GetDaemonSetInitContainers(item runtime.Object) []v1.Container {
return item.(*appsv1.DaemonSet).Spec.Template.Spec.InitContainers
daemonSet, ok := item.(*appsv1.DaemonSet)
if !ok {
return []v1.Container{}
}
return daemonSet.Spec.Template.Spec.InitContainers
}
// GetStatefulSetInitContainers returns the containers of given statefulSet
func GetStatefulSetInitContainers(item runtime.Object) []v1.Container {
return item.(*appsv1.StatefulSet).Spec.Template.Spec.InitContainers
statefulSet, ok := item.(*appsv1.StatefulSet)
if !ok {
return []v1.Container{}
}
return statefulSet.Spec.Template.Spec.InitContainers
}
// GetRolloutInitContainers returns the containers of given rollout
func GetRolloutInitContainers(item runtime.Object) []v1.Container {
return item.(*argorolloutv1alpha1.Rollout).Spec.Template.Spec.InitContainers
rollout, ok := item.(*argorolloutv1alpha1.Rollout)
if !ok {
return []v1.Container{}
}
return rollout.Spec.Template.Spec.InitContainers
}
// GetPatchTemplates returns patch templates
@@ -430,21 +527,30 @@ func GetPatchTemplates() PatchTemplates {
// UpdateDeployment performs rolling upgrade on deployment
func UpdateDeployment(clients kube.Clients, namespace string, resource runtime.Object) error {
deployment := resource.(*appsv1.Deployment)
deployment, ok := resource.(*appsv1.Deployment)
if !ok {
return errors.New("resource is not a Deployment")
}
_, err := clients.KubernetesClient.AppsV1().Deployments(namespace).Update(context.TODO(), deployment, meta_v1.UpdateOptions{FieldManager: "Reloader"})
return err
}
// PatchDeployment performs rolling upgrade on deployment
func PatchDeployment(clients kube.Clients, namespace string, resource runtime.Object, patchType patchtypes.PatchType, bytes []byte) error {
deployment := resource.(*appsv1.Deployment)
deployment, ok := resource.(*appsv1.Deployment)
if !ok {
return errors.New("resource is not a Deployment")
}
_, err := clients.KubernetesClient.AppsV1().Deployments(namespace).Patch(context.TODO(), deployment.Name, patchType, bytes, meta_v1.PatchOptions{FieldManager: "Reloader"})
return err
}
// CreateJobFromCronjob performs rolling upgrade on cronjob
func CreateJobFromCronjob(clients kube.Clients, namespace string, resource runtime.Object) error {
cronJob := resource.(*batchv1.CronJob)
cronJob, ok := resource.(*batchv1.CronJob)
if !ok {
return errors.New("resource is not a CronJob")
}
annotations := make(map[string]string)
annotations["cronjob.kubernetes.io/instantiate"] = "manual"
@@ -470,7 +576,10 @@ func PatchCronJob(clients kube.Clients, namespace string, resource runtime.Objec
// ReCreateJobFromjob performs rolling upgrade on job
func ReCreateJobFromjob(clients kube.Clients, namespace string, resource runtime.Object) error {
oldJob := resource.(*batchv1.Job)
oldJob, ok := resource.(*batchv1.Job)
if !ok {
return errors.New("resource is not a Job")
}
job := oldJob.DeepCopy()
// Delete the old job
@@ -506,33 +615,48 @@ func PatchJob(clients kube.Clients, namespace string, resource runtime.Object, p
// UpdateDaemonSet performs rolling upgrade on daemonSet
func UpdateDaemonSet(clients kube.Clients, namespace string, resource runtime.Object) error {
daemonSet := resource.(*appsv1.DaemonSet)
daemonSet, ok := resource.(*appsv1.DaemonSet)
if !ok {
return errors.New("resource is not a DaemonSet")
}
_, err := clients.KubernetesClient.AppsV1().DaemonSets(namespace).Update(context.TODO(), daemonSet, meta_v1.UpdateOptions{FieldManager: "Reloader"})
return err
}
func PatchDaemonSet(clients kube.Clients, namespace string, resource runtime.Object, patchType patchtypes.PatchType, bytes []byte) error {
daemonSet := resource.(*appsv1.DaemonSet)
daemonSet, ok := resource.(*appsv1.DaemonSet)
if !ok {
return errors.New("resource is not a DaemonSet")
}
_, err := clients.KubernetesClient.AppsV1().DaemonSets(namespace).Patch(context.TODO(), daemonSet.Name, patchType, bytes, meta_v1.PatchOptions{FieldManager: "Reloader"})
return err
}
// UpdateStatefulSet performs rolling upgrade on statefulSet
func UpdateStatefulSet(clients kube.Clients, namespace string, resource runtime.Object) error {
statefulSet := resource.(*appsv1.StatefulSet)
statefulSet, ok := resource.(*appsv1.StatefulSet)
if !ok {
return errors.New("resource is not a StatefulSet")
}
_, err := clients.KubernetesClient.AppsV1().StatefulSets(namespace).Update(context.TODO(), statefulSet, meta_v1.UpdateOptions{FieldManager: "Reloader"})
return err
}
func PatchStatefulSet(clients kube.Clients, namespace string, resource runtime.Object, patchType patchtypes.PatchType, bytes []byte) error {
statefulSet := resource.(*appsv1.StatefulSet)
statefulSet, ok := resource.(*appsv1.StatefulSet)
if !ok {
return errors.New("resource is not a StatefulSet")
}
_, err := clients.KubernetesClient.AppsV1().StatefulSets(namespace).Patch(context.TODO(), statefulSet.Name, patchType, bytes, meta_v1.PatchOptions{FieldManager: "Reloader"})
return err
}
// UpdateRollout performs rolling upgrade on rollout
func UpdateRollout(clients kube.Clients, namespace string, resource runtime.Object) error {
rollout := resource.(*argorolloutv1alpha1.Rollout)
rollout, ok := resource.(*argorolloutv1alpha1.Rollout)
if !ok {
return errors.New("resource is not a Rollout")
}
strategy := rollout.GetAnnotations()[options.RolloutStrategyAnnotation]
var err error
switch options.ToArgoRolloutStrategy(strategy) {
@@ -550,30 +674,54 @@ func PatchRollout(clients kube.Clients, namespace string, resource runtime.Objec
// GetDeploymentVolumes returns the Volumes of given deployment
func GetDeploymentVolumes(item runtime.Object) []v1.Volume {
return item.(*appsv1.Deployment).Spec.Template.Spec.Volumes
deployment, ok := item.(*appsv1.Deployment)
if !ok {
return []v1.Volume{}
}
return deployment.Spec.Template.Spec.Volumes
}
// GetCronJobVolumes returns the Volumes of given cronjob
func GetCronJobVolumes(item runtime.Object) []v1.Volume {
return item.(*batchv1.CronJob).Spec.JobTemplate.Spec.Template.Spec.Volumes
cronJob, ok := item.(*batchv1.CronJob)
if !ok {
return []v1.Volume{}
}
return cronJob.Spec.JobTemplate.Spec.Template.Spec.Volumes
}
// GetJobVolumes returns the Volumes of given job
func GetJobVolumes(item runtime.Object) []v1.Volume {
return item.(*batchv1.Job).Spec.Template.Spec.Volumes
job, ok := item.(*batchv1.Job)
if !ok {
return []v1.Volume{}
}
return job.Spec.Template.Spec.Volumes
}
// GetDaemonSetVolumes returns the Volumes of given daemonSet
func GetDaemonSetVolumes(item runtime.Object) []v1.Volume {
return item.(*appsv1.DaemonSet).Spec.Template.Spec.Volumes
daemonSet, ok := item.(*appsv1.DaemonSet)
if !ok {
return []v1.Volume{}
}
return daemonSet.Spec.Template.Spec.Volumes
}
// GetStatefulSetVolumes returns the Volumes of given statefulSet
func GetStatefulSetVolumes(item runtime.Object) []v1.Volume {
return item.(*appsv1.StatefulSet).Spec.Template.Spec.Volumes
statefulSet, ok := item.(*appsv1.StatefulSet)
if !ok {
return []v1.Volume{}
}
return statefulSet.Spec.Template.Spec.Volumes
}
// GetRolloutVolumes returns the Volumes of given rollout
func GetRolloutVolumes(item runtime.Object) []v1.Volume {
return item.(*argorolloutv1alpha1.Rollout).Spec.Template.Spec.Volumes
rollout, ok := item.(*argorolloutv1alpha1.Rollout)
if !ok {
return []v1.Volume{}
}
return rollout.Spec.Template.Spec.Volumes
}

View File

@@ -6,12 +6,6 @@ import (
"time"
"github.com/sirupsen/logrus"
"github.com/stakater/Reloader/internal/pkg/constants"
"github.com/stakater/Reloader/internal/pkg/handler"
"github.com/stakater/Reloader/internal/pkg/metrics"
"github.com/stakater/Reloader/internal/pkg/options"
"github.com/stakater/Reloader/internal/pkg/util"
"github.com/stakater/Reloader/pkg/kube"
v1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/fields"
@@ -24,12 +18,18 @@ import (
"k8s.io/client-go/util/workqueue"
"k8s.io/kubectl/pkg/scheme"
csiv1 "sigs.k8s.io/secrets-store-csi-driver/apis/v1"
"github.com/stakater/Reloader/internal/pkg/constants"
"github.com/stakater/Reloader/internal/pkg/handler"
"github.com/stakater/Reloader/internal/pkg/metrics"
"github.com/stakater/Reloader/internal/pkg/options"
"github.com/stakater/Reloader/internal/pkg/util"
"github.com/stakater/Reloader/pkg/kube"
)
// Controller for checking events
type Controller struct {
client kubernetes.Interface
indexer cache.Indexer
queue workqueue.TypedRateLimitingInterface[any]
informer cache.Controller
namespace string
@@ -42,14 +42,13 @@ type Controller struct {
}
// controllerInitialized flag determines whether controlled is being initialized
var secretControllerInitialized bool = false
var configmapControllerInitialized bool = false
var secretControllerInitialized = false
var configmapControllerInitialized = false
var selectedNamespacesCache []string
// NewController for initializing a Controller
func NewController(
client kubernetes.Interface, resource string, namespace string, ignoredNamespaces []string, namespaceLabelSelector string, resourceLabelSelector string, collectors metrics.Collectors) (*Controller, error) {
func NewController(client kubernetes.Interface, resource string, namespace string, ignoredNamespaces []string, namespaceLabelSelector string, resourceLabelSelector string, collectors metrics.Collectors) (*Controller,
error) {
if options.SyncAfterRestart {
secretControllerInitialized = true
configmapControllerInitialized = true
@@ -67,17 +66,18 @@ func NewController(
eventBroadcaster.StartRecordingToSink(&typedcorev1.EventSinkImpl{
Interface: client.CoreV1().Events(""),
})
recorder := eventBroadcaster.NewRecorder(scheme.Scheme, v1.EventSource{Component: fmt.Sprintf("reloader-%s", resource)})
recorder := eventBroadcaster.NewRecorder(scheme.Scheme,
v1.EventSource{Component: fmt.Sprintf("reloader-%s", resource)})
queue := workqueue.NewTypedRateLimitingQueue(workqueue.DefaultTypedControllerRateLimiter[any]())
optionsModifier := func(options *metav1.ListOptions) {
optionsModifier := func(opts *metav1.ListOptions) {
if resource == "namespaces" {
options.LabelSelector = c.namespaceSelector
opts.LabelSelector = c.namespaceSelector
} else if len(c.resourceSelector) > 0 {
options.LabelSelector = c.resourceSelector
opts.LabelSelector = c.resourceSelector
} else {
options.FieldSelector = fields.Everything().String()
opts.FieldSelector = fields.Everything().String()
}
}
@@ -299,7 +299,12 @@ func (c *Controller) processNextItem() bool {
startTime := time.Now()
// Invoke the method containing the business logic
err := resourceHandler.(handler.ResourceHandler).Handle()
rh, ok := resourceHandler.(handler.ResourceHandler)
if !ok {
logrus.Errorf("Invalid resource handler type: %T", resourceHandler)
return true
}
err := rh.Handle()
duration := time.Since(startTime)

File diff suppressed because it is too large Load Diff

View File

@@ -4,11 +4,12 @@ import (
"time"
"github.com/sirupsen/logrus"
v1 "k8s.io/api/core/v1"
"k8s.io/client-go/tools/record"
"github.com/stakater/Reloader/internal/pkg/metrics"
"github.com/stakater/Reloader/internal/pkg/options"
"github.com/stakater/Reloader/pkg/common"
v1 "k8s.io/api/core/v1"
"k8s.io/client-go/tools/record"
)
// ResourceCreatedHandler contains new objects
@@ -59,10 +60,10 @@ func (r ResourceCreatedHandler) Handle() error {
func (r ResourceCreatedHandler) GetConfig() (common.Config, string) {
var oldSHAData string
var config common.Config
if _, ok := r.Resource.(*v1.ConfigMap); ok {
config = common.GetConfigmapConfig(r.Resource.(*v1.ConfigMap))
} else if _, ok := r.Resource.(*v1.Secret); ok {
config = common.GetSecretConfig(r.Resource.(*v1.Secret))
if cm, ok := r.Resource.(*v1.ConfigMap); ok {
config = common.GetConfigmapConfig(cm)
} else if secret, ok := r.Resource.(*v1.Secret); ok {
config = common.GetSecretConfig(secret)
} else {
logrus.Warnf("Invalid resource: Resource should be 'Secret' or 'Configmap' but found, %v", r.Resource)
}

View File

@@ -0,0 +1,353 @@
package handler
import (
"testing"
"github.com/stretchr/testify/assert"
v1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"github.com/stakater/Reloader/internal/pkg/constants"
"github.com/stakater/Reloader/internal/pkg/metrics"
)
func TestResourceCreatedHandler_GetConfig(t *testing.T) {
tests := []struct {
name string
resource interface{}
expectedName string
expectedNS string
expectedType string
expectSHANotEmpty bool
expectOldSHAEmpty bool
}{
{
name: "ConfigMap with data",
resource: &v1.ConfigMap{
ObjectMeta: metav1.ObjectMeta{
Name: "my-configmap",
Namespace: "test-ns",
},
Data: map[string]string{
"key1": "value1",
"key2": "value2",
},
},
expectedName: "my-configmap",
expectedNS: "test-ns",
expectedType: constants.ConfigmapEnvVarPostfix,
expectSHANotEmpty: true,
expectOldSHAEmpty: true,
},
{
name: "ConfigMap with empty data",
resource: &v1.ConfigMap{
ObjectMeta: metav1.ObjectMeta{
Name: "empty-configmap",
Namespace: "default",
},
Data: map[string]string{},
},
expectedName: "empty-configmap",
expectedNS: "default",
expectedType: constants.ConfigmapEnvVarPostfix,
expectSHANotEmpty: true,
expectOldSHAEmpty: true,
},
{
name: "ConfigMap with binary data",
resource: &v1.ConfigMap{
ObjectMeta: metav1.ObjectMeta{
Name: "binary-configmap",
Namespace: "default",
},
BinaryData: map[string][]byte{
"binary-key": []byte("binary-value"),
},
},
expectedName: "binary-configmap",
expectedNS: "default",
expectedType: constants.ConfigmapEnvVarPostfix,
expectSHANotEmpty: true,
expectOldSHAEmpty: true,
},
{
name: "ConfigMap with annotations",
resource: &v1.ConfigMap{
ObjectMeta: metav1.ObjectMeta{
Name: "annotated-configmap",
Namespace: "default",
Annotations: map[string]string{
"reloader.stakater.com/match": "true",
},
},
Data: map[string]string{"key": "value"},
},
expectedName: "annotated-configmap",
expectedNS: "default",
expectedType: constants.ConfigmapEnvVarPostfix,
expectSHANotEmpty: true,
expectOldSHAEmpty: true,
},
{
name: "Secret with data",
resource: &v1.Secret{
ObjectMeta: metav1.ObjectMeta{
Name: "my-secret",
Namespace: "secret-ns",
},
Data: map[string][]byte{
"password": []byte("secret-password"),
},
},
expectedName: "my-secret",
expectedNS: "secret-ns",
expectedType: constants.SecretEnvVarPostfix,
expectSHANotEmpty: true,
expectOldSHAEmpty: true,
},
{
name: "Secret with empty data",
resource: &v1.Secret{
ObjectMeta: metav1.ObjectMeta{
Name: "empty-secret",
Namespace: "default",
},
Data: map[string][]byte{},
},
expectedName: "empty-secret",
expectedNS: "default",
expectedType: constants.SecretEnvVarPostfix,
expectSHANotEmpty: true,
expectOldSHAEmpty: true,
},
{
name: "Secret with StringData",
resource: &v1.Secret{
ObjectMeta: metav1.ObjectMeta{
Name: "stringdata-secret",
Namespace: "default",
},
StringData: map[string]string{
"username": "admin",
},
},
expectedName: "stringdata-secret",
expectedNS: "default",
expectedType: constants.SecretEnvVarPostfix,
expectSHANotEmpty: true,
expectOldSHAEmpty: true,
},
{
name: "Secret with labels",
resource: &v1.Secret{
ObjectMeta: metav1.ObjectMeta{
Name: "labeled-secret",
Namespace: "default",
Labels: map[string]string{
"app": "test",
},
},
Data: map[string][]byte{"key": []byte("value")},
},
expectedName: "labeled-secret",
expectedNS: "default",
expectedType: constants.SecretEnvVarPostfix,
expectSHANotEmpty: true,
expectOldSHAEmpty: true,
},
{
name: "Invalid resource type - string",
resource: "invalid-string",
expectedName: "",
expectedNS: "",
expectedType: "",
expectSHANotEmpty: false,
expectOldSHAEmpty: true,
},
{
name: "Invalid resource type - int",
resource: 123,
expectedName: "",
expectedNS: "",
expectedType: "",
expectSHANotEmpty: false,
expectOldSHAEmpty: true,
},
{
name: "Invalid resource type - struct",
resource: struct{ Name string }{Name: "test"},
expectedName: "",
expectedNS: "",
expectedType: "",
expectSHANotEmpty: false,
expectOldSHAEmpty: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
handler := ResourceCreatedHandler{
Resource: tt.resource,
Collectors: metrics.NewCollectors(),
}
config, oldSHA := handler.GetConfig()
assert.Equal(t, tt.expectedName, config.ResourceName)
assert.Equal(t, tt.expectedNS, config.Namespace)
assert.Equal(t, tt.expectedType, config.Type)
if tt.expectSHANotEmpty {
assert.NotEmpty(t, config.SHAValue, "SHA should not be empty")
}
if tt.expectOldSHAEmpty {
assert.Empty(t, oldSHA, "oldSHA should always be empty for create handler")
}
})
}
}
func TestResourceCreatedHandler_GetConfig_Annotations(t *testing.T) {
cm := &v1.ConfigMap{
ObjectMeta: metav1.ObjectMeta{
Name: "annotated-cm",
Namespace: "default",
Annotations: map[string]string{
"reloader.stakater.com/match": "true",
"reloader.stakater.com/search": "true",
},
},
Data: map[string]string{"key": "value"},
}
handler := ResourceCreatedHandler{
Resource: cm,
Collectors: metrics.NewCollectors(),
}
config, _ := handler.GetConfig()
assert.NotNil(t, config.ResourceAnnotations)
assert.Equal(t, "true", config.ResourceAnnotations["reloader.stakater.com/match"])
assert.Equal(t, "true", config.ResourceAnnotations["reloader.stakater.com/search"])
}
func TestResourceCreatedHandler_GetConfig_Labels(t *testing.T) {
secret := &v1.Secret{
ObjectMeta: metav1.ObjectMeta{
Name: "labeled-secret",
Namespace: "default",
Labels: map[string]string{
"app": "myapp",
"version": "v1",
},
},
Data: map[string][]byte{"key": []byte("value")},
}
handler := ResourceCreatedHandler{
Resource: secret,
Collectors: metrics.NewCollectors(),
}
config, _ := handler.GetConfig()
assert.NotNil(t, config.Labels)
assert.Equal(t, "myapp", config.Labels["app"])
assert.Equal(t, "v1", config.Labels["version"])
}
func TestResourceCreatedHandler_Handle(t *testing.T) {
tests := []struct {
name string
resource interface{}
expectError bool
}{
{
name: "Nil resource",
resource: nil,
expectError: false,
},
{
name: "Valid ConfigMap - no workloads to update",
resource: &v1.ConfigMap{
ObjectMeta: metav1.ObjectMeta{
Name: "test-cm",
Namespace: "default",
},
Data: map[string]string{"key": "value"},
},
expectError: false,
},
{
name: "Valid Secret - no workloads to update",
resource: &v1.Secret{
ObjectMeta: metav1.ObjectMeta{
Name: "test-secret",
Namespace: "default",
},
Data: map[string][]byte{"key": []byte("value")},
},
expectError: false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
handler := ResourceCreatedHandler{
Resource: tt.resource,
Collectors: metrics.NewCollectors(),
}
err := handler.Handle()
if tt.expectError {
assert.Error(t, err)
} else {
assert.NoError(t, err)
}
})
}
}
func TestResourceCreatedHandler_SHAConsistency(t *testing.T) {
data := map[string]string{"key": "value"}
cm1 := &v1.ConfigMap{
ObjectMeta: metav1.ObjectMeta{Name: "cm1", Namespace: "default"},
Data: data,
}
cm2 := &v1.ConfigMap{
ObjectMeta: metav1.ObjectMeta{Name: "cm2", Namespace: "default"},
Data: data,
}
handler1 := ResourceCreatedHandler{Resource: cm1, Collectors: metrics.NewCollectors()}
handler2 := ResourceCreatedHandler{Resource: cm2, Collectors: metrics.NewCollectors()}
config1, _ := handler1.GetConfig()
config2, _ := handler2.GetConfig()
assert.Equal(t, config1.SHAValue, config2.SHAValue)
}
func TestResourceCreatedHandler_SHADifference(t *testing.T) {
cm1 := &v1.ConfigMap{
ObjectMeta: metav1.ObjectMeta{Name: "cm", Namespace: "default"},
Data: map[string]string{"key": "value1"},
}
cm2 := &v1.ConfigMap{
ObjectMeta: metav1.ObjectMeta{Name: "cm", Namespace: "default"},
Data: map[string]string{"key": "value2"},
}
handler1 := ResourceCreatedHandler{Resource: cm1, Collectors: metrics.NewCollectors()}
handler2 := ResourceCreatedHandler{Resource: cm2, Collectors: metrics.NewCollectors()}
config1, _ := handler1.GetConfig()
config2, _ := handler2.GetConfig()
assert.NotEqual(t, config1.SHAValue, config2.SHAValue)
}

View File

@@ -6,6 +6,7 @@ import (
"time"
"github.com/sirupsen/logrus"
"github.com/stakater/Reloader/internal/pkg/callbacks"
"github.com/stakater/Reloader/internal/pkg/constants"
"github.com/stakater/Reloader/internal/pkg/metrics"
@@ -67,10 +68,10 @@ func (r ResourceDeleteHandler) Handle() error {
func (r ResourceDeleteHandler) GetConfig() (common.Config, string) {
var oldSHAData string
var config common.Config
if _, ok := r.Resource.(*v1.ConfigMap); ok {
config = common.GetConfigmapConfig(r.Resource.(*v1.ConfigMap))
} else if _, ok := r.Resource.(*v1.Secret); ok {
config = common.GetSecretConfig(r.Resource.(*v1.Secret))
if cm, ok := r.Resource.(*v1.ConfigMap); ok {
config = common.GetConfigmapConfig(cm)
} else if secret, ok := r.Resource.(*v1.Secret); ok {
config = common.GetSecretConfig(secret)
} else {
logrus.Warnf("Invalid resource: Resource should be 'Secret' or 'Configmap' but found, %v", r.Resource)
}
@@ -98,7 +99,7 @@ func removeContainerEnvVars(upgradeFuncs callbacks.RollingUpgradeFuncs, item run
return InvokeStrategyResult{constants.NoContainerFound, nil}
}
//remove if env var exists
// remove if env var exists
if len(container.Env) > 0 {
index := slices.IndexFunc(container.Env, func(envVariable v1.EnvVar) bool {
return envVariable.Name == envVar

View File

@@ -0,0 +1,353 @@
package handler
import (
"testing"
"github.com/stretchr/testify/assert"
appsv1 "k8s.io/api/apps/v1"
v1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
"github.com/stakater/Reloader/internal/pkg/callbacks"
"github.com/stakater/Reloader/internal/pkg/constants"
"github.com/stakater/Reloader/internal/pkg/options"
"github.com/stakater/Reloader/pkg/common"
)
// mockDeploymentForDelete creates a deployment with containers for testing delete strategies
func mockDeploymentForDelete(name, namespace string, containers []v1.Container, volumes []v1.Volume) *appsv1.Deployment {
return &appsv1.Deployment{
ObjectMeta: metav1.ObjectMeta{
Name: name,
Namespace: namespace,
},
Spec: appsv1.DeploymentSpec{
Template: v1.PodTemplateSpec{
ObjectMeta: metav1.ObjectMeta{
Annotations: map[string]string{},
},
Spec: v1.PodSpec{
Containers: containers,
Volumes: volumes,
},
},
},
}
}
// Mock funcs for testing
func mockContainersFunc(item runtime.Object) []v1.Container {
deployment, ok := item.(*appsv1.Deployment)
if !ok {
return nil
}
return deployment.Spec.Template.Spec.Containers
}
func mockInitContainersFunc(item runtime.Object) []v1.Container {
deployment, ok := item.(*appsv1.Deployment)
if !ok {
return nil
}
return deployment.Spec.Template.Spec.InitContainers
}
func mockVolumesFunc(item runtime.Object) []v1.Volume {
deployment, ok := item.(*appsv1.Deployment)
if !ok {
return nil
}
return deployment.Spec.Template.Spec.Volumes
}
func mockPodAnnotationsFunc(item runtime.Object) map[string]string {
deployment, ok := item.(*appsv1.Deployment)
if !ok {
return nil
}
return deployment.Spec.Template.Annotations
}
func mockPatchTemplatesFunc() callbacks.PatchTemplates {
return callbacks.PatchTemplates{
AnnotationTemplate: `{"spec":{"template":{"metadata":{"annotations":{"%s":"%s"}}}}}`,
EnvVarTemplate: `{"spec":{"template":{"spec":{"containers":[{"name":"%s","env":[{"name":"%s","value":"%s"}]}]}}}}`,
DeleteEnvVarTemplate: `[{"op":"remove","path":"/spec/template/spec/containers/%d/env/%d"}]`,
}
}
func TestRemoveContainerEnvVars(t *testing.T) {
tests := []struct {
name string
containers []v1.Container
volumes []v1.Volume
config common.Config
autoReload bool
expected constants.Result
envVarRemoved bool
}{
{
name: "Remove existing env var - configmap envFrom",
containers: []v1.Container{
{
Name: "app",
EnvFrom: []v1.EnvFromSource{
{
ConfigMapRef: &v1.ConfigMapEnvSource{
LocalObjectReference: v1.LocalObjectReference{
Name: "my-configmap",
},
},
},
},
Env: []v1.EnvVar{
{Name: "STAKATER_MY_CONFIGMAP_CONFIGMAP", Value: "sha-value"},
},
},
},
volumes: []v1.Volume{},
config: common.Config{
ResourceName: "my-configmap",
Type: constants.ConfigmapEnvVarPostfix,
},
autoReload: true,
expected: constants.Updated,
envVarRemoved: true,
},
{
name: "No env var to remove",
containers: []v1.Container{
{
Name: "app",
EnvFrom: []v1.EnvFromSource{
{
ConfigMapRef: &v1.ConfigMapEnvSource{
LocalObjectReference: v1.LocalObjectReference{
Name: "my-configmap",
},
},
},
},
Env: []v1.EnvVar{},
},
},
volumes: []v1.Volume{},
config: common.Config{
ResourceName: "my-configmap",
Type: constants.ConfigmapEnvVarPostfix,
},
autoReload: true,
expected: constants.NotUpdated,
envVarRemoved: false,
},
{
name: "Remove existing env var - secret envFrom",
containers: []v1.Container{
{
Name: "app",
EnvFrom: []v1.EnvFromSource{
{
SecretRef: &v1.SecretEnvSource{
LocalObjectReference: v1.LocalObjectReference{
Name: "my-secret",
},
},
},
},
Env: []v1.EnvVar{
{Name: "STAKATER_MY_SECRET_SECRET", Value: "sha-value"},
},
},
},
volumes: []v1.Volume{},
config: common.Config{
ResourceName: "my-secret",
Type: constants.SecretEnvVarPostfix,
},
autoReload: true,
expected: constants.Updated,
envVarRemoved: true,
},
{
name: "No container found",
containers: []v1.Container{},
volumes: []v1.Volume{},
config: common.Config{
ResourceName: "my-configmap",
Type: constants.ConfigmapEnvVarPostfix,
},
autoReload: true,
expected: constants.NoContainerFound,
envVarRemoved: false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
deployment := mockDeploymentForDelete("test-deploy", "default", tt.containers, tt.volumes)
funcs := callbacks.RollingUpgradeFuncs{
ContainersFunc: mockContainersFunc,
InitContainersFunc: mockInitContainersFunc,
VolumesFunc: mockVolumesFunc,
PodAnnotationsFunc: mockPodAnnotationsFunc,
PatchTemplatesFunc: mockPatchTemplatesFunc,
SupportsPatch: true,
}
result := removeContainerEnvVars(funcs, deployment, tt.config, tt.autoReload)
assert.Equal(t, tt.expected, result.Result)
if tt.envVarRemoved {
containers := deployment.Spec.Template.Spec.Containers
for _, c := range containers {
for _, env := range c.Env {
envVarName := getEnvVarName(tt.config.ResourceName, tt.config.Type)
assert.NotEqual(t, envVarName, env.Name, "Env var should have been removed")
}
}
}
})
}
}
func TestInvokeDeleteStrategy(t *testing.T) {
originalStrategy := options.ReloadStrategy
defer func() {
options.ReloadStrategy = originalStrategy
}()
tests := []struct {
name string
reloadStrategy string
containers []v1.Container
volumes []v1.Volume
config common.Config
}{
{
name: "Annotations strategy",
reloadStrategy: constants.AnnotationsReloadStrategy,
containers: []v1.Container{
{
Name: "app",
EnvFrom: []v1.EnvFromSource{
{
ConfigMapRef: &v1.ConfigMapEnvSource{
LocalObjectReference: v1.LocalObjectReference{
Name: "my-configmap",
},
},
},
},
},
},
volumes: []v1.Volume{},
config: common.Config{
ResourceName: "my-configmap",
Type: constants.ConfigmapEnvVarPostfix,
SHAValue: "sha-value",
},
},
{
name: "EnvVars strategy",
reloadStrategy: constants.EnvVarsReloadStrategy,
containers: []v1.Container{
{
Name: "app",
EnvFrom: []v1.EnvFromSource{
{
ConfigMapRef: &v1.ConfigMapEnvSource{
LocalObjectReference: v1.LocalObjectReference{
Name: "my-configmap",
},
},
},
},
Env: []v1.EnvVar{
{Name: "STAKATER_MY_CONFIGMAP_CONFIGMAP", Value: "sha-value"},
},
},
},
volumes: []v1.Volume{},
config: common.Config{
ResourceName: "my-configmap",
Type: constants.ConfigmapEnvVarPostfix,
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
options.ReloadStrategy = tt.reloadStrategy
deployment := mockDeploymentForDelete("test-deploy", "default", tt.containers, tt.volumes)
funcs := callbacks.RollingUpgradeFuncs{
ContainersFunc: mockContainersFunc,
InitContainersFunc: mockInitContainersFunc,
VolumesFunc: mockVolumesFunc,
PodAnnotationsFunc: mockPodAnnotationsFunc,
PatchTemplatesFunc: mockPatchTemplatesFunc,
SupportsPatch: true,
}
result := invokeDeleteStrategy(funcs, deployment, tt.config, true)
assert.NotNil(t, result)
})
}
}
func TestRemovePodAnnotations(t *testing.T) {
tests := []struct {
name string
containers []v1.Container
volumes []v1.Volume
config common.Config
}{
{
name: "Remove pod annotations - configmap",
containers: []v1.Container{
{
Name: "app",
EnvFrom: []v1.EnvFromSource{
{
ConfigMapRef: &v1.ConfigMapEnvSource{
LocalObjectReference: v1.LocalObjectReference{
Name: "my-configmap",
},
},
},
},
},
},
volumes: []v1.Volume{},
config: common.Config{
ResourceName: "my-configmap",
Type: constants.ConfigmapEnvVarPostfix,
SHAValue: "sha-value",
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
deployment := mockDeploymentForDelete("test-deploy", "default", tt.containers, tt.volumes)
funcs := callbacks.RollingUpgradeFuncs{
ContainersFunc: mockContainersFunc,
InitContainersFunc: mockInitContainersFunc,
VolumesFunc: mockVolumesFunc,
PodAnnotationsFunc: mockPodAnnotationsFunc,
PatchTemplatesFunc: mockPatchTemplatesFunc,
SupportsPatch: false,
}
result := removePodAnnotations(funcs, deployment, tt.config, true)
assert.Equal(t, constants.Updated, result.Result)
})
}
}

View File

@@ -0,0 +1,281 @@
package handler
import (
"testing"
"github.com/stretchr/testify/assert"
v1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"github.com/stakater/Reloader/internal/pkg/constants"
"github.com/stakater/Reloader/internal/pkg/metrics"
)
// Helper function to create a test ConfigMap
func createTestConfigMap(data map[string]string) *v1.ConfigMap {
return &v1.ConfigMap{
ObjectMeta: metav1.ObjectMeta{
Name: "test-cm",
Namespace: "default",
},
Data: data,
}
}
// Helper function to create a test Secret
func createTestSecret(data map[string][]byte) *v1.Secret {
return &v1.Secret{
ObjectMeta: metav1.ObjectMeta{
Name: "test-secret",
Namespace: "default",
},
Data: data,
}
}
// Helper function to create test metrics collectors
func createTestCollectors() metrics.Collectors {
return metrics.NewCollectors()
}
// ============================================================
// ResourceCreatedHandler Tests
// ============================================================
func TestResourceCreatedHandler_GetConfig_ConfigMap(t *testing.T) {
cm := createTestConfigMap(map[string]string{"key": "value"})
handler := ResourceCreatedHandler{
Resource: cm,
Collectors: createTestCollectors(),
}
config, oldSHA := handler.GetConfig()
assert.Equal(t, "test-cm", config.ResourceName)
assert.Equal(t, "default", config.Namespace)
assert.Equal(t, constants.ConfigmapEnvVarPostfix, config.Type)
assert.NotEmpty(t, config.SHAValue)
assert.Empty(t, oldSHA)
}
func TestResourceCreatedHandler_GetConfig_Secret(t *testing.T) {
secret := createTestSecret(map[string][]byte{"key": []byte("value")})
handler := ResourceCreatedHandler{
Resource: secret,
Collectors: createTestCollectors(),
}
config, oldSHA := handler.GetConfig()
assert.Equal(t, "test-secret", config.ResourceName)
assert.Equal(t, "default", config.Namespace)
assert.Equal(t, constants.SecretEnvVarPostfix, config.Type)
assert.NotEmpty(t, config.SHAValue)
assert.Empty(t, oldSHA)
}
func TestResourceCreatedHandler_GetConfig_InvalidResource(t *testing.T) {
handler := ResourceCreatedHandler{
Resource: "invalid",
Collectors: createTestCollectors(),
}
config, _ := handler.GetConfig()
assert.Empty(t, config.ResourceName)
}
func TestResourceCreatedHandler_Handle_NilResource(t *testing.T) {
handler := ResourceCreatedHandler{
Resource: nil,
Collectors: createTestCollectors(),
}
err := handler.Handle()
assert.NoError(t, err)
}
// ============================================================
// ResourceDeleteHandler Tests
// ============================================================
func TestResourceDeleteHandler_GetConfig_ConfigMap(t *testing.T) {
cm := createTestConfigMap(map[string]string{"key": "value"})
handler := ResourceDeleteHandler{
Resource: cm,
Collectors: createTestCollectors(),
}
config, oldSHA := handler.GetConfig()
assert.Equal(t, "test-cm", config.ResourceName)
assert.Equal(t, "default", config.Namespace)
assert.Equal(t, constants.ConfigmapEnvVarPostfix, config.Type)
assert.NotEmpty(t, config.SHAValue)
assert.Empty(t, oldSHA)
}
func TestResourceDeleteHandler_GetConfig_Secret(t *testing.T) {
secret := createTestSecret(map[string][]byte{"key": []byte("value")})
handler := ResourceDeleteHandler{
Resource: secret,
Collectors: createTestCollectors(),
}
config, oldSHA := handler.GetConfig()
assert.Equal(t, "test-secret", config.ResourceName)
assert.Equal(t, "default", config.Namespace)
assert.Equal(t, constants.SecretEnvVarPostfix, config.Type)
assert.NotEmpty(t, config.SHAValue)
assert.Empty(t, oldSHA)
}
func TestResourceDeleteHandler_GetConfig_InvalidResource(t *testing.T) {
handler := ResourceDeleteHandler{
Resource: "invalid",
Collectors: createTestCollectors(),
}
config, _ := handler.GetConfig()
assert.Empty(t, config.ResourceName)
}
func TestResourceDeleteHandler_Handle_NilResource(t *testing.T) {
handler := ResourceDeleteHandler{
Resource: nil,
Collectors: createTestCollectors(),
}
err := handler.Handle()
assert.NoError(t, err)
}
// ============================================================
// ResourceUpdatedHandler Tests
// ============================================================
func TestResourceUpdatedHandler_GetConfig_ConfigMap(t *testing.T) {
oldCM := createTestConfigMap(map[string]string{"key": "old-value"})
newCM := createTestConfigMap(map[string]string{"key": "new-value"})
handler := ResourceUpdatedHandler{
Resource: newCM,
OldResource: oldCM,
Collectors: createTestCollectors(),
}
config, oldSHA := handler.GetConfig()
assert.Equal(t, "test-cm", config.ResourceName)
assert.Equal(t, "default", config.Namespace)
assert.Equal(t, constants.ConfigmapEnvVarPostfix, config.Type)
assert.NotEmpty(t, config.SHAValue)
assert.NotEmpty(t, oldSHA)
assert.NotEqual(t, config.SHAValue, oldSHA)
}
func TestResourceUpdatedHandler_GetConfig_ConfigMap_SameData(t *testing.T) {
oldCM := createTestConfigMap(map[string]string{"key": "same-value"})
newCM := createTestConfigMap(map[string]string{"key": "same-value"})
handler := ResourceUpdatedHandler{
Resource: newCM,
OldResource: oldCM,
Collectors: createTestCollectors(),
}
config, oldSHA := handler.GetConfig()
assert.Equal(t, "test-cm", config.ResourceName)
assert.Equal(t, config.SHAValue, oldSHA)
}
func TestResourceUpdatedHandler_GetConfig_Secret(t *testing.T) {
oldSecret := createTestSecret(map[string][]byte{"key": []byte("old-value")})
newSecret := createTestSecret(map[string][]byte{"key": []byte("new-value")})
handler := ResourceUpdatedHandler{
Resource: newSecret,
OldResource: oldSecret,
Collectors: createTestCollectors(),
}
config, oldSHA := handler.GetConfig()
assert.Equal(t, "test-secret", config.ResourceName)
assert.Equal(t, "default", config.Namespace)
assert.Equal(t, constants.SecretEnvVarPostfix, config.Type)
assert.NotEmpty(t, config.SHAValue)
assert.NotEmpty(t, oldSHA)
assert.NotEqual(t, config.SHAValue, oldSHA)
}
func TestResourceUpdatedHandler_GetConfig_Secret_SameData(t *testing.T) {
oldSecret := createTestSecret(map[string][]byte{"key": []byte("same-value")})
newSecret := createTestSecret(map[string][]byte{"key": []byte("same-value")})
handler := ResourceUpdatedHandler{
Resource: newSecret,
OldResource: oldSecret,
Collectors: createTestCollectors(),
}
config, oldSHA := handler.GetConfig()
assert.Equal(t, "test-secret", config.ResourceName)
assert.Equal(t, config.SHAValue, oldSHA)
}
func TestResourceUpdatedHandler_GetConfig_InvalidResource(t *testing.T) {
handler := ResourceUpdatedHandler{
Resource: "invalid",
OldResource: "invalid",
Collectors: createTestCollectors(),
}
config, _ := handler.GetConfig()
assert.Empty(t, config.ResourceName)
}
func TestResourceUpdatedHandler_Handle_NilResource(t *testing.T) {
handler := ResourceUpdatedHandler{
Resource: nil,
OldResource: nil,
Collectors: createTestCollectors(),
}
err := handler.Handle()
assert.NoError(t, err)
}
func TestResourceUpdatedHandler_Handle_NilOldResource(t *testing.T) {
cm := createTestConfigMap(map[string]string{"key": "value"})
handler := ResourceUpdatedHandler{
Resource: cm,
OldResource: nil,
Collectors: createTestCollectors(),
}
err := handler.Handle()
assert.NoError(t, err)
}
func TestResourceUpdatedHandler_Handle_NoChange(t *testing.T) {
cm := createTestConfigMap(map[string]string{"key": "same-value"})
handler := ResourceUpdatedHandler{
Resource: cm,
OldResource: cm,
Collectors: createTestCollectors(),
}
err := handler.Handle()
assert.NoError(t, err)
}

View File

@@ -7,11 +7,12 @@ import (
"time"
"github.com/sirupsen/logrus"
"github.com/stakater/Reloader/internal/pkg/options"
"github.com/stakater/Reloader/pkg/kube"
app "k8s.io/api/apps/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
patchtypes "k8s.io/apimachinery/pkg/types"
"github.com/stakater/Reloader/internal/pkg/options"
"github.com/stakater/Reloader/pkg/kube"
)
// Keeps track of currently active timers

View File

@@ -6,14 +6,15 @@ import (
"testing"
"time"
"github.com/stakater/Reloader/internal/pkg/options"
"github.com/stakater/Reloader/pkg/kube"
"github.com/stretchr/testify/assert"
appsv1 "k8s.io/api/apps/v1"
"k8s.io/apimachinery/pkg/api/meta"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
testclient "k8s.io/client-go/kubernetes/fake"
"github.com/stakater/Reloader/internal/pkg/options"
"github.com/stakater/Reloader/pkg/kube"
)
func TestIsPaused(t *testing.T) {
@@ -377,7 +378,7 @@ func FindDeploymentByName(deployments []runtime.Object, deploymentName string) (
for _, deployment := range deployments {
accessor, err := meta.Accessor(deployment)
if err != nil {
return nil, fmt.Errorf("error getting accessor for item: %v", err)
return nil, fmt.Errorf("error getting accessor for item: %w", err)
}
if accessor.GetName() == deploymentName {
deploymentObj, ok := deployment.(*appsv1.Deployment)

View File

@@ -4,13 +4,14 @@ import (
"time"
"github.com/sirupsen/logrus"
v1 "k8s.io/api/core/v1"
"k8s.io/client-go/tools/record"
csiv1 "sigs.k8s.io/secrets-store-csi-driver/apis/v1"
"github.com/stakater/Reloader/internal/pkg/metrics"
"github.com/stakater/Reloader/internal/pkg/options"
"github.com/stakater/Reloader/internal/pkg/util"
"github.com/stakater/Reloader/pkg/common"
v1 "k8s.io/api/core/v1"
"k8s.io/client-go/tools/record"
csiv1 "sigs.k8s.io/secrets-store-csi-driver/apis/v1"
)
// ResourceUpdatedHandler contains updated objects

View File

@@ -0,0 +1,520 @@
package handler
import (
"testing"
"github.com/stretchr/testify/assert"
v1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"github.com/stakater/Reloader/internal/pkg/constants"
"github.com/stakater/Reloader/internal/pkg/metrics"
)
func TestResourceUpdatedHandler_GetConfig(t *testing.T) {
tests := []struct {
name string
oldResource any
newResource any
expectedName string
expectedNS string
expectedType string
expectSHANotEmpty bool
expectSHAChanged bool
}{
{
name: "ConfigMap data changed",
oldResource: &v1.ConfigMap{
ObjectMeta: metav1.ObjectMeta{Name: "my-cm", Namespace: "default"},
Data: map[string]string{"key": "old-value"},
},
newResource: &v1.ConfigMap{
ObjectMeta: metav1.ObjectMeta{Name: "my-cm", Namespace: "default"},
Data: map[string]string{"key": "new-value"},
},
expectedName: "my-cm",
expectedNS: "default",
expectedType: constants.ConfigmapEnvVarPostfix,
expectSHANotEmpty: true,
expectSHAChanged: true,
},
{
name: "ConfigMap data unchanged",
oldResource: &v1.ConfigMap{
ObjectMeta: metav1.ObjectMeta{Name: "my-cm", Namespace: "default"},
Data: map[string]string{"key": "same-value"},
},
newResource: &v1.ConfigMap{
ObjectMeta: metav1.ObjectMeta{Name: "my-cm", Namespace: "default"},
Data: map[string]string{"key": "same-value"},
},
expectedName: "my-cm",
expectedNS: "default",
expectedType: constants.ConfigmapEnvVarPostfix,
expectSHANotEmpty: true,
expectSHAChanged: false,
},
{
name: "ConfigMap key added",
oldResource: &v1.ConfigMap{
ObjectMeta: metav1.ObjectMeta{Name: "my-cm", Namespace: "default"},
Data: map[string]string{"key1": "value1"},
},
newResource: &v1.ConfigMap{
ObjectMeta: metav1.ObjectMeta{Name: "my-cm", Namespace: "default"},
Data: map[string]string{"key1": "value1", "key2": "value2"},
},
expectedName: "my-cm",
expectedNS: "default",
expectedType: constants.ConfigmapEnvVarPostfix,
expectSHANotEmpty: true,
expectSHAChanged: true,
},
{
name: "ConfigMap key removed",
oldResource: &v1.ConfigMap{
ObjectMeta: metav1.ObjectMeta{Name: "my-cm", Namespace: "default"},
Data: map[string]string{"key1": "value1", "key2": "value2"},
},
newResource: &v1.ConfigMap{
ObjectMeta: metav1.ObjectMeta{Name: "my-cm", Namespace: "default"},
Data: map[string]string{"key1": "value1"},
},
expectedName: "my-cm",
expectedNS: "default",
expectedType: constants.ConfigmapEnvVarPostfix,
expectSHANotEmpty: true,
expectSHAChanged: true,
},
{
name: "ConfigMap only labels changed - SHA unchanged",
oldResource: &v1.ConfigMap{
ObjectMeta: metav1.ObjectMeta{
Name: "my-cm",
Namespace: "default",
Labels: map[string]string{"version": "v1"},
},
Data: map[string]string{"key": "value"},
},
newResource: &v1.ConfigMap{
ObjectMeta: metav1.ObjectMeta{
Name: "my-cm",
Namespace: "default",
Labels: map[string]string{"version": "v2"},
},
Data: map[string]string{"key": "value"},
},
expectedName: "my-cm",
expectedNS: "default",
expectedType: constants.ConfigmapEnvVarPostfix,
expectSHANotEmpty: true,
expectSHAChanged: false,
},
{
name: "ConfigMap only annotations changed - SHA unchanged",
oldResource: &v1.ConfigMap{
ObjectMeta: metav1.ObjectMeta{
Name: "my-cm",
Namespace: "default",
Annotations: map[string]string{"note": "old"},
},
Data: map[string]string{"key": "value"},
},
newResource: &v1.ConfigMap{
ObjectMeta: metav1.ObjectMeta{
Name: "my-cm",
Namespace: "default",
Annotations: map[string]string{"note": "new"},
},
Data: map[string]string{"key": "value"},
},
expectedName: "my-cm",
expectedNS: "default",
expectedType: constants.ConfigmapEnvVarPostfix,
expectSHANotEmpty: true,
expectSHAChanged: false,
},
{
name: "Secret data changed",
oldResource: &v1.Secret{
ObjectMeta: metav1.ObjectMeta{Name: "my-secret", Namespace: "default"},
Data: map[string][]byte{"password": []byte("old-pass")},
},
newResource: &v1.Secret{
ObjectMeta: metav1.ObjectMeta{Name: "my-secret", Namespace: "default"},
Data: map[string][]byte{"password": []byte("new-pass")},
},
expectedName: "my-secret",
expectedNS: "default",
expectedType: constants.SecretEnvVarPostfix,
expectSHANotEmpty: true,
expectSHAChanged: true,
},
{
name: "Secret data unchanged",
oldResource: &v1.Secret{
ObjectMeta: metav1.ObjectMeta{Name: "my-secret", Namespace: "default"},
Data: map[string][]byte{"password": []byte("same-pass")},
},
newResource: &v1.Secret{
ObjectMeta: metav1.ObjectMeta{Name: "my-secret", Namespace: "default"},
Data: map[string][]byte{"password": []byte("same-pass")},
},
expectedName: "my-secret",
expectedNS: "default",
expectedType: constants.SecretEnvVarPostfix,
expectSHANotEmpty: true,
expectSHAChanged: false,
},
{
name: "Secret key added",
oldResource: &v1.Secret{
ObjectMeta: metav1.ObjectMeta{Name: "my-secret", Namespace: "default"},
Data: map[string][]byte{"key1": []byte("value1")},
},
newResource: &v1.Secret{
ObjectMeta: metav1.ObjectMeta{Name: "my-secret", Namespace: "default"},
Data: map[string][]byte{"key1": []byte("value1"), "key2": []byte("value2")},
},
expectedName: "my-secret",
expectedNS: "default",
expectedType: constants.SecretEnvVarPostfix,
expectSHANotEmpty: true,
expectSHAChanged: true,
},
{
name: "Secret only labels changed - SHA unchanged",
oldResource: &v1.Secret{
ObjectMeta: metav1.ObjectMeta{
Name: "my-secret",
Namespace: "default",
Labels: map[string]string{"env": "dev"},
},
Data: map[string][]byte{"key": []byte("value")},
},
newResource: &v1.Secret{
ObjectMeta: metav1.ObjectMeta{
Name: "my-secret",
Namespace: "default",
Labels: map[string]string{"env": "prod"},
},
Data: map[string][]byte{"key": []byte("value")},
},
expectedName: "my-secret",
expectedNS: "default",
expectedType: constants.SecretEnvVarPostfix,
expectSHANotEmpty: true,
expectSHAChanged: false,
},
{
name: "Invalid resource type",
oldResource: "invalid",
newResource: "invalid",
expectedName: "",
expectedNS: "",
expectedType: "",
expectSHANotEmpty: false,
expectSHAChanged: false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
handler := ResourceUpdatedHandler{
Resource: tt.newResource,
OldResource: tt.oldResource,
Collectors: metrics.NewCollectors(),
}
config, oldSHA := handler.GetConfig()
assert.Equal(t, tt.expectedName, config.ResourceName)
assert.Equal(t, tt.expectedNS, config.Namespace)
assert.Equal(t, tt.expectedType, config.Type)
if tt.expectSHANotEmpty {
assert.NotEmpty(t, config.SHAValue, "new SHA should not be empty")
assert.NotEmpty(t, oldSHA, "old SHA should not be empty")
}
if tt.expectSHAChanged {
assert.NotEqual(t, config.SHAValue, oldSHA, "SHA should have changed")
} else if tt.expectSHANotEmpty {
assert.Equal(t, config.SHAValue, oldSHA, "SHA should not have changed")
}
})
}
}
func TestResourceUpdatedHandler_Handle(t *testing.T) {
tests := []struct {
name string
oldResource any
newResource any
expectError bool
}{
{
name: "Both resources nil",
oldResource: nil,
newResource: nil,
expectError: false,
},
{
name: "Old resource nil",
oldResource: nil,
newResource: &v1.ConfigMap{
ObjectMeta: metav1.ObjectMeta{Name: "cm", Namespace: "default"},
Data: map[string]string{"key": "value"},
},
expectError: false,
},
{
name: "New resource nil",
oldResource: &v1.ConfigMap{
ObjectMeta: metav1.ObjectMeta{Name: "cm", Namespace: "default"},
Data: map[string]string{"key": "value"},
},
newResource: nil,
expectError: false,
},
{
name: "ConfigMap unchanged - no action",
oldResource: &v1.ConfigMap{
ObjectMeta: metav1.ObjectMeta{Name: "cm", Namespace: "default"},
Data: map[string]string{"key": "same"},
},
newResource: &v1.ConfigMap{
ObjectMeta: metav1.ObjectMeta{Name: "cm", Namespace: "default"},
Data: map[string]string{"key": "same"},
},
expectError: false,
},
{
name: "ConfigMap changed - triggers update",
oldResource: &v1.ConfigMap{
ObjectMeta: metav1.ObjectMeta{Name: "cm", Namespace: "default"},
Data: map[string]string{"key": "old"},
},
newResource: &v1.ConfigMap{
ObjectMeta: metav1.ObjectMeta{Name: "cm", Namespace: "default"},
Data: map[string]string{"key": "new"},
},
expectError: false,
},
{
name: "Secret unchanged - no action",
oldResource: &v1.Secret{
ObjectMeta: metav1.ObjectMeta{Name: "secret", Namespace: "default"},
Data: map[string][]byte{"key": []byte("same")},
},
newResource: &v1.Secret{
ObjectMeta: metav1.ObjectMeta{Name: "secret", Namespace: "default"},
Data: map[string][]byte{"key": []byte("same")},
},
expectError: false,
},
{
name: "Secret changed - triggers update",
oldResource: &v1.Secret{
ObjectMeta: metav1.ObjectMeta{Name: "secret", Namespace: "default"},
Data: map[string][]byte{"key": []byte("old")},
},
newResource: &v1.Secret{
ObjectMeta: metav1.ObjectMeta{Name: "secret", Namespace: "default"},
Data: map[string][]byte{"key": []byte("new")},
},
expectError: false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
handler := ResourceUpdatedHandler{
Resource: tt.newResource,
OldResource: tt.oldResource,
Collectors: metrics.NewCollectors(),
}
err := handler.Handle()
if tt.expectError {
assert.Error(t, err)
} else {
assert.NoError(t, err)
}
})
}
}
func TestResourceUpdatedHandler_GetConfig_Annotations(t *testing.T) {
oldCM := &v1.ConfigMap{
ObjectMeta: metav1.ObjectMeta{
Name: "cm",
Namespace: "default",
Annotations: map[string]string{
"old-annotation": "old-value",
},
},
Data: map[string]string{"key": "value"},
}
newCM := &v1.ConfigMap{
ObjectMeta: metav1.ObjectMeta{
Name: "cm",
Namespace: "default",
Annotations: map[string]string{
"new-annotation": "new-value",
},
},
Data: map[string]string{"key": "value"},
}
handler := ResourceUpdatedHandler{
Resource: newCM,
OldResource: oldCM,
Collectors: metrics.NewCollectors(),
}
config, _ := handler.GetConfig()
assert.Equal(t, "new-value", config.ResourceAnnotations["new-annotation"])
_, hasOld := config.ResourceAnnotations["old-annotation"]
assert.False(t, hasOld)
}
func TestResourceUpdatedHandler_GetConfig_Labels(t *testing.T) {
oldSecret := &v1.Secret{
ObjectMeta: metav1.ObjectMeta{
Name: "secret",
Namespace: "default",
Labels: map[string]string{"version": "v1"},
},
Data: map[string][]byte{"key": []byte("value")},
}
newSecret := &v1.Secret{
ObjectMeta: metav1.ObjectMeta{
Name: "secret",
Namespace: "default",
Labels: map[string]string{"version": "v2"},
},
Data: map[string][]byte{"key": []byte("value")},
}
handler := ResourceUpdatedHandler{
Resource: newSecret,
OldResource: oldSecret,
Collectors: metrics.NewCollectors(),
}
config, _ := handler.GetConfig()
assert.Equal(t, "v2", config.Labels["version"])
}
func TestResourceUpdatedHandler_EmptyToNonEmpty(t *testing.T) {
oldCM := &v1.ConfigMap{
ObjectMeta: metav1.ObjectMeta{Name: "cm", Namespace: "default"},
Data: map[string]string{},
}
newCM := &v1.ConfigMap{
ObjectMeta: metav1.ObjectMeta{Name: "cm", Namespace: "default"},
Data: map[string]string{"key": "value"},
}
handler := ResourceUpdatedHandler{
Resource: newCM,
OldResource: oldCM,
Collectors: metrics.NewCollectors(),
}
config, oldSHA := handler.GetConfig()
assert.NotEqual(t, config.SHAValue, oldSHA, "SHA should change when data is added")
}
func TestResourceUpdatedHandler_NonEmptyToEmpty(t *testing.T) {
oldCM := &v1.ConfigMap{
ObjectMeta: metav1.ObjectMeta{Name: "cm", Namespace: "default"},
Data: map[string]string{"key": "value"},
}
newCM := &v1.ConfigMap{
ObjectMeta: metav1.ObjectMeta{Name: "cm", Namespace: "default"},
Data: map[string]string{},
}
handler := ResourceUpdatedHandler{
Resource: newCM,
OldResource: oldCM,
Collectors: metrics.NewCollectors(),
}
config, oldSHA := handler.GetConfig()
assert.NotEqual(t, config.SHAValue, oldSHA, "SHA should change when data is removed")
}
func TestResourceUpdatedHandler_BinaryDataChange(t *testing.T) {
oldCM := &v1.ConfigMap{
ObjectMeta: metav1.ObjectMeta{Name: "cm", Namespace: "default"},
BinaryData: map[string][]byte{"binary": []byte("old-binary")},
}
newCM := &v1.ConfigMap{
ObjectMeta: metav1.ObjectMeta{Name: "cm", Namespace: "default"},
BinaryData: map[string][]byte{"binary": []byte("new-binary")},
}
handler := ResourceUpdatedHandler{
Resource: newCM,
OldResource: oldCM,
Collectors: metrics.NewCollectors(),
}
config, oldSHA := handler.GetConfig()
assert.NotEqual(t, config.SHAValue, oldSHA, "SHA should change when binary data changes")
}
func TestResourceUpdatedHandler_MixedDataAndBinaryData(t *testing.T) {
oldCM := &v1.ConfigMap{
ObjectMeta: metav1.ObjectMeta{Name: "cm", Namespace: "default"},
Data: map[string]string{"text": "value"},
BinaryData: map[string][]byte{"binary": []byte("binary-value")},
}
newCM := &v1.ConfigMap{
ObjectMeta: metav1.ObjectMeta{Name: "cm", Namespace: "default"},
Data: map[string]string{"text": "value"},
BinaryData: map[string][]byte{"binary": []byte("new-binary-value")},
}
handler := ResourceUpdatedHandler{
Resource: newCM,
OldResource: oldCM,
Collectors: metrics.NewCollectors(),
}
config, oldSHA := handler.GetConfig()
assert.NotEqual(t, config.SHAValue, oldSHA, "SHA should change when binary data changes")
}
func TestResourceUpdatedHandler_DifferentNamespaces(t *testing.T) {
oldCM := &v1.ConfigMap{
ObjectMeta: metav1.ObjectMeta{Name: "cm", Namespace: "ns1"},
Data: map[string]string{"key": "value"},
}
newCM := &v1.ConfigMap{
ObjectMeta: metav1.ObjectMeta{Name: "cm", Namespace: "ns2"},
Data: map[string]string{"key": "value"},
}
handler := ResourceUpdatedHandler{
Resource: newCM,
OldResource: oldCM,
Collectors: metrics.NewCollectors(),
}
config, _ := handler.GetConfig()
assert.Equal(t, "ns2", config.Namespace)
}

View File

@@ -14,14 +14,6 @@ import (
"github.com/parnurzeal/gorequest"
"github.com/prometheus/client_golang/prometheus"
"github.com/sirupsen/logrus"
alert "github.com/stakater/Reloader/internal/pkg/alerts"
"github.com/stakater/Reloader/internal/pkg/callbacks"
"github.com/stakater/Reloader/internal/pkg/constants"
"github.com/stakater/Reloader/internal/pkg/metrics"
"github.com/stakater/Reloader/internal/pkg/options"
"github.com/stakater/Reloader/internal/pkg/util"
"github.com/stakater/Reloader/pkg/common"
"github.com/stakater/Reloader/pkg/kube"
app "k8s.io/api/apps/v1"
v1 "k8s.io/api/core/v1"
apierrors "k8s.io/apimachinery/pkg/api/errors"
@@ -32,6 +24,15 @@ import (
"k8s.io/apimachinery/pkg/util/wait"
"k8s.io/client-go/tools/record"
"k8s.io/client-go/util/retry"
alert "github.com/stakater/Reloader/internal/pkg/alerts"
"github.com/stakater/Reloader/internal/pkg/callbacks"
"github.com/stakater/Reloader/internal/pkg/constants"
"github.com/stakater/Reloader/internal/pkg/metrics"
"github.com/stakater/Reloader/internal/pkg/options"
"github.com/stakater/Reloader/internal/pkg/util"
"github.com/stakater/Reloader/pkg/common"
"github.com/stakater/Reloader/pkg/kube"
)
// GetDeploymentRollingUpgradeFuncs returns all callback funcs for a deployment
@@ -617,7 +618,7 @@ func updateContainerEnvVars(upgradeFuncs callbacks.RollingUpgradeFuncs, item run
return InvokeStrategyResult{constants.NotUpdated, nil}
}
//update if env var exists
// update if env var exists
updateResult := updateEnvVar(container, envVar, config.SHAValue)
// if no existing env var exists lets create one
@@ -680,10 +681,10 @@ func populateAnnotationsFromSecretProviderClass(clients kube.Clients, config *co
}
func jsonEscape(toEscape string) (string, error) {
bytes, err := json.Marshal(toEscape)
data, err := json.Marshal(toEscape)
if err != nil {
return "", err
}
escaped := string(bytes)
escaped := string(data)
return escaped[1 : len(escaped)-1], nil
}

File diff suppressed because it is too large Load Diff

View File

@@ -7,11 +7,12 @@ import (
"time"
"github.com/sirupsen/logrus"
"github.com/stakater/Reloader/internal/pkg/controller"
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/tools/leaderelection"
"k8s.io/client-go/tools/leaderelection/resourcelock"
"github.com/stakater/Reloader/internal/pkg/controller"
coordinationv1 "k8s.io/client-go/kubernetes/typed/coordination/v1"
)
@@ -75,7 +76,7 @@ func RunLeaderElection(lock *resourcelock.LeaseLock, ctx context.Context, cancel
func runControllers(controllers []*controller.Controller, stopChannels []chan struct{}) {
for i, c := range controllers {
c := c
go c.Run(1, stopChannels[i])
}
}

View File

@@ -10,6 +10,7 @@ import (
"time"
"github.com/sirupsen/logrus"
"github.com/stakater/Reloader/internal/pkg/constants"
"github.com/stakater/Reloader/internal/pkg/controller"
"github.com/stakater/Reloader/internal/pkg/handler"

View File

@@ -15,14 +15,6 @@ import (
openshiftv1 "github.com/openshift/api/apps/v1"
appsclient "github.com/openshift/client-go/apps/clientset/versioned"
"github.com/sirupsen/logrus"
"github.com/stakater/Reloader/internal/pkg/callbacks"
"github.com/stakater/Reloader/internal/pkg/constants"
"github.com/stakater/Reloader/internal/pkg/crypto"
"github.com/stakater/Reloader/internal/pkg/metrics"
"github.com/stakater/Reloader/internal/pkg/options"
"github.com/stakater/Reloader/internal/pkg/util"
"github.com/stakater/Reloader/pkg/common"
"github.com/stakater/Reloader/pkg/kube"
appsv1 "k8s.io/api/apps/v1"
batchv1 "k8s.io/api/batch/v1"
v1 "k8s.io/api/core/v1"
@@ -33,6 +25,15 @@ import (
csiv1 "sigs.k8s.io/secrets-store-csi-driver/apis/v1"
csiclient "sigs.k8s.io/secrets-store-csi-driver/pkg/client/clientset/versioned"
csiclient_v1 "sigs.k8s.io/secrets-store-csi-driver/pkg/client/clientset/versioned/typed/apis/v1"
"github.com/stakater/Reloader/internal/pkg/callbacks"
"github.com/stakater/Reloader/internal/pkg/constants"
"github.com/stakater/Reloader/internal/pkg/crypto"
"github.com/stakater/Reloader/internal/pkg/metrics"
"github.com/stakater/Reloader/internal/pkg/options"
"github.com/stakater/Reloader/internal/pkg/util"
"github.com/stakater/Reloader/pkg/common"
"github.com/stakater/Reloader/pkg/kube"
)
var (

View File

@@ -31,7 +31,7 @@ type ObjectMeta struct {
func ToObjectMeta(kubernetesObject interface{}) ObjectMeta {
objectValue := reflect.ValueOf(kubernetesObject)
fieldName := reflect.TypeOf((*metav1.ObjectMeta)(nil)).Elem().Name()
field := objectValue.FieldByName(fieldName).Interface().(metav1.ObjectMeta)
field, _ := objectValue.FieldByName(fieldName).Interface().(metav1.ObjectMeta)
return ObjectMeta{
ObjectMeta: field,
@@ -41,9 +41,11 @@ func ToObjectMeta(kubernetesObject interface{}) ObjectMeta {
// ParseBool returns result in bool format after parsing
func ParseBool(value interface{}) bool {
if reflect.Bool == reflect.TypeOf(value).Kind() {
return value.(bool)
b, _ := value.(bool)
return b
} else if reflect.String == reflect.TypeOf(value).Kind() {
result, _ := strconv.ParseBool(value.(string))
s, _ := value.(string)
result, _ := strconv.ParseBool(s)
return result
}
return false

View File

@@ -9,11 +9,12 @@ import (
"strings"
"github.com/spf13/cobra"
v1 "k8s.io/api/core/v1"
csiv1 "sigs.k8s.io/secrets-store-csi-driver/apis/v1"
"github.com/stakater/Reloader/internal/pkg/constants"
"github.com/stakater/Reloader/internal/pkg/crypto"
"github.com/stakater/Reloader/internal/pkg/options"
v1 "k8s.io/api/core/v1"
csiv1 "sigs.k8s.io/secrets-store-csi-driver/apis/v1"
)
// ConvertToEnvVarName converts the given text into a usable env var

View File

@@ -3,8 +3,9 @@ package util
import (
"testing"
"github.com/stakater/Reloader/internal/pkg/options"
v1 "k8s.io/api/core/v1"
"github.com/stakater/Reloader/internal/pkg/options"
)
func TestConvertToEnvVarName(t *testing.T) {