github.com/uber/kraken@v0.1.4/lib/dockerregistry/transfer/rw_transferer_test.go (about)

     1  // Copyright (c) 2016-2019 Uber Technologies, Inc.
     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  package transfer
    15  
    16  import (
    17  	"bytes"
    18  	"errors"
    19  	"io/ioutil"
    20  	"testing"
    21  
    22  	"github.com/uber/kraken/build-index/tagclient"
    23  	"github.com/uber/kraken/core"
    24  	"github.com/uber/kraken/lib/store"
    25  	"github.com/uber/kraken/mocks/build-index/tagclient"
    26  	"github.com/uber/kraken/mocks/origin/blobclient"
    27  	"github.com/uber/kraken/utils/dockerutil"
    28  	"github.com/uber/kraken/utils/mockutil"
    29  	"github.com/uber/kraken/utils/testutil"
    30  
    31  	"github.com/golang/mock/gomock"
    32  	"github.com/stretchr/testify/require"
    33  	"github.com/uber-go/tally"
    34  )
    35  
    36  type proxyTransfererMocks struct {
    37  	tags          *mocktagclient.MockClient
    38  	originCluster *mockblobclient.MockClusterClient
    39  	cas           *store.CAStore
    40  }
    41  
    42  func newReadWriteTransfererMocks(t *testing.T) (*proxyTransfererMocks, func()) {
    43  	var cleanup testutil.Cleanup
    44  
    45  	ctrl := gomock.NewController(t)
    46  	cleanup.Add(ctrl.Finish)
    47  
    48  	tags := mocktagclient.NewMockClient(ctrl)
    49  
    50  	originCluster := mockblobclient.NewMockClusterClient(ctrl)
    51  
    52  	cas, c := store.CAStoreFixture()
    53  	cleanup.Add(c)
    54  
    55  	return &proxyTransfererMocks{tags, originCluster, cas}, cleanup.Run
    56  }
    57  
    58  func (m *proxyTransfererMocks) new() *ReadWriteTransferer {
    59  	return NewReadWriteTransferer(tally.NoopScope, m.tags, m.originCluster, m.cas)
    60  }
    61  
    62  func TestReadWriteTransfererDownloadCachesBlob(t *testing.T) {
    63  	require := require.New(t)
    64  
    65  	mocks, cleanup := newReadWriteTransfererMocks(t)
    66  	defer cleanup()
    67  
    68  	transferer := mocks.new()
    69  
    70  	namespace := "docker/test-image"
    71  	blob := core.NewBlobFixture()
    72  
    73  	mocks.originCluster.EXPECT().DownloadBlob(
    74  		namespace, blob.Digest, mockutil.MatchWriter(blob.Content)).Return(nil)
    75  
    76  	// Downloading multiple times should only call blob download once.
    77  	for i := 0; i < 10; i++ {
    78  		result, err := transferer.Download(namespace, blob.Digest)
    79  		require.NoError(err)
    80  		b, err := ioutil.ReadAll(result)
    81  		require.NoError(err)
    82  		require.Equal(blob.Content, b)
    83  	}
    84  }
    85  
    86  func TestReadWriteTransfererGetTag(t *testing.T) {
    87  	require := require.New(t)
    88  
    89  	mocks, cleanup := newReadWriteTransfererMocks(t)
    90  	defer cleanup()
    91  
    92  	transferer := mocks.new()
    93  
    94  	tag := "docker/some-tag"
    95  	manifest := core.DigestFixture()
    96  
    97  	mocks.tags.EXPECT().Get(tag).Return(manifest, nil)
    98  
    99  	d, err := transferer.GetTag(tag)
   100  	require.NoError(err)
   101  	require.Equal(manifest, d)
   102  }
   103  
   104  func TestReadWriteTransfererGetTagNotFound(t *testing.T) {
   105  	require := require.New(t)
   106  
   107  	mocks, cleanup := newReadWriteTransfererMocks(t)
   108  	defer cleanup()
   109  
   110  	transferer := mocks.new()
   111  
   112  	tag := "docker/some-tag"
   113  
   114  	mocks.tags.EXPECT().Get(tag).Return(core.Digest{}, tagclient.ErrTagNotFound)
   115  
   116  	_, err := transferer.GetTag(tag)
   117  	require.Error(err)
   118  	require.Equal(ErrTagNotFound, err)
   119  }
   120  
   121  func TestReadWriteTransfererPutTag(t *testing.T) {
   122  	require := require.New(t)
   123  
   124  	mocks, cleanup := newReadWriteTransfererMocks(t)
   125  	defer cleanup()
   126  
   127  	transferer := mocks.new()
   128  
   129  	config := core.DigestFixture()
   130  	layer1 := core.DigestFixture()
   131  	layer2 := core.DigestFixture()
   132  
   133  	manifestDigest, rawManifest := dockerutil.ManifestFixture(config, layer1, layer2)
   134  
   135  	require.NoError(mocks.cas.CreateCacheFile(manifestDigest.Hex(), bytes.NewReader(rawManifest)))
   136  
   137  	tag := "docker/some-tag"
   138  
   139  	mocks.tags.EXPECT().PutAndReplicate(tag, manifestDigest).Return(nil)
   140  
   141  	require.NoError(transferer.PutTag(tag, manifestDigest))
   142  }
   143  
   144  func TestReadWriteTransfererStatLocalBlob(t *testing.T) {
   145  	require := require.New(t)
   146  
   147  	mocks, cleanup := newReadWriteTransfererMocks(t)
   148  	defer cleanup()
   149  
   150  	transferer := mocks.new()
   151  
   152  	namespace := "docker/test-image"
   153  	blob := core.NewBlobFixture()
   154  
   155  	require.NoError(mocks.cas.CreateCacheFile(blob.Digest.Hex(), bytes.NewReader(blob.Content)))
   156  
   157  	bi, err := transferer.Stat(namespace, blob.Digest)
   158  	require.NoError(err)
   159  	require.Equal(blob.Info(), bi)
   160  }
   161  
   162  func TestReadWriteTransfererStatRemoteBlob(t *testing.T) {
   163  	require := require.New(t)
   164  
   165  	mocks, cleanup := newReadWriteTransfererMocks(t)
   166  	defer cleanup()
   167  
   168  	transferer := mocks.new()
   169  
   170  	namespace := "docker/test-image"
   171  	blob := core.NewBlobFixture()
   172  
   173  	mocks.originCluster.EXPECT().Stat(namespace, blob.Digest).Return(blob.Info(), nil)
   174  
   175  	bi, err := transferer.Stat(namespace, blob.Digest)
   176  	require.NoError(err)
   177  	require.Equal(blob.Info(), bi)
   178  }
   179  
   180  func TestReadWriteTransfererStatNotFoundOnAnyOriginError(t *testing.T) {
   181  	require := require.New(t)
   182  
   183  	mocks, cleanup := newReadWriteTransfererMocks(t)
   184  	defer cleanup()
   185  
   186  	transferer := mocks.new()
   187  
   188  	namespace := "docker/test-image"
   189  	blob := core.NewBlobFixture()
   190  
   191  	mocks.originCluster.EXPECT().Stat(namespace, blob.Digest).Return(nil, errors.New("any error"))
   192  
   193  	_, err := transferer.Stat(namespace, blob.Digest)
   194  	require.Equal(ErrBlobNotFound, err)
   195  }