2015-08-21 04:50:15 +00:00
|
|
|
package schema1
|
|
|
|
|
|
|
|
import (
|
2017-08-11 22:31:16 +00:00
|
|
|
"context"
|
|
|
|
"errors"
|
2015-08-21 04:50:15 +00:00
|
|
|
"fmt"
|
|
|
|
|
2020-08-24 11:18:39 +00:00
|
|
|
"github.com/distribution/distribution/v3"
|
|
|
|
"github.com/distribution/distribution/v3/manifest"
|
|
|
|
"github.com/distribution/distribution/v3/reference"
|
2015-08-21 04:50:15 +00:00
|
|
|
"github.com/docker/libtrust"
|
2016-12-17 00:28:34 +00:00
|
|
|
"github.com/opencontainers/go-digest"
|
2015-08-21 04:50:15 +00:00
|
|
|
)
|
|
|
|
|
2015-12-10 00:38:04 +00:00
|
|
|
// referenceManifestBuilder is a type for constructing manifests from schema1
|
|
|
|
// dependencies.
|
|
|
|
type referenceManifestBuilder struct {
|
2015-08-21 04:50:15 +00:00
|
|
|
Manifest
|
|
|
|
pk libtrust.PrivateKey
|
|
|
|
}
|
|
|
|
|
2015-12-10 00:38:04 +00:00
|
|
|
// NewReferenceManifestBuilder is used to build new manifests for the current
|
|
|
|
// schema version using schema1 dependencies.
|
2015-12-15 22:35:23 +00:00
|
|
|
func NewReferenceManifestBuilder(pk libtrust.PrivateKey, ref reference.Named, architecture string) distribution.ManifestBuilder {
|
|
|
|
tag := ""
|
|
|
|
if tagged, isTagged := ref.(reference.Tagged); isTagged {
|
|
|
|
tag = tagged.Tag()
|
|
|
|
}
|
|
|
|
|
2015-12-10 00:38:04 +00:00
|
|
|
return &referenceManifestBuilder{
|
2015-08-21 04:50:15 +00:00
|
|
|
Manifest: Manifest{
|
|
|
|
Versioned: manifest.Versioned{
|
|
|
|
SchemaVersion: 1,
|
|
|
|
},
|
2015-12-15 22:35:23 +00:00
|
|
|
Name: ref.Name(),
|
2015-08-21 04:50:15 +00:00
|
|
|
Tag: tag,
|
|
|
|
Architecture: architecture,
|
|
|
|
},
|
|
|
|
pk: pk,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-12-10 00:38:04 +00:00
|
|
|
func (mb *referenceManifestBuilder) Build(ctx context.Context) (distribution.Manifest, error) {
|
2015-08-21 04:50:15 +00:00
|
|
|
m := mb.Manifest
|
|
|
|
if len(m.FSLayers) == 0 {
|
|
|
|
return nil, errors.New("cannot build manifest with zero layers or history")
|
|
|
|
}
|
|
|
|
|
|
|
|
m.FSLayers = make([]FSLayer, len(mb.Manifest.FSLayers))
|
|
|
|
m.History = make([]History, len(mb.Manifest.History))
|
|
|
|
copy(m.FSLayers, mb.Manifest.FSLayers)
|
|
|
|
copy(m.History, mb.Manifest.History)
|
|
|
|
|
|
|
|
return Sign(&m, mb.pk)
|
|
|
|
}
|
|
|
|
|
2015-12-10 00:38:04 +00:00
|
|
|
// AppendReference adds a reference to the current ManifestBuilder
|
|
|
|
func (mb *referenceManifestBuilder) AppendReference(d distribution.Describable) error {
|
2015-08-21 04:50:15 +00:00
|
|
|
r, ok := d.(Reference)
|
|
|
|
if !ok {
|
2019-02-05 00:01:04 +00:00
|
|
|
return fmt.Errorf("unable to add non-reference type to v1 builder")
|
2015-08-21 04:50:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Entries need to be prepended
|
|
|
|
mb.Manifest.FSLayers = append([]FSLayer{{BlobSum: r.Digest}}, mb.Manifest.FSLayers...)
|
|
|
|
mb.Manifest.History = append([]History{r.History}, mb.Manifest.History...)
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// References returns the current references added to this builder
|
2015-12-10 00:38:04 +00:00
|
|
|
func (mb *referenceManifestBuilder) References() []distribution.Descriptor {
|
2015-08-21 04:50:15 +00:00
|
|
|
refs := make([]distribution.Descriptor, len(mb.Manifest.FSLayers))
|
|
|
|
for i := range mb.Manifest.FSLayers {
|
|
|
|
layerDigest := mb.Manifest.FSLayers[i].BlobSum
|
|
|
|
history := mb.Manifest.History[i]
|
|
|
|
ref := Reference{layerDigest, 0, history}
|
|
|
|
refs[i] = ref.Descriptor()
|
|
|
|
}
|
|
|
|
return refs
|
|
|
|
}
|
|
|
|
|
|
|
|
// Reference describes a manifest v2, schema version 1 dependency.
|
|
|
|
// An FSLayer associated with a history entry.
|
|
|
|
type Reference struct {
|
|
|
|
Digest digest.Digest
|
|
|
|
Size int64 // if we know it, set it for the descriptor.
|
|
|
|
History History
|
|
|
|
}
|
|
|
|
|
|
|
|
// Descriptor describes a reference
|
|
|
|
func (r Reference) Descriptor() distribution.Descriptor {
|
|
|
|
return distribution.Descriptor{
|
|
|
|
MediaType: MediaTypeManifestLayer,
|
|
|
|
Digest: r.Digest,
|
|
|
|
Size: r.Size,
|
|
|
|
}
|
|
|
|
}
|