Skip to content

Commit 9dcb37f

Browse files
committed
policy: add --platform to eval
Allow buildx policy eval to accept an explicit target platform and skip worker platform discovery when the flag is provided. Signed-off-by: Tonis Tiigi <tonistiigi@gmail.com>
1 parent dc5f986 commit 9dcb37f

3 files changed

Lines changed: 73 additions & 17 deletions

File tree

commands/policy/eval.go

Lines changed: 19 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ type evalOpts struct {
3333
filename string
3434
printOutput bool
3535
fields []string
36+
platform string
3637
builder *string
3738
}
3839

@@ -52,6 +53,7 @@ func evalCmd(dockerCli command.Cli, rootOpts RootOptions) *cobra.Command {
5253
cmd.Flags().StringVar(&opts.filename, "filename", "Dockerfile", "Policy filename to evaluate")
5354
cmd.Flags().BoolVar(&opts.printOutput, "print", false, "Print policy output")
5455
cmd.Flags().StringSliceVar(&opts.fields, "fields", nil, "Fields to evaluate")
56+
cmd.Flags().StringVar(&opts.platform, "platform", "", "Target platform for policy evaluation")
5557
return cmd
5658
}
5759

@@ -81,29 +83,29 @@ func runEval(ctx context.Context, dockerCli command.Cli, source string, opts eva
8183
return err
8284
}
8385

84-
workers, err := c.ListWorkers(ctx)
85-
if err != nil {
86-
return err
87-
}
86+
var p ocispecs.Platform
87+
if opts.platform != "" {
88+
parsedPlatform, err := parsePlatform(opts.platform)
89+
if err != nil {
90+
return err
91+
}
92+
p = *parsedPlatform
93+
} else {
94+
workers, err := c.ListWorkers(ctx)
95+
if err != nil {
96+
return err
97+
}
8898

89-
if len(workers) == 0 {
90-
return errors.New("no workers available in the builder")
91-
}
99+
if len(workers) == 0 {
100+
return errors.New("no workers available in the builder")
101+
}
92102

93-
defaultPlatform := workers[0].Platforms[0]
94-
p := ocispecs.Platform{
95-
Architecture: defaultPlatform.Architecture,
96-
OS: defaultPlatform.OS,
97-
Variant: defaultPlatform.Variant,
103+
p = workers[0].Platforms[0]
98104
}
99105
metaResolver := sourcemeta.NewResolver(c)
100106
defer metaResolver.Close()
101107

102-
platform := &pb.Platform{
103-
Architecture: p.Architecture,
104-
OS: p.OS,
105-
Variant: p.Variant,
106-
}
108+
platform := toPBPlatform(p)
107109
verifier := policy.SignatureVerifier(confutil.NewConfig(dockerCli))
108110

109111
if opts.printOutput {

commands/policy/eval_test.go

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,39 @@ import (
66
policytypes "github.com/docker/buildx/policy"
77
"github.com/docker/buildx/util/sourcemeta"
88
gwpb "github.com/moby/buildkit/frontend/gateway/pb"
9+
"github.com/moby/buildkit/solver/pb"
910
ocispecs "github.com/opencontainers/image-spec/specs-go/v1"
1011
"github.com/stretchr/testify/require"
1112
)
1213

14+
func TestParsePlatform(t *testing.T) {
15+
t.Run("normalize", func(t *testing.T) {
16+
platform, err := parsePlatform("linux/arm/v7")
17+
require.NoError(t, err)
18+
require.Equal(t, &ocispecs.Platform{
19+
OS: "linux",
20+
Architecture: "arm",
21+
Variant: "v7",
22+
}, platform)
23+
})
24+
25+
t.Run("invalid", func(t *testing.T) {
26+
platform, err := parsePlatform("not-a-platform")
27+
require.Nil(t, platform)
28+
require.Error(t, err)
29+
require.ErrorContains(t, err, "invalid platform \"not-a-platform\"")
30+
require.ErrorContains(t, err, "unknown operating system or architecture")
31+
})
32+
}
33+
34+
func TestToPBPlatform(t *testing.T) {
35+
platform := ocispecs.Platform{OS: "linux", Architecture: "amd64"}
36+
require.Equal(t, &pb.Platform{
37+
OS: "linux",
38+
Architecture: "amd64",
39+
}, toPBPlatform(platform))
40+
}
41+
1342
func TestSourceResolverOptIncludesResolveAttestations(t *testing.T) {
1443
req := &gwpb.ResolveSourceMetaRequest{
1544
ResolveMode: "default",

commands/policy/platform.go

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
package policy
2+
3+
import (
4+
"github.com/containerd/platforms"
5+
"github.com/moby/buildkit/solver/pb"
6+
ocispecs "github.com/opencontainers/image-spec/specs-go/v1"
7+
"github.com/pkg/errors"
8+
)
9+
10+
func parsePlatform(platform string) (*ocispecs.Platform, error) {
11+
p, err := platforms.Parse(platform)
12+
if err != nil {
13+
return nil, errors.Wrapf(err, "invalid platform %q", platform)
14+
}
15+
p = platforms.Normalize(p)
16+
return &p, nil
17+
}
18+
19+
func toPBPlatform(platform ocispecs.Platform) *pb.Platform {
20+
return &pb.Platform{
21+
Architecture: platform.Architecture,
22+
OS: platform.OS,
23+
Variant: platform.Variant,
24+
}
25+
}

0 commit comments

Comments
 (0)