Skip to content

Commit 420855d

Browse files
authored
fix(helm): ensure coder can be deployed in a non-default namespace (coder#16579)
Added namespace to all resources in the helm chart and added tests to ensure that coder can be deployed in non-default namespaces, as specified via the namespace flag in the helm command. Ways to verify this: - current state: ```bash $ helm template my-coder coder -n coder --version 2.19.0 --repo https://helm.coder.com/v2 | yq '.metadata.namespace' null --- null --- null --- null --- null ``` - fixed state when checking out this PR: ```bash $ helm template my-coder ./helm/coder -n coder --set coder.image.tag=latest | yq '.metadata.namespace' coder --- coder --- coder --- coder --- coder ``` Change-Id: Ib66d4be9bcc4984dfe15709362e1fe0dcd3e847f Signed-off-by: Thomas Kosiewski <[email protected]>
1 parent a777c26 commit 420855d

File tree

73 files changed

+6040
-114
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

73 files changed

+6040
-114
lines changed

helm/coder/templates/ingress.yaml

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
1-
21
{{- if .Values.coder.ingress.enable }}
32
---
43
apiVersion: networking.k8s.io/v1
54
kind: Ingress
65
metadata:
76
name: coder
7+
namespace: {{ .Release.Namespace }}
88
labels:
99
{{- include "coder.labels" . | nindent 4 }}
1010
annotations:

helm/coder/templates/service.yaml

+1
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ apiVersion: v1
44
kind: Service
55
metadata:
66
name: coder
7+
namespace: {{ .Release.Namespace }}
78
labels:
89
{{- include "coder.labels" . | nindent 4 }}
910
annotations:

helm/coder/tests/chart_test.go

+62-40
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,11 @@ import (
2323
// updateGoldenFiles is a flag that can be set to update golden files.
2424
var updateGoldenFiles = flag.Bool("update", false, "Update golden files")
2525

26+
var namespaces = []string{
27+
"default",
28+
"coder",
29+
}
30+
2631
var testCases = []testCase{
2732
{
2833
name: "default_values",
@@ -116,6 +121,7 @@ var testCases = []testCase{
116121

117122
type testCase struct {
118123
name string // Name of the test case. This is used to control which values and golden file are used.
124+
namespace string // Namespace is the name of the namespace the resources should be generated within
119125
expectedError string // Expected error from running `helm template`.
120126
}
121127

@@ -124,7 +130,11 @@ func (tc testCase) valuesFilePath() string {
124130
}
125131

126132
func (tc testCase) goldenFilePath() string {
127-
return filepath.Join("./testdata", tc.name+".golden")
133+
if tc.namespace == "default" {
134+
return filepath.Join("./testdata", tc.name+".golden")
135+
}
136+
137+
return filepath.Join("./testdata", tc.name+"_"+tc.namespace+".golden")
128138
}
129139

130140
func TestRenderChart(t *testing.T) {
@@ -146,35 +156,41 @@ func TestRenderChart(t *testing.T) {
146156

147157
for _, tc := range testCases {
148158
tc := tc
149-
t.Run(tc.name, func(t *testing.T) {
150-
t.Parallel()
151159

152-
// Ensure that the values file exists.
153-
valuesFilePath := tc.valuesFilePath()
154-
if _, err := os.Stat(valuesFilePath); os.IsNotExist(err) {
155-
t.Fatalf("values file %q does not exist", valuesFilePath)
156-
}
160+
for _, ns := range namespaces {
161+
tc := tc
162+
tc.namespace = ns
157163

158-
// Run helm template with the values file.
159-
templateOutput, err := runHelmTemplate(t, helmPath, "..", valuesFilePath)
160-
if tc.expectedError != "" {
161-
require.Error(t, err, "helm template should have failed")
162-
require.Contains(t, templateOutput, tc.expectedError, "helm template output should contain expected error")
163-
} else {
164-
require.NoError(t, err, "helm template should not have failed")
165-
require.NotEmpty(t, templateOutput, "helm template output should not be empty")
166-
goldenFilePath := tc.goldenFilePath()
167-
goldenBytes, err := os.ReadFile(goldenFilePath)
168-
require.NoError(t, err, "failed to read golden file %q", goldenFilePath)
169-
170-
// Remove carriage returns to make tests pass on Windows.
171-
goldenBytes = bytes.Replace(goldenBytes, []byte("\r"), []byte(""), -1)
172-
expected := string(goldenBytes)
173-
174-
require.NoError(t, err, "failed to load golden file %q")
175-
require.Equal(t, expected, templateOutput)
176-
}
177-
})
164+
t.Run(tc.namespace+"/"+tc.name, func(t *testing.T) {
165+
t.Parallel()
166+
167+
// Ensure that the values file exists.
168+
valuesFilePath := tc.valuesFilePath()
169+
if _, err := os.Stat(valuesFilePath); os.IsNotExist(err) {
170+
t.Fatalf("values file %q does not exist", valuesFilePath)
171+
}
172+
173+
// Run helm template with the values file.
174+
templateOutput, err := runHelmTemplate(t, helmPath, "..", valuesFilePath, tc.namespace)
175+
if tc.expectedError != "" {
176+
require.Error(t, err, "helm template should have failed")
177+
require.Contains(t, templateOutput, tc.expectedError, "helm template output should contain expected error")
178+
} else {
179+
require.NoError(t, err, "helm template should not have failed")
180+
require.NotEmpty(t, templateOutput, "helm template output should not be empty")
181+
goldenFilePath := tc.goldenFilePath()
182+
goldenBytes, err := os.ReadFile(goldenFilePath)
183+
require.NoError(t, err, "failed to read golden file %q", goldenFilePath)
184+
185+
// Remove carriage returns to make tests pass on Windows.
186+
goldenBytes = bytes.ReplaceAll(goldenBytes, []byte("\r"), []byte(""))
187+
expected := string(goldenBytes)
188+
189+
require.NoError(t, err, "failed to load golden file %q")
190+
require.Equal(t, expected, templateOutput)
191+
}
192+
})
193+
}
178194
}
179195
}
180196

@@ -189,22 +205,28 @@ func TestUpdateGoldenFiles(t *testing.T) {
189205
require.NoError(t, err, "failed to build Helm dependencies")
190206

191207
for _, tc := range testCases {
208+
tc := tc
192209
if tc.expectedError != "" {
193210
t.Logf("skipping test case %q with render error", tc.name)
194211
continue
195212
}
196213

197-
valuesPath := tc.valuesFilePath()
198-
templateOutput, err := runHelmTemplate(t, helmPath, "..", valuesPath)
199-
if err != nil {
200-
t.Logf("error running `helm template -f %q`: %v", valuesPath, err)
201-
t.Logf("output: %s", templateOutput)
202-
}
203-
require.NoError(t, err, "failed to run `helm template -f %q`", valuesPath)
214+
for _, ns := range namespaces {
215+
tc := tc
216+
tc.namespace = ns
217+
218+
valuesPath := tc.valuesFilePath()
219+
templateOutput, err := runHelmTemplate(t, helmPath, "..", valuesPath, tc.namespace)
220+
if err != nil {
221+
t.Logf("error running `helm template -f %q`: %v", valuesPath, err)
222+
t.Logf("output: %s", templateOutput)
223+
}
224+
require.NoError(t, err, "failed to run `helm template -f %q`", valuesPath)
204225

205-
goldenFilePath := tc.goldenFilePath()
206-
err = os.WriteFile(goldenFilePath, []byte(templateOutput), 0o644) // nolint:gosec
207-
require.NoError(t, err, "failed to write golden file %q", goldenFilePath)
226+
goldenFilePath := tc.goldenFilePath()
227+
err = os.WriteFile(goldenFilePath, []byte(templateOutput), 0o644) // nolint:gosec
228+
require.NoError(t, err, "failed to write golden file %q", goldenFilePath)
229+
}
208230
}
209231
t.Log("Golden files updated. Please review the changes and commit them.")
210232
}
@@ -231,13 +253,13 @@ func updateHelmDependencies(t testing.TB, helmPath, chartDir string) error {
231253

232254
// runHelmTemplate runs helm template on the given chart with the given values and
233255
// returns the raw output.
234-
func runHelmTemplate(t testing.TB, helmPath, chartDir, valuesFilePath string) (string, error) {
256+
func runHelmTemplate(t testing.TB, helmPath, chartDir, valuesFilePath, namespace string) (string, error) {
235257
// Ensure that valuesFilePath exists
236258
if _, err := os.Stat(valuesFilePath); err != nil {
237259
return "", xerrors.Errorf("values file %q does not exist: %w", valuesFilePath, err)
238260
}
239261

240-
cmd := exec.Command(helmPath, "template", chartDir, "-f", valuesFilePath, "--namespace", "default")
262+
cmd := exec.Command(helmPath, "template", chartDir, "-f", valuesFilePath, "--namespace", namespace)
241263
t.Logf("exec command: %v", cmd.Args)
242264
out, err := cmd.CombinedOutput()
243265
return string(out), err

helm/coder/tests/testdata/auto_access_url_1.golden

+5
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,14 @@ metadata:
1212
app.kubernetes.io/version: 0.1.0
1313
helm.sh/chart: coder-0.1.0
1414
name: coder
15+
namespace: default
1516
---
1617
# Source: coder/templates/rbac.yaml
1718
apiVersion: rbac.authorization.k8s.io/v1
1819
kind: Role
1920
metadata:
2021
name: coder-workspace-perms
22+
namespace: default
2123
rules:
2224
- apiGroups: [""]
2325
resources: ["pods"]
@@ -60,6 +62,7 @@ apiVersion: rbac.authorization.k8s.io/v1
6062
kind: RoleBinding
6163
metadata:
6264
name: "coder"
65+
namespace: default
6366
subjects:
6467
- kind: ServiceAccount
6568
name: "coder"
@@ -73,6 +76,7 @@ apiVersion: v1
7376
kind: Service
7477
metadata:
7578
name: coder
79+
namespace: default
7680
labels:
7781
helm.sh/chart: coder-0.1.0
7882
app.kubernetes.io/name: coder
@@ -109,6 +113,7 @@ metadata:
109113
app.kubernetes.io/version: 0.1.0
110114
helm.sh/chart: coder-0.1.0
111115
name: coder
116+
namespace: default
112117
spec:
113118
replicas: 1
114119
selector:

0 commit comments

Comments
 (0)