bake: better handling of compose extension interface

Signed-off-by: CrazyMax <crazy-max@users.noreply.github.com>
pull/1167/head
CrazyMax 3 years ago
parent 055e85f48f
commit 432c2b2650
No known key found for this signature in database
GPG Key ID: 3248E46B6BB8C7F7

@ -9,6 +9,7 @@ import (
"github.com/compose-spec/compose-go/loader" "github.com/compose-spec/compose-go/loader"
compose "github.com/compose-spec/compose-go/types" compose "github.com/compose-spec/compose-go/types"
"github.com/pkg/errors" "github.com/pkg/errors"
"gopkg.in/yaml.v3"
) )
func parseCompose(dt []byte) (*compose.Project, error) { func parseCompose(dt []byte) (*compose.Project, error) {
@ -135,90 +136,86 @@ func flatten(in compose.MappingWithEquals) compose.Mapping {
return out return out
} }
// composeExtTarget converts Compose build extension x-bake to bake Target // xbake Compose build extension provides fields not (yet) available in
// https://github.com/compose-spec/compose-spec/blob/master/spec.md#extension // Compose build specification: https://github.com/compose-spec/compose-spec/blob/master/build.md
func (t *Target) composeExtTarget(exts map[string]interface{}) error { type xbake struct {
if ext, ok := exts["x-bake"]; ok { Tags stringArray `yaml:"tags,omitempty"`
for key, val := range ext.(map[string]interface{}) { CacheFrom stringArray `yaml:"cache-from,omitempty"`
switch key { CacheTo stringArray `yaml:"cache-to,omitempty"`
case "tags": Secrets stringArray `yaml:"secret,omitempty"`
if res, k := val.(string); k { SSH stringArray `yaml:"ssh,omitempty"`
t.Tags = append(t.Tags, res) Platforms stringArray `yaml:"platforms,omitempty"`
} else { Outputs stringArray `yaml:"output,omitempty"`
for _, res := range val.([]interface{}) { Pull *bool `yaml:"pull,omitempty"`
t.Tags = append(t.Tags, res.(string)) NoCache *bool `yaml:"no-cache,omitempty"`
} NoCacheFilter stringArray `yaml:"no-cache-filter,omitempty"`
} // don't forget to update documentation if you add a new field:
case "cache-from": // docs/guides/bake/compose-file.md#extension-field-with-x-bake
t.CacheFrom = []string{} // Needed to override the main field }
if res, k := val.(string); k {
t.CacheFrom = append(t.CacheFrom, res) type stringArray []string
} else {
for _, res := range val.([]interface{}) { func (sa *stringArray) UnmarshalYAML(unmarshal func(interface{}) error) error {
t.CacheFrom = append(t.CacheFrom, res.(string)) var multi []string
} err := unmarshal(&multi)
} if err != nil {
case "cache-to": var single string
if res, k := val.(string); k { if err := unmarshal(&single); err != nil {
t.CacheTo = append(t.CacheTo, res) return err
} else {
for _, res := range val.([]interface{}) {
t.CacheTo = append(t.CacheTo, res.(string))
}
} }
case "secret": *sa = strings.Fields(single)
if res, k := val.(string); k {
t.Secrets = append(t.Secrets, res)
} else { } else {
for _, res := range val.([]interface{}) { *sa = multi
t.Secrets = append(t.Secrets, res.(string))
}
} }
case "ssh": return nil
if res, k := val.(string); k {
t.SSH = append(t.SSH, res)
} else {
for _, res := range val.([]interface{}) {
t.SSH = append(t.SSH, res.(string))
} }
// composeExtTarget converts Compose build extension x-bake to bake Target
// https://github.com/compose-spec/compose-spec/blob/master/spec.md#extension
func (t *Target) composeExtTarget(exts map[string]interface{}) error {
var xb xbake
ext, ok := exts["x-bake"]
if !ok || ext == nil {
return nil
} }
case "platforms":
if res, k := val.(string); k { yb, _ := yaml.Marshal(ext)
t.Platforms = append(t.Platforms, res) if err := yaml.Unmarshal(yb, &xb); err != nil {
} else { return err
for _, res := range val.([]interface{}) {
t.Platforms = append(t.Platforms, res.(string))
} }
if len(xb.Tags) > 0 {
t.Tags = append(t.Tags, xb.Tags...)
} }
case "output": if len(xb.CacheFrom) > 0 {
if res, k := val.(string); k { t.CacheFrom = xb.CacheFrom // override main field
t.Outputs = append(t.Outputs, res)
} else {
for _, res := range val.([]interface{}) {
t.Outputs = append(t.Outputs, res.(string))
} }
if len(xb.CacheTo) > 0 {
t.CacheTo = append(t.CacheTo, xb.CacheTo...)
} }
case "pull": if len(xb.Secrets) > 0 {
if res, ok := val.(bool); ok { t.Secrets = append(t.Secrets, xb.Secrets...)
t.Pull = &res
} }
case "no-cache": if len(xb.SSH) > 0 {
if res, ok := val.(bool); ok { t.SSH = append(t.SSH, xb.SSH...)
t.NoCache = &res
} }
case "no-cache-filter": if len(xb.Platforms) > 0 {
if res, k := val.(string); k { t.Platforms = append(t.Platforms, xb.Platforms...)
t.NoCacheFilter = append(t.NoCacheFilter, res)
} else {
for _, res := range val.([]interface{}) {
t.NoCacheFilter = append(t.NoCacheFilter, res.(string))
} }
if len(xb.Outputs) > 0 {
t.Outputs = append(t.Outputs, xb.Outputs...)
} }
default: if xb.Pull != nil {
return fmt.Errorf("compose file invalid: unkwown %s field for x-bake", key) t.Pull = xb.Pull
} }
if xb.NoCache != nil {
t.NoCache = xb.NoCache
} }
if len(xb.NoCacheFilter) > 0 {
t.NoCacheFilter = append(t.NoCacheFilter, xb.NoCacheFilter...)
} }
return nil return nil
} }

@ -273,7 +273,7 @@ services:
- linux/arm64 - linux/arm64
cache-from: cache-from:
- type=local,src=path/to/cache - type=local,src=path/to/cache
cache-to: local,dest=path/to/cache cache-to: type=local,dest=path/to/cache
pull: true pull: true
aws: aws:
@ -303,7 +303,7 @@ services:
require.Equal(t, c.Targets[0].Tags, []string{"ct-addon:baz", "ct-addon:foo", "ct-addon:alp"}) require.Equal(t, c.Targets[0].Tags, []string{"ct-addon:baz", "ct-addon:foo", "ct-addon:alp"})
require.Equal(t, c.Targets[0].Platforms, []string{"linux/amd64", "linux/arm64"}) require.Equal(t, c.Targets[0].Platforms, []string{"linux/amd64", "linux/arm64"})
require.Equal(t, c.Targets[0].CacheFrom, []string{"type=local,src=path/to/cache"}) require.Equal(t, c.Targets[0].CacheFrom, []string{"type=local,src=path/to/cache"})
require.Equal(t, c.Targets[0].CacheTo, []string{"local,dest=path/to/cache"}) require.Equal(t, c.Targets[0].CacheTo, []string{"type=local,dest=path/to/cache"})
require.Equal(t, c.Targets[0].Pull, newBool(true)) require.Equal(t, c.Targets[0].Pull, newBool(true))
require.Equal(t, c.Targets[1].Tags, []string{"ct-fake-aws:bar"}) require.Equal(t, c.Targets[1].Tags, []string{"ct-fake-aws:bar"})
require.Equal(t, c.Targets[1].Secrets, []string{"id=mysecret,src=/local/secret", "id=mysecret2,src=/local/secret2"}) require.Equal(t, c.Targets[1].Secrets, []string{"id=mysecret,src=/local/secret", "id=mysecret2,src=/local/secret2"})

@ -31,6 +31,7 @@ require (
go.opentelemetry.io/otel/trace v1.4.1 go.opentelemetry.io/otel/trace v1.4.1
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c golang.org/x/sync v0.0.0-20210220032951-036812b2e83c
google.golang.org/grpc v1.45.0 google.golang.org/grpc v1.45.0
gopkg.in/yaml.v3 v3.0.1
k8s.io/api v0.23.4 k8s.io/api v0.23.4
k8s.io/apimachinery v0.23.4 k8s.io/apimachinery v0.23.4
k8s.io/client-go v0.23.4 k8s.io/client-go v0.23.4
@ -139,7 +140,6 @@ require (
gopkg.in/gorethink/gorethink.v3 v3.0.5 // indirect gopkg.in/gorethink/gorethink.v3 v3.0.5 // indirect
gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/inf.v0 v0.9.1 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect
gopkg.in/yaml.v3 v3.0.0 // indirect
k8s.io/klog/v2 v2.30.0 // indirect k8s.io/klog/v2 v2.30.0 // indirect
k8s.io/utils v0.0.0-20210930125809-cb0fa318a74b // indirect k8s.io/utils v0.0.0-20210930125809-cb0fa318a74b // indirect
sigs.k8s.io/structured-merge-diff/v4 v4.1.2 // indirect sigs.k8s.io/structured-merge-diff/v4 v4.1.2 // indirect

@ -1124,8 +1124,9 @@ gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.0 h1:hjy8E9ON/egN1tAYqKb61G10WtihqetD4sz2H+8nIeA=
gopkg.in/yaml.v3 v3.0.0/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gotest.tools/v3 v3.0.2/go.mod h1:3SzNCllyD9/Y+b5r9JIKQ474KzkZyqLqEfYqMsX94Bk= gotest.tools/v3 v3.0.2/go.mod h1:3SzNCllyD9/Y+b5r9JIKQ474KzkZyqLqEfYqMsX94Bk=
gotest.tools/v3 v3.0.3/go.mod h1:Z7Lb0S5l+klDB31fvDQX8ss/FlKDxtlFlw3Oa8Ymbl8= gotest.tools/v3 v3.0.3/go.mod h1:Z7Lb0S5l+klDB31fvDQX8ss/FlKDxtlFlw3Oa8Ymbl8=
gotest.tools/v3 v3.2.0 h1:I0DwBVMGAx26dttAj1BtJLAkVGncrkkUXfJLC4Flt/I= gotest.tools/v3 v3.2.0 h1:I0DwBVMGAx26dttAj1BtJLAkVGncrkkUXfJLC4Flt/I=

@ -687,6 +687,9 @@ func yaml_parser_parse_node(parser *yaml_parser_t, event *yaml_event_t, block, i
func yaml_parser_parse_block_sequence_entry(parser *yaml_parser_t, event *yaml_event_t, first bool) bool { func yaml_parser_parse_block_sequence_entry(parser *yaml_parser_t, event *yaml_event_t, first bool) bool {
if first { if first {
token := peek_token(parser) token := peek_token(parser)
if token == nil {
return false
}
parser.marks = append(parser.marks, token.start_mark) parser.marks = append(parser.marks, token.start_mark)
skip_token(parser) skip_token(parser)
} }
@ -786,7 +789,7 @@ func yaml_parser_split_stem_comment(parser *yaml_parser_t, stem_len int) {
} }
token := peek_token(parser) token := peek_token(parser)
if token.typ != yaml_BLOCK_SEQUENCE_START_TOKEN && token.typ != yaml_BLOCK_MAPPING_START_TOKEN { if token == nil || token.typ != yaml_BLOCK_SEQUENCE_START_TOKEN && token.typ != yaml_BLOCK_MAPPING_START_TOKEN {
return return
} }
@ -813,6 +816,9 @@ func yaml_parser_split_stem_comment(parser *yaml_parser_t, stem_len int) {
func yaml_parser_parse_block_mapping_key(parser *yaml_parser_t, event *yaml_event_t, first bool) bool { func yaml_parser_parse_block_mapping_key(parser *yaml_parser_t, event *yaml_event_t, first bool) bool {
if first { if first {
token := peek_token(parser) token := peek_token(parser)
if token == nil {
return false
}
parser.marks = append(parser.marks, token.start_mark) parser.marks = append(parser.marks, token.start_mark)
skip_token(parser) skip_token(parser)
} }
@ -922,6 +928,9 @@ func yaml_parser_parse_block_mapping_value(parser *yaml_parser_t, event *yaml_ev
func yaml_parser_parse_flow_sequence_entry(parser *yaml_parser_t, event *yaml_event_t, first bool) bool { func yaml_parser_parse_flow_sequence_entry(parser *yaml_parser_t, event *yaml_event_t, first bool) bool {
if first { if first {
token := peek_token(parser) token := peek_token(parser)
if token == nil {
return false
}
parser.marks = append(parser.marks, token.start_mark) parser.marks = append(parser.marks, token.start_mark)
skip_token(parser) skip_token(parser)
} }

@ -761,7 +761,7 @@ gopkg.in/inf.v0
# gopkg.in/yaml.v2 v2.4.0 # gopkg.in/yaml.v2 v2.4.0
## explicit; go 1.15 ## explicit; go 1.15
gopkg.in/yaml.v2 gopkg.in/yaml.v2
# gopkg.in/yaml.v3 v3.0.0 # gopkg.in/yaml.v3 v3.0.1
## explicit ## explicit
gopkg.in/yaml.v3 gopkg.in/yaml.v3
# k8s.io/api v0.23.4 => k8s.io/api v0.22.4 # k8s.io/api v0.23.4 => k8s.io/api v0.22.4

Loading…
Cancel
Save