4
4
package nutanix
5
5
6
6
import (
7
+ "bytes"
7
8
"fmt"
9
+ "os/exec"
10
+ "path/filepath"
11
+ "strings"
8
12
"testing"
13
+ "text/template"
9
14
10
15
"github.com/stretchr/testify/assert"
11
16
"github.com/stretchr/testify/require"
17
+ corev1 "k8s.io/api/core/v1"
18
+ "sigs.k8s.io/yaml"
12
19
13
20
"github.com/nutanix-cloud-native/cluster-api-runtime-extensions-nutanix/api/v1alpha1"
14
21
apivariables "github.com/nutanix-cloud-native/cluster-api-runtime-extensions-nutanix/api/variables"
15
22
)
16
23
17
24
const (
18
- in = `---
19
- prismCentralEndPoint: {{ .PrismCentralHost }}
20
- prismCentralPort: {{ .PrismCentralPort }}
21
- prismCentralInsecure: {{ .PrismCentralInsecure }}
22
- prismCentralAdditionalTrustBundle: "{{ or .PrismCentralAdditionalTrustBundle "" }}"
23
-
24
- # The Secret containing the credentials will be created by the handler.
25
- createSecret: false
26
- secretName: nutanix-ccm-credentials
27
- `
28
25
//nolint:lll // just a long string
29
26
testCertBundle = "LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUVjekNDQTF1Z0F3SUJBZ0lCQURBTkJna3Foa2lHOXcwQkFRUUZBRC4uQWtHQTFVRUJoTUNSMEl4CkV6QVJCZ05WQkFnVENsTnZiV1V0VTNSaGRHVXhGREFTQmdOVkJBb1RDMC4uMEVnVEhSa01UY3dOUVlEClZRUUxFeTVEYkdGemN5QXhJRkIxWW14cFl5QlFjbWx0WVhKNUlFTmxjbi4uWFJwYjI0Z1FYVjBhRzl5CmFYUjVNUlF3RWdZRFZRUURFd3RDWlhOMElFTkJJRXgwWkRBZUZ3MHdNRC4uVFV3TVRaYUZ3MHdNVEF5Ck1EUXhPVFV3TVRaYU1JR0hNUXN3Q1FZRFZRUUdFd0pIUWpFVE1CRUdBMS4uMjl0WlMxVGRHRjBaVEVVCk1CSUdBMVVFQ2hNTFFtVnpkQ0JEUVNCTWRHUXhOekExQmdOVkJBc1RMay4uREVnVUhWaWJHbGpJRkJ5CmFXMWhjbmtnUTJWeWRHbG1hV05oZEdsdmJpQkJkWFJvYjNKcGRIa3hGRC4uQU1UQzBKbGMzUWdRMEVnClRIUmtNSUlCSWpBTkJna3Foa2lHOXcwQkFRRUZBQU9DQVE4QU1JSUJDZy4uVHoybXI3U1ppQU1mUXl1CnZCak05T2lKalJhelhCWjFCalA1Q0UvV20vUnI1MDBQUksrTGg5eDVlSi4uL0FOQkUwc1RLMFpzREdNCmFrMm0xZzdvcnVJM2RZM1ZIcUl4RlR6MFRhMWQrTkFqd25MZTRuT2I3Ly4uazA1U2hoQnJKR0JLS3hiCjhuMTA0by81cDhIQXNaUGR6YkZNSXlOakp6Qk0ybzV5NUExM3dpTGl0RS4uZnlZa1F6YXhDdzBBd3psCmtWSGlJeUN1YUY0d2o1NzFwU3prdjZzdis0SURNYlQvWHBDbzhMNndUYS4uc2grZXRMRDZGdFRqWWJiCnJ2WjhSUU0xdGxLZG9NSGcycXhyYUFWKytITkJZbU5XczBkdUVkalViSi4uWEk5VHRuUzRvMUNrajdQCk9mbGppUUlEQVFBQm80SG5NSUhrTUIwR0ExVWREZ1FXQkJROHVyTUNSTC4uNUFrSXA5TkpISnc1VENCCnRBWURWUjBqQklHc01JR3BnQlE4dXJNQ1JMWVlNSFVLVTVBa0lwOU5KSC4uYVNCaWpDQmh6RUxNQWtHCkExVUVCaE1DUjBJeEV6QVJCZ05WQkFnVENsTnZiV1V0VTNSaGRHVXhGRC4uQW9UQzBKbGMzUWdRMEVnClRIUmtNVGN3TlFZRFZRUUxFeTVEYkdGemN5QXhJRkIxWW14cFl5QlFjbS4uRU5sY25ScFptbGpZWFJwCmIyNGdRWFYwYUc5eWFYUjVNUlF3RWdZRFZRUURFd3RDWlhOMElFTkJJRS4uREFNQmdOVkhSTUVCVEFECkFRSC9NQTBHQ1NxR1NJYjNEUUVCQkFVQUE0SUJBUUMxdVlCY3NTbmN3QS4uRENzUWVyNzcyQzJ1Y3BYCnhRVUUvQzBwV1dtNmdEa3dkNUQwRFNNREpScVYvd2VvWjR3QzZCNzNmNS4uYkxoR1lIYVhKZVNENktyClhjb093TGRTYUdtSllzbExLWkIzWklERXAwd1lUR2hndGViNkpGaVR0bi4uc2YyeGRyWWZQQ2lJQjdnCkJNQVY3R3pkYzRWc3BTNmxqckFoYmlpYXdkQmlRbFFtc0JlRno5SmtGNC4uYjNsOEJvR04rcU1hNTZZCkl0OHVuYTJnWTRsMk8vL29uODhyNUlXSmxtMUwwb0E4ZTRmUjJ5ckJIWC4uYWRzR2VGS2t5TnJ3R2kvCjd2UU1mWGRHc1JyWE5HUkduWCt2V0RaMy96V0kwam9EdENrTm5xRXBWbi4uSG9YCi0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0="
30
- )
31
27
32
- const (
33
28
//nolint:lll // just a long string
34
29
expectedWithAdditionalTrustBundle = `---
35
30
prismCentralEndPoint: prism-central.nutanix.com
@@ -39,24 +34,34 @@ prismCentralAdditionalTrustBundle: "LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUVj
39
34
40
35
# The Secret containing the credentials will be created by the handler.
41
36
createSecret: false
42
- secretName: nutanix-ccm-credentials
43
- `
37
+ secretName: nutanix-ccm-credentials`
44
38
45
39
expectedWithoutAdditionalTrustBundle = `---
46
40
prismCentralEndPoint: prism-central.nutanix.com
47
41
prismCentralPort: 9440
48
42
prismCentralInsecure: true
49
- prismCentralAdditionalTrustBundle: ""
50
43
51
44
# The Secret containing the credentials will be created by the handler.
52
45
createSecret: false
53
- secretName: nutanix-ccm-credentials
54
- `
46
+ secretName: nutanix-ccm-credentials`
47
+ )
48
+
49
+ var templateFile = filepath .Join (
50
+ moduleRootDir (),
51
+ "charts" ,
52
+ "cluster-api-runtime-extensions-nutanix" ,
53
+ "templates" ,
54
+ "ccm" ,
55
+ "nutanix" ,
56
+ "manifests" ,
57
+ "helm-addon-installation.yaml" ,
55
58
)
56
59
57
60
func Test_templateValues (t * testing.T ) {
58
61
t .Parallel ()
59
62
63
+ valuesTemplate := readCCMTemplateFromProjectHelmChart (t )
64
+
60
65
tests := []struct {
61
66
name string
62
67
clusterConfig * apivariables.ClusterConfigSpec
@@ -88,7 +93,7 @@ func Test_templateValues(t *testing.T) {
88
93
},
89
94
},
90
95
},
91
- in : in ,
96
+ in : valuesTemplate ,
92
97
expected : expectedWithAdditionalTrustBundle ,
93
98
},
94
99
{
@@ -115,7 +120,7 @@ func Test_templateValues(t *testing.T) {
115
120
},
116
121
},
117
122
},
118
- in : in ,
123
+ in : valuesTemplate ,
119
124
expected : expectedWithoutAdditionalTrustBundle ,
120
125
},
121
126
}
@@ -129,3 +134,59 @@ func Test_templateValues(t *testing.T) {
129
134
})
130
135
}
131
136
}
137
+
138
+ // readCCMTemplateFromProjectHelmChart gets the CCM template from the Helm chart in the project
139
+ // and renders it with dummy values, finally extracting the embedded template that will be used by
140
+ // CAAPH when installing the Nutanix CCM addon.
141
+ // This is important to do this way to ensure that the hard-to-read double templating works as expected.
142
+ func readCCMTemplateFromProjectHelmChart (t * testing.T ) string {
143
+ t .Helper ()
144
+
145
+ // Mimic the Helm templating using dummy values that will render the template correctly.
146
+ const dummyValues = `---
147
+ hooks:
148
+ ccm:
149
+ nutanix:
150
+ helmAddonStrategy:
151
+ defaultValueTemplateConfigMap:
152
+ create: true
153
+ `
154
+ templateData := map [string ]interface {}{}
155
+ require .NoError (t , yaml .Unmarshal ([]byte (dummyValues ), & templateData ))
156
+
157
+ // And set that as the value of Values in the templateData.
158
+ templateData ["Values" ] = templateData
159
+
160
+ // Run the actual template as Helm would.
161
+ var templatedBytes bytes.Buffer
162
+ require .NoError (
163
+ t ,
164
+ template .Must (
165
+ template .New (
166
+ "helm-addon-installation.yaml" ).ParseFiles (templateFile ),
167
+ ).Execute (& templatedBytes , templateData ),
168
+ )
169
+ cm := & corev1.ConfigMap {}
170
+ require .NoError (t , yaml .UnmarshalStrict (templatedBytes .Bytes (), cm ))
171
+
172
+ // And return the values from the template.
173
+ return cm .Data ["values.yaml" ]
174
+ }
175
+
176
+ func moduleRootDir () string {
177
+ cmd := exec .Command ("go" , "list" , "-m" , "-f" , "{{ .Dir }}" )
178
+ out , err := cmd .CombinedOutput ()
179
+ if err != nil {
180
+ // We include the combined output because the error is usually
181
+ // an exit code, which does not explain why the command failed.
182
+ panic (
183
+ fmt .Sprintf ("cmd.Dir=%q, cmd.Env=%q, cmd.Args=%q, err=%q, output=%q" ,
184
+ cmd .Dir ,
185
+ cmd .Env ,
186
+ cmd .Args ,
187
+ err ,
188
+ out ),
189
+ )
190
+ }
191
+ return strings .TrimSpace (string (out ))
192
+ }
0 commit comments