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 }