Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add flag to skip deleting obsolete referrers index #957

Merged
merged 48 commits into from
Jul 3, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
48 commits
Select commit Hold shift + click to select a range
8b22600
feat!: add flag for referrers GC
qweeah May 29, 2023
7b7e5a4
update go mod
qweeah May 29, 2023
e27d723
fix e2e
qweeah May 29, 2023
57b4e75
add e2e
qweeah May 29, 2023
adfcca1
update deps
qweeah May 29, 2023
cacd6bb
update dep
qweeah May 30, 2023
f0ecebf
update
qweeah May 30, 2023
ffbd8bc
update version
qweeah May 30, 2023
d5f1937
mod tidy
qweeah May 30, 2023
abae524
fix e2e
qweeah May 30, 2023
06d382d
rename flag
qweeah Jun 1, 2023
86f3b1d
fix: default to true
qweeah Jun 2, 2023
19c4516
fix e2e
qweeah Jun 2, 2023
623dc99
change default value to false
qweeah Jun 6, 2023
aa73bc9
fix e2e
qweeah Jun 6, 2023
aa91493
fix e2e
qweeah Jun 6, 2023
06af37b
refactor: simplify e2e scripts and github action
qweeah Jun 6, 2023
f78e02d
fix makefile
qweeah Jun 6, 2023
3b2f883
fix e2e
qweeah Jun 6, 2023
5d1b6f2
remove global coverage dump path
qweeah Jun 6, 2023
71a1551
feat!: add flag for referrers GC
qweeah May 29, 2023
8c34fb3
update go mod
qweeah May 29, 2023
f0ddea5
fix e2e
qweeah May 29, 2023
d5d1b75
add e2e
qweeah May 29, 2023
c7fc74b
update deps
qweeah May 29, 2023
84a9542
update dep
qweeah May 30, 2023
0d3705d
update
qweeah May 30, 2023
ce74b34
update version
qweeah May 30, 2023
43f8b3e
mod tidy
qweeah May 30, 2023
9664843
fix e2e
qweeah May 30, 2023
a397824
rename flag
qweeah Jun 1, 2023
7984217
fix: default to true
qweeah Jun 2, 2023
cd95fa1
fix e2e
qweeah Jun 2, 2023
da91691
change default value to false
qweeah Jun 6, 2023
b302cdb
fix e2e
qweeah Jun 6, 2023
e698088
fix e2e
qweeah Jun 6, 2023
785e8b9
test: add e2e for referrers GC
qweeah Jun 6, 2023
be69555
Merge branch 'gc-referrers' of github.com:qweeah/oras into gc-referrers
qweeah Jun 6, 2023
1084fa6
add error hint
qweeah Jun 8, 2023
6ba07e5
Merge branch 'main' into gc-referrers
Jun 8, 2023
f033ead
Merge branch 'main' into gc-referrers
qweeah Jun 9, 2023
4e9b9fa
Merge branch 'gc-referrers' of github.com:qweeah/oras into gc-referrers
qweeah Jun 9, 2023
bec6661
Merge branch 'main' into gc-referrers
qweeah Jun 28, 2023
a69435d
Merge branch 'main' into gc-referrers
qweeah Jun 28, 2023
fdc59b8
Merge remote-tracking branch 'origin-upstream/main' into gc-referrers
qweeah Jun 29, 2023
6b92395
bug fix
qweeah Jun 29, 2023
757f2ae
update comment
qweeah Jul 3, 2023
474c798
Merge branch 'main' into gc-referrers
qweeah Jul 3, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions cmd/oras/internal/errors/errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,11 @@ limitations under the License.
package errors

import (
"errors"
"fmt"

"oras.land/oras-go/v2/registry"
"oras.land/oras-go/v2/registry/remote"
)

// NewErrInvalidReference creates a new error based on the reference string.
Expand All @@ -30,3 +32,9 @@ func NewErrInvalidReference(ref registry.Reference) error {
func NewErrInvalidReferenceStr(ref string) error {
return fmt.Errorf("%s: invalid image reference, expecting <name:tag|name@digest>", ref)
}

// IsReferrersIndexDelete checks if err is a referrers index delete error.
func IsReferrersIndexDelete(err error) bool {
var re *remote.ReferrersError
return errors.As(err, &re) && re.IsReferrersIndexDelete()
}
42 changes: 42 additions & 0 deletions cmd/oras/internal/option/referrers.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
/*
Copyright The ORAS Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package option

import (
"github.com/sirupsen/logrus"
"github.com/spf13/pflag"
"oras.land/oras-go/v2/registry/remote"
)

// Referrers option struct.
type Referrers struct {
SkipDeleteReferrers bool
}

// ApplyFlags applies flags to a command flag set.
func (opts *Referrers) ApplyFlags(fs *pflag.FlagSet) {
fs.BoolVarP(&opts.SkipDeleteReferrers, "skip-delete-referrers", "", false, "skip deleting old referrers index, only work on registry when referrers API is not supported")
qweeah marked this conversation as resolved.
Show resolved Hide resolved
}

// SetReferrersGC sets the referrers GC option for the passed-in target.
func (opts *Referrers) SetReferrersGC(target any, logger logrus.FieldLogger) {
if repo, ok := target.(*remote.Repository); ok {
repo.SkipReferrersGC = opts.SkipDeleteReferrers
} else if opts.SkipDeleteReferrers {
// not a registry, can't skip referrers deletion
logger.Warnln("referrers deletion can only be enforced upon registry")
}
}
10 changes: 9 additions & 1 deletion cmd/oras/root/attach.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,15 @@ import (
"context"
"errors"
"fmt"
"os"
"strings"

ocispec "github.com/opencontainers/image-spec/specs-go/v1"
"github.com/spf13/cobra"
"oras.land/oras-go/v2"
"oras.land/oras-go/v2/content"
"oras.land/oras-go/v2/content/file"
oerr "oras.land/oras/cmd/oras/internal/errors"
"oras.land/oras/cmd/oras/internal/option"
"oras.land/oras/internal/graph"
)
Expand All @@ -35,6 +37,7 @@ type attachOptions struct {
option.Packer
option.ImageSpec
option.Target
option.Referrers

artifactType string
concurrency int
Expand Down Expand Up @@ -98,7 +101,7 @@ Example - Attach file to the manifest tagged 'v1' in an OCI image layout folder
}

func runAttach(ctx context.Context, opts attachOptions) error {
ctx, _ = opts.WithContext(ctx)
ctx, logger := opts.WithContext(ctx)
annotations, err := opts.LoadManifestAnnotations()
if err != nil {
return err
Expand All @@ -121,6 +124,8 @@ func runAttach(ctx context.Context, opts attachOptions) error {
if err := opts.EnsureReferenceNotEmpty(); err != nil {
return err
}
opts.SetReferrersGC(dst, logger)

subject, err := dst.Resolve(ctx, opts.Reference)
if err != nil {
return err
Expand Down Expand Up @@ -163,6 +168,9 @@ func runAttach(ctx context.Context, opts attachOptions) error {

root, err := pushArtifact(dst, pack, copy)
if err != nil {
if oerr.IsReferrersIndexDelete(err) {
fmt.Fprintln(os.Stderr, "attached successfully but failed to remove the outdated referrers index, please use `--skip-delete-referrers` if you want to skip the deletion")
}
return err
}

Expand Down
9 changes: 8 additions & 1 deletion cmd/oras/root/cp.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ package root
import (
"context"
"fmt"
"os"
"strings"
"sync"

Expand All @@ -26,6 +27,7 @@ import (
"github.com/spf13/cobra"
"oras.land/oras-go/v2"
"oras.land/oras/cmd/oras/internal/display"
oerr "oras.land/oras/cmd/oras/internal/errors"
"oras.land/oras/cmd/oras/internal/option"
"oras.land/oras/internal/graph"
)
Expand All @@ -34,6 +36,7 @@ type copyOptions struct {
option.Common
option.Platform
option.BinaryTarget
option.Referrers

recursive bool
concurrency int
Expand Down Expand Up @@ -96,7 +99,7 @@ Example - Copy an artifact with multiple tags with concurrency tuned:
}

func runCopy(ctx context.Context, opts copyOptions) error {
ctx, _ = opts.WithContext(ctx)
ctx, logger := opts.WithContext(ctx)

// Prepare source
src, err := opts.From.NewReadonlyTarget(ctx, opts.Common)
Expand All @@ -112,6 +115,7 @@ func runCopy(ctx context.Context, opts copyOptions) error {
if err != nil {
return err
}
opts.SetReferrersGC(dst, logger)

// Prepare copy options
committed := &sync.Map{}
Expand Down Expand Up @@ -167,6 +171,9 @@ func runCopy(ctx context.Context, opts copyOptions) error {
}
}
if err != nil {
if oerr.IsReferrersIndexDelete(err) {
fmt.Fprintln(os.Stderr, "failed to remove the outdated referrers index, please use `--skip-delete-referrers` if you want to skip the deletion")
}
return err
}

Expand Down
8 changes: 7 additions & 1 deletion cmd/oras/root/manifest/push.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import (
"oras.land/oras-go/v2/errdef"
"oras.land/oras-go/v2/registry/remote"
"oras.land/oras/cmd/oras/internal/display"
oerr "oras.land/oras/cmd/oras/internal/errors"
"oras.land/oras/cmd/oras/internal/option"
"oras.land/oras/internal/file"
)
Expand All @@ -38,6 +39,7 @@ type pushOptions struct {
option.Descriptor
option.Pretty
option.Target
option.Referrers

concurrency int
extraRefs []string
Expand Down Expand Up @@ -104,13 +106,14 @@ Example - Push a manifest to an OCI image layout folder 'layout-dir' and tag wit
}

func pushManifest(ctx context.Context, opts pushOptions) error {
ctx, _ = opts.WithContext(ctx)
ctx, logger := opts.WithContext(ctx)
var target oras.Target
var err error
target, err = opts.NewTarget(opts.Common)
if err != nil {
return err
}
opts.SetReferrersGC(target, logger)
if repo, ok := target.(*remote.Repository); ok {
target = repo.Manifests()
}
Expand Down Expand Up @@ -151,6 +154,9 @@ func pushManifest(ctx context.Context, opts pushOptions) error {
return err
}
if _, err := oras.TagBytes(ctx, target, mediaType, contentBytes, ref); err != nil {
if oerr.IsReferrersIndexDelete(err) {
fmt.Fprintln(os.Stderr, "pushed successfully but failed to remove the outdated referrers index, please use `--skip-delete-referrers` if you want to skip the deletion")
}
return err
}
if err = display.PrintStatus(desc, "Uploaded ", verbose); err != nil {
Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ require (
github.com/spf13/pflag v1.0.5
golang.org/x/term v0.9.0
gopkg.in/yaml.v3 v3.0.1
oras.land/oras-go/v2 v2.2.0
oras.land/oras-go/v2 v2.2.1-0.20230531090906-7dd0378382c6
)

require (
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -38,3 +38,5 @@ gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
oras.land/oras-go/v2 v2.2.0 h1:E1fqITD56Eg5neZbxBtAdZVgDHD6wBabJo6xESTcQyo=
oras.land/oras-go/v2 v2.2.0/go.mod h1:pXjn0+KfarspMHHNR3A56j3tgvr+mxArHuI8qVn59v8=
oras.land/oras-go/v2 v2.2.1-0.20230531090906-7dd0378382c6 h1:2P1fjq1znGLo7tjy9PJsZrFF5L+qywbv28IgzKEX62E=
oras.land/oras-go/v2 v2.2.1-0.20230531090906-7dd0378382c6/go.mod h1:pXjn0+KfarspMHHNR3A56j3tgvr+mxArHuI8qVn59v8=
2 changes: 1 addition & 1 deletion test/e2e/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ go test oras.land/oras/test/e2e/suite/${suite_name}
This is super handy when you want to do step-by-step debugging from command-line or via an IDE. If you need to debug certain specs, use [focused specs](https://onsi.github.io/ginkgo/#focused-specs) but don't check it in.

### 4. Testing Registry Services
The backend of E2E tests are two registry services: [oras-distribution](https://github.com/oras-project/distribution) and [upstream distribution](https://github.com/distribution/distribution). The former is expected to support image and artifact media types and referrer API; The latter is expected to only support image media type with subject and provide referrers via [tag schema](https://github.com/opencontainers/distribution-spec/blob/v1.1.0-rc1/spec.md#referrers-tag-schema).
The backend of E2E tests are two registry services: [oras-distribution](https://github.com/oras-project/distribution) and [upstream distribution](https://github.com/distribution/distribution). The former is expected to support image and artifact media types and referrer API; The latter is expected to only support image media type with subject and provide referrers via [tag schema](https://github.com/opencontainers/distribution-spec/blob/v1.1.0-rc1/spec.md#referrers-tag-schema), with deletion disabled.

You can run scenario test suite against your own registry services via setting `ORAS_REGISTRY_HOST` or `ORAS_REGISTRY_FALLBACK_HOST` environmental variables.

Expand Down
2 changes: 1 addition & 1 deletion test/e2e/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ require (
github.com/opencontainers/go-digest v1.0.0
github.com/opencontainers/image-spec v1.1.0-rc.3
gopkg.in/yaml.v2 v2.4.0
oras.land/oras-go/v2 v2.2.0
oras.land/oras-go/v2 v2.2.1-0.20230531090906-7dd0378382c6
)

require (
Expand Down
4 changes: 2 additions & 2 deletions test/e2e/go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -47,5 +47,5 @@ gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
oras.land/oras-go/v2 v2.2.0 h1:E1fqITD56Eg5neZbxBtAdZVgDHD6wBabJo6xESTcQyo=
oras.land/oras-go/v2 v2.2.0/go.mod h1:pXjn0+KfarspMHHNR3A56j3tgvr+mxArHuI8qVn59v8=
oras.land/oras-go/v2 v2.2.1-0.20230531090906-7dd0378382c6 h1:2P1fjq1znGLo7tjy9PJsZrFF5L+qywbv28IgzKEX62E=
oras.land/oras-go/v2 v2.2.1-0.20230531090906-7dd0378382c6/go.mod h1:pXjn0+KfarspMHHNR3A56j3tgvr+mxArHuI8qVn59v8=
4 changes: 4 additions & 0 deletions test/e2e/internal/testdata/foobar/const.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ limitations under the License.
package foobar

import (
"fmt"

"github.com/opencontainers/go-digest"
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
"oras.land/oras/test/e2e/internal/utils/match"
Expand All @@ -24,6 +26,8 @@ import (
var (
Tag = "foobar"
Digest = "sha256:fd6ed2f36b5465244d5dc86cb4e7df0ab8a9d24adc57825099f522fe009a22bb"
Size = 851
DescriptorStr = fmt.Sprintf(`{"mediaType":"application/vnd.oci.image.manifest.v1+json","digest":"%s","size":%d}`, Digest, Size)
ManifestStateKey = match.StateKey{Digest: "fd6ed2f36b54", Name: "application/vnd.oci.image.manifest.v1+json"}

FileLayerNames = []string{
Expand Down
5 changes: 3 additions & 2 deletions test/e2e/scripts/common.sh
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,14 @@

help () {
echo "Usage"
echo " run-registry <mount-root> <image-name> <container-name> <container-port>"
echo " run-registry <mount-root> <image-name> <container-name> <container-port> <deletion-enabled>"
echo ""
echo "Arguments"
echo " mount-root root mounting directory for pre-baked registry storage files."
echo " image-name image name of the registry."
echo " container-name container name of the registry service."
echo " container-port port to export the registry service."
echo " delete-enabled if set to true, the registry service will be configured to allow deletion."
}

# run registry service for testing
Expand Down Expand Up @@ -61,7 +62,7 @@ run_registry () {
try_clean_up $ctr_name
docker run --pull always -d -p $ctr_port:5000 --rm --name $ctr_name \
-u $(id -u $(whoami)) \
--env REGISTRY_STORAGE_DELETE_ENABLED=true \
--env REGISTRY_STORAGE_DELETE_ENABLED=$5 \
--env REGISTRY_AUTH_HTPASSWD_REALM=test-basic \
--env REGISTRY_AUTH_HTPASSWD_PATH=/etc/docker/registry/passwd \
--mount type=bind,source=$mnt_root/docker,target=/var/lib/registry/docker \
Expand Down
6 changes: 4 additions & 2 deletions test/e2e/scripts/e2e.sh
Original file line number Diff line number Diff line change
Expand Up @@ -49,14 +49,16 @@ run_registry \
${e2e_root}/testdata/distribution/mount \
ghcr.io/oras-project/registry:v1.0.0-rc.4 \
$oras_container_name \
$ORAS_REGISTRY_PORT
$ORAS_REGISTRY_PORT \
true

echo " === preparing upstream distribution === "
run_registry \
${e2e_root}/testdata/distribution/mount_fallback \
registry:2.8.1 \
$upstream_container_name \
$ORAS_REGISTRY_FALLBACK_PORT
$ORAS_REGISTRY_FALLBACK_PORT \
false

echo " === run tests === "
if ! ginkgo -r -p --succinct suite; then
Expand Down
Loading