reference_builder.go 2.8 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798
  1. package schema1
  2. import (
  3. "fmt"
  4. "errors"
  5. "github.com/docker/distribution"
  6. "github.com/docker/distribution/context"
  7. "github.com/docker/distribution/manifest"
  8. "github.com/docker/distribution/reference"
  9. "github.com/docker/libtrust"
  10. "github.com/opencontainers/go-digest"
  11. )
  12. // referenceManifestBuilder is a type for constructing manifests from schema1
  13. // dependencies.
  14. type referenceManifestBuilder struct {
  15. Manifest
  16. pk libtrust.PrivateKey
  17. }
  18. // NewReferenceManifestBuilder is used to build new manifests for the current
  19. // schema version using schema1 dependencies.
  20. func NewReferenceManifestBuilder(pk libtrust.PrivateKey, ref reference.Named, architecture string) distribution.ManifestBuilder {
  21. tag := ""
  22. if tagged, isTagged := ref.(reference.Tagged); isTagged {
  23. tag = tagged.Tag()
  24. }
  25. return &referenceManifestBuilder{
  26. Manifest: Manifest{
  27. Versioned: manifest.Versioned{
  28. SchemaVersion: 1,
  29. },
  30. Name: ref.Name(),
  31. Tag: tag,
  32. Architecture: architecture,
  33. },
  34. pk: pk,
  35. }
  36. }
  37. func (mb *referenceManifestBuilder) Build(ctx context.Context) (distribution.Manifest, error) {
  38. m := mb.Manifest
  39. if len(m.FSLayers) == 0 {
  40. return nil, errors.New("cannot build manifest with zero layers or history")
  41. }
  42. m.FSLayers = make([]FSLayer, len(mb.Manifest.FSLayers))
  43. m.History = make([]History, len(mb.Manifest.History))
  44. copy(m.FSLayers, mb.Manifest.FSLayers)
  45. copy(m.History, mb.Manifest.History)
  46. return Sign(&m, mb.pk)
  47. }
  48. // AppendReference adds a reference to the current ManifestBuilder
  49. func (mb *referenceManifestBuilder) AppendReference(d distribution.Describable) error {
  50. r, ok := d.(Reference)
  51. if !ok {
  52. return fmt.Errorf("Unable to add non-reference type to v1 builder")
  53. }
  54. // Entries need to be prepended
  55. mb.Manifest.FSLayers = append([]FSLayer{{BlobSum: r.Digest}}, mb.Manifest.FSLayers...)
  56. mb.Manifest.History = append([]History{r.History}, mb.Manifest.History...)
  57. return nil
  58. }
  59. // References returns the current references added to this builder
  60. func (mb *referenceManifestBuilder) References() []distribution.Descriptor {
  61. refs := make([]distribution.Descriptor, len(mb.Manifest.FSLayers))
  62. for i := range mb.Manifest.FSLayers {
  63. layerDigest := mb.Manifest.FSLayers[i].BlobSum
  64. history := mb.Manifest.History[i]
  65. ref := Reference{layerDigest, 0, history}
  66. refs[i] = ref.Descriptor()
  67. }
  68. return refs
  69. }
  70. // Reference describes a manifest v2, schema version 1 dependency.
  71. // An FSLayer associated with a history entry.
  72. type Reference struct {
  73. Digest digest.Digest
  74. Size int64 // if we know it, set it for the descriptor.
  75. History History
  76. }
  77. // Descriptor describes a reference
  78. func (r Reference) Descriptor() distribution.Descriptor {
  79. return distribution.Descriptor{
  80. MediaType: MediaTypeManifestLayer,
  81. Digest: r.Digest,
  82. Size: r.Size,
  83. }
  84. }