Skip to content

Commit cb8ba78

Browse files
hoffmtonglil
andauthored
Sanitize namespace flag consistently (#220)
Co-authored-by: Tony Li <[email protected]>
1 parent 976c869 commit cb8ba78

File tree

2 files changed

+90
-22
lines changed

2 files changed

+90
-22
lines changed

main.go

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -381,13 +381,22 @@ func checkParams(c *cli.Context) error {
381381
return fmt.Errorf("Missing required param: cluster")
382382
}
383383

384+
namespace := c.String("namespace")
385+
c.Set("namespace", sanitizeNamespace(namespace))
386+
384387
if err := validateKubectlVersion(c, extraKubectlVersions); err != nil {
385388
return err
386389
}
387390

388391
return nil
389392
}
390393

394+
func sanitizeNamespace(namespace string) string {
395+
namespace = strings.ToLower(namespace)
396+
namespace = invalidNameRegex.ReplaceAllString(namespace, "-")
397+
return namespace
398+
}
399+
391400
// validateKubectlVersion tests whether a given version is valid within the current environment
392401
func validateKubectlVersion(c *cli.Context, availableVersions []string) error {
393402
kubectlVersionParam := c.String("kubectl-version")
@@ -729,10 +738,6 @@ func setNamespace(c *cli.Context, project string, runner Runner) error {
729738
return nil
730739
}
731740

732-
//replace invalid char in namespace
733-
namespace = strings.ToLower(namespace)
734-
namespace = invalidNameRegex.ReplaceAllString(namespace, "-")
735-
736741
// Set the execution namespace.
737742
log("Configuring kubectl to the %s namespace\n", namespace)
738743

main_test.go

Lines changed: 81 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ import (
44
"bytes"
55
"flag"
66
"fmt"
7-
"io/ioutil"
87
"os"
98
"strconv"
109
"strings"
@@ -73,6 +72,17 @@ func TestCheckParams(t *testing.T) {
7372
set.String("cluster", "cluster-0", "")
7473
err = checkParams(c)
7574
assert.NoError(t, err)
75+
76+
// Sanitizes namespace
77+
set = flag.NewFlagSet("namespace-sanitize", 0)
78+
c = cli.NewContext(nil, set, nil)
79+
set.String("token", "{}", "")
80+
set.String("region", "us-west1", "")
81+
set.String("cluster", "cluster-0", "")
82+
set.String("namespace", "feature/1892-TEST-NS", "")
83+
err = checkParams(c)
84+
assert.NoError(t, err)
85+
assert.Equal(t, "feature-1892-test-ns", c.String("namespace"))
7686
}
7787

7888
func TestValidateKubectlVersion(t *testing.T) {
@@ -197,7 +207,8 @@ func TestFetchCredentials(t *testing.T) {
197207
assert.NoError(t, regionalErr)
198208

199209
// Verify token file
200-
buf, err := ioutil.ReadFile("/tmp/gcloud.json")
210+
buf, err := os.ReadFile("/tmp/gcloud.json")
211+
assert.NoError(t, err)
201212
assert.Equal(t, "{\"key\", \"val\"}", string(buf))
202213

203214
// Run() error
@@ -259,13 +270,13 @@ func TestTemplateData(t *testing.T) {
259270

260271
// Variable overrides existing ones
261272
vars = map[string]interface{}{"zone": "us-east4-b"}
262-
tmplData, secretsData, secretsDataRedacted, err = templateData(c, "us-east1-b", vars, secrets)
273+
_, _, _, err = templateData(c, "us-east1-b", vars, secrets)
263274
assert.Error(t, err)
264275

265276
// Secret overrides variable
266277
vars = map[string]interface{}{"SECRET_TEST": "val0"}
267278
secrets = map[string]string{"SECRET_TEST": "test_val"}
268-
tmplData, secretsData, secretsDataRedacted, err = templateData(c, "us-east1-b", vars, secrets)
279+
_, _, _, err = templateData(c, "us-east1-b", vars, secrets)
269280
assert.Error(t, err)
270281
}
271282

@@ -324,19 +335,20 @@ func TestTemplateDataExpandingVars(t *testing.T) {
324335

325336
// Variable overrides existing ones
326337
vars = map[string]interface{}{"zone": "us-east4-b"}
327-
tmplData, secretsData, secretsDataRedacted, err = templateData(c, "us-east1-b", vars, secrets)
338+
_, _, _, err = templateData(c, "us-east1-b", vars, secrets)
328339
assert.Error(t, err)
329340

330341
// Secret overrides variable
331342
vars = map[string]interface{}{"SECRET_TEST": "val0"}
332343
secrets = map[string]string{"SECRET_TEST": "test_val"}
333-
tmplData, secretsData, secretsDataRedacted, err = templateData(c, "us-east1-b", vars, secrets)
344+
_, _, _, err = templateData(c, "us-east1-b", vars, secrets)
334345
assert.Error(t, err)
335346
}
336347

337348
func TestRenderTemplates(t *testing.T) {
338349
// Mkdir for testing template files
339-
os.MkdirAll("/tmp/drone-gke-tests/", os.ModePerm)
350+
err := os.MkdirAll("/tmp/drone-gke-tests/", os.ModePerm)
351+
assert.NoError(t, err)
340352
kubeTemplatePath := "/tmp/drone-gke-tests/.kube.yml"
341353
secretTemplatePath := "/tmp/drone-gke-tests/.kube.sec.yml"
342354

@@ -359,32 +371,35 @@ func TestRenderTemplates(t *testing.T) {
359371
// No template file, should error
360372
os.Remove(kubeTemplatePath)
361373
os.Remove(secretTemplatePath)
362-
_, err := renderTemplates(c, tmplData, secretsData)
374+
_, err = renderTemplates(c, tmplData, secretsData)
363375
assert.Error(t, err)
364376

365377
// Normal
366378
// Create test template files
367379
tmplBuf := []byte("{{.COMMIT}}-{{.key0}}")
368-
err = ioutil.WriteFile(kubeTemplatePath, tmplBuf, 0600)
380+
err = os.WriteFile(kubeTemplatePath, tmplBuf, 0600)
369381
assert.NoError(t, err)
370382
tmplBuf = []byte("{{.COMMIT}}-{{.SECRET_TEST}}")
371-
err = ioutil.WriteFile(secretTemplatePath, tmplBuf, 0600)
383+
err = os.WriteFile(secretTemplatePath, tmplBuf, 0600)
372384
assert.NoError(t, err)
373385

374386
// Render
375387
manifestPaths, err := renderTemplates(c, tmplData, secretsData)
376388
assert.NoError(t, err)
377389

378390
// Verify token files
379-
buf, err := ioutil.ReadFile(manifestPaths[kubeTemplatePath])
391+
buf, err := os.ReadFile(manifestPaths[kubeTemplatePath])
392+
assert.NoError(t, err)
380393
assert.Equal(t, "e0f21b90a-val0", string(buf))
381394

382-
buf, err = ioutil.ReadFile(manifestPaths[secretTemplatePath])
395+
buf, err = os.ReadFile(manifestPaths[secretTemplatePath])
396+
assert.NoError(t, err)
383397
assert.Equal(t, "e0f21b90a-test_sec_val", string(buf))
384398

385399
// Secret variables shouldn't be available in kube template
386400
tmplBuf = []byte("{{.SECRET_TEST}}")
387-
err = ioutil.WriteFile(kubeTemplatePath, tmplBuf, 0600)
401+
err = os.WriteFile(kubeTemplatePath, tmplBuf, 0600)
402+
assert.NoError(t, err)
388403
_, err = renderTemplates(c, tmplData, secretsData)
389404
assert.Error(t, err)
390405
}
@@ -475,14 +490,15 @@ func TestSetNamespace(t *testing.T) {
475490
assert.NoError(t, err)
476491

477492
// Verify written file
478-
buf, err := ioutil.ReadFile("/tmp/namespace.json")
493+
buf, err := os.ReadFile("/tmp/namespace.json")
494+
assert.NoError(t, err)
479495
assert.Equal(t, "\n---\napiVersion: v1\nkind: Namespace\nmetadata:\n name: test-ns\n", string(buf))
480496

481497
// Dry-run
482498
set = flag.NewFlagSet("test-set", 0)
483499
set.String("zone", "us-east1-b", "")
484500
set.String("cluster", "cluster-0", "")
485-
set.String("namespace", "Feature/1892-TEST-NS", "")
501+
set.String("namespace", "feature-1892-test-ns", "") // the namespace is already sanitized by this point
486502
set.Bool("dry-run", true, "")
487503
set.Bool("create-namespace", true, "")
488504
c = cli.NewContext(nil, set, nil)
@@ -498,7 +514,7 @@ func TestSetNamespace(t *testing.T) {
498514
set = flag.NewFlagSet("no-create-namespace-set", 0)
499515
set.String("zone", "us-east1-b", "")
500516
set.String("cluster", "cluster-0", "")
501-
set.String("namespace", "Feature/1892-TEST-NS", "")
517+
set.String("namespace", "feature-1892-test-ns", "") // the namespace is already sanitized by this point
502518
set.Bool("dry-run", false, "")
503519
set.Bool("create-namespace", false, "")
504520
c = cli.NewContext(nil, set, nil)
@@ -891,6 +907,7 @@ func TestSetDryRunFlag(t *testing.T) {
891907
expectedFlag: clientSideDryRunFlagDefault,
892908
},
893909
}
910+
894911
for _, test := range tests {
895912
t.Run(test.name, func(t *testing.T) {
896913
os.Clearenv()
@@ -918,7 +935,8 @@ func TestSetDryRunFlag(t *testing.T) {
918935
}
919936

920937
// Run
921-
setDryRunFlag(testRunner, buf, ctx)
938+
err := setDryRunFlag(testRunner, buf, ctx)
939+
assert.NoError(t, err)
922940

923941
// Check
924942
if dryRunFlag != test.expectedFlag {
@@ -927,7 +945,6 @@ func TestSetDryRunFlag(t *testing.T) {
927945
return nil
928946
},
929947
}).Run([]string{"run"})
930-
931948
if err != nil {
932949
t.Fatalf("unepected err: %v", err)
933950
}
@@ -988,3 +1005,49 @@ func Test_decodeToken(t *testing.T) {
9881005
})
9891006
}
9901007
}
1008+
1009+
func TestSanitizeNamespace(t *testing.T) {
1010+
tests := []struct {
1011+
name string
1012+
input string
1013+
expected string
1014+
}{
1015+
{
1016+
name: "already sanitized",
1017+
input: "test-ns",
1018+
expected: "test-ns",
1019+
},
1020+
{
1021+
name: "uppercase characters",
1022+
input: "TEST-NS",
1023+
expected: "test-ns",
1024+
},
1025+
{
1026+
name: "mixed case",
1027+
input: "Test-Ns",
1028+
expected: "test-ns",
1029+
},
1030+
{
1031+
name: "special-chars",
1032+
input: "feature/1892_test_ns",
1033+
expected: "feature-1892-test-ns",
1034+
},
1035+
{
1036+
name: "uppercase and special chars",
1037+
input: "feature/1892-TEST-NS",
1038+
expected: "feature-1892-test-ns",
1039+
},
1040+
{
1041+
name: "empty",
1042+
input: "",
1043+
expected: "",
1044+
},
1045+
}
1046+
1047+
for _, tt := range tests {
1048+
t.Run(tt.name, func(t *testing.T) {
1049+
output := sanitizeNamespace(tt.input)
1050+
assert.Equal(t, tt.expected, output)
1051+
})
1052+
}
1053+
}

0 commit comments

Comments
 (0)