Compare commits
25 commits
tcl/master
...
main
Author | SHA1 | Date | |
---|---|---|---|
|
3fe707de5c | ||
|
0c4d622374 | ||
|
f072af9573 | ||
|
91eda593ef | ||
|
21f3291612 | ||
|
fde4b7d664 | ||
|
2577121fa8 | ||
|
8619a11f73 | ||
|
d4f611dfab | ||
|
3fe99ca2c0 | ||
|
252619876a | ||
|
33b657b5ae | ||
|
1e89cf780c | ||
|
ed46691519 | ||
|
e0503319b2 | ||
|
753d64b677 | ||
|
a18cc8a656 | ||
|
54cf4165d4 | ||
|
3d0239ac6f | ||
|
f1c8c41408 | ||
|
671184e910 | ||
|
c345425ff5 | ||
|
f22dd61860 | ||
|
9ba7340601 | ||
|
eb6123f5ed |
49 changed files with 440 additions and 314 deletions
10
.github/workflows/build.yml
vendored
10
.github/workflows/build.yml
vendored
|
@ -27,8 +27,8 @@ jobs:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
go:
|
go:
|
||||||
- 1.21.8
|
- 1.21.12
|
||||||
- 1.22.1
|
- 1.22.5
|
||||||
target:
|
target:
|
||||||
- test-coverage
|
- test-coverage
|
||||||
- test-cloud-storage
|
- test-cloud-storage
|
||||||
|
@ -112,7 +112,7 @@ jobs:
|
||||||
password: ${{ secrets.GITHUB_TOKEN }}
|
password: ${{ secrets.GITHUB_TOKEN }}
|
||||||
-
|
-
|
||||||
name: Build artifacts
|
name: Build artifacts
|
||||||
uses: docker/bake-action@v4
|
uses: docker/bake-action@v5
|
||||||
with:
|
with:
|
||||||
targets: artifact-all
|
targets: artifact-all
|
||||||
-
|
-
|
||||||
|
@ -140,7 +140,7 @@ jobs:
|
||||||
if-no-files-found: error
|
if-no-files-found: error
|
||||||
-
|
-
|
||||||
name: Build image
|
name: Build image
|
||||||
uses: docker/bake-action@v4
|
uses: docker/bake-action@v5
|
||||||
with:
|
with:
|
||||||
files: |
|
files: |
|
||||||
./docker-bake.hcl
|
./docker-bake.hcl
|
||||||
|
@ -149,7 +149,7 @@ jobs:
|
||||||
push: ${{ github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/') }}
|
push: ${{ github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/') }}
|
||||||
-
|
-
|
||||||
name: GitHub Release
|
name: GitHub Release
|
||||||
uses: softprops/action-gh-release@v1
|
uses: softprops/action-gh-release@v2
|
||||||
if: startsWith(github.ref, 'refs/tags/')
|
if: startsWith(github.ref, 'refs/tags/')
|
||||||
with:
|
with:
|
||||||
draft: true
|
draft: true
|
||||||
|
|
2
.github/workflows/conformance.yml
vendored
2
.github/workflows/conformance.yml
vendored
|
@ -22,7 +22,7 @@ jobs:
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
-
|
-
|
||||||
name: Build image
|
name: Build image
|
||||||
uses: docker/bake-action@v4
|
uses: docker/bake-action@v5
|
||||||
with:
|
with:
|
||||||
targets: image-local
|
targets: image-local
|
||||||
-
|
-
|
||||||
|
|
2
.github/workflows/docs.yml
vendored
2
.github/workflows/docs.yml
vendored
|
@ -30,7 +30,7 @@ jobs:
|
||||||
- name: Set up Docker Buildx
|
- name: Set up Docker Buildx
|
||||||
uses: docker/setup-buildx-action@v3
|
uses: docker/setup-buildx-action@v3
|
||||||
- name: Build docs
|
- name: Build docs
|
||||||
uses: docker/bake-action@v4
|
uses: docker/bake-action@v5
|
||||||
with:
|
with:
|
||||||
files: |
|
files: |
|
||||||
docker-bake.hcl
|
docker-bake.hcl
|
||||||
|
|
2
.github/workflows/e2e.yml
vendored
2
.github/workflows/e2e.yml
vendored
|
@ -25,7 +25,7 @@ jobs:
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
-
|
-
|
||||||
name: Build image
|
name: Build image
|
||||||
uses: docker/bake-action@v4
|
uses: docker/bake-action@v5
|
||||||
with:
|
with:
|
||||||
targets: image-local
|
targets: image-local
|
||||||
-
|
-
|
||||||
|
|
2
.github/workflows/scorecards.yml
vendored
2
.github/workflows/scorecards.yml
vendored
|
@ -27,7 +27,7 @@ jobs:
|
||||||
persist-credentials: false
|
persist-credentials: false
|
||||||
|
|
||||||
- name: "Run analysis"
|
- name: "Run analysis"
|
||||||
uses: ossf/scorecard-action@0864cf19026789058feabb7e87baa5f140aac736 # tag=v2.3.1
|
uses: ossf/scorecard-action@dc50aa9510b46c811795eb24b2f1ba02a914e534 # tag=v2.3.3
|
||||||
with:
|
with:
|
||||||
results_file: results.sarif
|
results_file: results.sarif
|
||||||
results_format: sarif
|
results_format: sarif
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
# syntax=docker/dockerfile:1
|
# syntax=docker/dockerfile:1
|
||||||
|
|
||||||
ARG GO_VERSION=1.22.4
|
ARG GO_VERSION=1.22.5
|
||||||
ARG ALPINE_VERSION=3.20
|
ARG ALPINE_VERSION=3.20
|
||||||
ARG XX_VERSION=1.2.1
|
ARG XX_VERSION=1.2.1
|
||||||
|
|
||||||
|
|
9
blobs.go
9
blobs.go
|
@ -85,15 +85,6 @@ type Descriptor struct {
|
||||||
// depend on the simplicity of this type.
|
// depend on the simplicity of this type.
|
||||||
}
|
}
|
||||||
|
|
||||||
// Descriptor returns the descriptor, to make it satisfy the Describable
|
|
||||||
// interface. Note that implementations of Describable are generally objects
|
|
||||||
// which can be described, not simply descriptors; this exception is in place
|
|
||||||
// to make it more convenient to pass actual descriptors to functions that
|
|
||||||
// expect Describable objects.
|
|
||||||
func (d Descriptor) Descriptor() Descriptor {
|
|
||||||
return d
|
|
||||||
}
|
|
||||||
|
|
||||||
// BlobStatter makes blob descriptors available by digest. The service may
|
// BlobStatter makes blob descriptors available by digest. The service may
|
||||||
// provide a descriptor of a different digest if the provided digest is not
|
// provide a descriptor of a different digest if the provided digest is not
|
||||||
// canonical.
|
// canonical.
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
# syntax=docker/dockerfile:1
|
# syntax=docker/dockerfile:1
|
||||||
|
|
||||||
ARG GO_VERSION=1.22.4
|
ARG GO_VERSION=1.22.5
|
||||||
ARG ALPINE_VERSION=3.20
|
ARG ALPINE_VERSION=3.20
|
||||||
|
|
||||||
FROM golang:${GO_VERSION}-alpine${ALPINE_VERSION} AS base
|
FROM golang:${GO_VERSION}-alpine${ALPINE_VERSION} AS base
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
# syntax=docker/dockerfile:1
|
# syntax=docker/dockerfile:1
|
||||||
|
|
||||||
ARG GO_VERSION=1.22.4
|
ARG GO_VERSION=1.22.5
|
||||||
ARG ALPINE_VERSION=3.20
|
ARG ALPINE_VERSION=3.20
|
||||||
|
|
||||||
FROM alpine:${ALPINE_VERSION} AS base
|
FROM alpine:${ALPINE_VERSION} AS base
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
# syntax=docker/dockerfile:1
|
# syntax=docker/dockerfile:1
|
||||||
|
|
||||||
ARG GO_VERSION=1.22.4
|
ARG GO_VERSION=1.22.5
|
||||||
ARG ALPINE_VERSION=3.20
|
ARG ALPINE_VERSION=3.20
|
||||||
ARG GOLANGCI_LINT_VERSION=v1.59.1
|
ARG GOLANGCI_LINT_VERSION=v1.59.1
|
||||||
ARG BUILDTAGS=""
|
ARG BUILDTAGS=""
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
# syntax=docker/dockerfile:1
|
# syntax=docker/dockerfile:1
|
||||||
|
|
||||||
ARG GO_VERSION=1.22.4
|
ARG GO_VERSION=1.22.5
|
||||||
ARG ALPINE_VERSION=3.20
|
ARG ALPINE_VERSION=3.20
|
||||||
ARG MODOUTDATED_VERSION=v0.8.0
|
ARG MODOUTDATED_VERSION=v0.8.0
|
||||||
|
|
||||||
|
|
4
go.mod
4
go.mod
|
@ -1,6 +1,6 @@
|
||||||
module github.com/distribution/distribution/v3
|
module github.com/distribution/distribution/v3
|
||||||
|
|
||||||
go 1.22.4
|
go 1.22.5
|
||||||
|
|
||||||
require (
|
require (
|
||||||
cloud.google.com/go/storage v1.30.1
|
cloud.google.com/go/storage v1.30.1
|
||||||
|
@ -22,7 +22,7 @@ require (
|
||||||
github.com/klauspost/compress v1.17.4
|
github.com/klauspost/compress v1.17.4
|
||||||
github.com/mitchellh/mapstructure v1.5.0
|
github.com/mitchellh/mapstructure v1.5.0
|
||||||
github.com/opencontainers/go-digest v1.0.0
|
github.com/opencontainers/go-digest v1.0.0
|
||||||
github.com/opencontainers/image-spec v1.0.2
|
github.com/opencontainers/image-spec v1.1.0
|
||||||
github.com/redis/go-redis/extra/redisotel/v9 v9.0.5
|
github.com/redis/go-redis/extra/redisotel/v9 v9.0.5
|
||||||
github.com/redis/go-redis/v9 v9.1.0
|
github.com/redis/go-redis/v9 v9.1.0
|
||||||
github.com/sirupsen/logrus v1.9.3
|
github.com/sirupsen/logrus v1.9.3
|
||||||
|
|
4
go.sum
4
go.sum
|
@ -183,8 +183,8 @@ github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3Rllmb
|
||||||
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
|
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
|
||||||
github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U=
|
github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U=
|
||||||
github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM=
|
github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM=
|
||||||
github.com/opencontainers/image-spec v1.0.2 h1:9yCKha/T5XdGtO0q9Q9a6T5NUCsTn/DrBg0D7ufOcFM=
|
github.com/opencontainers/image-spec v1.1.0 h1:8SG7/vwALn54lVB/0yZ/MMwhFrPYtpEHQb2IpWsCzug=
|
||||||
github.com/opencontainers/image-spec v1.0.2/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0=
|
github.com/opencontainers/image-spec v1.1.0/go.mod h1:W4s4sFTMaBeK1BQLXbG4AdM2szdn85PY75RI83NrTrM=
|
||||||
github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c h1:+mdjkGKdHQG3305AYmdv1U2eRNDiU2ErMBj1gwrq8eQ=
|
github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c h1:+mdjkGKdHQG3305AYmdv1U2eRNDiU2ErMBj1gwrq8eQ=
|
||||||
github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c/go.mod h1:7rwL4CYBLnjLxUqIJNnCWiEdr3bn6IUYi15bNlnbCCU=
|
github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c/go.mod h1:7rwL4CYBLnjLxUqIJNnCWiEdr3bn6IUYi15bNlnbCCU=
|
||||||
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||||
|
|
|
@ -18,13 +18,13 @@ import (
|
||||||
|
|
||||||
"github.com/distribution/distribution/v3"
|
"github.com/distribution/distribution/v3"
|
||||||
"github.com/distribution/distribution/v3/internal/dcontext"
|
"github.com/distribution/distribution/v3/internal/dcontext"
|
||||||
"github.com/distribution/distribution/v3/manifest"
|
|
||||||
"github.com/distribution/distribution/v3/manifest/ocischema"
|
"github.com/distribution/distribution/v3/manifest/ocischema"
|
||||||
"github.com/distribution/distribution/v3/registry/api/errcode"
|
"github.com/distribution/distribution/v3/registry/api/errcode"
|
||||||
"github.com/distribution/distribution/v3/testutil"
|
"github.com/distribution/distribution/v3/testutil"
|
||||||
"github.com/distribution/reference"
|
"github.com/distribution/reference"
|
||||||
"github.com/google/uuid"
|
"github.com/google/uuid"
|
||||||
"github.com/opencontainers/go-digest"
|
"github.com/opencontainers/go-digest"
|
||||||
|
"github.com/opencontainers/image-spec/specs-go"
|
||||||
v1 "github.com/opencontainers/image-spec/specs-go/v1"
|
v1 "github.com/opencontainers/image-spec/specs-go/v1"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -928,10 +928,8 @@ func newRandomOCIManifest(t *testing.T, blobCount int) (*ocischema.Manifest, dig
|
||||||
}
|
}
|
||||||
|
|
||||||
m := ocischema.Manifest{
|
m := ocischema.Manifest{
|
||||||
Versioned: manifest.Versioned{
|
Versioned: specs.Versioned{SchemaVersion: 2},
|
||||||
SchemaVersion: 2,
|
|
||||||
MediaType: v1.MediaTypeImageManifest,
|
MediaType: v1.MediaTypeImageManifest,
|
||||||
},
|
|
||||||
Config: distribution.Descriptor{
|
Config: distribution.Descriptor{
|
||||||
Digest: "sha256:1a9ec845ee94c202b2d5da74a24f0ed2058318bfa9879fa541efaecba272e86b",
|
Digest: "sha256:1a9ec845ee94c202b2d5da74a24f0ed2058318bfa9879fa541efaecba272e86b",
|
||||||
Size: 123,
|
Size: 123,
|
||||||
|
|
|
@ -8,6 +8,7 @@ import (
|
||||||
"github.com/distribution/distribution/v3"
|
"github.com/distribution/distribution/v3"
|
||||||
"github.com/distribution/distribution/v3/manifest"
|
"github.com/distribution/distribution/v3/manifest"
|
||||||
"github.com/opencontainers/go-digest"
|
"github.com/opencontainers/go-digest"
|
||||||
|
"github.com/opencontainers/image-spec/specs-go"
|
||||||
v1 "github.com/opencontainers/image-spec/specs-go/v1"
|
v1 "github.com/opencontainers/image-spec/specs-go/v1"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -18,33 +19,37 @@ const (
|
||||||
|
|
||||||
// SchemaVersion provides a pre-initialized version structure for this
|
// SchemaVersion provides a pre-initialized version structure for this
|
||||||
// packages version of the manifest.
|
// packages version of the manifest.
|
||||||
|
//
|
||||||
|
// Deprecated: use [specs.Versioned] and set MediaType on the manifest
|
||||||
|
// to [MediaTypeManifestList].
|
||||||
|
//
|
||||||
|
//nolint:staticcheck // ignore SA1019: manifest.Versioned is deprecated:
|
||||||
var SchemaVersion = manifest.Versioned{
|
var SchemaVersion = manifest.Versioned{
|
||||||
SchemaVersion: 2,
|
SchemaVersion: 2,
|
||||||
MediaType: MediaTypeManifestList,
|
MediaType: MediaTypeManifestList,
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
manifestListFunc := func(b []byte) (distribution.Manifest, distribution.Descriptor, error) {
|
if err := distribution.RegisterManifestSchema(MediaTypeManifestList, unmarshalManifestList); err != nil {
|
||||||
m := new(DeserializedManifestList)
|
panic(fmt.Sprintf("Unable to register manifest: %s", err))
|
||||||
err := m.UnmarshalJSON(b)
|
}
|
||||||
if err != nil {
|
}
|
||||||
|
|
||||||
|
func unmarshalManifestList(b []byte) (distribution.Manifest, distribution.Descriptor, error) {
|
||||||
|
m := &DeserializedManifestList{}
|
||||||
|
if err := m.UnmarshalJSON(b); err != nil {
|
||||||
return nil, distribution.Descriptor{}, err
|
return nil, distribution.Descriptor{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if m.MediaType != MediaTypeManifestList {
|
if m.MediaType != MediaTypeManifestList {
|
||||||
err = fmt.Errorf("mediaType in manifest list should be '%s' not '%s'",
|
return nil, distribution.Descriptor{}, fmt.Errorf("mediaType in manifest list should be '%s' not '%s'", MediaTypeManifestList, m.MediaType)
|
||||||
MediaTypeManifestList, m.MediaType)
|
|
||||||
|
|
||||||
return nil, distribution.Descriptor{}, err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
dgst := digest.FromBytes(b)
|
return m, distribution.Descriptor{
|
||||||
return m, distribution.Descriptor{Digest: dgst, Size: int64(len(b)), MediaType: MediaTypeManifestList}, err
|
Digest: digest.FromBytes(b),
|
||||||
}
|
Size: int64(len(b)),
|
||||||
err := distribution.RegisterManifestSchema(MediaTypeManifestList, manifestListFunc)
|
MediaType: MediaTypeManifestList,
|
||||||
if err != nil {
|
}, nil
|
||||||
panic(fmt.Sprintf("Unable to register manifest: %s", err))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// PlatformSpec specifies a platform where a particular image manifest is
|
// PlatformSpec specifies a platform where a particular image manifest is
|
||||||
|
@ -85,7 +90,10 @@ type ManifestDescriptor struct {
|
||||||
|
|
||||||
// ManifestList references manifests for various platforms.
|
// ManifestList references manifests for various platforms.
|
||||||
type ManifestList struct {
|
type ManifestList struct {
|
||||||
manifest.Versioned
|
specs.Versioned
|
||||||
|
|
||||||
|
// MediaType is the media type of this schema.
|
||||||
|
MediaType string `json:"mediaType,omitempty"`
|
||||||
|
|
||||||
// Manifests references a list of manifests
|
// Manifests references a list of manifests
|
||||||
Manifests []ManifestDescriptor `json:"manifests"`
|
Manifests []ManifestDescriptor `json:"manifests"`
|
||||||
|
@ -128,10 +136,8 @@ func FromDescriptors(descriptors []ManifestDescriptor) (*DeserializedManifestLis
|
||||||
// fromDescriptorsWithMediaType is for testing purposes, it's useful to be able to specify the media type explicitly
|
// fromDescriptorsWithMediaType is for testing purposes, it's useful to be able to specify the media type explicitly
|
||||||
func fromDescriptorsWithMediaType(descriptors []ManifestDescriptor, mediaType string) (*DeserializedManifestList, error) {
|
func fromDescriptorsWithMediaType(descriptors []ManifestDescriptor, mediaType string) (*DeserializedManifestList, error) {
|
||||||
m := ManifestList{
|
m := ManifestList{
|
||||||
Versioned: manifest.Versioned{
|
Versioned: specs.Versioned{SchemaVersion: 2},
|
||||||
SchemaVersion: SchemaVersion.SchemaVersion,
|
|
||||||
MediaType: mediaType,
|
MediaType: mediaType,
|
||||||
},
|
|
||||||
}
|
}
|
||||||
|
|
||||||
m.Manifests = make([]ManifestDescriptor, len(descriptors))
|
m.Manifests = make([]ManifestDescriptor, len(descriptors))
|
||||||
|
@ -176,7 +182,14 @@ func (m *DeserializedManifestList) MarshalJSON() ([]byte, error) {
|
||||||
// Payload returns the raw content of the manifest list. The contents can be
|
// Payload returns the raw content of the manifest list. The contents can be
|
||||||
// used to calculate the content identifier.
|
// used to calculate the content identifier.
|
||||||
func (m DeserializedManifestList) Payload() (string, []byte, error) {
|
func (m DeserializedManifestList) Payload() (string, []byte, error) {
|
||||||
return m.MediaType, m.canonical, nil
|
var mediaType string
|
||||||
|
if m.MediaType == "" {
|
||||||
|
mediaType = v1.MediaTypeImageIndex
|
||||||
|
} else {
|
||||||
|
mediaType = m.MediaType
|
||||||
|
}
|
||||||
|
|
||||||
|
return mediaType, m.canonical, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// validateManifestList returns an error if the byte slice is invalid JSON or if it
|
// validateManifestList returns an error if the byte slice is invalid JSON or if it
|
||||||
|
|
|
@ -5,8 +5,8 @@ import (
|
||||||
"errors"
|
"errors"
|
||||||
|
|
||||||
"github.com/distribution/distribution/v3"
|
"github.com/distribution/distribution/v3"
|
||||||
"github.com/distribution/distribution/v3/manifest"
|
|
||||||
"github.com/opencontainers/go-digest"
|
"github.com/opencontainers/go-digest"
|
||||||
|
"github.com/opencontainers/image-spec/specs-go"
|
||||||
v1 "github.com/opencontainers/image-spec/specs-go/v1"
|
v1 "github.com/opencontainers/image-spec/specs-go/v1"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -32,7 +32,7 @@ type Builder struct {
|
||||||
// NewManifestBuilder is used to build new manifests for the current schema
|
// NewManifestBuilder is used to build new manifests for the current schema
|
||||||
// version. It takes a BlobService so it can publish the configuration blob
|
// version. It takes a BlobService so it can publish the configuration blob
|
||||||
// as part of the Build process, and annotations.
|
// as part of the Build process, and annotations.
|
||||||
func NewManifestBuilder(bs distribution.BlobService, configJSON []byte, annotations map[string]string) distribution.ManifestBuilder {
|
func NewManifestBuilder(bs distribution.BlobService, configJSON []byte, annotations map[string]string) *Builder {
|
||||||
mb := &Builder{
|
mb := &Builder{
|
||||||
bs: bs,
|
bs: bs,
|
||||||
configJSON: make([]byte, len(configJSON)),
|
configJSON: make([]byte, len(configJSON)),
|
||||||
|
@ -58,10 +58,8 @@ func (mb *Builder) SetMediaType(mediaType string) error {
|
||||||
// Build produces a final manifest from the given references.
|
// Build produces a final manifest from the given references.
|
||||||
func (mb *Builder) Build(ctx context.Context) (distribution.Manifest, error) {
|
func (mb *Builder) Build(ctx context.Context) (distribution.Manifest, error) {
|
||||||
m := Manifest{
|
m := Manifest{
|
||||||
Versioned: manifest.Versioned{
|
Versioned: specs.Versioned{SchemaVersion: 2},
|
||||||
SchemaVersion: 2,
|
|
||||||
MediaType: mb.mediaType,
|
MediaType: mb.mediaType,
|
||||||
},
|
|
||||||
Layers: make([]distribution.Descriptor, len(mb.layers)),
|
Layers: make([]distribution.Descriptor, len(mb.layers)),
|
||||||
Annotations: mb.annotations,
|
Annotations: mb.annotations,
|
||||||
}
|
}
|
||||||
|
@ -96,8 +94,8 @@ func (mb *Builder) Build(ctx context.Context) (distribution.Manifest, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// AppendReference adds a reference to the current ManifestBuilder.
|
// AppendReference adds a reference to the current ManifestBuilder.
|
||||||
func (mb *Builder) AppendReference(d distribution.Describable) error {
|
func (mb *Builder) AppendReference(ref distribution.Descriptor) error {
|
||||||
mb.layers = append(mb.layers, d.Descriptor())
|
mb.layers = append(mb.layers, ref)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -8,51 +8,56 @@ import (
|
||||||
"github.com/distribution/distribution/v3"
|
"github.com/distribution/distribution/v3"
|
||||||
"github.com/distribution/distribution/v3/manifest"
|
"github.com/distribution/distribution/v3/manifest"
|
||||||
"github.com/opencontainers/go-digest"
|
"github.com/opencontainers/go-digest"
|
||||||
|
"github.com/opencontainers/image-spec/specs-go"
|
||||||
v1 "github.com/opencontainers/image-spec/specs-go/v1"
|
v1 "github.com/opencontainers/image-spec/specs-go/v1"
|
||||||
)
|
)
|
||||||
|
|
||||||
// IndexSchemaVersion provides a pre-initialized version structure for OCI Image
|
// IndexSchemaVersion provides a pre-initialized version structure for OCI Image
|
||||||
// Indices.
|
// Indices.
|
||||||
|
//
|
||||||
|
// Deprecated: use [specs.Versioned] and set MediaType on the manifest
|
||||||
|
// to [v1.MediaTypeImageIndex].
|
||||||
|
//
|
||||||
|
//nolint:staticcheck // ignore SA1019: manifest.Versioned is deprecated:
|
||||||
var IndexSchemaVersion = manifest.Versioned{
|
var IndexSchemaVersion = manifest.Versioned{
|
||||||
SchemaVersion: 2,
|
SchemaVersion: 2,
|
||||||
MediaType: v1.MediaTypeImageIndex,
|
MediaType: v1.MediaTypeImageIndex,
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
imageIndexFunc := func(b []byte) (distribution.Manifest, distribution.Descriptor, error) {
|
if err := distribution.RegisterManifestSchema(v1.MediaTypeImageIndex, unmarshalImageIndex); err != nil {
|
||||||
if err := validateIndex(b); err != nil {
|
|
||||||
return nil, distribution.Descriptor{}, err
|
|
||||||
}
|
|
||||||
m := new(DeserializedImageIndex)
|
|
||||||
err := m.UnmarshalJSON(b)
|
|
||||||
if err != nil {
|
|
||||||
return nil, distribution.Descriptor{}, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if m.MediaType != "" && m.MediaType != v1.MediaTypeImageIndex {
|
|
||||||
err = fmt.Errorf("if present, mediaType in image index should be '%s' not '%s'",
|
|
||||||
v1.MediaTypeImageIndex, m.MediaType)
|
|
||||||
|
|
||||||
return nil, distribution.Descriptor{}, err
|
|
||||||
}
|
|
||||||
|
|
||||||
dgst := digest.FromBytes(b)
|
|
||||||
return m, distribution.Descriptor{
|
|
||||||
MediaType: v1.MediaTypeImageIndex,
|
|
||||||
Digest: dgst,
|
|
||||||
Size: int64(len(b)),
|
|
||||||
Annotations: m.Annotations,
|
|
||||||
}, err
|
|
||||||
}
|
|
||||||
err := distribution.RegisterManifestSchema(v1.MediaTypeImageIndex, imageIndexFunc)
|
|
||||||
if err != nil {
|
|
||||||
panic(fmt.Sprintf("Unable to register OCI Image Index: %s", err))
|
panic(fmt.Sprintf("Unable to register OCI Image Index: %s", err))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func unmarshalImageIndex(b []byte) (distribution.Manifest, distribution.Descriptor, error) {
|
||||||
|
if err := validateIndex(b); err != nil {
|
||||||
|
return nil, distribution.Descriptor{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
m := &DeserializedImageIndex{}
|
||||||
|
if err := m.UnmarshalJSON(b); err != nil {
|
||||||
|
return nil, distribution.Descriptor{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if m.MediaType != "" && m.MediaType != v1.MediaTypeImageIndex {
|
||||||
|
return nil, distribution.Descriptor{}, fmt.Errorf("if present, mediaType in image index should be '%s' not '%s'", v1.MediaTypeImageIndex, m.MediaType)
|
||||||
|
}
|
||||||
|
|
||||||
|
return m, distribution.Descriptor{
|
||||||
|
MediaType: v1.MediaTypeImageIndex,
|
||||||
|
Digest: digest.FromBytes(b),
|
||||||
|
Size: int64(len(b)),
|
||||||
|
Annotations: m.Annotations,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
// ImageIndex references manifests for various platforms.
|
// ImageIndex references manifests for various platforms.
|
||||||
type ImageIndex struct {
|
type ImageIndex struct {
|
||||||
manifest.Versioned
|
specs.Versioned
|
||||||
|
|
||||||
|
// MediaType is the media type of this schema.
|
||||||
|
MediaType string `json:"mediaType,omitempty"`
|
||||||
|
|
||||||
// Manifests references a list of manifests
|
// Manifests references a list of manifests
|
||||||
Manifests []distribution.Descriptor `json:"manifests"`
|
Manifests []distribution.Descriptor `json:"manifests"`
|
||||||
|
@ -88,10 +93,8 @@ func FromDescriptors(descriptors []distribution.Descriptor, annotations map[stri
|
||||||
// fromDescriptorsWithMediaType is for testing purposes, it's useful to be able to specify the media type explicitly
|
// fromDescriptorsWithMediaType is for testing purposes, it's useful to be able to specify the media type explicitly
|
||||||
func fromDescriptorsWithMediaType(descriptors []distribution.Descriptor, annotations map[string]string, mediaType string) (_ *DeserializedImageIndex, err error) {
|
func fromDescriptorsWithMediaType(descriptors []distribution.Descriptor, annotations map[string]string, mediaType string) (_ *DeserializedImageIndex, err error) {
|
||||||
m := ImageIndex{
|
m := ImageIndex{
|
||||||
Versioned: manifest.Versioned{
|
Versioned: specs.Versioned{SchemaVersion: 2},
|
||||||
SchemaVersion: IndexSchemaVersion.SchemaVersion,
|
|
||||||
MediaType: mediaType,
|
MediaType: mediaType,
|
||||||
},
|
|
||||||
Annotations: annotations,
|
Annotations: annotations,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -8,44 +8,52 @@ import (
|
||||||
"github.com/distribution/distribution/v3"
|
"github.com/distribution/distribution/v3"
|
||||||
"github.com/distribution/distribution/v3/manifest"
|
"github.com/distribution/distribution/v3/manifest"
|
||||||
"github.com/opencontainers/go-digest"
|
"github.com/opencontainers/go-digest"
|
||||||
|
"github.com/opencontainers/image-spec/specs-go"
|
||||||
v1 "github.com/opencontainers/image-spec/specs-go/v1"
|
v1 "github.com/opencontainers/image-spec/specs-go/v1"
|
||||||
)
|
)
|
||||||
|
|
||||||
// SchemaVersion provides a pre-initialized version structure for OCI Image
|
// SchemaVersion provides a pre-initialized version structure for OCI Image
|
||||||
// Manifests
|
// Manifests.
|
||||||
|
//
|
||||||
|
// Deprecated: use [specs.Versioned] and set MediaType on the manifest
|
||||||
|
// to [v1.MediaTypeImageManifest].
|
||||||
|
//
|
||||||
|
//nolint:staticcheck // ignore SA1019: manifest.Versioned is deprecated:
|
||||||
var SchemaVersion = manifest.Versioned{
|
var SchemaVersion = manifest.Versioned{
|
||||||
SchemaVersion: 2,
|
SchemaVersion: 2,
|
||||||
MediaType: v1.MediaTypeImageManifest,
|
MediaType: v1.MediaTypeImageManifest,
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
ocischemaFunc := func(b []byte) (distribution.Manifest, distribution.Descriptor, error) {
|
if err := distribution.RegisterManifestSchema(v1.MediaTypeImageManifest, unmarshalOCISchema); err != nil {
|
||||||
if err := validateManifest(b); err != nil {
|
|
||||||
return nil, distribution.Descriptor{}, err
|
|
||||||
}
|
|
||||||
m := new(DeserializedManifest)
|
|
||||||
err := m.UnmarshalJSON(b)
|
|
||||||
if err != nil {
|
|
||||||
return nil, distribution.Descriptor{}, err
|
|
||||||
}
|
|
||||||
|
|
||||||
dgst := digest.FromBytes(b)
|
|
||||||
return m, distribution.Descriptor{
|
|
||||||
MediaType: v1.MediaTypeImageManifest,
|
|
||||||
Digest: dgst,
|
|
||||||
Size: int64(len(b)),
|
|
||||||
Annotations: m.Annotations,
|
|
||||||
}, err
|
|
||||||
}
|
|
||||||
err := distribution.RegisterManifestSchema(v1.MediaTypeImageManifest, ocischemaFunc)
|
|
||||||
if err != nil {
|
|
||||||
panic(fmt.Sprintf("Unable to register manifest: %s", err))
|
panic(fmt.Sprintf("Unable to register manifest: %s", err))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func unmarshalOCISchema(b []byte) (distribution.Manifest, distribution.Descriptor, error) {
|
||||||
|
if err := validateManifest(b); err != nil {
|
||||||
|
return nil, distribution.Descriptor{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
m := &DeserializedManifest{}
|
||||||
|
if err := m.UnmarshalJSON(b); err != nil {
|
||||||
|
return nil, distribution.Descriptor{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return m, distribution.Descriptor{
|
||||||
|
MediaType: v1.MediaTypeImageManifest,
|
||||||
|
Digest: digest.FromBytes(b),
|
||||||
|
Size: int64(len(b)),
|
||||||
|
Annotations: m.Annotations,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
// Manifest defines a ocischema manifest.
|
// Manifest defines a ocischema manifest.
|
||||||
type Manifest struct {
|
type Manifest struct {
|
||||||
manifest.Versioned
|
specs.Versioned
|
||||||
|
|
||||||
|
// MediaType is the media type of this schema.
|
||||||
|
MediaType string `json:"mediaType,omitempty"`
|
||||||
|
|
||||||
// Config references the image configuration as a blob.
|
// Config references the image configuration as a blob.
|
||||||
Config distribution.Descriptor `json:"config"`
|
Config distribution.Descriptor `json:"config"`
|
||||||
|
@ -125,7 +133,7 @@ func (m *DeserializedManifest) MarshalJSON() ([]byte, error) {
|
||||||
|
|
||||||
// Payload returns the raw content of the manifest. The contents can be used to
|
// Payload returns the raw content of the manifest. The contents can be used to
|
||||||
// calculate the content identifier.
|
// calculate the content identifier.
|
||||||
func (m DeserializedManifest) Payload() (string, []byte, error) {
|
func (m *DeserializedManifest) Payload() (string, []byte, error) {
|
||||||
return v1.MediaTypeImageManifest, m.canonical, nil
|
return v1.MediaTypeImageManifest, m.canonical, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,8 +7,8 @@ import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/distribution/distribution/v3"
|
"github.com/distribution/distribution/v3"
|
||||||
"github.com/distribution/distribution/v3/manifest"
|
|
||||||
"github.com/distribution/distribution/v3/manifest/manifestlist"
|
"github.com/distribution/distribution/v3/manifest/manifestlist"
|
||||||
|
"github.com/opencontainers/image-spec/specs-go"
|
||||||
|
|
||||||
"github.com/opencontainers/go-digest"
|
"github.com/opencontainers/go-digest"
|
||||||
v1 "github.com/opencontainers/image-spec/specs-go/v1"
|
v1 "github.com/opencontainers/image-spec/specs-go/v1"
|
||||||
|
@ -42,10 +42,8 @@ const expectedManifestSerialization = `{
|
||||||
|
|
||||||
func makeTestManifest(mediaType string) Manifest {
|
func makeTestManifest(mediaType string) Manifest {
|
||||||
return Manifest{
|
return Manifest{
|
||||||
Versioned: manifest.Versioned{
|
Versioned: specs.Versioned{SchemaVersion: 2},
|
||||||
SchemaVersion: 2,
|
|
||||||
MediaType: mediaType,
|
MediaType: mediaType,
|
||||||
},
|
|
||||||
Config: distribution.Descriptor{
|
Config: distribution.Descriptor{
|
||||||
MediaType: v1.MediaTypeImageConfig,
|
MediaType: v1.MediaTypeImageConfig,
|
||||||
Digest: "sha256:1a9ec845ee94c202b2d5da74a24f0ed2058318bfa9879fa541efaecba272e86b",
|
Digest: "sha256:1a9ec845ee94c202b2d5da74a24f0ed2058318bfa9879fa541efaecba272e86b",
|
||||||
|
|
|
@ -4,10 +4,11 @@ import (
|
||||||
"context"
|
"context"
|
||||||
|
|
||||||
"github.com/distribution/distribution/v3"
|
"github.com/distribution/distribution/v3"
|
||||||
|
"github.com/opencontainers/image-spec/specs-go"
|
||||||
)
|
)
|
||||||
|
|
||||||
// builder is a type for constructing manifests.
|
// Builder is a type for constructing manifests.
|
||||||
type builder struct {
|
type Builder struct {
|
||||||
// configDescriptor is used to describe configuration
|
// configDescriptor is used to describe configuration
|
||||||
configDescriptor distribution.Descriptor
|
configDescriptor distribution.Descriptor
|
||||||
|
|
||||||
|
@ -22,8 +23,8 @@ type builder struct {
|
||||||
// NewManifestBuilder is used to build new manifests for the current schema
|
// NewManifestBuilder is used to build new manifests for the current schema
|
||||||
// version. It takes a BlobService so it can publish the configuration blob
|
// version. It takes a BlobService so it can publish the configuration blob
|
||||||
// as part of the Build process.
|
// as part of the Build process.
|
||||||
func NewManifestBuilder(configDescriptor distribution.Descriptor, configJSON []byte) distribution.ManifestBuilder {
|
func NewManifestBuilder(configDescriptor distribution.Descriptor, configJSON []byte) *Builder {
|
||||||
mb := &builder{
|
mb := &Builder{
|
||||||
configDescriptor: configDescriptor,
|
configDescriptor: configDescriptor,
|
||||||
configJSON: make([]byte, len(configJSON)),
|
configJSON: make([]byte, len(configJSON)),
|
||||||
}
|
}
|
||||||
|
@ -33,9 +34,10 @@ func NewManifestBuilder(configDescriptor distribution.Descriptor, configJSON []b
|
||||||
}
|
}
|
||||||
|
|
||||||
// Build produces a final manifest from the given references.
|
// Build produces a final manifest from the given references.
|
||||||
func (mb *builder) Build(ctx context.Context) (distribution.Manifest, error) {
|
func (mb *Builder) Build(ctx context.Context) (distribution.Manifest, error) {
|
||||||
m := Manifest{
|
m := Manifest{
|
||||||
Versioned: SchemaVersion,
|
Versioned: specs.Versioned{SchemaVersion: defaultSchemaVersion},
|
||||||
|
MediaType: defaultMediaType,
|
||||||
Layers: make([]distribution.Descriptor, len(mb.dependencies)),
|
Layers: make([]distribution.Descriptor, len(mb.dependencies)),
|
||||||
}
|
}
|
||||||
copy(m.Layers, mb.dependencies)
|
copy(m.Layers, mb.dependencies)
|
||||||
|
@ -46,12 +48,12 @@ func (mb *builder) Build(ctx context.Context) (distribution.Manifest, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// AppendReference adds a reference to the current ManifestBuilder.
|
// AppendReference adds a reference to the current ManifestBuilder.
|
||||||
func (mb *builder) AppendReference(d distribution.Describable) error {
|
func (mb *Builder) AppendReference(ref distribution.Descriptor) error {
|
||||||
mb.dependencies = append(mb.dependencies, d.Descriptor())
|
mb.dependencies = append(mb.dependencies, ref)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// References returns the current references added to this builder.
|
// References returns the current references added to this builder.
|
||||||
func (mb *builder) References() []distribution.Descriptor {
|
func (mb *Builder) References() []distribution.Descriptor {
|
||||||
return mb.dependencies
|
return mb.dependencies
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,6 +8,7 @@ import (
|
||||||
"github.com/distribution/distribution/v3"
|
"github.com/distribution/distribution/v3"
|
||||||
"github.com/distribution/distribution/v3/manifest"
|
"github.com/distribution/distribution/v3/manifest"
|
||||||
"github.com/opencontainers/go-digest"
|
"github.com/opencontainers/go-digest"
|
||||||
|
"github.com/opencontainers/image-spec/specs-go"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -33,33 +34,48 @@ const (
|
||||||
MediaTypeUncompressedLayer = "application/vnd.docker.image.rootfs.diff.tar"
|
MediaTypeUncompressedLayer = "application/vnd.docker.image.rootfs.diff.tar"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
defaultSchemaVersion = 2
|
||||||
|
defaultMediaType = MediaTypeManifest
|
||||||
|
)
|
||||||
|
|
||||||
// SchemaVersion provides a pre-initialized version structure for this
|
// SchemaVersion provides a pre-initialized version structure for this
|
||||||
// packages version of the manifest.
|
// packages version of the manifest.
|
||||||
|
//
|
||||||
|
// Deprecated: use [specs.Versioned] and set MediaType on the manifest
|
||||||
|
// to [MediaTypeManifest].
|
||||||
|
//
|
||||||
|
//nolint:staticcheck // ignore SA1019: manifest.Versioned is deprecated:
|
||||||
var SchemaVersion = manifest.Versioned{
|
var SchemaVersion = manifest.Versioned{
|
||||||
SchemaVersion: 2,
|
SchemaVersion: defaultSchemaVersion,
|
||||||
MediaType: MediaTypeManifest,
|
MediaType: defaultMediaType,
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
schema2Func := func(b []byte) (distribution.Manifest, distribution.Descriptor, error) {
|
if err := distribution.RegisterManifestSchema(defaultMediaType, unmarshalSchema2); err != nil {
|
||||||
m := new(DeserializedManifest)
|
|
||||||
err := m.UnmarshalJSON(b)
|
|
||||||
if err != nil {
|
|
||||||
return nil, distribution.Descriptor{}, err
|
|
||||||
}
|
|
||||||
|
|
||||||
dgst := digest.FromBytes(b)
|
|
||||||
return m, distribution.Descriptor{Digest: dgst, Size: int64(len(b)), MediaType: MediaTypeManifest}, err
|
|
||||||
}
|
|
||||||
err := distribution.RegisterManifestSchema(MediaTypeManifest, schema2Func)
|
|
||||||
if err != nil {
|
|
||||||
panic(fmt.Sprintf("Unable to register manifest: %s", err))
|
panic(fmt.Sprintf("Unable to register manifest: %s", err))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func unmarshalSchema2(b []byte) (distribution.Manifest, distribution.Descriptor, error) {
|
||||||
|
m := &DeserializedManifest{}
|
||||||
|
if err := m.UnmarshalJSON(b); err != nil {
|
||||||
|
return nil, distribution.Descriptor{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return m, distribution.Descriptor{
|
||||||
|
Digest: digest.FromBytes(b),
|
||||||
|
Size: int64(len(b)),
|
||||||
|
MediaType: defaultMediaType,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
// Manifest defines a schema2 manifest.
|
// Manifest defines a schema2 manifest.
|
||||||
type Manifest struct {
|
type Manifest struct {
|
||||||
manifest.Versioned
|
specs.Versioned
|
||||||
|
|
||||||
|
// MediaType is the media type of this schema.
|
||||||
|
MediaType string `json:"mediaType,omitempty"`
|
||||||
|
|
||||||
// Config references the image configuration as a blob.
|
// Config references the image configuration as a blob.
|
||||||
Config distribution.Descriptor `json:"config"`
|
Config distribution.Descriptor `json:"config"`
|
||||||
|
@ -114,9 +130,8 @@ func (m *DeserializedManifest) UnmarshalJSON(b []byte) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if mfst.MediaType != MediaTypeManifest {
|
if mfst.MediaType != defaultMediaType {
|
||||||
return fmt.Errorf("mediaType in manifest should be '%s' not '%s'",
|
return fmt.Errorf("mediaType in manifest should be '%s' not '%s'", defaultMediaType, mfst.MediaType)
|
||||||
MediaTypeManifest, mfst.MediaType)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
m.Manifest = mfst
|
m.Manifest = mfst
|
||||||
|
|
|
@ -7,7 +7,7 @@ import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/distribution/distribution/v3"
|
"github.com/distribution/distribution/v3"
|
||||||
"github.com/distribution/distribution/v3/manifest"
|
"github.com/opencontainers/image-spec/specs-go"
|
||||||
)
|
)
|
||||||
|
|
||||||
const expectedManifestSerialization = `{
|
const expectedManifestSerialization = `{
|
||||||
|
@ -29,10 +29,8 @@ const expectedManifestSerialization = `{
|
||||||
|
|
||||||
func makeTestManifest(mediaType string) Manifest {
|
func makeTestManifest(mediaType string) Manifest {
|
||||||
return Manifest{
|
return Manifest{
|
||||||
Versioned: manifest.Versioned{
|
Versioned: specs.Versioned{SchemaVersion: 2},
|
||||||
SchemaVersion: 2,
|
|
||||||
MediaType: mediaType,
|
MediaType: mediaType,
|
||||||
},
|
|
||||||
Config: distribution.Descriptor{
|
Config: distribution.Descriptor{
|
||||||
MediaType: MediaTypeImageConfig,
|
MediaType: MediaTypeImageConfig,
|
||||||
Digest: "sha256:1a9ec845ee94c202b2d5da74a24f0ed2058318bfa9879fa541efaecba272e86b",
|
Digest: "sha256:1a9ec845ee94c202b2d5da74a24f0ed2058318bfa9879fa541efaecba272e86b",
|
||||||
|
|
|
@ -3,6 +3,8 @@ package manifest
|
||||||
// Versioned provides a struct with the manifest schemaVersion and mediaType.
|
// Versioned provides a struct with the manifest schemaVersion and mediaType.
|
||||||
// Incoming content with unknown schema version can be decoded against this
|
// Incoming content with unknown schema version can be decoded against this
|
||||||
// struct to check the version.
|
// struct to check the version.
|
||||||
|
//
|
||||||
|
// Deprecated: use [specs.Versioned] and set MediaType on the Manifest itself.
|
||||||
type Versioned struct {
|
type Versioned struct {
|
||||||
// SchemaVersion is the image manifest schema that this image follows
|
// SchemaVersion is the image manifest schema that this image follows
|
||||||
SchemaVersion int `json:"schemaVersion"`
|
SchemaVersion int `json:"schemaVersion"`
|
||||||
|
|
27
manifests.go
27
manifests.go
|
@ -26,27 +26,6 @@ type Manifest interface {
|
||||||
Payload() (mediaType string, payload []byte, err error)
|
Payload() (mediaType string, payload []byte, err error)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ManifestBuilder creates a manifest allowing one to include dependencies.
|
|
||||||
// Instances can be obtained from a version-specific manifest package. Manifest
|
|
||||||
// specific data is passed into the function which creates the builder.
|
|
||||||
type ManifestBuilder interface {
|
|
||||||
// Build creates the manifest from his builder.
|
|
||||||
Build(ctx context.Context) (Manifest, error)
|
|
||||||
|
|
||||||
// References returns a list of objects which have been added to this
|
|
||||||
// builder. The dependencies are returned in the order they were added,
|
|
||||||
// which should be from base to head.
|
|
||||||
References() []Descriptor
|
|
||||||
|
|
||||||
// AppendReference includes the given object in the manifest after any
|
|
||||||
// existing dependencies. If the add fails, such as when adding an
|
|
||||||
// unsupported dependency, an error may be returned.
|
|
||||||
//
|
|
||||||
// The destination of the reference is dependent on the manifest type and
|
|
||||||
// the dependency type.
|
|
||||||
AppendReference(dependency Describable) error
|
|
||||||
}
|
|
||||||
|
|
||||||
// ManifestService describes operations on manifests.
|
// ManifestService describes operations on manifests.
|
||||||
type ManifestService interface {
|
type ManifestService interface {
|
||||||
// Exists returns true if the manifest exists.
|
// Exists returns true if the manifest exists.
|
||||||
|
@ -69,8 +48,12 @@ type ManifestEnumerator interface {
|
||||||
Enumerate(ctx context.Context, ingester func(digest.Digest) error) error
|
Enumerate(ctx context.Context, ingester func(digest.Digest) error) error
|
||||||
}
|
}
|
||||||
|
|
||||||
// Describable is an interface for descriptors
|
// Describable is an interface for descriptors.
|
||||||
|
//
|
||||||
|
// Implementations of Describable are generally objects which can be
|
||||||
|
// described, not simply descriptors.
|
||||||
type Describable interface {
|
type Describable interface {
|
||||||
|
// Descriptor returns the descriptor.
|
||||||
Descriptor() Descriptor
|
Descriptor() Descriptor
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,13 +4,13 @@ import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/distribution/distribution/v3"
|
"github.com/distribution/distribution/v3"
|
||||||
"github.com/distribution/distribution/v3/manifest"
|
|
||||||
"github.com/distribution/distribution/v3/manifest/schema2"
|
"github.com/distribution/distribution/v3/manifest/schema2"
|
||||||
v2 "github.com/distribution/distribution/v3/registry/api/v2"
|
v2 "github.com/distribution/distribution/v3/registry/api/v2"
|
||||||
"github.com/distribution/reference"
|
"github.com/distribution/reference"
|
||||||
events "github.com/docker/go-events"
|
events "github.com/docker/go-events"
|
||||||
"github.com/google/uuid"
|
"github.com/google/uuid"
|
||||||
"github.com/opencontainers/go-digest"
|
"github.com/opencontainers/go-digest"
|
||||||
|
"github.com/opencontainers/image-spec/specs-go"
|
||||||
v1 "github.com/opencontainers/image-spec/specs-go/v1"
|
v1 "github.com/opencontainers/image-spec/specs-go/v1"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -29,7 +29,6 @@ var (
|
||||||
}
|
}
|
||||||
request = RequestRecord{}
|
request = RequestRecord{}
|
||||||
tag = "latest"
|
tag = "latest"
|
||||||
ociMediaType = v1.MediaTypeImageManifest
|
|
||||||
artifactType = "application/vnd.example.sbom.v1"
|
artifactType = "application/vnd.example.sbom.v1"
|
||||||
cfg = distribution.Descriptor{
|
cfg = distribution.Descriptor{
|
||||||
MediaType: artifactType,
|
MediaType: artifactType,
|
||||||
|
@ -143,14 +142,13 @@ func TestEventBridgeRepoDeleted(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func createTestEnv(t *testing.T, fn testSinkFn) Listener {
|
func createTestEnv(t *testing.T, fn testSinkFn) Listener {
|
||||||
manifest := schema2.Manifest{
|
mfst := schema2.Manifest{
|
||||||
Versioned: manifest.Versioned{
|
Versioned: specs.Versioned{SchemaVersion: 2},
|
||||||
MediaType: ociMediaType,
|
MediaType: v1.MediaTypeImageManifest,
|
||||||
},
|
|
||||||
Config: cfg,
|
Config: cfg,
|
||||||
}
|
}
|
||||||
|
|
||||||
deserializedManifest, err := schema2.FromStruct(manifest)
|
deserializedManifest, err := schema2.FromStruct(mfst)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("creating OCI manifest: %v", err)
|
t.Fatalf("creating OCI manifest: %v", err)
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,6 +14,7 @@ import (
|
||||||
"github.com/distribution/distribution/v3/testutil"
|
"github.com/distribution/distribution/v3/testutil"
|
||||||
"github.com/distribution/reference"
|
"github.com/distribution/reference"
|
||||||
"github.com/opencontainers/go-digest"
|
"github.com/opencontainers/go-digest"
|
||||||
|
"github.com/opencontainers/image-spec/specs-go"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestListener(t *testing.T) {
|
func TestListener(t *testing.T) {
|
||||||
|
@ -143,7 +144,8 @@ func checkTestRepository(t *testing.T, repository distribution.Repository, remov
|
||||||
}
|
}
|
||||||
|
|
||||||
m := schema2.Manifest{
|
m := schema2.Manifest{
|
||||||
Versioned: schema2.SchemaVersion,
|
Versioned: specs.Versioned{SchemaVersion: 2},
|
||||||
|
MediaType: schema2.MediaTypeManifest,
|
||||||
Config: distribution.Descriptor{
|
Config: distribution.Descriptor{
|
||||||
MediaType: "foo/bar",
|
MediaType: "foo/bar",
|
||||||
Digest: configDgst,
|
Digest: configDgst,
|
||||||
|
|
|
@ -21,7 +21,7 @@ import (
|
||||||
// init handles registering the token auth backend.
|
// init handles registering the token auth backend.
|
||||||
func init() {
|
func init() {
|
||||||
if err := auth.Register("token", auth.InitFunc(newAccessController)); err != nil {
|
if err := auth.Register("token", auth.InitFunc(newAccessController)); err != nil {
|
||||||
logrus.Errorf("tailed to register token auth: %v", err)
|
logrus.Errorf("failed to register token auth: %v", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -21,7 +21,6 @@ import (
|
||||||
|
|
||||||
"github.com/distribution/distribution/v3"
|
"github.com/distribution/distribution/v3"
|
||||||
"github.com/distribution/distribution/v3/configuration"
|
"github.com/distribution/distribution/v3/configuration"
|
||||||
"github.com/distribution/distribution/v3/manifest"
|
|
||||||
"github.com/distribution/distribution/v3/manifest/manifestlist"
|
"github.com/distribution/distribution/v3/manifest/manifestlist"
|
||||||
"github.com/distribution/distribution/v3/manifest/schema2"
|
"github.com/distribution/distribution/v3/manifest/schema2"
|
||||||
"github.com/distribution/distribution/v3/registry/api/errcode"
|
"github.com/distribution/distribution/v3/registry/api/errcode"
|
||||||
|
@ -33,6 +32,7 @@ import (
|
||||||
"github.com/distribution/reference"
|
"github.com/distribution/reference"
|
||||||
"github.com/gorilla/handlers"
|
"github.com/gorilla/handlers"
|
||||||
"github.com/opencontainers/go-digest"
|
"github.com/opencontainers/go-digest"
|
||||||
|
"github.com/opencontainers/image-spec/specs-go"
|
||||||
)
|
)
|
||||||
|
|
||||||
var headerConfig = http.Header{
|
var headerConfig = http.Header{
|
||||||
|
@ -1577,10 +1577,8 @@ func testManifestAPISchema2(t *testing.T, env *testEnv, imageName reference.Name
|
||||||
// --------------------------------
|
// --------------------------------
|
||||||
// Attempt to push manifest with missing config and missing layers
|
// Attempt to push manifest with missing config and missing layers
|
||||||
manifest := &schema2.Manifest{
|
manifest := &schema2.Manifest{
|
||||||
Versioned: manifest.Versioned{
|
Versioned: specs.Versioned{SchemaVersion: 2},
|
||||||
SchemaVersion: 2,
|
|
||||||
MediaType: schema2.MediaTypeManifest,
|
MediaType: schema2.MediaTypeManifest,
|
||||||
},
|
|
||||||
Config: distribution.Descriptor{
|
Config: distribution.Descriptor{
|
||||||
Digest: "sha256:1a9ec845ee94c202b2d5da74a24f0ed2058318bfa9879fa541efaecba272e86b",
|
Digest: "sha256:1a9ec845ee94c202b2d5da74a24f0ed2058318bfa9879fa541efaecba272e86b",
|
||||||
Size: 3253,
|
Size: 3253,
|
||||||
|
@ -1900,10 +1898,8 @@ func testManifestAPIManifestList(t *testing.T, env *testEnv, args manifestArgs)
|
||||||
// --------------------------------
|
// --------------------------------
|
||||||
// Attempt to push manifest list that refers to an unknown manifest
|
// Attempt to push manifest list that refers to an unknown manifest
|
||||||
manifestList := &manifestlist.ManifestList{
|
manifestList := &manifestlist.ManifestList{
|
||||||
Versioned: manifest.Versioned{
|
Versioned: specs.Versioned{SchemaVersion: 2},
|
||||||
SchemaVersion: 2,
|
|
||||||
MediaType: manifestlist.MediaTypeManifestList,
|
MediaType: manifestlist.MediaTypeManifestList,
|
||||||
},
|
|
||||||
Manifests: []manifestlist.ManifestDescriptor{
|
Manifests: []manifestlist.ManifestDescriptor{
|
||||||
{
|
{
|
||||||
Descriptor: distribution.Descriptor{
|
Descriptor: distribution.Descriptor{
|
||||||
|
@ -2639,10 +2635,8 @@ func createRepository(env *testEnv, t *testing.T, imageName string, tag string)
|
||||||
}
|
}
|
||||||
|
|
||||||
manifest := &schema2.Manifest{
|
manifest := &schema2.Manifest{
|
||||||
Versioned: manifest.Versioned{
|
Versioned: specs.Versioned{SchemaVersion: 2},
|
||||||
SchemaVersion: 2,
|
|
||||||
MediaType: schema2.MediaTypeManifest,
|
MediaType: schema2.MediaTypeManifest,
|
||||||
},
|
|
||||||
Config: distribution.Descriptor{
|
Config: distribution.Descriptor{
|
||||||
Digest: "sha256:1a9ec845ee94c202b2d5da74a24f0ed2058318bfa9879fa541efaecba272e86b",
|
Digest: "sha256:1a9ec845ee94c202b2d5da74a24f0ed2058318bfa9879fa541efaecba272e86b",
|
||||||
Size: 3253,
|
Size: 3253,
|
||||||
|
@ -2736,10 +2730,8 @@ func TestRegistryAsCacheMutationAPIs(t *testing.T) {
|
||||||
|
|
||||||
// Manifest upload
|
// Manifest upload
|
||||||
manifest := &schema2.Manifest{
|
manifest := &schema2.Manifest{
|
||||||
Versioned: manifest.Versioned{
|
Versioned: specs.Versioned{SchemaVersion: 2},
|
||||||
SchemaVersion: 2,
|
|
||||||
MediaType: schema2.MediaTypeManifest,
|
MediaType: schema2.MediaTypeManifest,
|
||||||
},
|
|
||||||
Config: distribution.Descriptor{
|
Config: distribution.Descriptor{
|
||||||
Digest: "sha256:1a9ec845ee94c202b2d5da74a24f0ed2058318bfa9879fa541efaecba272e86b",
|
Digest: "sha256:1a9ec845ee94c202b2d5da74a24f0ed2058318bfa9879fa541efaecba272e86b",
|
||||||
Size: 3253,
|
Size: 3253,
|
||||||
|
|
|
@ -17,6 +17,7 @@ import (
|
||||||
"github.com/distribution/distribution/v3/testutil"
|
"github.com/distribution/distribution/v3/testutil"
|
||||||
"github.com/distribution/reference"
|
"github.com/distribution/reference"
|
||||||
"github.com/opencontainers/go-digest"
|
"github.com/opencontainers/go-digest"
|
||||||
|
"github.com/opencontainers/image-spec/specs-go"
|
||||||
)
|
)
|
||||||
|
|
||||||
type statsManifest struct {
|
type statsManifest struct {
|
||||||
|
@ -153,7 +154,8 @@ func populateRepo(ctx context.Context, t *testing.T, repository distribution.Rep
|
||||||
}
|
}
|
||||||
|
|
||||||
m := schema2.Manifest{
|
m := schema2.Manifest{
|
||||||
Versioned: schema2.SchemaVersion,
|
Versioned: specs.Versioned{SchemaVersion: 2},
|
||||||
|
MediaType: schema2.MediaTypeManifest,
|
||||||
Config: distribution.Descriptor{
|
Config: distribution.Descriptor{
|
||||||
MediaType: "foo/bar",
|
MediaType: "foo/bar",
|
||||||
Digest: configDigest,
|
Digest: configDigest,
|
||||||
|
|
|
@ -14,7 +14,7 @@ import (
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
if err := storagemiddleware.Register("redirect", newRedirectStorageMiddleware); err != nil {
|
if err := storagemiddleware.Register("redirect", newRedirectStorageMiddleware); err != nil {
|
||||||
logrus.Errorf("tailed to register redirect storage middleware: %v", err)
|
logrus.Errorf("failed to register redirect storage middleware: %v", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -14,7 +14,7 @@ import (
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
if err := storagemiddleware.Register("rewrite", newRewriteStorageMiddleware); err != nil {
|
if err := storagemiddleware.Register("rewrite", newRewriteStorageMiddleware); err != nil {
|
||||||
logrus.Errorf("tailed to register redirect storage middleware: %v", err)
|
logrus.Errorf("failed to register redirect storage middleware: %v", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -223,12 +223,13 @@ func FromParameters(ctx context.Context, parameters map[string]interface{}) (*Dr
|
||||||
}
|
}
|
||||||
|
|
||||||
regionName := parameters["region"]
|
regionName := parameters["region"]
|
||||||
if regionName == nil || fmt.Sprint(regionName) == "" {
|
|
||||||
return nil, fmt.Errorf("no region parameter provided")
|
|
||||||
}
|
|
||||||
region := fmt.Sprint(regionName)
|
region := fmt.Sprint(regionName)
|
||||||
|
|
||||||
// Don't check the region value if a custom endpoint is provided.
|
// Don't check the region value if a custom endpoint is provided.
|
||||||
if regionEndpoint == "" {
|
if regionEndpoint == "" {
|
||||||
|
if regionName == nil || region == "" {
|
||||||
|
return nil, fmt.Errorf("no region parameter provided")
|
||||||
|
}
|
||||||
if _, ok := validRegions[region]; !ok {
|
if _, ok := validRegions[region]; !ok {
|
||||||
return nil, fmt.Errorf("invalid region provided: %v", region)
|
return nil, fmt.Errorf("invalid region provided: %v", region)
|
||||||
}
|
}
|
||||||
|
@ -763,37 +764,76 @@ func (d *driver) Writer(ctx context.Context, path string, appendMode bool) (stor
|
||||||
return nil, storagedriver.PathNotFoundError{Path: path}
|
return nil, storagedriver.PathNotFoundError{Path: path}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Stat retrieves the FileInfo for the given path, including the current size
|
func (d *driver) statHead(ctx context.Context, path string) (*storagedriver.FileInfoFields, error) {
|
||||||
// in bytes and the creation time.
|
resp, err := d.S3.HeadObjectWithContext(ctx, &s3.HeadObjectInput{
|
||||||
func (d *driver) Stat(ctx context.Context, path string) (storagedriver.FileInfo, error) {
|
Bucket: aws.String(d.Bucket),
|
||||||
|
Key: aws.String(d.s3Path(path)),
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &storagedriver.FileInfoFields{
|
||||||
|
Path: path,
|
||||||
|
IsDir: false,
|
||||||
|
Size: *resp.ContentLength,
|
||||||
|
ModTime: *resp.LastModified,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *driver) statList(ctx context.Context, path string) (*storagedriver.FileInfoFields, error) {
|
||||||
|
s3Path := d.s3Path(path)
|
||||||
resp, err := d.S3.ListObjectsV2WithContext(ctx, &s3.ListObjectsV2Input{
|
resp, err := d.S3.ListObjectsV2WithContext(ctx, &s3.ListObjectsV2Input{
|
||||||
Bucket: aws.String(d.Bucket),
|
Bucket: aws.String(d.Bucket),
|
||||||
Prefix: aws.String(d.s3Path(path)),
|
Prefix: aws.String(s3Path),
|
||||||
MaxKeys: aws.Int64(1),
|
MaxKeys: aws.Int64(1),
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
fi := storagedriver.FileInfoFields{
|
|
||||||
Path: path,
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(resp.Contents) == 1 {
|
if len(resp.Contents) == 1 {
|
||||||
if *resp.Contents[0].Key != d.s3Path(path) {
|
if *resp.Contents[0].Key != s3Path {
|
||||||
fi.IsDir = true
|
return &storagedriver.FileInfoFields{
|
||||||
} else {
|
Path: path,
|
||||||
fi.IsDir = false
|
IsDir: true,
|
||||||
fi.Size = *resp.Contents[0].Size
|
}, nil
|
||||||
fi.ModTime = *resp.Contents[0].LastModified
|
}
|
||||||
|
return &storagedriver.FileInfoFields{
|
||||||
|
Path: path,
|
||||||
|
Size: *resp.Contents[0].Size,
|
||||||
|
ModTime: *resp.Contents[0].LastModified,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
if len(resp.CommonPrefixes) == 1 {
|
||||||
|
return &storagedriver.FileInfoFields{
|
||||||
|
Path: path,
|
||||||
|
IsDir: true,
|
||||||
|
}, nil
|
||||||
}
|
}
|
||||||
} else if len(resp.CommonPrefixes) == 1 {
|
|
||||||
fi.IsDir = true
|
|
||||||
} else {
|
|
||||||
return nil, storagedriver.PathNotFoundError{Path: path}
|
return nil, storagedriver.PathNotFoundError{Path: path}
|
||||||
}
|
}
|
||||||
|
|
||||||
return storagedriver.FileInfoInternal{FileInfoFields: fi}, nil
|
// Stat retrieves the FileInfo for the given path, including the current size
|
||||||
|
// in bytes and the creation time.
|
||||||
|
func (d *driver) Stat(ctx context.Context, path string) (storagedriver.FileInfo, error) {
|
||||||
|
fi, err := d.statHead(ctx, path)
|
||||||
|
if err != nil {
|
||||||
|
// For AWS errors, we fail over to ListObjects:
|
||||||
|
// Though the official docs https://docs.aws.amazon.com/AmazonS3/latest/API/API_HeadObject.html#API_HeadObject_Errors
|
||||||
|
// are slightly outdated, the HeadObject actually returns NotFound error
|
||||||
|
// if querying a key which doesn't exist or a key which has nested keys
|
||||||
|
// and Forbidden if IAM/ACL permissions do not allow Head but allow List.
|
||||||
|
var awsErr awserr.Error
|
||||||
|
if errors.As(err, &awsErr) {
|
||||||
|
fi, err := d.statList(ctx, path)
|
||||||
|
if err != nil {
|
||||||
|
return nil, parseError(path, err)
|
||||||
|
}
|
||||||
|
return storagedriver.FileInfoInternal{FileInfoFields: *fi}, nil
|
||||||
|
}
|
||||||
|
// For non-AWS errors, return the error directly
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return storagedriver.FileInfoInternal{FileInfoFields: *fi}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// List returns a list of the objects that are direct descendants of the given path.
|
// List returns a list of the objects that are direct descendants of the given path.
|
||||||
|
@ -834,7 +874,10 @@ func (d *driver) List(ctx context.Context, opath string) ([]string, error) {
|
||||||
directories = append(directories, strings.Replace(commonPrefix[0:len(commonPrefix)-1], d.s3Path(""), prefix, 1))
|
directories = append(directories, strings.Replace(commonPrefix[0:len(commonPrefix)-1], d.s3Path(""), prefix, 1))
|
||||||
}
|
}
|
||||||
|
|
||||||
if *resp.IsTruncated {
|
if resp.IsTruncated == nil || !*resp.IsTruncated {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
resp, err = d.S3.ListObjectsV2WithContext(ctx, &s3.ListObjectsV2Input{
|
resp, err = d.S3.ListObjectsV2WithContext(ctx, &s3.ListObjectsV2Input{
|
||||||
Bucket: aws.String(d.Bucket),
|
Bucket: aws.String(d.Bucket),
|
||||||
Prefix: aws.String(d.s3Path(path)),
|
Prefix: aws.String(d.s3Path(path)),
|
||||||
|
@ -845,9 +888,6 @@ func (d *driver) List(ctx context.Context, opath string) ([]string, error) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if opath != "/" {
|
if opath != "/" {
|
||||||
|
|
|
@ -35,17 +35,17 @@ func (ms *manifestListHandler) Unmarshal(ctx context.Context, dgst digest.Digest
|
||||||
func (ms *manifestListHandler) Put(ctx context.Context, manifestList distribution.Manifest, skipDependencyVerification bool) (digest.Digest, error) {
|
func (ms *manifestListHandler) Put(ctx context.Context, manifestList distribution.Manifest, skipDependencyVerification bool) (digest.Digest, error) {
|
||||||
dcontext.GetLogger(ms.ctx).Debug("(*manifestListHandler).Put")
|
dcontext.GetLogger(ms.ctx).Debug("(*manifestListHandler).Put")
|
||||||
|
|
||||||
var schemaVersion, expectedSchemaVersion int
|
var schemaVersion int
|
||||||
switch m := manifestList.(type) {
|
switch m := manifestList.(type) {
|
||||||
case *manifestlist.DeserializedManifestList:
|
case *manifestlist.DeserializedManifestList:
|
||||||
expectedSchemaVersion = manifestlist.SchemaVersion.SchemaVersion
|
|
||||||
schemaVersion = m.SchemaVersion
|
schemaVersion = m.SchemaVersion
|
||||||
case *ocischema.DeserializedImageIndex:
|
case *ocischema.DeserializedImageIndex:
|
||||||
expectedSchemaVersion = ocischema.IndexSchemaVersion.SchemaVersion
|
|
||||||
schemaVersion = m.SchemaVersion
|
schemaVersion = m.SchemaVersion
|
||||||
default:
|
default:
|
||||||
return "", fmt.Errorf("wrong type put to manifestListHandler: %T", manifestList)
|
return "", fmt.Errorf("wrong type put to manifestListHandler: %T", manifestList)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const expectedSchemaVersion = 2
|
||||||
if schemaVersion != expectedSchemaVersion {
|
if schemaVersion != expectedSchemaVersion {
|
||||||
return "", fmt.Errorf("unrecognized manifest list schema version %d, expected %d", schemaVersion, expectedSchemaVersion)
|
return "", fmt.Errorf("unrecognized manifest list schema version %d, expected %d", schemaVersion, expectedSchemaVersion)
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,11 +7,11 @@ import (
|
||||||
|
|
||||||
"github.com/distribution/distribution/v3"
|
"github.com/distribution/distribution/v3"
|
||||||
"github.com/distribution/distribution/v3/internal/dcontext"
|
"github.com/distribution/distribution/v3/internal/dcontext"
|
||||||
"github.com/distribution/distribution/v3/manifest"
|
|
||||||
"github.com/distribution/distribution/v3/manifest/manifestlist"
|
"github.com/distribution/distribution/v3/manifest/manifestlist"
|
||||||
"github.com/distribution/distribution/v3/manifest/ocischema"
|
"github.com/distribution/distribution/v3/manifest/ocischema"
|
||||||
"github.com/distribution/distribution/v3/manifest/schema2"
|
"github.com/distribution/distribution/v3/manifest/schema2"
|
||||||
"github.com/opencontainers/go-digest"
|
"github.com/opencontainers/go-digest"
|
||||||
|
"github.com/opencontainers/image-spec/specs-go"
|
||||||
v1 "github.com/opencontainers/image-spec/specs-go/v1"
|
v1 "github.com/opencontainers/image-spec/specs-go/v1"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -88,7 +88,13 @@ func (ms *manifestStore) Get(ctx context.Context, dgst digest.Digest, options ..
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
var versioned manifest.Versioned
|
// versioned is a minimal representation of a manifest with version and mediatype.
|
||||||
|
var versioned struct {
|
||||||
|
specs.Versioned
|
||||||
|
|
||||||
|
// MediaType is the media type of this schema.
|
||||||
|
MediaType string `json:"mediaType,omitempty"`
|
||||||
|
}
|
||||||
if err = json.Unmarshal(content, &versioned); err != nil {
|
if err = json.Unmarshal(content, &versioned); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,7 +9,6 @@ import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/distribution/distribution/v3"
|
"github.com/distribution/distribution/v3"
|
||||||
"github.com/distribution/distribution/v3/manifest"
|
|
||||||
"github.com/distribution/distribution/v3/manifest/manifestlist"
|
"github.com/distribution/distribution/v3/manifest/manifestlist"
|
||||||
"github.com/distribution/distribution/v3/manifest/ocischema"
|
"github.com/distribution/distribution/v3/manifest/ocischema"
|
||||||
"github.com/distribution/distribution/v3/manifest/schema2"
|
"github.com/distribution/distribution/v3/manifest/schema2"
|
||||||
|
@ -19,6 +18,7 @@ import (
|
||||||
"github.com/distribution/distribution/v3/testutil"
|
"github.com/distribution/distribution/v3/testutil"
|
||||||
"github.com/distribution/reference"
|
"github.com/distribution/reference"
|
||||||
"github.com/opencontainers/go-digest"
|
"github.com/opencontainers/go-digest"
|
||||||
|
"github.com/opencontainers/image-spec/specs-go"
|
||||||
v1 "github.com/opencontainers/image-spec/specs-go/v1"
|
v1 "github.com/opencontainers/image-spec/specs-go/v1"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -94,10 +94,8 @@ func testManifestStorage(t *testing.T, options ...RegistryOption) {
|
||||||
builder := schema2.NewManifestBuilder(d, sampleConfig)
|
builder := schema2.NewManifestBuilder(d, sampleConfig)
|
||||||
|
|
||||||
m := &schema2.Manifest{
|
m := &schema2.Manifest{
|
||||||
Versioned: manifest.Versioned{
|
Versioned: specs.Versioned{SchemaVersion: 2},
|
||||||
SchemaVersion: 2,
|
|
||||||
MediaType: schema2.MediaTypeManifest,
|
MediaType: schema2.MediaTypeManifest,
|
||||||
},
|
|
||||||
Config: distribution.Descriptor{
|
Config: distribution.Descriptor{
|
||||||
Digest: digest.FromBytes(sampleConfig),
|
Digest: digest.FromBytes(sampleConfig),
|
||||||
Size: int64(len(sampleConfig)),
|
Size: int64(len(sampleConfig)),
|
||||||
|
@ -393,7 +391,7 @@ func testOCIManifestStorage(t *testing.T, testname string, includeMediaTypes boo
|
||||||
t.Fatalf("%s: unexpected MediaType for result, %s", testname, fetchedManifest.MediaType)
|
t.Fatalf("%s: unexpected MediaType for result, %s", testname, fetchedManifest.MediaType)
|
||||||
}
|
}
|
||||||
|
|
||||||
if fetchedManifest.SchemaVersion != ocischema.SchemaVersion.SchemaVersion {
|
if fetchedManifest.SchemaVersion != 2 {
|
||||||
t.Fatalf("%s: unexpected schema version for result, %d", testname, fetchedManifest.SchemaVersion)
|
t.Fatalf("%s: unexpected schema version for result, %d", testname, fetchedManifest.SchemaVersion)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -595,7 +593,7 @@ func TestIndexManifestStorageWithSelectivePlatforms(t *testing.T) {
|
||||||
// createRandomImage builds an image manifest and store it and its layers in the registry
|
// createRandomImage builds an image manifest and store it and its layers in the registry
|
||||||
func createRandomImage(t *testing.T, testname string, imageMediaType string, blobStore distribution.BlobStore) (distribution.Manifest, error) {
|
func createRandomImage(t *testing.T, testname string, imageMediaType string, blobStore distribution.BlobStore) (distribution.Manifest, error) {
|
||||||
builder := ocischema.NewManifestBuilder(blobStore, []byte{}, map[string]string{})
|
builder := ocischema.NewManifestBuilder(blobStore, []byte{}, map[string]string{})
|
||||||
err := builder.(*ocischema.Builder).SetMediaType(imageMediaType)
|
err := builder.SetMediaType(imageMediaType)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
|
@ -88,7 +88,7 @@ func (ms *ocischemaManifestHandler) verifyManifest(ctx context.Context, mnfst oc
|
||||||
}
|
}
|
||||||
|
|
||||||
switch descriptor.MediaType {
|
switch descriptor.MediaType {
|
||||||
case v1.MediaTypeImageLayer, v1.MediaTypeImageLayerGzip, v1.MediaTypeImageLayerNonDistributable, v1.MediaTypeImageLayerNonDistributableGzip:
|
case v1.MediaTypeImageLayer, v1.MediaTypeImageLayerGzip, v1.MediaTypeImageLayerNonDistributable, v1.MediaTypeImageLayerNonDistributableGzip: //nolint:staticcheck // ignore A1019: v1.MediaTypeImageLayerNonDistributable is deprecated: Non-distributable layers are deprecated, and not recommended for future use.
|
||||||
allow := ms.manifestURLs.allow
|
allow := ms.manifestURLs.allow
|
||||||
deny := ms.manifestURLs.deny
|
deny := ms.manifestURLs.deny
|
||||||
for _, u := range descriptor.URLs {
|
for _, u := range descriptor.URLs {
|
||||||
|
|
|
@ -7,10 +7,10 @@ import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/distribution/distribution/v3"
|
"github.com/distribution/distribution/v3"
|
||||||
"github.com/distribution/distribution/v3/manifest"
|
|
||||||
"github.com/distribution/distribution/v3/manifest/ocischema"
|
"github.com/distribution/distribution/v3/manifest/ocischema"
|
||||||
"github.com/distribution/distribution/v3/registry/storage/driver/inmemory"
|
"github.com/distribution/distribution/v3/registry/storage/driver/inmemory"
|
||||||
"github.com/opencontainers/go-digest"
|
"github.com/opencontainers/go-digest"
|
||||||
|
"github.com/opencontainers/image-spec/specs-go"
|
||||||
v1 "github.com/opencontainers/image-spec/specs-go/v1"
|
v1 "github.com/opencontainers/image-spec/specs-go/v1"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -36,7 +36,7 @@ func TestVerifyOCIManifestNonDistributableLayer(t *testing.T) {
|
||||||
nonDistributableLayer := distribution.Descriptor{
|
nonDistributableLayer := distribution.Descriptor{
|
||||||
Digest: "sha256:463435349086340864309863409683460843608348608934092322395278926a",
|
Digest: "sha256:463435349086340864309863409683460843608348608934092322395278926a",
|
||||||
Size: 6323,
|
Size: 6323,
|
||||||
MediaType: v1.MediaTypeImageLayerNonDistributableGzip,
|
MediaType: v1.MediaTypeImageLayerNonDistributableGzip, //nolint:staticcheck // ignore A1019: v1.MediaTypeImageLayerNonDistributableGzip is deprecated: Non-distributable layers are deprecated, and not recommended for future use
|
||||||
}
|
}
|
||||||
|
|
||||||
emptyLayer := distribution.Descriptor{
|
emptyLayer := distribution.Descriptor{
|
||||||
|
@ -49,10 +49,8 @@ func TestVerifyOCIManifestNonDistributableLayer(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
template := ocischema.Manifest{
|
template := ocischema.Manifest{
|
||||||
Versioned: manifest.Versioned{
|
Versioned: specs.Versioned{SchemaVersion: 2},
|
||||||
SchemaVersion: 2,
|
|
||||||
MediaType: v1.MediaTypeImageManifest,
|
MediaType: v1.MediaTypeImageManifest,
|
||||||
},
|
|
||||||
Config: config,
|
Config: config,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -189,10 +187,8 @@ func TestVerifyOCIManifestBlobLayerAndConfig(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
template := ocischema.Manifest{
|
template := ocischema.Manifest{
|
||||||
Versioned: manifest.Versioned{
|
Versioned: specs.Versioned{SchemaVersion: 2},
|
||||||
SchemaVersion: 2,
|
|
||||||
MediaType: v1.MediaTypeImageManifest,
|
MediaType: v1.MediaTypeImageManifest,
|
||||||
},
|
|
||||||
}
|
}
|
||||||
|
|
||||||
checkFn := func(m ocischema.Manifest, rerr error) {
|
checkFn := func(m ocischema.Manifest, rerr error) {
|
||||||
|
|
|
@ -7,10 +7,10 @@ import (
|
||||||
|
|
||||||
"github.com/distribution/distribution/v3"
|
"github.com/distribution/distribution/v3"
|
||||||
"github.com/distribution/distribution/v3/internal/dcontext"
|
"github.com/distribution/distribution/v3/internal/dcontext"
|
||||||
"github.com/distribution/distribution/v3/manifest"
|
|
||||||
"github.com/distribution/distribution/v3/manifest/schema2"
|
"github.com/distribution/distribution/v3/manifest/schema2"
|
||||||
"github.com/distribution/distribution/v3/registry/storage/driver/inmemory"
|
"github.com/distribution/distribution/v3/registry/storage/driver/inmemory"
|
||||||
"github.com/opencontainers/go-digest"
|
"github.com/opencontainers/go-digest"
|
||||||
|
"github.com/opencontainers/image-spec/specs-go"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestVerifyManifestForeignLayer(t *testing.T) {
|
func TestVerifyManifestForeignLayer(t *testing.T) {
|
||||||
|
@ -45,10 +45,8 @@ func TestVerifyManifestForeignLayer(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
template := schema2.Manifest{
|
template := schema2.Manifest{
|
||||||
Versioned: manifest.Versioned{
|
Versioned: specs.Versioned{SchemaVersion: 2},
|
||||||
SchemaVersion: 2,
|
|
||||||
MediaType: schema2.MediaTypeManifest,
|
MediaType: schema2.MediaTypeManifest,
|
||||||
},
|
|
||||||
Config: config,
|
Config: config,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -176,10 +174,8 @@ func TestVerifyManifestBlobLayerAndConfig(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
template := schema2.Manifest{
|
template := schema2.Manifest{
|
||||||
Versioned: manifest.Versioned{
|
Versioned: specs.Versioned{SchemaVersion: 2},
|
||||||
SchemaVersion: 2,
|
|
||||||
MediaType: schema2.MediaTypeManifest,
|
MediaType: schema2.MediaTypeManifest,
|
||||||
},
|
|
||||||
}
|
}
|
||||||
|
|
||||||
checkFn := func(m schema2.Manifest, rerr error) {
|
checkFn := func(m schema2.Manifest, rerr error) {
|
||||||
|
|
|
@ -6,11 +6,11 @@ import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/distribution/distribution/v3"
|
"github.com/distribution/distribution/v3"
|
||||||
"github.com/distribution/distribution/v3/manifest"
|
|
||||||
"github.com/distribution/distribution/v3/manifest/schema2"
|
"github.com/distribution/distribution/v3/manifest/schema2"
|
||||||
"github.com/distribution/distribution/v3/registry/storage/driver/inmemory"
|
"github.com/distribution/distribution/v3/registry/storage/driver/inmemory"
|
||||||
"github.com/distribution/reference"
|
"github.com/distribution/reference"
|
||||||
digest "github.com/opencontainers/go-digest"
|
digest "github.com/opencontainers/go-digest"
|
||||||
|
"github.com/opencontainers/image-spec/specs-go"
|
||||||
)
|
)
|
||||||
|
|
||||||
type tagsTestEnv struct {
|
type tagsTestEnv struct {
|
||||||
|
@ -243,10 +243,8 @@ func TestTagIndexes(t *testing.T) {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
m := schema2.Manifest{
|
m := schema2.Manifest{
|
||||||
Versioned: manifest.Versioned{
|
Versioned: specs.Versioned{SchemaVersion: 2},
|
||||||
SchemaVersion: 2,
|
|
||||||
MediaType: schema2.MediaTypeManifest,
|
MediaType: schema2.MediaTypeManifest,
|
||||||
},
|
|
||||||
Config: distribution.Descriptor{
|
Config: distribution.Descriptor{
|
||||||
Digest: conf.Digest,
|
Digest: conf.Digest,
|
||||||
Size: 1,
|
Size: 1,
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
package testutil
|
package testutil
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/distribution/distribution/v3"
|
"github.com/distribution/distribution/v3"
|
||||||
|
@ -51,7 +50,18 @@ func MakeSchema2Manifest(repository distribution.Repository, digests []digest.Di
|
||||||
return nil, fmt.Errorf("unexpected error storing content in blobstore: %v", err)
|
return nil, fmt.Errorf("unexpected error storing content in blobstore: %v", err)
|
||||||
}
|
}
|
||||||
builder := schema2.NewManifestBuilder(d, configJSON)
|
builder := schema2.NewManifestBuilder(d, configJSON)
|
||||||
return makeManifest(ctx, builder, digests)
|
for _, dgst := range digests {
|
||||||
|
if err := builder.AppendReference(distribution.Descriptor{Digest: dgst}); err != nil {
|
||||||
|
return nil, fmt.Errorf("unexpected error building schema2 manifest: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mfst, err := builder.Build(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("unexpected error generating schema2 manifest: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return mfst, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func MakeOCIManifest(repository distribution.Repository, digests []digest.Digest) (distribution.Manifest, error) {
|
func MakeOCIManifest(repository distribution.Repository, digests []digest.Digest) (distribution.Manifest, error) {
|
||||||
|
@ -61,19 +71,15 @@ func MakeOCIManifest(repository distribution.Repository, digests []digest.Digest
|
||||||
var configJSON []byte
|
var configJSON []byte
|
||||||
|
|
||||||
builder := ocischema.NewManifestBuilder(blobStore, configJSON, make(map[string]string))
|
builder := ocischema.NewManifestBuilder(blobStore, configJSON, make(map[string]string))
|
||||||
return makeManifest(ctx, builder, digests)
|
for _, dgst := range digests {
|
||||||
}
|
if err := builder.AppendReference(distribution.Descriptor{Digest: dgst}); err != nil {
|
||||||
|
return nil, fmt.Errorf("unexpected error building OCI manifest: %v", err)
|
||||||
func makeManifest(ctx context.Context, builder distribution.ManifestBuilder, digests []digest.Digest) (distribution.Manifest, error) {
|
|
||||||
for _, digest := range digests {
|
|
||||||
if err := builder.AppendReference(distribution.Descriptor{Digest: digest}); err != nil {
|
|
||||||
return nil, fmt.Errorf("unexpected error building manifest: %v", err)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
mfst, err := builder.Build(ctx)
|
mfst, err := builder.Build(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("unexpected error generating manifest: %v", err)
|
return nil, fmt.Errorf("unexpected error generating OCI manifest: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return mfst, nil
|
return mfst, nil
|
||||||
|
|
6
vendor/github.com/opencontainers/image-spec/specs-go/v1/annotations.go
generated
vendored
6
vendor/github.com/opencontainers/image-spec/specs-go/v1/annotations.go
generated
vendored
|
@ -53,4 +53,10 @@ const (
|
||||||
|
|
||||||
// AnnotationDescription is the annotation key for the human-readable description of the software packaged in the image.
|
// AnnotationDescription is the annotation key for the human-readable description of the software packaged in the image.
|
||||||
AnnotationDescription = "org.opencontainers.image.description"
|
AnnotationDescription = "org.opencontainers.image.description"
|
||||||
|
|
||||||
|
// AnnotationBaseImageDigest is the annotation key for the digest of the image's base image.
|
||||||
|
AnnotationBaseImageDigest = "org.opencontainers.image.base.digest"
|
||||||
|
|
||||||
|
// AnnotationBaseImageName is the annotation key for the image reference of the image's base image.
|
||||||
|
AnnotationBaseImageName = "org.opencontainers.image.base.name"
|
||||||
)
|
)
|
||||||
|
|
18
vendor/github.com/opencontainers/image-spec/specs-go/v1/config.go
generated
vendored
18
vendor/github.com/opencontainers/image-spec/specs-go/v1/config.go
generated
vendored
|
@ -48,6 +48,17 @@ type ImageConfig struct {
|
||||||
|
|
||||||
// StopSignal contains the system call signal that will be sent to the container to exit.
|
// StopSignal contains the system call signal that will be sent to the container to exit.
|
||||||
StopSignal string `json:"StopSignal,omitempty"`
|
StopSignal string `json:"StopSignal,omitempty"`
|
||||||
|
|
||||||
|
// ArgsEscaped
|
||||||
|
//
|
||||||
|
// Deprecated: This field is present only for legacy compatibility with
|
||||||
|
// Docker and should not be used by new image builders. It is used by Docker
|
||||||
|
// for Windows images to indicate that the `Entrypoint` or `Cmd` or both,
|
||||||
|
// contains only a single element array, that is a pre-escaped, and combined
|
||||||
|
// into a single string `CommandLine`. If `true` the value in `Entrypoint` or
|
||||||
|
// `Cmd` should be used as-is to avoid double escaping.
|
||||||
|
// https://github.com/opencontainers/image-spec/pull/892
|
||||||
|
ArgsEscaped bool `json:"ArgsEscaped,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// RootFS describes a layer content addresses
|
// RootFS describes a layer content addresses
|
||||||
|
@ -86,11 +97,8 @@ type Image struct {
|
||||||
// Author defines the name and/or email address of the person or entity which created and is responsible for maintaining the image.
|
// Author defines the name and/or email address of the person or entity which created and is responsible for maintaining the image.
|
||||||
Author string `json:"author,omitempty"`
|
Author string `json:"author,omitempty"`
|
||||||
|
|
||||||
// Architecture is the CPU architecture which the binaries in this image are built to run on.
|
// Platform describes the platform which the image in the manifest runs on.
|
||||||
Architecture string `json:"architecture"`
|
Platform
|
||||||
|
|
||||||
// OS is the name of the operating system which the image is built to run on.
|
|
||||||
OS string `json:"os"`
|
|
||||||
|
|
||||||
// Config defines the execution parameters which should be used as a base when running a container using the image.
|
// Config defines the execution parameters which should be used as a base when running a container using the image.
|
||||||
Config ImageConfig `json:"config,omitempty"`
|
Config ImageConfig `json:"config,omitempty"`
|
||||||
|
|
22
vendor/github.com/opencontainers/image-spec/specs-go/v1/descriptor.go
generated
vendored
22
vendor/github.com/opencontainers/image-spec/specs-go/v1/descriptor.go
generated
vendored
|
@ -1,4 +1,4 @@
|
||||||
// Copyright 2016 The Linux Foundation
|
// Copyright 2016-2022 The Linux Foundation
|
||||||
//
|
//
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
// you may not use this file except in compliance with the License.
|
// you may not use this file except in compliance with the License.
|
||||||
|
@ -21,7 +21,7 @@ import digest "github.com/opencontainers/go-digest"
|
||||||
// when marshalled to JSON.
|
// when marshalled to JSON.
|
||||||
type Descriptor struct {
|
type Descriptor struct {
|
||||||
// MediaType is the media type of the object this schema refers to.
|
// MediaType is the media type of the object this schema refers to.
|
||||||
MediaType string `json:"mediaType,omitempty"`
|
MediaType string `json:"mediaType"`
|
||||||
|
|
||||||
// Digest is the digest of the targeted content.
|
// Digest is the digest of the targeted content.
|
||||||
Digest digest.Digest `json:"digest"`
|
Digest digest.Digest `json:"digest"`
|
||||||
|
@ -35,16 +35,24 @@ type Descriptor struct {
|
||||||
// Annotations contains arbitrary metadata relating to the targeted content.
|
// Annotations contains arbitrary metadata relating to the targeted content.
|
||||||
Annotations map[string]string `json:"annotations,omitempty"`
|
Annotations map[string]string `json:"annotations,omitempty"`
|
||||||
|
|
||||||
|
// Data is an embedding of the targeted content. This is encoded as a base64
|
||||||
|
// string when marshalled to JSON (automatically, by encoding/json). If
|
||||||
|
// present, Data can be used directly to avoid fetching the targeted content.
|
||||||
|
Data []byte `json:"data,omitempty"`
|
||||||
|
|
||||||
// Platform describes the platform which the image in the manifest runs on.
|
// Platform describes the platform which the image in the manifest runs on.
|
||||||
//
|
//
|
||||||
// This should only be used when referring to a manifest.
|
// This should only be used when referring to a manifest.
|
||||||
Platform *Platform `json:"platform,omitempty"`
|
Platform *Platform `json:"platform,omitempty"`
|
||||||
|
|
||||||
|
// ArtifactType is the IANA media type of this artifact.
|
||||||
|
ArtifactType string `json:"artifactType,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// Platform describes the platform which the image in the manifest runs on.
|
// Platform describes the platform which the image in the manifest runs on.
|
||||||
type Platform struct {
|
type Platform struct {
|
||||||
// Architecture field specifies the CPU architecture, for example
|
// Architecture field specifies the CPU architecture, for example
|
||||||
// `amd64` or `ppc64`.
|
// `amd64` or `ppc64le`.
|
||||||
Architecture string `json:"architecture"`
|
Architecture string `json:"architecture"`
|
||||||
|
|
||||||
// OS specifies the operating system, for example `linux` or `windows`.
|
// OS specifies the operating system, for example `linux` or `windows`.
|
||||||
|
@ -62,3 +70,11 @@ type Platform struct {
|
||||||
// example `v7` to specify ARMv7 when architecture is `arm`.
|
// example `v7` to specify ARMv7 when architecture is `arm`.
|
||||||
Variant string `json:"variant,omitempty"`
|
Variant string `json:"variant,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DescriptorEmptyJSON is the descriptor of a blob with content of `{}`.
|
||||||
|
var DescriptorEmptyJSON = Descriptor{
|
||||||
|
MediaType: MediaTypeEmptyJSON,
|
||||||
|
Digest: `sha256:44136fa355b3678a1146ad16f7e8649e94fb4fc21fe77e8310c060f61caaff8a`,
|
||||||
|
Size: 2,
|
||||||
|
Data: []byte(`{}`),
|
||||||
|
}
|
||||||
|
|
8
vendor/github.com/opencontainers/image-spec/specs-go/v1/index.go
generated
vendored
8
vendor/github.com/opencontainers/image-spec/specs-go/v1/index.go
generated
vendored
|
@ -21,12 +21,18 @@ import "github.com/opencontainers/image-spec/specs-go"
|
||||||
type Index struct {
|
type Index struct {
|
||||||
specs.Versioned
|
specs.Versioned
|
||||||
|
|
||||||
// MediaType specificies the type of this document data structure e.g. `application/vnd.oci.image.index.v1+json`
|
// MediaType specifies the type of this document data structure e.g. `application/vnd.oci.image.index.v1+json`
|
||||||
MediaType string `json:"mediaType,omitempty"`
|
MediaType string `json:"mediaType,omitempty"`
|
||||||
|
|
||||||
|
// ArtifactType specifies the IANA media type of artifact when the manifest is used for an artifact.
|
||||||
|
ArtifactType string `json:"artifactType,omitempty"`
|
||||||
|
|
||||||
// Manifests references platform specific manifests.
|
// Manifests references platform specific manifests.
|
||||||
Manifests []Descriptor `json:"manifests"`
|
Manifests []Descriptor `json:"manifests"`
|
||||||
|
|
||||||
|
// Subject is an optional link from the image manifest to another manifest forming an association between the image manifest and the other manifest.
|
||||||
|
Subject *Descriptor `json:"subject,omitempty"`
|
||||||
|
|
||||||
// Annotations contains arbitrary metadata for the image index.
|
// Annotations contains arbitrary metadata for the image index.
|
||||||
Annotations map[string]string `json:"annotations,omitempty"`
|
Annotations map[string]string `json:"annotations,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
6
vendor/github.com/opencontainers/image-spec/specs-go/v1/layout.go
generated
vendored
6
vendor/github.com/opencontainers/image-spec/specs-go/v1/layout.go
generated
vendored
|
@ -15,10 +15,14 @@
|
||||||
package v1
|
package v1
|
||||||
|
|
||||||
const (
|
const (
|
||||||
// ImageLayoutFile is the file name of oci image layout file
|
// ImageLayoutFile is the file name containing ImageLayout in an OCI Image Layout
|
||||||
ImageLayoutFile = "oci-layout"
|
ImageLayoutFile = "oci-layout"
|
||||||
// ImageLayoutVersion is the version of ImageLayout
|
// ImageLayoutVersion is the version of ImageLayout
|
||||||
ImageLayoutVersion = "1.0.0"
|
ImageLayoutVersion = "1.0.0"
|
||||||
|
// ImageIndexFile is the file name of the entry point for references and descriptors in an OCI Image Layout
|
||||||
|
ImageIndexFile = "index.json"
|
||||||
|
// ImageBlobsDir is the directory name containing content addressable blobs in an OCI Image Layout
|
||||||
|
ImageBlobsDir = "blobs"
|
||||||
)
|
)
|
||||||
|
|
||||||
// ImageLayout is the structure in the "oci-layout" file, found in the root
|
// ImageLayout is the structure in the "oci-layout" file, found in the root
|
||||||
|
|
10
vendor/github.com/opencontainers/image-spec/specs-go/v1/manifest.go
generated
vendored
10
vendor/github.com/opencontainers/image-spec/specs-go/v1/manifest.go
generated
vendored
|
@ -1,4 +1,4 @@
|
||||||
// Copyright 2016 The Linux Foundation
|
// Copyright 2016-2022 The Linux Foundation
|
||||||
//
|
//
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
// you may not use this file except in compliance with the License.
|
// you may not use this file except in compliance with the License.
|
||||||
|
@ -20,9 +20,12 @@ import "github.com/opencontainers/image-spec/specs-go"
|
||||||
type Manifest struct {
|
type Manifest struct {
|
||||||
specs.Versioned
|
specs.Versioned
|
||||||
|
|
||||||
// MediaType specificies the type of this document data structure e.g. `application/vnd.oci.image.manifest.v1+json`
|
// MediaType specifies the type of this document data structure e.g. `application/vnd.oci.image.manifest.v1+json`
|
||||||
MediaType string `json:"mediaType,omitempty"`
|
MediaType string `json:"mediaType,omitempty"`
|
||||||
|
|
||||||
|
// ArtifactType specifies the IANA media type of artifact when the manifest is used for an artifact.
|
||||||
|
ArtifactType string `json:"artifactType,omitempty"`
|
||||||
|
|
||||||
// Config references a configuration object for a container, by digest.
|
// Config references a configuration object for a container, by digest.
|
||||||
// The referenced configuration object is a JSON blob that the runtime uses to set up the container.
|
// The referenced configuration object is a JSON blob that the runtime uses to set up the container.
|
||||||
Config Descriptor `json:"config"`
|
Config Descriptor `json:"config"`
|
||||||
|
@ -30,6 +33,9 @@ type Manifest struct {
|
||||||
// Layers is an indexed list of layers referenced by the manifest.
|
// Layers is an indexed list of layers referenced by the manifest.
|
||||||
Layers []Descriptor `json:"layers"`
|
Layers []Descriptor `json:"layers"`
|
||||||
|
|
||||||
|
// Subject is an optional link from the image manifest to another manifest forming an association between the image manifest and the other manifest.
|
||||||
|
Subject *Descriptor `json:"subject,omitempty"`
|
||||||
|
|
||||||
// Annotations contains arbitrary metadata for the image manifest.
|
// Annotations contains arbitrary metadata for the image manifest.
|
||||||
Annotations map[string]string `json:"annotations,omitempty"`
|
Annotations map[string]string `json:"annotations,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
47
vendor/github.com/opencontainers/image-spec/specs-go/v1/mediatype.go
generated
vendored
47
vendor/github.com/opencontainers/image-spec/specs-go/v1/mediatype.go
generated
vendored
|
@ -21,12 +21,20 @@ const (
|
||||||
// MediaTypeLayoutHeader specifies the media type for the oci-layout.
|
// MediaTypeLayoutHeader specifies the media type for the oci-layout.
|
||||||
MediaTypeLayoutHeader = "application/vnd.oci.layout.header.v1+json"
|
MediaTypeLayoutHeader = "application/vnd.oci.layout.header.v1+json"
|
||||||
|
|
||||||
// MediaTypeImageManifest specifies the media type for an image manifest.
|
|
||||||
MediaTypeImageManifest = "application/vnd.oci.image.manifest.v1+json"
|
|
||||||
|
|
||||||
// MediaTypeImageIndex specifies the media type for an image index.
|
// MediaTypeImageIndex specifies the media type for an image index.
|
||||||
MediaTypeImageIndex = "application/vnd.oci.image.index.v1+json"
|
MediaTypeImageIndex = "application/vnd.oci.image.index.v1+json"
|
||||||
|
|
||||||
|
// MediaTypeImageManifest specifies the media type for an image manifest.
|
||||||
|
MediaTypeImageManifest = "application/vnd.oci.image.manifest.v1+json"
|
||||||
|
|
||||||
|
// MediaTypeImageConfig specifies the media type for the image configuration.
|
||||||
|
MediaTypeImageConfig = "application/vnd.oci.image.config.v1+json"
|
||||||
|
|
||||||
|
// MediaTypeEmptyJSON specifies the media type for an unused blob containing the value "{}".
|
||||||
|
MediaTypeEmptyJSON = "application/vnd.oci.empty.v1+json"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
// MediaTypeImageLayer is the media type used for layers referenced by the manifest.
|
// MediaTypeImageLayer is the media type used for layers referenced by the manifest.
|
||||||
MediaTypeImageLayer = "application/vnd.oci.image.layer.v1.tar"
|
MediaTypeImageLayer = "application/vnd.oci.image.layer.v1.tar"
|
||||||
|
|
||||||
|
@ -34,15 +42,44 @@ const (
|
||||||
// referenced by the manifest.
|
// referenced by the manifest.
|
||||||
MediaTypeImageLayerGzip = "application/vnd.oci.image.layer.v1.tar+gzip"
|
MediaTypeImageLayerGzip = "application/vnd.oci.image.layer.v1.tar+gzip"
|
||||||
|
|
||||||
|
// MediaTypeImageLayerZstd is the media type used for zstd compressed
|
||||||
|
// layers referenced by the manifest.
|
||||||
|
MediaTypeImageLayerZstd = "application/vnd.oci.image.layer.v1.tar+zstd"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Non-distributable layer media-types.
|
||||||
|
//
|
||||||
|
// Deprecated: Non-distributable layers are deprecated, and not recommended
|
||||||
|
// for future use. Implementations SHOULD NOT produce new non-distributable
|
||||||
|
// layers.
|
||||||
|
// https://github.com/opencontainers/image-spec/pull/965
|
||||||
|
const (
|
||||||
// MediaTypeImageLayerNonDistributable is the media type for layers referenced by
|
// MediaTypeImageLayerNonDistributable is the media type for layers referenced by
|
||||||
// the manifest but with distribution restrictions.
|
// the manifest but with distribution restrictions.
|
||||||
|
//
|
||||||
|
// Deprecated: Non-distributable layers are deprecated, and not recommended
|
||||||
|
// for future use. Implementations SHOULD NOT produce new non-distributable
|
||||||
|
// layers.
|
||||||
|
// https://github.com/opencontainers/image-spec/pull/965
|
||||||
MediaTypeImageLayerNonDistributable = "application/vnd.oci.image.layer.nondistributable.v1.tar"
|
MediaTypeImageLayerNonDistributable = "application/vnd.oci.image.layer.nondistributable.v1.tar"
|
||||||
|
|
||||||
// MediaTypeImageLayerNonDistributableGzip is the media type for
|
// MediaTypeImageLayerNonDistributableGzip is the media type for
|
||||||
// gzipped layers referenced by the manifest but with distribution
|
// gzipped layers referenced by the manifest but with distribution
|
||||||
// restrictions.
|
// restrictions.
|
||||||
|
//
|
||||||
|
// Deprecated: Non-distributable layers are deprecated, and not recommended
|
||||||
|
// for future use. Implementations SHOULD NOT produce new non-distributable
|
||||||
|
// layers.
|
||||||
|
// https://github.com/opencontainers/image-spec/pull/965
|
||||||
MediaTypeImageLayerNonDistributableGzip = "application/vnd.oci.image.layer.nondistributable.v1.tar+gzip"
|
MediaTypeImageLayerNonDistributableGzip = "application/vnd.oci.image.layer.nondistributable.v1.tar+gzip"
|
||||||
|
|
||||||
// MediaTypeImageConfig specifies the media type for the image configuration.
|
// MediaTypeImageLayerNonDistributableZstd is the media type for zstd
|
||||||
MediaTypeImageConfig = "application/vnd.oci.image.config.v1+json"
|
// compressed layers referenced by the manifest but with distribution
|
||||||
|
// restrictions.
|
||||||
|
//
|
||||||
|
// Deprecated: Non-distributable layers are deprecated, and not recommended
|
||||||
|
// for future use. Implementations SHOULD NOT produce new non-distributable
|
||||||
|
// layers.
|
||||||
|
// https://github.com/opencontainers/image-spec/pull/965
|
||||||
|
MediaTypeImageLayerNonDistributableZstd = "application/vnd.oci.image.layer.nondistributable.v1.tar+zstd"
|
||||||
)
|
)
|
||||||
|
|
4
vendor/github.com/opencontainers/image-spec/specs-go/version.go
generated
vendored
4
vendor/github.com/opencontainers/image-spec/specs-go/version.go
generated
vendored
|
@ -20,9 +20,9 @@ const (
|
||||||
// VersionMajor is for an API incompatible changes
|
// VersionMajor is for an API incompatible changes
|
||||||
VersionMajor = 1
|
VersionMajor = 1
|
||||||
// VersionMinor is for functionality in a backwards-compatible manner
|
// VersionMinor is for functionality in a backwards-compatible manner
|
||||||
VersionMinor = 0
|
VersionMinor = 1
|
||||||
// VersionPatch is for backwards-compatible bug fixes
|
// VersionPatch is for backwards-compatible bug fixes
|
||||||
VersionPatch = 2
|
VersionPatch = 0
|
||||||
|
|
||||||
// VersionDev indicates development branch. Releases will be empty string.
|
// VersionDev indicates development branch. Releases will be empty string.
|
||||||
VersionDev = ""
|
VersionDev = ""
|
||||||
|
|
4
vendor/modules.txt
vendored
4
vendor/modules.txt
vendored
|
@ -295,8 +295,8 @@ github.com/mitchellh/mapstructure
|
||||||
## explicit; go 1.13
|
## explicit; go 1.13
|
||||||
github.com/opencontainers/go-digest
|
github.com/opencontainers/go-digest
|
||||||
github.com/opencontainers/go-digest/digestset
|
github.com/opencontainers/go-digest/digestset
|
||||||
# github.com/opencontainers/image-spec v1.0.2
|
# github.com/opencontainers/image-spec v1.1.0
|
||||||
## explicit
|
## explicit; go 1.18
|
||||||
github.com/opencontainers/image-spec/specs-go
|
github.com/opencontainers/image-spec/specs-go
|
||||||
github.com/opencontainers/image-spec/specs-go/v1
|
github.com/opencontainers/image-spec/specs-go/v1
|
||||||
# github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c
|
# github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c
|
||||||
|
|
Loading…
Reference in a new issue