@@ -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,123 @@ 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
+ want : want {
711
+ errStr : "inspecting chart layer: templates directory not found" ,
712
+ },
713
+ },
714
+ {
715
+ name : "store existing from dummy reader" ,
716
+ args : args {
717
+ path : tmp ,
718
+ data : LayerData {
719
+ Index : 0 ,
720
+ MediaType : registry .ChartLayerMediaType ,
721
+ Reader : & dummyReader {},
722
+ },
723
+ },
724
+ want : want {
725
+ errStr : "error reading layer[0]: something went wrong" ,
726
+ },
727
+ },
728
+ {
729
+ name : "handle chart layer data" ,
730
+ args : args {
731
+ path : tmp ,
732
+ data : LayerData {
733
+ Index : 0 ,
734
+ MediaType : registry .ChartLayerMediaType ,
735
+ Err : fmt .Errorf ("invalid layer data" ),
736
+ Reader : bytes .NewBuffer (mockHelmChartTgz (t ,
737
+ []fileContent {
738
+ {
739
+ name : "testchart/Chart.yaml" ,
740
+ content : []byte ("apiVersion: v2\n name: testchart\n version: 0.1.0" ),
741
+ },
742
+ {
743
+ name : "testchart/deployment.yaml" ,
744
+ content : []byte ("kind: Deployment\n apiVersion: apps/v1" ),
745
+ },
746
+ },
747
+ )),
748
+ },
749
+ },
750
+ want : want {
751
+ errStr : "error found in layer data: invalid layer data" ,
752
+ },
753
+ },
754
+ }
755
+
756
+ for _ , tc := range tests {
757
+ t .Run (tc .name , func (t * testing.T ) {
758
+ err := storeChartLayer (tc .args .path , tc .args .data )
759
+ if tc .want .errStr != "" {
760
+ require .Error (t , err )
761
+ require .EqualError (t , err , tc .want .errStr , "chart store error" )
762
+ } else {
763
+ require .NoError (t , err )
764
+ }
765
+ })
766
+ }
767
+ }
768
+
588
769
func mustParseCanonical (t * testing.T , s string ) reference.Canonical {
589
770
n , err := reference .ParseNamed (s )
590
771
require .NoError (t , err )
@@ -619,3 +800,11 @@ func fsTarReader(fsys fs.FS) io.ReadCloser {
619
800
}()
620
801
return pr
621
802
}
803
+
804
+ type dummyReader struct {}
805
+
806
+ var _ io.Reader = & dummyReader {}
807
+
808
+ func (r * dummyReader ) Read (p []byte ) (int , error ) {
809
+ return 0 , errors .New ("something went wrong" )
810
+ }
0 commit comments