builder.go 2.5 KB

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