From 4fc2d7b5e7ffa51235a30f55432d1f0eb619f77c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Gronowski?= Date: Wed, 8 Mar 2023 16:07:15 +0100 Subject: [PATCH 1/3] containerimage: Export option keys MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Paweł Gronowski --- control/control.go | 5 +- exporter/containerimage/export.go | 22 +++----- exporter/containerimage/exptypes/keys.go | 71 ++++++++++++++++++++++++ exporter/containerimage/opts.go | 20 ++----- exporter/util/epoch/parse.go | 4 +- 5 files changed, 87 insertions(+), 35 deletions(-) create mode 100644 exporter/containerimage/exptypes/keys.go diff --git a/control/control.go b/control/control.go index 040b4fd42..df03f4ca7 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[exptypes.OptKeySourceDateEpoch]; !ok { if req.ExporterAttrs == nil { req.ExporterAttrs = make(map[string]string) } - req.ExporterAttrs[epoch.KeySourceDateEpoch] = v + req.ExporterAttrs[exptypes.OptKeySourceDateEpoch] = v } } diff --git a/exporter/containerimage/export.go b/exporter/containerimage/export.go index 026550f3f..d73434995 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. @@ -88,7 +80,7 @@ func (e *imageExporter) Resolve(ctx context.Context, opt map[string]string) (exp for k, v := range opt { switch k { - case keyPush: + 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..b08c9fa75 --- /dev/null +++ b/exporter/containerimage/exptypes/keys.go @@ -0,0 +1,71 @@ +package exptypes + +// Options keys supported by the image exporter output. +var ( + // Name of the image. + // Value: string + OptKeyName = "name" + + // Push after creating image. + // Value: bool + OptKeyPush = "push" + + // Push unnamed image. + // Value: bool + OptKeyPushByDigest = "push-by-digest" + + // Allow pushing to insecure HTTP registry. + // Value: bool + OptKeyInsecure = "registry.insecure" + + // Unpack image after it's created (containerd). + // Value: bool + OptKeyUnpack = "unpack" + + // Fallback image name prefix if image name isn't provided. + // If used, image will be named as @ + // Value: string + OptKeyDanglingPrefix = "dangling-name-prefix" + + // Creates additional image name with format @ + // Value: bool + OptKeyNameCanonical = "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 = "store" + + // Use OCI mediatypes instead of Docker in JSON configs. + // Value: bool + OptKeyOCITypes = "oci-mediatypes" + + // Force attestation to be attached. + // Value: bool + OptKeyForceInlineAttestations = "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 = "prefer-nondist-layers" + + // Clamp produced timestamps. For more information see the + // SOURCE_DATE_EPOCH specification. + // Value: int (number of seconds since Unix epoch) + OptKeySourceDateEpoch = "source-date-epoch" + + // Compression type for newly created and cached layers. + // estargz should be used with OptKeyOCITypes set to true. + // Value: string + OptKeyLayerCompression = "compression" + + // Force compression on all (including existing) layers. + // Value: bool + OptKeyForceCompression = "force-compression" + + // Compression level + // Value: int (0-9) for gzip and estargz + // Value: int (0-22) for zstd + OptKeyCompressionLevel = "compression-level" +) diff --git a/exporter/containerimage/opts.go b/exporter/containerimage/opts.go index edc1959e0..25060f460 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 @@ -54,13 +44,13 @@ func (c *ImageCommitOpts) Load(ctx context.Context, opt map[string]string) (map[ for k, v := range opt { var err error switch k { - case keyImageName: + 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/util/epoch/parse.go b/exporter/util/epoch/parse.go index 63f806e1b..2aea70a3f 100644 --- a/exporter/util/epoch/parse.go +++ b/exporter/util/epoch/parse.go @@ -11,8 +11,6 @@ import ( 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 exptypes.OptKeySourceDateEpoch: var err error tm, err = parseTime(k, v) if err != nil { From cecab8d64bdeb8106b322e8009142195a7ecafe1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Gronowski?= Date: Wed, 24 May 2023 14:03:17 +0200 Subject: [PATCH 2/3] exporter/image/exptypes: Make strongly typed MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Paweł Gronowski --- control/control.go | 4 +-- exporter/containerimage/export.go | 2 +- exporter/containerimage/exptypes/keys.go | 32 +++++++++++++----------- exporter/containerimage/opts.go | 2 +- exporter/util/epoch/parse.go | 2 +- 5 files changed, 22 insertions(+), 20 deletions(-) diff --git a/control/control.go b/control/control.go index df03f4ca7..899fb2da0 100644 --- a/control/control.go +++ b/control/control.go @@ -332,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[exptypes.OptKeySourceDateEpoch]; !ok { + if _, ok := req.ExporterAttrs[string(exptypes.OptKeySourceDateEpoch)]; !ok { if req.ExporterAttrs == nil { req.ExporterAttrs = make(map[string]string) } - req.ExporterAttrs[exptypes.OptKeySourceDateEpoch] = v + req.ExporterAttrs[string(exptypes.OptKeySourceDateEpoch)] = v } } diff --git a/exporter/containerimage/export.go b/exporter/containerimage/export.go index d73434995..18c678a67 100644 --- a/exporter/containerimage/export.go +++ b/exporter/containerimage/export.go @@ -79,7 +79,7 @@ func (e *imageExporter) Resolve(ctx context.Context, opt map[string]string) (exp } for k, v := range opt { - switch k { + switch exptypes.ImageExporterOptKey(k) { case exptypes.OptKeyPush: if v == "" { i.push = true diff --git a/exporter/containerimage/exptypes/keys.go b/exporter/containerimage/exptypes/keys.go index b08c9fa75..1b46d0707 100644 --- a/exporter/containerimage/exptypes/keys.go +++ b/exporter/containerimage/exptypes/keys.go @@ -1,71 +1,73 @@ package exptypes +type ImageExporterOptKey string + // Options keys supported by the image exporter output. var ( // Name of the image. // Value: string - OptKeyName = "name" + OptKeyName ImageExporterOptKey = "name" // Push after creating image. // Value: bool - OptKeyPush = "push" + OptKeyPush ImageExporterOptKey = "push" // Push unnamed image. // Value: bool - OptKeyPushByDigest = "push-by-digest" + OptKeyPushByDigest ImageExporterOptKey = "push-by-digest" // Allow pushing to insecure HTTP registry. // Value: bool - OptKeyInsecure = "registry.insecure" + OptKeyInsecure ImageExporterOptKey = "registry.insecure" // Unpack image after it's created (containerd). // Value: bool - OptKeyUnpack = "unpack" + OptKeyUnpack ImageExporterOptKey = "unpack" // Fallback image name prefix if image name isn't provided. // If used, image will be named as @ // Value: string - OptKeyDanglingPrefix = "dangling-name-prefix" + OptKeyDanglingPrefix ImageExporterOptKey = "dangling-name-prefix" // Creates additional image name with format @ // Value: bool - OptKeyNameCanonical = "name-canonical" + 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 = "store" + OptKeyStore ImageExporterOptKey = "store" // Use OCI mediatypes instead of Docker in JSON configs. // Value: bool - OptKeyOCITypes = "oci-mediatypes" + OptKeyOCITypes ImageExporterOptKey = "oci-mediatypes" // Force attestation to be attached. // Value: bool - OptKeyForceInlineAttestations = "attestation-inline" + 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 = "prefer-nondist-layers" + 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 = "source-date-epoch" + OptKeySourceDateEpoch ImageExporterOptKey = "source-date-epoch" // Compression type for newly created and cached layers. // estargz should be used with OptKeyOCITypes set to true. // Value: string - OptKeyLayerCompression = "compression" + OptKeyLayerCompression ImageExporterOptKey = "compression" // Force compression on all (including existing) layers. // Value: bool - OptKeyForceCompression = "force-compression" + OptKeyForceCompression ImageExporterOptKey = "force-compression" // Compression level // Value: int (0-9) for gzip and estargz // Value: int (0-22) for zstd - OptKeyCompressionLevel = "compression-level" + OptKeyCompressionLevel ImageExporterOptKey = "compression-level" ) diff --git a/exporter/containerimage/opts.go b/exporter/containerimage/opts.go index 25060f460..791f268af 100644 --- a/exporter/containerimage/opts.go +++ b/exporter/containerimage/opts.go @@ -43,7 +43,7 @@ func (c *ImageCommitOpts) Load(ctx context.Context, opt map[string]string) (map[ for k, v := range opt { var err error - switch k { + switch exptypes.ImageExporterOptKey(k) { case exptypes.OptKeyName: c.ImageName = v case exptypes.OptKeyOCITypes: diff --git a/exporter/util/epoch/parse.go b/exporter/util/epoch/parse.go index 2aea70a3f..ed080ed88 100644 --- a/exporter/util/epoch/parse.go +++ b/exporter/util/epoch/parse.go @@ -25,7 +25,7 @@ func ParseExporterAttrs(opt map[string]string) (*time.Time, map[string]string, e for k, v := range opt { switch k { - case exptypes.OptKeySourceDateEpoch: + case string(exptypes.OptKeySourceDateEpoch): var err error tm, err = parseTime(k, v) if err != nil { From d82a80313e5c8b7113ab5acc28577d13dfa46f7f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Gronowski?= Date: Thu, 1 Jun 2023 11:13:55 +0200 Subject: [PATCH 3/3] exporter: Add exptypes with Common exporter keys MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Paweł Gronowski --- exporter/containerimage/exptypes/keys.go | 4 +++- exporter/containerimage/exptypes/types.go | 1 - exporter/exptypes/keys.go | 15 +++++++++++++++ exporter/util/epoch/parse.go | 6 +++--- 4 files changed, 21 insertions(+), 5 deletions(-) create mode 100644 exporter/exptypes/keys.go diff --git a/exporter/containerimage/exptypes/keys.go b/exporter/containerimage/exptypes/keys.go index 1b46d0707..c43221849 100644 --- a/exporter/containerimage/exptypes/keys.go +++ b/exporter/containerimage/exptypes/keys.go @@ -1,5 +1,7 @@ package exptypes +import commonexptypes "github.com/moby/buildkit/exporter/exptypes" + type ImageExporterOptKey string // Options keys supported by the image exporter output. @@ -55,7 +57,7 @@ var ( // Clamp produced timestamps. For more information see the // SOURCE_DATE_EPOCH specification. // Value: int (number of seconds since Unix epoch) - OptKeySourceDateEpoch ImageExporterOptKey = "source-date-epoch" + OptKeySourceDateEpoch ImageExporterOptKey = ImageExporterOptKey(commonexptypes.OptKeySourceDateEpoch) // Compression type for newly created and cached layers. // estargz should be used with OptKeyOCITypes set to true. 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/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 ed080ed88..d5a014608 100644 --- a/exporter/util/epoch/parse.go +++ b/exporter/util/epoch/parse.go @@ -5,7 +5,7 @@ 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" ) @@ -25,7 +25,7 @@ func ParseExporterAttrs(opt map[string]string) (*time.Time, map[string]string, e for k, v := range opt { switch k { - case string(exptypes.OptKeySourceDateEpoch): + case string(commonexptypes.OptKeySourceDateEpoch): var err error tm, err = parseTime(k, v) if err != nil { @@ -40,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)