...

Source file src/cuelabs.dev/go/oci/ociregistry/ocifilter/sub_test.go

Documentation: cuelabs.dev/go/oci/ociregistry/ocifilter

     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  	"sort"
    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 := ocitest.NewRegistry(t, Sub(r.R, "foo"))
    94  	desc, err := r1.R.ResolveTag(ctx, "bar", "t1")
    95  	qt.Assert(t, qt.IsNil(err))
    96  
    97  	m := getManifest(t, r1.R, "bar", desc.Digest)
    98  	b1Content := getBlob(t, r1.R, "bar", m.Layers[0].Digest)
    99  	qt.Assert(t, qt.Equals(string(b1Content), "hello"))
   100  
   101  	repos, err := ociregistry.All(r1.R.Repositories(ctx, ""))
   102  	qt.Assert(t, qt.IsNil(err))
   103  	sort.Strings(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  }
   157  

View as plain text