Bundle is not a command anymore
Code moved to packager Signed-off-by: Nicolas De Loof <nicolas.deloof@gmail.com>
This commit is contained in:
Родитель
e4fd0c8a95
Коммит
9d6eb024d2
|
@ -236,7 +236,7 @@
|
|||
version = "v0.3.2-beta1"
|
||||
|
||||
[[projects]]
|
||||
digest = "1:fc67ad7796e9571f4b9986e7ef73160304e69c3157929518a9ddfe9735322459"
|
||||
digest = "1:6093483b2ea90f1c0c5ec0fd75778650031bc3da75526b1bd87309d22e1e7d6b"
|
||||
name = "github.com/docker/buildx"
|
||||
packages = [
|
||||
"bake",
|
||||
|
@ -248,7 +248,8 @@
|
|||
"util/progress",
|
||||
]
|
||||
pruneopts = "NUT"
|
||||
revision = "96fb17b71125d4a11c904bd8a4298bac3b9e11e9"
|
||||
revision = "6db68d029599c6710a32aa7adcba8e5a344795a7"
|
||||
version = "v0.3.1"
|
||||
|
||||
[[projects]]
|
||||
digest = "1:bc88d135d4f5d9a0968a213b3b2d786d1e216b9f10c30720f4d0d4976346732b"
|
||||
|
@ -712,7 +713,7 @@
|
|||
version = "v1.1.2"
|
||||
|
||||
[[projects]]
|
||||
digest = "1:4c3f5dc296bad571948333726a115427bab9caeeb732828d8f8f684a005557aa"
|
||||
digest = "1:31d7e51628b4f5ed783d6923bac666dad0cad3ab6767477efc9c01c642a61f61"
|
||||
name = "github.com/moby/buildkit"
|
||||
packages = [
|
||||
"api/services/control",
|
||||
|
@ -748,7 +749,8 @@
|
|||
"util/system",
|
||||
]
|
||||
pruneopts = "NUT"
|
||||
revision = "f238f1efb04f00bf0cc147141fda9ddb55c8bc49"
|
||||
revision = "ae10b292fefb00e0fbf9fecd1419c5f252e58895"
|
||||
version = "v0.6.2"
|
||||
|
||||
[[projects]]
|
||||
digest = "1:2f42fa12d6911c7b7659738758631bec870b7e9b4c6be5444f963cdcfccc191f"
|
||||
|
@ -1459,10 +1461,11 @@
|
|||
"github.com/docker/cli/cli/context/kubernetes",
|
||||
"github.com/docker/cli/cli/context/store",
|
||||
"github.com/docker/cli/cli/flags",
|
||||
"github.com/docker/cli/cli/streams",
|
||||
"github.com/docker/cli/opts",
|
||||
"github.com/docker/cnab-to-oci/converter",
|
||||
"github.com/docker/cnab-to-oci/remotes",
|
||||
"github.com/docker/distribution/manifest/manifestlist",
|
||||
"github.com/docker/distribution/manifest/schema2",
|
||||
"github.com/docker/distribution/reference",
|
||||
"github.com/docker/docker/api/types",
|
||||
"github.com/docker/docker/api/types/container",
|
||||
|
|
|
@ -23,11 +23,11 @@ required = ["github.com/wadey/gocovmerge"]
|
|||
|
||||
[[constraint]]
|
||||
name = "github.com/docker/buildx"
|
||||
revision = "96fb17b71125d4a11c904bd8a4298bac3b9e11e9"
|
||||
version = "=v0.3.1"
|
||||
|
||||
[[override]]
|
||||
name = "github.com/moby/buildkit"
|
||||
revision = "f238f1efb04f00bf0cc147141fda9ddb55c8bc49"
|
||||
version = "=v0.6.2"
|
||||
|
||||
[[override]]
|
||||
name = "github.com/jaguilar/vt100"
|
||||
|
|
|
@ -4,8 +4,8 @@ import (
|
|||
"encoding/json"
|
||||
"github.com/deislabs/cnab-go/bundle"
|
||||
"gotest.tools/assert"
|
||||
"gotest.tools/fs"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path"
|
||||
"testing"
|
||||
|
||||
|
@ -17,10 +17,9 @@ func TestBuild(t *testing.T) {
|
|||
defer cleanup()
|
||||
|
||||
testDir := path.Join("testdata", "build")
|
||||
tmp, err := ioutil.TempDir("","")
|
||||
assert.NilError(t, err)
|
||||
defer os.Remove(tmp)
|
||||
f := path.Join(tmp, "bundle.json")
|
||||
dir := fs.NewDir(t, "test-name")
|
||||
defer dir.Remove()
|
||||
f := dir.Join("bundle.json")
|
||||
cmd.Command = dockerCli.Command("app", "build", path.Join(testDir, "single"), "--output", f)
|
||||
icmd.RunCmd(cmd).Assert(t, icmd.Success)
|
||||
|
||||
|
|
|
@ -5,8 +5,11 @@ import (
|
|||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"github.com/deislabs/cnab-go/bundle"
|
||||
"github.com/docker/app/internal/packager"
|
||||
"github.com/docker/app/types"
|
||||
"github.com/docker/distribution/reference"
|
||||
"github.com/moby/buildkit/client"
|
||||
"github.com/moby/buildkit/session"
|
||||
"github.com/moby/buildkit/session/auth/authprovider"
|
||||
"github.com/opencontainers/go-digest"
|
||||
|
@ -26,7 +29,6 @@ import (
|
|||
_ "github.com/docker/buildx/driver/docker" // required to get default driver registered, see driver/docker/factory.go:14
|
||||
"github.com/docker/cli/cli"
|
||||
"github.com/docker/cli/cli/command"
|
||||
dockerclient "github.com/docker/docker/client"
|
||||
"github.com/moby/buildkit/util/appcontext"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
@ -45,7 +47,7 @@ func buildCmd(dockerCli command.Cli) *cobra.Command {
|
|||
Use: "build [APPLICATION]",
|
||||
Short: "Build service images for the application",
|
||||
Example: `$ docker app build myapp.dockerapp`,
|
||||
Args: cli.RequiresRangeArgs(1, 1),
|
||||
Args: cli.ExactArgs(1),
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
tag, err := runBuild(dockerCli, args[0], opts)
|
||||
if err == nil {
|
||||
|
@ -73,33 +75,20 @@ func runBuild(dockerCli command.Cli, application string, opt buildOptions) (refe
|
|||
defer app.Cleanup()
|
||||
appname := app.Name
|
||||
|
||||
bundle, err := makeBundleFromApp(dockerCli, app, nil)
|
||||
bundle, err := packager.MakeBundleFromApp(dockerCli, app, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
ctx := appcontext.Context()
|
||||
|
||||
compose, err := bake.ParseCompose(app.Composes()[0]) // Fixme can have > 1 composes ?
|
||||
targets, err := parseCompose(app)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
targets := map[string]bake.Target{}
|
||||
for _, n := range compose.ResolveGroup("default") {
|
||||
t, err := compose.ResolveTarget(n)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if t != nil {
|
||||
targets[n] = *t
|
||||
}
|
||||
}
|
||||
|
||||
for service, t := range targets {
|
||||
if strings.HasPrefix(*t.Context, ".") {
|
||||
// Relative path in compose file under x.dockerapp refers to parent folder
|
||||
// FIXME docker app init should maybe udate them ?
|
||||
// FIXME docker app init should maybe update them ?
|
||||
path, err := filepath.Abs(appname + "/../" + (*t.Context)[1:])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -108,33 +97,19 @@ func runBuild(dockerCli command.Cli, application string, opt buildOptions) (refe
|
|||
targets[service] = t
|
||||
}
|
||||
}
|
||||
|
||||
if logrus.IsLevelEnabled(logrus.DebugLevel) {
|
||||
dt, err := json.MarshalIndent(targets, "", " ")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
logrus.Debug(string(dt))
|
||||
}
|
||||
debugTargets(targets)
|
||||
|
||||
buildopts, err := bake.TargetsToBuildOpt(targets, opt.noCache, opt.pull)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
buildContext := bytes.NewBuffer(nil)
|
||||
if err := packager.PackInvocationImageContext(dockerCli, app, buildContext); err != nil {
|
||||
buildopts["invocation-image"], err = createInvocationImageBuildOptions(dockerCli, app)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
buildopts["invocation-image"] = build.Options{
|
||||
Inputs: build.Inputs{
|
||||
InStream: buildContext,
|
||||
ContextPath: "-",
|
||||
},
|
||||
Session: []session.Attachable{authprovider.NewDockerAuthProvider(os.Stderr)},
|
||||
}
|
||||
|
||||
ctx := appcontext.Context()
|
||||
d, err := driver.GetDriver(ctx, "buildx_buildkit_default", nil, dockerCli.Client(), nil, "", nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -146,23 +121,19 @@ func runBuild(dockerCli command.Cli, application string, opt buildOptions) (refe
|
|||
},
|
||||
}
|
||||
|
||||
ctx2, cancel := context.WithCancel(context.TODO())
|
||||
ctx2, cancel := context.WithCancel(ctx)
|
||||
defer cancel()
|
||||
|
||||
pw := progress.NewPrinter(ctx2, os.Stderr, opt.progress)
|
||||
resp, err := build.Build(ctx2, driverInfo, buildopts, dockerAPI(dockerCli), dockerCli.ConfigFile(), pw)
|
||||
|
||||
// We rely on buildx "docker" builder integrated in docker engine, so don't nee a DockerAPI here
|
||||
resp, err := build.Build(ctx2, driverInfo, buildopts, nil, dockerCli.ConfigFile(), pw)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
fmt.Println("Successfully built service images")
|
||||
if logrus.IsLevelEnabled(logrus.DebugLevel) {
|
||||
dt, err := json.MarshalIndent(resp, "", " ")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
logrus.Debug(string(dt))
|
||||
}
|
||||
debugSolveResponses(resp)
|
||||
|
||||
for service, r := range resp {
|
||||
digest := r.ExporterResponse["containerimage.digest"]
|
||||
|
@ -175,33 +146,21 @@ func runBuild(dockerCli command.Cli, application string, opt buildOptions) (refe
|
|||
image.Digest = digest
|
||||
bundle.Images[service] = image
|
||||
}
|
||||
fmt.Printf(" - %s : %s\n", service, digest)
|
||||
}
|
||||
|
||||
if logrus.IsLevelEnabled(logrus.DebugLevel) {
|
||||
dt, err := json.MarshalIndent(resp, "", " ")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
logrus.Debug(string(dt))
|
||||
fmt.Fprintf(dockerCli.Out(), " - %s : %s\n", service, digest)
|
||||
}
|
||||
debugBundle(bundle)
|
||||
|
||||
var ref reference.Named
|
||||
ref, err = getNamedTagged(opt.tag)
|
||||
ref, err = packager.GetNamedTagged(opt.tag)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if ref == nil {
|
||||
b := bytes.Buffer{}
|
||||
_, err := bundle.WriteTo(&b)
|
||||
if err != nil {
|
||||
if ref, err = computeDigest(bundle); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
digest := digest.SHA256.FromBytes(b.Bytes())
|
||||
ref = sha{digest}
|
||||
}
|
||||
|
||||
|
||||
if opt.out != "" {
|
||||
b, err := json.MarshalIndent(bundle, "", " ")
|
||||
if err != nil {
|
||||
|
@ -215,45 +174,110 @@ func runBuild(dockerCli command.Cli, application string, opt buildOptions) (refe
|
|||
return ref, err
|
||||
}
|
||||
|
||||
if err := persistInBundleStore(ref, bundle); err != nil {
|
||||
if err := packager.PersistInBundleStore(ref, bundle); err != nil {
|
||||
return ref, err
|
||||
}
|
||||
|
||||
return ref, nil
|
||||
}
|
||||
|
||||
func computeDigest(bundle *bundle.Bundle) (reference.Named, error) {
|
||||
b := bytes.Buffer{}
|
||||
_, err := bundle.WriteTo(&b)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
digest := digest.SHA256.FromBytes(b.Bytes())
|
||||
ref := sha{digest}
|
||||
return ref, nil
|
||||
}
|
||||
|
||||
func createInvocationImageBuildOptions(dockerCli command.Cli, app *types.App) (build.Options, error) {
|
||||
buildContext := bytes.NewBuffer(nil)
|
||||
if err := packager.PackInvocationImageContext(dockerCli, app, buildContext); err != nil {
|
||||
return build.Options{}, err
|
||||
}
|
||||
return build.Options{
|
||||
Inputs: build.Inputs{
|
||||
InStream: buildContext,
|
||||
ContextPath: "-",
|
||||
},
|
||||
Session: []session.Attachable{authprovider.NewDockerAuthProvider(os.Stderr)},
|
||||
}, nil
|
||||
}
|
||||
|
||||
func debugTargets(targets map[string]bake.Target) {
|
||||
if logrus.IsLevelEnabled(logrus.DebugLevel) {
|
||||
dt, err := json.MarshalIndent(targets, "", " ")
|
||||
if err != nil {
|
||||
logrus.Debugf("Failed to marshal Buildx response: %s", err.Error())
|
||||
} else {
|
||||
logrus.Debug(string(dt))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func debugBundle(bundle *bundle.Bundle) {
|
||||
if logrus.IsLevelEnabled(logrus.DebugLevel) {
|
||||
dt, err := json.MarshalIndent(bundle, "", " ")
|
||||
if err != nil {
|
||||
logrus.Debugf("Failed to marshal Bundle: %s", err.Error())
|
||||
} else {
|
||||
logrus.Debug(string(dt))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func debugSolveResponses(resp map[string]*client.SolveResponse) {
|
||||
if logrus.IsLevelEnabled(logrus.DebugLevel) {
|
||||
dt, err := json.MarshalIndent(resp, "", " ")
|
||||
if err != nil {
|
||||
logrus.Debugf("Failed to marshal Buildx response: %s", err.Error())
|
||||
} else {
|
||||
logrus.Debug(string(dt))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// parseCompose do parse app compose file and extract buildx targets
|
||||
func parseCompose(app *types.App) (map[string]bake.Target, error) {
|
||||
compose, err := bake.ParseCompose(app.Composes()[0])
|
||||
// Fixme can have > 1 composes ?
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
targets := map[string]bake.Target{}
|
||||
for _, n := range compose.ResolveGroup("default") {
|
||||
t, err := compose.ResolveTarget(n)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if t != nil {
|
||||
targets[n] = *t
|
||||
}
|
||||
}
|
||||
return targets, nil
|
||||
}
|
||||
|
||||
|
||||
type sha struct {
|
||||
d digest.Digest
|
||||
}
|
||||
var _ reference.Named = sha{""}
|
||||
var _ reference.Digested = sha{""}
|
||||
|
||||
// Digest implement Digested.Digest()
|
||||
func (s sha) Digest() digest.Digest {
|
||||
return s.d
|
||||
}
|
||||
|
||||
// Digest implement Named.String()
|
||||
func (s sha) String() string {
|
||||
return s.d.String()
|
||||
}
|
||||
|
||||
// Digest implement Named.Name()
|
||||
func (s sha) Name() string {
|
||||
return s.d.String()
|
||||
}
|
||||
|
||||
var _ reference.Named = sha{""}
|
||||
var _ reference.Digested = sha{""}
|
||||
|
||||
|
||||
/// FIXME copy from vendor/github.com/docker/buildx/commands/util.go:318 could probably be made public
|
||||
func dockerAPI(dockerCli command.Cli) *api {
|
||||
return &api{dockerCli: dockerCli}
|
||||
}
|
||||
|
||||
type api struct {
|
||||
dockerCli command.Cli
|
||||
}
|
||||
|
||||
func (a *api) DockerAPI(name string) (dockerclient.APIClient, error) {
|
||||
if name == "" {
|
||||
name = a.dockerCli.CurrentContext()
|
||||
}
|
||||
return nil, fmt.Errorf("Only support default context in this prototype")
|
||||
}
|
||||
|
|
|
@ -239,7 +239,7 @@ func extractAndLoadAppBasedBundle(dockerCli command.Cli, name string) (*bundle.B
|
|||
return nil, "", err
|
||||
}
|
||||
defer app.Cleanup()
|
||||
bndl, err := makeBundleFromApp(dockerCli, app, nil)
|
||||
bndl, err := packager.MakeBundleFromApp(dockerCli, app, nil)
|
||||
return bndl, "", err
|
||||
}
|
||||
|
||||
|
|
|
@ -4,6 +4,7 @@ import (
|
|||
"bytes"
|
||||
"context"
|
||||
"fmt"
|
||||
"github.com/docker/app/internal/packager"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
|
@ -202,7 +203,7 @@ func shouldRetagInvocationImage(meta metadata.AppMetadata, bndl *bundle.Bundle,
|
|||
imgName := tagOverride
|
||||
var err error
|
||||
if imgName == "" {
|
||||
imgName, err = makeCNABImageName(meta.Name, meta.Version, "")
|
||||
imgName, err = packager.MakeCNABImageName(meta.Name, meta.Version, "")
|
||||
if err != nil {
|
||||
return retagResult{}, err
|
||||
}
|
||||
|
|
|
@ -1,11 +1,10 @@
|
|||
package commands
|
||||
package packager
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"fmt"
|
||||
"github.com/deislabs/cnab-go/bundle"
|
||||
"github.com/docker/app/internal/packager"
|
||||
"github.com/docker/app/internal/store"
|
||||
"github.com/docker/app/types"
|
||||
"github.com/docker/app/types/metadata"
|
||||
|
@ -19,16 +18,16 @@ import (
|
|||
"io/ioutil"
|
||||
)
|
||||
|
||||
func makeBundleFromApp(dockerCli command.Cli, app *types.App, refOverride reference.NamedTagged) (*bundle.Bundle, error) {
|
||||
func MakeBundleFromApp(dockerCli command.Cli, app *types.App, refOverride reference.NamedTagged) (*bundle.Bundle, error) {
|
||||
logrus.Debug("Making app bundle")
|
||||
meta := app.Metadata()
|
||||
invocationImageName, err := makeInvocationImageName(meta, refOverride)
|
||||
invocationImageName, err := MakeInvocationImageName(meta, refOverride)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
buildContext := bytes.NewBuffer(nil)
|
||||
if err := packager.PackInvocationImageContext(dockerCli, app, buildContext); err != nil {
|
||||
if err := PackInvocationImageContext(dockerCli, app, buildContext); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
|
@ -46,23 +45,23 @@ func makeBundleFromApp(dockerCli command.Cli, app *types.App, refOverride refere
|
|||
if err := jsonmessage.DisplayJSONMessagesStream(buildResp.Body, ioutil.Discard, 0, false, func(jsonmessage.JSONMessage) {}); err != nil {
|
||||
// If the invocation image can't be found we will get an error of the form:
|
||||
// manifest for docker/cnab-app-base:v0.6.0-202-gbaf0b246c7 not found
|
||||
if err.Error() == fmt.Sprintf("manifest for %s not found", packager.BaseInvocationImage(dockerCli)) {
|
||||
return nil, fmt.Errorf("unable to resolve Docker App base image: %s", packager.BaseInvocationImage(dockerCli))
|
||||
if err.Error() == fmt.Sprintf("manifest for %s not found", BaseInvocationImage(dockerCli)) {
|
||||
return nil, fmt.Errorf("unable to resolve Docker App base image: %s", BaseInvocationImage(dockerCli))
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return packager.ToCNAB(app, invocationImageName)
|
||||
return ToCNAB(app, invocationImageName)
|
||||
}
|
||||
|
||||
func makeInvocationImageName(meta metadata.AppMetadata, refOverride reference.NamedTagged) (string, error) {
|
||||
func MakeInvocationImageName(meta metadata.AppMetadata, refOverride reference.NamedTagged) (string, error) {
|
||||
if refOverride != nil {
|
||||
return makeCNABImageName(reference.FamiliarName(refOverride), refOverride.Tag(), "-invoc")
|
||||
return MakeCNABImageName(reference.FamiliarName(refOverride), refOverride.Tag(), "-invoc")
|
||||
}
|
||||
return makeCNABImageName(meta.Name, meta.Version, "-invoc")
|
||||
return MakeCNABImageName(meta.Name, meta.Version, "-invoc")
|
||||
}
|
||||
|
||||
func makeCNABImageName(appName, appVersion, suffix string) (string, error) {
|
||||
func MakeCNABImageName(appName, appVersion, suffix string) (string, error) {
|
||||
name := fmt.Sprintf("%s:%s%s", appName, appVersion, suffix)
|
||||
if _, err := reference.ParseNormalizedNamed(name); err != nil {
|
||||
return "", errors.Wrapf(err, "image name %q is invalid, please check name and version fields", name)
|
||||
|
@ -70,7 +69,7 @@ func makeCNABImageName(appName, appVersion, suffix string) (string, error) {
|
|||
return name, nil
|
||||
}
|
||||
|
||||
func persistInBundleStore(ref reference.Named, bndle *bundle.Bundle) error {
|
||||
func PersistInBundleStore(ref reference.Named, bndle *bundle.Bundle) error {
|
||||
if ref == nil {
|
||||
return nil
|
||||
}
|
||||
|
@ -85,7 +84,7 @@ func persistInBundleStore(ref reference.Named, bndle *bundle.Bundle) error {
|
|||
return bundleStore.Store(ref, bndle)
|
||||
}
|
||||
|
||||
func getNamedTagged(tag string) (reference.NamedTagged, error) {
|
||||
func GetNamedTagged(tag string) (reference.NamedTagged, error) {
|
||||
if tag == "" {
|
||||
return nil, nil
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
package commands
|
||||
package packager
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
@ -34,9 +34,9 @@ func TestMakeInvocationImage(t *testing.T) {
|
|||
}
|
||||
for _, c := range testcases {
|
||||
t.Run(c.name, func(t *testing.T) {
|
||||
ref, err := getNamedTagged(c.tag)
|
||||
ref, err := GetNamedTagged(c.tag)
|
||||
assert.NilError(t, err)
|
||||
actual, err := makeInvocationImageName(c.meta, ref)
|
||||
actual, err := MakeInvocationImageName(c.meta, ref)
|
||||
if c.err != "" {
|
||||
assert.ErrorContains(t, err, c.err)
|
||||
assert.Equal(t, actual, "", "On "+c.meta.Name)
|
|
@ -400,7 +400,7 @@ func toSolveOpt(d driver.Driver, multiDriver bool, opt Options, dl dockerLoadCal
|
|||
return nil, nil, err
|
||||
}
|
||||
defers = append(defers, cancel)
|
||||
opt.Exports[i].Output = w
|
||||
opt.Exports[i].Output = wrapWriteCloser(w)
|
||||
}
|
||||
} else if !d.Features()[driver.DockerExporter] {
|
||||
return nil, nil, notSupported(d, driver.DockerExporter)
|
||||
|
|
|
@ -2,6 +2,7 @@ package build
|
|||
|
||||
import (
|
||||
"encoding/csv"
|
||||
"io"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
|
@ -81,7 +82,7 @@ func ParseOutputs(inp []string) ([]client.ExportEntry, error) {
|
|||
if _, err := console.ConsoleFromFile(os.Stdout); err == nil {
|
||||
return nil, errors.Errorf("output file is required for %s exporter. refusing to write to console", out.Type)
|
||||
}
|
||||
out.Output = os.Stdout
|
||||
out.Output = wrapWriteCloser(os.Stdout)
|
||||
} else if dest != "" {
|
||||
fi, err := os.Stat(dest)
|
||||
if err != nil && !os.IsNotExist(err) {
|
||||
|
@ -94,7 +95,7 @@ func ParseOutputs(inp []string) ([]client.ExportEntry, error) {
|
|||
if err != nil {
|
||||
return nil, errors.Errorf("failed to open %s", err)
|
||||
}
|
||||
out.Output = f
|
||||
out.Output = wrapWriteCloser(f)
|
||||
}
|
||||
delete(out.Attrs, "dest")
|
||||
case "registry":
|
||||
|
@ -106,3 +107,9 @@ func ParseOutputs(inp []string) ([]client.ExportEntry, error) {
|
|||
}
|
||||
return outs, nil
|
||||
}
|
||||
|
||||
func wrapWriteCloser(wc io.WriteCloser) func(map[string]string) (io.WriteCloser, error) {
|
||||
return func(map[string]string) (io.WriteCloser, error) {
|
||||
return wc, nil
|
||||
}
|
||||
}
|
||||
|
|
|
@ -427,11 +427,13 @@ func Security(s pb.SecurityMode) RunOption {
|
|||
}
|
||||
|
||||
func Shlex(str string) RunOption {
|
||||
return Shlexf(str)
|
||||
return runOptionFunc(func(ei *ExecInfo) {
|
||||
ei.State = shlexf(str, false)(ei.State)
|
||||
})
|
||||
}
|
||||
func Shlexf(str string, v ...interface{}) RunOption {
|
||||
return runOptionFunc(func(ei *ExecInfo) {
|
||||
ei.State = shlexf(str, v...)(ei.State)
|
||||
ei.State = shlexf(str, true, v...)(ei.State)
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -442,7 +444,9 @@ func Args(a []string) RunOption {
|
|||
}
|
||||
|
||||
func AddEnv(key, value string) RunOption {
|
||||
return AddEnvf(key, value)
|
||||
return runOptionFunc(func(ei *ExecInfo) {
|
||||
ei.State = ei.State.AddEnv(key, value)
|
||||
})
|
||||
}
|
||||
|
||||
func AddEnvf(key, value string, v ...interface{}) RunOption {
|
||||
|
@ -458,7 +462,9 @@ func User(str string) RunOption {
|
|||
}
|
||||
|
||||
func Dir(str string) RunOption {
|
||||
return Dirf(str)
|
||||
return runOptionFunc(func(ei *ExecInfo) {
|
||||
ei.State = ei.State.Dir(str)
|
||||
})
|
||||
}
|
||||
func Dirf(str string, v ...interface{}) RunOption {
|
||||
return runOptionFunc(func(ei *ExecInfo) {
|
||||
|
|
|
@ -24,19 +24,24 @@ var (
|
|||
keySecurity = contextKeyT("llb.security")
|
||||
)
|
||||
|
||||
func addEnvf(key, value string, v ...interface{}) StateOption {
|
||||
func addEnvf(key, value string, replace bool, v ...interface{}) StateOption {
|
||||
if replace {
|
||||
value = fmt.Sprintf(value, v...)
|
||||
}
|
||||
return func(s State) State {
|
||||
return s.WithValue(keyEnv, getEnv(s).AddOrReplace(key, fmt.Sprintf(value, v...)))
|
||||
return s.WithValue(keyEnv, getEnv(s).AddOrReplace(key, value))
|
||||
}
|
||||
}
|
||||
|
||||
func dir(str string) StateOption {
|
||||
return dirf(str)
|
||||
return dirf(str, false)
|
||||
}
|
||||
|
||||
func dirf(str string, v ...interface{}) StateOption {
|
||||
func dirf(value string, replace bool, v ...interface{}) StateOption {
|
||||
if replace {
|
||||
value = fmt.Sprintf(value, v...)
|
||||
}
|
||||
return func(s State) State {
|
||||
value := fmt.Sprintf(str, v...)
|
||||
if !path.IsAbs(value) {
|
||||
prev := getDir(s)
|
||||
if prev == "" {
|
||||
|
@ -100,9 +105,12 @@ func args(args ...string) StateOption {
|
|||
}
|
||||
}
|
||||
|
||||
func shlexf(str string, v ...interface{}) StateOption {
|
||||
func shlexf(str string, replace bool, v ...interface{}) StateOption {
|
||||
if replace {
|
||||
str = fmt.Sprintf(str, v...)
|
||||
}
|
||||
return func(s State) State {
|
||||
arg, err := shlex.Split(fmt.Sprintf(str, v...))
|
||||
arg, err := shlex.Split(str)
|
||||
if err != nil {
|
||||
// TODO: handle error
|
||||
}
|
||||
|
|
|
@ -240,18 +240,18 @@ func (s State) File(a *FileAction, opts ...ConstraintsOpt) State {
|
|||
}
|
||||
|
||||
func (s State) AddEnv(key, value string) State {
|
||||
return s.AddEnvf(key, value)
|
||||
return addEnvf(key, value, false)(s)
|
||||
}
|
||||
|
||||
func (s State) AddEnvf(key, value string, v ...interface{}) State {
|
||||
return addEnvf(key, value, v...)(s)
|
||||
return addEnvf(key, value, true, v...)(s)
|
||||
}
|
||||
|
||||
func (s State) Dir(str string) State {
|
||||
return s.Dirf(str)
|
||||
return dirf(str, false)(s)
|
||||
}
|
||||
func (s State) Dirf(str string, v ...interface{}) State {
|
||||
return dirf(str, v...)(s)
|
||||
return dirf(str, true, v...)(s)
|
||||
}
|
||||
|
||||
func (s State) GetEnv(key string) (string, bool) {
|
||||
|
|
|
@ -46,8 +46,8 @@ type SolveOpt struct {
|
|||
type ExportEntry struct {
|
||||
Type string
|
||||
Attrs map[string]string
|
||||
Output io.WriteCloser // for ExporterOCI and ExporterDocker
|
||||
OutputDir string // for ExporterLocal
|
||||
Output func(map[string]string) (io.WriteCloser, error) // for ExporterOCI and ExporterDocker
|
||||
OutputDir string // for ExporterLocal
|
||||
}
|
||||
|
||||
type CacheOptionsEntry struct {
|
||||
|
|
2
vendor/github.com/moby/buildkit/frontend/gateway/grpcclient/client.go
сгенерированный
поставляемый
2
vendor/github.com/moby/buildkit/frontend/gateway/grpcclient/client.go
сгенерированный
поставляемый
|
@ -128,7 +128,7 @@ func (c *grpcClient) Run(ctx context.Context, f client.BuildFunc) (retError erro
|
|||
}
|
||||
}
|
||||
if retError != nil {
|
||||
st, _ := status.FromError(retError)
|
||||
st, _ := status.FromError(errors.Cause(retError))
|
||||
stp := st.Proto()
|
||||
req.Error = &rpc.Status{
|
||||
Code: stp.Code,
|
||||
|
|
|
@ -4,6 +4,7 @@ import (
|
|||
"context"
|
||||
|
||||
"github.com/moby/buildkit/session"
|
||||
"github.com/pkg/errors"
|
||||
"google.golang.org/grpc/codes"
|
||||
"google.golang.org/grpc/status"
|
||||
)
|
||||
|
@ -16,10 +17,10 @@ func CredentialsFunc(ctx context.Context, c session.Caller) func(string) (string
|
|||
Host: host,
|
||||
})
|
||||
if err != nil {
|
||||
if st, ok := status.FromError(err); ok && st.Code() == codes.Unimplemented {
|
||||
if st, ok := status.FromError(errors.Cause(err)); ok && st.Code() == codes.Unimplemented {
|
||||
return "", "", nil
|
||||
}
|
||||
return "", "", err
|
||||
return "", "", errors.WithStack(err)
|
||||
}
|
||||
return resp.Username, resp.Secret, nil
|
||||
}
|
||||
|
|
|
@ -9,6 +9,7 @@ import (
|
|||
"github.com/moby/buildkit/session"
|
||||
digest "github.com/opencontainers/go-digest"
|
||||
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
|
||||
"github.com/pkg/errors"
|
||||
"google.golang.org/grpc/metadata"
|
||||
)
|
||||
|
||||
|
@ -31,47 +32,53 @@ func (cs *callerContentStore) choose(ctx context.Context) context.Context {
|
|||
|
||||
func (cs *callerContentStore) Info(ctx context.Context, dgst digest.Digest) (content.Info, error) {
|
||||
ctx = cs.choose(ctx)
|
||||
return cs.store.Info(ctx, dgst)
|
||||
info, err := cs.store.Info(ctx, dgst)
|
||||
return info, errors.WithStack(err)
|
||||
}
|
||||
|
||||
func (cs *callerContentStore) Update(ctx context.Context, info content.Info, fieldpaths ...string) (content.Info, error) {
|
||||
ctx = cs.choose(ctx)
|
||||
return cs.store.Update(ctx, info, fieldpaths...)
|
||||
info, err := cs.store.Update(ctx, info, fieldpaths...)
|
||||
return info, errors.WithStack(err)
|
||||
}
|
||||
|
||||
func (cs *callerContentStore) Walk(ctx context.Context, fn content.WalkFunc, fs ...string) error {
|
||||
ctx = cs.choose(ctx)
|
||||
return cs.store.Walk(ctx, fn, fs...)
|
||||
return errors.WithStack(cs.store.Walk(ctx, fn, fs...))
|
||||
}
|
||||
|
||||
func (cs *callerContentStore) Delete(ctx context.Context, dgst digest.Digest) error {
|
||||
ctx = cs.choose(ctx)
|
||||
return cs.store.Delete(ctx, dgst)
|
||||
return errors.WithStack(cs.store.Delete(ctx, dgst))
|
||||
}
|
||||
|
||||
func (cs *callerContentStore) ListStatuses(ctx context.Context, fs ...string) ([]content.Status, error) {
|
||||
ctx = cs.choose(ctx)
|
||||
return cs.store.ListStatuses(ctx, fs...)
|
||||
resp, err := cs.store.ListStatuses(ctx, fs...)
|
||||
return resp, errors.WithStack(err)
|
||||
}
|
||||
|
||||
func (cs *callerContentStore) Status(ctx context.Context, ref string) (content.Status, error) {
|
||||
ctx = cs.choose(ctx)
|
||||
return cs.store.Status(ctx, ref)
|
||||
st, err := cs.store.Status(ctx, ref)
|
||||
return st, errors.WithStack(err)
|
||||
}
|
||||
|
||||
func (cs *callerContentStore) Abort(ctx context.Context, ref string) error {
|
||||
ctx = cs.choose(ctx)
|
||||
return cs.store.Abort(ctx, ref)
|
||||
return errors.WithStack(cs.store.Abort(ctx, ref))
|
||||
}
|
||||
|
||||
func (cs *callerContentStore) Writer(ctx context.Context, opts ...content.WriterOpt) (content.Writer, error) {
|
||||
ctx = cs.choose(ctx)
|
||||
return cs.store.Writer(ctx, opts...)
|
||||
w, err := cs.store.Writer(ctx, opts...)
|
||||
return w, errors.WithStack(err)
|
||||
}
|
||||
|
||||
func (cs *callerContentStore) ReaderAt(ctx context.Context, desc ocispec.Descriptor) (content.ReaderAt, error) {
|
||||
ctx = cs.choose(ctx)
|
||||
return cs.store.ReaderAt(ctx, desc)
|
||||
ra, err := cs.store.ReaderAt(ctx, desc)
|
||||
return ra, errors.WithStack(err)
|
||||
}
|
||||
|
||||
// NewCallerStore creates content.Store from session.Caller with specified storeID
|
||||
|
|
|
@ -14,7 +14,7 @@ import (
|
|||
)
|
||||
|
||||
func sendDiffCopy(stream grpc.Stream, fs fsutil.FS, progress progressCb) error {
|
||||
return fsutil.Send(stream.Context(), stream, fs, progress)
|
||||
return errors.WithStack(fsutil.Send(stream.Context(), stream, fs, progress))
|
||||
}
|
||||
|
||||
func newStreamWriter(stream grpc.ClientStream) io.WriteCloser {
|
||||
|
@ -29,7 +29,7 @@ type bufferedWriteCloser struct {
|
|||
|
||||
func (bwc *bufferedWriteCloser) Close() error {
|
||||
if err := bwc.Writer.Flush(); err != nil {
|
||||
return err
|
||||
return errors.WithStack(err)
|
||||
}
|
||||
return bwc.Closer.Close()
|
||||
}
|
||||
|
@ -40,19 +40,25 @@ type streamWriterCloser struct {
|
|||
|
||||
func (wc *streamWriterCloser) Write(dt []byte) (int, error) {
|
||||
if err := wc.ClientStream.SendMsg(&BytesMessage{Data: dt}); err != nil {
|
||||
return 0, err
|
||||
// SendMsg return EOF on remote errors
|
||||
if errors.Cause(err) == io.EOF {
|
||||
if err := errors.WithStack(wc.ClientStream.RecvMsg(struct{}{})); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
}
|
||||
return 0, errors.WithStack(err)
|
||||
}
|
||||
return len(dt), nil
|
||||
}
|
||||
|
||||
func (wc *streamWriterCloser) Close() error {
|
||||
if err := wc.ClientStream.CloseSend(); err != nil {
|
||||
return err
|
||||
return errors.WithStack(err)
|
||||
}
|
||||
// block until receiver is done
|
||||
var bm BytesMessage
|
||||
if err := wc.ClientStream.RecvMsg(&bm); err != io.EOF {
|
||||
return err
|
||||
return errors.WithStack(err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
@ -69,19 +75,19 @@ func recvDiffCopy(ds grpc.Stream, dest string, cu CacheUpdater, progress progres
|
|||
cf = cu.HandleChange
|
||||
ch = cu.ContentHasher()
|
||||
}
|
||||
return fsutil.Receive(ds.Context(), ds, dest, fsutil.ReceiveOpt{
|
||||
return errors.WithStack(fsutil.Receive(ds.Context(), ds, dest, fsutil.ReceiveOpt{
|
||||
NotifyHashed: cf,
|
||||
ContentHasher: ch,
|
||||
ProgressCb: progress,
|
||||
Filter: fsutil.FilterFunc(filter),
|
||||
})
|
||||
}))
|
||||
}
|
||||
|
||||
func syncTargetDiffCopy(ds grpc.Stream, dest string) error {
|
||||
if err := os.MkdirAll(dest, 0700); err != nil {
|
||||
return err
|
||||
return errors.Wrapf(err, "failed to create synctarget dest dir %s", dest)
|
||||
}
|
||||
return fsutil.Receive(ds.Context(), ds, dest, fsutil.ReceiveOpt{
|
||||
return errors.WithStack(fsutil.Receive(ds.Context(), ds, dest, fsutil.ReceiveOpt{
|
||||
Merge: true,
|
||||
Filter: func() func(string, *fstypes.Stat) bool {
|
||||
uid := os.Getuid()
|
||||
|
@ -92,7 +98,7 @@ func syncTargetDiffCopy(ds grpc.Stream, dest string) error {
|
|||
return true
|
||||
}
|
||||
}(),
|
||||
})
|
||||
}))
|
||||
}
|
||||
|
||||
func writeTargetFile(ds grpc.Stream, wc io.WriteCloser) error {
|
||||
|
@ -102,10 +108,10 @@ func writeTargetFile(ds grpc.Stream, wc io.WriteCloser) error {
|
|||
if errors.Cause(err) == io.EOF {
|
||||
return nil
|
||||
}
|
||||
return err
|
||||
return errors.WithStack(err)
|
||||
}
|
||||
if _, err := wc.Write(bm.Data); err != nil {
|
||||
return err
|
||||
return errors.WithStack(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,11 +18,12 @@ import (
|
|||
)
|
||||
|
||||
const (
|
||||
keyOverrideExcludes = "override-excludes"
|
||||
keyIncludePatterns = "include-patterns"
|
||||
keyExcludePatterns = "exclude-patterns"
|
||||
keyFollowPaths = "followpaths"
|
||||
keyDirName = "dir-name"
|
||||
keyOverrideExcludes = "override-excludes"
|
||||
keyIncludePatterns = "include-patterns"
|
||||
keyExcludePatterns = "exclude-patterns"
|
||||
keyFollowPaths = "followpaths"
|
||||
keyDirName = "dir-name"
|
||||
keyExporterMetaPrefix = "exporter-md-"
|
||||
)
|
||||
|
||||
type fsSyncProvider struct {
|
||||
|
@ -238,16 +239,16 @@ func NewFSSyncTargetDir(outdir string) session.Attachable {
|
|||
}
|
||||
|
||||
// NewFSSyncTarget allows writing into an io.WriteCloser
|
||||
func NewFSSyncTarget(w io.WriteCloser) session.Attachable {
|
||||
func NewFSSyncTarget(f func(map[string]string) (io.WriteCloser, error)) session.Attachable {
|
||||
p := &fsSyncTarget{
|
||||
outfile: w,
|
||||
f: f,
|
||||
}
|
||||
return p
|
||||
}
|
||||
|
||||
type fsSyncTarget struct {
|
||||
outdir string
|
||||
outfile io.WriteCloser
|
||||
outdir string
|
||||
f func(map[string]string) (io.WriteCloser, error)
|
||||
}
|
||||
|
||||
func (sp *fsSyncTarget) Register(server *grpc.Server) {
|
||||
|
@ -258,11 +259,26 @@ func (sp *fsSyncTarget) DiffCopy(stream FileSend_DiffCopyServer) error {
|
|||
if sp.outdir != "" {
|
||||
return syncTargetDiffCopy(stream, sp.outdir)
|
||||
}
|
||||
if sp.outfile == nil {
|
||||
|
||||
if sp.f == nil {
|
||||
return errors.New("empty outfile and outdir")
|
||||
}
|
||||
defer sp.outfile.Close()
|
||||
return writeTargetFile(stream, sp.outfile)
|
||||
opts, _ := metadata.FromIncomingContext(stream.Context()) // if no metadata continue with empty object
|
||||
md := map[string]string{}
|
||||
for k, v := range opts {
|
||||
if strings.HasPrefix(k, keyExporterMetaPrefix) {
|
||||
md[strings.TrimPrefix(k, keyExporterMetaPrefix)] = strings.Join(v, ",")
|
||||
}
|
||||
}
|
||||
wc, err := sp.f(md)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if wc == nil {
|
||||
return status.Errorf(codes.AlreadyExists, "target already exists")
|
||||
}
|
||||
defer wc.Close()
|
||||
return writeTargetFile(stream, wc)
|
||||
}
|
||||
|
||||
func CopyToCaller(ctx context.Context, fs fsutil.FS, c session.Caller, progress func(int, bool)) error {
|
||||
|
@ -275,13 +291,13 @@ func CopyToCaller(ctx context.Context, fs fsutil.FS, c session.Caller, progress
|
|||
|
||||
cc, err := client.DiffCopy(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
return errors.WithStack(err)
|
||||
}
|
||||
|
||||
return sendDiffCopy(cc, fs, progress)
|
||||
}
|
||||
|
||||
func CopyFileWriter(ctx context.Context, c session.Caller) (io.WriteCloser, error) {
|
||||
func CopyFileWriter(ctx context.Context, md map[string]string, c session.Caller) (io.WriteCloser, error) {
|
||||
method := session.MethodURL(_FileSend_serviceDesc.ServiceName, "diffcopy")
|
||||
if !c.Supports(method) {
|
||||
return nil, errors.Errorf("method %s not supported by the client", method)
|
||||
|
@ -289,9 +305,16 @@ func CopyFileWriter(ctx context.Context, c session.Caller) (io.WriteCloser, erro
|
|||
|
||||
client := NewFileSendClient(c.Conn())
|
||||
|
||||
opts := make(map[string][]string, len(md))
|
||||
for k, v := range md {
|
||||
opts[keyExporterMetaPrefix+k] = []string{v}
|
||||
}
|
||||
|
||||
ctx = metadata.NewOutgoingContext(ctx, opts)
|
||||
|
||||
cc, err := client.DiffCopy(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, errors.WithStack(err)
|
||||
}
|
||||
|
||||
return newStreamWriter(cc), nil
|
||||
|
|
|
@ -21,10 +21,10 @@ func GetSecret(ctx context.Context, c session.Caller, id string) ([]byte, error)
|
|||
ID: id,
|
||||
})
|
||||
if err != nil {
|
||||
if st, ok := status.FromError(err); ok && (st.Code() == codes.Unimplemented || st.Code() == codes.NotFound) {
|
||||
if st, ok := status.FromError(errors.Cause(err)); ok && (st.Code() == codes.Unimplemented || st.Code() == codes.NotFound) {
|
||||
return nil, errors.Wrapf(ErrNotFound, "secret %s not found", id)
|
||||
}
|
||||
return nil, err
|
||||
return nil, errors.WithStack(err)
|
||||
}
|
||||
return resp.Data, nil
|
||||
}
|
||||
|
|
|
@ -3,23 +3,24 @@ package sshforward
|
|||
import (
|
||||
io "io"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
context "golang.org/x/net/context"
|
||||
"golang.org/x/sync/errgroup"
|
||||
"google.golang.org/grpc"
|
||||
)
|
||||
|
||||
func Copy(ctx context.Context, conn io.ReadWriteCloser, stream grpc.Stream) error {
|
||||
func Copy(ctx context.Context, conn io.ReadWriteCloser, stream grpc.Stream, closeStream func() error) error {
|
||||
g, ctx := errgroup.WithContext(ctx)
|
||||
|
||||
g.Go(func() (retErr error) {
|
||||
p := &BytesMessage{}
|
||||
for {
|
||||
if err := stream.RecvMsg(p); err != nil {
|
||||
conn.Close()
|
||||
if err == io.EOF {
|
||||
return nil
|
||||
}
|
||||
conn.Close()
|
||||
return err
|
||||
return errors.WithStack(err)
|
||||
}
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
|
@ -29,7 +30,7 @@ func Copy(ctx context.Context, conn io.ReadWriteCloser, stream grpc.Stream) erro
|
|||
}
|
||||
if _, err := conn.Write(p.Data); err != nil {
|
||||
conn.Close()
|
||||
return err
|
||||
return errors.WithStack(err)
|
||||
}
|
||||
p.Data = p.Data[:0]
|
||||
}
|
||||
|
@ -41,9 +42,12 @@ func Copy(ctx context.Context, conn io.ReadWriteCloser, stream grpc.Stream) erro
|
|||
n, err := conn.Read(buf)
|
||||
switch {
|
||||
case err == io.EOF:
|
||||
if closeStream != nil {
|
||||
closeStream()
|
||||
}
|
||||
return nil
|
||||
case err != nil:
|
||||
return err
|
||||
return errors.WithStack(err)
|
||||
}
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
|
@ -52,7 +56,7 @@ func Copy(ctx context.Context, conn io.ReadWriteCloser, stream grpc.Stream) erro
|
|||
}
|
||||
p := &BytesMessage{Data: buf[:n]}
|
||||
if err := stream.SendMsg(p); err != nil {
|
||||
return err
|
||||
return errors.WithStack(err)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
|
|
@ -7,6 +7,7 @@ import (
|
|||
"path/filepath"
|
||||
|
||||
"github.com/moby/buildkit/session"
|
||||
"github.com/pkg/errors"
|
||||
context "golang.org/x/net/context"
|
||||
"golang.org/x/sync/errgroup"
|
||||
"google.golang.org/grpc/metadata"
|
||||
|
@ -48,7 +49,7 @@ func (s *server) run(ctx context.Context, l net.Listener, id string) error {
|
|||
return err
|
||||
}
|
||||
|
||||
go Copy(ctx, conn, stream)
|
||||
go Copy(ctx, conn, stream, stream.CloseSend)
|
||||
}
|
||||
})
|
||||
|
||||
|
@ -65,7 +66,7 @@ type SocketOpt struct {
|
|||
func MountSSHSocket(ctx context.Context, c session.Caller, opt SocketOpt) (sockPath string, closer func() error, err error) {
|
||||
dir, err := ioutil.TempDir("", ".buildkit-ssh-sock")
|
||||
if err != nil {
|
||||
return "", nil, err
|
||||
return "", nil, errors.WithStack(err)
|
||||
}
|
||||
|
||||
defer func() {
|
||||
|
@ -78,16 +79,16 @@ func MountSSHSocket(ctx context.Context, c session.Caller, opt SocketOpt) (sockP
|
|||
|
||||
l, err := net.Listen("unix", sockPath)
|
||||
if err != nil {
|
||||
return "", nil, err
|
||||
return "", nil, errors.WithStack(err)
|
||||
}
|
||||
|
||||
if err := os.Chown(sockPath, opt.UID, opt.GID); err != nil {
|
||||
l.Close()
|
||||
return "", nil, err
|
||||
return "", nil, errors.WithStack(err)
|
||||
}
|
||||
if err := os.Chmod(sockPath, os.FileMode(opt.Mode)); err != nil {
|
||||
l.Close()
|
||||
return "", nil, err
|
||||
return "", nil, errors.WithStack(err)
|
||||
}
|
||||
|
||||
s := &server{caller: c}
|
||||
|
@ -102,12 +103,12 @@ func MountSSHSocket(ctx context.Context, c session.Caller, opt SocketOpt) (sockP
|
|||
return sockPath, func() error {
|
||||
err := l.Close()
|
||||
os.RemoveAll(sockPath)
|
||||
return err
|
||||
return errors.WithStack(err)
|
||||
}, nil
|
||||
}
|
||||
|
||||
func CheckSSHID(ctx context.Context, c session.Caller, id string) error {
|
||||
client := NewSSHClient(c.Conn())
|
||||
_, err := client.CheckAgent(ctx, &CheckAgentRequest{ID: id})
|
||||
return err
|
||||
return errors.WithStack(err)
|
||||
}
|
||||
|
|
2
vendor/github.com/moby/buildkit/session/sshforward/sshprovider/agentprovider.go
сгенерированный
поставляемый
2
vendor/github.com/moby/buildkit/session/sshforward/sshprovider/agentprovider.go
сгенерированный
поставляемый
|
@ -114,7 +114,7 @@ func (sp *socketProvider) ForwardAgent(stream sshforward.SSH_ForwardAgentServer)
|
|||
|
||||
eg.Go(func() error {
|
||||
defer s1.Close()
|
||||
return sshforward.Copy(ctx, s2, stream)
|
||||
return sshforward.Copy(ctx, s2, stream, nil)
|
||||
})
|
||||
|
||||
return eg.Wait()
|
||||
|
|
|
@ -6,6 +6,7 @@ import (
|
|||
"net/url"
|
||||
|
||||
"github.com/moby/buildkit/session"
|
||||
"github.com/pkg/errors"
|
||||
"google.golang.org/grpc/metadata"
|
||||
)
|
||||
|
||||
|
@ -26,7 +27,7 @@ func New(ctx context.Context, c session.Caller, url *url.URL) (*Upload, error) {
|
|||
|
||||
cc, err := client.Pull(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, errors.WithStack(err)
|
||||
}
|
||||
|
||||
return &Upload{cc: cc}, nil
|
||||
|
@ -44,12 +45,12 @@ func (u *Upload) WriteTo(w io.Writer) (int, error) {
|
|||
if err == io.EOF {
|
||||
return n, nil
|
||||
}
|
||||
return n, err
|
||||
return n, errors.WithStack(err)
|
||||
}
|
||||
nn, err := w.Write(bm.Data)
|
||||
n += nn
|
||||
if err != nil {
|
||||
return n, err
|
||||
return n, errors.WithStack(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -30,19 +30,20 @@ const (
|
|||
|
||||
CapBuildOpLLBFileName apicaps.CapID = "source.buildop.llbfilename"
|
||||
|
||||
CapExecMetaBase apicaps.CapID = "exec.meta.base"
|
||||
CapExecMetaProxy apicaps.CapID = "exec.meta.proxyenv"
|
||||
CapExecMetaNetwork apicaps.CapID = "exec.meta.network"
|
||||
CapExecMetaSecurity apicaps.CapID = "exec.meta.security"
|
||||
CapExecMetaSetsDefaultPath apicaps.CapID = "exec.meta.setsdefaultpath"
|
||||
CapExecMountBind apicaps.CapID = "exec.mount.bind"
|
||||
CapExecMountCache apicaps.CapID = "exec.mount.cache"
|
||||
CapExecMountCacheSharing apicaps.CapID = "exec.mount.cache.sharing"
|
||||
CapExecMountSelector apicaps.CapID = "exec.mount.selector"
|
||||
CapExecMountTmpfs apicaps.CapID = "exec.mount.tmpfs"
|
||||
CapExecMountSecret apicaps.CapID = "exec.mount.secret"
|
||||
CapExecMountSSH apicaps.CapID = "exec.mount.ssh"
|
||||
CapExecCgroupsMounted apicaps.CapID = "exec.cgroup"
|
||||
CapExecMetaBase apicaps.CapID = "exec.meta.base"
|
||||
CapExecMetaProxy apicaps.CapID = "exec.meta.proxyenv"
|
||||
CapExecMetaNetwork apicaps.CapID = "exec.meta.network"
|
||||
CapExecMetaSecurity apicaps.CapID = "exec.meta.security"
|
||||
CapExecMetaSetsDefaultPath apicaps.CapID = "exec.meta.setsdefaultpath"
|
||||
CapExecMountBind apicaps.CapID = "exec.mount.bind"
|
||||
CapExecMountBindReadWriteNoOuput apicaps.CapID = "exec.mount.bind.readwrite-nooutput"
|
||||
CapExecMountCache apicaps.CapID = "exec.mount.cache"
|
||||
CapExecMountCacheSharing apicaps.CapID = "exec.mount.cache.sharing"
|
||||
CapExecMountSelector apicaps.CapID = "exec.mount.selector"
|
||||
CapExecMountTmpfs apicaps.CapID = "exec.mount.tmpfs"
|
||||
CapExecMountSecret apicaps.CapID = "exec.mount.secret"
|
||||
CapExecMountSSH apicaps.CapID = "exec.mount.ssh"
|
||||
CapExecCgroupsMounted apicaps.CapID = "exec.cgroup"
|
||||
|
||||
CapFileBase apicaps.CapID = "file.base"
|
||||
|
||||
|
@ -193,6 +194,12 @@ func init() {
|
|||
Status: apicaps.CapStatusExperimental,
|
||||
})
|
||||
|
||||
Caps.Init(apicaps.Cap{
|
||||
ID: CapExecMountBindReadWriteNoOuput,
|
||||
Enabled: true,
|
||||
Status: apicaps.CapStatusExperimental,
|
||||
})
|
||||
|
||||
Caps.Init(apicaps.Cap{
|
||||
ID: CapExecMountCache,
|
||||
Enabled: true,
|
||||
|
|
Загрузка…
Ссылка в новой задаче