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>
This commit is contained in:
committed by
CrazyMax
parent
3c3e4a6d5f
commit
9387640676
162
bake/bake.go
162
bake/bake.go
@@ -15,14 +15,11 @@ import (
|
|||||||
composecli "github.com/compose-spec/compose-go/cli"
|
composecli "github.com/compose-spec/compose-go/cli"
|
||||||
"github.com/docker/buildx/bake/hclparser"
|
"github.com/docker/buildx/bake/hclparser"
|
||||||
"github.com/docker/buildx/build"
|
"github.com/docker/buildx/build"
|
||||||
|
cbuild "github.com/docker/buildx/controller/build"
|
||||||
controllerapi "github.com/docker/buildx/controller/pb"
|
controllerapi "github.com/docker/buildx/controller/pb"
|
||||||
"github.com/docker/buildx/util/buildflags"
|
"github.com/docker/buildx/util/buildflags"
|
||||||
"github.com/docker/buildx/util/platformutil"
|
|
||||||
|
|
||||||
"github.com/docker/cli/cli/config"
|
|
||||||
hcl "github.com/hashicorp/hcl/v2"
|
hcl "github.com/hashicorp/hcl/v2"
|
||||||
"github.com/moby/buildkit/client/llb"
|
"github.com/moby/buildkit/client/llb"
|
||||||
"github.com/moby/buildkit/session/auth/authprovider"
|
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"github.com/zclconf/go-cty/cty"
|
"github.com/zclconf/go-cty/cty"
|
||||||
"github.com/zclconf/go-cty/cty/convert"
|
"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) {
|
func TargetsToBuildOpt(m map[string]*Target, inp *Input) (map[string]build.Options, error) {
|
||||||
m2 := make(map[string]build.Options, len(m))
|
m2 := make(map[string]build.Options, len(m))
|
||||||
for k, v := range 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 {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -923,14 +924,14 @@ func TargetsToBuildOpt(m map[string]*Target, inp *Input) (map[string]build.Optio
|
|||||||
return m2, nil
|
return m2, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func updateContext(t *build.Inputs, inp *Input) {
|
func updateContext(t *controllerapi.Inputs, inp *Input) error {
|
||||||
if inp == nil || inp.State == nil {
|
if inp == nil || inp.State == nil {
|
||||||
return
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
for k, v := range t.NamedContexts {
|
for k, v := range t.NamedContexts {
|
||||||
if v.Path == "." {
|
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:") {
|
if strings.HasPrefix(v.Path, "cwd://") || strings.HasPrefix(v.Path, "target:") || strings.HasPrefix(v.Path, "docker-image:") {
|
||||||
continue
|
continue
|
||||||
@@ -939,18 +940,22 @@ func updateContext(t *build.Inputs, inp *Input) {
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
st := llb.Scratch().File(llb.Copy(*inp.State, v.Path, "/"), llb.WithCustomNamef("set context %s to %s", k, v.Path))
|
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 == "." {
|
if t.ContextPath == "." {
|
||||||
t.ContextPath = inp.URL
|
t.ContextPath = inp.URL
|
||||||
return
|
return nil
|
||||||
}
|
}
|
||||||
if strings.HasPrefix(t.ContextPath, "cwd://") {
|
if strings.HasPrefix(t.ContextPath, "cwd://") {
|
||||||
return
|
return nil
|
||||||
}
|
}
|
||||||
if build.IsRemoteURL(t.ContextPath) {
|
if build.IsRemoteURL(t.ContextPath) {
|
||||||
return
|
return nil
|
||||||
}
|
}
|
||||||
st := llb.Scratch().File(
|
st := llb.Scratch().File(
|
||||||
llb.Copy(*inp.State, t.ContextPath, "/", &llb.CopyInfo{
|
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),
|
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
|
// validateContextsEntitlements is a basic check to ensure contexts do not
|
||||||
// escape local directories when loaded from remote sources. This is to be
|
// escape local directories when loaded from remote sources. This is to be
|
||||||
// replaced with proper entitlements support in the future.
|
// 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 {
|
if inp == nil || inp.State == nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@@ -973,13 +983,13 @@ func validateContextsEntitlements(t build.Inputs, inp *Input) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if t.ContextState == nil {
|
if t.ContextDefinition == nil {
|
||||||
if err := checkPath(t.ContextPath); err != nil {
|
if err := checkPath(t.ContextPath); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for _, v := range t.NamedContexts {
|
for _, v := range t.NamedContexts {
|
||||||
if v.State != nil {
|
if v.Definition != nil {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if err := checkPath(v.Path); err != nil {
|
if err := checkPath(v.Path); err != nil {
|
||||||
@@ -1019,7 +1029,9 @@ func checkPath(p string) error {
|
|||||||
return nil
|
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 == "-" {
|
if v := t.Context; v != nil && *v == "-" {
|
||||||
return nil, errors.Errorf("context from stdin not allowed in bake")
|
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
|
dockerfilePath = *t.Dockerfile
|
||||||
}
|
}
|
||||||
|
|
||||||
bi := build.Inputs{
|
bi := controllerapi.Inputs{
|
||||||
ContextPath: contextPath,
|
ContextPath: contextPath,
|
||||||
DockerfilePath: dockerfilePath,
|
DockerfileName: dockerfilePath,
|
||||||
NamedContexts: toNamedContexts(t.Contexts),
|
NamedContexts: toNamedContexts(t.Contexts),
|
||||||
}
|
}
|
||||||
if t.DockerfileInline != nil {
|
if t.DockerfileInline != nil {
|
||||||
bi.DockerfileInline = *t.DockerfileInline
|
bi.DockerfileInline = *t.DockerfileInline
|
||||||
}
|
}
|
||||||
updateContext(&bi, inp)
|
updateContext(&bi, inp)
|
||||||
if !build.IsRemoteURL(bi.ContextPath) && bi.ContextState == nil && !path.IsAbs(bi.DockerfilePath) {
|
if !build.IsRemoteURL(bi.ContextPath) && bi.ContextDefinition == nil && !path.IsAbs(bi.DockerfileName) {
|
||||||
bi.DockerfilePath = path.Join(bi.ContextPath, bi.DockerfilePath)
|
bi.DockerfileName = path.Join(bi.ContextPath, bi.DockerfileName)
|
||||||
}
|
}
|
||||||
if strings.HasPrefix(bi.ContextPath, "cwd://") {
|
if strings.HasPrefix(bi.ContextPath, "cwd://") {
|
||||||
bi.ContextPath = path.Clean(strings.TrimPrefix(bi.ContextPath, "cwd://"))
|
bi.ContextPath = path.Clean(strings.TrimPrefix(bi.ContextPath, "cwd://"))
|
||||||
}
|
}
|
||||||
for k, v := range bi.NamedContexts {
|
for k, v := range bi.NamedContexts {
|
||||||
if strings.HasPrefix(v.Path, "cwd://") {
|
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
|
networkMode = *t.NetworkMode
|
||||||
}
|
}
|
||||||
|
|
||||||
bo := &build.Options{
|
opts := &controllerapi.BuildOptions{
|
||||||
Inputs: bi,
|
Inputs: &bi,
|
||||||
|
Opts: &controllerapi.CommonOptions{
|
||||||
|
NoCache: noCache,
|
||||||
|
Pull: pull,
|
||||||
|
Linked: t.linked,
|
||||||
|
},
|
||||||
Tags: t.Tags,
|
Tags: t.Tags,
|
||||||
BuildArgs: args,
|
BuildArgs: args,
|
||||||
Labels: labels,
|
Labels: labels,
|
||||||
NoCache: noCache,
|
|
||||||
NoCacheFilter: t.NoCacheFilter,
|
NoCacheFilter: t.NoCacheFilter,
|
||||||
Pull: pull,
|
|
||||||
NetworkMode: networkMode,
|
NetworkMode: networkMode,
|
||||||
Linked: t.linked,
|
Platforms: t.Platforms,
|
||||||
}
|
}
|
||||||
|
|
||||||
platforms, err := platformutil.Parse(t.Platforms)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
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)
|
|
||||||
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)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
bo.Session = append(bo.Session, sshAttachment)
|
|
||||||
|
|
||||||
if t.Target != nil {
|
if t.Target != nil {
|
||||||
bo.Target = *t.Target
|
opts.Target = *t.Target
|
||||||
}
|
}
|
||||||
|
|
||||||
cacheImports, err := buildflags.ParseCacheEntry(t.CacheFrom)
|
opts.Secrets, err = buildflags.ParseSecretSpecs(t.Secrets)
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
bo.CacheFrom = controllerapi.CreateCaches(cacheImports)
|
|
||||||
|
|
||||||
cacheExports, 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)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
attests, err := buildflags.ParseAttests(t.Attest)
|
opts.SSH, err = buildflags.ParseSSHSpecs(t.SSH)
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
bo.Attests = controllerapi.CreateAttestations(attests)
|
|
||||||
|
|
||||||
bo.SourcePolicy, err = build.ReadSourcePolicy()
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return bo, nil
|
opts.CacheFrom, err = buildflags.ParseCacheEntry(t.CacheFrom)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
opts.CacheTo, err = buildflags.ParseCacheEntry(t.CacheTo)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
opts.Exports, err = buildflags.ParseExports(t.Outputs)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
opts.Attests, err = buildflags.ParseAttests(t.Attest)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
opts.SourcePolicy, err = build.ReadSourcePolicy()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return opts, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func defaultTarget() *Target {
|
func defaultTarget() *Target {
|
||||||
@@ -1264,10 +1250,10 @@ func sliceEqual(s1, s2 []string) bool {
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
func toNamedContexts(m map[string]string) map[string]build.NamedContext {
|
func toNamedContexts(m map[string]string) map[string]*controllerapi.NamedContext {
|
||||||
m2 := make(map[string]build.NamedContext, len(m))
|
m2 := make(map[string]*controllerapi.NamedContext, len(m))
|
||||||
for k, v := range m {
|
for k, v := range m {
|
||||||
m2[k] = build.NamedContext{Path: v}
|
m2[k] = &controllerapi.NamedContext{Path: v}
|
||||||
}
|
}
|
||||||
return m2
|
return m2
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user