diff --git a/control/control.go b/control/control.go index 040b4fd42..899fb2da0 100644 --- a/control/control.go +++ b/control/control.go @@ -20,6 +20,7 @@ import ( "github.com/moby/buildkit/cmd/buildkitd/config" controlgateway "github.com/moby/buildkit/control/gateway" "github.com/moby/buildkit/exporter" + "github.com/moby/buildkit/exporter/containerimage/exptypes" "github.com/moby/buildkit/exporter/util/epoch" "github.com/moby/buildkit/frontend" "github.com/moby/buildkit/frontend/attestations" @@ -331,11 +332,11 @@ func (c *Controller) Solve(ctx context.Context, req *controlapi.SolveRequest) (* // if SOURCE_DATE_EPOCH is set, enable it for the exporter if v, ok := epoch.ParseBuildArgs(req.FrontendAttrs); ok { - if _, ok := req.ExporterAttrs[epoch.KeySourceDateEpoch]; !ok { + if _, ok := req.ExporterAttrs[string(exptypes.OptKeySourceDateEpoch)]; !ok { if req.ExporterAttrs == nil { req.ExporterAttrs = make(map[string]string) } - req.ExporterAttrs[epoch.KeySourceDateEpoch] = v + req.ExporterAttrs[string(exptypes.OptKeySourceDateEpoch)] = v } } diff --git a/exporter/containerimage/export.go b/exporter/containerimage/export.go index 026550f3f..18c678a67 100644 --- a/exporter/containerimage/export.go +++ b/exporter/containerimage/export.go @@ -34,14 +34,6 @@ import ( ) const ( - keyPush = "push" - keyPushByDigest = "push-by-digest" - keyInsecure = "registry.insecure" - keyUnpack = "unpack" - keyDanglingPrefix = "dangling-name-prefix" - keyNameCanonical = "name-canonical" - keyStore = "store" - // keyUnsafeInternalStoreAllowIncomplete should only be used for tests. This option allows exporting image to the image store // as well as lacking some blobs in the content store. Some integration tests for lazyref behaviour depends on this option. // Ignored when store=false. @@ -87,8 +79,8 @@ func (e *imageExporter) Resolve(ctx context.Context, opt map[string]string) (exp } for k, v := range opt { - switch k { - case keyPush: + switch exptypes.ImageExporterOptKey(k) { + case exptypes.OptKeyPush: if v == "" { i.push = true continue @@ -98,7 +90,7 @@ func (e *imageExporter) Resolve(ctx context.Context, opt map[string]string) (exp return nil, errors.Wrapf(err, "non-bool value specified for %s", k) } i.push = b - case keyPushByDigest: + case exptypes.OptKeyPushByDigest: if v == "" { i.pushByDigest = true continue @@ -108,7 +100,7 @@ func (e *imageExporter) Resolve(ctx context.Context, opt map[string]string) (exp return nil, errors.Wrapf(err, "non-bool value specified for %s", k) } i.pushByDigest = b - case keyInsecure: + case exptypes.OptKeyInsecure: if v == "" { i.insecure = true continue @@ -118,7 +110,7 @@ func (e *imageExporter) Resolve(ctx context.Context, opt map[string]string) (exp return nil, errors.Wrapf(err, "non-bool value specified for %s", k) } i.insecure = b - case keyUnpack: + case exptypes.OptKeyUnpack: if v == "" { i.unpack = true continue @@ -128,7 +120,7 @@ func (e *imageExporter) Resolve(ctx context.Context, opt map[string]string) (exp return nil, errors.Wrapf(err, "non-bool value specified for %s", k) } i.unpack = b - case keyStore: + case exptypes.OptKeyStore: if v == "" { i.store = true continue @@ -148,9 +140,9 @@ func (e *imageExporter) Resolve(ctx context.Context, opt map[string]string) (exp return nil, errors.Wrapf(err, "non-bool value specified for %s", k) } i.storeAllowIncomplete = b - case keyDanglingPrefix: + case exptypes.OptKeyDanglingPrefix: i.danglingPrefix = v - case keyNameCanonical: + case exptypes.OptKeyNameCanonical: if v == "" { i.nameCanonical = true continue diff --git a/exporter/containerimage/exptypes/keys.go b/exporter/containerimage/exptypes/keys.go new file mode 100644 index 000000000..c43221849 --- /dev/null +++ b/exporter/containerimage/exptypes/keys.go @@ -0,0 +1,75 @@ +package exptypes + +import commonexptypes "github.com/moby/buildkit/exporter/exptypes" + +type ImageExporterOptKey string + +// Options keys supported by the image exporter output. +var ( + // Name of the image. + // Value: string + OptKeyName ImageExporterOptKey = "name" + + // Push after creating image. + // Value: bool + OptKeyPush ImageExporterOptKey = "push" + + // Push unnamed image. + // Value: bool + OptKeyPushByDigest ImageExporterOptKey = "push-by-digest" + + // Allow pushing to insecure HTTP registry. + // Value: bool + OptKeyInsecure ImageExporterOptKey = "registry.insecure" + + // Unpack image after it's created (containerd). + // Value: bool + OptKeyUnpack ImageExporterOptKey = "unpack" + + // Fallback image name prefix if image name isn't provided. + // If used, image will be named as @ + // Value: string + OptKeyDanglingPrefix ImageExporterOptKey = "dangling-name-prefix" + + // Creates additional image name with format @ + // Value: bool + OptKeyNameCanonical ImageExporterOptKey = "name-canonical" + + // Store the resulting image along with all of the content it references. + // Ignored if the worker doesn't have image store (e.g. OCI worker). + // Value: bool + OptKeyStore ImageExporterOptKey = "store" + + // Use OCI mediatypes instead of Docker in JSON configs. + // Value: bool + OptKeyOCITypes ImageExporterOptKey = "oci-mediatypes" + + // Force attestation to be attached. + // Value: bool + OptKeyForceInlineAttestations ImageExporterOptKey = "attestation-inline" + + // Mark layers as non-distributable if they are found to use a + // non-distributable media type. When this option is not set, the exporter + // will change the media type of the layer to a distributable one. + // Value: bool + OptKeyPreferNondistLayers ImageExporterOptKey = "prefer-nondist-layers" + + // Clamp produced timestamps. For more information see the + // SOURCE_DATE_EPOCH specification. + // Value: int (number of seconds since Unix epoch) + OptKeySourceDateEpoch ImageExporterOptKey = ImageExporterOptKey(commonexptypes.OptKeySourceDateEpoch) + + // Compression type for newly created and cached layers. + // estargz should be used with OptKeyOCITypes set to true. + // Value: string + OptKeyLayerCompression ImageExporterOptKey = "compression" + + // Force compression on all (including existing) layers. + // Value: bool + OptKeyForceCompression ImageExporterOptKey = "force-compression" + + // Compression level + // Value: int (0-9) for gzip and estargz + // Value: int (0-22) for zstd + OptKeyCompressionLevel ImageExporterOptKey = "compression-level" +) diff --git a/exporter/containerimage/exptypes/types.go b/exporter/containerimage/exptypes/types.go index 07a6d4730..c4d5721ea 100644 --- a/exporter/containerimage/exptypes/types.go +++ b/exporter/containerimage/exptypes/types.go @@ -12,7 +12,6 @@ const ( ExporterImageDescriptorKey = "containerimage.descriptor" ExporterInlineCache = "containerimage.inlinecache" ExporterPlatformsKey = "refs.platforms" - ExporterEpochKey = "source.date.epoch" ) // KnownRefMetadataKeys are the subset of exporter keys that can be suffixed by diff --git a/exporter/containerimage/opts.go b/exporter/containerimage/opts.go index edc1959e0..791f268af 100644 --- a/exporter/containerimage/opts.go +++ b/exporter/containerimage/opts.go @@ -6,23 +6,13 @@ import ( "time" cacheconfig "github.com/moby/buildkit/cache/config" + "github.com/moby/buildkit/exporter/containerimage/exptypes" "github.com/moby/buildkit/exporter/util/epoch" "github.com/moby/buildkit/util/bklog" "github.com/moby/buildkit/util/compression" "github.com/pkg/errors" ) -const ( - keyImageName = "name" - keyOCITypes = "oci-mediatypes" - keyForceInlineAttestations = "attestation-inline" - - // preferNondistLayersKey is an exporter option which can be used to mark a layer as non-distributable if the layer reference was - // already found to use a non-distributable media type. - // When this option is not set, the exporter will change the media type of the layer to a distributable one. - keyPreferNondistLayers = "prefer-nondist-layers" -) - type ImageCommitOpts struct { ImageName string RefCfg cacheconfig.RefConfig @@ -53,14 +43,14 @@ func (c *ImageCommitOpts) Load(ctx context.Context, opt map[string]string) (map[ for k, v := range opt { var err error - switch k { - case keyImageName: + switch exptypes.ImageExporterOptKey(k) { + case exptypes.OptKeyName: c.ImageName = v - case keyOCITypes: + case exptypes.OptKeyOCITypes: err = parseBoolWithDefault(&c.OCITypes, k, v, true) - case keyForceInlineAttestations: + case exptypes.OptKeyForceInlineAttestations: err = parseBool(&c.ForceInlineAttestations, k, v) - case keyPreferNondistLayers: + case exptypes.OptKeyPreferNondistLayers: err = parseBool(&c.RefCfg.PreferNonDistributable, k, v) default: rest[k] = v diff --git a/exporter/exptypes/keys.go b/exporter/exptypes/keys.go new file mode 100644 index 000000000..4b568154f --- /dev/null +++ b/exporter/exptypes/keys.go @@ -0,0 +1,15 @@ +package exptypes + +const ( + ExporterEpochKey = "source.date.epoch" +) + +type ExporterOptKey string + +// Options keys supported by all exporters. +var ( + // Clamp produced timestamps. For more information see the + // SOURCE_DATE_EPOCH specification. + // Value: int (number of seconds since Unix epoch) + OptKeySourceDateEpoch ExporterOptKey = "source-date-epoch" +) diff --git a/exporter/util/epoch/parse.go b/exporter/util/epoch/parse.go index 63f806e1b..d5a014608 100644 --- a/exporter/util/epoch/parse.go +++ b/exporter/util/epoch/parse.go @@ -5,14 +5,12 @@ import ( "time" "github.com/moby/buildkit/exporter" - "github.com/moby/buildkit/exporter/containerimage/exptypes" + commonexptypes "github.com/moby/buildkit/exporter/exptypes" "github.com/pkg/errors" ) const ( frontendSourceDateEpochArg = "build-arg:SOURCE_DATE_EPOCH" - - KeySourceDateEpoch = "source-date-epoch" ) func ParseBuildArgs(opt map[string]string) (string, bool) { @@ -27,7 +25,7 @@ func ParseExporterAttrs(opt map[string]string) (*time.Time, map[string]string, e for k, v := range opt { switch k { - case KeySourceDateEpoch: + case string(commonexptypes.OptKeySourceDateEpoch): var err error tm, err = parseTime(k, v) if err != nil { @@ -42,7 +40,7 @@ func ParseExporterAttrs(opt map[string]string) (*time.Time, map[string]string, e } func ParseSource(inp *exporter.Source) (*time.Time, bool, error) { - if v, ok := inp.Metadata[exptypes.ExporterEpochKey]; ok { + if v, ok := inp.Metadata[commonexptypes.ExporterEpochKey]; ok { epoch, err := parseTime("", string(v)) if err != nil { return nil, false, errors.Wrapf(err, "invalid SOURCE_DATE_EPOCH from frontend: %q", v)