builder.go 2.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778
  1. package schema2
  2. import (
  3. "github.com/docker/distribution"
  4. "github.com/docker/distribution/context"
  5. "github.com/docker/distribution/digest"
  6. )
  7. // builder is a type for constructing manifests.
  8. type builder struct {
  9. // bs is a BlobService used to publish the configuration blob.
  10. bs distribution.BlobService
  11. // configJSON references
  12. configJSON []byte
  13. // layers is a list of layer descriptors that gets built by successive
  14. // calls to AppendReference.
  15. layers []distribution.Descriptor
  16. }
  17. // NewManifestBuilder is used to build new manifests for the current schema
  18. // version. It takes a BlobService so it can publish the configuration blob
  19. // as part of the Build process.
  20. func NewManifestBuilder(bs distribution.BlobService, configJSON []byte) distribution.ManifestBuilder {
  21. mb := &builder{
  22. bs: bs,
  23. configJSON: make([]byte, len(configJSON)),
  24. }
  25. copy(mb.configJSON, configJSON)
  26. return mb
  27. }
  28. // Build produces a final manifest from the given references.
  29. func (mb *builder) Build(ctx context.Context) (distribution.Manifest, error) {
  30. m := Manifest{
  31. Versioned: SchemaVersion,
  32. Layers: make([]distribution.Descriptor, len(mb.layers)),
  33. }
  34. copy(m.Layers, mb.layers)
  35. configDigest := digest.FromBytes(mb.configJSON)
  36. var err error
  37. m.Config, err = mb.bs.Stat(ctx, configDigest)
  38. switch err {
  39. case nil:
  40. return FromStruct(m)
  41. case distribution.ErrBlobUnknown:
  42. // nop
  43. default:
  44. return nil, err
  45. }
  46. // Add config to the blob store
  47. m.Config, err = mb.bs.Put(ctx, MediaTypeConfig, mb.configJSON)
  48. // Override MediaType, since Put always replaces the specified media
  49. // type with application/octet-stream in the descriptor it returns.
  50. m.Config.MediaType = MediaTypeConfig
  51. if err != nil {
  52. return nil, err
  53. }
  54. return FromStruct(m)
  55. }
  56. // AppendReference adds a reference to the current ManifestBuilder.
  57. func (mb *builder) AppendReference(d distribution.Describable) error {
  58. mb.layers = append(mb.layers, d.Descriptor())
  59. return nil
  60. }
  61. // References returns the current references added to this builder.
  62. func (mb *builder) References() []distribution.Descriptor {
  63. return mb.layers
  64. }