mirror of https://github.com/docker/cli.git
Merge pull request #1846 from andrewhsu/v
update vndr docker/docker ac48309 and related packages
This commit is contained in:
commit
f28d9cc929
10
vendor.conf
10
vendor.conf
|
@ -8,13 +8,13 @@ github.com/containerd/containerd ceba56893a76f22cf0126c46d835
|
|||
github.com/containerd/continuity 004b46473808b3e7a4a3049c20e4376c91eb966d
|
||||
github.com/containerd/fifo a9fb20d87448d386e6d50b1f2e1fa70dcf0de43c
|
||||
github.com/containerd/typeurl 2a93cfde8c20b23de8eb84a5adbc234ddf7a9e8d
|
||||
github.com/coreos/etcd fca8add78a9d926166eb739b8e4a124434025ba3 # v3.3.9
|
||||
github.com/coreos/etcd d57e8b8d97adfc4a6c224fe116714bf1a1f3beb9 # v3.3.12
|
||||
github.com/cpuguy83/go-md2man 20f5889cbdc3c73dbd2862796665e7c465ade7d1 # v1.0.8
|
||||
github.com/davecgh/go-spew 8991bc29aa16c548c550c7ff78260e27b9ab7c73 # v1.1.1
|
||||
github.com/dgrijalva/jwt-go a2c85815a77d0f951e33ba4db5ae93629a1530af
|
||||
github.com/docker/compose-on-kubernetes 7a68f5c914c7e06d7a08dc71608f41811c91f0bc # v0.4.21
|
||||
github.com/docker/distribution 0d3efadf0154c2b8a4e7b6621fff9809655cc580
|
||||
github.com/docker/docker 92a6266c9d4f1bacbfb68d1c6b9c94f673d6cfde
|
||||
github.com/docker/docker ac48309ac4024b5bfe21a126b1a23a3e93521d75
|
||||
github.com/docker/docker-credential-helpers 5241b46610f2491efdf9d1c85f1ddf5b02f6d962
|
||||
github.com/docker/go d30aec9fd63c35133f8f79c3412ad91a3b08be06 # Contains a customized version of canonical/json and is used by Notary. The package is periodically rebased on current Go versions.
|
||||
github.com/docker/go-connections 7395e3f8aa162843a74ed6d48e79627d9792ac55 # v0.4.0
|
||||
|
@ -47,11 +47,11 @@ github.com/json-iterator/go 0ff49de124c6f76f8494e194af75
|
|||
github.com/konsorten/go-windows-terminal-sequences f55edac94c9bbba5d6182a4be46d86a2c9b5b50e # v1.0.2
|
||||
github.com/mattn/go-shellwords a72fbe27a1b0ed0df2f02754945044ce1456608b # v1.0.5
|
||||
github.com/matttproud/golang_protobuf_extensions c12348ce28de40eed0136aa2b644d0ee0650e56c # v1.0.1
|
||||
github.com/Microsoft/go-winio c599b533b43b1363d7d7c6cfda5ede70ed73ff13
|
||||
github.com/Microsoft/hcsshim ba3d6667710fa905116f39a19d059c4c1016be7c
|
||||
github.com/Microsoft/go-winio 84b4ab48a50763fe7b3abcef38e5205c12027fac
|
||||
github.com/Microsoft/hcsshim 672e52e9209d1e53718c1b6a7d68cc9272654ab5
|
||||
github.com/miekg/pkcs11 6120d95c0e9576ccf4a78ba40855809dca31a9ed
|
||||
github.com/mitchellh/mapstructure f15292f7a699fcc1a38a80977f80a046874ba8ac
|
||||
github.com/moby/buildkit b3028967ae6259c9a31c1a1deeccd30fe3469cce
|
||||
github.com/moby/buildkit 8818c67cff663befa7b70f21454e340f71616581
|
||||
github.com/modern-go/concurrent bacd9c7ef1dd9b15be4a9909b8ac7a4e313eec94 # 1.0.3
|
||||
github.com/modern-go/reflect2 4b7aa43c6742a2c18fdef89dd197aaae7dac7ccd # 1.0.1
|
||||
github.com/morikuni/aec 39771216ff4c63d11f5e604076f9c45e8be1067b
|
||||
|
|
|
@ -3,10 +3,13 @@
|
|||
package winio
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"net"
|
||||
"os"
|
||||
"runtime"
|
||||
"syscall"
|
||||
"time"
|
||||
"unsafe"
|
||||
|
@ -18,6 +21,48 @@ import (
|
|||
//sys getNamedPipeInfo(pipe syscall.Handle, flags *uint32, outSize *uint32, inSize *uint32, maxInstances *uint32) (err error) = GetNamedPipeInfo
|
||||
//sys getNamedPipeHandleState(pipe syscall.Handle, state *uint32, curInstances *uint32, maxCollectionCount *uint32, collectDataTimeout *uint32, userName *uint16, maxUserNameSize uint32) (err error) = GetNamedPipeHandleStateW
|
||||
//sys localAlloc(uFlags uint32, length uint32) (ptr uintptr) = LocalAlloc
|
||||
//sys ntCreateNamedPipeFile(pipe *syscall.Handle, access uint32, oa *objectAttributes, iosb *ioStatusBlock, share uint32, disposition uint32, options uint32, typ uint32, readMode uint32, completionMode uint32, maxInstances uint32, inboundQuota uint32, outputQuota uint32, timeout *int64) (status ntstatus) = ntdll.NtCreateNamedPipeFile
|
||||
//sys rtlNtStatusToDosError(status ntstatus) (winerr error) = ntdll.RtlNtStatusToDosErrorNoTeb
|
||||
//sys rtlDosPathNameToNtPathName(name *uint16, ntName *unicodeString, filePart uintptr, reserved uintptr) (status ntstatus) = ntdll.RtlDosPathNameToNtPathName_U
|
||||
//sys rtlDefaultNpAcl(dacl *uintptr) (status ntstatus) = ntdll.RtlDefaultNpAcl
|
||||
|
||||
type ioStatusBlock struct {
|
||||
Status, Information uintptr
|
||||
}
|
||||
|
||||
type objectAttributes struct {
|
||||
Length uintptr
|
||||
RootDirectory uintptr
|
||||
ObjectName *unicodeString
|
||||
Attributes uintptr
|
||||
SecurityDescriptor *securityDescriptor
|
||||
SecurityQoS uintptr
|
||||
}
|
||||
|
||||
type unicodeString struct {
|
||||
Length uint16
|
||||
MaximumLength uint16
|
||||
Buffer uintptr
|
||||
}
|
||||
|
||||
type securityDescriptor struct {
|
||||
Revision byte
|
||||
Sbz1 byte
|
||||
Control uint16
|
||||
Owner uintptr
|
||||
Group uintptr
|
||||
Sacl uintptr
|
||||
Dacl uintptr
|
||||
}
|
||||
|
||||
type ntstatus int32
|
||||
|
||||
func (status ntstatus) Err() error {
|
||||
if status >= 0 {
|
||||
return nil
|
||||
}
|
||||
return rtlNtStatusToDosError(status)
|
||||
}
|
||||
|
||||
const (
|
||||
cERROR_PIPE_BUSY = syscall.Errno(231)
|
||||
|
@ -25,21 +70,20 @@ const (
|
|||
cERROR_PIPE_CONNECTED = syscall.Errno(535)
|
||||
cERROR_SEM_TIMEOUT = syscall.Errno(121)
|
||||
|
||||
cPIPE_ACCESS_DUPLEX = 0x3
|
||||
cFILE_FLAG_FIRST_PIPE_INSTANCE = 0x80000
|
||||
cSECURITY_SQOS_PRESENT = 0x100000
|
||||
cSECURITY_ANONYMOUS = 0
|
||||
|
||||
cPIPE_REJECT_REMOTE_CLIENTS = 0x8
|
||||
|
||||
cPIPE_UNLIMITED_INSTANCES = 255
|
||||
|
||||
cNMPWAIT_USE_DEFAULT_WAIT = 0
|
||||
cNMPWAIT_NOWAIT = 1
|
||||
cSECURITY_SQOS_PRESENT = 0x100000
|
||||
cSECURITY_ANONYMOUS = 0
|
||||
|
||||
cPIPE_TYPE_MESSAGE = 4
|
||||
|
||||
cPIPE_READMODE_MESSAGE = 2
|
||||
|
||||
cFILE_OPEN = 1
|
||||
cFILE_CREATE = 2
|
||||
|
||||
cFILE_PIPE_MESSAGE_TYPE = 1
|
||||
cFILE_PIPE_REJECT_REMOTE_CLIENTS = 2
|
||||
|
||||
cSE_DACL_PRESENT = 4
|
||||
)
|
||||
|
||||
var (
|
||||
|
@ -137,9 +181,30 @@ func (s pipeAddress) String() string {
|
|||
return string(s)
|
||||
}
|
||||
|
||||
// tryDialPipe attempts to dial the pipe at `path` until `ctx` cancellation or timeout.
|
||||
func tryDialPipe(ctx context.Context, path *string) (syscall.Handle, error) {
|
||||
for {
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return syscall.Handle(0), ctx.Err()
|
||||
default:
|
||||
h, err := createFile(*path, syscall.GENERIC_READ|syscall.GENERIC_WRITE, 0, nil, syscall.OPEN_EXISTING, syscall.FILE_FLAG_OVERLAPPED|cSECURITY_SQOS_PRESENT|cSECURITY_ANONYMOUS, 0)
|
||||
if err == nil {
|
||||
return h, nil
|
||||
}
|
||||
if err != cERROR_PIPE_BUSY {
|
||||
return h, &os.PathError{Err: err, Op: "open", Path: *path}
|
||||
}
|
||||
// Wait 10 msec and try again. This is a rather simplistic
|
||||
// view, as we always try each 10 milliseconds.
|
||||
time.Sleep(time.Millisecond * 10)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// DialPipe connects to a named pipe by path, timing out if the connection
|
||||
// takes longer than the specified duration. If timeout is nil, then we use
|
||||
// a default timeout of 5 seconds. (We do not use WaitNamedPipe.)
|
||||
// a default timeout of 2 seconds. (We do not use WaitNamedPipe.)
|
||||
func DialPipe(path string, timeout *time.Duration) (net.Conn, error) {
|
||||
var absTimeout time.Time
|
||||
if timeout != nil {
|
||||
|
@ -147,23 +212,22 @@ func DialPipe(path string, timeout *time.Duration) (net.Conn, error) {
|
|||
} else {
|
||||
absTimeout = time.Now().Add(time.Second * 2)
|
||||
}
|
||||
ctx, _ := context.WithDeadline(context.Background(), absTimeout)
|
||||
conn, err := DialPipeContext(ctx, path)
|
||||
if err == context.DeadlineExceeded {
|
||||
return nil, ErrTimeout
|
||||
}
|
||||
return conn, err
|
||||
}
|
||||
|
||||
// DialPipeContext attempts to connect to a named pipe by `path` until `ctx`
|
||||
// cancellation or timeout.
|
||||
func DialPipeContext(ctx context.Context, path string) (net.Conn, error) {
|
||||
var err error
|
||||
var h syscall.Handle
|
||||
for {
|
||||
h, err = createFile(path, syscall.GENERIC_READ|syscall.GENERIC_WRITE, 0, nil, syscall.OPEN_EXISTING, syscall.FILE_FLAG_OVERLAPPED|cSECURITY_SQOS_PRESENT|cSECURITY_ANONYMOUS, 0)
|
||||
if err != cERROR_PIPE_BUSY {
|
||||
break
|
||||
}
|
||||
if time.Now().After(absTimeout) {
|
||||
return nil, ErrTimeout
|
||||
}
|
||||
|
||||
// Wait 10 msec and try again. This is a rather simplistic
|
||||
// view, as we always try each 10 milliseconds.
|
||||
time.Sleep(time.Millisecond * 10)
|
||||
}
|
||||
h, err = tryDialPipe(ctx, &path)
|
||||
if err != nil {
|
||||
return nil, &os.PathError{Op: "open", Path: path, Err: err}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var flags uint32
|
||||
|
@ -194,43 +258,87 @@ type acceptResponse struct {
|
|||
}
|
||||
|
||||
type win32PipeListener struct {
|
||||
firstHandle syscall.Handle
|
||||
path string
|
||||
securityDescriptor []byte
|
||||
config PipeConfig
|
||||
acceptCh chan (chan acceptResponse)
|
||||
closeCh chan int
|
||||
doneCh chan int
|
||||
firstHandle syscall.Handle
|
||||
path string
|
||||
config PipeConfig
|
||||
acceptCh chan (chan acceptResponse)
|
||||
closeCh chan int
|
||||
doneCh chan int
|
||||
}
|
||||
|
||||
func makeServerPipeHandle(path string, securityDescriptor []byte, c *PipeConfig, first bool) (syscall.Handle, error) {
|
||||
var flags uint32 = cPIPE_ACCESS_DUPLEX | syscall.FILE_FLAG_OVERLAPPED
|
||||
if first {
|
||||
flags |= cFILE_FLAG_FIRST_PIPE_INSTANCE
|
||||
}
|
||||
|
||||
var mode uint32 = cPIPE_REJECT_REMOTE_CLIENTS
|
||||
if c.MessageMode {
|
||||
mode |= cPIPE_TYPE_MESSAGE
|
||||
}
|
||||
|
||||
sa := &syscall.SecurityAttributes{}
|
||||
sa.Length = uint32(unsafe.Sizeof(*sa))
|
||||
if securityDescriptor != nil {
|
||||
len := uint32(len(securityDescriptor))
|
||||
sa.SecurityDescriptor = localAlloc(0, len)
|
||||
defer localFree(sa.SecurityDescriptor)
|
||||
copy((*[0xffff]byte)(unsafe.Pointer(sa.SecurityDescriptor))[:], securityDescriptor)
|
||||
}
|
||||
h, err := createNamedPipe(path, flags, mode, cPIPE_UNLIMITED_INSTANCES, uint32(c.OutputBufferSize), uint32(c.InputBufferSize), 0, sa)
|
||||
func makeServerPipeHandle(path string, sd []byte, c *PipeConfig, first bool) (syscall.Handle, error) {
|
||||
path16, err := syscall.UTF16FromString(path)
|
||||
if err != nil {
|
||||
return 0, &os.PathError{Op: "open", Path: path, Err: err}
|
||||
}
|
||||
|
||||
var oa objectAttributes
|
||||
oa.Length = unsafe.Sizeof(oa)
|
||||
|
||||
var ntPath unicodeString
|
||||
if err := rtlDosPathNameToNtPathName(&path16[0], &ntPath, 0, 0).Err(); err != nil {
|
||||
return 0, &os.PathError{Op: "open", Path: path, Err: err}
|
||||
}
|
||||
defer localFree(ntPath.Buffer)
|
||||
oa.ObjectName = &ntPath
|
||||
|
||||
// The security descriptor is only needed for the first pipe.
|
||||
if first {
|
||||
if sd != nil {
|
||||
len := uint32(len(sd))
|
||||
sdb := localAlloc(0, len)
|
||||
defer localFree(sdb)
|
||||
copy((*[0xffff]byte)(unsafe.Pointer(sdb))[:], sd)
|
||||
oa.SecurityDescriptor = (*securityDescriptor)(unsafe.Pointer(sdb))
|
||||
} else {
|
||||
// Construct the default named pipe security descriptor.
|
||||
var dacl uintptr
|
||||
if err := rtlDefaultNpAcl(&dacl).Err(); err != nil {
|
||||
return 0, fmt.Errorf("getting default named pipe ACL: %s", err)
|
||||
}
|
||||
defer localFree(dacl)
|
||||
|
||||
sdb := &securityDescriptor{
|
||||
Revision: 1,
|
||||
Control: cSE_DACL_PRESENT,
|
||||
Dacl: dacl,
|
||||
}
|
||||
oa.SecurityDescriptor = sdb
|
||||
}
|
||||
}
|
||||
|
||||
typ := uint32(cFILE_PIPE_REJECT_REMOTE_CLIENTS)
|
||||
if c.MessageMode {
|
||||
typ |= cFILE_PIPE_MESSAGE_TYPE
|
||||
}
|
||||
|
||||
disposition := uint32(cFILE_OPEN)
|
||||
access := uint32(syscall.GENERIC_READ | syscall.GENERIC_WRITE | syscall.SYNCHRONIZE)
|
||||
if first {
|
||||
disposition = cFILE_CREATE
|
||||
// By not asking for read or write access, the named pipe file system
|
||||
// will put this pipe into an initially disconnected state, blocking
|
||||
// client connections until the next call with first == false.
|
||||
access = syscall.SYNCHRONIZE
|
||||
}
|
||||
|
||||
timeout := int64(-50 * 10000) // 50ms
|
||||
|
||||
var (
|
||||
h syscall.Handle
|
||||
iosb ioStatusBlock
|
||||
)
|
||||
err = ntCreateNamedPipeFile(&h, access, &oa, &iosb, syscall.FILE_SHARE_READ|syscall.FILE_SHARE_WRITE, disposition, 0, typ, 0, 0, 0xffffffff, uint32(c.InputBufferSize), uint32(c.OutputBufferSize), &timeout).Err()
|
||||
if err != nil {
|
||||
return 0, &os.PathError{Op: "open", Path: path, Err: err}
|
||||
}
|
||||
|
||||
runtime.KeepAlive(ntPath)
|
||||
return h, nil
|
||||
}
|
||||
|
||||
func (l *win32PipeListener) makeServerPipe() (*win32File, error) {
|
||||
h, err := makeServerPipeHandle(l.path, l.securityDescriptor, &l.config, false)
|
||||
h, err := makeServerPipeHandle(l.path, nil, &l.config, false)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -341,32 +449,13 @@ func ListenPipe(path string, c *PipeConfig) (net.Listener, error) {
|
|||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// Create a client handle and connect it. This results in the pipe
|
||||
// instance always existing, so that clients see ERROR_PIPE_BUSY
|
||||
// rather than ERROR_FILE_NOT_FOUND. This ties the first instance
|
||||
// up so that no other instances can be used. This would have been
|
||||
// cleaner if the Win32 API matched CreateFile with ConnectNamedPipe
|
||||
// instead of CreateNamedPipe. (Apparently created named pipes are
|
||||
// considered to be in listening state regardless of whether any
|
||||
// active calls to ConnectNamedPipe are outstanding.)
|
||||
h2, err := createFile(path, 0, 0, nil, syscall.OPEN_EXISTING, cSECURITY_SQOS_PRESENT|cSECURITY_ANONYMOUS, 0)
|
||||
if err != nil {
|
||||
syscall.Close(h)
|
||||
return nil, err
|
||||
}
|
||||
// Close the client handle. The server side of the instance will
|
||||
// still be busy, leading to ERROR_PIPE_BUSY instead of
|
||||
// ERROR_NOT_FOUND, as long as we don't close the server handle,
|
||||
// or disconnect the client with DisconnectNamedPipe.
|
||||
syscall.Close(h2)
|
||||
l := &win32PipeListener{
|
||||
firstHandle: h,
|
||||
path: path,
|
||||
securityDescriptor: sd,
|
||||
config: *c,
|
||||
acceptCh: make(chan (chan acceptResponse)),
|
||||
closeCh: make(chan int),
|
||||
doneCh: make(chan int),
|
||||
firstHandle: h,
|
||||
path: path,
|
||||
config: *c,
|
||||
acceptCh: make(chan (chan acceptResponse)),
|
||||
closeCh: make(chan int),
|
||||
doneCh: make(chan int),
|
||||
}
|
||||
go l.listenerRoutine()
|
||||
return l, nil
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// MACHINE GENERATED BY 'go generate' COMMAND; DO NOT EDIT
|
||||
// Code generated by 'go generate'; DO NOT EDIT.
|
||||
|
||||
package winio
|
||||
|
||||
|
@ -38,6 +38,7 @@ func errnoErr(e syscall.Errno) error {
|
|||
|
||||
var (
|
||||
modkernel32 = windows.NewLazySystemDLL("kernel32.dll")
|
||||
modntdll = windows.NewLazySystemDLL("ntdll.dll")
|
||||
modadvapi32 = windows.NewLazySystemDLL("advapi32.dll")
|
||||
|
||||
procCancelIoEx = modkernel32.NewProc("CancelIoEx")
|
||||
|
@ -47,10 +48,13 @@ var (
|
|||
procConnectNamedPipe = modkernel32.NewProc("ConnectNamedPipe")
|
||||
procCreateNamedPipeW = modkernel32.NewProc("CreateNamedPipeW")
|
||||
procCreateFileW = modkernel32.NewProc("CreateFileW")
|
||||
procWaitNamedPipeW = modkernel32.NewProc("WaitNamedPipeW")
|
||||
procGetNamedPipeInfo = modkernel32.NewProc("GetNamedPipeInfo")
|
||||
procGetNamedPipeHandleStateW = modkernel32.NewProc("GetNamedPipeHandleStateW")
|
||||
procLocalAlloc = modkernel32.NewProc("LocalAlloc")
|
||||
procNtCreateNamedPipeFile = modntdll.NewProc("NtCreateNamedPipeFile")
|
||||
procRtlNtStatusToDosErrorNoTeb = modntdll.NewProc("RtlNtStatusToDosErrorNoTeb")
|
||||
procRtlDosPathNameToNtPathName_U = modntdll.NewProc("RtlDosPathNameToNtPathName_U")
|
||||
procRtlDefaultNpAcl = modntdll.NewProc("RtlDefaultNpAcl")
|
||||
procLookupAccountNameW = modadvapi32.NewProc("LookupAccountNameW")
|
||||
procConvertSidToStringSidW = modadvapi32.NewProc("ConvertSidToStringSidW")
|
||||
procConvertStringSecurityDescriptorToSecurityDescriptorW = modadvapi32.NewProc("ConvertStringSecurityDescriptorToSecurityDescriptorW")
|
||||
|
@ -176,27 +180,6 @@ func _createFile(name *uint16, access uint32, mode uint32, sa *syscall.SecurityA
|
|||
return
|
||||
}
|
||||
|
||||
func waitNamedPipe(name string, timeout uint32) (err error) {
|
||||
var _p0 *uint16
|
||||
_p0, err = syscall.UTF16PtrFromString(name)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
return _waitNamedPipe(_p0, timeout)
|
||||
}
|
||||
|
||||
func _waitNamedPipe(name *uint16, timeout uint32) (err error) {
|
||||
r1, _, e1 := syscall.Syscall(procWaitNamedPipeW.Addr(), 2, uintptr(unsafe.Pointer(name)), uintptr(timeout), 0)
|
||||
if r1 == 0 {
|
||||
if e1 != 0 {
|
||||
err = errnoErr(e1)
|
||||
} else {
|
||||
err = syscall.EINVAL
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func getNamedPipeInfo(pipe syscall.Handle, flags *uint32, outSize *uint32, inSize *uint32, maxInstances *uint32) (err error) {
|
||||
r1, _, e1 := syscall.Syscall6(procGetNamedPipeInfo.Addr(), 5, uintptr(pipe), uintptr(unsafe.Pointer(flags)), uintptr(unsafe.Pointer(outSize)), uintptr(unsafe.Pointer(inSize)), uintptr(unsafe.Pointer(maxInstances)), 0)
|
||||
if r1 == 0 {
|
||||
|
@ -227,6 +210,32 @@ func localAlloc(uFlags uint32, length uint32) (ptr uintptr) {
|
|||
return
|
||||
}
|
||||
|
||||
func ntCreateNamedPipeFile(pipe *syscall.Handle, access uint32, oa *objectAttributes, iosb *ioStatusBlock, share uint32, disposition uint32, options uint32, typ uint32, readMode uint32, completionMode uint32, maxInstances uint32, inboundQuota uint32, outputQuota uint32, timeout *int64) (status ntstatus) {
|
||||
r0, _, _ := syscall.Syscall15(procNtCreateNamedPipeFile.Addr(), 14, uintptr(unsafe.Pointer(pipe)), uintptr(access), uintptr(unsafe.Pointer(oa)), uintptr(unsafe.Pointer(iosb)), uintptr(share), uintptr(disposition), uintptr(options), uintptr(typ), uintptr(readMode), uintptr(completionMode), uintptr(maxInstances), uintptr(inboundQuota), uintptr(outputQuota), uintptr(unsafe.Pointer(timeout)), 0)
|
||||
status = ntstatus(r0)
|
||||
return
|
||||
}
|
||||
|
||||
func rtlNtStatusToDosError(status ntstatus) (winerr error) {
|
||||
r0, _, _ := syscall.Syscall(procRtlNtStatusToDosErrorNoTeb.Addr(), 1, uintptr(status), 0, 0)
|
||||
if r0 != 0 {
|
||||
winerr = syscall.Errno(r0)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func rtlDosPathNameToNtPathName(name *uint16, ntName *unicodeString, filePart uintptr, reserved uintptr) (status ntstatus) {
|
||||
r0, _, _ := syscall.Syscall6(procRtlDosPathNameToNtPathName_U.Addr(), 4, uintptr(unsafe.Pointer(name)), uintptr(unsafe.Pointer(ntName)), uintptr(filePart), uintptr(reserved), 0, 0)
|
||||
status = ntstatus(r0)
|
||||
return
|
||||
}
|
||||
|
||||
func rtlDefaultNpAcl(dacl *uintptr) (status ntstatus) {
|
||||
r0, _, _ := syscall.Syscall(procRtlDefaultNpAcl.Addr(), 1, uintptr(unsafe.Pointer(dacl)), 0, 0)
|
||||
status = ntstatus(r0)
|
||||
return
|
||||
}
|
||||
|
||||
func lookupAccountName(systemName *uint16, accountName string, sid *byte, sidSize *uint32, refDomain *uint16, refDomainSize *uint32, sidNameUse *uint32) (err error) {
|
||||
var _p0 *uint16
|
||||
_p0, err = syscall.UTF16PtrFromString(accountName)
|
||||
|
|
|
@ -1,100 +0,0 @@
|
|||
package guestrequest
|
||||
|
||||
import (
|
||||
"github.com/Microsoft/hcsshim/internal/schema2"
|
||||
)
|
||||
|
||||
// Arguably, many of these (at least CombinedLayers) should have been generated
|
||||
// by swagger.
|
||||
//
|
||||
// This will also change package name due to an inbound breaking change.
|
||||
|
||||
// This class is used by a modify request to add or remove a combined layers
|
||||
// structure in the guest. For windows, the GCS applies a filter in ContainerRootPath
|
||||
// using the specified layers as the parent content. Ignores property ScratchPath
|
||||
// since the container path is already the scratch path. For linux, the GCS unions
|
||||
// the specified layers and ScratchPath together, placing the resulting union
|
||||
// filesystem at ContainerRootPath.
|
||||
type CombinedLayers struct {
|
||||
ContainerRootPath string `json:"ContainerRootPath,omitempty"`
|
||||
Layers []hcsschema.Layer `json:"Layers,omitempty"`
|
||||
ScratchPath string `json:"ScratchPath,omitempty"`
|
||||
}
|
||||
|
||||
// Defines the schema for hosted settings passed to GCS and/or OpenGCS
|
||||
|
||||
// SCSI. Scratch space for remote file-system commands, or R/W layer for containers
|
||||
type LCOWMappedVirtualDisk struct {
|
||||
MountPath string `json:"MountPath,omitempty"` // /tmp/scratch for an LCOW utility VM being used as a service VM
|
||||
Lun uint8 `json:"Lun,omitempty"`
|
||||
Controller uint8 `json:"Controller,omitempty"`
|
||||
ReadOnly bool `json:"ReadOnly,omitempty"`
|
||||
}
|
||||
|
||||
type WCOWMappedVirtualDisk struct {
|
||||
ContainerPath string `json:"ContainerPath,omitempty"`
|
||||
Lun int32 `json:"Lun,omitempty"`
|
||||
}
|
||||
|
||||
type LCOWMappedDirectory struct {
|
||||
MountPath string `json:"MountPath,omitempty"`
|
||||
Port int32 `json:"Port,omitempty"`
|
||||
ShareName string `json:"ShareName,omitempty"` // If empty not using ANames (not currently supported)
|
||||
ReadOnly bool `json:"ReadOnly,omitempty"`
|
||||
}
|
||||
|
||||
// Read-only layers over VPMem
|
||||
type LCOWMappedVPMemDevice struct {
|
||||
DeviceNumber uint32 `json:"DeviceNumber,omitempty"`
|
||||
MountPath string `json:"MountPath,omitempty"` // /tmp/pN
|
||||
}
|
||||
|
||||
type LCOWNetworkAdapter struct {
|
||||
NamespaceID string `json:",omitempty"`
|
||||
ID string `json:",omitempty"`
|
||||
MacAddress string `json:",omitempty"`
|
||||
IPAddress string `json:",omitempty"`
|
||||
PrefixLength uint8 `json:",omitempty"`
|
||||
GatewayAddress string `json:",omitempty"`
|
||||
DNSSuffix string `json:",omitempty"`
|
||||
DNSServerList string `json:",omitempty"`
|
||||
EnableLowMetric bool `json:",omitempty"`
|
||||
EncapOverhead uint16 `json:",omitempty"`
|
||||
}
|
||||
|
||||
type ResourceType string
|
||||
|
||||
const (
|
||||
// These are constants for v2 schema modify guest requests.
|
||||
ResourceTypeMappedDirectory ResourceType = "MappedDirectory"
|
||||
ResourceTypeMappedVirtualDisk ResourceType = "MappedVirtualDisk"
|
||||
ResourceTypeNetwork ResourceType = "Network"
|
||||
ResourceTypeNetworkNamespace ResourceType = "NetworkNamespace"
|
||||
ResourceTypeCombinedLayers ResourceType = "CombinedLayers"
|
||||
ResourceTypeVPMemDevice ResourceType = "VPMemDevice"
|
||||
)
|
||||
|
||||
// GuestRequest is for modify commands passed to the guest.
|
||||
type GuestRequest struct {
|
||||
RequestType string `json:"RequestType,omitempty"`
|
||||
ResourceType ResourceType `json:"ResourceType,omitempty"`
|
||||
Settings interface{} `json:"Settings,omitempty"`
|
||||
}
|
||||
|
||||
type NetworkModifyRequest struct {
|
||||
AdapterId string `json:"AdapterId,omitempty"`
|
||||
RequestType string `json:"RequestType,omitempty"`
|
||||
Settings interface{} `json:"Settings,omitempty"`
|
||||
}
|
||||
|
||||
type RS4NetworkModifyRequest struct {
|
||||
AdapterInstanceId string `json:"AdapterInstanceId,omitempty"`
|
||||
RequestType string `json:"RequestType,omitempty"`
|
||||
Settings interface{} `json:"Settings,omitempty"`
|
||||
}
|
||||
|
||||
// SignalProcessOptions is the options passed to either WCOW or LCOW
|
||||
// to signal a given process.
|
||||
type SignalProcessOptions struct {
|
||||
Signal int `json:,omitempty`
|
||||
}
|
|
@ -1,10 +1,12 @@
|
|||
package hcs
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"sync"
|
||||
"syscall"
|
||||
|
||||
"github.com/Microsoft/hcsshim/internal/interop"
|
||||
"github.com/Microsoft/hcsshim/internal/logfields"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
|
@ -40,16 +42,61 @@ var (
|
|||
)
|
||||
|
||||
type hcsNotification uint32
|
||||
|
||||
func (hn hcsNotification) String() string {
|
||||
switch hn {
|
||||
case hcsNotificationSystemExited:
|
||||
return "SystemExited"
|
||||
case hcsNotificationSystemCreateCompleted:
|
||||
return "SystemCreateCompleted"
|
||||
case hcsNotificationSystemStartCompleted:
|
||||
return "SystemStartCompleted"
|
||||
case hcsNotificationSystemPauseCompleted:
|
||||
return "SystemPauseCompleted"
|
||||
case hcsNotificationSystemResumeCompleted:
|
||||
return "SystemResumeCompleted"
|
||||
case hcsNotificationSystemCrashReport:
|
||||
return "SystemCrashReport"
|
||||
case hcsNotificationSystemSiloJobCreated:
|
||||
return "SystemSiloJobCreated"
|
||||
case hcsNotificationSystemSaveCompleted:
|
||||
return "SystemSaveCompleted"
|
||||
case hcsNotificationSystemRdpEnhancedModeStateChanged:
|
||||
return "SystemRdpEnhancedModeStateChanged"
|
||||
case hcsNotificationSystemShutdownFailed:
|
||||
return "SystemShutdownFailed"
|
||||
case hcsNotificationSystemGetPropertiesCompleted:
|
||||
return "SystemGetPropertiesCompleted"
|
||||
case hcsNotificationSystemModifyCompleted:
|
||||
return "SystemModifyCompleted"
|
||||
case hcsNotificationSystemCrashInitiated:
|
||||
return "SystemCrashInitiated"
|
||||
case hcsNotificationSystemGuestConnectionClosed:
|
||||
return "SystemGuestConnectionClosed"
|
||||
case hcsNotificationProcessExited:
|
||||
return "ProcessExited"
|
||||
case hcsNotificationInvalid:
|
||||
return "Invalid"
|
||||
case hcsNotificationServiceDisconnect:
|
||||
return "ServiceDisconnect"
|
||||
default:
|
||||
return fmt.Sprintf("Unknown: %d", hn)
|
||||
}
|
||||
}
|
||||
|
||||
type notificationChannel chan error
|
||||
|
||||
type notifcationWatcherContext struct {
|
||||
channels notificationChannels
|
||||
handle hcsCallback
|
||||
|
||||
systemID string
|
||||
processID int
|
||||
}
|
||||
|
||||
type notificationChannels map[hcsNotification]notificationChannel
|
||||
|
||||
func newChannels() notificationChannels {
|
||||
func newSystemChannels() notificationChannels {
|
||||
channels := make(notificationChannels)
|
||||
|
||||
channels[hcsNotificationSystemExited] = make(notificationChannel, 1)
|
||||
|
@ -57,17 +104,14 @@ func newChannels() notificationChannels {
|
|||
channels[hcsNotificationSystemStartCompleted] = make(notificationChannel, 1)
|
||||
channels[hcsNotificationSystemPauseCompleted] = make(notificationChannel, 1)
|
||||
channels[hcsNotificationSystemResumeCompleted] = make(notificationChannel, 1)
|
||||
|
||||
return channels
|
||||
}
|
||||
|
||||
func newProcessChannels() notificationChannels {
|
||||
channels := make(notificationChannels)
|
||||
|
||||
channels[hcsNotificationProcessExited] = make(notificationChannel, 1)
|
||||
channels[hcsNotificationServiceDisconnect] = make(notificationChannel, 1)
|
||||
channels[hcsNotificationSystemCrashReport] = make(notificationChannel, 1)
|
||||
channels[hcsNotificationSystemSiloJobCreated] = make(notificationChannel, 1)
|
||||
channels[hcsNotificationSystemSaveCompleted] = make(notificationChannel, 1)
|
||||
channels[hcsNotificationSystemRdpEnhancedModeStateChanged] = make(notificationChannel, 1)
|
||||
channels[hcsNotificationSystemShutdownFailed] = make(notificationChannel, 1)
|
||||
channels[hcsNotificationSystemGetPropertiesCompleted] = make(notificationChannel, 1)
|
||||
channels[hcsNotificationSystemModifyCompleted] = make(notificationChannel, 1)
|
||||
channels[hcsNotificationSystemCrashInitiated] = make(notificationChannel, 1)
|
||||
channels[hcsNotificationSystemGuestConnectionClosed] = make(notificationChannel, 1)
|
||||
|
||||
return channels
|
||||
}
|
||||
|
@ -92,12 +136,28 @@ func notificationWatcher(notificationType hcsNotification, callbackNumber uintpt
|
|||
return 0
|
||||
}
|
||||
|
||||
log := logrus.WithFields(logrus.Fields{
|
||||
"notification-type": notificationType.String(),
|
||||
"system-id": context.systemID,
|
||||
})
|
||||
if context.processID != 0 {
|
||||
log.Data[logfields.ProcessID] = context.processID
|
||||
}
|
||||
log.Debug("")
|
||||
|
||||
// The HCS notification system can grow overtime. We explicitly opt-in to
|
||||
// the notifications we would like to handle, all others we simply return.
|
||||
// This means that as it grows we don't have issues associated with new
|
||||
// notification types the code didn't know about.
|
||||
switch notificationType {
|
||||
case hcsNotificationSystemExited, hcsNotificationSystemCreateCompleted, hcsNotificationSystemStartCompleted, hcsNotificationSystemPauseCompleted, hcsNotificationSystemResumeCompleted:
|
||||
case hcsNotificationProcessExited:
|
||||
default:
|
||||
return 0
|
||||
}
|
||||
|
||||
if channel, ok := context.channels[notificationType]; ok {
|
||||
channel <- result
|
||||
} else {
|
||||
logrus.WithFields(logrus.Fields{
|
||||
"notification-type": notificationType,
|
||||
}).Warn("Received a callback of an unsupported type")
|
||||
}
|
||||
|
||||
return 0
|
||||
|
|
|
@ -272,6 +272,13 @@ func IsNotSupported(err error) bool {
|
|||
err == ErrVmcomputeUnknownMessage
|
||||
}
|
||||
|
||||
// IsOperationInvalidState returns true when err is caused by
|
||||
// `ErrVmcomputeOperationInvalidState`.
|
||||
func IsOperationInvalidState(err error) bool {
|
||||
err = getInnerError(err)
|
||||
return err == ErrVmcomputeOperationInvalidState
|
||||
}
|
||||
|
||||
func getInnerError(err error) error {
|
||||
switch pe := err.(type) {
|
||||
case nil:
|
||||
|
|
|
@ -27,7 +27,7 @@ import (
|
|||
//sys hcsOpenProcess(computeSystem hcsSystem, pid uint32, process *hcsProcess, result **uint16) (hr error) = vmcompute.HcsOpenProcess?
|
||||
//sys hcsCloseProcess(process hcsProcess) (hr error) = vmcompute.HcsCloseProcess?
|
||||
//sys hcsTerminateProcess(process hcsProcess, result **uint16) (hr error) = vmcompute.HcsTerminateProcess?
|
||||
//sys hcsSignalProcess(process hcsProcess, options string, result **uint16) (hr error) = vmcompute.HcsTerminateProcess?
|
||||
//sys hcsSignalProcess(process hcsProcess, options string, result **uint16) (hr error) = vmcompute.HcsSignalProcess?
|
||||
//sys hcsGetProcessInfo(process hcsProcess, processInformation *hcsProcessInformation, result **uint16) (hr error) = vmcompute.HcsGetProcessInfo?
|
||||
//sys hcsGetProcessProperties(process hcsProcess, processProperties **uint16, result **uint16) (hr error) = vmcompute.HcsGetProcessProperties?
|
||||
//sys hcsModifyProcess(process hcsProcess, settings string, result **uint16) (hr error) = vmcompute.HcsModifyProcess?
|
||||
|
|
|
@ -7,7 +7,6 @@ import (
|
|||
"syscall"
|
||||
"time"
|
||||
|
||||
"github.com/Microsoft/hcsshim/internal/guestrequest"
|
||||
"github.com/Microsoft/hcsshim/internal/interop"
|
||||
"github.com/Microsoft/hcsshim/internal/logfields"
|
||||
"github.com/sirupsen/logrus"
|
||||
|
@ -112,7 +111,11 @@ func (process *Process) logOperationEnd(operation string, err error) {
|
|||
}
|
||||
|
||||
// Signal signals the process with `options`.
|
||||
func (process *Process) Signal(options guestrequest.SignalProcessOptions) (err error) {
|
||||
//
|
||||
// For LCOW `guestrequest.SignalProcessOptionsLCOW`.
|
||||
//
|
||||
// For WCOW `guestrequest.SignalProcessOptionsWCOW`.
|
||||
func (process *Process) Signal(options interface{}) (err error) {
|
||||
process.handleLock.RLock()
|
||||
defer process.handleLock.RUnlock()
|
||||
|
||||
|
@ -189,7 +192,7 @@ func (process *Process) Wait() (err error) {
|
|||
|
||||
<-process.waitBlock
|
||||
if process.waitError != nil {
|
||||
return makeProcessError(process, operation, err, nil)
|
||||
return makeProcessError(process, operation, process.waitError, nil)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
@ -432,7 +435,9 @@ func (process *Process) Close() (err error) {
|
|||
|
||||
func (process *Process) registerCallback() error {
|
||||
context := ¬ifcationWatcherContext{
|
||||
channels: newChannels(),
|
||||
channels: newProcessChannels(),
|
||||
systemID: process.SystemID(),
|
||||
processID: process.processID,
|
||||
}
|
||||
|
||||
callbackMapLock.Lock()
|
||||
|
|
|
@ -414,18 +414,19 @@ func (computeSystem *System) Properties(types ...schema1.PropertyType) (_ *schem
|
|||
computeSystem.logOperationBegin(operation)
|
||||
defer func() { computeSystem.logOperationEnd(operation, err) }()
|
||||
|
||||
queryj, err := json.Marshal(schema1.PropertyQuery{types})
|
||||
queryBytes, err := json.Marshal(schema1.PropertyQuery{PropertyTypes: types})
|
||||
if err != nil {
|
||||
return nil, makeSystemError(computeSystem, "Properties", "", err, nil)
|
||||
}
|
||||
|
||||
queryString := string(queryBytes)
|
||||
logrus.WithFields(computeSystem.logctx).
|
||||
WithField(logfields.JSON, queryj).
|
||||
WithField(logfields.JSON, queryString).
|
||||
Debug("HCS ComputeSystem Properties Query")
|
||||
|
||||
var resultp, propertiesp *uint16
|
||||
syscallWatcher(computeSystem.logctx, func() {
|
||||
err = hcsGetComputeSystemProperties(computeSystem.handle, string(queryj), &propertiesp, &resultp)
|
||||
err = hcsGetComputeSystemProperties(computeSystem.handle, string(queryString), &propertiesp, &resultp)
|
||||
})
|
||||
events := processHcsResult(resultp)
|
||||
if err != nil {
|
||||
|
@ -625,7 +626,8 @@ func (computeSystem *System) Close() (err error) {
|
|||
|
||||
func (computeSystem *System) registerCallback() error {
|
||||
context := ¬ifcationWatcherContext{
|
||||
channels: newChannels(),
|
||||
channels: newSystemChannels(),
|
||||
systemID: computeSystem.id,
|
||||
}
|
||||
|
||||
callbackMapLock.Lock()
|
||||
|
|
|
@ -56,13 +56,13 @@ var (
|
|||
procHcsOpenProcess = modvmcompute.NewProc("HcsOpenProcess")
|
||||
procHcsCloseProcess = modvmcompute.NewProc("HcsCloseProcess")
|
||||
procHcsTerminateProcess = modvmcompute.NewProc("HcsTerminateProcess")
|
||||
|
||||
procHcsGetProcessInfo = modvmcompute.NewProc("HcsGetProcessInfo")
|
||||
procHcsGetProcessProperties = modvmcompute.NewProc("HcsGetProcessProperties")
|
||||
procHcsModifyProcess = modvmcompute.NewProc("HcsModifyProcess")
|
||||
procHcsGetServiceProperties = modvmcompute.NewProc("HcsGetServiceProperties")
|
||||
procHcsRegisterProcessCallback = modvmcompute.NewProc("HcsRegisterProcessCallback")
|
||||
procHcsUnregisterProcessCallback = modvmcompute.NewProc("HcsUnregisterProcessCallback")
|
||||
procHcsSignalProcess = modvmcompute.NewProc("HcsSignalProcess")
|
||||
procHcsGetProcessInfo = modvmcompute.NewProc("HcsGetProcessInfo")
|
||||
procHcsGetProcessProperties = modvmcompute.NewProc("HcsGetProcessProperties")
|
||||
procHcsModifyProcess = modvmcompute.NewProc("HcsModifyProcess")
|
||||
procHcsGetServiceProperties = modvmcompute.NewProc("HcsGetServiceProperties")
|
||||
procHcsRegisterProcessCallback = modvmcompute.NewProc("HcsRegisterProcessCallback")
|
||||
procHcsUnregisterProcessCallback = modvmcompute.NewProc("HcsUnregisterProcessCallback")
|
||||
)
|
||||
|
||||
func hcsEnumerateComputeSystems(query string, computeSystems **uint16, result **uint16) (hr error) {
|
||||
|
@ -417,10 +417,10 @@ func hcsSignalProcess(process hcsProcess, options string, result **uint16) (hr e
|
|||
}
|
||||
|
||||
func _hcsSignalProcess(process hcsProcess, options *uint16, result **uint16) (hr error) {
|
||||
if hr = procHcsTerminateProcess.Find(); hr != nil {
|
||||
if hr = procHcsSignalProcess.Find(); hr != nil {
|
||||
return
|
||||
}
|
||||
r0, _, _ := syscall.Syscall(procHcsTerminateProcess.Addr(), 3, uintptr(process), uintptr(unsafe.Pointer(options)), uintptr(unsafe.Pointer(result)))
|
||||
r0, _, _ := syscall.Syscall(procHcsSignalProcess.Addr(), 3, uintptr(process), uintptr(unsafe.Pointer(options)), uintptr(unsafe.Pointer(result)))
|
||||
if int32(r0) < 0 {
|
||||
if r0&0x1fff0000 == 0x00070000 {
|
||||
r0 &= 0xffff
|
||||
|
|
51
vendor/github.com/Microsoft/hcsshim/osversion/osversion_windows.go
generated
vendored
Normal file
51
vendor/github.com/Microsoft/hcsshim/osversion/osversion_windows.go
generated
vendored
Normal file
|
@ -0,0 +1,51 @@
|
|||
package osversion
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"golang.org/x/sys/windows"
|
||||
)
|
||||
|
||||
// OSVersion is a wrapper for Windows version information
|
||||
// https://msdn.microsoft.com/en-us/library/windows/desktop/ms724439(v=vs.85).aspx
|
||||
type OSVersion struct {
|
||||
Version uint32
|
||||
MajorVersion uint8
|
||||
MinorVersion uint8
|
||||
Build uint16
|
||||
}
|
||||
|
||||
// https://msdn.microsoft.com/en-us/library/windows/desktop/ms724833(v=vs.85).aspx
|
||||
type osVersionInfoEx struct {
|
||||
OSVersionInfoSize uint32
|
||||
MajorVersion uint32
|
||||
MinorVersion uint32
|
||||
BuildNumber uint32
|
||||
PlatformID uint32
|
||||
CSDVersion [128]uint16
|
||||
ServicePackMajor uint16
|
||||
ServicePackMinor uint16
|
||||
SuiteMask uint16
|
||||
ProductType byte
|
||||
Reserve byte
|
||||
}
|
||||
|
||||
// Get gets the operating system version on Windows.
|
||||
// The calling application must be manifested to get the correct version information.
|
||||
func Get() OSVersion {
|
||||
var err error
|
||||
osv := OSVersion{}
|
||||
osv.Version, err = windows.GetVersion()
|
||||
if err != nil {
|
||||
// GetVersion never fails.
|
||||
panic(err)
|
||||
}
|
||||
osv.MajorVersion = uint8(osv.Version & 0xFF)
|
||||
osv.MinorVersion = uint8(osv.Version >> 8 & 0xFF)
|
||||
osv.Build = uint16(osv.Version >> 16)
|
||||
return osv
|
||||
}
|
||||
|
||||
func (osv OSVersion) ToString() string {
|
||||
return fmt.Sprintf("%d.%d.%d", osv.MajorVersion, osv.MinorVersion, osv.Build)
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
package osversion
|
||||
|
||||
const (
|
||||
// RS1 (version 1607, codename "Redstone 1") corresponds to Windows Server
|
||||
// 2016 (ltsc2016) and Windows 10 (Anniversary Update).
|
||||
RS1 = 14393
|
||||
|
||||
// RS2 (version 1703, codename "Redstone 2") was a client-only update, and
|
||||
// corresponds to Windows 10 (Creators Update).
|
||||
RS2 = 15063
|
||||
|
||||
// RS3 (version 1709, codename "Redstone 3") corresponds to Windows Server
|
||||
// 1709 (Semi-Annual Channel (SAC)), and Windows 10 (Fall Creators Update).
|
||||
RS3 = 16299
|
||||
|
||||
// RS4 (version 1803, codename "Redstone 4") corresponds to Windows Server
|
||||
// 1809 (Semi-Annual Channel (SAC)), and Windows 10 (April 2018 Update).
|
||||
RS4 = 17134
|
||||
|
||||
// RS5 (version 1809, codename "Redstone 5") corresponds to Windows Server
|
||||
// 2019 (ltsc2019), and Windows 10 (October 2018 Update).
|
||||
RS5 = 17763
|
||||
)
|
|
@ -10,7 +10,7 @@ github.com/hashicorp/errwrap 7554cd9344cec97297fa6649b055a8c98c2a1e55
|
|||
github.com/hashicorp/go-multierror ed905158d87462226a13fe39ddf685ea65f1c11f
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.1
|
||||
github.com/linuxkit/virtsock 8e79449dea0735c1c056d814934dd035734cc97c
|
||||
github.com/Microsoft/go-winio c599b533b43b1363d7d7c6cfda5ede70ed73ff13
|
||||
github.com/Microsoft/go-winio 84b4ab48a50763fe7b3abcef38e5205c12027fac
|
||||
github.com/Microsoft/opengcs v0.3.9
|
||||
github.com/opencontainers/go-digest c9281466c8b2f606084ac71339773efd177436e7
|
||||
github.com/opencontainers/runc 12f6a991201fdb8f82579582d5e00e28fba06d0a
|
||||
|
|
|
@ -81,6 +81,15 @@ type Client struct {
|
|||
customHTTPHeaders map[string]string
|
||||
// manualOverride is set to true when the version was set by users.
|
||||
manualOverride bool
|
||||
|
||||
// negotiateVersion indicates if the client should automatically negotiate
|
||||
// the API version to use when making requests. API version negotiation is
|
||||
// performed on the first request, after which negotiated is set to "true"
|
||||
// so that subsequent requests do not re-negotiate.
|
||||
negotiateVersion bool
|
||||
|
||||
// negotiated indicates that API version negotiation took place
|
||||
negotiated bool
|
||||
}
|
||||
|
||||
// CheckRedirect specifies the policy for dealing with redirect responses:
|
||||
|
@ -169,8 +178,11 @@ func (cli *Client) Close() error {
|
|||
|
||||
// getAPIPath returns the versioned request path to call the api.
|
||||
// It appends the query parameters to the path if they are not empty.
|
||||
func (cli *Client) getAPIPath(p string, query url.Values) string {
|
||||
func (cli *Client) getAPIPath(ctx context.Context, p string, query url.Values) string {
|
||||
var apiPath string
|
||||
if cli.negotiateVersion && !cli.negotiated {
|
||||
cli.NegotiateAPIVersion(ctx)
|
||||
}
|
||||
if cli.version != "" {
|
||||
v := strings.TrimPrefix(cli.version, "v")
|
||||
apiPath = path.Join(cli.basePath, "/v"+v, p)
|
||||
|
@ -186,19 +198,31 @@ func (cli *Client) ClientVersion() string {
|
|||
}
|
||||
|
||||
// NegotiateAPIVersion queries the API and updates the version to match the
|
||||
// API version. Any errors are silently ignored.
|
||||
// API version. Any errors are silently ignored. If a manual override is in place,
|
||||
// either through the `DOCKER_API_VERSION` environment variable, or if the client
|
||||
// was initialized with a fixed version (`opts.WithVersion(xx)`), no negotiation
|
||||
// will be performed.
|
||||
func (cli *Client) NegotiateAPIVersion(ctx context.Context) {
|
||||
ping, _ := cli.Ping(ctx)
|
||||
cli.NegotiateAPIVersionPing(ping)
|
||||
if !cli.manualOverride {
|
||||
ping, _ := cli.Ping(ctx)
|
||||
cli.negotiateAPIVersionPing(ping)
|
||||
}
|
||||
}
|
||||
|
||||
// NegotiateAPIVersionPing updates the client version to match the Ping.APIVersion
|
||||
// if the ping version is less than the default version.
|
||||
// if the ping version is less than the default version. If a manual override is
|
||||
// in place, either through the `DOCKER_API_VERSION` environment variable, or if
|
||||
// the client was initialized with a fixed version (`opts.WithVersion(xx)`), no
|
||||
// negotiation is performed.
|
||||
func (cli *Client) NegotiateAPIVersionPing(p types.Ping) {
|
||||
if cli.manualOverride {
|
||||
return
|
||||
if !cli.manualOverride {
|
||||
cli.negotiateAPIVersionPing(p)
|
||||
}
|
||||
}
|
||||
|
||||
// negotiateAPIVersionPing queries the API and updates the version to match the
|
||||
// API version. Any errors are silently ignored.
|
||||
func (cli *Client) negotiateAPIVersionPing(p types.Ping) {
|
||||
// try the latest version before versioning headers existed
|
||||
if p.APIVersion == "" {
|
||||
p.APIVersion = "1.24"
|
||||
|
@ -213,6 +237,12 @@ func (cli *Client) NegotiateAPIVersionPing(p types.Ping) {
|
|||
if versions.LessThan(p.APIVersion, cli.version) {
|
||||
cli.version = p.APIVersion
|
||||
}
|
||||
|
||||
// Store the results, so that automatic API version negotiation (if enabled)
|
||||
// won't be performed on the next request.
|
||||
if cli.negotiateVersion {
|
||||
cli.negotiated = true
|
||||
}
|
||||
}
|
||||
|
||||
// DaemonHost returns the host address used by the client
|
||||
|
|
|
@ -23,7 +23,7 @@ func (cli *Client) postHijacked(ctx context.Context, path string, query url.Valu
|
|||
return types.HijackedResponse{}, err
|
||||
}
|
||||
|
||||
apiPath := cli.getAPIPath(path, query)
|
||||
apiPath := cli.getAPIPath(ctx, path, query)
|
||||
req, err := http.NewRequest("POST", apiPath, bodyEncoded)
|
||||
if err != nil {
|
||||
return types.HijackedResponse{}, err
|
||||
|
|
|
@ -159,3 +159,14 @@ func WithVersion(version string) Opt {
|
|||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// WithAPIVersionNegotiation enables automatic API version negotiation for the client.
|
||||
// With this option enabled, the client automatically negotiates the API version
|
||||
// to use when making requests. API version negotiation is performed on the first
|
||||
// request; subsequent requests will not re-negotiate.
|
||||
func WithAPIVersionNegotiation() Opt {
|
||||
return func(c *Client) error {
|
||||
c.negotiateVersion = true
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
|
|
@ -115,7 +115,7 @@ func (cli *Client) buildRequest(method, path string, body io.Reader, headers hea
|
|||
}
|
||||
|
||||
func (cli *Client) sendRequest(ctx context.Context, method, path string, query url.Values, body io.Reader, headers headers) (serverResponse, error) {
|
||||
req, err := cli.buildRequest(method, cli.getAPIPath(path, query), body, headers)
|
||||
req, err := cli.buildRequest(method, cli.getAPIPath(ctx, path, query), body, headers)
|
||||
if err != nil {
|
||||
return serverResponse{}, err
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@ package system // import "github.com/docker/docker/pkg/system"
|
|||
import (
|
||||
"os"
|
||||
|
||||
"github.com/Microsoft/hcsshim/osversion"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
|
@ -15,10 +16,10 @@ var (
|
|||
containerdRuntimeSupported = false
|
||||
)
|
||||
|
||||
// InitLCOW sets whether LCOW is supported or not
|
||||
// InitLCOW sets whether LCOW is supported or not. Requires RS5+
|
||||
func InitLCOW(experimental bool) {
|
||||
v := GetOSVersion()
|
||||
if experimental && v.Build >= 16299 {
|
||||
if experimental && v.Build >= osversion.RS5 {
|
||||
lcowSupported = true
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
github.com/Azure/go-ansiterm d6e3b3328b783f23731bc4d058875b0371ff8109
|
||||
github.com/Microsoft/hcsshim ba3d6667710fa905116f39a19d059c4c1016be7c
|
||||
github.com/Microsoft/hcsshim 672e52e9209d1e53718c1b6a7d68cc9272654ab5
|
||||
github.com/Microsoft/go-winio c599b533b43b1363d7d7c6cfda5ede70ed73ff13
|
||||
github.com/docker/libtrust 9cbd2a1374f46905c68a4eb3694a130610adc62a
|
||||
github.com/go-check/check 4ed411733c5785b40214c70bce814c3a3a689609 https://github.com/cpuguy83/check.git
|
||||
|
@ -16,7 +16,7 @@ github.com/tchap/go-patricia a7f0089c6f496e8e70402f617336
|
|||
github.com/vdemeester/shakers 24d7f1d6a71aa5d9cbe7390e4afb66b7eef9e1b3 # v0.1.0
|
||||
golang.org/x/net eb5bcb51f2a31c7d5141d810b70815c05d9c9146
|
||||
golang.org/x/sys 4b34438f7a67ee5f45cc6132e2bad873a20324e9
|
||||
github.com/docker/go-units 47565b4f722fb6ceae66b95f853feed578a4a51c # v0.3.3
|
||||
github.com/docker/go-units 519db1ee28dcc9fd2474ae59fca29a810482bfb1 # v0.4.0
|
||||
github.com/docker/go-connections 7395e3f8aa162843a74ed6d48e79627d9792ac55 # v0.4.0
|
||||
golang.org/x/text f21a4dfb5e38f5895301dc265a8def02365cc3d0 # v0.3.0
|
||||
gotest.tools 1083505acf35a0bd8a696b26837e1fb3187a7a83 # v2.3.0
|
||||
|
@ -27,7 +27,7 @@ github.com/imdario/mergo 7c29201646fa3de8506f70121347
|
|||
golang.org/x/sync e225da77a7e68af35c70ccbf71af2b83e6acac3c
|
||||
|
||||
# buildkit
|
||||
github.com/moby/buildkit b3028967ae6259c9a31c1a1deeccd30fe3469cce
|
||||
github.com/moby/buildkit 8818c67cff663befa7b70f21454e340f71616581
|
||||
github.com/tonistiigi/fsutil 3bbb99cdbd76619ab717299830c60f6f2a533a6b
|
||||
github.com/grpc-ecosystem/grpc-opentracing 8e809c8a86450a29b90dcc9efbf062d0fe6d9746
|
||||
github.com/opentracing/opentracing-go 1361b9cd60be79c4c3a7fa9841b3c132e40066a7
|
||||
|
@ -39,7 +39,7 @@ github.com/gofrs/flock 7f43ea2e6a643ad441fc12d0ecc0
|
|||
# libnetwork
|
||||
|
||||
# When updating, also update LIBNETWORK_COMMIT in hack/dockerfile/install/proxy.installer accordingly
|
||||
github.com/docker/libnetwork 48f846327bbe6a0dce0c556e8dc9f5bb939d5c16
|
||||
github.com/docker/libnetwork 9ff9b57c344df5cd47443ad9e65702ec85c5aeb0
|
||||
github.com/docker/go-events 9461782956ad83b30282bf90e31fa6a70c255ba9
|
||||
github.com/armon/go-radix e39d623f12e8e41c7b5529e9a9dd67a1e2261f80
|
||||
github.com/armon/go-metrics eb0af217e5e9747e41dd5303755356b62d28e3ec
|
||||
|
@ -57,7 +57,7 @@ github.com/vishvananda/netlink b2de5d10e38ecce8607e6b438b6d
|
|||
github.com/BurntSushi/toml 3012a1dbe2e4bd1391d42b32f0577cb7bbc7f005 # v0.3.1
|
||||
github.com/samuel/go-zookeeper d0e0d8e11f318e000a8cc434616d69e329edc374
|
||||
github.com/deckarep/golang-set ef32fa3046d9f249d399f98ebaf9be944430fd1d
|
||||
github.com/coreos/etcd fca8add78a9d926166eb739b8e4a124434025ba3 # v3.3.9
|
||||
github.com/coreos/etcd d57e8b8d97adfc4a6c224fe116714bf1a1f3beb9 # v3.3.12
|
||||
github.com/coreos/go-semver 8ab6407b697782a06568d4b7f1db25550ec2e4c6 # v0.2.0
|
||||
github.com/ugorji/go b4c50a2b199d93b13dc15e78929cfb23bfdf21ab # v1.1.1
|
||||
github.com/hashicorp/consul 9a9cc9341bb487651a0399e3fc5e1e8a42e62dd9 # v0.5.2
|
||||
|
@ -95,9 +95,9 @@ github.com/golang/protobuf aa810b61a9c79d51363740d207bb
|
|||
github.com/Graylog2/go-gelf 4143646226541087117ff2f83334ea48b3201841
|
||||
|
||||
# fluent-logger-golang deps
|
||||
github.com/fluent/fluent-logger-golang 8bbc2356beaf021b04c9bd5cdc76ea5a7ccb40ec # v1.3.0
|
||||
github.com/fluent/fluent-logger-golang 7a6c9dcd7f14c2ed5d8c55c11b894e5455ee311b # v1.4.0
|
||||
github.com/philhofer/fwd bb6d471dc95d4fe11e432687f8b70ff496cf3136 # v1.0.0
|
||||
github.com/tinylib/msgp 3b556c64540842d4f82967be066a7f7fffc3adad
|
||||
github.com/tinylib/msgp af6442a0fcf6e2a1b824f70dd0c734f01e817751 # v1.1.0
|
||||
|
||||
# fsnotify
|
||||
github.com/fsnotify/fsnotify 1485a34d5d5723fea214f5710708e19a831720e4 # v1.4.7-11-g1485a34
|
||||
|
@ -150,7 +150,7 @@ github.com/prometheus/client_model 6f3806018612930941127f2a7c6c
|
|||
github.com/prometheus/common 7600349dcfe1abd18d72d3a1770870d9800a7801
|
||||
github.com/prometheus/procfs 7d6f385de8bea29190f15ba9931442a0eaef9af7
|
||||
github.com/matttproud/golang_protobuf_extensions c12348ce28de40eed0136aa2b644d0ee0650e56c # v1.0.1
|
||||
github.com/pkg/errors 645ef00459ed84a119197bfb8d8205042c6df63d # v0.8.0
|
||||
github.com/pkg/errors ba968bfe8b2f7e042a574c888954fccecfa385b4 # v0.8.1
|
||||
github.com/grpc-ecosystem/go-grpc-prometheus c225b8c3b01faf2899099b768856a9e916e5087b # v1.2.0
|
||||
|
||||
# cli
|
||||
|
|
|
@ -38,7 +38,7 @@ BuildKit is used by the following projects:
|
|||
- [OpenFaaS Cloud](https://github.com/openfaas/openfaas-cloud)
|
||||
- [container build interface](https://github.com/containerbuilding/cbi)
|
||||
- [Knative Build Templates](https://github.com/knative/build-templates)
|
||||
- [boss](https://github.com/crosbymichael/boss)
|
||||
- [vab](https://github.com/stellarproject/vab)
|
||||
- [Rio](https://github.com/rancher/rio) (on roadmap)
|
||||
|
||||
### Quick start
|
||||
|
@ -100,7 +100,7 @@ To start building use `buildctl build` command. The example script accepts `--wi
|
|||
go run examples/buildkit0/buildkit.go | buildctl build
|
||||
```
|
||||
|
||||
`buildctl build` will show interactive progress bar by default while the build job is running. It will also show you the path to the trace file that contains all information about the timing of the individual steps and logs.
|
||||
`buildctl build` will show interactive progress bar by default while the build job is running. If the path to the trace file is specified, the trace file generated will contain all information about the timing of the individual steps and logs.
|
||||
|
||||
Different versions of the example scripts show different ways of describing the build definition for this project to show the capabilities of the library. New versions have been added when new features have become available.
|
||||
|
||||
|
@ -218,8 +218,8 @@ buildctl build ... --import-cache type=registry,ref=localhost:5000/myrepo:buildc
|
|||
#### To/From local filesystem
|
||||
|
||||
```
|
||||
buildctl build ... --export-cache type=local,src=path/to/input-dir
|
||||
buildctl build ... --import-cache type=local,dest=path/to/output-dir
|
||||
buildctl build ... --export-cache type=local,dest=path/to/output-dir
|
||||
buildctl build ... --import-cache type=local,src=path/to/input-dir
|
||||
```
|
||||
|
||||
The directory layout conforms to OCI Image Spec v1.0.
|
||||
|
@ -228,11 +228,11 @@ The directory layout conforms to OCI Image Spec v1.0.
|
|||
* `mode=min` (default): only export layers for the resulting image
|
||||
* `mode=max`: export all the layers of all intermediate steps
|
||||
* `ref=docker.io/user/image:tag`: reference for `registry` cache exporter
|
||||
* `src=path/to/output-dir`: directory for `local` cache exporter
|
||||
* `dest=path/to/output-dir`: directory for `local` cache exporter
|
||||
|
||||
#### `--import-cache` options
|
||||
* `ref=docker.io/user/image:tag`: reference for `registry` cache importer
|
||||
* `dest=path/to/input-dir`: directory for `local` cache importer
|
||||
* `src=path/to/input-dir`: directory for `local` cache importer
|
||||
* `digest=sha256:deadbeef`: digest of the manifest list to import for `local` cache importer. Defaults to the digest of "latest" tag in `index.json`
|
||||
|
||||
### Other
|
||||
|
@ -271,6 +271,18 @@ buildctl build --help
|
|||
The images can be also built locally using `./hack/dockerfiles/test.Dockerfile` (or `./hack/dockerfiles/test.buildkit.Dockerfile` if you already have BuildKit).
|
||||
Run `make images` to build the images as `moby/buildkit:local` and `moby/buildkit:local-rootless`.
|
||||
|
||||
#### Connection helpers
|
||||
|
||||
If you are running `moby/buildkit:master` or `moby/buildkit:master-rootless` as a Docker/Kubernetes container, you can use special `BUILDKIT_HOST` URL for connecting to the BuildKit daemon in the container:
|
||||
|
||||
```
|
||||
export BUILDKIT_HOST=docker://<container>
|
||||
```
|
||||
|
||||
```
|
||||
export BUILDKIT_HOST=kube-pod://<pod>
|
||||
```
|
||||
|
||||
### Opentracing support
|
||||
|
||||
BuildKit supports opentracing for buildkitd gRPC API and buildctl commands. To capture the trace to [Jaeger](https://github.com/jaegertracing/jaeger), set `JAEGER_TRACE` environment variable to the collection address.
|
||||
|
|
|
@ -30,15 +30,17 @@ import (
|
|||
)
|
||||
|
||||
type SolveOpt struct {
|
||||
Exports []ExportEntry
|
||||
LocalDirs map[string]string
|
||||
SharedKey string
|
||||
Frontend string
|
||||
FrontendAttrs map[string]string
|
||||
CacheExports []CacheOptionsEntry
|
||||
CacheImports []CacheOptionsEntry
|
||||
Session []session.Attachable
|
||||
AllowedEntitlements []entitlements.Entitlement
|
||||
Exports []ExportEntry
|
||||
LocalDirs map[string]string
|
||||
SharedKey string
|
||||
Frontend string
|
||||
FrontendAttrs map[string]string
|
||||
CacheExports []CacheOptionsEntry
|
||||
CacheImports []CacheOptionsEntry
|
||||
Session []session.Attachable
|
||||
AllowedEntitlements []entitlements.Entitlement
|
||||
SharedSession *session.Session // TODO: refactor to better session syncing
|
||||
SessionPreInitialized bool // TODO: refactor to better session syncing
|
||||
}
|
||||
|
||||
type ExportEntry struct {
|
||||
|
@ -94,50 +96,15 @@ func (c *Client) solve(ctx context.Context, def *llb.Definition, runGateway runG
|
|||
statusContext = opentracing.ContextWithSpan(statusContext, span)
|
||||
}
|
||||
|
||||
s, err := session.NewSession(statusContext, defaultSessionName(), opt.SharedKey)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "failed to create session")
|
||||
}
|
||||
s := opt.SharedSession
|
||||
|
||||
if len(syncedDirs) > 0 {
|
||||
s.Allow(filesync.NewFSSyncProvider(syncedDirs))
|
||||
}
|
||||
|
||||
for _, a := range opt.Session {
|
||||
s.Allow(a)
|
||||
}
|
||||
|
||||
var ex ExportEntry
|
||||
if len(opt.Exports) > 1 {
|
||||
return nil, errors.New("currently only single Exports can be specified")
|
||||
}
|
||||
if len(opt.Exports) == 1 {
|
||||
ex = opt.Exports[0]
|
||||
}
|
||||
|
||||
switch ex.Type {
|
||||
case ExporterLocal:
|
||||
if ex.Output != nil {
|
||||
return nil, errors.New("output file writer is not supported by local exporter")
|
||||
if s == nil {
|
||||
if opt.SessionPreInitialized {
|
||||
return nil, errors.Errorf("no session provided for preinitialized option")
|
||||
}
|
||||
if ex.OutputDir == "" {
|
||||
return nil, errors.New("output directory is required for local exporter")
|
||||
}
|
||||
s.Allow(filesync.NewFSSyncTargetDir(ex.OutputDir))
|
||||
case ExporterOCI, ExporterDocker, ExporterTar:
|
||||
if ex.OutputDir != "" {
|
||||
return nil, errors.Errorf("output directory %s is not supported by %s exporter", ex.OutputDir, ex.Type)
|
||||
}
|
||||
if ex.Output == nil {
|
||||
return nil, errors.Errorf("output file writer is required for %s exporter", ex.Type)
|
||||
}
|
||||
s.Allow(filesync.NewFSSyncTarget(ex.Output))
|
||||
default:
|
||||
if ex.Output != nil {
|
||||
return nil, errors.Errorf("output file writer is not supported by %s exporter", ex.Type)
|
||||
}
|
||||
if ex.OutputDir != "" {
|
||||
return nil, errors.Errorf("output directory %s is not supported by %s exporter", ex.OutputDir, ex.Type)
|
||||
s, err = session.NewSession(statusContext, defaultSessionName(), opt.SharedKey)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "failed to create session")
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -145,17 +112,64 @@ func (c *Client) solve(ctx context.Context, def *llb.Definition, runGateway runG
|
|||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(cacheOpt.contentStores) > 0 {
|
||||
s.Allow(sessioncontent.NewAttachable(cacheOpt.contentStores))
|
||||
|
||||
var ex ExportEntry
|
||||
|
||||
if !opt.SessionPreInitialized {
|
||||
if len(syncedDirs) > 0 {
|
||||
s.Allow(filesync.NewFSSyncProvider(syncedDirs))
|
||||
}
|
||||
|
||||
for _, a := range opt.Session {
|
||||
s.Allow(a)
|
||||
}
|
||||
|
||||
if len(opt.Exports) > 1 {
|
||||
return nil, errors.New("currently only single Exports can be specified")
|
||||
}
|
||||
if len(opt.Exports) == 1 {
|
||||
ex = opt.Exports[0]
|
||||
}
|
||||
|
||||
switch ex.Type {
|
||||
case ExporterLocal:
|
||||
if ex.Output != nil {
|
||||
return nil, errors.New("output file writer is not supported by local exporter")
|
||||
}
|
||||
if ex.OutputDir == "" {
|
||||
return nil, errors.New("output directory is required for local exporter")
|
||||
}
|
||||
s.Allow(filesync.NewFSSyncTargetDir(ex.OutputDir))
|
||||
case ExporterOCI, ExporterDocker, ExporterTar:
|
||||
if ex.OutputDir != "" {
|
||||
return nil, errors.Errorf("output directory %s is not supported by %s exporter", ex.OutputDir, ex.Type)
|
||||
}
|
||||
if ex.Output == nil {
|
||||
return nil, errors.Errorf("output file writer is required for %s exporter", ex.Type)
|
||||
}
|
||||
s.Allow(filesync.NewFSSyncTarget(ex.Output))
|
||||
default:
|
||||
if ex.Output != nil {
|
||||
return nil, errors.Errorf("output file writer is not supported by %s exporter", ex.Type)
|
||||
}
|
||||
if ex.OutputDir != "" {
|
||||
return nil, errors.Errorf("output directory %s is not supported by %s exporter", ex.OutputDir, ex.Type)
|
||||
}
|
||||
}
|
||||
|
||||
if len(cacheOpt.contentStores) > 0 {
|
||||
s.Allow(sessioncontent.NewAttachable(cacheOpt.contentStores))
|
||||
}
|
||||
|
||||
eg.Go(func() error {
|
||||
return s.Run(statusContext, grpchijack.Dialer(c.controlClient()))
|
||||
})
|
||||
}
|
||||
|
||||
for k, v := range cacheOpt.frontendAttrs {
|
||||
opt.FrontendAttrs[k] = v
|
||||
}
|
||||
|
||||
eg.Go(func() error {
|
||||
return s.Run(statusContext, grpchijack.Dialer(c.controlClient()))
|
||||
})
|
||||
|
||||
solveCtx, cancelSolve := context.WithCancel(ctx)
|
||||
var res *SolveResponse
|
||||
eg.Go(func() error {
|
||||
|
|
|
@ -227,7 +227,10 @@ func (t *trace) update(s *client.SolveStatus, termWidth int) {
|
|||
}
|
||||
t.vertexes = append(t.vertexes, t.byDigest[v.Digest])
|
||||
}
|
||||
t.byDigest[v.Digest].Vertex = v
|
||||
// allow a duplicate initial vertex that shouldn't reset state
|
||||
if !(prev != nil && prev.Started != nil && v.Started == nil) {
|
||||
t.byDigest[v.Digest].Vertex = v
|
||||
}
|
||||
t.byDigest[v.Digest].jobCached = false
|
||||
}
|
||||
for _, s := range s.Statuses {
|
||||
|
|
Loading…
Reference in New Issue