@@ -19,6 +19,8 @@ package chart
19
19
import (
20
20
"bytes"
21
21
"context"
22
+ "fmt"
23
+ "net/url"
22
24
"os"
23
25
"path/filepath"
24
26
"strings"
@@ -29,11 +31,35 @@ import (
29
31
helmchart "helm.sh/helm/v3/pkg/chart"
30
32
"helm.sh/helm/v3/pkg/chartutil"
31
33
helmgetter "helm.sh/helm/v3/pkg/getter"
34
+ "helm.sh/helm/v3/pkg/registry"
32
35
33
36
"github.com/fluxcd/source-controller/internal/helm/chart/secureloader"
34
37
"github.com/fluxcd/source-controller/internal/helm/repository"
35
38
)
36
39
40
+ type mockRegistryClient struct {
41
+ tags map [string ][]string
42
+ requestedURL string
43
+ }
44
+
45
+ func (m * mockRegistryClient ) Tags (url string ) ([]string , error ) {
46
+ m .requestedURL = url
47
+ if tags , ok := m .tags [url ]; ok {
48
+ return tags , nil
49
+ }
50
+ return nil , fmt .Errorf ("no tags found for %s" , url )
51
+ }
52
+
53
+ func (m * mockRegistryClient ) Login (url string , opts ... registry.LoginOption ) error {
54
+ m .requestedURL = url
55
+ return nil
56
+ }
57
+
58
+ func (m * mockRegistryClient ) Logout (url string , opts ... registry.LogoutOption ) error {
59
+ m .requestedURL = url
60
+ return nil
61
+ }
62
+
37
63
// mockIndexChartGetter returns specific response for index and chart queries.
38
64
type mockIndexChartGetter struct {
39
65
IndexResponse []byte
@@ -54,7 +80,7 @@ func (g *mockIndexChartGetter) LastGet() string {
54
80
return g .requestedURL
55
81
}
56
82
57
- func TestRemoteBuilder_Build (t * testing.T ) {
83
+ func TestRemoteBuilder__BuildFromChartRepository (t * testing.T ) {
58
84
g := NewWithT (t )
59
85
60
86
chartGrafana , err := os .ReadFile ("./../testdata/charts/helmchart-0.1.0.tgz" )
@@ -195,6 +221,140 @@ entries:
195
221
}
196
222
}
197
223
224
+ func TestRemoteBuilder_BuildFromOCIChatRepository (t * testing.T ) {
225
+ g := NewWithT (t )
226
+
227
+ chartGrafana , err := os .ReadFile ("./../testdata/charts/helmchart-0.1.0.tgz" )
228
+ g .Expect (err ).ToNot (HaveOccurred ())
229
+ g .Expect (chartGrafana ).ToNot (BeEmpty ())
230
+
231
+ registryClient := & mockRegistryClient {
232
+ tags : map [string ][]string {
233
+ "localhost:5000/my_repo/grafana" : {"6.17.4" },
234
+ },
235
+ }
236
+
237
+ mockGetter := & mockIndexChartGetter {
238
+ ChartResponse : chartGrafana ,
239
+ }
240
+
241
+ u , err := url .Parse ("oci://localhost:5000/my_repo" )
242
+ g .Expect (err ).ToNot (HaveOccurred ())
243
+
244
+ mockRepo := func () * repository.OCIChartRepository {
245
+ return & repository.OCIChartRepository {
246
+ URL : * u ,
247
+ Client : mockGetter ,
248
+ RegistryClient : registryClient ,
249
+ }
250
+ }
251
+
252
+ tests := []struct {
253
+ name string
254
+ reference Reference
255
+ buildOpts BuildOptions
256
+ repository * repository.OCIChartRepository
257
+ wantValues chartutil.Values
258
+ wantVersion string
259
+ wantPackaged bool
260
+ wantErr string
261
+ }{
262
+ {
263
+ name : "invalid reference" ,
264
+ reference : LocalReference {},
265
+ wantErr : "expected remote chart reference" ,
266
+ },
267
+ {
268
+ name : "invalid reference - no name" ,
269
+ reference : RemoteReference {},
270
+ wantErr : "no name set for remote chart reference" ,
271
+ },
272
+ {
273
+ name : "chart not in repository" ,
274
+ reference : RemoteReference {Name : "foo" },
275
+ repository : mockRepo (),
276
+ wantErr : "failed to get chart version for remote reference" ,
277
+ },
278
+ {
279
+ name : "chart version not in repository" ,
280
+ reference : RemoteReference {Name : "grafana" , Version : "1.1.1" },
281
+ repository : mockRepo (),
282
+ wantErr : "failed to get chart version for remote reference" ,
283
+ },
284
+ {
285
+ name : "invalid version metadata" ,
286
+ reference : RemoteReference {Name : "grafana" },
287
+ repository : mockRepo (),
288
+ buildOpts : BuildOptions {VersionMetadata : "^" },
289
+ wantErr : "Invalid Metadata string" ,
290
+ },
291
+ {
292
+ name : "with version metadata" ,
293
+ reference : RemoteReference {Name : "grafana" },
294
+ repository : mockRepo (),
295
+ buildOpts : BuildOptions {VersionMetadata : "foo" },
296
+ wantVersion : "6.17.4+foo" ,
297
+ wantPackaged : true ,
298
+ },
299
+ {
300
+ name : "default values" ,
301
+ reference : RemoteReference {Name : "grafana" },
302
+ repository : mockRepo (),
303
+ wantVersion : "0.1.0" ,
304
+ wantValues : chartutil.Values {
305
+ "replicaCount" : float64 (1 ),
306
+ },
307
+ },
308
+ {
309
+ name : "merge values" ,
310
+ reference : RemoteReference {Name : "grafana" },
311
+ buildOpts : BuildOptions {
312
+ ValuesFiles : []string {"a.yaml" , "b.yaml" , "c.yaml" },
313
+ },
314
+ repository : mockRepo (),
315
+ wantVersion : "6.17.4" ,
316
+ wantValues : chartutil.Values {
317
+ "a" : "b" ,
318
+ "b" : "d" ,
319
+ },
320
+ wantPackaged : true ,
321
+ },
322
+ }
323
+ for _ , tt := range tests {
324
+ t .Run (tt .name , func (t * testing.T ) {
325
+ g := NewWithT (t )
326
+
327
+ tmpDir , err := os .MkdirTemp ("" , "remote-chart-builder-" )
328
+ g .Expect (err ).ToNot (HaveOccurred ())
329
+ defer os .RemoveAll (tmpDir )
330
+ targetPath := filepath .Join (tmpDir , "chart.tgz" )
331
+
332
+ b := NewRemoteBuilder (tt .repository )
333
+
334
+ cb , err := b .Build (context .TODO (), tt .reference , targetPath , tt .buildOpts )
335
+
336
+ if tt .wantErr != "" {
337
+ g .Expect (err ).To (HaveOccurred ())
338
+ g .Expect (err .Error ()).To (ContainSubstring (tt .wantErr ))
339
+ g .Expect (cb ).To (BeZero ())
340
+ return
341
+ }
342
+ g .Expect (err ).ToNot (HaveOccurred ())
343
+ g .Expect (cb .Packaged ).To (Equal (tt .wantPackaged ), "unexpected Build.Packaged value" )
344
+ g .Expect (cb .Path ).ToNot (BeEmpty (), "empty Build.Path" )
345
+
346
+ // Load the resulting chart and verify the values.
347
+ resultChart , err := secureloader .LoadFile (cb .Path )
348
+ g .Expect (err ).ToNot (HaveOccurred ())
349
+ g .Expect (resultChart .Metadata .Version ).To (Equal (tt .wantVersion ))
350
+
351
+ for k , v := range tt .wantValues {
352
+ g .Expect (v ).To (Equal (resultChart .Values [k ]))
353
+ }
354
+ })
355
+ }
356
+ }
357
+
198
358
func TestRemoteBuilder_Build_CachedChart (t * testing.T ) {
199
359
g := NewWithT (t )
200
360
0 commit comments