From 72935fbc06762341ea69b8d059dfb0166b83b1b8 Mon Sep 17 00:00:00 2001 From: Sam Alba Date: Mon, 8 Nov 2021 17:12:46 -0800 Subject: [PATCH 1/4] added winio to godeps Signed-off-by: Sam Alba --- Makefile | 3 +++ go.mod | 1 + go.sum | 2 ++ 3 files changed, 6 insertions(+) diff --git a/Makefile b/Makefile index e62baa70..760d9fff 100644 --- a/Makefile +++ b/Makefile @@ -11,6 +11,9 @@ dagger: dagger-debug: go build -race -o ./cmd/dagger/dagger-debug -ldflags '-X go.dagger.io/dagger/version.Revision=$(GIT_REVISION)' ./cmd/dagger/ +.PHONY: install + go install ./cmd/dagger + .PHONY: test test: go test -race -v ./... diff --git a/go.mod b/go.mod index 0fc14d50..c8a6ebbf 100644 --- a/go.mod +++ b/go.mod @@ -6,6 +6,7 @@ require ( cuelang.org/go v0.4.0 filippo.io/age v1.0.0 github.com/KromDaniel/jonson v0.0.0-20180630143114-d2f9c3c389db + github.com/Microsoft/go-winio v0.5.1 // indirect github.com/containerd/console v1.0.3 github.com/containerd/containerd v1.5.7 github.com/docker/buildx v0.6.2 diff --git a/go.sum b/go.sum index f2af6f79..c04575df 100644 --- a/go.sum +++ b/go.sum @@ -154,6 +154,8 @@ github.com/Microsoft/go-winio v0.4.17-0.20210211115548-6eac466e5fa3/go.mod h1:JP github.com/Microsoft/go-winio v0.4.17-0.20210324224401-5516f17a5958/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84= github.com/Microsoft/go-winio v0.4.17 h1:iT12IBVClFevaf8PuVyi3UmZOVh4OqnaLxDTW2O6j3w= github.com/Microsoft/go-winio v0.4.17/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84= +github.com/Microsoft/go-winio v0.5.1 h1:aPJp2QD7OOrhO5tQXqQoGSJc+DjDtWTGLOmNyAm6FgY= +github.com/Microsoft/go-winio v0.5.1/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84= github.com/Microsoft/hcsshim v0.8.6/go.mod h1:Op3hHsoHPAvb6lceZHDtd9OkTew38wNoXnJs8iY7rUg= github.com/Microsoft/hcsshim v0.8.7-0.20190325164909-8abdbb8205e4/go.mod h1:Op3hHsoHPAvb6lceZHDtd9OkTew38wNoXnJs8iY7rUg= github.com/Microsoft/hcsshim v0.8.7/go.mod h1:OHd7sQqRFrYd3RmSgbgji+ctCwkbq2wbEYNSzOYtcBQ= From e6de59a340d7d22e33b7b674b63b844d4bc14dc9 Mon Sep 17 00:00:00 2001 From: Sam Alba Date: Mon, 8 Nov 2021 17:16:38 -0800 Subject: [PATCH 2/4] added support for stream type npipe (Windows named pipe) Signed-off-by: Sam Alba --- environment/pipeline.go | 33 ++++++++++++++++++++++++--------- solver/socketprovider.go | 28 +++++++++++++++++++--------- state/input.go | 25 ++++++++++++++++++------- stdlib/dagger/dagger.cue | 8 +++++++- 4 files changed, 68 insertions(+), 26 deletions(-) diff --git a/environment/pipeline.go b/environment/pipeline.go index a0cd1fe8..d0dfad72 100644 --- a/environment/pipeline.go +++ b/environment/pipeline.go @@ -574,20 +574,35 @@ func (p *Pipeline) mount(ctx context.Context, dest string, mnt *compiler.Value) return nil, fmt.Errorf("invalid stream %q: not a stream", stream.Path().String()) } + // Unix socket unixValue := stream.Lookup("unix") - if !unixValue.Exists() { - return nil, fmt.Errorf("invalid stream %q: not a unix socket", stream.Path().String()) + if unixValue.Exists() { + unix, err := unixValue.String() + if err != nil { + return nil, fmt.Errorf("invalid unix path id: %w", err) + } + + return llb.AddSSHSocket( + llb.SSHID(fmt.Sprintf("unix=%s", unix)), + llb.SSHSocketTarget(dest), + ), nil } - unix, err := unixValue.String() - if err != nil { - return nil, fmt.Errorf("invalid unix path id: %w", err) + // Windows named pipe + npipeValue := stream.Lookup("npipe") + if npipeValue.Exists() { + npipe, err := npipeValue.String() + if err != nil { + return nil, fmt.Errorf("invalid npipe path id: %w", err) + } + + return llb.AddSSHSocket( + llb.SSHID(fmt.Sprintf("npipe=%s", npipe)), + llb.SSHSocketTarget(dest), + ), nil } - return llb.AddSSHSocket( - llb.SSHID(fmt.Sprintf("unix=%s", unix)), - llb.SSHSocketTarget(dest), - ), nil + return nil, fmt.Errorf("invalid stream %q: not a valid stream", stream.Path().String()) } // eg. mount: "/foo": { from: www.source } diff --git a/solver/socketprovider.go b/solver/socketprovider.go index 2e232fc7..d7a7dd90 100644 --- a/solver/socketprovider.go +++ b/solver/socketprovider.go @@ -7,6 +7,7 @@ import ( "strings" "time" + "github.com/Microsoft/go-winio" "github.com/moby/buildkit/session" "github.com/moby/buildkit/session/sshforward" "google.golang.org/grpc" @@ -14,7 +15,8 @@ import ( ) const ( - unixPrefix = "unix=" + unixPrefix = "unix=" + npipePrefix = "npipe=" ) type SocketProvider struct { @@ -33,12 +35,26 @@ func (sp *SocketProvider) CheckAgent(ctx context.Context, req *sshforward.CheckA if req.ID != "" { id = req.ID } - if !strings.HasPrefix(id, unixPrefix) { + if !strings.HasPrefix(id, unixPrefix) && !strings.HasPrefix(id, npipePrefix) { return &sshforward.CheckAgentResponse{}, fmt.Errorf("invalid socket forward key %s", id) } return &sshforward.CheckAgentResponse{}, nil } +func dialStream(id string) (net.Conn, error) { + switch { + case strings.HasPrefix(id, unixPrefix): + id = strings.TrimPrefix(id, unixPrefix) + return net.DialTimeout("unix", id, time.Second) + case strings.HasPrefix(id, npipePrefix): + id = strings.TrimPrefix(id, npipePrefix) + dur := time.Second + return winio.DialPipe(id, &dur) + default: + return nil, fmt.Errorf("invalid socket forward key %s", id) + } +} + func (sp *SocketProvider) ForwardAgent(stream sshforward.SSH_ForwardAgentServer) error { id := sshforward.DefaultID @@ -48,13 +64,7 @@ func (sp *SocketProvider) ForwardAgent(stream sshforward.SSH_ForwardAgentServer) id = v[0] } - if !strings.HasPrefix(id, unixPrefix) { - return fmt.Errorf("invalid socket forward key %s", id) - } - - id = strings.TrimPrefix(id, unixPrefix) - - conn, err := net.DialTimeout("unix", id, time.Second) + conn, err := dialStream(id) if err != nil { return fmt.Errorf("failed to connect to %s: %w", id, err) } diff --git a/state/input.go b/state/input.go index 838a5844..22be56fc 100644 --- a/state/input.go +++ b/state/input.go @@ -280,7 +280,7 @@ func FileInput(data string) Input { } type fileInput struct { - Path string `json:"data,omitempty"` + Path string `yaml:"path,omitempty"` } func (i fileInput) Compile(_ string, _ *State) (*compiler.Value, error) { @@ -296,20 +296,31 @@ func (i fileInput) Compile(_ string, _ *State) (*compiler.Value, error) { } // A socket input value -func SocketInput(data string) Input { - i := socketInput{ - Unix: data, +func SocketInput(data, socketType string) Input { + i := socketInput{} + + switch socketType { + case "npipe": + i.Npipe = data + case "unix": + i.Unix = data } + return Input{ Socket: &i, } } type socketInput struct { - Unix string `json:"unix,omitempty"` + Unix string `json:"unix,omitempty" yaml:"unix,omitempty"` + Npipe string `json:"npipe,omitempty" yaml:"npipe,omitempty"` } func (i socketInput) Compile(_ string, _ *State) (*compiler.Value, error) { - socketValue := fmt.Sprintf(`{unix: %q}`, i.Unix) - return compiler.Compile("", socketValue) + socketValue, err := json.Marshal(i) + if err != nil { + return nil, err + } + + return compiler.Compile("", string(socketValue)) } diff --git a/stdlib/dagger/dagger.cue b/stdlib/dagger/dagger.cue index 35da3ce6..0d236c6d 100644 --- a/stdlib/dagger/dagger.cue +++ b/stdlib/dagger/dagger.cue @@ -18,7 +18,13 @@ import ( #Stream: { @dagger(stream) - unix: string + { + // Unix Socket + unix: string + } | { + // Windows Named Pipe + npipe: string + } } // Secret value From a147f130ee002f1ed0509d0b0e02796d4acc1557 Mon Sep 17 00:00:00 2001 From: Sam Alba Date: Mon, 8 Nov 2021 17:17:33 -0800 Subject: [PATCH 3/4] cmd/input: added auto-detection for Windows named pipe Signed-off-by: Sam Alba --- cmd/dagger/cmd/input/socket.go | 41 ++++++++++++++++++++++++---------- 1 file changed, 29 insertions(+), 12 deletions(-) diff --git a/cmd/dagger/cmd/input/socket.go b/cmd/dagger/cmd/input/socket.go index 8bf1b417..3a6d6801 100644 --- a/cmd/dagger/cmd/input/socket.go +++ b/cmd/dagger/cmd/input/socket.go @@ -1,8 +1,11 @@ package input import ( + "context" "os" + "runtime" + "github.com/rs/zerolog/log" "github.com/spf13/cobra" "github.com/spf13/viper" "go.dagger.io/dagger/cmd/dagger/logger" @@ -24,26 +27,40 @@ var socketCmd = &cobra.Command{ lg := logger.New() ctx := lg.WithContext(cmd.Context()) - unix := args[1] - - st, err := os.Stat(unix) - if err != nil { - lg.Fatal().Err(err).Str("path", unix).Msg("invalid unix socket") - } - - if st.Mode()&os.ModeSocket == 0 { - lg.Fatal().Str("path", unix).Msg("not a unix socket") - } - updateEnvironmentInput( ctx, cmd, args[0], - state.SocketInput(unix), + state.SocketInput(detectStreamType(ctx, args[1])), ) }, } +func detectStreamType(ctx context.Context, path string) (string, string) { + lg := log.Ctx(ctx) + + if runtime.GOOS == "windows" { + // support the unix format for convenience + if path == "/var/run/docker.sock" || path == "\\var\\run\\docker.sock" { + path = "\\\\.\\pipe\\docker_engine" + lg.Info().Str("path", path).Msg("Windows detected, override unix socket path") + } + + return path, "npipe" + } + + st, err := os.Stat(path) + if err != nil { + lg.Fatal().Err(err).Str("path", path).Msg("invalid unix socket") + } + + if st.Mode()&os.ModeSocket == 0 { + lg.Fatal().Str("path", path).Msg("not a unix socket") + } + + return path, "unix" +} + func init() { if err := viper.BindPFlags(boolCmd.Flags()); err != nil { panic(err) From d46a347781ca685291f5069ad06bf4cd4b9bde6c Mon Sep 17 00:00:00 2001 From: Sam Alba Date: Mon, 8 Nov 2021 17:51:40 -0800 Subject: [PATCH 4/4] solver: split platform specific code Signed-off-by: Sam Alba --- solver/socketprovider.go | 17 ----------------- solver/socketprovider_unix.go | 20 ++++++++++++++++++++ solver/socketprovider_windows.go | 14 ++++++++++++++ 3 files changed, 34 insertions(+), 17 deletions(-) create mode 100644 solver/socketprovider_unix.go create mode 100644 solver/socketprovider_windows.go diff --git a/solver/socketprovider.go b/solver/socketprovider.go index d7a7dd90..d0a0f52f 100644 --- a/solver/socketprovider.go +++ b/solver/socketprovider.go @@ -3,11 +3,8 @@ package solver import ( "context" "fmt" - "net" "strings" - "time" - "github.com/Microsoft/go-winio" "github.com/moby/buildkit/session" "github.com/moby/buildkit/session/sshforward" "google.golang.org/grpc" @@ -41,20 +38,6 @@ func (sp *SocketProvider) CheckAgent(ctx context.Context, req *sshforward.CheckA return &sshforward.CheckAgentResponse{}, nil } -func dialStream(id string) (net.Conn, error) { - switch { - case strings.HasPrefix(id, unixPrefix): - id = strings.TrimPrefix(id, unixPrefix) - return net.DialTimeout("unix", id, time.Second) - case strings.HasPrefix(id, npipePrefix): - id = strings.TrimPrefix(id, npipePrefix) - dur := time.Second - return winio.DialPipe(id, &dur) - default: - return nil, fmt.Errorf("invalid socket forward key %s", id) - } -} - func (sp *SocketProvider) ForwardAgent(stream sshforward.SSH_ForwardAgentServer) error { id := sshforward.DefaultID diff --git a/solver/socketprovider_unix.go b/solver/socketprovider_unix.go new file mode 100644 index 00000000..04e31fcc --- /dev/null +++ b/solver/socketprovider_unix.go @@ -0,0 +1,20 @@ +//go:build !windows +// +build !windows + +package solver + +import ( + "fmt" + "net" + "strings" + "time" +) + +func dialStream(id string) (net.Conn, error) { + if !strings.HasPrefix(id, unixPrefix) { + return nil, fmt.Errorf("invalid socket forward key %s", id) + } + + id = strings.TrimPrefix(id, unixPrefix) + return net.DialTimeout("unix", id, time.Second) +} diff --git a/solver/socketprovider_windows.go b/solver/socketprovider_windows.go new file mode 100644 index 00000000..d5094fbb --- /dev/null +++ b/solver/socketprovider_windows.go @@ -0,0 +1,14 @@ +//go:build windows +// +build windows + +package solver + +func dialStream(id string) (net.Conn, error) { + if !strings.HasPrefix(id, unixPrefix) { + return nil, fmt.Errorf("invalid socket forward key %s", id) + } + + id = strings.TrimPrefix(id, npipePrefix) + dur := time.Second + return winio.DialPipe(id, &dur) +}