Skip to content

Commit 679390a

Browse files
danpetitclercDanny Petitclerccolinhoglund
authored
INFRA-3884 (#17)
* prevent helm namespace from overriding namespace flag * update makefile to enable local tests * fix failing unit tests * update hardcoded vars * update some more tests * update deprecated pkg * update tests * update plugin version * update makefile * fmt * Update cmd/ksec/main.go Co-authored-by: Colin Hoglund <colinhoglund@users.noreply.github.com> * add namespace check back * update mocks to check for empty config namespace * update dependent test --------- Co-authored-by: Danny Petitclerc <danny.petitclerc@mongodb.com> Co-authored-by: Colin Hoglund <colinhoglund@users.noreply.github.com>
1 parent 83717d3 commit 679390a

File tree

7 files changed

+177
-106
lines changed

7 files changed

+177
-106
lines changed

Makefile

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,11 @@ test:
1717
build:
1818
go install ./cmd/ksec/
1919

20+
.PHONY: install-plugin-local
21+
install-plugin-local: build
22+
helm plugin remove $(CMD_NAME) || true
23+
HELM_PLUGIN_BUILD_SOURCE=1 helm plugin install $(shell pwd)
24+
2025
.PHONY: dist
2126
dist: dist-setup dist-linux dist-darwin dist-windows ## Cross compile binaries into ./dist/
2227

cmd/ksec/main.go

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,14 @@ func NewRootCmd() *cobra.Command {
5757
Version: version.Get().Version,
5858
PersistentPreRun: func(cmd *cobra.Command, args []string) {
5959
var err error
60-
secretsClient, err = models.NewSecretsClient(viper.GetString("namespace"))
60+
namespace := viper.GetString("namespace")
61+
62+
// sets namespace when used as a helm plugin since helm hijacks the "--namespace" flag.
63+
if namespace == "" && os.Getenv("HELM_NAMESPACE") != "" {
64+
namespace = os.Getenv("HELM_NAMESPACE")
65+
}
66+
67+
secretsClient, err = models.NewSecretsClient(namespace)
6168
if err != nil {
6269
log.Fatal(err.Error())
6370
}

cmd/ksec/main_test.go

Lines changed: 40 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,13 @@ package main
33
import (
44
"bufio"
55
"context"
6-
"io/ioutil"
76
"os"
87
"strings"
98
"testing"
109

1110
"github.com/kanopy-platform/ksec/pkg/models"
1211
"github.com/spf13/cobra"
12+
"github.com/stretchr/testify/assert"
1313
)
1414

1515
// mock rootCmd
@@ -21,113 +21,102 @@ func TestMain(m *testing.M) {
2121
Short: "A tool for managing Kubernetes Secret data",
2222
}
2323
initRootCmd(rootCmd)
24-
secretsClient = models.MockNewSecretsClient()
24+
mockConfig := models.MockClientConfig()
25+
secretsClient, _ = models.MockNewSecretsClient(mockConfig, "default")
2526
os.Exit(m.Run())
26-
27-
}
28-
29-
// helpers
30-
func testErr(err error, t *testing.T) {
31-
if err != nil {
32-
t.Fatal(err)
33-
}
3427
}
3528

3629
func cmdExec(args []string) error {
3730
rootCmd.SetArgs(args)
38-
if err := rootCmd.Execute(); err != nil {
39-
return err
40-
}
41-
return nil
31+
return rootCmd.Execute()
4232
}
4333

4434
// tests
4535
func TestCreateSecret(t *testing.T) {
4636
ctx := context.Background()
4737

4838
err := cmdExec([]string{"create", "test"})
49-
testErr(err, t)
39+
assert.NoError(t, err, "Creating secret should not return an error")
5040

5141
err = cmdExec([]string{"set", "test", "key=value"})
52-
testErr(err, t)
42+
assert.NoError(t, err, "Setting secret key should not return an error")
5343

5444
secret, err := secretsClient.Get(ctx, "test")
55-
testErr(err, t)
45+
assert.NoError(t, err, "Getting secret should not return an error")
46+
assert.NotNil(t, secret, "Secret should not be nil")
5647

5748
val, ok := secret.Data["key"]
58-
if !ok {
59-
t.Fatal("Key does not exist")
60-
} else if string(val) != "value" {
61-
t.Fatal("Key has incorrect value")
62-
}
49+
assert.True(t, ok, "Key should exist in secret data")
50+
assert.Equal(t, "value", string(val), "Key should have the correct value")
6351
}
6452

6553
func TestUnsetSecretKey(t *testing.T) {
6654
ctx := context.Background()
55+
6756
err := cmdExec([]string{"unset", "test", "key"})
68-
testErr(err, t)
57+
assert.NoError(t, err, "Unsetting secret key should not return an error")
6958

7059
secret, err := secretsClient.Get(ctx, "test")
71-
testErr(err, t)
60+
assert.NoError(t, err, "Getting secret should not return an error")
61+
assert.NotNil(t, secret, "Secret should not be nil")
7262

73-
if _, ok := secret.Data["key"]; ok {
74-
t.Fatal("Key should not exist")
75-
}
63+
_, ok := secret.Data["key"]
64+
assert.False(t, ok, "Key should not exist in secret data")
7665
}
7766

7867
func TestDeleteSecret(t *testing.T) {
7968
err := cmdExec([]string{"delete", "test", "--yes"})
80-
testErr(err, t)
69+
assert.NoError(t, err, "Deleting secret should not return an error")
8170

8271
err = cmdExec([]string{"get", "test"})
83-
if !strings.HasSuffix(err.Error(), "not found") {
84-
t.Fatal("Secret still exists")
85-
}
72+
assert.Error(t, err, "Getting deleted secret should return an error")
73+
assert.True(t, strings.HasSuffix(err.Error(), "not found"), "Error should indicate that the secret was not found")
8674
}
8775

8876
func TestPushSecret(t *testing.T) {
8977
ctx := context.Background()
9078
content := []byte("ENV_VAR=secret")
91-
tempfile, err := ioutil.TempFile("", "ksec")
92-
testErr(err, t)
79+
80+
tempfile, err := os.CreateTemp("", "ksec")
81+
assert.NoError(t, err, "Creating temp file should not return an error")
9382
defer os.Remove(tempfile.Name())
9483

9584
_, err = tempfile.Write(content)
96-
testErr(err, t)
85+
assert.NoError(t, err, "Writing to temp file should not return an error")
9786

9887
err = cmdExec([]string{"push", tempfile.Name(), "pushtest"})
99-
testErr(err, t)
88+
assert.NoError(t, err, "Pushing secret should not return an error")
10089

10190
secret, err := secretsClient.Get(ctx, "pushtest")
102-
testErr(err, t)
91+
assert.NoError(t, err, "Getting pushed secret should not return an error")
92+
assert.NotNil(t, secret, "Pushed secret should not be nil")
10393

10494
val, ok := secret.Data["ENV_VAR"]
105-
if !ok {
106-
t.Fatal("Key does not exist")
107-
} else if string(val) != "secret" {
108-
t.Fatal("Key has incorrect value")
109-
}
95+
assert.True(t, ok, "ENV_VAR key should exist in pushed secret data")
96+
assert.Equal(t, "secret", string(val), "ENV_VAR key should have the correct value")
11097

11198
err = tempfile.Close()
112-
testErr(err, t)
99+
assert.NoError(t, err, "Closing temp file should not return an error")
113100
}
114101

115102
func TestPullSecret(t *testing.T) {
116-
tempfile, err := ioutil.TempFile("", "ksec")
117-
testErr(err, t)
103+
tempfile, err := os.CreateTemp("", "ksec")
104+
assert.NoError(t, err, "Creating temp file should not return an error")
118105
defer os.Remove(tempfile.Name())
119106

120107
err = cmdExec([]string{"set", "pulltest", "ENV_VAR=secret"})
121-
testErr(err, t)
108+
assert.NoError(t, err, "Setting secret should not return an error")
122109

123110
err = cmdExec([]string{"pull", "pulltest", tempfile.Name()})
124-
testErr(err, t)
111+
assert.NoError(t, err, "Pulling secret should not return an error")
112+
113+
file, err := os.Open(tempfile.Name())
114+
assert.NoError(t, err, "Opening temp file should not return an error")
115+
defer file.Close()
125116

126-
reader := bufio.NewReader(tempfile)
117+
reader := bufio.NewReader(file)
127118
line, _, err := reader.ReadLine()
128-
testErr(err, t)
119+
assert.NoError(t, err, "Reading line from temp file should not return an error")
129120

130-
if string(line) != "ENV_VAR=secret" {
131-
t.Fatal("File does not contain pulled contents")
132-
}
121+
assert.Equal(t, "ENV_VAR=secret", string(line), "File should contain the pulled secret contents")
133122
}

pkg/models/secrets_client_test.go

Lines changed: 90 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -4,110 +4,152 @@ import (
44
"context"
55
"strings"
66
"testing"
7+
8+
"github.com/stretchr/testify/assert"
79
)
810

911
var secretsClient *SecretsClient
10-
11-
// helpers
12-
func testErr(err error, t *testing.T) {
13-
if err != nil {
14-
t.Fatal(err.Error())
15-
}
12+
var expectedSecretName = "test-secret"
13+
var defaultNamespace = "default"
14+
var err error
15+
16+
// setupTestClient initializes a new secretsClient before each test
17+
func setupTestClient(namespace string) {
18+
mockConfig := MockClientConfig()
19+
secretsClient, err = MockNewSecretsClient(mockConfig, namespace)
1620
}
1721

18-
// unit tests
1922
func TestNewSecretsClient(t *testing.T) {
20-
secretsClient = MockNewSecretsClient()
23+
setupTestClient(defaultNamespace)
24+
25+
assert.NoError(t, err)
26+
assert.Equal(t, defaultNamespace, secretsClient.Namespace)
27+
assert.Equal(t, "testuser", secretsClient.AuthInfo)
28+
assert.NotNil(t, secretsClient.secretInterface)
29+
}
30+
31+
func TestNewSecretsClientUndefinedNamespace(t *testing.T) {
32+
// undefined namespace, expected to fail
33+
setupTestClient("")
34+
assert.Error(t, err)
2135
}
2236

2337
func TestCreate(t *testing.T) {
38+
setupTestClient(defaultNamespace)
2439
ctx := context.Background()
25-
_, err := secretsClient.Create(ctx, "test-secret")
26-
testErr(err, t)
40+
41+
secret, err := secretsClient.Create(ctx, expectedSecretName)
42+
assert.NoError(t, err, "Creating secret should not return an error")
43+
44+
assert.NotNil(t, secret, "Created secret should not be nil")
45+
assert.Equal(t, secret.Name, expectedSecretName)
2746
}
2847

2948
func TestList(t *testing.T) {
49+
setupTestClient(defaultNamespace)
3050
ctx := context.Background()
31-
secrets, err := secretsClient.List(ctx)
32-
testErr(err, t)
3351

34-
if secrets.Items[0].Name != "test-secret" {
35-
t.Fatal(err.Error())
36-
}
52+
_, err := secretsClient.Create(ctx, expectedSecretName)
53+
assert.NoError(t, err, "Creating secret should not return an error")
54+
55+
secrets, err := secretsClient.List(ctx)
56+
assert.NoError(t, err, "Listing secrets should not return an error")
57+
assert.NotEmpty(t, secrets.Items, "Secrets list should not be empty")
58+
assert.Equal(t, expectedSecretName, secrets.Items[0].Name, "First secret name should be %s", expectedSecretName)
3759
}
3860

3961
func TestCreateWithData(t *testing.T) {
62+
setupTestClient(defaultNamespace)
63+
ctx := context.Background()
64+
4065
dataArgs := []string{
4166
"key=value",
4267
"secret-key=secret-value",
4368
"ENV_VAR=~!@#$%^&*()_+",
4469
"DB_URL=mongodb://host1.example.com:27017,host2.example.com:27017/prod?replicaSet=prod",
4570
}
71+
4672
data := make(map[string][]byte)
4773

4874
for _, item := range dataArgs {
4975
split := strings.SplitN(item, "=", 2)
50-
if len(split) != 2 {
51-
t.Errorf("Data is not formatted correctly: %s", item)
52-
}
76+
assert.Len(t, split, 2, "Data is not formatted correctly")
5377
data[split[0]] = []byte(split[1])
5478
}
5579

56-
ctx := context.Background()
57-
_, err := secretsClient.CreateWithData(ctx, "test-secret-with-data", data)
58-
testErr(err, t)
80+
secret, err := secretsClient.CreateWithData(ctx, expectedSecretName, data)
81+
assert.NoError(t, err, "Creating secret with data should not return an error")
82+
83+
assert.NotNil(t, secret.Data, "Created secret with data should not be nil")
84+
assert.Equal(t, data, secret.Data)
5985
}
6086

6187
func TestGet(t *testing.T) {
88+
setupTestClient(defaultNamespace)
6289
ctx := context.Background()
63-
secret, err := secretsClient.Get(ctx, "test-secret-with-data")
64-
testErr(err, t)
6590

66-
if string(secret.Data["DB_URL"]) != "mongodb://host1.example.com:27017,host2.example.com:27017/prod?replicaSet=prod" {
67-
t.Fatal(err.Error())
68-
}
91+
_, err := secretsClient.CreateWithData(ctx, expectedSecretName, map[string][]byte{
92+
"DB_URL": []byte("mongodb://host1.example.com:27017,host2.example.com:27017/prod?replicaSet=prod"),
93+
})
94+
assert.NoError(t, err, "Creating secret with data should not return an error")
95+
96+
secret, err := secretsClient.Get(ctx, expectedSecretName)
97+
assert.NoError(t, err, "Getting secret should not return an error")
98+
assert.Equal(t, "mongodb://host1.example.com:27017,host2.example.com:27017/prod?replicaSet=prod", string(secret.Data["DB_URL"]), "DB_URL should match the expected value")
6999
}
70100

71101
func TestGetKey(t *testing.T) {
102+
setupTestClient(defaultNamespace)
72103
ctx := context.Background()
73-
value, err := secretsClient.GetKey(ctx, "test-secret-with-data", "secret-key")
74-
testErr(err, t)
75104

76-
if value != "secret-value" {
77-
t.Fatal(err.Error())
78-
}
105+
_, err := secretsClient.CreateWithData(ctx, expectedSecretName, map[string][]byte{
106+
"secret-key": []byte("secret-value"),
107+
})
108+
assert.NoError(t, err, "Creating secret with data should not return an error")
79109

80-
value, err = secretsClient.GetKey(ctx, "test-secret-with_data", "thiskeydoesnotexist")
81-
if err == nil {
82-
t.Fatal("non-existent key should have received an error")
83-
}
110+
value, err := secretsClient.GetKey(ctx, expectedSecretName, "secret-key")
111+
assert.NoError(t, err, "Getting secret key should not return an error")
112+
assert.Equal(t, "secret-value", value, "Secret key value should match the expected value")
113+
114+
value, err = secretsClient.GetKey(ctx, expectedSecretName, "thiskeydoesnotexist")
115+
assert.Error(t, err, "Getting a non-existent key should return an error")
116+
assert.Empty(t, value, "Non-existent key should return an empty value")
84117
}
85118

86119
func TestUpdate(t *testing.T) {
120+
setupTestClient(defaultNamespace)
87121
ctx := context.Background()
88-
secret, err := secretsClient.Get(ctx, "test-secret-with-data")
89-
testErr(err, t)
122+
123+
secret, err := secretsClient.CreateWithData(ctx, expectedSecretName, map[string][]byte{
124+
"key": []byte("oldvalue"),
125+
})
126+
assert.NoError(t, err, "Creating secret with data should not return an error")
90127

91128
data := map[string][]byte{
92129
"key": []byte("newvalue"),
93130
}
94131

95-
secretsClient.Update(ctx, secret, data)
96-
97-
if string(secret.Data["key"]) != "newvalue" {
98-
t.Fatal(err.Error())
99-
}
132+
secret, err = secretsClient.Update(ctx, secret, data)
133+
assert.NoError(t, err, "Updating secret should not return an error")
134+
assert.Equal(t, "newvalue", string(secret.Data["key"]), "Key value should be updated to 'newvalue'")
100135
}
101136

102137
func TestUpsert(t *testing.T) {
138+
setupTestClient(defaultNamespace)
139+
ctx := context.Background()
140+
103141
data := map[string][]byte{
104142
"key": []byte("upsert"),
105143
}
106-
ctx := context.Background()
107-
secret, err := secretsClient.Upsert(ctx, "upsert-secret", data)
108-
testErr(err, t)
109144

110-
if string(secret.Data["key"]) != "upsert" {
111-
t.Fatal(err.Error())
112-
}
145+
// First upsert (should create the secret)
146+
secret, err := secretsClient.Upsert(ctx, expectedSecretName, data)
147+
assert.NoError(t, err, "Upserting (creating) secret should not return an error")
148+
assert.Equal(t, "upsert", string(secret.Data["key"]), "Key value should be 'upsert'")
149+
150+
// Second upsert (should update the secret)
151+
data["key"] = []byte("upserted")
152+
secret, err = secretsClient.Upsert(ctx, expectedSecretName, data)
153+
assert.NoError(t, err, "Upserting (updating) secret should not return an error")
154+
assert.Equal(t, "upserted", string(secret.Data["key"]), "Key value should be 'upserted'")
113155
}

0 commit comments

Comments
 (0)