// newRepositoryWithClient returns a new repository middleware. func newRepositoryWithClient( registryOSClient client.Interface, quotaClient kcoreclient.ResourceQuotasGetter, limitClient kcoreclient.LimitRangesGetter, ctx context.Context, repo distribution.Repository, options map[string]interface{}, ) (distribution.Repository, error) { registryAddr := os.Getenv(DockerRegistryURLEnvVar) if len(registryAddr) == 0 { return nil, fmt.Errorf("%s is required", DockerRegistryURLEnvVar) } acceptschema2, err := getBoolOption(AcceptSchema2EnvVar, "acceptschema2", false, options) if err != nil { context.GetLogger(ctx).Error(err) } blobrepositorycachettl, err := getDurationOption(BlobRepositoryCacheTTLEnvVar, "blobrepositorycachettl", defaultBlobRepositoryCacheTTL, options) if err != nil { context.GetLogger(ctx).Error(err) } pullthrough, err := getBoolOption(PullthroughEnvVar, "pullthrough", true, options) if err != nil { context.GetLogger(ctx).Error(err) } mirrorPullthrough, err := getBoolOption(MirrorPullthroughEnvVar, "mirrorpullthrough", true, options) if err != nil { context.GetLogger(ctx).Error(err) } nameParts := strings.SplitN(repo.Named().Name(), "/", 2) if len(nameParts) != 2 { return nil, fmt.Errorf("invalid repository name %q: it must be of the format <project>/<name>", repo.Named().Name()) } return &repository{ Repository: repo, ctx: ctx, quotaClient: quotaClient, limitClient: limitClient, registryOSClient: registryOSClient, registryAddr: registryAddr, namespace: nameParts[0], name: nameParts[1], acceptschema2: acceptschema2, blobrepositorycachettl: blobrepositorycachettl, pullthrough: pullthrough, mirrorPullthrough: mirrorPullthrough, cachedLayers: cachedLayers, }, nil }
// newRepositoryWithClient returns a new repository middleware. func newRepositoryWithClient( registryOSClient client.Interface, quotaClient kclient.ResourceQuotasNamespacer, limitClient kclient.LimitRangesNamespacer, ctx context.Context, repo distribution.Repository, options map[string]interface{}, ) (distribution.Repository, error) { registryAddr := os.Getenv(DockerRegistryURLEnvVar) if len(registryAddr) == 0 { return nil, fmt.Errorf("%s is required", DockerRegistryURLEnvVar) } pullthrough := getBoolOption("pullthrough", false, options) acceptschema2 := false if os.Getenv(AcceptSchema2EnvVar) != "" { acceptschema2 = os.Getenv(AcceptSchema2EnvVar) == "true" } else { acceptschema2 = getBoolOption("acceptschema2", false, options) } nameParts := strings.SplitN(repo.Named().Name(), "/", 2) if len(nameParts) != 2 { return nil, fmt.Errorf("invalid repository name %q: it must be of the format <project>/<name>", repo.Named().Name()) } return &repository{ Repository: repo, ctx: ctx, quotaClient: quotaClient, limitClient: limitClient, registryOSClient: registryOSClient, registryAddr: registryAddr, namespace: nameParts[0], name: nameParts[1], pullthrough: pullthrough, acceptschema2: acceptschema2, cachedLayers: cachedLayers, }, nil }
// checkExerciseRegistry takes the registry through all of its operations, // carrying out generic checks. func checkExerciseRepository(t *testing.T, repository distribution.Repository) { // TODO(stevvooe): This would be a nice testutil function. Basically, it // takes the registry through a common set of operations. This could be // used to make cross-cutting updates by changing internals that affect // update counts. Basically, it would make writing tests a lot easier. ctx := context.Background() tag := "thetag" // todo: change this to use Builder m := schema1.Manifest{ Versioned: manifest.Versioned{ SchemaVersion: 1, }, Name: repository.Named().Name(), Tag: tag, } blobs := repository.Blobs(ctx) for i := 0; i < 2; i++ { rs, ds, err := testutil.CreateRandomTarFile() if err != nil { t.Fatalf("error creating test layer: %v", err) } dgst := digest.Digest(ds) wr, err := blobs.Create(ctx) if err != nil { t.Fatalf("error creating layer upload: %v", err) } // Use the resumes, as well! wr, err = blobs.Resume(ctx, wr.ID()) if err != nil { t.Fatalf("error resuming layer upload: %v", err) } io.Copy(wr, rs) if _, err := wr.Commit(ctx, distribution.Descriptor{Digest: dgst}); err != nil { t.Fatalf("unexpected error finishing upload: %v", err) } m.FSLayers = append(m.FSLayers, schema1.FSLayer{ BlobSum: dgst, }) m.History = append(m.History, schema1.History{ V1Compatibility: "", }) // Then fetch the blobs if rc, err := blobs.Open(ctx, dgst); err != nil { t.Fatalf("error fetching layer: %v", err) } else { defer rc.Close() } } pk, err := libtrust.GenerateECP256PrivateKey() if err != nil { t.Fatalf("unexpected error generating key: %v", err) } sm, err := schema1.Sign(&m, pk) if err != nil { t.Fatalf("unexpected error signing manifest: %v", err) } manifests, err := repository.Manifests(ctx) if err != nil { t.Fatal(err.Error()) } var digestPut digest.Digest if digestPut, err = manifests.Put(ctx, sm); err != nil { t.Fatalf("unexpected error putting the manifest: %v", err) } dgst := digest.FromBytes(sm.Canonical) if dgst != digestPut { t.Fatalf("mismatching digest from payload and put") } _, err = manifests.Get(ctx, dgst) if err != nil { t.Fatalf("unexpected error fetching manifest: %v", err) } }