reference_builder.go 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899
  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/digest"
  8. "github.com/docker/distribution/manifest"
  9. "github.com/docker/distribution/reference"
  10. "github.com/docker/libtrust"
  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. }