Skip to content

Commit 060d100

Browse files
fix: HOOKS section should also be parsed when HELM_DIFF_USE_UPGRADE_DRY_RUN=true (#364)
* HOOKS section should also be parsed when HELM_DIFF_USE_UPGRADE_DRY_RUN=true * fix for charts that don't have any hooks * change condition operator on if statement * fix sections extract if only HOOKS sections is present * fixup! fix sections extract if only HOOKS sections is present Co-authored-by: crmendes <[email protected]> Co-authored-by: Yusuke Kuoka <[email protected]>
1 parent f5a7c50 commit 060d100

File tree

2 files changed

+181
-14
lines changed

2 files changed

+181
-14
lines changed

cmd/helm3.go

Lines changed: 44 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ func (d *diffCmd) template(isUpgrade bool) ([]byte, error) {
8787
if d.devel {
8888
flags = append(flags, "--devel")
8989
}
90-
if d.noHooks {
90+
if d.noHooks && !d.useUpgradeDryRun {
9191
flags = append(flags, "--no-hooks")
9292
}
9393
if d.chartVersion != "" {
@@ -171,19 +171,7 @@ func (d *diffCmd) template(isUpgrade bool) ([]byte, error) {
171171
flags = append(flags, "--dry-run")
172172
subcmd = "upgrade"
173173
filter = func(s []byte) []byte {
174-
if len(s) == 0 {
175-
return s
176-
}
177-
178-
i := bytes.Index(s, []byte("MANIFEST:"))
179-
s = s[i:]
180-
i = bytes.Index(s, []byte("---"))
181-
s = s[i:]
182-
i = bytes.Index(s, []byte("\nNOTES:"))
183-
if i != -1 {
184-
s = s[:i+1]
185-
}
186-
return s
174+
return extractManifestFromHelmUpgradeDryRunOutput(s, d.noHooks)
187175
}
188176
} else {
189177
if !d.disableValidation && !d.dryRun {
@@ -220,3 +208,45 @@ func (d *diffCmd) writeExistingValues(f *os.File) error {
220208
cmd.Stdout = f
221209
return cmd.Run()
222210
}
211+
212+
func extractManifestFromHelmUpgradeDryRunOutput(s []byte, noHooks bool) []byte {
213+
if len(s) == 0 {
214+
return s
215+
}
216+
217+
i := bytes.Index(s, []byte("HOOKS:"))
218+
hooks := s[i:]
219+
220+
j := bytes.Index(hooks, []byte("MANIFEST:"))
221+
222+
manifest := hooks[j:]
223+
hooks = hooks[:j]
224+
225+
k := bytes.Index(manifest, []byte("\nNOTES:"))
226+
227+
if k > -1 {
228+
manifest = manifest[:k+1]
229+
}
230+
231+
if noHooks {
232+
hooks = nil
233+
} else {
234+
a := bytes.Index(hooks, []byte("---"))
235+
if a > -1 {
236+
hooks = hooks[a:]
237+
} else {
238+
hooks = nil
239+
}
240+
}
241+
242+
a := bytes.Index(manifest, []byte("---"))
243+
if a > -1 {
244+
manifest = manifest[a:]
245+
}
246+
247+
r := []byte{}
248+
r = append(r, manifest...)
249+
r = append(r, hooks...)
250+
251+
return r
252+
}

cmd/helm3_test.go

Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
1+
package cmd
2+
3+
import (
4+
"testing"
5+
6+
"github.com/google/go-cmp/cmp"
7+
)
8+
9+
func TestExtractManifestFromHelmUpgradeDryRunOutput(t *testing.T) {
10+
type testdata struct {
11+
description string
12+
13+
s string
14+
noHooks bool
15+
16+
want string
17+
}
18+
19+
manifest := `---
20+
# Source: mysql/templates/secrets.yaml
21+
apiVersion: v1
22+
kind: Secret
23+
metadata:
24+
name: my1-mysql
25+
namespace: default
26+
labels:
27+
app: my1-mysql
28+
chart: "mysql-1.6.9"
29+
release: "my1"
30+
heritage: "Helm"
31+
type: Opaque
32+
data:
33+
mysql-root-password: "ZlhEVGJseUhmeg=="
34+
mysql-password: "YnRuU3pPOTJMVg=="
35+
---
36+
# Source: mysql/templates/tests/test-configmap.yaml
37+
apiVersion: v1
38+
kind: ConfigMap
39+
metadata:
40+
name: my1-mysql-test
41+
namespace: default
42+
labels:
43+
app: my1-mysql
44+
chart: "mysql-1.6.9"
45+
heritage: "Helm"
46+
release: "my1"
47+
data:
48+
run.sh: |-
49+
50+
`
51+
hooks := `---
52+
# Source: mysql/templates/tests/test.yaml
53+
apiVersion: v1
54+
kind: Pod
55+
metadata:
56+
name: my1-mysql-test
57+
namespace: default
58+
labels:
59+
app: my1-mysql
60+
chart: "mysql-1.6.9"
61+
heritage: "Helm"
62+
release: "my1"
63+
annotations:
64+
"helm.sh/hook": test-success
65+
spec:
66+
containers:
67+
- name: my1-test
68+
image: "bats/bats:1.2.1"
69+
imagePullPolicy: "IfNotPresent"
70+
command: ["/opt/bats/bin/bats", "-t", "/tests/run.sh"]
71+
`
72+
73+
header := `Release "my1" has been upgraded. Happy Helming!
74+
NAME: my1
75+
LAST DEPLOYED: Sun Feb 13 02:26:16 2022
76+
NAMESPACE: default
77+
STATUS: pending-upgrade
78+
REVISION: 2
79+
HOOKS:
80+
`
81+
82+
notes := `NOTES:
83+
MySQL can be accessed via port 3306 on the following DNS name from within your cluster:
84+
my1-mysql.default.svc.cluster.local
85+
86+
*snip*
87+
88+
To connect to your database directly from outside the K8s cluster:
89+
MYSQL_HOST=127.0.0.1
90+
MYSQL_PORT=3306
91+
92+
# Execute the following command to route the connection:
93+
kubectl port-forward svc/my1-mysql 3306
94+
95+
mysql -h ${MYSQL_HOST} -P${MYSQL_PORT} -u root -p${MYSQL_ROOT_PASSWORD}
96+
`
97+
98+
outputWithHooks := header + hooks + "MANIFEST:\n" + manifest + notes
99+
outputWithNoHooks := header + "MANIFEST:\n" + manifest + notes
100+
101+
testcases := []testdata{
102+
{
103+
description: "should output manifest when noHooks specified",
104+
s: outputWithHooks,
105+
noHooks: true,
106+
want: manifest,
107+
},
108+
{
109+
description: "should output manifest and hooks when noHooks unspecified",
110+
s: outputWithHooks,
111+
noHooks: false,
112+
want: manifest + hooks,
113+
},
114+
{
115+
description: "should output manifest if noHooks specified but input did not contain hooks",
116+
s: outputWithNoHooks,
117+
noHooks: true,
118+
want: manifest,
119+
},
120+
{
121+
description: "should output manifest if noHooks unspecified and input did not contain hooks",
122+
s: outputWithNoHooks,
123+
noHooks: false,
124+
want: manifest,
125+
},
126+
}
127+
128+
for _, tc := range testcases {
129+
t.Run(tc.description, func(t *testing.T) {
130+
got := extractManifestFromHelmUpgradeDryRunOutput([]byte(tc.s), tc.noHooks)
131+
132+
if d := cmp.Diff(tc.want, string(got)); d != "" {
133+
t.Errorf("unexpected diff: %s", d)
134+
}
135+
})
136+
}
137+
}

0 commit comments

Comments
 (0)