diff.go 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145
  1. /*
  2. Copyright The containerd Authors.
  3. Licensed under the Apache License, Version 2.0 (the "License");
  4. you may not use this file except in compliance with the License.
  5. You may obtain a copy of the License at
  6. http://www.apache.org/licenses/LICENSE-2.0
  7. Unless required by applicable law or agreed to in writing, software
  8. distributed under the License is distributed on an "AS IS" BASIS,
  9. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  10. See the License for the specific language governing permissions and
  11. limitations under the License.
  12. */
  13. package diff
  14. import (
  15. "context"
  16. "io"
  17. "time"
  18. "github.com/containerd/containerd/mount"
  19. "github.com/containerd/typeurl/v2"
  20. ocispec "github.com/opencontainers/image-spec/specs-go/v1"
  21. )
  22. // Config is used to hold parameters needed for a diff operation
  23. type Config struct {
  24. // MediaType is the type of diff to generate
  25. // Default depends on the differ,
  26. // i.e. application/vnd.oci.image.layer.v1.tar+gzip
  27. MediaType string
  28. // Reference is the content upload reference
  29. // Default will use a random reference string
  30. Reference string
  31. // Labels are the labels to apply to the generated content
  32. Labels map[string]string
  33. // Compressor is a function to compress the diff stream
  34. // instead of the default gzip compressor. Differ passes
  35. // the MediaType of the target diff content to the compressor.
  36. // When using this config, MediaType must be specified as well.
  37. Compressor func(dest io.Writer, mediaType string) (io.WriteCloser, error)
  38. // SourceDateEpoch specifies the SOURCE_DATE_EPOCH without touching the env vars.
  39. SourceDateEpoch *time.Time
  40. }
  41. // Opt is used to configure a diff operation
  42. type Opt func(*Config) error
  43. // Comparer allows creation of filesystem diffs between mounts
  44. type Comparer interface {
  45. // Compare computes the difference between two mounts and returns a
  46. // descriptor for the computed diff. The options can provide
  47. // a ref which can be used to track the content creation of the diff.
  48. // The media type which is used to determine the format of the created
  49. // content can also be provided as an option.
  50. Compare(ctx context.Context, lower, upper []mount.Mount, opts ...Opt) (ocispec.Descriptor, error)
  51. }
  52. // ApplyConfig is used to hold parameters needed for a apply operation
  53. type ApplyConfig struct {
  54. // ProcessorPayloads specifies the payload sent to various processors
  55. ProcessorPayloads map[string]typeurl.Any
  56. // SyncFs is to synchronize the underlying filesystem containing files
  57. SyncFs bool
  58. }
  59. // ApplyOpt is used to configure an Apply operation
  60. type ApplyOpt func(context.Context, ocispec.Descriptor, *ApplyConfig) error
  61. // Applier allows applying diffs between mounts
  62. type Applier interface {
  63. // Apply applies the content referred to by the given descriptor to
  64. // the provided mount. The method of applying is based on the
  65. // implementation and content descriptor. For example, in the common
  66. // case the descriptor is a file system difference in tar format,
  67. // that tar would be applied on top of the mounts.
  68. Apply(ctx context.Context, desc ocispec.Descriptor, mount []mount.Mount, opts ...ApplyOpt) (ocispec.Descriptor, error)
  69. }
  70. // WithCompressor sets the function to be used to compress the diff stream.
  71. func WithCompressor(f func(dest io.Writer, mediaType string) (io.WriteCloser, error)) Opt {
  72. return func(c *Config) error {
  73. c.Compressor = f
  74. return nil
  75. }
  76. }
  77. // WithMediaType sets the media type to use for creating the diff, without
  78. // specifying the differ will choose a default.
  79. func WithMediaType(m string) Opt {
  80. return func(c *Config) error {
  81. c.MediaType = m
  82. return nil
  83. }
  84. }
  85. // WithReference is used to set the content upload reference used by
  86. // the diff operation. This allows the caller to track the upload through
  87. // the content store.
  88. func WithReference(ref string) Opt {
  89. return func(c *Config) error {
  90. c.Reference = ref
  91. return nil
  92. }
  93. }
  94. // WithLabels is used to set content labels on the created diff content.
  95. func WithLabels(labels map[string]string) Opt {
  96. return func(c *Config) error {
  97. c.Labels = labels
  98. return nil
  99. }
  100. }
  101. // WithPayloads sets the apply processor payloads to the config
  102. func WithPayloads(payloads map[string]typeurl.Any) ApplyOpt {
  103. return func(_ context.Context, _ ocispec.Descriptor, c *ApplyConfig) error {
  104. c.ProcessorPayloads = payloads
  105. return nil
  106. }
  107. }
  108. // WithSourceDateEpoch specifies the timestamp used for whiteouts to provide control for reproducibility.
  109. // See also https://reproducible-builds.org/docs/source-date-epoch/ .
  110. func WithSourceDateEpoch(tm *time.Time) Opt {
  111. return func(c *Config) error {
  112. c.SourceDateEpoch = tm
  113. return nil
  114. }
  115. }
  116. // WithSyncFs sets sync flag to the config.
  117. func WithSyncFs(sync bool) ApplyOpt {
  118. return func(_ context.Context, _ ocispec.Descriptor, c *ApplyConfig) error {
  119. c.SyncFs = sync
  120. return nil
  121. }
  122. }