Skip to content

Commit

Permalink
Merge pull request #2944 from jsternberg/cache-ref-only-format-fix
Browse files Browse the repository at this point in the history
buildflags: fix ref only format for command line and bake
  • Loading branch information
tonistiigi authored Jan 22, 2025
2 parents cc4a291 + 11c8497 commit 17af006
Show file tree
Hide file tree
Showing 7 changed files with 72 additions and 53 deletions.
39 changes: 2 additions & 37 deletions bake/bake.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@ import (
"github.com/moby/buildkit/session/auth/authprovider"
"github.com/moby/buildkit/util/entitlements"
"github.com/pkg/errors"
"github.com/tonistiigi/go-csvvalue"
"github.com/zclconf/go-cty/cty"
"github.com/zclconf/go-cty/cty/convert"
)
Expand Down Expand Up @@ -900,7 +899,7 @@ func (t *Target) AddOverrides(overrides map[string]Override, ent *EntitlementCon
case "tags":
t.Tags = o.ArrValue
case "cache-from":
cacheFrom, err := parseCacheArrValues(o.ArrValue)
cacheFrom, err := buildflags.ParseCacheEntry(o.ArrValue)
if err != nil {
return err
}
Expand All @@ -913,7 +912,7 @@ func (t *Target) AddOverrides(overrides map[string]Override, ent *EntitlementCon
}
}
case "cache-to":
cacheTo, err := parseCacheArrValues(o.ArrValue)
cacheTo, err := buildflags.ParseCacheEntry(o.ArrValue)
if err != nil {
return err
}
Expand Down Expand Up @@ -1585,37 +1584,3 @@ func parseArrValue[T any, PT arrValue[T]](s []string) ([]*T, error) {
}
return outputs, nil
}

func parseCacheArrValues(s []string) (buildflags.CacheOptions, error) {
var outs buildflags.CacheOptions
for _, in := range s {
if in == "" {
continue
}

if !strings.Contains(in, "=") {
// This is ref only format. Each field in the CSV is its own entry.
fields, err := csvvalue.Fields(in, nil)
if err != nil {
return nil, err
}

for _, field := range fields {
out := buildflags.CacheOptionsEntry{}
if err := out.UnmarshalText([]byte(field)); err != nil {
return nil, err
}
outs = append(outs, &out)
}
continue
}

// Normal entry.
out := buildflags.CacheOptionsEntry{}
if err := out.UnmarshalText([]byte(in)); err != nil {
return nil, err
}
outs = append(outs, &out)
}
return outs, nil
}
22 changes: 22 additions & 0 deletions bake/bake_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
"strings"
"testing"

"github.com/docker/buildx/util/buildflags"
"github.com/moby/buildkit/util/entitlements"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
Expand Down Expand Up @@ -1759,6 +1760,27 @@ func TestAnnotations(t *testing.T) {
require.Equal(t, "bar", bo["app"].Exports[0].Attrs["annotation-manifest[linux/amd64].foo"])
}

func TestRefOnlyCacheOptions(t *testing.T) {
fp := File{
Name: "docker-bake.hcl",
Data: []byte(
`target "app" {
output = ["type=image,name=foo"]
cache-from = ["ref1,ref2"]
}`),
}
ctx := context.TODO()
m, _, err := ReadTargets(ctx, []File{fp}, []string{"app"}, nil, nil, &EntitlementConf{})
require.NoError(t, err)

require.Len(t, m, 1)
require.Contains(t, m, "app")
require.Equal(t, buildflags.CacheOptions{
{Type: "registry", Attrs: map[string]string{"ref": "ref1"}},
{Type: "registry", Attrs: map[string]string{"ref": "ref2"}},
}, m["app"].CacheFrom)
}

func TestHCLEntitlements(t *testing.T) {
fp := File{
Name: "docker-bake.hcl",
Expand Down
8 changes: 4 additions & 4 deletions bake/compose.go
Original file line number Diff line number Diff line change
Expand Up @@ -145,12 +145,12 @@ func ParseCompose(cfgs []composetypes.ConfigFile, envs map[string]string) (*Conf
labels[k] = &v
}

cacheFrom, err := parseCacheArrValues(s.Build.CacheFrom)
cacheFrom, err := buildflags.ParseCacheEntry(s.Build.CacheFrom)
if err != nil {
return nil, err
}

cacheTo, err := parseCacheArrValues(s.Build.CacheTo)
cacheTo, err := buildflags.ParseCacheEntry(s.Build.CacheTo)
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -349,14 +349,14 @@ func (t *Target) composeExtTarget(exts map[string]interface{}) error {
t.Tags = dedupSlice(append(t.Tags, xb.Tags...))
}
if len(xb.CacheFrom) > 0 {
cacheFrom, err := parseCacheArrValues(xb.CacheFrom)
cacheFrom, err := buildflags.ParseCacheEntry(xb.CacheFrom)
if err != nil {
return err
}
t.CacheFrom = t.CacheFrom.Merge(cacheFrom)
}
if len(xb.CacheTo) > 0 {
cacheTo, err := parseCacheArrValues(xb.CacheTo)
cacheTo, err := buildflags.ParseCacheEntry(xb.CacheTo)
if err != nil {
return err
}
Expand Down
7 changes: 5 additions & 2 deletions commands/build.go
Original file line number Diff line number Diff line change
Expand Up @@ -183,14 +183,17 @@ func (o *buildOptions) toControllerOptions() (*controllerapi.BuildOptions, error
}
}

opts.CacheFrom, err = buildflags.ParseCacheEntry(o.cacheFrom)
cacheFrom, err := buildflags.ParseCacheEntry(o.cacheFrom)
if err != nil {
return nil, err
}
opts.CacheTo, err = buildflags.ParseCacheEntry(o.cacheTo)
opts.CacheFrom = cacheFrom.ToPB()

cacheTo, err := buildflags.ParseCacheEntry(o.cacheTo)
if err != nil {
return nil, err
}
opts.CacheTo = cacheTo.ToPB()

opts.Secrets, err = buildflags.ParseSecretSpecs(o.secrets)
if err != nil {
Expand Down
21 changes: 19 additions & 2 deletions util/buildflags/cache.go
Original file line number Diff line number Diff line change
Expand Up @@ -167,20 +167,37 @@ func (e *CacheOptionsEntry) validate(gv interface{}) error {
return nil
}

func ParseCacheEntry(in []string) ([]*controllerapi.CacheOptionsEntry, error) {
func ParseCacheEntry(in []string) (CacheOptions, error) {
if len(in) == 0 {
return nil, nil
}

opts := make(CacheOptions, 0, len(in))
for _, in := range in {
if !strings.Contains(in, "=") {
// This is ref only format. Each field in the CSV is its own entry.
fields, err := csvvalue.Fields(in, nil)
if err != nil {
return nil, err
}

for _, field := range fields {
opt := CacheOptionsEntry{}
if err := opt.UnmarshalText([]byte(field)); err != nil {
return nil, err
}
opts = append(opts, &opt)
}
continue
}

var out CacheOptionsEntry
if err := out.UnmarshalText([]byte(in)); err != nil {
return nil, err
}
opts = append(opts, &out)
}
return opts.ToPB(), nil
return opts, nil
}

func addGithubToken(ci *controllerapi.CacheOptionsEntry) {
Expand Down
17 changes: 10 additions & 7 deletions util/buildflags/cache_cty.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,16 @@ func (o *CacheOptions) fromCtyValue(in cty.Value, p cty.Path) error {
continue
}

// Special handling for a string type to handle ref only format.
if value.Type() == cty.String {
entries, err := ParseCacheEntry([]string{value.AsString()})
if err != nil {
return err
}
*o = append(*o, entries...)
continue
}

entry := &CacheOptionsEntry{}
if err := entry.FromCtyValue(value, p); err != nil {
return err
Expand All @@ -52,13 +62,6 @@ func (o CacheOptions) ToCtyValue() cty.Value {
}

func (o *CacheOptionsEntry) FromCtyValue(in cty.Value, p cty.Path) error {
if in.Type() == cty.String {
if err := o.UnmarshalText([]byte(in.AsString())); err != nil {
return p.NewError(err)
}
return nil
}

conv, err := convert.Convert(in, cty.Map(cty.String))
if err != nil {
return err
Expand Down
11 changes: 10 additions & 1 deletion util/buildflags/cache_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ func TestCacheOptions_DerivedVars(t *testing.T) {
"session_token": "not_a_mitm_attack",
},
},
}, cacheFrom)
}, cacheFrom.ToPB())
}

func TestCacheOptions(t *testing.T) {
Expand Down Expand Up @@ -109,3 +109,12 @@ func TestCacheOptions(t *testing.T) {
require.True(t, result.True())
})
}

func TestCacheOptions_RefOnlyFormat(t *testing.T) {
opts, err := ParseCacheEntry([]string{"ref1", "ref2"})
require.NoError(t, err)
require.Equal(t, CacheOptions{
{Type: "registry", Attrs: map[string]string{"ref": "ref1"}},
{Type: "registry", Attrs: map[string]string{"ref": "ref2"}},
}, opts)
}

0 comments on commit 17af006

Please sign in to comment.