Skip to content

Commit 9d6d33d

Browse files
committed
control: handle duplicate inline cache exporter
Inline cache exporter can be set with multiple ways, doesn't have any attributes and can always only run one time. Instead of allowing multiple inline exporters where one gets ignored later when there is an attribute difference, or erroring when attributes are unset, just ignore the extra ones. Signed-off-by: Tonis Tiigi <[email protected]>
1 parent fe65d5f commit 9d6d33d

File tree

2 files changed

+73
-7
lines changed

2 files changed

+73
-7
lines changed

control/control.go

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -425,15 +425,17 @@ func (c *Controller) Solve(ctx context.Context, req *controlapi.SolveRequest) (*
425425
expis = append(expis, expi)
426426
}
427427

428-
if c, err := findDuplicateCacheOptions(req.Cache.Exports); err != nil {
428+
rest, dupes, err := findDuplicateCacheOptions(req.Cache.Exports)
429+
if err != nil {
429430
return nil, err
430-
} else if c != nil {
431+
} else if len(dupes) > 0 {
431432
types := []string{}
432-
for _, c := range c {
433+
for _, c := range dupes {
433434
types = append(types, c.Type)
434435
}
435436
return nil, errors.Errorf("duplicate cache exports %s", types)
436437
}
438+
req.Cache.Exports = rest
437439
var cacheExporters []llbsolver.RemoteCacheExporter
438440
for _, e := range req.Cache.Exports {
439441
cacheExporterFunc, ok := c.opt.ResolveCacheExporterFuncs[e.Type]
@@ -727,25 +729,34 @@ func toPBCDIDevices(manager *cdidevices.Manager) []*apitypes.CDIDevice {
727729
return out
728730
}
729731

730-
func findDuplicateCacheOptions(cacheOpts []*controlapi.CacheOptionsEntry) ([]*controlapi.CacheOptionsEntry, error) {
732+
func findDuplicateCacheOptions(cacheOpts []*controlapi.CacheOptionsEntry) ([]*controlapi.CacheOptionsEntry, []*controlapi.CacheOptionsEntry, error) {
731733
seen := map[string]*controlapi.CacheOptionsEntry{}
732734
duplicate := map[string]struct{}{}
735+
hasInline := false
736+
rest := make([]*controlapi.CacheOptionsEntry, 0, len(cacheOpts))
733737
for _, opt := range cacheOpts {
738+
if opt.Type == "inline" && hasInline {
739+
continue
740+
}
734741
k, err := cacheOptKey(opt)
735742
if err != nil {
736-
return nil, err
743+
return nil, nil, err
737744
}
738745
if _, ok := seen[k]; ok {
739746
duplicate[k] = struct{}{}
740747
}
741748
seen[k] = opt
749+
if opt.Type == "inline" {
750+
hasInline = true
751+
}
752+
rest = append(rest, opt)
742753
}
743754

744755
var duplicates []*controlapi.CacheOptionsEntry
745756
for k := range duplicate {
746757
duplicates = append(duplicates, seen[k])
747758
}
748-
return duplicates, nil
759+
return rest, duplicates, nil
749760
}
750761

751762
func cacheOptKey(opt *controlapi.CacheOptionsEntry) (string, error) {

control/control_test.go

Lines changed: 56 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ func TestDuplicateCacheOptions(t *testing.T) {
1212
name string
1313
opts []*controlapi.CacheOptionsEntry
1414
expected []*controlapi.CacheOptionsEntry
15+
rest []*controlapi.CacheOptionsEntry
1516
}{
1617
{
1718
name: "avoids unique opts",
@@ -74,13 +75,67 @@ func TestDuplicateCacheOptions(t *testing.T) {
7475
},
7576
},
7677
},
78+
{
79+
name: "skip inline with attrs",
80+
opts: []*controlapi.CacheOptionsEntry{
81+
{
82+
Type: "inline",
83+
},
84+
{
85+
Type: "registry",
86+
Attrs: map[string]string{
87+
"ref": "example.com/ref:v1.0.0",
88+
},
89+
},
90+
{
91+
Type: "inline",
92+
Attrs: map[string]string{
93+
"foo": "bar",
94+
},
95+
},
96+
},
97+
rest: []*controlapi.CacheOptionsEntry{
98+
{
99+
Type: "inline",
100+
},
101+
{
102+
Type: "registry",
103+
Attrs: map[string]string{
104+
"ref": "example.com/ref:v1.0.0",
105+
},
106+
},
107+
},
108+
expected: nil,
109+
},
110+
{
111+
name: "skip inline simple",
112+
opts: []*controlapi.CacheOptionsEntry{
113+
{
114+
Type: "inline",
115+
},
116+
{
117+
Type: "inline",
118+
},
119+
},
120+
rest: []*controlapi.CacheOptionsEntry{
121+
{
122+
Type: "inline",
123+
},
124+
},
125+
expected: nil,
126+
},
77127
}
78128

79129
for _, tc := range testCases {
80130
t.Run(tc.name, func(t *testing.T) {
81-
result, err := findDuplicateCacheOptions(tc.opts)
131+
rest, result, err := findDuplicateCacheOptions(tc.opts)
82132
require.NoError(t, err)
83133
require.ElementsMatch(t, tc.expected, result)
134+
if tc.rest != nil {
135+
require.ElementsMatch(t, tc.rest, rest)
136+
} else if len(result) == 0 {
137+
require.ElementsMatch(t, tc.opts, rest)
138+
}
84139
})
85140
}
86141
}

0 commit comments

Comments
 (0)