github.com/mika/distribution@v2.2.2-0.20160108133430-a75790e3d8e0+incompatible/registry/proxy/proxymanifeststore_test.go (about)

     1  package proxy
     2  
     3  import (
     4  	"io"
     5  	"testing"
     6  
     7  	"github.com/docker/distribution"
     8  	"github.com/docker/distribution/context"
     9  	"github.com/docker/distribution/digest"
    10  	"github.com/docker/distribution/manifest"
    11  	"github.com/docker/distribution/manifest/schema1"
    12  	"github.com/docker/distribution/registry/proxy/scheduler"
    13  	"github.com/docker/distribution/registry/storage"
    14  	"github.com/docker/distribution/registry/storage/cache/memory"
    15  	"github.com/docker/distribution/registry/storage/driver/inmemory"
    16  	"github.com/docker/distribution/testutil"
    17  	"github.com/docker/libtrust"
    18  )
    19  
    20  type statsManifest struct {
    21  	manifests distribution.ManifestService
    22  	stats     map[string]int
    23  }
    24  
    25  type manifestStoreTestEnv struct {
    26  	manifestDigest digest.Digest // digest of the signed manifest in the local storage
    27  	manifests      proxyManifestStore
    28  }
    29  
    30  func (te manifestStoreTestEnv) LocalStats() *map[string]int {
    31  	ls := te.manifests.localManifests.(statsManifest).stats
    32  	return &ls
    33  }
    34  
    35  func (te manifestStoreTestEnv) RemoteStats() *map[string]int {
    36  	rs := te.manifests.remoteManifests.(statsManifest).stats
    37  	return &rs
    38  }
    39  
    40  func (sm statsManifest) Delete(ctx context.Context, dgst digest.Digest) error {
    41  	sm.stats["delete"]++
    42  	return sm.manifests.Delete(ctx, dgst)
    43  }
    44  
    45  func (sm statsManifest) Exists(ctx context.Context, dgst digest.Digest) (bool, error) {
    46  	sm.stats["exists"]++
    47  	return sm.manifests.Exists(ctx, dgst)
    48  }
    49  
    50  func (sm statsManifest) Get(ctx context.Context, dgst digest.Digest, options ...distribution.ManifestServiceOption) (distribution.Manifest, error) {
    51  	sm.stats["get"]++
    52  	return sm.manifests.Get(ctx, dgst)
    53  }
    54  
    55  func (sm statsManifest) Put(ctx context.Context, manifest distribution.Manifest, options ...distribution.ManifestServiceOption) (digest.Digest, error) {
    56  	sm.stats["put"]++
    57  	return sm.manifests.Put(ctx, manifest)
    58  }
    59  
    60  /*func (sm statsManifest) Enumerate(ctx context.Context, manifests []distribution.Manifest, last distribution.Manifest) (n int, err error) {
    61  	sm.stats["enumerate"]++
    62  	return sm.manifests.Enumerate(ctx, manifests, last)
    63  }
    64  */
    65  
    66  func newManifestStoreTestEnv(t *testing.T, name, tag string) *manifestStoreTestEnv {
    67  	ctx := context.Background()
    68  	truthRegistry, err := storage.NewRegistry(ctx, inmemory.New(), storage.BlobDescriptorCacheProvider(memory.NewInMemoryBlobDescriptorCacheProvider()))
    69  	if err != nil {
    70  		t.Fatalf("error creating registry: %v", err)
    71  	}
    72  	truthRepo, err := truthRegistry.Repository(ctx, name)
    73  	if err != nil {
    74  		t.Fatalf("unexpected error getting repo: %v", err)
    75  	}
    76  	tr, err := truthRepo.Manifests(ctx)
    77  	if err != nil {
    78  		t.Fatal(err.Error())
    79  	}
    80  	truthManifests := statsManifest{
    81  		manifests: tr,
    82  		stats:     make(map[string]int),
    83  	}
    84  
    85  	manifestDigest, err := populateRepo(t, ctx, truthRepo, name, tag)
    86  	if err != nil {
    87  		t.Fatalf(err.Error())
    88  	}
    89  
    90  	localRegistry, err := storage.NewRegistry(ctx, inmemory.New(), storage.BlobDescriptorCacheProvider(memory.NewInMemoryBlobDescriptorCacheProvider()), storage.EnableRedirect, storage.DisableDigestResumption)
    91  	if err != nil {
    92  		t.Fatalf("error creating registry: %v", err)
    93  	}
    94  	localRepo, err := localRegistry.Repository(ctx, name)
    95  	if err != nil {
    96  		t.Fatalf("unexpected error getting repo: %v", err)
    97  	}
    98  	lr, err := localRepo.Manifests(ctx)
    99  	if err != nil {
   100  		t.Fatal(err.Error())
   101  	}
   102  
   103  	localManifests := statsManifest{
   104  		manifests: lr,
   105  		stats:     make(map[string]int),
   106  	}
   107  
   108  	s := scheduler.New(ctx, inmemory.New(), "/scheduler-state.json")
   109  	return &manifestStoreTestEnv{
   110  		manifestDigest: manifestDigest,
   111  		manifests: proxyManifestStore{
   112  			ctx:             ctx,
   113  			localManifests:  localManifests,
   114  			remoteManifests: truthManifests,
   115  			scheduler:       s,
   116  		},
   117  	}
   118  }
   119  
   120  func populateRepo(t *testing.T, ctx context.Context, repository distribution.Repository, name, tag string) (digest.Digest, error) {
   121  	m := schema1.Manifest{
   122  		Versioned: manifest.Versioned{
   123  			SchemaVersion: 1,
   124  		},
   125  		Name: name,
   126  		Tag:  tag,
   127  	}
   128  
   129  	for i := 0; i < 2; i++ {
   130  		wr, err := repository.Blobs(ctx).Create(ctx)
   131  		if err != nil {
   132  			t.Fatalf("unexpected error creating test upload: %v", err)
   133  		}
   134  
   135  		rs, ts, err := testutil.CreateRandomTarFile()
   136  		if err != nil {
   137  			t.Fatalf("unexpected error generating test layer file")
   138  		}
   139  		dgst := digest.Digest(ts)
   140  		if _, err := io.Copy(wr, rs); err != nil {
   141  			t.Fatalf("unexpected error copying to upload: %v", err)
   142  		}
   143  
   144  		if _, err := wr.Commit(ctx, distribution.Descriptor{Digest: dgst}); err != nil {
   145  			t.Fatalf("unexpected error finishing upload: %v", err)
   146  		}
   147  	}
   148  
   149  	pk, err := libtrust.GenerateECP256PrivateKey()
   150  	if err != nil {
   151  		t.Fatalf("unexpected error generating private key: %v", err)
   152  	}
   153  
   154  	sm, err := schema1.Sign(&m, pk)
   155  	if err != nil {
   156  		t.Fatalf("error signing manifest: %v", err)
   157  	}
   158  
   159  	ms, err := repository.Manifests(ctx)
   160  	if err != nil {
   161  		t.Fatalf(err.Error())
   162  	}
   163  	dgst, err := ms.Put(ctx, sm)
   164  	if err != nil {
   165  		t.Fatalf("unexpected errors putting manifest: %v", err)
   166  	}
   167  
   168  	return dgst, nil
   169  }
   170  
   171  // TestProxyManifests contains basic acceptance tests
   172  // for the pull-through behavior
   173  func TestProxyManifests(t *testing.T) {
   174  	name := "foo/bar"
   175  	env := newManifestStoreTestEnv(t, name, "latest")
   176  
   177  	localStats := env.LocalStats()
   178  	remoteStats := env.RemoteStats()
   179  
   180  	ctx := context.Background()
   181  	// Stat - must check local and remote
   182  	exists, err := env.manifests.Exists(ctx, env.manifestDigest)
   183  	if err != nil {
   184  		t.Fatalf("Error checking existance")
   185  	}
   186  	if !exists {
   187  		t.Errorf("Unexpected non-existant manifest")
   188  	}
   189  
   190  	if (*localStats)["exists"] != 1 && (*remoteStats)["exists"] != 1 {
   191  		t.Errorf("Unexpected exists count : \n%v \n%v", localStats, remoteStats)
   192  	}
   193  
   194  	// Get - should succeed and pull manifest into local
   195  	_, err = env.manifests.Get(ctx, env.manifestDigest)
   196  	if err != nil {
   197  		t.Fatal(err)
   198  	}
   199  
   200  	if (*localStats)["get"] != 1 && (*remoteStats)["get"] != 1 {
   201  		t.Errorf("Unexpected get count")
   202  	}
   203  
   204  	if (*localStats)["put"] != 1 {
   205  		t.Errorf("Expected local put")
   206  	}
   207  
   208  	// Stat - should only go to local
   209  	exists, err = env.manifests.Exists(ctx, env.manifestDigest)
   210  	if err != nil {
   211  		t.Fatal(err)
   212  	}
   213  	if !exists {
   214  		t.Errorf("Unexpected non-existant manifest")
   215  	}
   216  
   217  	if (*localStats)["exists"] != 2 && (*remoteStats)["exists"] != 1 {
   218  		t.Errorf("Unexpected exists count")
   219  	}
   220  
   221  	// Get - should get from remote, to test freshness
   222  	_, err = env.manifests.Get(ctx, env.manifestDigest)
   223  	if err != nil {
   224  		t.Fatal(err)
   225  	}
   226  
   227  	if (*remoteStats)["get"] != 2 && (*remoteStats)["exists"] != 1 && (*localStats)["put"] != 1 {
   228  		t.Errorf("Unexpected get count")
   229  	}
   230  }
   231  
   232  func TestProxyTagService(t *testing.T) {
   233  
   234  }