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>
This commit is contained in:
Tonis Tiigi
2026-03-23 11:04:12 -07:00
parent dc5f9862a5
commit 9dcb37f47c
3 changed files with 73 additions and 17 deletions
+19 -17
View File
@@ -33,6 +33,7 @@ type evalOpts struct {
filename string
printOutput bool
fields []string
platform string
builder *string
}
@@ -52,6 +53,7 @@ func evalCmd(dockerCli command.Cli, rootOpts RootOptions) *cobra.Command {
cmd.Flags().StringVar(&opts.filename, "filename", "Dockerfile", "Policy filename to evaluate")
cmd.Flags().BoolVar(&opts.printOutput, "print", false, "Print policy output")
cmd.Flags().StringSliceVar(&opts.fields, "fields", nil, "Fields to evaluate")
cmd.Flags().StringVar(&opts.platform, "platform", "", "Target platform for policy evaluation")
return cmd
}
@@ -81,29 +83,29 @@ func runEval(ctx context.Context, dockerCli command.Cli, source string, opts eva
return err
}
workers, err := c.ListWorkers(ctx)
if err != nil {
return err
}
var p ocispecs.Platform
if opts.platform != "" {
parsedPlatform, err := parsePlatform(opts.platform)
if err != nil {
return err
}
p = *parsedPlatform
} else {
workers, err := c.ListWorkers(ctx)
if err != nil {
return err
}
if len(workers) == 0 {
return errors.New("no workers available in the builder")
}
if len(workers) == 0 {
return errors.New("no workers available in the builder")
}
defaultPlatform := workers[0].Platforms[0]
p := ocispecs.Platform{
Architecture: defaultPlatform.Architecture,
OS: defaultPlatform.OS,
Variant: defaultPlatform.Variant,
p = workers[0].Platforms[0]
}
metaResolver := sourcemeta.NewResolver(c)
defer metaResolver.Close()
platform := &pb.Platform{
Architecture: p.Architecture,
OS: p.OS,
Variant: p.Variant,
}
platform := toPBPlatform(p)
verifier := policy.SignatureVerifier(confutil.NewConfig(dockerCli))
if opts.printOutput {
+29
View File
@@ -6,10 +6,39 @@ import (
policytypes "github.com/docker/buildx/policy"
"github.com/docker/buildx/util/sourcemeta"
gwpb "github.com/moby/buildkit/frontend/gateway/pb"
"github.com/moby/buildkit/solver/pb"
ocispecs "github.com/opencontainers/image-spec/specs-go/v1"
"github.com/stretchr/testify/require"
)
func TestParsePlatform(t *testing.T) {
t.Run("normalize", func(t *testing.T) {
platform, err := parsePlatform("linux/arm/v7")
require.NoError(t, err)
require.Equal(t, &ocispecs.Platform{
OS: "linux",
Architecture: "arm",
Variant: "v7",
}, platform)
})
t.Run("invalid", func(t *testing.T) {
platform, err := parsePlatform("not-a-platform")
require.Nil(t, platform)
require.Error(t, err)
require.ErrorContains(t, err, "invalid platform \"not-a-platform\"")
require.ErrorContains(t, err, "unknown operating system or architecture")
})
}
func TestToPBPlatform(t *testing.T) {
platform := ocispecs.Platform{OS: "linux", Architecture: "amd64"}
require.Equal(t, &pb.Platform{
OS: "linux",
Architecture: "amd64",
}, toPBPlatform(platform))
}
func TestSourceResolverOptIncludesResolveAttestations(t *testing.T) {
req := &gwpb.ResolveSourceMetaRequest{
ResolveMode: "default",
+25
View File
@@ -0,0 +1,25 @@
package policy
import (
"github.com/containerd/platforms"
"github.com/moby/buildkit/solver/pb"
ocispecs "github.com/opencontainers/image-spec/specs-go/v1"
"github.com/pkg/errors"
)
func parsePlatform(platform string) (*ocispecs.Platform, error) {
p, err := platforms.Parse(platform)
if err != nil {
return nil, errors.Wrapf(err, "invalid platform %q", platform)
}
p = platforms.Normalize(p)
return &p, nil
}
func toPBPlatform(platform ocispecs.Platform) *pb.Platform {
return &pb.Platform{
Architecture: platform.Architecture,
OS: platform.OS,
Variant: platform.Variant,
}
}