cuelabs.dev/go/oci/ociregistry@v0.0.0-20240906074133-82eb438dd565/ocifilter/sub_test.go (about) 1 // Copyright 2023 CUE Labs AG 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package ocifilter 16 17 import ( 18 "context" 19 "encoding/json" 20 "fmt" 21 "io" 22 "slices" 23 "testing" 24 25 "github.com/go-quicktest/qt" 26 "github.com/opencontainers/go-digest" 27 ocispec "github.com/opencontainers/image-spec/specs-go/v1" 28 29 "cuelabs.dev/go/oci/ociregistry" 30 "cuelabs.dev/go/oci/ociregistry/ociauth" 31 "cuelabs.dev/go/oci/ociregistry/ocimem" 32 "cuelabs.dev/go/oci/ociregistry/ocitest" 33 ) 34 35 func TestSub(t *testing.T) { 36 ctx := context.Background() 37 r := ocitest.NewRegistry(t, ocimem.New()) 38 r.MustPushContent(ocitest.RegistryContent{ 39 "foo/bar": { 40 Blobs: map[string]string{ 41 "b1": "hello", 42 "scratch": "{}", 43 }, 44 Manifests: map[string]ociregistry.Manifest{ 45 "m1": { 46 MediaType: ocispec.MediaTypeImageManifest, 47 Config: ociregistry.Descriptor{ 48 Digest: "scratch", 49 }, 50 Layers: []ociregistry.Descriptor{{ 51 Digest: "b1", 52 }}, 53 }, 54 }, 55 Tags: map[string]string{ 56 "t1": "m1", 57 "t2": "m1", 58 }, 59 }, 60 "fooey": { 61 Blobs: map[string]string{ 62 "scratch": "{}", 63 }, 64 Manifests: map[string]ociregistry.Manifest{ 65 "m1": { 66 MediaType: ocispec.MediaTypeImageManifest, 67 Config: ociregistry.Descriptor{ 68 Digest: "scratch", 69 }, 70 }, 71 }, 72 Tags: map[string]string{ 73 "t1": "m1", 74 }, 75 }, 76 "other/blah": { 77 Blobs: map[string]string{ 78 "scratch": "{}", 79 }, 80 Manifests: map[string]ociregistry.Manifest{ 81 "m1": { 82 MediaType: ocispec.MediaTypeImageManifest, 83 Config: ociregistry.Descriptor{ 84 Digest: "scratch", 85 }, 86 }, 87 }, 88 Tags: map[string]string{ 89 "t1": "m1", 90 }, 91 }, 92 }) 93 r1 := Sub(r.R, "foo") 94 desc, err := r1.ResolveTag(ctx, "bar", "t1") 95 qt.Assert(t, qt.IsNil(err)) 96 97 m := getManifest(t, r1, "bar", desc.Digest) 98 b1Content := getBlob(t, r1, "bar", m.Layers[0].Digest) 99 qt.Assert(t, qt.Equals(string(b1Content), "hello")) 100 101 repos, err := ociregistry.All(r1.Repositories(ctx, "")) 102 qt.Assert(t, qt.IsNil(err)) 103 slices.Sort(repos) 104 qt.Assert(t, qt.DeepEquals(repos, []string{"bar"})) 105 } 106 107 func TestSubMaintainsAuthScope(t *testing.T) { 108 var gotScope ociauth.Scope 109 r := Sub(contextChecker{ 110 check: func(ctx context.Context) { 111 gotScope = ociauth.ScopeFromContext(ctx) 112 }, 113 }, "foo/bar") 114 scope := ociauth.ParseScope("other registry:catalog:* repository:a/b:pull,push repository:foo:delete,push") 115 ctx := ociauth.ContextWithScope(context.Background(), scope) 116 117 // As the implementation is so uniform (and easily inspected in the source, 118 // we use the GetBlob entry point as a proxy for testing all the entry points. 119 // TODO it would be nice to have a reusable way (in ocitest, probably) of testing general properties 120 // across all ociregistry.Interface methods. 121 _, _ = r.GetBlob(ctx, "some/repo", "sha256:fffff") 122 qt.Assert(t, qt.DeepEquals(gotScope, ociauth.ParseScope( 123 "other registry:catalog:* repository:foo/bar/a/b:pull,push repository:foo/bar/foo:delete,push", 124 ))) 125 } 126 127 type contextChecker struct { 128 ociregistry.Interface 129 check func(context.Context) 130 } 131 132 func (r contextChecker) GetBlob(ctx context.Context, repo string, digest ociregistry.Digest) (ociregistry.BlobReader, error) { 133 r.check(ctx) 134 return nil, fmt.Errorf("nope") 135 } 136 137 func getManifest(t *testing.T, r ociregistry.Interface, repo string, dg digest.Digest) ociregistry.Manifest { 138 rd, err := r.GetManifest(context.Background(), repo, dg) 139 qt.Assert(t, qt.IsNil(err)) 140 defer rd.Close() 141 var m ociregistry.Manifest 142 data, err := io.ReadAll(rd) 143 qt.Assert(t, qt.IsNil(err)) 144 err = json.Unmarshal(data, &m) 145 qt.Assert(t, qt.IsNil(err)) 146 return m 147 } 148 149 func getBlob(t *testing.T, r ociregistry.Interface, repo string, dg digest.Digest) []byte { 150 rd, err := r.GetBlob(context.Background(), repo, dg) 151 qt.Assert(t, qt.IsNil(err)) 152 defer rd.Close() 153 data, err := io.ReadAll(rd) 154 qt.Assert(t, qt.IsNil(err)) 155 return data 156 }