From 61adfa576aa8589a1863381255d66a3290990469 Mon Sep 17 00:00:00 2001 From: Ilya Dmitrichenko Date: Tue, 13 Dec 2022 14:08:50 +0000 Subject: [PATCH] options: move Options types from build package Signed-off-by: Ilya Dmitrichenko --- bake/bake.go | 29 ++++++++++---------- build/build.go | 68 +++++++--------------------------------------- commands/build.go | 22 ++++++++------- commands/print.go | 4 +-- options/options.go | 61 +++++++++++++++++++++++++++++++++++++++++ 5 files changed, 100 insertions(+), 84 deletions(-) create mode 100644 options/options.go diff --git a/bake/bake.go b/bake/bake.go index 423d074c..3467cedc 100644 --- a/bake/bake.go +++ b/bake/bake.go @@ -14,7 +14,8 @@ import ( "strings" "github.com/docker/buildx/bake/hclparser" - "github.com/docker/buildx/build" + "github.com/docker/buildx/options" + "github.com/docker/buildx/util/buildflags" "github.com/docker/buildx/util/platformutil" "github.com/docker/cli/cli/config" @@ -760,8 +761,8 @@ func (t *Target) AddOverrides(overrides map[string]Override) error { return nil } -func TargetsToBuildOpt(m map[string]*Target, inp *Input) (map[string]build.Options, error) { - m2 := make(map[string]build.Options, len(m)) +func TargetsToBuildOpt(m map[string]*Target, inp *Input) (map[string]options.Options, error) { + m2 := make(map[string]options.Options, len(m)) for k, v := range m { bo, err := toBuildOpt(v, inp) if err != nil { @@ -772,14 +773,14 @@ func TargetsToBuildOpt(m map[string]*Target, inp *Input) (map[string]build.Optio return m2, nil } -func updateContext(t *build.Inputs, inp *Input) { +func updateContext(t *options.Inputs, inp *Input) { if inp == nil || inp.State == nil { return } for k, v := range t.NamedContexts { if v.Path == "." { - t.NamedContexts[k] = build.NamedContext{Path: inp.URL} + t.NamedContexts[k] = options.NamedContext{Path: inp.URL} } if strings.HasPrefix(v.Path, "cwd://") || strings.HasPrefix(v.Path, "target:") || strings.HasPrefix(v.Path, "docker-image:") { continue @@ -788,7 +789,7 @@ func updateContext(t *build.Inputs, inp *Input) { continue } st := llb.Scratch().File(llb.Copy(*inp.State, v.Path, "/"), llb.WithCustomNamef("set context %s to %s", k, v.Path)) - t.NamedContexts[k] = build.NamedContext{State: &st} + t.NamedContexts[k] = options.NamedContext{State: &st} } if t.ContextPath == "." { @@ -808,7 +809,7 @@ func updateContext(t *build.Inputs, inp *Input) { // validateContextsEntitlements is a basic check to ensure contexts do not // escape local directories when loaded from remote sources. This is to be // replaced with proper entitlements support in the future. -func validateContextsEntitlements(t build.Inputs, inp *Input) error { +func validateContextsEntitlements(t options.Inputs, inp *Input) error { if inp == nil || inp.State == nil { return nil } @@ -858,7 +859,7 @@ func checkPath(p string) error { return nil } -func toBuildOpt(t *Target, inp *Input) (*build.Options, error) { +func toBuildOpt(t *Target, inp *Input) (*options.Options, error) { if v := t.Context; v != nil && *v == "-" { return nil, errors.Errorf("context from stdin not allowed in bake") } @@ -895,7 +896,7 @@ func toBuildOpt(t *Target, inp *Input) (*build.Options, error) { networkMode = *t.NetworkMode } - bi := build.Inputs{ + bi := options.Inputs{ ContextPath: contextPath, DockerfilePath: dockerfilePath, NamedContexts: toNamedContexts(t.Contexts), @@ -909,7 +910,7 @@ func toBuildOpt(t *Target, inp *Input) (*build.Options, error) { } for k, v := range bi.NamedContexts { if strings.HasPrefix(v.Path, "cwd://") { - bi.NamedContexts[k] = build.NamedContext{Path: path.Clean(strings.TrimPrefix(v.Path, "cwd://"))} + bi.NamedContexts[k] = options.NamedContext{Path: path.Clean(strings.TrimPrefix(v.Path, "cwd://"))} } } @@ -919,7 +920,7 @@ func toBuildOpt(t *Target, inp *Input) (*build.Options, error) { t.Context = &bi.ContextPath - bo := &build.Options{ + bo := &options.Options{ Inputs: bi, Tags: t.Tags, BuildArgs: t.Args, @@ -1057,10 +1058,10 @@ func sliceEqual(s1, s2 []string) bool { return true } -func toNamedContexts(m map[string]string) map[string]build.NamedContext { - m2 := make(map[string]build.NamedContext, len(m)) +func toNamedContexts(m map[string]string) map[string]options.NamedContext { + m2 := make(map[string]options.NamedContext, len(m)) for k, v := range m { - m2[k] = build.NamedContext{Path: v} + m2[k] = options.NamedContext{Path: v} } return m2 } diff --git a/build/build.go b/build/build.go index c42586d2..bf61e4e0 100644 --- a/build/build.go +++ b/build/build.go @@ -23,13 +23,14 @@ import ( "github.com/containerd/containerd/images" "github.com/containerd/containerd/platforms" "github.com/docker/buildx/builder" + "github.com/docker/buildx/options" + "github.com/docker/buildx/driver" "github.com/docker/buildx/util/dockerutil" "github.com/docker/buildx/util/imagetools" "github.com/docker/buildx/util/progress" "github.com/docker/buildx/util/resolver" "github.com/docker/buildx/util/waitmap" - "github.com/docker/cli/opts" "github.com/docker/distribution/reference" "github.com/docker/docker/api/types" "github.com/docker/docker/builder/remotecontext/urlutil" @@ -39,7 +40,6 @@ import ( "github.com/moby/buildkit/exporter/containerimage/exptypes" "github.com/moby/buildkit/frontend/attestations" gateway "github.com/moby/buildkit/frontend/gateway/client" - "github.com/moby/buildkit/session" "github.com/moby/buildkit/session/upload/uploadprovider" "github.com/moby/buildkit/solver/errdefs" "github.com/moby/buildkit/solver/pb" @@ -64,54 +64,6 @@ const ( printFallbackImage = "docker/dockerfile-upstream:1.4-outline@sha256:627443ff4e2d0f635d429cfc1da5388bcd5a70949c38adcd3cd7c4e5df67c73c" ) -type Options struct { - Inputs Inputs - - Allow []entitlements.Entitlement - Attests map[string]*string - BuildArgs map[string]string - CacheFrom []client.CacheOptionsEntry - CacheTo []client.CacheOptionsEntry - CgroupParent string - Exports []client.ExportEntry - ExtraHosts []string - ImageIDFile string - Labels map[string]string - NetworkMode string - NoCache bool - NoCacheFilter []string - Platforms []specs.Platform - Pull bool - Session []session.Attachable - ShmSize opts.MemBytes - Tags []string - Target string - Ulimits *opts.UlimitOpt - - // Linked marks this target as exclusively linked (not requested by the user). - Linked bool - PrintFunc *PrintFunc -} - -type PrintFunc struct { - Name string - Format string -} - -type Inputs struct { - ContextPath string - DockerfilePath string - InStream io.Reader - ContextState *llb.State - DockerfileInline string - NamedContexts map[string]NamedContext -} - -type NamedContext struct { - Path string - State *llb.State -} - type driverPair struct { driverIndex int platforms []specs.Platform @@ -168,7 +120,7 @@ func ensureBooted(ctx context.Context, nodes []builder.Node, idxs []int, pw prog return clients, nil } -func splitToDriverPairs(availablePlatforms map[string]int, opt map[string]Options) map[string][]driverPair { +func splitToDriverPairs(availablePlatforms map[string]int, opt map[string]options.Options) map[string][]driverPair { m := map[string][]driverPair{} for k, opt := range opt { mm := map[int][]specs.Platform{} @@ -192,7 +144,7 @@ func splitToDriverPairs(availablePlatforms map[string]int, opt map[string]Option return m } -func resolveDrivers(ctx context.Context, nodes []builder.Node, opt map[string]Options, pw progress.Writer) (map[string][]driverPair, []*client.Client, error) { +func resolveDrivers(ctx context.Context, nodes []builder.Node, opt map[string]options.Options, pw progress.Writer) (map[string][]driverPair, []*client.Client, error) { dps, clients, err := resolveDriversBase(ctx, nodes, opt, pw) if err != nil { return nil, nil, err @@ -233,7 +185,7 @@ func resolveDrivers(ctx context.Context, nodes []builder.Node, opt map[string]Op return dps, clients, nil } -func resolveDriversBase(ctx context.Context, nodes []builder.Node, opt map[string]Options, pw progress.Writer) (map[string][]driverPair, []*client.Client, error) { +func resolveDriversBase(ctx context.Context, nodes []builder.Node, opt map[string]options.Options, pw progress.Writer) (map[string][]driverPair, []*client.Client, error) { availablePlatforms := map[string]int{} for i, node := range nodes { for _, p := range node.Platforms { @@ -339,7 +291,7 @@ func toRepoOnly(in string) (string, error) { return strings.Join(out, ","), nil } -func toSolveOpt(ctx context.Context, node builder.Node, multiDriver bool, opt Options, bopts gateway.BuildOpts, configDir string, pw progress.Writer, dl dockerLoadCallback) (solveOpt *client.SolveOpt, release func(), err error) { +func toSolveOpt(ctx context.Context, node builder.Node, multiDriver bool, opt options.Options, bopts gateway.BuildOpts, configDir string, pw progress.Writer, dl dockerLoadCallback) (solveOpt *client.SolveOpt, release func(), err error) { nodeDriver := node.Driver defers := make([]func(), 0, 2) releaseF := func() { @@ -776,11 +728,11 @@ func Invoke(ctx context.Context, cfg ContainerConfig) error { return err } -func Build(ctx context.Context, nodes []builder.Node, opt map[string]Options, docker *dockerutil.Client, configDir string, w progress.Writer) (resp map[string]*client.SolveResponse, err error) { +func Build(ctx context.Context, nodes []builder.Node, opt map[string]options.Options, docker *dockerutil.Client, configDir string, w progress.Writer) (resp map[string]*client.SolveResponse, err error) { return BuildWithResultHandler(ctx, nodes, opt, docker, configDir, w, nil, false) } -func BuildWithResultHandler(ctx context.Context, nodes []builder.Node, opt map[string]Options, docker *dockerutil.Client, configDir string, w progress.Writer, resultHandleFunc func(driverIndex int, rCtx *ResultContext), allowNoOutput bool) (resp map[string]*client.SolveResponse, err error) { +func BuildWithResultHandler(ctx context.Context, nodes []builder.Node, opt map[string]options.Options, docker *dockerutil.Client, configDir string, w progress.Writer, resultHandleFunc func(driverIndex int, rCtx *ResultContext), allowNoOutput bool) (resp map[string]*client.SolveResponse, err error) { if len(nodes) == 0 { return nil, errors.Errorf("driver required for build") } @@ -1339,7 +1291,7 @@ func createTempDockerfile(r io.Reader) (string, error) { return dir, err } -func LoadInputs(ctx context.Context, d driver.Driver, inp Inputs, pw progress.Writer, target *client.SolveOpt) (func(), error) { +func LoadInputs(ctx context.Context, d driver.Driver, inp options.Inputs, pw progress.Writer, target *client.SolveOpt) (func(), error) { if inp.ContextPath == "" { return nil, errors.New("please specify build context (e.g. \".\" for the current directory)") } @@ -1679,7 +1631,7 @@ func tryNodeIdentifier(configDir string) (out string) { return } -func noPrintFunc(opt map[string]Options) bool { +func noPrintFunc(opt map[string]options.Options) bool { for _, v := range opt { if v.PrintFunc != nil { return false diff --git a/commands/build.go b/commands/build.go index 99e820e3..5d76affb 100644 --- a/commands/build.go +++ b/commands/build.go @@ -16,6 +16,8 @@ import ( "github.com/containerd/console" "github.com/docker/buildx/build" + "github.com/docker/buildx/options" + "github.com/docker/buildx/builder" "github.com/docker/buildx/monitor" "github.com/docker/buildx/store" @@ -133,8 +135,8 @@ func runBuild(dockerCli command.Cli, in buildOptions) (err error) { return err } - opts := build.Options{ - Inputs: build.Inputs{ + opts := options.Options{ + Inputs: options.Inputs{ ContextPath: in.contextPath, DockerfilePath: in.dockerfileName, InStream: os.Stdin, @@ -271,7 +273,7 @@ func runBuild(dockerCli command.Cli, in buildOptions) (err error) { return err } - imageID, res, err := buildTargets(ctx, dockerCli, nodes, map[string]build.Options{defaultTargetName: opts}, in.progress, in.metadataFile, in.invoke != "") + imageID, res, err := buildTargets(ctx, dockerCli, nodes, map[string]options.Options{defaultTargetName: opts}, in.progress, in.metadataFile, in.invoke != "") err = wrapBuildError(err, false) if err != nil { return err @@ -288,7 +290,7 @@ func runBuild(dockerCli command.Cli, in buildOptions) (err error) { return errors.Errorf("failed to configure terminal: %v", err) } err = monitor.RunMonitor(ctx, cfg, func(ctx context.Context) (*build.ResultContext, error) { - _, rr, err := buildTargets(ctx, dockerCli, nodes, map[string]build.Options{defaultTargetName: opts}, in.progress, in.metadataFile, true) + _, rr, err := buildTargets(ctx, dockerCli, nodes, map[string]options.Options{defaultTargetName: opts}, in.progress, in.metadataFile, true) return rr, err }, io.NopCloser(os.Stdin), nopCloser{os.Stdout}, nopCloser{os.Stderr}) if err != nil { @@ -309,7 +311,7 @@ type nopCloser struct { func (c nopCloser) Close() error { return nil } -func buildTargets(ctx context.Context, dockerCli command.Cli, nodes []builder.Node, opts map[string]build.Options, progressMode string, metadataFile string, allowNoOutput bool) (imageID string, res *build.ResultContext, err error) { +func buildTargets(ctx context.Context, dockerCli command.Cli, nodes []builder.Node, opts map[string]options.Options, progressMode string, metadataFile string, allowNoOutput bool) (imageID string, res *build.ResultContext, err error) { ctx2, cancel := context.WithCancel(context.TODO()) defer cancel() @@ -623,11 +625,11 @@ func listToMap(values []string, defaultEnv bool) map[string]string { return result } -func parseContextNames(values []string) (map[string]build.NamedContext, error) { +func parseContextNames(values []string) (map[string]options.NamedContext, error) { if len(values) == 0 { return nil, nil } - result := make(map[string]build.NamedContext, len(values)) + result := make(map[string]options.NamedContext, len(values)) for _, value := range values { kv := strings.SplitN(value, "=", 2) if len(kv) != 2 { @@ -638,12 +640,12 @@ func parseContextNames(values []string) (map[string]build.NamedContext, error) { return nil, errors.Wrapf(err, "invalid context name %s", kv[0]) } name := strings.TrimSuffix(reference.FamiliarString(named), ":latest") - result[name] = build.NamedContext{Path: kv[1]} + result[name] = options.NamedContext{Path: kv[1]} } return result, nil } -func parsePrintFunc(str string) (*build.PrintFunc, error) { +func parsePrintFunc(str string) (*options.PrintFunc, error) { if str == "" { return nil, nil } @@ -652,7 +654,7 @@ func parsePrintFunc(str string) (*build.PrintFunc, error) { if err != nil { return nil, err } - f := &build.PrintFunc{} + f := &options.PrintFunc{} for _, field := range fields { parts := strings.SplitN(field, "=", 2) if len(parts) == 2 { diff --git a/commands/print.go b/commands/print.go index 9c7f9460..bcc6a259 100644 --- a/commands/print.go +++ b/commands/print.go @@ -6,14 +6,14 @@ import ( "log" "os" - "github.com/docker/buildx/build" + "github.com/docker/buildx/options" "github.com/docker/docker/api/types/versions" "github.com/moby/buildkit/frontend/subrequests" "github.com/moby/buildkit/frontend/subrequests/outline" "github.com/moby/buildkit/frontend/subrequests/targets" ) -func printResult(f *build.PrintFunc, res map[string]string) error { +func printResult(f *options.PrintFunc, res map[string]string) error { switch f.Name { case "outline": return printValue(outline.PrintOutline, outline.SubrequestsOutlineDefinition.Version, f.Format, res) diff --git a/options/options.go b/options/options.go new file mode 100644 index 00000000..c4bd099a --- /dev/null +++ b/options/options.go @@ -0,0 +1,61 @@ +package options + +import ( + _ "crypto/sha256" // ensure digests can be computed + "io" + + "github.com/docker/cli/opts" + "github.com/moby/buildkit/client" + "github.com/moby/buildkit/client/llb" + "github.com/moby/buildkit/session" + "github.com/moby/buildkit/util/entitlements" + specs "github.com/opencontainers/image-spec/specs-go/v1" +) + +type Options struct { + Inputs Inputs + + Allow []entitlements.Entitlement + Attests map[string]*string + BuildArgs map[string]string + CacheFrom []client.CacheOptionsEntry + CacheTo []client.CacheOptionsEntry + CgroupParent string + Exports []client.ExportEntry + ExtraHosts []string + ImageIDFile string + Labels map[string]string + NetworkMode string + NoCache bool + NoCacheFilter []string + Platforms []specs.Platform + Pull bool + Session []session.Attachable + ShmSize opts.MemBytes + Tags []string + Target string + Ulimits *opts.UlimitOpt + + // Linked marks this target as exclusively linked (not requested by the user). + Linked bool + PrintFunc *PrintFunc +} + +type PrintFunc struct { + Name string + Format string +} + +type Inputs struct { + ContextPath string + DockerfilePath string + InStream io.Reader + ContextState *llb.State + DockerfileInline string + NamedContexts map[string]NamedContext +} + +type NamedContext struct { + Path string + State *llb.State +}