Skip to content

Commit 824d796

Browse files
feat: Add utility function to check for duplicates in environment variables
PiperOrigin-RevId: 817616522
1 parent 36570e0 commit 824d796

File tree

2 files changed

+138
-1
lines changed

2 files changed

+138
-1
lines changed

packages/cdenv/cdenv.go

Lines changed: 41 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,12 @@
1-
// Package cdenv contains Cloud Deploy environment variable keys.
1+
// Package cdenv contains Cloud Deploy environment variable keys and utility functions for environment
2+
// variables.
23
package cdenv
34

5+
import (
6+
"fmt"
7+
"strings"
8+
)
9+
410
// Cloud Deploy environment variable keys.
511
const (
612
RequestTypeEnvKey = "CLOUD_DEPLOY_REQUEST_TYPE"
@@ -30,3 +36,37 @@ const (
3036
CloudBuildServiceAccount = "CLOUD_DEPLOY_WP_CB_ServiceAccount"
3137
CloudBuildWorkerPool = "CLOUD_DEPLOY_WP_CB_WorkerPool"
3238
)
39+
40+
// CheckDuplicates expects environment variables in the k=v format. It
41+
// converts the environment string slice to a map and checks for duplicates
42+
// and malformed entries.
43+
func CheckDuplicates(environ []string) (map[string]string, error) {
44+
envMap := make(map[string]string)
45+
46+
if len(environ) == 0 {
47+
return nil, fmt.Errorf("no environment variables found")
48+
}
49+
50+
for _, envVar := range environ {
51+
pair := strings.SplitN(envVar, "=", 2)
52+
if len(pair) != 2 {
53+
return nil, fmt.Errorf("incorrect env variable format - expected k=v")
54+
}
55+
56+
key := pair[0]
57+
value := pair[1]
58+
if key == "" {
59+
return nil, fmt.Errorf("empty environment variable key")
60+
}
61+
62+
if value == "" {
63+
return nil, fmt.Errorf("empty environment variable value")
64+
}
65+
66+
if _, exists := envMap[strings.ToLower(key)]; exists {
67+
return nil, fmt.Errorf("duplicate environment variable key: %s", key)
68+
}
69+
envMap[strings.ToLower(key)] = value
70+
}
71+
return envMap, nil
72+
}

packages/cdenv/cdenv_test.go

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
package cdenv
2+
3+
import (
4+
"testing"
5+
6+
"github.com/google/go-cmp/cmp"
7+
)
8+
9+
func TestCheckDuplicatesValid(t *testing.T) {
10+
tests := []struct {
11+
name string
12+
envVars []string
13+
wantVars map[string]string
14+
}{
15+
{
16+
name: "Valid environment variables",
17+
envVars: []string{
18+
"KEY1=VALUE1",
19+
"KEY2=VALUE2",
20+
},
21+
wantVars: map[string]string{
22+
"key1": "VALUE1",
23+
"key2": "VALUE2",
24+
},
25+
},
26+
}
27+
28+
for _, test := range tests {
29+
t.Run(test.name, func(t *testing.T) {
30+
vars, err := CheckDuplicates(test.envVars)
31+
if err != nil {
32+
t.Errorf("checkDuplicates() error = %v", err)
33+
}
34+
if diff := cmp.Diff(vars, test.wantVars); diff != "" {
35+
t.Errorf("checkDuplicates() mismatch (-want +got):\n%s", diff)
36+
}
37+
})
38+
}
39+
}
40+
41+
func TestCheckDuplicatesInvalid(t *testing.T) {
42+
tests := []struct {
43+
name string
44+
envVars []string
45+
}{
46+
{
47+
name: "Empty environment variables",
48+
envVars: []string{
49+
"",
50+
"",
51+
},
52+
},
53+
{
54+
name: "Duplicate environment variable with same case",
55+
envVars: []string{
56+
"KEY1=VALUE1",
57+
"KEY1=VALUE2",
58+
},
59+
},
60+
{
61+
name: "Duplicate environment variable with different cases",
62+
envVars: []string{
63+
"KEY1=VALUE1",
64+
"key1=VALUE2",
65+
},
66+
},
67+
{
68+
name: "Empty environment variable value",
69+
envVars: []string{
70+
"KEY1VALUE1=",
71+
"KEY2=VALUE2",
72+
},
73+
},
74+
{
75+
name: "Empty environment variable key",
76+
envVars: []string{
77+
"=KEY1VALUE1",
78+
"KEY2=VALUE2",
79+
},
80+
},
81+
{
82+
name: "Incorrect env variable format - expected k=v",
83+
envVars: []string{
84+
"KEY1VALUE1",
85+
"KEY2=VALUE2",
86+
},
87+
},
88+
}
89+
for _, test := range tests {
90+
t.Run(test.name, func(t *testing.T) {
91+
_, err := CheckDuplicates(test.envVars)
92+
if err == nil {
93+
t.Errorf("checkDuplicates() error = nil, want error")
94+
}
95+
})
96+
}
97+
}

0 commit comments

Comments
 (0)