bake: use controller build options as an intermediate stage

With the previous changes to bring controllerapi.BuildOptions up to date
with build.Options, we can have bake generate
controllerapi.BuildOptions, and then convert those to build.Option using
the controller/build package.

This is an intermediate patch, designed to allow us to clean up some
shared logic between both build and bake. The next step will be to
modify bake to use the controller api, and completely skip the
build.Options generation step.

Signed-off-by: CrazyMax <crazy-max@users.noreply.github.com>
pull/1861/head
Justin Chadwell 2 years ago committed by CrazyMax
parent 3c3e4a6d5f
commit 9387640676
No known key found for this signature in database
GPG Key ID: 3248E46B6BB8C7F7

@ -15,14 +15,11 @@ import (
composecli "github.com/compose-spec/compose-go/cli"
"github.com/docker/buildx/bake/hclparser"
"github.com/docker/buildx/build"
cbuild "github.com/docker/buildx/controller/build"
controllerapi "github.com/docker/buildx/controller/pb"
"github.com/docker/buildx/util/buildflags"
"github.com/docker/buildx/util/platformutil"
"github.com/docker/cli/cli/config"
hcl "github.com/hashicorp/hcl/v2"
"github.com/moby/buildkit/client/llb"
"github.com/moby/buildkit/session/auth/authprovider"
"github.com/pkg/errors"
"github.com/zclconf/go-cty/cty"
"github.com/zclconf/go-cty/cty/convert"
@ -914,7 +911,11 @@ func (t *Target) GetName(ectx *hcl.EvalContext, block *hcl.Block, loadDeps func(
func TargetsToBuildOpt(m map[string]*Target, inp *Input) (map[string]build.Options, error) {
m2 := make(map[string]build.Options, len(m))
for k, v := range m {
bo, err := toBuildOpt(v, inp)
opts, err := toControllerOpt(v, inp)
if err != nil {
return nil, err
}
bo, err := cbuild.ToBuildOpts(*opts, nil)
if err != nil {
return nil, err
}
@ -923,14 +924,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 *controllerapi.Inputs, inp *Input) error {
if inp == nil || inp.State == nil {
return
return nil
}
for k, v := range t.NamedContexts {
if v.Path == "." {
t.NamedContexts[k] = build.NamedContext{Path: inp.URL}
t.NamedContexts[k] = &controllerapi.NamedContext{Path: inp.URL}
}
if strings.HasPrefix(v.Path, "cwd://") || strings.HasPrefix(v.Path, "target:") || strings.HasPrefix(v.Path, "docker-image:") {
continue
@ -939,18 +940,22 @@ 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}
def, err := st.Marshal(context.TODO())
if err != nil {
return err
}
t.NamedContexts[k] = &controllerapi.NamedContext{Definition: def.ToPB()}
}
if t.ContextPath == "." {
t.ContextPath = inp.URL
return
return nil
}
if strings.HasPrefix(t.ContextPath, "cwd://") {
return
return nil
}
if build.IsRemoteURL(t.ContextPath) {
return
return nil
}
st := llb.Scratch().File(
llb.Copy(*inp.State, t.ContextPath, "/", &llb.CopyInfo{
@ -958,13 +963,18 @@ func updateContext(t *build.Inputs, inp *Input) {
}),
llb.WithCustomNamef("set context to %s", t.ContextPath),
)
t.ContextState = &st
def, err := st.Marshal(context.TODO())
if err != nil {
return err
}
t.ContextDefinition = def.ToPB()
return nil
}
// 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 controllerapi.Inputs, inp *Input) error {
if inp == nil || inp.State == nil {
return nil
}
@ -973,13 +983,13 @@ func validateContextsEntitlements(t build.Inputs, inp *Input) error {
return nil
}
}
if t.ContextState == nil {
if t.ContextDefinition == nil {
if err := checkPath(t.ContextPath); err != nil {
return err
}
}
for _, v := range t.NamedContexts {
if v.State != nil {
if v.Definition != nil {
continue
}
if err := checkPath(v.Path); err != nil {
@ -1019,7 +1029,9 @@ func checkPath(p string) error {
return nil
}
func toBuildOpt(t *Target, inp *Input) (*build.Options, error) {
func toControllerOpt(t *Target, inp *Input) (*controllerapi.BuildOptions, error) {
var err error
if v := t.Context; v != nil && *v == "-" {
return nil, errors.Errorf("context from stdin not allowed in bake")
}
@ -1039,24 +1051,24 @@ func toBuildOpt(t *Target, inp *Input) (*build.Options, error) {
dockerfilePath = *t.Dockerfile
}
bi := build.Inputs{
bi := controllerapi.Inputs{
ContextPath: contextPath,
DockerfilePath: dockerfilePath,
DockerfileName: dockerfilePath,
NamedContexts: toNamedContexts(t.Contexts),
}
if t.DockerfileInline != nil {
bi.DockerfileInline = *t.DockerfileInline
}
updateContext(&bi, inp)
if !build.IsRemoteURL(bi.ContextPath) && bi.ContextState == nil && !path.IsAbs(bi.DockerfilePath) {
bi.DockerfilePath = path.Join(bi.ContextPath, bi.DockerfilePath)
if !build.IsRemoteURL(bi.ContextPath) && bi.ContextDefinition == nil && !path.IsAbs(bi.DockerfileName) {
bi.DockerfileName = path.Join(bi.ContextPath, bi.DockerfileName)
}
if strings.HasPrefix(bi.ContextPath, "cwd://") {
bi.ContextPath = path.Clean(strings.TrimPrefix(bi.ContextPath, "cwd://"))
}
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] = &controllerapi.NamedContext{Path: path.Clean(strings.TrimPrefix(v.Path, "cwd://"))}
}
}
@ -1095,87 +1107,61 @@ func toBuildOpt(t *Target, inp *Input) (*build.Options, error) {
networkMode = *t.NetworkMode
}
bo := &build.Options{
Inputs: bi,
opts := &controllerapi.BuildOptions{
Inputs: &bi,
Opts: &controllerapi.CommonOptions{
NoCache: noCache,
Pull: pull,
Linked: t.linked,
},
Tags: t.Tags,
BuildArgs: args,
Labels: labels,
NoCache: noCache,
NoCacheFilter: t.NoCacheFilter,
Pull: pull,
NetworkMode: networkMode,
Linked: t.linked,
Platforms: t.Platforms,
}
platforms, err := platformutil.Parse(t.Platforms)
if err != nil {
return nil, err
if t.Target != nil {
opts.Target = *t.Target
}
bo.Platforms = platforms
dockerConfig := config.LoadDefaultConfigFile(os.Stderr)
bo.Session = append(bo.Session, authprovider.NewDockerAuthProvider(dockerConfig))
secrets, err := buildflags.ParseSecretSpecs(t.Secrets)
if err != nil {
return nil, err
}
secretAttachment, err := controllerapi.CreateSecrets(secrets)
opts.Secrets, err = buildflags.ParseSecretSpecs(t.Secrets)
if err != nil {
return nil, err
}
bo.Session = append(bo.Session, secretAttachment)
sshSpecs, err := buildflags.ParseSSHSpecs(t.SSH)
if err != nil {
return nil, err
}
if len(sshSpecs) == 0 && (buildflags.IsGitSSH(bi.ContextPath) || (inp != nil && buildflags.IsGitSSH(inp.URL))) {
sshSpecs = append(sshSpecs, &controllerapi.SSH{ID: "default"})
}
sshAttachment, err := controllerapi.CreateSSH(sshSpecs)
opts.SSH, err = buildflags.ParseSSHSpecs(t.SSH)
if err != nil {
return nil, err
}
bo.Session = append(bo.Session, sshAttachment)
if t.Target != nil {
bo.Target = *t.Target
}
cacheImports, err := buildflags.ParseCacheEntry(t.CacheFrom)
opts.CacheFrom, err = buildflags.ParseCacheEntry(t.CacheFrom)
if err != nil {
return nil, err
}
bo.CacheFrom = controllerapi.CreateCaches(cacheImports)
cacheExports, err := buildflags.ParseCacheEntry(t.CacheTo)
opts.CacheTo, err = buildflags.ParseCacheEntry(t.CacheTo)
if err != nil {
return nil, err
}
bo.CacheTo = controllerapi.CreateCaches(cacheExports)
outputs, err := buildflags.ParseExports(t.Outputs)
if err != nil {
return nil, err
}
bo.Exports, err = controllerapi.CreateExports(outputs)
opts.Exports, err = buildflags.ParseExports(t.Outputs)
if err != nil {
return nil, err
}
attests, err := buildflags.ParseAttests(t.Attest)
opts.Attests, err = buildflags.ParseAttests(t.Attest)
if err != nil {
return nil, err
}
bo.Attests = controllerapi.CreateAttestations(attests)
bo.SourcePolicy, err = build.ReadSourcePolicy()
opts.SourcePolicy, err = build.ReadSourcePolicy()
if err != nil {
return nil, err
}
return bo, nil
return opts, nil
}
func defaultTarget() *Target {
@ -1264,10 +1250,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]*controllerapi.NamedContext {
m2 := make(map[string]*controllerapi.NamedContext, len(m))
for k, v := range m {
m2[k] = build.NamedContext{Path: v}
m2[k] = &controllerapi.NamedContext{Path: v}
}
return m2
}

Loading…
Cancel
Save