@@ -2,8 +2,10 @@ package image
2
2
3
3
import (
4
4
"archive/tar"
5
+ "bytes"
5
6
"context"
6
7
"errors"
8
+ "fmt"
7
9
"io"
8
10
"io/fs"
9
11
"iter"
@@ -20,6 +22,7 @@ import (
20
22
ocispecv1 "github.com/opencontainers/image-spec/specs-go/v1"
21
23
"github.com/stretchr/testify/assert"
22
24
"github.com/stretchr/testify/require"
25
+ "helm.sh/helm/v3/pkg/registry"
23
26
24
27
fsutil "github.com/operator-framework/operator-controller/internal/shared/util/fs"
25
28
)
@@ -144,6 +147,67 @@ func TestDiskCacheFetch(t *testing.T) {
144
147
}
145
148
}
146
149
150
+ func TestDiskCacheStore_HelmChart (t * testing.T ) {
151
+ const myOwner = "myOwner"
152
+ myCanonicalRef := mustParseCanonical (t , "my.registry.io/ns/chart@sha256:5891b5b522d5df086d0ff0b110fbd9d21bb4fc7163af34d08286a2e846f6be03" )
153
+ myTaggedRef , err := reference .WithTag (reference .TrimNamed (myCanonicalRef ), "test-tag" )
154
+ require .NoError (t , err )
155
+
156
+ testCases := []struct {
157
+ name string
158
+ ownerID string
159
+ srcRef reference.Named
160
+ canonicalRef reference.Canonical
161
+ imgConfig ocispecv1.Image
162
+ layers iter.Seq [LayerData ]
163
+ filterFunc func (context.Context , reference.Named , ocispecv1.Image ) (archive.Filter , error )
164
+ setup func (* testing.T , * diskCache )
165
+ expect func (* testing.T , * diskCache , fs.FS , time.Time , error )
166
+ }{
167
+ {
168
+ name : "returns no error if layer read contains helm chart" ,
169
+ ownerID : myOwner ,
170
+ srcRef : myTaggedRef ,
171
+ canonicalRef : myCanonicalRef ,
172
+ layers : func () iter.Seq [LayerData ] {
173
+ testChart := mockHelmChartTgz (t ,
174
+ []fileContent {
175
+ {
176
+ name : "testchart/Chart.yaml" ,
177
+ content : []byte ("apiVersion: v2\n name: testchart\n version: 0.1.0" ),
178
+ },
179
+ {
180
+ name : "testchart/templates/deployment.yaml" ,
181
+ content : []byte ("kind: Deployment\n apiVersion: apps/v1" ),
182
+ },
183
+ },
184
+ )
185
+ return func (yield func (LayerData ) bool ) {
186
+ yield (LayerData {Reader : bytes .NewBuffer (testChart ), MediaType : registry .ChartLayerMediaType })
187
+ }
188
+ }(),
189
+ expect : func (t * testing.T , cache * diskCache , fsys fs.FS , modTime time.Time , err error ) {
190
+ require .NoError (t , err )
191
+ },
192
+ },
193
+ }
194
+ for _ , tc := range testCases {
195
+ t .Run (tc .name , func (t * testing.T ) {
196
+ dc := & diskCache {
197
+ basePath : t .TempDir (),
198
+ filterFunc : tc .filterFunc ,
199
+ }
200
+ if tc .setup != nil {
201
+ tc .setup (t , dc )
202
+ }
203
+ fsys , modTime , err := dc .Store (context .Background (), tc .ownerID , tc .srcRef , tc .canonicalRef , tc .imgConfig , tc .layers )
204
+ require .NotNil (t , tc .expect , "test case must include an expect function" )
205
+ tc .expect (t , dc , fsys , modTime , err )
206
+ require .NoError (t , fsutil .DeleteReadOnlyRecursive (dc .basePath ))
207
+ })
208
+ }
209
+ }
210
+
147
211
func TestDiskCacheStore (t * testing.T ) {
148
212
const myOwner = "myOwner"
149
213
myCanonicalRef := mustParseCanonical (t , "my.registry.io/ns/repo@sha256:5891b5b522d5df086d0ff0b110fbd9d21bb4fc7163af34d08286a2e846f6be03" )
@@ -585,6 +649,120 @@ func TestDiskCacheGarbageCollection(t *testing.T) {
585
649
}
586
650
}
587
651
652
+ func Test_storeChartLayer (t * testing.T ) {
653
+ tmp := t .TempDir ()
654
+ type args struct {
655
+ path string
656
+ data LayerData
657
+ }
658
+ type want struct {
659
+ errStr string
660
+ }
661
+
662
+ tests := []struct {
663
+ name string
664
+ args args
665
+ want want
666
+ }{
667
+ {
668
+ name : "store chart layer to given path" ,
669
+ args : args {
670
+ path : tmp ,
671
+ data : LayerData {
672
+ Index : 0 ,
673
+ MediaType : registry .ChartLayerMediaType ,
674
+ Reader : bytes .NewBuffer (mockHelmChartTgz (t ,
675
+ []fileContent {
676
+ {
677
+ name : "testchart/Chart.yaml" ,
678
+ content : []byte ("apiVersion: v2\n name: testchart\n version: 0.1.0" ),
679
+ },
680
+ {
681
+ name : "testchart/templates/deployment.yaml" ,
682
+ content : []byte ("kind: Deployment\n apiVersion: apps/v1" ),
683
+ },
684
+ },
685
+ )),
686
+ },
687
+ },
688
+ },
689
+ {
690
+ name : "store invalid chart layer" ,
691
+ args : args {
692
+ path : tmp ,
693
+ data : LayerData {
694
+ Index : 0 ,
695
+ MediaType : registry .ChartLayerMediaType ,
696
+ Reader : bytes .NewBuffer (mockHelmChartTgz (t ,
697
+ []fileContent {
698
+ {
699
+ name : "testchart/Chart.yaml" ,
700
+ content : []byte ("apiVersion: v2\n name: testchart\n version: 0.1.0" ),
701
+ },
702
+ {
703
+ name : "testchart/deployment.yaml" ,
704
+ content : []byte ("kind: Deployment\n apiVersion: apps/v1" ),
705
+ },
706
+ },
707
+ )),
708
+ },
709
+ },
710
+ },
711
+ {
712
+ name : "store existing from dummy reader" ,
713
+ args : args {
714
+ path : tmp ,
715
+ data : LayerData {
716
+ Index : 0 ,
717
+ MediaType : registry .ChartLayerMediaType ,
718
+ Reader : & dummyReader {},
719
+ },
720
+ },
721
+ want : want {
722
+ errStr : "error reading layer[0]: something went wrong" ,
723
+ },
724
+ },
725
+ {
726
+ name : "handle chart layer data" ,
727
+ args : args {
728
+ path : tmp ,
729
+ data : LayerData {
730
+ Index : 0 ,
731
+ MediaType : registry .ChartLayerMediaType ,
732
+ Err : fmt .Errorf ("invalid layer data" ),
733
+ Reader : bytes .NewBuffer (mockHelmChartTgz (t ,
734
+ []fileContent {
735
+ {
736
+ name : "testchart/Chart.yaml" ,
737
+ content : []byte ("apiVersion: v2\n name: testchart\n version: 0.1.0" ),
738
+ },
739
+ {
740
+ name : "testchart/deployment.yaml" ,
741
+ content : []byte ("kind: Deployment\n apiVersion: apps/v1" ),
742
+ },
743
+ },
744
+ )),
745
+ },
746
+ },
747
+ want : want {
748
+ errStr : "error found in layer data: invalid layer data" ,
749
+ },
750
+ },
751
+ }
752
+
753
+ for _ , tc := range tests {
754
+ t .Run (tc .name , func (t * testing.T ) {
755
+ err := storeChartLayer (tc .args .path , tc .args .data )
756
+ if tc .want .errStr != "" {
757
+ require .Error (t , err )
758
+ require .EqualError (t , err , tc .want .errStr , "chart store error" )
759
+ } else {
760
+ require .NoError (t , err )
761
+ }
762
+ })
763
+ }
764
+ }
765
+
588
766
func mustParseCanonical (t * testing.T , s string ) reference.Canonical {
589
767
n , err := reference .ParseNamed (s )
590
768
require .NoError (t , err )
@@ -619,3 +797,11 @@ func fsTarReader(fsys fs.FS) io.ReadCloser {
619
797
}()
620
798
return pr
621
799
}
800
+
801
+ type dummyReader struct {}
802
+
803
+ var _ io.Reader = & dummyReader {}
804
+
805
+ func (r * dummyReader ) Read (p []byte ) (int , error ) {
806
+ return 0 , errors .New ("something went wrong" )
807
+ }
0 commit comments