controller: refactor build inputs to external struct
This patch continues the move to attempt to merge the build.Options struct into the controllerapi.Options message. To do this, we extract all the input parameters into a dedicated message (adding the missing ones, except for the InStream parameter which will require some additional fiddling around). We also rework the NamedContexts to allow containing States (by transmitting them as DefinitionOps), and adding a Linked field to the common options. Signed-off-by: CrazyMax <crazy-max@users.noreply.github.com>
This commit is contained in:
committed by
CrazyMax
parent
ea06685c11
commit
3c3e4a6d5f
@@ -23,6 +23,7 @@ import (
|
||||
dockeropts "github.com/docker/cli/opts"
|
||||
"github.com/docker/go-units"
|
||||
"github.com/moby/buildkit/client"
|
||||
"github.com/moby/buildkit/client/llb"
|
||||
"github.com/moby/buildkit/session/auth/authprovider"
|
||||
"github.com/moby/buildkit/util/grpcerrors"
|
||||
"github.com/pkg/errors"
|
||||
@@ -37,29 +38,85 @@ const defaultTargetName = "default"
|
||||
// this function returns it in addition to the error (i.e. it does "return nil, res, err"). The caller can
|
||||
// inspect the result and debug the cause of that error.
|
||||
func RunBuild(ctx context.Context, dockerCli command.Cli, in controllerapi.BuildOptions, inStream io.Reader, progress progress.Writer, generateResult bool) (*client.SolveResponse, *build.ResultHandle, error) {
|
||||
if in.NoCache && len(in.NoCacheFilter) > 0 {
|
||||
return nil, nil, errors.Errorf("--no-cache and --no-cache-filter cannot currently be used together")
|
||||
opts, err := ToBuildOpts(in, inStream)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
// key string used for kubernetes "sticky" mode
|
||||
contextPathHash, err := filepath.Abs(in.Inputs.ContextPath)
|
||||
if err != nil {
|
||||
contextPathHash = in.Inputs.ContextPath
|
||||
}
|
||||
|
||||
b, err := builder.New(dockerCli,
|
||||
builder.WithName(in.Opts.Builder),
|
||||
builder.WithContextPathHash(contextPathHash),
|
||||
)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
if err = updateLastActivity(dockerCli, b.NodeGroup); err != nil {
|
||||
return nil, nil, errors.Wrapf(err, "failed to update builder last activity time")
|
||||
}
|
||||
nodes, err := b.LoadNodes(ctx, false)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
resp, res, err := buildTargets(ctx, dockerCli, b.NodeGroup, nodes, map[string]build.Options{defaultTargetName: *opts}, progress, generateResult)
|
||||
err = wrapBuildError(err, false)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
return resp, res, nil
|
||||
}
|
||||
|
||||
func ToBuildOpts(in controllerapi.BuildOptions, inStream io.Reader) (*build.Options, error) {
|
||||
if in.Opts.NoCache && len(in.NoCacheFilter) > 0 {
|
||||
return nil, errors.Errorf("--no-cache and --no-cache-filter cannot currently be used together")
|
||||
}
|
||||
|
||||
var ctxst *llb.State
|
||||
if in.Inputs.ContextDefinition != nil {
|
||||
defop, err := llb.NewDefinitionOp(in.Inputs.ContextDefinition)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
st := llb.NewState(defop)
|
||||
ctxst = &st
|
||||
}
|
||||
|
||||
contexts := map[string]build.NamedContext{}
|
||||
for name, path := range in.NamedContexts {
|
||||
contexts[name] = build.NamedContext{Path: path}
|
||||
for name, nctx := range in.Inputs.NamedContexts {
|
||||
if nctx.Definition != nil {
|
||||
defop, err := llb.NewDefinitionOp(nctx.Definition)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
st := llb.NewState(defop)
|
||||
contexts[name] = build.NamedContext{State: &st}
|
||||
} else {
|
||||
contexts[name] = build.NamedContext{Path: nctx.Path}
|
||||
}
|
||||
}
|
||||
|
||||
opts := build.Options{
|
||||
Inputs: build.Inputs{
|
||||
ContextPath: in.ContextPath,
|
||||
DockerfilePath: in.DockerfileName,
|
||||
InStream: inStream,
|
||||
NamedContexts: contexts,
|
||||
ContextPath: in.Inputs.ContextPath,
|
||||
DockerfilePath: in.Inputs.DockerfileName,
|
||||
DockerfileInline: in.Inputs.DockerfileInline,
|
||||
ContextState: ctxst,
|
||||
InStream: inStream,
|
||||
NamedContexts: contexts,
|
||||
},
|
||||
BuildArgs: in.BuildArgs,
|
||||
ExtraHosts: in.ExtraHosts,
|
||||
Labels: in.Labels,
|
||||
NetworkMode: in.NetworkMode,
|
||||
NoCache: in.NoCache,
|
||||
NoCache: in.Opts.NoCache,
|
||||
NoCacheFilter: in.NoCacheFilter,
|
||||
Pull: in.Pull,
|
||||
Pull: in.Opts.Pull,
|
||||
ShmSize: dockeropts.MemBytes(in.ShmSize),
|
||||
Tags: in.Tags,
|
||||
Target: in.Target,
|
||||
@@ -68,7 +125,7 @@ func RunBuild(ctx context.Context, dockerCli command.Cli, in controllerapi.Build
|
||||
|
||||
platforms, err := platformutil.Parse(in.Platforms)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
return nil, err
|
||||
}
|
||||
opts.Platforms = platforms
|
||||
|
||||
@@ -77,27 +134,27 @@ func RunBuild(ctx context.Context, dockerCli command.Cli, in controllerapi.Build
|
||||
|
||||
secrets, err := controllerapi.CreateSecrets(in.Secrets)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
return nil, err
|
||||
}
|
||||
opts.Session = append(opts.Session, secrets)
|
||||
|
||||
sshSpecs := in.SSH
|
||||
if len(sshSpecs) == 0 && buildflags.IsGitSSH(in.ContextPath) {
|
||||
if len(sshSpecs) == 0 && buildflags.IsGitSSH(in.Inputs.ContextPath) {
|
||||
sshSpecs = append(sshSpecs, &controllerapi.SSH{ID: "default"})
|
||||
}
|
||||
ssh, err := controllerapi.CreateSSH(sshSpecs)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
return nil, err
|
||||
}
|
||||
opts.Session = append(opts.Session, ssh)
|
||||
|
||||
outputs, err := controllerapi.CreateExports(in.Exports)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
return nil, err
|
||||
}
|
||||
if in.ExportPush {
|
||||
if in.ExportLoad {
|
||||
return nil, nil, errors.Errorf("push and load may not be set together at the moment")
|
||||
if in.Opts.ExportPush {
|
||||
if in.Opts.ExportLoad {
|
||||
return nil, errors.Errorf("push and load may not be set together at the moment")
|
||||
}
|
||||
if len(outputs) == 0 {
|
||||
outputs = []client.ExportEntry{{
|
||||
@@ -111,11 +168,11 @@ func RunBuild(ctx context.Context, dockerCli command.Cli, in controllerapi.Build
|
||||
case "image":
|
||||
outputs[0].Attrs["push"] = "true"
|
||||
default:
|
||||
return nil, nil, errors.Errorf("push and %q output can't be used together", outputs[0].Type)
|
||||
return nil, errors.Errorf("push and %q output can't be used together", outputs[0].Type)
|
||||
}
|
||||
}
|
||||
}
|
||||
if in.ExportLoad {
|
||||
if in.Opts.ExportLoad {
|
||||
if len(outputs) == 0 {
|
||||
outputs = []client.ExportEntry{{
|
||||
Type: "docker",
|
||||
@@ -125,7 +182,7 @@ func RunBuild(ctx context.Context, dockerCli command.Cli, in controllerapi.Build
|
||||
switch outputs[0].Type {
|
||||
case "docker":
|
||||
default:
|
||||
return nil, nil, errors.Errorf("load and %q output can't be used together", outputs[0].Type)
|
||||
return nil, errors.Errorf("load and %q output can't be used together", outputs[0].Type)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -140,7 +197,7 @@ func RunBuild(ctx context.Context, dockerCli command.Cli, in controllerapi.Build
|
||||
|
||||
allow, err := buildflags.ParseEntitlements(in.Allow)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
return nil, err
|
||||
}
|
||||
opts.Allow = allow
|
||||
|
||||
@@ -151,35 +208,7 @@ func RunBuild(ctx context.Context, dockerCli command.Cli, in controllerapi.Build
|
||||
}
|
||||
}
|
||||
|
||||
// key string used for kubernetes "sticky" mode
|
||||
contextPathHash, err := filepath.Abs(in.ContextPath)
|
||||
if err != nil {
|
||||
contextPathHash = in.ContextPath
|
||||
}
|
||||
|
||||
// TODO: this should not be loaded this side of the controller api
|
||||
b, err := builder.New(dockerCli,
|
||||
builder.WithName(in.Builder),
|
||||
builder.WithContextPathHash(contextPathHash),
|
||||
)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
if err = updateLastActivity(dockerCli, b.NodeGroup); err != nil {
|
||||
return nil, nil, errors.Wrapf(err, "failed to update builder last activity time")
|
||||
}
|
||||
nodes, err := b.LoadNodes(ctx, false)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
resp, res, err := buildTargets(ctx, dockerCli, b.NodeGroup, nodes, map[string]build.Options{defaultTargetName: opts}, progress, generateResult)
|
||||
err = wrapBuildError(err, false)
|
||||
if err != nil {
|
||||
// NOTE: buildTargets can return *build.ResultHandle even on error.
|
||||
return nil, res, err
|
||||
}
|
||||
return resp, res, nil
|
||||
return &opts, nil
|
||||
}
|
||||
|
||||
// buildTargets runs the specified build and returns the result.
|
||||
|
||||
Reference in New Issue
Block a user