Skip to content

Commit

Permalink
fix: parse secret envs (#14)
Browse files Browse the repository at this point in the history
Signed-off-by: Xuhui zhang <[email protected]>
  • Loading branch information
zxh326 authored Dec 17, 2024
1 parent e62edc7 commit 7953d60
Show file tree
Hide file tree
Showing 4 changed files with 209 additions and 2 deletions.
22 changes: 20 additions & 2 deletions pkg/builder/pod.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import (
"context"
"fmt"
"regexp"
"sort"
"strings"
"time"

Expand Down Expand Up @@ -124,8 +125,22 @@ func newBasicPod(cg *juicefsiov1.CacheGroup, nodeName string) *corev1.Pod {
return worker
}

func (p *PodBuilder) genEnvs() []corev1.EnvVar {
func (p *PodBuilder) genEnvs(ctx context.Context) []corev1.EnvVar {
envs := []corev1.EnvVar{}
if v, ok := p.secretData["envs"]; ok && v != "" {
secretEnvs, err := utils.ParseYamlOrJson(v)
if err != nil {
log.FromContext(ctx).Error(err, "failed to parse envs, will ignore", "envs", v)
} else {
for k, v := range secretEnvs {
envs = append(envs, corev1.EnvVar{
Name: k,
Value: fmt.Sprint(v),
})
}
}
}

for _, k := range secretStrippedEnvs {
_, isOptional := secretStrippedEnvOptional[k]
envs = append(envs, corev1.EnvVar{
Expand All @@ -142,6 +157,9 @@ func (p *PodBuilder) genEnvs() []corev1.EnvVar {
})
}
envs = append(envs, p.spec.Env...)
sort.SliceStable(envs, func(i, j int) bool {
return envs[i].Name < envs[j].Name
})
return envs
}

Expand Down Expand Up @@ -359,7 +377,7 @@ func (p *PodBuilder) NewCacheGroupWorker(ctx context.Context) *corev1.Pod {
} else {
worker.Spec.Containers[0].Resources = common.DefaultResources
}
worker.Spec.Containers[0].Env = p.genEnvs()
worker.Spec.Containers[0].Env = p.genEnvs(ctx)
worker.Spec.Containers[0].Command = p.genCommands(ctx)

hash := utils.GenHash(worker)
Expand Down
113 changes: 113 additions & 0 deletions pkg/builder/pod_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import (

juicefsiov1 "github.com/juicedata/juicefs-cache-group-operator/api/v1"
"github.com/juicedata/juicefs-cache-group-operator/pkg/common"
"github.com/juicedata/juicefs-cache-group-operator/pkg/utils"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
Expand Down Expand Up @@ -225,3 +226,115 @@ func TestUpdateWorkerGroupWeight(t *testing.T) {
})
}
}

func TestPodBuilder_genEnvs(t *testing.T) {
tests := []struct {
name string
podBuilder *PodBuilder
expected []corev1.EnvVar
}{
{
name: "basic envs",
podBuilder: &PodBuilder{
cg: &juicefsiov1.CacheGroup{
Spec: juicefsiov1.CacheGroupSpec{
SecretRef: &corev1.SecretEnvSource{
LocalObjectReference: corev1.LocalObjectReference{
Name: "test-secret",
},
},
},
},
secretData: map[string]string{
"envs": `{"ENV1": "value1", "ENV2": "value2"}`,
},
},
expected: []corev1.EnvVar{
{Name: "ENV1", Value: "value1"},
{Name: "ENV2", Value: "value2"},
{Name: "SECRET_KEY", ValueFrom: &corev1.EnvVarSource{
SecretKeyRef: &corev1.SecretKeySelector{
Key: "secret-key",
Optional: utils.ToPtr(false),
LocalObjectReference: corev1.LocalObjectReference{
Name: "test-secret",
},
},
}},
{Name: "SECRET_KEY_2", ValueFrom: &corev1.EnvVarSource{
SecretKeyRef: &corev1.SecretKeySelector{
Key: "secret-key2",
Optional: utils.ToPtr(true),
LocalObjectReference: corev1.LocalObjectReference{
Name: "test-secret",
},
},
}},
{Name: "TOKEN", ValueFrom: &corev1.EnvVarSource{
SecretKeyRef: &corev1.SecretKeySelector{
Key: "token",
Optional: utils.ToPtr(false),
LocalObjectReference: corev1.LocalObjectReference{
Name: "test-secret",
},
},
}},
},
},
{
name: "no envs in secretData",
podBuilder: &PodBuilder{
cg: &juicefsiov1.CacheGroup{
Spec: juicefsiov1.CacheGroupSpec{
SecretRef: &corev1.SecretEnvSource{
LocalObjectReference: corev1.LocalObjectReference{
Name: "test-secret",
},
},
},
},
secretData: map[string]string{},
spec: juicefsiov1.CacheGroupWorkerTemplate{},
},
expected: []corev1.EnvVar{
{Name: "SECRET_KEY", ValueFrom: &corev1.EnvVarSource{
SecretKeyRef: &corev1.SecretKeySelector{
Key: "secret-key",
Optional: utils.ToPtr(false),
LocalObjectReference: corev1.LocalObjectReference{
Name: "test-secret",
},
},
}},
{Name: "SECRET_KEY_2", ValueFrom: &corev1.EnvVarSource{
SecretKeyRef: &corev1.SecretKeySelector{
Key: "secret-key2",
Optional: utils.ToPtr(true),
LocalObjectReference: corev1.LocalObjectReference{
Name: "test-secret",
},
},
}},
{Name: "TOKEN", ValueFrom: &corev1.EnvVarSource{
SecretKeyRef: &corev1.SecretKeySelector{
Key: "token",
Optional: utils.ToPtr(false),
LocalObjectReference: corev1.LocalObjectReference{
Name: "test-secret",
},
},
}},
},
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
ctx := context.TODO()
got := tt.podBuilder.genEnvs(ctx)
if !reflect.DeepEqual(got, tt.expected) {
t.Errorf("genEnvs() = %v, want %v", got, tt.expected)
}
})
}
}
11 changes: 11 additions & 0 deletions pkg/utils/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import (

"github.com/juicedata/juicefs-cache-group-operator/pkg/common"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/util/yaml"
)

func ToPtr[T any](v T) *T {
Expand Down Expand Up @@ -111,3 +112,13 @@ func GetBackupWorkerDuration(d *metav1.Duration) time.Duration {
}
return d.Duration
}

func ParseYamlOrJson(source string) (map[string]interface{}, error) {
dst := make(map[string]interface{})
if err := json.Unmarshal([]byte(source), &dst); err != nil {
if err := yaml.Unmarshal([]byte(source), &dst); err != nil {
return nil, err
}
}
return dst, nil
}
65 changes: 65 additions & 0 deletions pkg/utils/utils_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -144,3 +144,68 @@ func TestCompareImageVersion(t *testing.T) {
})
}
}

func TestParseYamlOrJson(t *testing.T) {
tests := []struct {
name string
source string
want map[string]interface{}
wantErr bool
}{
{
name: "Test with valid JSON",
source: `{"key1": "value1", "key2": "value2"}`,
want: map[string]interface{}{
"key1": "value1",
"key2": "value2",
},
wantErr: false,
},
{
name: "Test with valid YAML",
source: "key1: value1\nkey2: value2\n",
want: map[string]interface{}{
"key1": "value1",
"key2": "value2",
},
wantErr: false,
},
{
name: "Test with invalid JSON and YAML",
source: `{"key1": "value1", "key2": "value2"`,
want: nil,
wantErr: true,
},
{
name: "Test with empty source",
source: ``,
want: map[string]interface{}{},
wantErr: false,
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got, err := ParseYamlOrJson(tt.source)
if (err != nil) != tt.wantErr {
t.Errorf("ParseYamlOrJson() error = %v, wantErr = %v", err, tt.wantErr)
return
}
if !tt.wantErr && !equalMaps(got, tt.want) {
t.Errorf("ParseYamlOrJson() = %v, want = %v", got, tt.want)
}
})
}
}

func equalMaps(a, b map[string]interface{}) bool {
if len(a) != len(b) {
return false
}
for k, v := range a {
if b[k] != v {
return false
}
}
return true
}

0 comments on commit 7953d60

Please sign in to comment.