mirror of
https://github.com/stakater/Reloader.git
synced 2026-05-17 06:06:39 +00:00
359 lines
9.2 KiB
Go
359 lines
9.2 KiB
Go
package handler
|
|
|
|
import (
|
|
"testing"
|
|
|
|
"github.com/stakater/Reloader/internal/pkg/constants"
|
|
"github.com/stakater/Reloader/internal/pkg/metrics"
|
|
"github.com/stretchr/testify/assert"
|
|
v1 "k8s.io/api/core/v1"
|
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
|
)
|
|
|
|
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) {
|
|
// Test that annotations are properly captured in config
|
|
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) {
|
|
// Test that labels are properly captured in config
|
|
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, // logs error but returns nil
|
|
},
|
|
{
|
|
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) {
|
|
// Test that same data produces same SHA
|
|
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()
|
|
|
|
// Same data should produce same SHA
|
|
assert.Equal(t, config1.SHAValue, config2.SHAValue)
|
|
}
|
|
|
|
func TestResourceCreatedHandler_SHADifference(t *testing.T) {
|
|
// Test that different data produces different SHA
|
|
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()
|
|
|
|
// Different data should produce different SHA
|
|
assert.NotEqual(t, config1.SHAValue, config2.SHAValue)
|
|
}
|