forked from rancher/fleet
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathociwrapper_test.go
More file actions
517 lines (465 loc) · 18.9 KB
/
ociwrapper_test.go
File metadata and controls
517 lines (465 loc) · 18.9 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
package ocistorage
import (
"bytes"
"context"
"crypto/tls"
"crypto/x509"
"fmt"
"net/http"
"os"
"github.com/opencontainers/go-digest"
"go.uber.org/mock/gomock"
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
"oras.land/oras-go/v2"
"oras.land/oras-go/v2/content"
orasmemory "oras.land/oras-go/v2/content/memory"
"oras.land/oras-go/v2/registry/remote/auth"
"oras.land/oras-go/v2/registry/remote/retry"
"github.com/rancher/fleet/internal/manifest"
"github.com/rancher/fleet/internal/mocks"
fleet "github.com/rancher/fleet/pkg/apis/fleet.cattle.io/v1alpha1"
. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
)
type MockOrasOperator struct {
ReturnOrasStore bool
Target *mocks.MockTarget
CopyMock func(ctx context.Context, src oras.ReadOnlyTarget, srcRef string, dst oras.Target, dstRef string, opts oras.CopyOptions) (ocispec.Descriptor, error)
PackManifestMock func(ctx context.Context, pusher content.Pusher, packManifestVersion oras.PackManifestVersion, artifactType string, opts oras.PackManifestOptions) (ocispec.Descriptor, error)
}
func (m *MockOrasOperator) PackManifest(ctx context.Context, pusher content.Pusher, packManifestVersion oras.PackManifestVersion, artifactType string, opts oras.PackManifestOptions) (ocispec.Descriptor, error) {
if m.PackManifestMock != nil {
return m.PackManifestMock(ctx, pusher, packManifestVersion, artifactType, opts)
}
return oras.PackManifest(ctx, pusher, packManifestVersion, artifactType, opts)
}
func (m *MockOrasOperator) Copy(ctx context.Context, src oras.ReadOnlyTarget, srcRef string, dst oras.Target, dstRef string, opts oras.CopyOptions) (ocispec.Descriptor, error) {
if m.CopyMock != nil {
return m.CopyMock(ctx, src, srcRef, dst, dstRef, opts)
}
return oras.Copy(ctx, src, srcRef, dst, dstRef, opts)
}
func (m *MockOrasOperator) NewStore() oras.Target {
if m.ReturnOrasStore {
return orasmemory.New()
}
return m.Target
}
func NewMockOrasOperator(ctrl *gomock.Controller, returnOrasStore bool) *MockOrasOperator {
return &MockOrasOperator{
ReturnOrasStore: returnOrasStore,
Target: mocks.NewMockTarget(ctrl),
}
}
var _ = Describe("OCIUtils tests", func() {
var (
ctrl *gomock.Controller
)
BeforeEach(func() {
ctrl = gomock.NewController(GinkgoT())
})
It("returns an error when can't push to the store", func() {
orasOperatorMock := NewMockOrasOperator(ctrl, false)
orasOperatorMock.Target.EXPECT().Push(gomock.Any(), gomock.Any(), gomock.Any()).Return(fmt.Errorf("TEST ERROR")).Times(1)
opts := OCIOpts{
Reference: "test.com",
}
manifest := &manifest.Manifest{
Commit: "123456",
Resources: []fleet.BundleResource{
{
Name: "resource1",
Content: "Content1",
Encoding: "encoding1",
},
},
}
oci := &OCIWrapper{
oci: orasOperatorMock,
}
err := oci.PushManifest(context.Background(), opts, "123", manifest)
Expect(err.Error()).To(Equal("TEST ERROR"))
})
It("returns an error if oras fails packing the manifest", func() {
orasOperatorMock := NewMockOrasOperator(ctrl, true)
orasOperatorMock.PackManifestMock = func(_ context.Context,
_ content.Pusher,
_ oras.PackManifestVersion,
_ string,
_ oras.PackManifestOptions) (ocispec.Descriptor, error) {
return ocispec.Descriptor{}, fmt.Errorf("ERROR PACKING")
}
oci := &OCIWrapper{
oci: orasOperatorMock,
}
opts := OCIOpts{
Reference: "test.com",
}
manifest := &manifest.Manifest{
Commit: "123456",
Resources: []fleet.BundleResource{
{
Name: "resource1",
Content: "Content1",
Encoding: "encoding1",
},
},
}
err := oci.PushManifest(context.Background(), opts, "123", manifest)
Expect(err.Error()).To(Equal("ERROR PACKING"))
})
It("returns an OCI repository with the expected values when using basic HTTP", func() {
opts := OCIOpts{
Reference: "test.com",
BasicHTTP: true,
}
repo, err := newOCIRepository("1234", opts)
Expect(err).ToNot(HaveOccurred())
Expect(repo.PlainHTTP).To(BeTrue())
opts.BasicHTTP = false
repo, err = newOCIRepository("1234", opts)
Expect(err).ToNot(HaveOccurred())
Expect(repo.PlainHTTP).To(BeFalse())
})
It("return the expected tls client", func() {
client := getHTTPClient(true, nil)
// Custom path wraps transport in retry.Transport
retryTransport, ok := client.Transport.(*retry.Transport)
Expect(ok).To(BeTrue())
innerTransport, ok := retryTransport.Base.(*http.Transport)
Expect(ok).To(BeTrue())
Expect(innerTransport.TLSClientConfig).ToNot(BeNil())
Expect(innerTransport.TLSClientConfig.InsecureSkipVerify).To(BeTrue())
Expect(innerTransport.Proxy).ToNot(BeNil())
client = getHTTPClient(false, nil)
Expect(client).To(Equal(retry.DefaultClient))
})
It("should use custom CA bundle when provided", func() {
// Use a valid test certificate from the codebase pattern (same as netutils_test.go)
caBundle := []byte(`-----BEGIN CERTIFICATE-----
MIICGTCCAZ+gAwIBAgIQCeCTZaz32ci5PhwLBCou8zAKBggqhkjOPQQDAzBOMQsw
CQYDVQQGEwJVUzEXMBUGA1UEChMORGlnaUNlcnQsIEluYy4xJjAkBgNVBAMTHURp
Z2lDZXJ0IFRMUyBFQ0MgUDM4NCBSb290IEc1MB4XDTIxMDExNTAwMDAwMFoXDTQ2
MDExNDIzNTk1OVowTjELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDkRpZ2lDZXJ0LCBJ
bmMuMSYwJAYDVQQDEx1EaWdpQ2VydCBUTFMgRUNDIFAzODQgUm9vdCBHNTB2MBAG
ByqGSM49AgEGBSuBBAAiA2IABMFEoc8Rl1Ca3iOCNQfN0MsYndLxf3c1TzvdlHJS
7cI7+Oz6e2tYIOyZrsn8aLN1udsJ7MgT9U7GCh1mMEy7H0cKPGEQQil8pQgO4CLp
0zVozptjn4S1mU1YoI71VOeVyaNCMEAwHQYDVR0OBBYEFMFRRVBZqz7nLFr6ICIS
B4CIfBFqMA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MAoGCCqGSM49
BAMDA2gAMGUCMQCJao1H5+z8blUD2WdsJk6Dxv3J+ysTvLd6jLRl0mlpYxNjOyZQ
LgGheQaRnUi/wr4CMEfDFXuxoJGZSZOoPHzoRgaLLPIxAJSdYsiJvRmEFOml+wG4
DXZDjC5Ty3zfDBeWUA==
-----END CERTIFICATE-----`)
client := getHTTPClient(false, caBundle)
// Verify transport is configured with custom TLS config
retryT, ok := client.Transport.(*retry.Transport)
Expect(ok).To(BeTrue())
transport, ok := retryT.Base.(*http.Transport)
Expect(ok).To(BeTrue())
Expect(transport.TLSClientConfig).ToNot(BeNil())
Expect(transport.TLSClientConfig.RootCAs).ToNot(BeNil())
Expect(transport.TLSClientConfig.MinVersion).To(Equal(uint16(tls.VersionTLS12)))
Expect(transport.TLSClientConfig.InsecureSkipVerify).To(BeFalse())
})
It("should merge proxy CA bundle from environment variable", func() {
// Use a valid certificate for proxy CA (same as custom test)
proxyCA := `-----BEGIN CERTIFICATE-----
MIICGTCCAZ+gAwIBAgIQCeCTZaz32ci5PhwLBCou8zAKBggqhkjOPQQDAzBOMQsw
CQYDVQQGEwJVUzEXMBUGA1UEChMORGlnaUNlcnQsIEluYy4xJjAkBgNVBAMTHURp
Z2lDZXJ0IFRMUyBFQ0MgUDM4NCBSb290IEc1MB4XDTIxMDExNTAwMDAwMFoXDTQ2
MDExNDIzNTk1OVowTjELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDkRpZ2lDZXJ0LCBJ
bmMuMSYwJAYDVQQDEx1EaWdpQ2VydCBUTFMgRUNDIFAzODQgUm9vdCBHNTB2MBAG
ByqGSM49AgEGBSuBBAAiA2IABMFEoc8Rl1Ca3iOCNQfN0MsYndLxf3c1TzvdlHJS
7cI7+Oz6e2tYIOyZrsn8aLN1udsJ7MgT9U7GCh1mMEy7H0cKPGEQQil8pQgO4CLp
0zVozptjn4S1mU1YoI71VOeVyaNCMEAwHQYDVR0OBBYEFMFRRVBZqz7nLFr6ICIS
B4CIfBFqMA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MAoGCCqGSM49
BAMDA2gAMGUCMQCJao1H5+z8blUD2WdsJk6Dxv3J+ysTvLd6jLRl0mlpYxNjOyZQ
LgGheQaRnUi/wr4CMEfDFXuxoJGZSZOoPHzoRgaLLPIxAJSdYsiJvRmEFOml+wG4
DXZDjC5Ty3zfDBeWUA==
-----END CERTIFICATE-----`
os.Setenv("PROXY_CA_BUNDLE", proxyCA)
defer os.Unsetenv("PROXY_CA_BUNDLE")
// Use the same valid certificate for custom CA (simpler for testing)
customCA := []byte(proxyCA)
client := getHTTPClient(false, customCA)
// Should have merged both CAs
retryT, ok := client.Transport.(*retry.Transport)
Expect(ok).To(BeTrue())
transport, ok := retryT.Base.(*http.Transport)
Expect(ok).To(BeTrue())
Expect(transport.TLSClientConfig).ToNot(BeNil())
Expect(transport.TLSClientConfig.RootCAs).ToNot(BeNil())
Expect(transport.TLSClientConfig.MinVersion).To(Equal(uint16(tls.VersionTLS12)))
// Verify both CAs are valid and would have been loaded
testPool := x509.NewCertPool()
ok = testPool.AppendCertsFromPEM(customCA)
Expect(ok).To(BeTrue(), "custom CA bundle should be valid PEM")
ok = testPool.AppendCertsFromPEM([]byte(proxyCA))
Expect(ok).To(BeTrue(), "proxy CA bundle should be valid PEM")
})
It("should handle invalid CA bundle gracefully", func() {
invalidCA := []byte("not a valid PEM certificate")
client := getHTTPClient(false, invalidCA)
// Should still create a client with TLS config (warning logged)
retryT, ok := client.Transport.(*retry.Transport)
Expect(ok).To(BeTrue())
transport, ok := retryT.Base.(*http.Transport)
Expect(ok).To(BeTrue())
Expect(transport.TLSClientConfig).ToNot(BeNil())
Expect(transport.TLSClientConfig.RootCAs).ToNot(BeNil())
})
It("should handle invalid proxy CA bundle gracefully", func() {
os.Setenv("PROXY_CA_BUNDLE", "invalid proxy PEM")
defer os.Unsetenv("PROXY_CA_BUNDLE")
client := getHTTPClient(false, nil)
// Should return default client when no valid CA and not insecure
Expect(client).To(Equal(retry.DefaultClient))
})
It("should combine insecureSkipTLS with CA bundle", func() {
caBundle := []byte(`-----BEGIN CERTIFICATE-----
MIICGTCCAZ+gAwIBAgIQCeCTZaz32ci5PhwLBCou8zAKBggqhkjOPQQDAzBOMQsw
CQYDVQQGEwJVUzEXMBUGA1UEChMORGlnaUNlcnQsIEluYy4xJjAkBgNVBAMTHURp
Z2lDZXJ0IFRMUyBFQ0MgUDM4NCBSb290IEc1MB4XDTIxMDExNTAwMDAwMFoXDTQ2
MDExNDIzNTk1OVowTjELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDkRpZ2lDZXJ0LCBJ
bmMuMSYwJAYDVQQDEx1EaWdpQ2VydCBUTFMgRUNDIFAzODQgUm9vdCBHNTB2MBAG
ByqGSM49AgEGBSuBBAAiA2IABMFEoc8Rl1Ca3iOCNQfN0MsYndLxf3c1TzvdlHJS
7cI7+Oz6e2tYIOyZrsn8aLN1udsJ7MgT9U7GCh1mMEy7H0cKPGEQQil8pQgO4CLp
0zVozptjn4S1mU1YoI71VOeVyaNCMEAwHQYDVR0OBBYEFMFRRVBZqz7nLFr6ICIS
B4CIfBFqMA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MAoGCCqGSM49
BAMDA2gAMGUCMQCJao1H5+z8blUD2WdsJk6Dxv3J+ysTvLd6jLRl0mlpYxNjOyZQ
LgGheQaRnUi/wr4CMEfDFXuxoJGZSZOoPHzoRgaLLPIxAJSdYsiJvRmEFOml+wG4
DXZDjC5Ty3zfDBeWUA==
-----END CERTIFICATE-----`)
client := getHTTPClient(true, caBundle)
retryT, ok := client.Transport.(*retry.Transport)
Expect(ok).To(BeTrue())
transport, ok := retryT.Base.(*http.Transport)
Expect(ok).To(BeTrue())
Expect(transport.TLSClientConfig).ToNot(BeNil())
Expect(transport.TLSClientConfig.InsecureSkipVerify).To(BeTrue())
Expect(transport.TLSClientConfig.RootCAs).ToNot(BeNil())
Expect(transport.TLSClientConfig.MinVersion).To(Equal(uint16(tls.VersionTLS12)))
// Verify the CA bundle is valid PEM (even though InsecureSkipVerify is set)
testPool := x509.NewCertPool()
ok = testPool.AppendCertsFromPEM(caBundle)
Expect(ok).To(BeTrue(), "CA bundle should be valid PEM")
})
It("should not mutate the original CA bundle slice", func() {
// validPEM is a real certificate so that AppendCertsFromPEM succeeds and
// getHTTPClient actually reaches the append(caBundle, proxyBytes...) path.
// An invalid PEM would make the function return early without appending,
// meaning the defensive copy would never be exercised.
validPEM := []byte(`-----BEGIN CERTIFICATE-----
MIICGTCCAZ+gAwIBAgIQCeCTZaz32ci5PhwLBCou8zAKBggqhkjOPQQDAzBOMQsw
CQYDVQQGEwJVUzEXMBUGA1UEChMORGlnaUNlcnQsIEluYy4xJjAkBgNVBAMTHURp
Z2lDZXJ0IFRMUyBFQ0MgUDM4NCBSb290IEc1MB4XDTIxMDExNTAwMDAwMFoXDTQ2
MDExNDIzNTk1OVowTjELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDkRpZ2lDZXJ0LCBJ
bmMuMSYwJAYDVQQDEx1EaWdpQ2VydCBUTFMgRUNDIFAzODQgUm9vdCBHNTB2MBAG
ByqGSM49AgEGBSuBBAAiA2IABMFEoc8Rl1Ca3iOCNQfN0MsYndLxf3c1TzvdlHJS
7cI7+Oz6e2tYIOyZrsn8aLN1udsJ7MgT9U7GCh1mMEy7H0cKPGEQQil8pQgO4CLp
0zVozptjn4S1mU1YoI71VOeVyaNCMEAwHQYDVR0OBBYEFMFRRVBZqz7nLFr6ICIS
B4CIfBFqMA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MAoGCCqGSM49
BAMDA2gAMGUCMQCJao1H5+z8blUD2WdsJk6Dxv3J+ysTvLd6jLRl0mlpYxNjOyZQ
LgGheQaRnUi/wr4CMEfDFXuxoJGZSZOoPHzoRgaLLPIxAJSdYsiJvRmEFOml+wG4
DXZDjC5Ty3zfDBeWUA==
-----END CERTIFICATE-----`)
os.Setenv("PROXY_CA_BUNDLE", string(validPEM))
defer os.Unsetenv("PROXY_CA_BUNDLE")
// Allocate with excess capacity so that append can write into the backing
// array without reallocating. With len == cap (e.g. []byte("literal")),
// append always reallocates and the defensive copy makes no observable
// difference — the test would pass even without it.
originalCA := make([]byte, len(validPEM), len(validPEM)+512)
copy(originalCA, validPEM)
// backing covers the full allocation so we can detect writes past len(originalCA).
backing := originalCA[:cap(originalCA)]
_ = getHTTPClient(false, originalCA)
// The slice header and visible content must be unchanged.
Expect(originalCA).To(Equal(validPEM))
// Without the defensive copy, getHTTPClient would append '\n'+proxyBytes
// directly into the excess capacity of the caller's backing array.
Expect(backing[len(validPEM):]).To(Equal(make([]byte, 512)),
"backing array beyond len(originalCA) must not be written to")
})
It("return the expected credentials", func() {
opts := OCIOpts{
Reference: "test.com",
BasicHTTP: true,
}
client := getAuthClient(opts)
Expect(client.Credential).To(BeNil())
opts.Username = "user"
client = getAuthClient(opts)
Expect(client.Credential).ToNot(BeNil())
cred, err := client.Credential(context.Background(), "test")
Expect(err).ToNot(HaveOccurred())
Expect(cred).To(Equal(auth.Credential{
Username: "user",
Password: "",
}))
opts.Password = "pass"
client = getAuthClient(opts)
Expect(client.Credential).ToNot(BeNil())
cred, err = client.Credential(context.Background(), "test")
Expect(err).ToNot(HaveOccurred())
Expect(cred).To(Equal(auth.Credential{
Username: "user",
Password: "pass",
}))
})
It("returns an error when using an empty OCI registry reference", func() {
opts := OCIOpts{
Reference: "",
}
manifest := &manifest.Manifest{
Commit: "123456",
Resources: []fleet.BundleResource{
{
Name: "resource1",
Content: "Content1",
Encoding: "encoding1",
},
},
}
oci := NewOCIWrapper()
err := oci.PushManifest(context.Background(), opts, "123", manifest)
Expect(err.Error()).To(Equal("invalid reference: missing registry or repository"))
})
It("returns an error if the OCI manifest does not have the expected annotation id", func() {
orasOperatorMock := NewMockOrasOperator(ctrl, true)
orasOperatorMock.CopyMock = func(_ context.Context,
_ oras.ReadOnlyTarget,
_ string,
target oras.Target,
_ string,
opts oras.CopyOptions) (ocispec.Descriptor, error) {
// fill the store with data
data := []byte("This is test")
desc := ocispec.Descriptor{
MediaType: "application/octet-stream",
Digest: digest.FromBytes(data),
Size: int64(len(data)),
Annotations: map[string]string{
"id": "example_id", // this is the annotation id that is not the expected one
},
}
ctx := context.Background()
err := target.Push(ctx, desc, bytes.NewReader(data))
Expect(err).ToNot(HaveOccurred())
fileDescriptors := make([]ocispec.Descriptor, 0, 1)
fileDescriptors = append(fileDescriptors, desc)
ociOpts := oras.PackManifestOptions{
Layers: fileDescriptors,
}
manifestDescriptor, err := oras.PackManifest(ctx, target, oras.PackManifestVersion1_1, artifactType, ociOpts)
Expect(err).ToNot(HaveOccurred())
tag := "latest"
err = target.Tag(ctx, manifestDescriptor, tag)
Expect(err).ToNot(HaveOccurred())
return ocispec.Descriptor{}, nil
}
opts := OCIOpts{
Reference: "test.com",
}
oci := &OCIWrapper{
oci: orasOperatorMock,
}
_, err := oci.PullManifest(context.Background(), opts, "s-123456")
// s-123456 != example_id so PullManifest should return an error
Expect(err.Error()).To(Equal("could not find expected id in Descriptor's annotations"))
})
It("returns an error if the OCI manifest does not have the expected tag", func() {
orasOperatorMock := NewMockOrasOperator(ctrl, true)
orasOperatorMock.CopyMock = func(_ context.Context, _ oras.ReadOnlyTarget, _ string, target oras.Target, _ string, opts oras.CopyOptions) (ocispec.Descriptor, error) {
// fill the store with data
data := []byte("This is test")
desc := ocispec.Descriptor{
MediaType: "application/octet-stream",
Digest: digest.FromBytes(data),
Size: int64(len(data)),
Annotations: map[string]string{
"id": "example_id", // this is the annotation id that is not the expected one
},
}
ctx := context.Background()
err := target.Push(ctx, desc, bytes.NewReader(data))
Expect(err).ToNot(HaveOccurred())
fileDescriptors := make([]ocispec.Descriptor, 0, 1)
fileDescriptors = append(fileDescriptors, desc)
ociOpts := oras.PackManifestOptions{
Layers: fileDescriptors,
}
manifestDescriptor, err := oras.PackManifest(ctx, target, oras.PackManifestVersion1_1, artifactType, ociOpts)
Expect(err).ToNot(HaveOccurred())
tag := "this_tag_is_not_expected"
err = target.Tag(ctx, manifestDescriptor, tag)
Expect(err).ToNot(HaveOccurred())
return ocispec.Descriptor{}, nil
}
opts := OCIOpts{
Reference: "test.com",
}
oci := &OCIWrapper{
oci: orasOperatorMock,
}
_, err := oci.PullManifest(context.Background(), opts, "s-123456")
Expect(err.Error()).To(ContainSubstring("not found"))
})
It("returns an error if the OCI manifest is empty", func() {
orasOperatorMock := NewMockOrasOperator(ctrl, true)
orasOperatorMock.CopyMock = func(_ context.Context, _ oras.ReadOnlyTarget, _ string, target oras.Target, _ string, opts oras.CopyOptions) (ocispec.Descriptor, error) {
// fill the store with an empty manifest
ctx := context.Background()
fileDescriptors := make([]ocispec.Descriptor, 0)
ociOpts := oras.PackManifestOptions{
Layers: fileDescriptors,
}
manifestDescriptor, err := oras.PackManifest(ctx, target, oras.PackManifestVersion1_1, artifactType, ociOpts)
Expect(err).ToNot(HaveOccurred())
tag := "latest"
err = target.Tag(ctx, manifestDescriptor, tag)
Expect(err).ToNot(HaveOccurred())
return ocispec.Descriptor{}, nil
}
opts := OCIOpts{
Reference: "test.com",
}
oci := &OCIWrapper{
oci: orasOperatorMock,
}
_, err := oci.PullManifest(context.Background(), opts, "s-123456")
Expect(err.Error()).To(Equal("expecting 1 Annotation in layer descriptor. Found 0"))
})
})
var _ = Describe("OCIUtils flag tests", func() {
var envBeforeTest string
BeforeEach(func() {
envBeforeTest = os.Getenv(OCIStorageFlag)
})
AfterEach(func() {
if envBeforeTest != "" {
// set the value it had before the test
Expect(os.Setenv(OCIStorageFlag, envBeforeTest)).ToNot(HaveOccurred())
} else {
Expect(os.Unsetenv(OCIStorageFlag)).ToNot(HaveOccurred())
}
})
DescribeTable("Check value returned is the expected one",
func(value string, expected bool) {
if value == "unset" {
Expect(os.Unsetenv(OCIStorageFlag)).ToNot(HaveOccurred())
} else {
Expect(os.Setenv(OCIStorageFlag, value)).ToNot(HaveOccurred())
}
result := OCIIsEnabled()
Expect(result).To(Equal(expected))
},
Entry("When setting to True", "True", true),
Entry("When setting to true", "true", true),
Entry("When setting to TRUE", "TRUE", true),
Entry("When setting to tRue", "tRue", true), // true because OCI storage is enabled by default.
Entry("When setting to false", "false", false),
Entry("When setting to whatever", "whatever", true), // true because OCI storage is enabled by default.
Entry("When not setting the value", "unset", true), // true because OCI storage is enabled by default.
)
})