apicaps: record the correct caps when constructing a CapSet

We need to capture `c` within the loop, otherwise all of the entries of `m` end
up pointing to the same thing, which is the last cap in `range caps`.

The symptom was that all caps were enabled/disabled based on the last cap's
setting and not their own.

Add a test for this.

Signed-off-by: Ian Campbell <ijc@docker.com>
docker-18.09
Ian Campbell 2018-07-25 14:25:07 +01:00
parent bec4a33fa5
commit e0196c9a12
2 changed files with 61 additions and 0 deletions

View File

@ -87,6 +87,7 @@ func (l *CapList) CapSet(caps []pb.APICap) CapSet {
m := make(map[string]*pb.APICap, len(caps)) m := make(map[string]*pb.APICap, len(caps))
for _, c := range caps { for _, c := range caps {
if c.ID != "" { if c.ID != "" {
c := c // capture loop iterator
m[c.ID] = &c m[c.ID] = &c
} }
} }

60
util/apicaps/caps_test.go Normal file
View File

@ -0,0 +1,60 @@
package apicaps
import (
"testing"
pb "github.com/moby/buildkit/util/apicaps/pb"
"github.com/stretchr/testify/assert"
)
func TestDisabledCap(t *testing.T) {
var cl CapList
cl.Init(Cap{
ID: "cap1",
Name: "a test cap",
Enabled: true,
Status: CapStatusExperimental,
})
cl.Init(Cap{
ID: "cap2",
Name: "a second test cap",
Enabled: false,
Status: CapStatusExperimental,
})
cs := cl.CapSet([]pb.APICap{
{ID: "cap1", Enabled: true},
{ID: "cap2", Enabled: true},
})
err := cs.Supports("cap1")
assert.NoError(t, err)
err = cs.Supports("cap2")
assert.NoError(t, err)
cs = cl.CapSet([]pb.APICap{
{ID: "cap1", Enabled: true},
{ID: "cap2", Enabled: false},
})
err = cs.Supports("cap1")
assert.NoError(t, err)
err = cs.Supports("cap2")
assert.EqualError(t, err, "requested experimental feature cap2 (a second test cap) has been disabled on the build server")
cs = cl.CapSet([]pb.APICap{
{ID: "cap1", Enabled: false},
{ID: "cap2", Enabled: true},
})
err = cs.Supports("cap1")
assert.EqualError(t, err, "requested experimental feature cap1 (a test cap) has been disabled on the build server")
err = cs.Supports("cap2")
assert.NoError(t, err)
cs = cl.CapSet([]pb.APICap{
{ID: "cap1", Enabled: false},
{ID: "cap2", Enabled: false},
})
err = cs.Supports("cap1")
assert.EqualError(t, err, "requested experimental feature cap1 (a test cap) has been disabled on the build server")
err = cs.Supports("cap2")
assert.EqualError(t, err, "requested experimental feature cap2 (a second test cap) has been disabled on the build server")
}