mirror of
https://gitea.com/Lydanne/buildx.git
synced 2025-07-12 14:37:08 +08:00
controller: remove controller grpc service
Remove the controller grpc service along with associated code related to sessions or remote controllers. Data types that are still used with complicated dependency chains have been kept in the same package for a future refactor. Signed-off-by: Jonathan A. Sternberg <jonathan.sternberg@docker.com>
This commit is contained in:

committed by
Jonathan A. Sternberg

parent
2eaea647d8
commit
2f1be25b8f
@ -34,7 +34,7 @@ const defaultTargetName = "default"
|
||||
// NOTE: When an error happens during the build and this function acquires the debuggable *build.ResultHandle,
|
||||
// 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, *build.Inputs, error) {
|
||||
func RunBuild(ctx context.Context, dockerCli command.Cli, in *Options, inStream io.Reader, progress progress.Writer, generateResult bool) (*client.SolveResponse, *build.ResultHandle, *build.Inputs, error) {
|
||||
if in.NoCache && len(in.NoCacheFilter) > 0 {
|
||||
return nil, nil, nil, errors.Errorf("--no-cache and --no-cache-filter cannot currently be used together")
|
||||
}
|
||||
|
217
controller/build/options.go
Normal file
217
controller/build/options.go
Normal file
@ -0,0 +1,217 @@
|
||||
package build
|
||||
|
||||
import (
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/docker/buildx/controller/pb"
|
||||
sourcepolicy "github.com/moby/buildkit/sourcepolicy/pb"
|
||||
"github.com/moby/buildkit/util/gitutil"
|
||||
)
|
||||
|
||||
type Options struct {
|
||||
ContextPath string
|
||||
DockerfileName string
|
||||
CallFunc *pb.CallFunc
|
||||
NamedContexts map[string]string
|
||||
Allow []string
|
||||
Attests []*pb.Attest
|
||||
BuildArgs map[string]string
|
||||
CacheFrom []*pb.CacheOptionsEntry
|
||||
CacheTo []*pb.CacheOptionsEntry
|
||||
CgroupParent string
|
||||
Exports []*pb.ExportEntry
|
||||
ExtraHosts []string
|
||||
Labels map[string]string
|
||||
NetworkMode string
|
||||
NoCacheFilter []string
|
||||
Platforms []string
|
||||
Secrets []*pb.Secret
|
||||
ShmSize int64
|
||||
SSH []*pb.SSH
|
||||
Tags []string
|
||||
Target string
|
||||
Ulimits *pb.UlimitOpt
|
||||
Builder string
|
||||
NoCache bool
|
||||
Pull bool
|
||||
ExportPush bool
|
||||
ExportLoad bool
|
||||
SourcePolicy *sourcepolicy.Policy
|
||||
Ref string
|
||||
GroupRef string
|
||||
Annotations []string
|
||||
ProvenanceResponseMode string
|
||||
}
|
||||
|
||||
// ResolveOptionPaths resolves all paths contained in BuildOptions
|
||||
// and replaces them to absolute paths.
|
||||
func ResolveOptionPaths(options *Options) (_ *Options, err error) {
|
||||
localContext := false
|
||||
if options.ContextPath != "" && options.ContextPath != "-" {
|
||||
if !isRemoteURL(options.ContextPath) {
|
||||
localContext = true
|
||||
options.ContextPath, err = filepath.Abs(options.ContextPath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
}
|
||||
if options.DockerfileName != "" && options.DockerfileName != "-" {
|
||||
if localContext && !isHTTPURL(options.DockerfileName) {
|
||||
options.DockerfileName, err = filepath.Abs(options.DockerfileName)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var contexts map[string]string
|
||||
for k, v := range options.NamedContexts {
|
||||
if isRemoteURL(v) || strings.HasPrefix(v, "docker-image://") {
|
||||
// url prefix, this is a remote path
|
||||
} else if strings.HasPrefix(v, "oci-layout://") {
|
||||
// oci layout prefix, this is a local path
|
||||
p := strings.TrimPrefix(v, "oci-layout://")
|
||||
p, err = filepath.Abs(p)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
v = "oci-layout://" + p
|
||||
} else {
|
||||
// no prefix, assume local path
|
||||
v, err = filepath.Abs(v)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
if contexts == nil {
|
||||
contexts = make(map[string]string)
|
||||
}
|
||||
contexts[k] = v
|
||||
}
|
||||
options.NamedContexts = contexts
|
||||
|
||||
var cacheFrom []*pb.CacheOptionsEntry
|
||||
for _, co := range options.CacheFrom {
|
||||
switch co.Type {
|
||||
case "local":
|
||||
var attrs map[string]string
|
||||
for k, v := range co.Attrs {
|
||||
if attrs == nil {
|
||||
attrs = make(map[string]string)
|
||||
}
|
||||
switch k {
|
||||
case "src":
|
||||
p := v
|
||||
if p != "" {
|
||||
p, err = filepath.Abs(p)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
attrs[k] = p
|
||||
default:
|
||||
attrs[k] = v
|
||||
}
|
||||
}
|
||||
co.Attrs = attrs
|
||||
cacheFrom = append(cacheFrom, co)
|
||||
default:
|
||||
cacheFrom = append(cacheFrom, co)
|
||||
}
|
||||
}
|
||||
options.CacheFrom = cacheFrom
|
||||
|
||||
var cacheTo []*pb.CacheOptionsEntry
|
||||
for _, co := range options.CacheTo {
|
||||
switch co.Type {
|
||||
case "local":
|
||||
var attrs map[string]string
|
||||
for k, v := range co.Attrs {
|
||||
if attrs == nil {
|
||||
attrs = make(map[string]string)
|
||||
}
|
||||
switch k {
|
||||
case "dest":
|
||||
p := v
|
||||
if p != "" {
|
||||
p, err = filepath.Abs(p)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
attrs[k] = p
|
||||
default:
|
||||
attrs[k] = v
|
||||
}
|
||||
}
|
||||
co.Attrs = attrs
|
||||
cacheTo = append(cacheTo, co)
|
||||
default:
|
||||
cacheTo = append(cacheTo, co)
|
||||
}
|
||||
}
|
||||
options.CacheTo = cacheTo
|
||||
var exports []*pb.ExportEntry
|
||||
for _, e := range options.Exports {
|
||||
if e.Destination != "" && e.Destination != "-" {
|
||||
e.Destination, err = filepath.Abs(e.Destination)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
exports = append(exports, e)
|
||||
}
|
||||
options.Exports = exports
|
||||
|
||||
var secrets []*pb.Secret
|
||||
for _, s := range options.Secrets {
|
||||
if s.FilePath != "" {
|
||||
s.FilePath, err = filepath.Abs(s.FilePath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
secrets = append(secrets, s)
|
||||
}
|
||||
options.Secrets = secrets
|
||||
|
||||
var ssh []*pb.SSH
|
||||
for _, s := range options.SSH {
|
||||
var ps []string
|
||||
for _, pt := range s.Paths {
|
||||
p := pt
|
||||
if p != "" {
|
||||
p, err = filepath.Abs(p)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
ps = append(ps, p)
|
||||
}
|
||||
s.Paths = ps
|
||||
ssh = append(ssh, s)
|
||||
}
|
||||
options.SSH = ssh
|
||||
|
||||
return options, nil
|
||||
}
|
||||
|
||||
// isHTTPURL returns true if the provided str is an HTTP(S) URL by checking if it
|
||||
// has a http:// or https:// scheme. No validation is performed to verify if the
|
||||
// URL is well-formed.
|
||||
func isHTTPURL(str string) bool {
|
||||
return strings.HasPrefix(str, "https://") || strings.HasPrefix(str, "http://")
|
||||
}
|
||||
|
||||
func isRemoteURL(c string) bool {
|
||||
if isHTTPURL(c) {
|
||||
return true
|
||||
}
|
||||
if _, err := gitutil.ParseGitRef(c); err == nil {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
250
controller/build/options_test.go
Normal file
250
controller/build/options_test.go
Normal file
@ -0,0 +1,250 @@
|
||||
package build
|
||||
|
||||
import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
"github.com/docker/buildx/controller/pb"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestResolvePaths(t *testing.T) {
|
||||
tmpwd, err := os.MkdirTemp("", "testresolvepaths")
|
||||
require.NoError(t, err)
|
||||
defer os.Remove(tmpwd)
|
||||
require.NoError(t, os.Chdir(tmpwd))
|
||||
tests := []struct {
|
||||
name string
|
||||
options *Options
|
||||
want *Options
|
||||
}{
|
||||
{
|
||||
name: "contextpath",
|
||||
options: &Options{ContextPath: "test"},
|
||||
want: &Options{ContextPath: filepath.Join(tmpwd, "test")},
|
||||
},
|
||||
{
|
||||
name: "contextpath-cwd",
|
||||
options: &Options{ContextPath: "."},
|
||||
want: &Options{ContextPath: tmpwd},
|
||||
},
|
||||
{
|
||||
name: "contextpath-dash",
|
||||
options: &Options{ContextPath: "-"},
|
||||
want: &Options{ContextPath: "-"},
|
||||
},
|
||||
{
|
||||
name: "contextpath-ssh",
|
||||
options: &Options{ContextPath: "git@github.com:docker/buildx.git"},
|
||||
want: &Options{ContextPath: "git@github.com:docker/buildx.git"},
|
||||
},
|
||||
{
|
||||
name: "dockerfilename",
|
||||
options: &Options{DockerfileName: "test", ContextPath: "."},
|
||||
want: &Options{DockerfileName: filepath.Join(tmpwd, "test"), ContextPath: tmpwd},
|
||||
},
|
||||
{
|
||||
name: "dockerfilename-dash",
|
||||
options: &Options{DockerfileName: "-", ContextPath: "."},
|
||||
want: &Options{DockerfileName: "-", ContextPath: tmpwd},
|
||||
},
|
||||
{
|
||||
name: "dockerfilename-remote",
|
||||
options: &Options{DockerfileName: "test", ContextPath: "git@github.com:docker/buildx.git"},
|
||||
want: &Options{DockerfileName: "test", ContextPath: "git@github.com:docker/buildx.git"},
|
||||
},
|
||||
{
|
||||
name: "contexts",
|
||||
options: &Options{NamedContexts: map[string]string{
|
||||
"a": "test1", "b": "test2",
|
||||
"alpine": "docker-image://alpine@sha256:0123456789", "project": "https://github.com/myuser/project.git",
|
||||
}},
|
||||
want: &Options{NamedContexts: map[string]string{
|
||||
"a": filepath.Join(tmpwd, "test1"), "b": filepath.Join(tmpwd, "test2"),
|
||||
"alpine": "docker-image://alpine@sha256:0123456789", "project": "https://github.com/myuser/project.git",
|
||||
}},
|
||||
},
|
||||
{
|
||||
name: "cache-from",
|
||||
options: &Options{
|
||||
CacheFrom: []*pb.CacheOptionsEntry{
|
||||
{
|
||||
Type: "local",
|
||||
Attrs: map[string]string{"src": "test"},
|
||||
},
|
||||
{
|
||||
Type: "registry",
|
||||
Attrs: map[string]string{"ref": "user/app"},
|
||||
},
|
||||
},
|
||||
},
|
||||
want: &Options{
|
||||
CacheFrom: []*pb.CacheOptionsEntry{
|
||||
{
|
||||
Type: "local",
|
||||
Attrs: map[string]string{"src": filepath.Join(tmpwd, "test")},
|
||||
},
|
||||
{
|
||||
Type: "registry",
|
||||
Attrs: map[string]string{"ref": "user/app"},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "cache-to",
|
||||
options: &Options{
|
||||
CacheTo: []*pb.CacheOptionsEntry{
|
||||
{
|
||||
Type: "local",
|
||||
Attrs: map[string]string{"dest": "test"},
|
||||
},
|
||||
{
|
||||
Type: "registry",
|
||||
Attrs: map[string]string{"ref": "user/app"},
|
||||
},
|
||||
},
|
||||
},
|
||||
want: &Options{
|
||||
CacheTo: []*pb.CacheOptionsEntry{
|
||||
{
|
||||
Type: "local",
|
||||
Attrs: map[string]string{"dest": filepath.Join(tmpwd, "test")},
|
||||
},
|
||||
{
|
||||
Type: "registry",
|
||||
Attrs: map[string]string{"ref": "user/app"},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "exports",
|
||||
options: &Options{
|
||||
Exports: []*pb.ExportEntry{
|
||||
{
|
||||
Type: "local",
|
||||
Destination: "-",
|
||||
},
|
||||
{
|
||||
Type: "local",
|
||||
Destination: "test1",
|
||||
},
|
||||
{
|
||||
Type: "tar",
|
||||
Destination: "test3",
|
||||
},
|
||||
{
|
||||
Type: "oci",
|
||||
Destination: "-",
|
||||
},
|
||||
{
|
||||
Type: "docker",
|
||||
Destination: "test4",
|
||||
},
|
||||
{
|
||||
Type: "image",
|
||||
Attrs: map[string]string{"push": "true"},
|
||||
},
|
||||
},
|
||||
},
|
||||
want: &Options{
|
||||
Exports: []*pb.ExportEntry{
|
||||
{
|
||||
Type: "local",
|
||||
Destination: "-",
|
||||
},
|
||||
{
|
||||
Type: "local",
|
||||
Destination: filepath.Join(tmpwd, "test1"),
|
||||
},
|
||||
{
|
||||
Type: "tar",
|
||||
Destination: filepath.Join(tmpwd, "test3"),
|
||||
},
|
||||
{
|
||||
Type: "oci",
|
||||
Destination: "-",
|
||||
},
|
||||
{
|
||||
Type: "docker",
|
||||
Destination: filepath.Join(tmpwd, "test4"),
|
||||
},
|
||||
{
|
||||
Type: "image",
|
||||
Attrs: map[string]string{"push": "true"},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "secrets",
|
||||
options: &Options{
|
||||
Secrets: []*pb.Secret{
|
||||
{
|
||||
FilePath: "test1",
|
||||
},
|
||||
{
|
||||
ID: "val",
|
||||
Env: "a",
|
||||
},
|
||||
{
|
||||
ID: "test",
|
||||
FilePath: "test3",
|
||||
},
|
||||
},
|
||||
},
|
||||
want: &Options{
|
||||
Secrets: []*pb.Secret{
|
||||
{
|
||||
FilePath: filepath.Join(tmpwd, "test1"),
|
||||
},
|
||||
{
|
||||
ID: "val",
|
||||
Env: "a",
|
||||
},
|
||||
{
|
||||
ID: "test",
|
||||
FilePath: filepath.Join(tmpwd, "test3"),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "ssh",
|
||||
options: &Options{
|
||||
SSH: []*pb.SSH{
|
||||
{
|
||||
ID: "default",
|
||||
Paths: []string{"test1", "test2"},
|
||||
},
|
||||
{
|
||||
ID: "a",
|
||||
Paths: []string{"test3"},
|
||||
},
|
||||
},
|
||||
},
|
||||
want: &Options{
|
||||
SSH: []*pb.SSH{
|
||||
{
|
||||
ID: "default",
|
||||
Paths: []string{filepath.Join(tmpwd, "test1"), filepath.Join(tmpwd, "test2")},
|
||||
},
|
||||
{
|
||||
ID: "a",
|
||||
Paths: []string{filepath.Join(tmpwd, "test3")},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
tt := tt
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
got, err := ResolveOptionPaths(tt.options)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, tt.want, got)
|
||||
})
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user