vendor: update buildkit to opentelemetry support

Signed-off-by: Tonis Tiigi <tonistiigi@gmail.com>
This commit is contained in:
Tonis Tiigi
2021-06-15 21:02:39 -07:00
parent 6ba080d337
commit 334c93fbbe
829 changed files with 89541 additions and 24438 deletions

View File

@ -52,8 +52,8 @@ func CredentialsFunc(sm *session.Manager, g session.Group) func(string) (session
}
}
func FetchToken(req *FetchTokenRequest, sm *session.Manager, g session.Group) (resp *FetchTokenResponse, err error) {
err = sm.Any(context.TODO(), g, func(ctx context.Context, id string, c session.Caller) error {
func FetchToken(ctx context.Context, req *FetchTokenRequest, sm *session.Manager, g session.Group) (resp *FetchTokenResponse, err error) {
err = sm.Any(ctx, g, func(ctx context.Context, id string, c session.Caller) error {
client := NewAuthClient(c.Conn())
resp, err = client.FetchToken(ctx, req)
@ -68,9 +68,9 @@ func FetchToken(req *FetchTokenRequest, sm *session.Manager, g session.Group) (r
return resp, nil
}
func VerifyTokenAuthority(host string, pubKey *[32]byte, sm *session.Manager, g session.Group) (sessionID string, ok bool, err error) {
func VerifyTokenAuthority(ctx context.Context, host string, pubKey *[32]byte, sm *session.Manager, g session.Group) (sessionID string, ok bool, err error) {
var verified bool
err = sm.Any(context.TODO(), g, func(ctx context.Context, id string, c session.Caller) error {
err = sm.Any(ctx, g, func(ctx context.Context, id string, c session.Caller) error {
client := NewAuthClient(c.Conn())
payload := make([]byte, 32)
@ -100,8 +100,8 @@ func VerifyTokenAuthority(host string, pubKey *[32]byte, sm *session.Manager, g
return sessionID, verified, nil
}
func GetTokenAuthority(host string, sm *session.Manager, g session.Group) (sessionID string, pubKey *[32]byte, err error) {
err = sm.Any(context.TODO(), g, func(ctx context.Context, id string, c session.Caller) error {
func GetTokenAuthority(ctx context.Context, host string, sm *session.Manager, g session.Group) (sessionID string, pubKey *[32]byte, err error) {
err = sm.Any(ctx, g, func(ctx context.Context, id string, c session.Caller) error {
client := NewAuthClient(c.Conn())
resp, err := client.GetTokenAuthority(ctx, &GetTokenAuthorityRequest{

View File

@ -70,7 +70,7 @@ func (wc *streamWriterCloser) Close() error {
return nil
}
func recvDiffCopy(ds grpc.ClientStream, dest string, cu CacheUpdater, progress progressCb, filter func(string, *fstypes.Stat) bool) error {
func recvDiffCopy(ds grpc.ClientStream, dest string, cu CacheUpdater, progress progressCb, differ fsutil.DiffType, filter func(string, *fstypes.Stat) bool) (err error) {
st := time.Now()
defer func() {
logrus.Debugf("diffcopy took: %v", time.Since(st))
@ -82,11 +82,18 @@ func recvDiffCopy(ds grpc.ClientStream, dest string, cu CacheUpdater, progress p
cf = cu.HandleChange
ch = cu.ContentHasher()
}
defer func() {
// tracing wrapper requires close trigger even on clean eof
if err == nil {
ds.CloseSend()
}
}()
return errors.WithStack(fsutil.Receive(ds.Context(), ds, dest, fsutil.ReceiveOpt{
NotifyHashed: cf,
ContentHasher: ch,
ProgressCb: progress,
Filter: fsutil.FilterFunc(filter),
Differ: differ,
}))
}

View File

@ -130,7 +130,7 @@ type progressCb func(int, bool)
type protocol struct {
name string
sendFn func(stream Stream, fs fsutil.FS, progress progressCb) error
recvFn func(stream grpc.ClientStream, destDir string, cu CacheUpdater, progress progressCb, mapFunc func(string, *fstypes.Stat) bool) error
recvFn func(stream grpc.ClientStream, destDir string, cu CacheUpdater, progress progressCb, differ fsutil.DiffType, mapFunc func(string, *fstypes.Stat) bool) error
}
func isProtoSupported(p string) bool {
@ -160,6 +160,7 @@ type FSSendRequestOpt struct {
CacheUpdater CacheUpdater
ProgressCb func(int, bool)
Filter func(string, *fstypes.Stat) bool
Differ fsutil.DiffType
}
// CacheUpdater is an object capable of sending notifications for the cache hash changes
@ -227,7 +228,7 @@ func FSSync(ctx context.Context, c session.Caller, opt FSSendRequestOpt) error {
panic(fmt.Sprintf("invalid protocol: %q", pr.name))
}
return pr.recvFn(stream, opt.DestDir, opt.CacheUpdater, opt.ProgressCb, opt.Filter)
return pr.recvFn(stream, opt.DestDir, opt.CacheUpdater, opt.ProgressCb, opt.Differ, opt.Filter)
}
// NewFSSyncTargetDir allows writing into a directory

View File

@ -8,6 +8,7 @@ import (
context "context"
fmt "fmt"
proto "github.com/gogo/protobuf/proto"
types "github.com/tonistiigi/fsutil/types"
grpc "google.golang.org/grpc"
codes "google.golang.org/grpc/codes"
status "google.golang.org/grpc/status"
@ -80,21 +81,25 @@ func init() {
func init() { proto.RegisterFile("filesync.proto", fileDescriptor_d1042549f1f24495) }
var fileDescriptor_d1042549f1f24495 = []byte{
// 217 bytes of a gzipped FileDescriptorProto
// 281 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0xe2, 0x4b, 0xcb, 0xcc, 0x49,
0x2d, 0xae, 0xcc, 0x4b, 0xd6, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x12, 0xc8, 0xcd, 0x4f, 0xaa,
0xd4, 0x83, 0x0b, 0x96, 0x19, 0x2a, 0x29, 0x71, 0xf1, 0x38, 0x55, 0x96, 0xa4, 0x16, 0xfb, 0xa6,
0x16, 0x17, 0x27, 0xa6, 0xa7, 0x0a, 0x09, 0x71, 0xb1, 0xa4, 0x24, 0x96, 0x24, 0x4a, 0x30, 0x2a,
0x30, 0x6a, 0xf0, 0x04, 0x81, 0xd9, 0x46, 0xab, 0x19, 0xb9, 0x38, 0xdc, 0x32, 0x73, 0x52, 0x83,
0x2b, 0xf3, 0x92, 0x85, 0xfc, 0xb8, 0x38, 0x5c, 0x32, 0xd3, 0xd2, 0x9c, 0xf3, 0x0b, 0x2a, 0x85,
0xe4, 0xf4, 0xd0, 0xcd, 0xd3, 0x43, 0x36, 0x4c, 0x8a, 0x80, 0xbc, 0x06, 0xa3, 0x01, 0xa3, 0x90,
0x3f, 0x17, 0x67, 0x48, 0x62, 0x51, 0x70, 0x49, 0x51, 0x6a, 0x62, 0x2e, 0x35, 0x0c, 0x34, 0x8a,
0x82, 0x3a, 0x36, 0x35, 0x2f, 0x85, 0xda, 0x8e, 0x75, 0xb2, 0xbb, 0xf0, 0x50, 0x8e, 0xe1, 0xc6,
0x43, 0x39, 0x86, 0x0f, 0x0f, 0xe5, 0x18, 0x1b, 0x1e, 0xc9, 0x31, 0xae, 0x78, 0x24, 0xc7, 0x78,
0xe2, 0x91, 0x1c, 0xe3, 0x85, 0x47, 0x72, 0x8c, 0x0f, 0x1e, 0xc9, 0x31, 0xbe, 0x78, 0x24, 0xc7,
0xf0, 0xe1, 0x91, 0x1c, 0xe3, 0x84, 0xc7, 0x72, 0x0c, 0x17, 0x1e, 0xcb, 0x31, 0xdc, 0x78, 0x2c,
0xc7, 0x10, 0xc5, 0x01, 0x33, 0x33, 0x89, 0x0d, 0x1c, 0x0d, 0xc6, 0x80, 0x00, 0x00, 0x00, 0xff,
0xff, 0x5e, 0xce, 0x52, 0xb3, 0x98, 0x01, 0x00, 0x00,
0xd4, 0x83, 0x0b, 0x96, 0x19, 0x4a, 0xe9, 0xa6, 0x67, 0x96, 0x64, 0x94, 0x26, 0xe9, 0x25, 0xe7,
0xe7, 0xea, 0x97, 0xe4, 0xe7, 0x65, 0x16, 0x97, 0x64, 0x66, 0xa6, 0x67, 0xea, 0xa7, 0x15, 0x97,
0x96, 0x64, 0xe6, 0xe8, 0x97, 0x54, 0x16, 0xa4, 0x16, 0xeb, 0x97, 0x67, 0x16, 0xa5, 0x42, 0x0c,
0x50, 0x52, 0xe2, 0xe2, 0x71, 0xaa, 0x2c, 0x49, 0x2d, 0xf6, 0x4d, 0x2d, 0x2e, 0x4e, 0x4c, 0x4f,
0x15, 0x12, 0xe2, 0x62, 0x49, 0x49, 0x2c, 0x49, 0x94, 0x60, 0x54, 0x60, 0xd4, 0xe0, 0x09, 0x02,
0xb3, 0x8d, 0x9a, 0x19, 0xb9, 0x38, 0xdc, 0x32, 0x73, 0x52, 0x83, 0x2b, 0xf3, 0x92, 0x85, 0xac,
0xb8, 0x38, 0x5c, 0x32, 0xd3, 0xd2, 0x9c, 0xf3, 0x0b, 0x2a, 0x85, 0x44, 0xf4, 0x20, 0xc6, 0xea,
0x81, 0x8d, 0xd5, 0x0b, 0x48, 0x4c, 0xce, 0x4e, 0x2d, 0x91, 0xc2, 0x2a, 0xaa, 0xc1, 0x68, 0xc0,
0x28, 0x64, 0xcd, 0xc5, 0x19, 0x92, 0x58, 0x14, 0x5c, 0x52, 0x94, 0x9a, 0x98, 0x4b, 0xaa, 0x66,
0xa3, 0x28, 0xa8, 0x23, 0x52, 0xf3, 0x52, 0x84, 0xfc, 0x90, 0x1c, 0x21, 0xa7, 0x87, 0x1e, 0x06,
0x7a, 0xc8, 0x3e, 0x92, 0x22, 0x20, 0x0f, 0x32, 0xdb, 0xc9, 0xee, 0xc2, 0x43, 0x39, 0x86, 0x1b,
0x0f, 0xe5, 0x18, 0x3e, 0x3c, 0x94, 0x63, 0x6c, 0x78, 0x24, 0xc7, 0xb8, 0xe2, 0x91, 0x1c, 0xe3,
0x89, 0x47, 0x72, 0x8c, 0x17, 0x1e, 0xc9, 0x31, 0x3e, 0x78, 0x24, 0xc7, 0xf8, 0xe2, 0x91, 0x1c,
0xc3, 0x87, 0x47, 0x72, 0x8c, 0x13, 0x1e, 0xcb, 0x31, 0x5c, 0x78, 0x2c, 0xc7, 0x70, 0xe3, 0xb1,
0x1c, 0x43, 0x14, 0x07, 0xcc, 0xcc, 0x24, 0x36, 0x70, 0x60, 0x1a, 0x03, 0x02, 0x00, 0x00, 0xff,
0xff, 0xe6, 0x17, 0x63, 0x59, 0x9f, 0x01, 0x00, 0x00,
}
func (this *BytesMessage) Equal(that interface{}) bool {
@ -174,8 +179,8 @@ func (c *fileSyncClient) DiffCopy(ctx context.Context, opts ...grpc.CallOption)
}
type FileSync_DiffCopyClient interface {
Send(*BytesMessage) error
Recv() (*BytesMessage, error)
Send(*types.Packet) error
Recv() (*types.Packet, error)
grpc.ClientStream
}
@ -183,12 +188,12 @@ type fileSyncDiffCopyClient struct {
grpc.ClientStream
}
func (x *fileSyncDiffCopyClient) Send(m *BytesMessage) error {
func (x *fileSyncDiffCopyClient) Send(m *types.Packet) error {
return x.ClientStream.SendMsg(m)
}
func (x *fileSyncDiffCopyClient) Recv() (*BytesMessage, error) {
m := new(BytesMessage)
func (x *fileSyncDiffCopyClient) Recv() (*types.Packet, error) {
m := new(types.Packet)
if err := x.ClientStream.RecvMsg(m); err != nil {
return nil, err
}
@ -205,8 +210,8 @@ func (c *fileSyncClient) TarStream(ctx context.Context, opts ...grpc.CallOption)
}
type FileSync_TarStreamClient interface {
Send(*BytesMessage) error
Recv() (*BytesMessage, error)
Send(*types.Packet) error
Recv() (*types.Packet, error)
grpc.ClientStream
}
@ -214,12 +219,12 @@ type fileSyncTarStreamClient struct {
grpc.ClientStream
}
func (x *fileSyncTarStreamClient) Send(m *BytesMessage) error {
func (x *fileSyncTarStreamClient) Send(m *types.Packet) error {
return x.ClientStream.SendMsg(m)
}
func (x *fileSyncTarStreamClient) Recv() (*BytesMessage, error) {
m := new(BytesMessage)
func (x *fileSyncTarStreamClient) Recv() (*types.Packet, error) {
m := new(types.Packet)
if err := x.ClientStream.RecvMsg(m); err != nil {
return nil, err
}
@ -252,8 +257,8 @@ func _FileSync_DiffCopy_Handler(srv interface{}, stream grpc.ServerStream) error
}
type FileSync_DiffCopyServer interface {
Send(*BytesMessage) error
Recv() (*BytesMessage, error)
Send(*types.Packet) error
Recv() (*types.Packet, error)
grpc.ServerStream
}
@ -261,12 +266,12 @@ type fileSyncDiffCopyServer struct {
grpc.ServerStream
}
func (x *fileSyncDiffCopyServer) Send(m *BytesMessage) error {
func (x *fileSyncDiffCopyServer) Send(m *types.Packet) error {
return x.ServerStream.SendMsg(m)
}
func (x *fileSyncDiffCopyServer) Recv() (*BytesMessage, error) {
m := new(BytesMessage)
func (x *fileSyncDiffCopyServer) Recv() (*types.Packet, error) {
m := new(types.Packet)
if err := x.ServerStream.RecvMsg(m); err != nil {
return nil, err
}
@ -278,8 +283,8 @@ func _FileSync_TarStream_Handler(srv interface{}, stream grpc.ServerStream) erro
}
type FileSync_TarStreamServer interface {
Send(*BytesMessage) error
Recv() (*BytesMessage, error)
Send(*types.Packet) error
Recv() (*types.Packet, error)
grpc.ServerStream
}
@ -287,12 +292,12 @@ type fileSyncTarStreamServer struct {
grpc.ServerStream
}
func (x *fileSyncTarStreamServer) Send(m *BytesMessage) error {
func (x *fileSyncTarStreamServer) Send(m *types.Packet) error {
return x.ServerStream.SendMsg(m)
}
func (x *fileSyncTarStreamServer) Recv() (*BytesMessage, error) {
m := new(BytesMessage)
func (x *fileSyncTarStreamServer) Recv() (*types.Packet, error) {
m := new(types.Packet)
if err := x.ServerStream.RecvMsg(m); err != nil {
return nil, err
}

View File

@ -4,9 +4,11 @@ package moby.filesync.v1;
option go_package = "filesync";
import "github.com/tonistiigi/fsutil/types/wire.proto";
service FileSync{
rpc DiffCopy(stream BytesMessage) returns (stream BytesMessage);
rpc TarStream(stream BytesMessage) returns (stream BytesMessage);
rpc DiffCopy(stream fsutil.types.Packet) returns (stream fsutil.types.Packet);
rpc TarStream(stream fsutil.types.Packet) returns (stream fsutil.types.Packet);
}
service FileSend{
@ -17,4 +19,4 @@ service FileSend{
// BytesMessage contains a chunk of byte data
message BytesMessage{
bytes data = 1;
}
}

View File

@ -1,3 +1,3 @@
package filesync
//go:generate protoc --gogoslick_out=plugins=grpc:. filesync.proto
//go:generate protoc -I=. -I=../../vendor/ -I=../../vendor/github.com/tonistiigi/fsutil/types/ --gogoslick_out=plugins=grpc:. filesync.proto

View File

@ -7,11 +7,11 @@ import (
"time"
grpc_middleware "github.com/grpc-ecosystem/go-grpc-middleware"
"github.com/grpc-ecosystem/grpc-opentracing/go/otgrpc"
"github.com/moby/buildkit/util/grpcerrors"
opentracing "github.com/opentracing/opentracing-go"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
"go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc"
"go.opentelemetry.io/otel/trace"
"golang.org/x/net/http2"
"google.golang.org/grpc"
"google.golang.org/grpc/health/grpc_health_v1"
@ -43,10 +43,9 @@ func grpcClientConn(ctx context.Context, conn net.Conn) (context.Context, *grpc.
grpc.WithInsecure(),
}
if span := opentracing.SpanFromContext(ctx); span != nil {
tracer := span.Tracer()
unary = append(unary, otgrpc.OpenTracingClientInterceptor(tracer, traceFilter()))
stream = append(stream, otgrpc.OpenTracingStreamClientInterceptor(tracer, traceFilter()))
if span := trace.SpanFromContext(ctx); span.SpanContext().IsValid() {
unary = append(unary, filterClient(otelgrpc.UnaryClientInterceptor(otelgrpc.WithTracerProvider(span.TracerProvider()), otelgrpc.WithPropagators(propagators))))
stream = append(stream, otelgrpc.StreamClientInterceptor(otelgrpc.WithTracerProvider(span.TracerProvider()), otelgrpc.WithPropagators(propagators)))
}
unary = append(unary, grpcerrors.UnaryClientInterceptor)

View File

@ -22,7 +22,7 @@ func GetSecret(ctx context.Context, c session.Caller, id string) ([]byte, error)
})
if err != nil {
if code := grpcerrors.Code(err); code == codes.Unimplemented || code == codes.NotFound {
return nil, errors.Wrapf(ErrNotFound, "secret %s not found", id)
return nil, errors.Wrapf(ErrNotFound, "secret %s", id)
}
return nil, err
}

View File

@ -6,11 +6,12 @@ import (
"strings"
grpc_middleware "github.com/grpc-ecosystem/go-grpc-middleware"
"github.com/grpc-ecosystem/grpc-opentracing/go/otgrpc"
"github.com/moby/buildkit/identity"
"github.com/moby/buildkit/util/grpcerrors"
opentracing "github.com/opentracing/opentracing-go"
"github.com/pkg/errors"
"go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc"
"go.opentelemetry.io/otel/propagation"
"go.opentelemetry.io/otel/trace"
"google.golang.org/grpc"
"google.golang.org/grpc/health"
"google.golang.org/grpc/health/grpc_health_v1"
@ -23,6 +24,8 @@ const (
headerSessionMethod = "X-Docker-Expose-Session-Grpc-Method"
)
var propagators = propagation.NewCompositeTextMapPropagator(propagation.TraceContext{}, propagation.Baggage{})
// Dialer returns a connection that can be used by the session
type Dialer func(ctx context.Context, proto string, meta map[string][]string) (net.Conn, error)
@ -51,10 +54,10 @@ func NewSession(ctx context.Context, name, sharedKey string) (*Session, error) {
var stream []grpc.StreamServerInterceptor
serverOpts := []grpc.ServerOption{}
if span := opentracing.SpanFromContext(ctx); span != nil {
tracer := span.Tracer()
unary = append(unary, otgrpc.OpenTracingServerInterceptor(tracer, traceFilter()))
stream = append(stream, otgrpc.OpenTracingStreamServerInterceptor(span.Tracer(), traceFilter()))
if span := trace.SpanFromContext(ctx); span.SpanContext().IsValid() {
unary = append(unary, filterServer(otelgrpc.UnaryServerInterceptor(otelgrpc.WithTracerProvider(span.TracerProvider()), otelgrpc.WithPropagators(propagators))))
stream = append(stream, otelgrpc.StreamServerInterceptor(otelgrpc.WithTracerProvider(span.TracerProvider()), otelgrpc.WithPropagators(propagators)))
}
unary = append(unary, grpcerrors.UnaryServerInterceptor)
@ -152,10 +155,21 @@ func MethodURL(s, m string) string {
return "/" + s + "/" + m
}
func traceFilter() otgrpc.Option {
return otgrpc.IncludingSpans(func(parentSpanCtx opentracing.SpanContext,
method string,
req, resp interface{}) bool {
return !strings.HasSuffix(method, "Health/Check")
})
// updates needed in opentelemetry-contrib to avoid this
func filterServer(intercept grpc.UnaryServerInterceptor) grpc.UnaryServerInterceptor {
return func(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (resp interface{}, err error) {
if strings.HasSuffix(info.FullMethod, "Health/Check") {
return handler(ctx, req)
}
return intercept(ctx, req, info, handler)
}
}
func filterClient(intercept grpc.UnaryClientInterceptor) grpc.UnaryClientInterceptor {
return func(ctx context.Context, method string, req, reply interface{}, cc *grpc.ClientConn, invoker grpc.UnaryInvoker, opts ...grpc.CallOption) error {
if strings.HasSuffix(method, "Health/Check") {
return invoker(ctx, method, req, reply, cc, opts...)
}
return intercept(ctx, method, req, reply, cc, invoker, opts...)
}
}

View File

@ -35,7 +35,11 @@ func NewSSHAgentProvider(confs []AgentConfig) (session.Attachable, error) {
}
if conf.Paths[0] == "" {
return nil, errors.Errorf("invalid empty ssh agent socket, make sure SSH_AUTH_SOCK is set")
p, err := getFallbackAgentPath()
if err != nil {
return nil, errors.Wrap(err, "invalid empty ssh agent socket")
}
conf.Paths[0] = p
}
src, err := toAgentSource(conf.Paths)
@ -56,7 +60,20 @@ func NewSSHAgentProvider(confs []AgentConfig) (session.Attachable, error) {
type source struct {
agent agent.Agent
socket string
socket *socketDialer
}
type socketDialer struct {
path string
dialer func(string) (net.Conn, error)
}
func (s socketDialer) Dial() (net.Conn, error) {
return s.dialer(s.path)
}
func (s socketDialer) String() string {
return s.path
}
type socketProvider struct {
@ -94,8 +111,8 @@ func (sp *socketProvider) ForwardAgent(stream sshforward.SSH_ForwardAgentServer)
var a agent.Agent
if src.socket != "" {
conn, err := net.DialTimeout("unix", src.socket, time.Second)
if src.socket != nil {
conn, err := src.socket.Dial()
if err != nil {
return errors.Wrapf(err, "failed to connect to %s", src.socket)
}
@ -124,21 +141,24 @@ func (sp *socketProvider) ForwardAgent(stream sshforward.SSH_ForwardAgentServer)
func toAgentSource(paths []string) (source, error) {
var keys bool
var socket string
var socket *socketDialer
a := agent.NewKeyring()
for _, p := range paths {
if socket != "" {
if socket != nil {
return source{}, errors.New("only single socket allowed")
}
if parsed := getWindowsPipeDialer(p); parsed != nil {
socket = parsed
continue
}
fi, err := os.Stat(p)
if err != nil {
return source{}, errors.WithStack(err)
}
if fi.Mode()&os.ModeSocket > 0 {
if keys {
return source{}, errors.Errorf("invalid combination of keys and sockets")
}
socket = p
socket = &socketDialer{path: p, dialer: unixSocketDialer}
continue
}
@ -160,7 +180,7 @@ func toAgentSource(paths []string) (source, error) {
if keys {
return source{}, errors.Errorf("invalid combination of keys and sockets")
}
socket = p
socket = &socketDialer{path: p, dialer: unixSocketDialer}
continue
}
@ -173,13 +193,20 @@ func toAgentSource(paths []string) (source, error) {
keys = true
}
if socket != "" {
if socket != nil {
if keys {
return source{}, errors.Errorf("invalid combination of keys and sockets")
}
return source{socket: socket}, nil
}
return source{agent: a}, nil
}
func unixSocketDialer(path string) (net.Conn, error) {
return net.DialTimeout("unix", path, 2*time.Second)
}
func sockPair() (io.ReadWriteCloser, io.ReadWriteCloser) {
pr1, pw1 := io.Pipe()
pr2, pw2 := io.Pipe()

View File

@ -0,0 +1,15 @@
// +build !windows
package sshprovider
import (
"github.com/pkg/errors"
)
func getFallbackAgentPath() (string, error) {
return "", errors.Errorf("make sure SSH_AUTH_SOCK is set")
}
func getWindowsPipeDialer(path string) *socketDialer {
return nil
}

View File

@ -0,0 +1,60 @@
// +build windows
package sshprovider
import (
"net"
"regexp"
"strings"
"github.com/Microsoft/go-winio"
"github.com/pkg/errors"
"golang.org/x/sys/windows"
)
// Returns the Windows OpenSSH agent named pipe path, but
// only if the agent is running. Returns an error otherwise.
func getFallbackAgentPath() (string, error) {
// Windows OpenSSH agent uses a named pipe rather
// than a UNIX socket. These pipes do not play nice
// with os.Stat (which tries to open its target), so
// use a FindFirstFile syscall to check for existence.
var fd windows.Win32finddata
path := `\\.\pipe\openssh-ssh-agent`
pathPtr, _ := windows.UTF16PtrFromString(path)
handle, err := windows.FindFirstFile(pathPtr, &fd)
if err != nil {
msg := "Windows OpenSSH agent not available at %s." +
" Enable the SSH agent service or set SSH_AUTH_SOCK."
return "", errors.Errorf(msg, path)
}
_ = windows.CloseHandle(handle)
return path, nil
}
// Returns true if the path references a named pipe.
func isWindowsPipePath(path string) bool {
// If path matches \\*\pipe\* then it references a named pipe
// and requires winio.DialPipe() rather than DialTimeout("unix").
// Slashes and backslashes may be used interchangeably in the path.
// Path separators may consist of multiple consecutive (back)slashes.
pipePattern := strings.ReplaceAll("^[/]{2}[^/]+[/]+pipe[/]+", "/", `\\/`)
ok, _ := regexp.MatchString(pipePattern, path)
return ok
}
func getWindowsPipeDialer(path string) *socketDialer {
if isWindowsPipePath(path) {
return &socketDialer{path: path, dialer: windowsPipeDialer}
}
return nil
}
func windowsPipeDialer(path string) (net.Conn, error) {
return winio.DialPipe(path, nil)
}