Repository: code-ready/crc
Pull request #2029 (2021-03-01 09:10:25)

Remove ClusterOperator kind from CVO overrides
For 4.7 bundles we are adding the deployment kind and clusteroperator
kind for monitoring as part of overrides, better to remove both when
enabling the monitoring from CVO.


**Fixes:** #2028 



openshift-ci-robot: [APPROVALNOTIFIER] This PR is **APPROVED**

This pull-request has been approved by: *<a href="https://github.com/code-ready/crc/pull/2029#" title="Author self-approved">praveenkumar</a>*

The full list of commands accepted by this bot can be found [here](https://go.k8s.io/bot-commands?repo=code-ready%2Fcrc).

The pull request process is described [here](https://git.k8s.io/community/contributors/guide/owners.md#the-code-review-process)

<details >
Needs approval from an approver in each of these files:

- ~~[OWNERS](https://github.com/code-ready/crc/blob/master/OWNERS)~~ [praveenkumar]

Approvers can indicate their approval by writing `/approve` in a comment
Approvers can cancel approval by writing `/approve cancel` in a comment
</details>
<!-- META={"approvers":[]} -->

Patch:
diff --git a/.circleci/config.yml b/.circleci/config.yml
index b8ee8300b..50f62acc3 100644
--- a/.circleci/config.yml
+++ b/.circleci/config.yml
@@ -42,7 +42,7 @@ jobs:
 
   build_mock_release:
     machine:
-      image: ubuntu-1604:202007-01
+      image: ubuntu-2004:202101-01
     environment:
       GOVERSION: "1.14.13"
       CONTAINER_RUNTIME: "docker"
@@ -72,7 +72,7 @@ jobs:
 
   build_docs:
     machine:
-      image: ubuntu-1604:201903-01
+      image: ubuntu-2004:202101-01
     steps:
     - checkout
     - run:
@@ -80,13 +80,13 @@ jobs:
         command: sudo rm -f /etc/apt/sources.list.d/google-chrome.list
     - run:
         name: Add podman ppa and update repo
-        command: sudo add-apt-repository -y ppa:projectatomic/ppa && sudo apt -y update
+        command: |
+          echo 'deb http://download.opensuse.org/repositories/devel:/kubic:/libcontainers:/stable/xUbuntu_20.04/ /' | sudo tee /etc/apt/sources.list.d/devel:kubic:libcontainers:stable.list
+          curl -fsSL https://download.opensuse.org/repositories/devel:kubic:libcontainers:stable/xUbuntu_20.04/Release.key | gpg --dearmor | sudo tee /etc/apt/trusted.gpg.d/devel_kubic_libcontainers_stable.gpg > /dev/null
+          sudo apt update
     - run:
         name: Install podman
         command: sudo apt -y install podman
-    - run:
-        name: Install slirp4netns
-        command: sudo apt -y install slirp4netns
     - run:
         name: Check podman
         command: podman info
@@ -104,7 +104,7 @@ jobs:
 
   docs_deploy:
     machine:
-      image: ubuntu-1604:201903-01
+      image: ubuntu-2004:202101-01
     steps:
     - attach_workspace:
         at: docs/build
diff --git a/Makefile b/Makefile
index 3578d47bc..ea3d37c7c 100644
--- a/Makefile
+++ b/Makefile
@@ -2,7 +2,7 @@ SHELL := /bin/bash
 
 BUNDLE_VERSION = 4.7.0
 BUNDLE_EXTENSION = crcbundle
-CRC_VERSION = 1.22.0
+CRC_VERSION = 1.23.0
 COMMIT_SHA=$(shell git rev-parse --short HEAD)
 MACOS_INSTALL_PATH = /Library/CodeReady Containers
 CONTAINER_RUNTIME ?= podman
diff --git a/cmd/crc/cmd/daemon.go b/cmd/crc/cmd/daemon.go
index 110c4ea7c..b7b15dbcb 100644
--- a/cmd/crc/cmd/daemon.go
+++ b/cmd/crc/cmd/daemon.go
@@ -8,18 +8,15 @@ import (
 	"os/signal"
 	"path/filepath"
 	"regexp"
-	"runtime"
 	"syscall"
 	"time"
 
 	cmdConfig "github.com/code-ready/crc/cmd/crc/cmd/config"
 	"github.com/code-ready/crc/pkg/crc/api"
 	"github.com/code-ready/crc/pkg/crc/constants"
-	"github.com/code-ready/gvisor-tap-vsock/pkg/transport"
 	"github.com/code-ready/gvisor-tap-vsock/pkg/types"
 	"github.com/code-ready/gvisor-tap-vsock/pkg/virtualnetwork"
 	"github.com/docker/go-units"
-	"github.com/pkg/errors"
 	log "github.com/sirupsen/logrus"
 	"github.com/spf13/cobra"
 )
@@ -36,16 +33,6 @@ var daemonCmd = &cobra.Command{
 	Long:   "Run the crc daemon",
 	Hidden: true,
 	RunE: func(cmd *cobra.Command, args []string) error {
-		var endpoints []string
-		if runtime.GOOS == "windows" {
-			endpoints = append(endpoints, transport.DefaultURL)
-		} else {
-			_ = os.Remove(constants.NetworkSocketPath)
-			endpoints = append(endpoints, fmt.Sprintf("unix://%s", constants.NetworkSocketPath))
-			if runtime.GOOS == "linux" {
-				endpoints = append(endpoints, transport.DefaultURL)
-			}
-		}
 		virtualNetworkConfig := types.Configuration{
 			Debug:             false, // never log packets
 			CaptureFile:       captureFile(),
@@ -80,11 +67,6 @@ var daemonCmd = &cobra.Command{
 					},
 				},
 			},
-			Forwards: map[string]string{
-				fmt.Sprintf(":%d", constants.VsockSSHPort): "192.168.127.2:22",
-				":6443": "192.168.127.2:6443",
-				":443":  "192.168.127.2:443",
-			},
 		}
 		if config.Get(cmdConfig.HostNetworkAccess).AsBool() {
 			log.Debugf("Enabling host network access")
@@ -103,7 +85,7 @@ var daemonCmd = &cobra.Command{
 			}
 			virtualNetworkConfig.NAT[hostVirtualIP] = "127.0.0.1"
 		}
-		err := run(&virtualNetworkConfig, endpoints)
+		err := run(&virtualNetworkConfig)
 		return err
 	},
 }
@@ -115,27 +97,43 @@ func captureFile() string {
 	return filepath.Join(constants.CrcBaseDir, "capture.pcap")
 }
 
-func run(configuration *types.Configuration, endpoints []string) error {
+func run(configuration *types.Configuration) error {
+	vsockListener, err := vsockListener()
+	if err != nil {
+		return err
+	}
+
 	vn, err := virtualnetwork.New(configuration)
 	if err != nil {
 		return err
 	}
-	log.Info("waiting for clients...")
+
 	errCh := make(chan error)
 
-	for _, endpoint := range endpoints {
-		log.Infof("listening %s", endpoint)
-		ln, err := transport.Listen(endpoint)
-		if err != nil {
-			return errors.Wrap(err, "cannot listen")
+	listener, err := httpListener()
+	if err != nil {
+		return err
+	}
+
+	go func() {
+		if listener == nil {
+			return
 		}
+		mux := http.NewServeMux()
+		mux.Handle("/network/", http.StripPrefix("/network", vn.Mux()))
+		if err := http.Serve(listener, mux); err != nil {
+			errCh <- err
+		}
+	}()
+
+	go func() {
+		mux := http.NewServeMux()
+		mux.Handle(types.ConnectPath, vn.Mux())
+		if err := http.Serve(vsockListener, mux); err != nil {
+			errCh <- err
+		}
+	}()
 
-		go func() {
-			if err := http.Serve(ln, vn.Mux()); err != nil {
-				errCh <- err
-			}
-		}()
-	}
 	if isDebugLog() {
 		go func() {
 			for {
diff --git a/cmd/crc/cmd/daemon_darwin.go b/cmd/crc/cmd/daemon_darwin.go
new file mode 100644
index 000000000..aca870932
--- /dev/null
+++ b/cmd/crc/cmd/daemon_darwin.go
@@ -0,0 +1,29 @@
+package cmd
+
+import (
+	"net"
+	"os"
+
+	"github.com/code-ready/crc/pkg/crc/constants"
+	"github.com/code-ready/crc/pkg/crc/logging"
+)
+
+func vsockListener() (net.Listener, error) {
+	_ = os.Remove(constants.TapSocketPath)
+	ln, err := net.Listen("unix", constants.TapSocketPath)
+	logging.Infof("listening %s", constants.TapSocketPath)
+	if err != nil {
+		return nil, err
+	}
+	return ln, nil
+}
+
+func httpListener() (net.Listener, error) {
+	_ = os.Remove(constants.DaemonHTTPSocketPath)
+	ln, err := net.Listen("unix", constants.DaemonHTTPSocketPath)
+	logging.Infof("listening %s", constants.DaemonHTTPSocketPath)
+	if err != nil {
+		return nil, err
+	}
+	return ln, nil
+}
diff --git a/cmd/crc/cmd/daemon_linux.go b/cmd/crc/cmd/daemon_linux.go
new file mode 100644
index 000000000..15bab5cff
--- /dev/null
+++ b/cmd/crc/cmd/daemon_linux.go
@@ -0,0 +1,29 @@
+package cmd
+
+import (
+	"net"
+	"os"
+
+	"github.com/code-ready/crc/pkg/crc/constants"
+	"github.com/code-ready/crc/pkg/crc/logging"
+	"github.com/code-ready/gvisor-tap-vsock/pkg/transport"
+)
+
+func vsockListener() (net.Listener, error) {
+	ln, err := transport.Listen(transport.DefaultURL)
+	logging.Infof("listening %s", transport.DefaultURL)
+	if err != nil {
+		return nil, err
+	}
+	return ln, nil
+}
+
+func httpListener() (net.Listener, error) {
+	_ = os.Remove(constants.DaemonHTTPSocketPath)
+	ln, err := net.Listen("unix", constants.DaemonHTTPSocketPath)
+	logging.Infof("listening %s", constants.DaemonHTTPSocketPath)
+	if err != nil {
+		return nil, err
+	}
+	return ln, nil
+}
diff --git a/cmd/crc/cmd/daemon_windows.go b/cmd/crc/cmd/daemon_windows.go
new file mode 100644
index 000000000..89fd3d0c6
--- /dev/null
+++ b/cmd/crc/cmd/daemon_windows.go
@@ -0,0 +1,32 @@
+package cmd
+
+import (
+	"net"
+
+	"github.com/Microsoft/go-winio"
+	"github.com/code-ready/crc/pkg/crc/constants"
+	"github.com/code-ready/crc/pkg/crc/logging"
+	"github.com/code-ready/gvisor-tap-vsock/pkg/transport"
+)
+
+func vsockListener() (net.Listener, error) {
+	ln, err := transport.Listen(transport.DefaultURL)
+	logging.Infof("listening %s", transport.DefaultURL)
+	if err != nil {
+		return nil, err
+	}
+	return ln, nil
+}
+
+func httpListener() (net.Listener, error) {
+	ln, err := winio.ListenPipe(constants.DaemonHTTPNamedPipe, &winio.PipeConfig{
+		MessageMode:      true,  // Use message mode so that CloseWrite() is supported
+		InputBufferSize:  65536, // Use 64kB buffers to improve performance
+		OutputBufferSize: 65536,
+	})
+	logging.Infof("listening %s", constants.DaemonHTTPNamedPipe)
+	if err != nil {
+		return nil, err
+	}
+	return ln, nil
+}
diff --git a/cmd/crc/cmd/start.go b/cmd/crc/cmd/start.go
index 661c73635..67dcbadb1 100644
--- a/cmd/crc/cmd/start.go
+++ b/cmd/crc/cmd/start.go
@@ -211,7 +211,7 @@ Log in as user:
 
 Use the 'oc' command line interface:
   {{ .CommandLinePrefix }} {{ .EvalCommandLine }}
-  {{ .CommandLinePrefix }} oc login {{ .ClusterConfig.URL }}
+  {{ .CommandLinePrefix }} oc login -u {{ .ClusterConfig.DeveloperCredentials.Username }} {{ .ClusterConfig.URL }}
 `
 
 type templateVariables struct {
diff --git a/docs/source/meta/product-attributes.adoc b/docs/source/meta/product-attributes.adoc
index 1c3167765..4aa3b7356 100644
--- a/docs/source/meta/product-attributes.adoc
+++ b/docs/source/meta/product-attributes.adoc
@@ -35,4 +35,4 @@
 
 :odo-docs-url: https://docs.openshift.com/container-platform/latest/cli_reference/developer_cli_odo/understanding-odo.html
 :odo-docs-url-installing: https://docs.openshift.com/container-platform/latest/cli_reference/developer_cli_odo/installing-odo.html
-:odo-docs-url-single-component: https://docs.openshift.com/container-platform/latest/cli_reference/developer_cli_odo/creating-a-single-component-application-with-odo.html
+:odo-docs-url-single-component: https://docs.openshift.com/container-platform/latest/cli_reference/developer_cli_odo/creating_and_deploying_applications_with_odo/creating-a-single-component-application-with-odo.html
diff --git a/go.mod b/go.mod
index 6102f5fab..26cbd0f61 100644
--- a/go.mod
+++ b/go.mod
@@ -4,12 +4,13 @@ go 1.14
 
 require (
 	github.com/Masterminds/semver v1.5.0
+	github.com/Microsoft/go-winio v0.4.15-0.20200908182639-5b44b70ab3ab
 	github.com/YourFin/binappend v0.0.0-20181105185800-0add4bf0b9ad
 	github.com/asaskevich/govalidator v0.0.0-20200907205600-7a23bdc65eef
 	github.com/cavaliercoder/grab v2.0.0+incompatible
 	github.com/cheggaaa/pb/v3 v3.0.5
 	github.com/code-ready/clicumber v0.0.0-20210201104241-cecb794bdf9a
-	github.com/code-ready/gvisor-tap-vsock v0.0.0-20210128145517-e5f886c34c9f
+	github.com/code-ready/gvisor-tap-vsock v0.0.0-20210216090540-914d522b9c38
 	github.com/code-ready/machine v0.0.0-20210122113819-281ccfbb4566
 	github.com/cucumber/godog v0.9.0
 	github.com/cucumber/messages-go/v10 v10.0.3
diff --git a/go.sum b/go.sum
index 2426b5007..bd13dd7b2 100644
--- a/go.sum
+++ b/go.sum
@@ -67,6 +67,7 @@ github.com/Masterminds/semver v1.5.0/go.mod h1:MB6lktGJrhw8PrUyiEoblNEGEQ+RzHPF0
 github.com/Microsoft/go-winio v0.4.11/go.mod h1:VhR8bwka0BXejwEJY73c50VrPtXAaKcyvVC4A4RozmA=
 github.com/Microsoft/go-winio v0.4.12/go.mod h1:VhR8bwka0BXejwEJY73c50VrPtXAaKcyvVC4A4RozmA=
 github.com/Microsoft/go-winio v0.4.15-0.20190919025122-fc70bd9a86b5/go.mod h1:tTuCMEN+UleMWgg9dVx4Hu52b1bJo+59jBh3ajtinzw=
+github.com/Microsoft/go-winio v0.4.15-0.20200908182639-5b44b70ab3ab h1:9pygWVFqbY9lPxM0peffumuVDyMuIMzNLyO9uFjJuQo=
 github.com/Microsoft/go-winio v0.4.15-0.20200908182639-5b44b70ab3ab/go.mod h1:tTuCMEN+UleMWgg9dVx4Hu52b1bJo+59jBh3ajtinzw=
 github.com/Microsoft/hcsshim v0.8.10/go.mod h1:g5uw8EV2mAlzqe94tfNBNdr89fnbD/n3HV0OhsddkmM=
 github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ=
@@ -162,8 +163,8 @@ github.com/cockroachdb/cockroach-go v0.0.0-20181001143604-e0a95dfd547c/go.mod h1
 github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8=
 github.com/code-ready/clicumber v0.0.0-20210201104241-cecb794bdf9a h1:VOQmCj9Y8pAPU4C0rIvF2ByUBuuqnaR9JSvb9C8uBQE=
 github.com/code-ready/clicumber v0.0.0-20210201104241-cecb794bdf9a/go.mod h1:ZPZUcYGpv/FQGnwakUuhiHP9x/IIcU2SKbn8xPe4ROc=
-github.com/code-ready/gvisor-tap-vsock v0.0.0-20210128145517-e5f886c34c9f h1:Kntt85ZTGkDccmxfC7WU6VzLPJAPTcTn4bDqgS68nAY=
-github.com/code-ready/gvisor-tap-vsock v0.0.0-20210128145517-e5f886c34c9f/go.mod h1:DsNrkk0GUSTqt0E/4/GMvjqsP7ns++O/6YaJn/TDBVM=
+github.com/code-ready/gvisor-tap-vsock v0.0.0-20210216090540-914d522b9c38 h1:vo1A+Tvie+BVZoSyYOzShDH6ieQkD1Q9l4JeeC0jCxA=
+github.com/code-ready/gvisor-tap-vsock v0.0.0-20210216090540-914d522b9c38/go.mod h1:DsNrkk0GUSTqt0E/4/GMvjqsP7ns++O/6YaJn/TDBVM=
 github.com/code-ready/machine v0.0.0-20210122113819-281ccfbb4566 h1:zBDinebc2kFq99UNTmLmTRfgxcxC6YieKQuXDRCljzw=
 github.com/code-ready/machine v0.0.0-20210122113819-281ccfbb4566/go.mod h1:4JgMqho7KuxFifYCIi7cKVmh4yA2l0QHOPftv9f5PNc=
 github.com/codegangsta/negroni v1.0.0/go.mod h1:v0y3T5G7Y1UlFfyxFn/QLRU4a2EuNau2iZY63YTKWo0=
@@ -1354,7 +1355,6 @@ gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
 gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
 gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
 gopkg.in/yaml.v3 v3.0.0-20190905181640-827449938966/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
-gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
 gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
 gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo=
 gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
diff --git a/images/docs-builder/Dockerfile b/images/docs-builder/Dockerfile
index c0b9a09b0..e55bd0be5 100644
--- a/images/docs-builder/Dockerfile
+++ b/images/docs-builder/Dockerfile
@@ -4,7 +4,7 @@ MAINTAINER CodeReady Containers <devtools-cdk@redhat.com>
 RUN yum update -y && \
     yum install --setopt=tsflags=nodocs -y \
     ruby rubygems python38 && \
-    yum module install nodejs:12 -y && \
+    yum module install nodejs:14 -y && \
     yum clean all && rm -rf /var/cache/yum/*
 
 RUN gem install asciidoctor asciidoctor-pdf --pre && \
@@ -12,7 +12,7 @@ RUN gem install asciidoctor asciidoctor-pdf --pre && \
 
 COPY entrypoint.sh /sbin/entrypoint.sh
 RUN chmod 755 /sbin/entrypoint.sh
-COPY links_whitelist.json /links_whitelist.json
+COPY links_ignorelist.json /links_ignorelist.json
 
 VOLUME /docs
 WORKDIR /docs
diff --git a/images/docs-builder/entrypoint.sh b/images/docs-builder/entrypoint.sh
index a84abd2dd..b84a7a38d 100644
--- a/images/docs-builder/entrypoint.sh
+++ b/images/docs-builder/entrypoint.sh
@@ -18,7 +18,7 @@ case $1 in
 		;;
 	docs_check_links)
 		echo "Checking if all links are alive in docs source"
-		find . -name \*.adoc | xargs -n1 asciidoc-link-check -c /links_whitelist.json -q
+		find . -name \*.adoc | xargs -n1 asciidoc-link-check -c /links_ignorelist.json -q
 		;;
 	docs_serve)
 		cd build
diff --git a/images/docs-builder/links_whitelist.json b/images/docs-builder/links_ignorelist.json
similarity index 100%
rename from images/docs-builder/links_whitelist.json
rename to images/docs-builder/links_ignorelist.json
diff --git a/pkg/crc/cluster/cluster.go b/pkg/crc/cluster/cluster.go
index b023344f3..6ff504175 100644
--- a/pkg/crc/cluster/cluster.go
+++ b/pkg/crc/cluster/cluster.go
@@ -310,7 +310,7 @@ func WaitForRequestHeaderClientCaFile(sshRunner *ssh.Runner) error {
 }
 
 func WaitForAPIServer(ocConfig oc.Config) error {
-	logging.Debugf("Waiting for apiserver availability")
+	logging.Info("Waiting for kube-apiserver availability... [takes around 2min]")
 	waitForAPIServer := func() error {
 		stdout, stderr, err := ocConfig.WithFailFast().RunOcCommand("get", "nodes")
 		if err != nil {
diff --git a/pkg/crc/cluster/monitoring.go b/pkg/crc/cluster/monitoring.go
index 89996e09d..37172ba18 100644
--- a/pkg/crc/cluster/monitoring.go
+++ b/pkg/crc/cluster/monitoring.go
@@ -20,20 +20,28 @@ func StartMonitoring(ocConfig oc.Config) error {
 		return err
 	}
 
+	indexForClusterMonitoringDeploymentKind := getIndexInOverridesForObjectName(cv, "cluster-monitoring-operator")
+	indexForClusterMonitoringCVOKind := getIndexInOverridesForObjectName(cv, "monitoring")
+
+	if indexForClusterMonitoringDeploymentKind != -1 && indexForClusterMonitoringCVOKind != -1 {
+		_, _, err = ocConfig.RunOcCommand("patch", "clusterversion/version",
+			"--type", "json",
+			"--patch", fmt.Sprintf(`'[{"op":"remove", "path":"/spec/overrides/%d"},{"op":"remove", "path":"/spec/overrides/%d"}]'`,
+				indexForClusterMonitoringDeploymentKind, indexForClusterMonitoringCVOKind-1))
+	}
+	return err
+}
+
+func getIndexInOverridesForObjectName(cv v1.ClusterVersion, objectName string) int {
 	pos := -1
 	for i, override := range cv.Spec.Overrides {
-		if override.Name == "cluster-monitoring-operator" {
+		if override.Name == objectName {
 			pos = i
 			break
 		}
 	}
 	if pos == -1 {
-		log.Debug("monitoring operator not found in cluster version overrides")
-		return nil
+		log.Debugf("%s not found in cluster version overrides", objectName)
 	}
-
-	_, _, err = ocConfig.RunOcCommand("patch", "clusterversion/version",
-		"--type", "json",
-		"--patch", fmt.Sprintf(`'[{"op":"remove", "path":"/spec/overrides/%d"}]'`, pos))
-	return err
+	return pos
 }
diff --git a/pkg/crc/constants/constants.go b/pkg/crc/constants/constants.go
index 1f9a0b8bd..de9dbef08 100644
--- a/pkg/crc/constants/constants.go
+++ b/pkg/crc/constants/constants.go
@@ -103,7 +103,6 @@ var (
 	MachineInstanceDir = filepath.Join(MachineBaseDir, "machines")
 	DefaultBundlePath  = defaultBundlePath()
 	DaemonSocketPath   = filepath.Join(CrcBaseDir, "crc.sock")
-	NetworkSocketPath  = filepath.Join(CrcBaseDir, "network.sock")
 )
 
 func defaultBundlePath() string {
diff --git a/pkg/crc/constants/constants_darwin.go b/pkg/crc/constants/constants_darwin.go
index 81337d8aa..152c820d2 100644
--- a/pkg/crc/constants/constants_darwin.go
+++ b/pkg/crc/constants/constants_darwin.go
@@ -15,8 +15,10 @@ const (
 )
 
 var (
-	TrayAppBundlePath  = trayAppBundlePath()
-	TrayExecutablePath = filepath.Join(TrayAppBundlePath, "Contents", "MacOS", "CodeReady Containers")
+	TrayAppBundlePath    = trayAppBundlePath()
+	TrayExecutablePath   = filepath.Join(TrayAppBundlePath, "Contents", "MacOS", "CodeReady Containers")
+	TapSocketPath        = filepath.Join(CrcBaseDir, "tap.sock")
+	DaemonHTTPSocketPath = filepath.Join(CrcBaseDir, "crc-http.sock")
 )
 
 func trayAppBundlePath() string {
diff --git a/pkg/crc/constants/constants_linux.go b/pkg/crc/constants/constants_linux.go
index 6d05ab7fb..d6152b678 100644
--- a/pkg/crc/constants/constants_linux.go
+++ b/pkg/crc/constants/constants_linux.go
@@ -1,7 +1,14 @@
 package constants
 
+import (
+	"path/filepath"
+)
+
 const (
 	OcExecutableName          = "oc"
 	PodmanExecutableName      = "podman"
 	AdminHelperExecutableName = "admin-helper-linux"
+	TapSocketPath             = ""
 )
+
+var DaemonHTTPSocketPath = filepath.Join(CrcBaseDir, "crc-http.sock")
diff --git a/pkg/crc/constants/constants_windows.go b/pkg/crc/constants/constants_windows.go
index 9d0b237a0..60891fb33 100644
--- a/pkg/crc/constants/constants_windows.go
+++ b/pkg/crc/constants/constants_windows.go
@@ -14,6 +14,8 @@ const (
 	DaemonBatchFileName         = "crc-daemon-autostart.bat"
 	DaemonPSScriptName          = "launch-crc-daemon.ps1"
 	DaemonBatchFileShortcutName = "crc-daemmon-autostart.bat.lnk"
+	TapSocketPath               = ""
+	DaemonHTTPNamedPipe         = `\\.\pipe\crc-http`
 )
 
 var (
diff --git a/pkg/crc/daemonclient/client.go b/pkg/crc/daemonclient/client.go
new file mode 100644
index 000000000..aa866634a
--- /dev/null
+++ b/pkg/crc/daemonclient/client.go
@@ -0,0 +1,19 @@
+package daemonclient
+
+import (
+	"net/http"
+
+	networkclient "github.com/code-ready/gvisor-tap-vsock/pkg/client"
+)
+
+type Client struct {
+	*networkclient.Client
+}
+
+func New() *Client {
+	return &Client{
+		Client: networkclient.New(&http.Client{
+			Transport: transport(),
+		}, "http://unix/network"),
+	}
+}
diff --git a/pkg/crc/daemonclient/transport_unix.go b/pkg/crc/daemonclient/transport_unix.go
new file mode 100644
index 000000000..a7e9f5aa0
--- /dev/null
+++ b/pkg/crc/daemonclient/transport_unix.go
@@ -0,0 +1,19 @@
+// +build !windows
+
+package daemonclient
+
+import (
+	"context"
+	"net"
+	"net/http"
+
+	"github.com/code-ready/crc/pkg/crc/constants"
+)
+
+func transport() *http.Transport {
+	return &http.Transport{
+		DialContext: func(ctx context.Context, network, addr string) (net.Conn, error) {
+			return net.Dial("unix", constants.DaemonHTTPSocketPath)
+		},
+	}
+}
diff --git a/pkg/crc/daemonclient/transport_windows.go b/pkg/crc/daemonclient/transport_windows.go
new file mode 100644
index 000000000..1974c15c2
--- /dev/null
+++ b/pkg/crc/daemonclient/transport_windows.go
@@ -0,0 +1,18 @@
+package daemonclient
+
+import (
+	"context"
+	"net"
+	"net/http"
+
+	"github.com/Microsoft/go-winio"
+	"github.com/code-ready/crc/pkg/crc/constants"
+)
+
+func transport() *http.Transport {
+	return &http.Transport{
+		DialContext: func(ctx context.Context, network, addr string) (net.Conn, error) {
+			return winio.DialPipeContext(ctx, constants.DaemonHTTPNamedPipe)
+		},
+	}
+}
diff --git a/pkg/crc/machine/bundle/metadata.go b/pkg/crc/machine/bundle/metadata.go
index 1b4a84b98..52d20078d 100644
--- a/pkg/crc/machine/bundle/metadata.go
+++ b/pkg/crc/machine/bundle/metadata.go
@@ -107,7 +107,10 @@ func (bundle *CrcBundleInfo) GetInitramfsPath() string {
 
 func (bundle *CrcBundleInfo) GetKubeadminPassword() (string, error) {
 	rawData, err := ioutil.ReadFile(bundle.resolvePath(bundle.ClusterInfo.KubeadminPasswordFile))
-	return string(rawData), err
+	if err != nil {
+		return "", err
+	}
+	return strings.TrimSpace(string(rawData)), nil
 }
 
 func (bundle *CrcBundleInfo) GetBundleBuildTime() (time.Time, error) {
diff --git a/pkg/crc/machine/kubeconfig.go b/pkg/crc/machine/kubeconfig.go
index f026eab3a..a398f03b6 100644
--- a/pkg/crc/machine/kubeconfig.go
+++ b/pkg/crc/machine/kubeconfig.go
@@ -4,7 +4,6 @@ import (
 	gocontext "context"
 	"crypto/tls"
 	"crypto/x509"
-	goerrors "errors"
 	"fmt"
 	"net"
 	"net/http"
@@ -14,11 +13,7 @@ import (
 	"strings"
 	"time"
 
-	"github.com/code-ready/crc/pkg/crc/cluster"
 	"github.com/code-ready/crc/pkg/crc/constants"
-	"github.com/code-ready/crc/pkg/crc/errors"
-	"github.com/code-ready/crc/pkg/crc/logging"
-	"github.com/code-ready/crc/pkg/crc/oc"
 	"github.com/openshift/oc/pkg/helpers/tokencmd"
 	restclient "k8s.io/client-go/rest"
 	"k8s.io/client-go/tools/clientcmd"
@@ -30,25 +25,7 @@ const (
 	developerContext = "crc-developer"
 )
 
-func eventuallyWriteKubeconfig(ocConfig oc.Config, ip string, clusterConfig *ClusterConfig) error {
-	if err := errors.RetryAfter(60*time.Second, func() error {
-		status, err := cluster.GetClusterOperatorStatus(ocConfig, "authentication")
-		if err != nil {
-			return &errors.RetriableError{Err: err}
-		}
-		if status.IsReady() {
-			return nil
-		}
-		return &errors.RetriableError{Err: goerrors.New("cluster operator authentication not ready")}
-	}, 2*time.Second); err != nil {
-		logging.Warn("Skipping the kubeconfig update. Cluster operator authentication still not ready after 2min.")
-	} else if err := WriteKubeconfig(ip, clusterConfig); err != nil {
-		return err
-	}
-	return nil
-}
-
-func WriteKubeconfig(ip string, clusterConfig *ClusterConfig) error {
+func writeKubeconfig(ip string, clusterConfig *ClusterConfig) error {
 	kubeconfig := getGlobalKubeConfigPath()
 	dir := filepath.Dir(kubeconfig)
 	if err := os.MkdirAll(dir, 0755); err != nil {
diff --git a/pkg/crc/machine/start.go b/pkg/crc/machine/start.go
index 15455223b..5d5799207 100644
--- a/pkg/crc/machine/start.go
+++ b/pkg/crc/machine/start.go
@@ -133,6 +133,12 @@ func (client *client) Start(ctx context.Context, startConfig StartConfig) (*Star
 			return nil, errors.Wrap(err, "Error getting bundle metadata")
 		}
 
+		if client.useVSock() {
+			if err := exposePorts(); err != nil {
+				return nil, err
+			}
+		}
+
 		logging.Infof("Creating CodeReady Containers VM for OpenShift %s...", crcBundleMetadata.GetOpenshiftVersion())
 
 		// Retrieve metadata info
@@ -184,6 +190,12 @@ func (client *client) Start(ctx context.Context, startConfig StartConfig) (*Star
 			}, nil
 		}
 
+		if client.useVSock() {
+			if err := exposePorts(); err != nil {
+				return nil, err
+			}
+		}
+
 		telemetry.SetStartType(ctx, telemetry.StartStartType)
 
 		logging.Infof("Starting CodeReady Containers VM for OpenShift %s...", crcBundleMetadata.GetOpenshiftVersion())
@@ -386,8 +398,8 @@ func (client *client) Start(ctx context.Context, startConfig StartConfig) (*Star
 
 	waitForProxyPropagation(ocConfig, proxyConfig)
 
-	logging.Info("Updating kubeconfig")
-	if err := eventuallyWriteKubeconfig(ocConfig, instanceIP, clusterConfig); err != nil {
+	logging.Info("Adding crc-admin and crc-developer contexts to kubeconfig...")
+	if err := writeKubeconfig(instanceIP, clusterConfig); err != nil {
 		logging.Warnf("Cannot update kubeconfig: %v", err)
 	}
 
@@ -439,7 +451,7 @@ func makeDaemonVisibleToHyperkit(name string) error {
 		if !os.IsNotExist(err) {
 			return errors.Wrap(err, "VSock listener error")
 		}
-		if err := os.Symlink(constants.NetworkSocketPath, dst); err != nil {
+		if err := os.Symlink(constants.TapSocketPath, dst); err != nil {
 			return errors.Wrap(err, "VSock listener error")
 		}
 	}
diff --git a/pkg/crc/machine/vsock.go b/pkg/crc/machine/vsock.go
new file mode 100644
index 000000000..b45b030c2
--- /dev/null
+++ b/pkg/crc/machine/vsock.go
@@ -0,0 +1,65 @@
+package machine
+
+import (
+	"fmt"
+
+	"github.com/code-ready/crc/pkg/crc/constants"
+	"github.com/code-ready/crc/pkg/crc/daemonclient"
+	"github.com/code-ready/gvisor-tap-vsock/pkg/types"
+	"github.com/pkg/errors"
+)
+
+func exposePorts() error {
+	daemonClient := daemonclient.New()
+	portsToExpose := vsockPorts()
+	alreadyOpenedPorts, err := daemonClient.List()
+	if err != nil {
+		return err
+	}
+	var missingPorts []types.ExposeRequest
+	for _, port := range portsToExpose {
+		if !isOpened(alreadyOpenedPorts, port) {
+			missingPorts = append(missingPorts, port)
+		}
+	}
+	for i := range missingPorts {
+		port := &missingPorts[i]
+		if err := daemonClient.Expose(port); err != nil {
+			return errors.Wrapf(err, "failed to expose port %s -> %s", port.Local, port.Remote)
+		}
+	}
+	return nil
+}
+
+func isOpened(exposed []types.ExposeRequest, port types.ExposeRequest) bool {
+	for _, alreadyOpenedPort := range exposed {
+		if port == alreadyOpenedPort {
+			return true
+		}
+	}
+	return false
+}
+
+const (
+	virtualMachineIP = "192.168.127.2"
+	internalSSHPort  = 22
+	httpsPort        = 443
+	apiPort          = 6443
+)
+
+func vsockPorts() []types.ExposeRequest {
+	return []types.ExposeRequest{
+		{
+			Local:  fmt.Sprintf(":%d", constants.VsockSSHPort),
+			Remote: fmt.Sprintf("%s:%d", virtualMachineIP, internalSSHPort),
+		},
+		{
+			Local:  fmt.Sprintf(":%d", apiPort),
+			Remote: fmt.Sprintf("%s:%d", virtualMachineIP, apiPort),
+		},
+		{
+			Local:  fmt.Sprintf(":%d", httpsPort),
+			Remote: fmt.Sprintf("%s:%d", virtualMachineIP, httpsPort),
+		},
+	}
+}
diff --git a/pkg/crc/preflight/preflight_checks_nondarwin.go b/pkg/crc/preflight/preflight_checks_nondarwin.go
new file mode 100644
index 000000000..6d498088f
--- /dev/null
+++ b/pkg/crc/preflight/preflight_checks_nondarwin.go
@@ -0,0 +1,36 @@
+// +build !darwin
+
+package preflight
+
+import (
+	"errors"
+	"net"
+
+	"github.com/code-ready/crc/pkg/crc/constants"
+)
+
+const daemonNotRunningErrMsg = "Network mode 'vsock' requires 'crc daemon' to be running, run it manually on different terminal/tab"
+
+var daemonRunningChecks = Check{
+	configKeySuffix:  "check-if-daemon-running",
+	checkDescription: "Checking if crc daemon is running",
+	check:            checkIfCRCDaemonRunning,
+	fixDescription:   daemonNotRunningErrMsg,
+	flags:            NoFix,
+}
+
+func checkIfCRCDaemonRunning() error {
+	l, err := net.Dial("unix", constants.DaemonSocketPath)
+	if err != nil {
+		// Log or report the error here
+		return errors.New(daemonNotRunningErrMsg)
+	}
+
+	defer func() {
+		if l != nil {
+			l.Close()
+		}
+	}()
+
+	return nil
+}
diff --git a/pkg/crc/preflight/preflight_linux.go b/pkg/crc/preflight/preflight_linux.go
index c64cbdf22..e7e270cb7 100644
--- a/pkg/crc/preflight/preflight_linux.go
+++ b/pkg/crc/preflight/preflight_linux.go
@@ -223,7 +223,8 @@ func getNetworkChecksForDistro(distro *linux.OsRelease, networkMode network.Mode
 	var checks []Check
 
 	if networkMode == network.VSockMode {
-		return append(checks, vsockPreflightChecks)
+		checks = append(checks, vsockPreflightChecks)
+		return append(checks, daemonRunningChecks)
 	}
 
 	switch {
diff --git a/pkg/crc/preflight/preflight_windows.go b/pkg/crc/preflight/preflight_windows.go
index 9ced5a2d9..268743d6a 100644
--- a/pkg/crc/preflight/preflight_windows.go
+++ b/pkg/crc/preflight/preflight_windows.go
@@ -148,6 +148,7 @@ func getPreflightChecks(experimentalFeatures bool, _ bool, networkMode network.M
 
 	if networkMode == network.VSockMode {
 		checks = append(checks, vsockChecks[:]...)
+		checks = append(checks, daemonRunningChecks)
 	}
 
 	// Experimental feature
diff --git a/pkg/crc/version/version.go b/pkg/crc/version/version.go
index 01d9a04b4..445a9f0ca 100644
--- a/pkg/crc/version/version.go
+++ b/pkg/crc/version/version.go
@@ -29,9 +29,9 @@ var (
 const (
 	releaseInfoLink = "https://mirror.openshift.com/pub/openshift-v4/clients/crc/latest/release-info.json"
 	// Tray version to be embedded in executable
-	crcMacTrayVersion = "1.0.0-beta.1"
+	crcMacTrayVersion = "1.0.3"
 	// Windows forms application version type major.minor.buildnumber.revesion
-	crcWindowsTrayVersion = "0.3.0.0"
+	crcWindowsTrayVersion = "0.4.0.0"
 )
 
 type CrcReleaseInfo struct {
diff --git a/vendor/github.com/Microsoft/go-winio/.gitignore b/vendor/github.com/Microsoft/go-winio/.gitignore
new file mode 100644
index 000000000..b883f1fdc
--- /dev/null
+++ b/vendor/github.com/Microsoft/go-winio/.gitignore
@@ -0,0 +1,1 @@
+*.exe
diff --git a/vendor/github.com/Microsoft/go-winio/LICENSE b/vendor/github.com/Microsoft/go-winio/LICENSE
new file mode 100644
index 000000000..b8b569d77
--- /dev/null
+++ b/vendor/github.com/Microsoft/go-winio/LICENSE
@@ -0,0 +1,22 @@
+The MIT License (MIT)
+
+Copyright (c) 2015 Microsoft
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+
diff --git a/vendor/github.com/Microsoft/go-winio/README.md b/vendor/github.com/Microsoft/go-winio/README.md
new file mode 100644
index 000000000..568001057
--- /dev/null
+++ b/vendor/github.com/Microsoft/go-winio/README.md
@@ -0,0 +1,22 @@
+# go-winio
+
+This repository contains utilities for efficiently performing Win32 IO operations in
+Go. Currently, this is focused on accessing named pipes and other file handles, and
+for using named pipes as a net transport.
+
+This code relies on IO completion ports to avoid blocking IO on system threads, allowing Go
+to reuse the thread to schedule another goroutine. This limits support to Windows Vista and
+newer operating systems. This is similar to the implementation of network sockets in Go's net
+package.
+
+Please see the LICENSE file for licensing information.
+
+This project has adopted the [Microsoft Open Source Code of
+Conduct](https://opensource.microsoft.com/codeofconduct/). For more information
+see the [Code of Conduct
+FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or contact
+[opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional
+questions or comments.
+
+Thanks to natefinch for the inspiration for this library. See https://github.com/natefinch/npipe
+for another named pipe implementation.
diff --git a/vendor/github.com/Microsoft/go-winio/backup.go b/vendor/github.com/Microsoft/go-winio/backup.go
new file mode 100644
index 000000000..2be34af43
--- /dev/null
+++ b/vendor/github.com/Microsoft/go-winio/backup.go
@@ -0,0 +1,280 @@
+// +build windows
+
+package winio
+
+import (
+	"encoding/binary"
+	"errors"
+	"fmt"
+	"io"
+	"io/ioutil"
+	"os"
+	"runtime"
+	"syscall"
+	"unicode/utf16"
+)
+
+//sys backupRead(h syscall.Handle, b []byte, bytesRead *uint32, abort bool, processSecurity bool, context *uintptr) (err error) = BackupRead
+//sys backupWrite(h syscall.Handle, b []byte, bytesWritten *uint32, abort bool, processSecurity bool, context *uintptr) (err error) = BackupWrite
+
+const (
+	BackupData = uint32(iota + 1)
+	BackupEaData
+	BackupSecurity
+	BackupAlternateData
+	BackupLink
+	BackupPropertyData
+	BackupObjectId
+	BackupReparseData
+	BackupSparseBlock
+	BackupTxfsData
+)
+
+const (
+	StreamSparseAttributes = uint32(8)
+)
+
+const (
+	WRITE_DAC              = 0x40000
+	WRITE_OWNER            = 0x80000
+	ACCESS_SYSTEM_SECURITY = 0x1000000
+)
+
+// BackupHeader represents a backup stream of a file.
+type BackupHeader struct {
+	Id         uint32 // The backup stream ID
+	Attributes uint32 // Stream attributes
+	Size       int64  // The size of the stream in bytes
+	Name       string // The name of the stream (for BackupAlternateData only).
+	Offset     int64  // The offset of the stream in the file (for BackupSparseBlock only).
+}
+
+type win32StreamId struct {
+	StreamId   uint32
+	Attributes uint32
+	Size       uint64
+	NameSize   uint32
+}
+
+// BackupStreamReader reads from a stream produced by the BackupRead Win32 API and produces a series
+// of BackupHeader values.
+type BackupStreamReader struct {
+	r         io.Reader
+	bytesLeft int64
+}
+
+// NewBackupStreamReader produces a BackupStreamReader from any io.Reader.
+func NewBackupStreamReader(r io.Reader) *BackupStreamReader {
+	return &BackupStreamReader{r, 0}
+}
+
+// Next returns the next backup stream and prepares for calls to Read(). It skips the remainder of the current stream if
+// it was not completely read.
+func (r *BackupStreamReader) Next() (*BackupHeader, error) {
+	if r.bytesLeft > 0 {
+		if s, ok := r.r.(io.Seeker); ok {
+			// Make sure Seek on io.SeekCurrent sometimes succeeds
+			// before trying the actual seek.
+			if _, err := s.Seek(0, io.SeekCurrent); err == nil {
+				if _, err = s.Seek(r.bytesLeft, io.SeekCurrent); err != nil {
+					return nil, err
+				}
+				r.bytesLeft = 0
+			}
+		}
+		if _, err := io.Copy(ioutil.Discard, r); err != nil {
+			return nil, err
+		}
+	}
+	var wsi win32StreamId
+	if err := binary.Read(r.r, binary.LittleEndian, &wsi); err != nil {
+		return nil, err
+	}
+	hdr := &BackupHeader{
+		Id:         wsi.StreamId,
+		Attributes: wsi.Attributes,
+		Size:       int64(wsi.Size),
+	}
+	if wsi.NameSize != 0 {
+		name := make([]uint16, int(wsi.NameSize/2))
+		if err := binary.Read(r.r, binary.LittleEndian, name); err != nil {
+			return nil, err
+		}
+		hdr.Name = syscall.UTF16ToString(name)
+	}
+	if wsi.StreamId == BackupSparseBlock {
+		if err := binary.Read(r.r, binary.LittleEndian, &hdr.Offset); err != nil {
+			return nil, err
+		}
+		hdr.Size -= 8
+	}
+	r.bytesLeft = hdr.Size
+	return hdr, nil
+}
+
+// Read reads from the current backup stream.
+func (r *BackupStreamReader) Read(b []byte) (int, error) {
+	if r.bytesLeft == 0 {
+		return 0, io.EOF
+	}
+	if int64(len(b)) > r.bytesLeft {
+		b = b[:r.bytesLeft]
+	}
+	n, err := r.r.Read(b)
+	r.bytesLeft -= int64(n)
+	if err == io.EOF {
+		err = io.ErrUnexpectedEOF
+	} else if r.bytesLeft == 0 && err == nil {
+		err = io.EOF
+	}
+	return n, err
+}
+
+// BackupStreamWriter writes a stream compatible with the BackupWrite Win32 API.
+type BackupStreamWriter struct {
+	w         io.Writer
+	bytesLeft int64
+}
+
+// NewBackupStreamWriter produces a BackupStreamWriter on top of an io.Writer.
+func NewBackupStreamWriter(w io.Writer) *BackupStreamWriter {
+	return &BackupStreamWriter{w, 0}
+}
+
+// WriteHeader writes the next backup stream header and prepares for calls to Write().
+func (w *BackupStreamWriter) WriteHeader(hdr *BackupHeader) error {
+	if w.bytesLeft != 0 {
+		return fmt.Errorf("missing %d bytes", w.bytesLeft)
+	}
+	name := utf16.Encode([]rune(hdr.Name))
+	wsi := win32StreamId{
+		StreamId:   hdr.Id,
+		Attributes: hdr.Attributes,
+		Size:       uint64(hdr.Size),
+		NameSize:   uint32(len(name) * 2),
+	}
+	if hdr.Id == BackupSparseBlock {
+		// Include space for the int64 block offset
+		wsi.Size += 8
+	}
+	if err := binary.Write(w.w, binary.LittleEndian, &wsi); err != nil {
+		return err
+	}
+	if len(name) != 0 {
+		if err := binary.Write(w.w, binary.LittleEndian, name); err != nil {
+			return err
+		}
+	}
+	if hdr.Id == BackupSparseBlock {
+		if err := binary.Write(w.w, binary.LittleEndian, hdr.Offset); err != nil {
+			return err
+		}
+	}
+	w.bytesLeft = hdr.Size
+	return nil
+}
+
+// Write writes to the current backup stream.
+func (w *BackupStreamWriter) Write(b []byte) (int, error) {
+	if w.bytesLeft < int64(len(b)) {
+		return 0, fmt.Errorf("too many bytes by %d", int64(len(b))-w.bytesLeft)
+	}
+	n, err := w.w.Write(b)
+	w.bytesLeft -= int64(n)
+	return n, err
+}
+
+// BackupFileReader provides an io.ReadCloser interface on top of the BackupRead Win32 API.
+type BackupFileReader struct {
+	f               *os.File
+	includeSecurity bool
+	ctx             uintptr
+}
+
+// NewBackupFileReader returns a new BackupFileReader from a file handle. If includeSecurity is true,
+// Read will attempt to read the security descriptor of the file.
+func NewBackupFileReader(f *os.File, includeSecurity bool) *BackupFileReader {
+	r := &BackupFileReader{f, includeSecurity, 0}
+	return r
+}
+
+// Read reads a backup stream from the file by calling the Win32 API BackupRead().
+func (r *BackupFileReader) Read(b []byte) (int, error) {
+	var bytesRead uint32
+	err := backupRead(syscall.Handle(r.f.Fd()), b, &bytesRead, false, r.includeSecurity, &r.ctx)
+	if err != nil {
+		return 0, &os.PathError{"BackupRead", r.f.Name(), err}
+	}
+	runtime.KeepAlive(r.f)
+	if bytesRead == 0 {
+		return 0, io.EOF
+	}
+	return int(bytesRead), nil
+}
+
+// Close frees Win32 resources associated with the BackupFileReader. It does not close
+// the underlying file.
+func (r *BackupFileReader) Close() error {
+	if r.ctx != 0 {
+		backupRead(syscall.Handle(r.f.Fd()), nil, nil, true, false, &r.ctx)
+		runtime.KeepAlive(r.f)
+		r.ctx = 0
+	}
+	return nil
+}
+
+// BackupFileWriter provides an io.WriteCloser interface on top of the BackupWrite Win32 API.
+type BackupFileWriter struct {
+	f               *os.File
+	includeSecurity bool
+	ctx             uintptr
+}
+
+// NewBackupFileWriter returns a new BackupFileWriter from a file handle. If includeSecurity is true,
+// Write() will attempt to restore the security descriptor from the stream.
+func NewBackupFileWriter(f *os.File, includeSecurity bool) *BackupFileWriter {
+	w := &BackupFileWriter{f, includeSecurity, 0}
+	return w
+}
+
+// Write restores a portion of the file using the provided backup stream.
+func (w *BackupFileWriter) Write(b []byte) (int, error) {
+	var bytesWritten uint32
+	err := backupWrite(syscall.Handle(w.f.Fd()), b, &bytesWritten, false, w.includeSecurity, &w.ctx)
+	if err != nil {
+		return 0, &os.PathError{"BackupWrite", w.f.Name(), err}
+	}
+	runtime.KeepAlive(w.f)
+	if int(bytesWritten) != len(b) {
+		return int(bytesWritten), errors.New("not all bytes could be written")
+	}
+	return len(b), nil
+}
+
+// Close frees Win32 resources associated with the BackupFileWriter. It does not
+// close the underlying file.
+func (w *BackupFileWriter) Close() error {
+	if w.ctx != 0 {
+		backupWrite(syscall.Handle(w.f.Fd()), nil, nil, true, false, &w.ctx)
+		runtime.KeepAlive(w.f)
+		w.ctx = 0
+	}
+	return nil
+}
+
+// OpenForBackup opens a file or directory, potentially skipping access checks if the backup
+// or restore privileges have been acquired.
+//
+// If the file opened was a directory, it cannot be used with Readdir().
+func OpenForBackup(path string, access uint32, share uint32, createmode uint32) (*os.File, error) {
+	winPath, err := syscall.UTF16FromString(path)
+	if err != nil {
+		return nil, err
+	}
+	h, err := syscall.CreateFile(&winPath[0], access, share, nil, createmode, syscall.FILE_FLAG_BACKUP_SEMANTICS|syscall.FILE_FLAG_OPEN_REPARSE_POINT, 0)
+	if err != nil {
+		err = &os.PathError{Op: "open", Path: path, Err: err}
+		return nil, err
+	}
+	return os.NewFile(uintptr(h), path), nil
+}
diff --git a/vendor/github.com/Microsoft/go-winio/ea.go b/vendor/github.com/Microsoft/go-winio/ea.go
new file mode 100644
index 000000000..4051c1b33
--- /dev/null
+++ b/vendor/github.com/Microsoft/go-winio/ea.go
@@ -0,0 +1,137 @@
+package winio
+
+import (
+	"bytes"
+	"encoding/binary"
+	"errors"
+)
+
+type fileFullEaInformation struct {
+	NextEntryOffset uint32
+	Flags           uint8
+	NameLength      uint8
+	ValueLength     uint16
+}
+
+var (
+	fileFullEaInformationSize = binary.Size(&fileFullEaInformation{})
+
+	errInvalidEaBuffer = errors.New("invalid extended attribute buffer")
+	errEaNameTooLarge  = errors.New("extended attribute name too large")
+	errEaValueTooLarge = errors.New("extended attribute value too large")
+)
+
+// ExtendedAttribute represents a single Windows EA.
+type ExtendedAttribute struct {
+	Name  string
+	Value []byte
+	Flags uint8
+}
+
+func parseEa(b []byte) (ea ExtendedAttribute, nb []byte, err error) {
+	var info fileFullEaInformation
+	err = binary.Read(bytes.NewReader(b), binary.LittleEndian, &info)
+	if err != nil {
+		err = errInvalidEaBuffer
+		return
+	}
+
+	nameOffset := fileFullEaInformationSize
+	nameLen := int(info.NameLength)
+	valueOffset := nameOffset + int(info.NameLength) + 1
+	valueLen := int(info.ValueLength)
+	nextOffset := int(info.NextEntryOffset)
+	if valueLen+valueOffset > len(b) || nextOffset < 0 || nextOffset > len(b) {
+		err = errInvalidEaBuffer
+		return
+	}
+
+	ea.Name = string(b[nameOffset : nameOffset+nameLen])
+	ea.Value = b[valueOffset : valueOffset+valueLen]
+	ea.Flags = info.Flags
+	if info.NextEntryOffset != 0 {
+		nb = b[info.NextEntryOffset:]
+	}
+	return
+}
+
+// DecodeExtendedAttributes decodes a list of EAs from a FILE_FULL_EA_INFORMATION
+// buffer retrieved from BackupRead, ZwQueryEaFile, etc.
+func DecodeExtendedAttributes(b []byte) (eas []ExtendedAttribute, err error) {
+	for len(b) != 0 {
+		ea, nb, err := parseEa(b)
+		if err != nil {
+			return nil, err
+		}
+
+		eas = append(eas, ea)
+		b = nb
+	}
+	return
+}
+
+func writeEa(buf *bytes.Buffer, ea *ExtendedAttribute, last bool) error {
+	if int(uint8(len(ea.Name))) != len(ea.Name) {
+		return errEaNameTooLarge
+	}
+	if int(uint16(len(ea.Value))) != len(ea.Value) {
+		return errEaValueTooLarge
+	}
+	entrySize := uint32(fileFullEaInformationSize + len(ea.Name) + 1 + len(ea.Value))
+	withPadding := (entrySize + 3) &^ 3
+	nextOffset := uint32(0)
+	if !last {
+		nextOffset = withPadding
+	}
+	info := fileFullEaInformation{
+		NextEntryOffset: nextOffset,
+		Flags:           ea.Flags,
+		NameLength:      uint8(len(ea.Name)),
+		ValueLength:     uint16(len(ea.Value)),
+	}
+
+	err := binary.Write(buf, binary.LittleEndian, &info)
+	if err != nil {
+		return err
+	}
+
+	_, err = buf.Write([]byte(ea.Name))
+	if err != nil {
+		return err
+	}
+
+	err = buf.WriteByte(0)
+	if err != nil {
+		return err
+	}
+
+	_, err = buf.Write(ea.Value)
+	if err != nil {
+		return err
+	}
+
+	_, err = buf.Write([]byte{0, 0, 0}[0 : withPadding-entrySize])
+	if err != nil {
+		return err
+	}
+
+	return nil
+}
+
+// EncodeExtendedAttributes encodes a list of EAs into a FILE_FULL_EA_INFORMATION
+// buffer for use with BackupWrite, ZwSetEaFile, etc.
+func EncodeExtendedAttributes(eas []ExtendedAttribute) ([]byte, error) {
+	var buf bytes.Buffer
+	for i := range eas {
+		last := false
+		if i == len(eas)-1 {
+			last = true
+		}
+
+		err := writeEa(&buf, &eas[i], last)
+		if err != nil {
+			return nil, err
+		}
+	}
+	return buf.Bytes(), nil
+}
diff --git a/vendor/github.com/Microsoft/go-winio/file.go b/vendor/github.com/Microsoft/go-winio/file.go
new file mode 100644
index 000000000..0385e4108
--- /dev/null
+++ b/vendor/github.com/Microsoft/go-winio/file.go
@@ -0,0 +1,323 @@
+// +build windows
+
+package winio
+
+import (
+	"errors"
+	"io"
+	"runtime"
+	"sync"
+	"sync/atomic"
+	"syscall"
+	"time"
+)
+
+//sys cancelIoEx(file syscall.Handle, o *syscall.Overlapped) (err error) = CancelIoEx
+//sys createIoCompletionPort(file syscall.Handle, port syscall.Handle, key uintptr, threadCount uint32) (newport syscall.Handle, err error) = CreateIoCompletionPort
+//sys getQueuedCompletionStatus(port syscall.Handle, bytes *uint32, key *uintptr, o **ioOperation, timeout uint32) (err error) = GetQueuedCompletionStatus
+//sys setFileCompletionNotificationModes(h syscall.Handle, flags uint8) (err error) = SetFileCompletionNotificationModes
+//sys wsaGetOverlappedResult(h syscall.Handle, o *syscall.Overlapped, bytes *uint32, wait bool, flags *uint32) (err error) = ws2_32.WSAGetOverlappedResult
+
+type atomicBool int32
+
+func (b *atomicBool) isSet() bool { return atomic.LoadInt32((*int32)(b)) != 0 }
+func (b *atomicBool) setFalse()   { atomic.StoreInt32((*int32)(b), 0) }
+func (b *atomicBool) setTrue()    { atomic.StoreInt32((*int32)(b), 1) }
+func (b *atomicBool) swap(new bool) bool {
+	var newInt int32
+	if new {
+		newInt = 1
+	}
+	return atomic.SwapInt32((*int32)(b), newInt) == 1
+}
+
+const (
+	cFILE_SKIP_COMPLETION_PORT_ON_SUCCESS = 1
+	cFILE_SKIP_SET_EVENT_ON_HANDLE        = 2
+)
+
+var (
+	ErrFileClosed = errors.New("file has already been closed")
+	ErrTimeout    = &timeoutError{}
+)
+
+type timeoutError struct{}
+
+func (e *timeoutError) Error() string   { return "i/o timeout" }
+func (e *timeoutError) Timeout() bool   { return true }
+func (e *timeoutError) Temporary() bool { return true }
+
+type timeoutChan chan struct{}
+
+var ioInitOnce sync.Once
+var ioCompletionPort syscall.Handle
+
+// ioResult contains the result of an asynchronous IO operation
+type ioResult struct {
+	bytes uint32
+	err   error
+}
+
+// ioOperation represents an outstanding asynchronous Win32 IO
+type ioOperation struct {
+	o  syscall.Overlapped
+	ch chan ioResult
+}
+
+func initIo() {
+	h, err := createIoCompletionPort(syscall.InvalidHandle, 0, 0, 0xffffffff)
+	if err != nil {
+		panic(err)
+	}
+	ioCompletionPort = h
+	go ioCompletionProcessor(h)
+}
+
+// win32File implements Reader, Writer, and Closer on a Win32 handle without blocking in a syscall.
+// It takes ownership of this handle and will close it if it is garbage collected.
+type win32File struct {
+	handle        syscall.Handle
+	wg            sync.WaitGroup
+	wgLock        sync.RWMutex
+	closing       atomicBool
+	socket        bool
+	readDeadline  deadlineHandler
+	writeDeadline deadlineHandler
+}
+
+type deadlineHandler struct {
+	setLock     sync.Mutex
+	channel     timeoutChan
+	channelLock sync.RWMutex
+	timer       *time.Timer
+	timedout    atomicBool
+}
+
+// makeWin32File makes a new win32File from an existing file handle
+func makeWin32File(h syscall.Handle) (*win32File, error) {
+	f := &win32File{handle: h}
+	ioInitOnce.Do(initIo)
+	_, err := createIoCompletionPort(h, ioCompletionPort, 0, 0xffffffff)
+	if err != nil {
+		return nil, err
+	}
+	err = setFileCompletionNotificationModes(h, cFILE_SKIP_COMPLETION_PORT_ON_SUCCESS|cFILE_SKIP_SET_EVENT_ON_HANDLE)
+	if err != nil {
+		return nil, err
+	}
+	f.readDeadline.channel = make(timeoutChan)
+	f.writeDeadline.channel = make(timeoutChan)
+	return f, nil
+}
+
+func MakeOpenFile(h syscall.Handle) (io.ReadWriteCloser, error) {
+	// If we return the result of makeWin32File directly, it can result in an
+	// interface-wrapped nil, rather than a nil interface value.
+	f, err := makeWin32File(h)
+	if err != nil {
+		return nil, err
+	}
+	return f, nil
+}
+
+// closeHandle closes the resources associated with a Win32 handle
+func (f *win32File) closeHandle() {
+	f.wgLock.Lock()
+	// Atomically set that we are closing, releasing the resources only once.
+	if !f.closing.swap(true) {
+		f.wgLock.Unlock()
+		// cancel all IO and wait for it to complete
+		cancelIoEx(f.handle, nil)
+		f.wg.Wait()
+		// at this point, no new IO can start
+		syscall.Close(f.handle)
+		f.handle = 0
+	} else {
+		f.wgLock.Unlock()
+	}
+}
+
+// Close closes a win32File.
+func (f *win32File) Close() error {
+	f.closeHandle()
+	return nil
+}
+
+// prepareIo prepares for a new IO operation.
+// The caller must call f.wg.Done() when the IO is finished, prior to Close() returning.
+func (f *win32File) prepareIo() (*ioOperation, error) {
+	f.wgLock.RLock()
+	if f.closing.isSet() {
+		f.wgLock.RUnlock()
+		return nil, ErrFileClosed
+	}
+	f.wg.Add(1)
+	f.wgLock.RUnlock()
+	c := &ioOperation{}
+	c.ch = make(chan ioResult)
+	return c, nil
+}
+
+// ioCompletionProcessor processes completed async IOs forever
+func ioCompletionProcessor(h syscall.Handle) {
+	for {
+		var bytes uint32
+		var key uintptr
+		var op *ioOperation
+		err := getQueuedCompletionStatus(h, &bytes, &key, &op, syscall.INFINITE)
+		if op == nil {
+			panic(err)
+		}
+		op.ch <- ioResult{bytes, err}
+	}
+}
+
+// asyncIo processes the return value from ReadFile or WriteFile, blocking until
+// the operation has actually completed.
+func (f *win32File) asyncIo(c *ioOperation, d *deadlineHandler, bytes uint32, err error) (int, error) {
+	if err != syscall.ERROR_IO_PENDING {
+		return int(bytes), err
+	}
+
+	if f.closing.isSet() {
+		cancelIoEx(f.handle, &c.o)
+	}
+
+	var timeout timeoutChan
+	if d != nil {
+		d.channelLock.Lock()
+		timeout = d.channel
+		d.channelLock.Unlock()
+	}
+
+	var r ioResult
+	select {
+	case r = <-c.ch:
+		err = r.err
+		if err == syscall.ERROR_OPERATION_ABORTED {
+			if f.closing.isSet() {
+				err = ErrFileClosed
+			}
+		} else if err != nil && f.socket {
+			// err is from Win32. Query the overlapped structure to get the winsock error.
+			var bytes, flags uint32
+			err = wsaGetOverlappedResult(f.handle, &c.o, &bytes, false, &flags)
+		}
+	case <-timeout:
+		cancelIoEx(f.handle, &c.o)
+		r = <-c.ch
+		err = r.err
+		if err == syscall.ERROR_OPERATION_ABORTED {
+			err = ErrTimeout
+		}
+	}
+
+	// runtime.KeepAlive is needed, as c is passed via native
+	// code to ioCompletionProcessor, c must remain alive
+	// until the channel read is complete.
+	runtime.KeepAlive(c)
+	return int(r.bytes), err
+}
+
+// Read reads from a file handle.
+func (f *win32File) Read(b []byte) (int, error) {
+	c, err := f.prepareIo()
+	if err != nil {
+		return 0, err
+	}
+	defer f.wg.Done()
+
+	if f.readDeadline.timedout.isSet() {
+		return 0, ErrTimeout
+	}
+
+	var bytes uint32
+	err = syscall.ReadFile(f.handle, b, &bytes, &c.o)
+	n, err := f.asyncIo(c, &f.readDeadline, bytes, err)
+	runtime.KeepAlive(b)
+
+	// Handle EOF conditions.
+	if err == nil && n == 0 && len(b) != 0 {
+		return 0, io.EOF
+	} else if err == syscall.ERROR_BROKEN_PIPE {
+		return 0, io.EOF
+	} else {
+		return n, err
+	}
+}
+
+// Write writes to a file handle.
+func (f *win32File) Write(b []byte) (int, error) {
+	c, err := f.prepareIo()
+	if err != nil {
+		return 0, err
+	}
+	defer f.wg.Done()
+
+	if f.writeDeadline.timedout.isSet() {
+		return 0, ErrTimeout
+	}
+
+	var bytes uint32
+	err = syscall.WriteFile(f.handle, b, &bytes, &c.o)
+	n, err := f.asyncIo(c, &f.writeDeadline, bytes, err)
+	runtime.KeepAlive(b)
+	return n, err
+}
+
+func (f *win32File) SetReadDeadline(deadline time.Time) error {
+	return f.readDeadline.set(deadline)
+}
+
+func (f *win32File) SetWriteDeadline(deadline time.Time) error {
+	return f.writeDeadline.set(deadline)
+}
+
+func (f *win32File) Flush() error {
+	return syscall.FlushFileBuffers(f.handle)
+}
+
+func (f *win32File) Fd() uintptr {
+	return uintptr(f.handle)
+}
+
+func (d *deadlineHandler) set(deadline time.Time) error {
+	d.setLock.Lock()
+	defer d.setLock.Unlock()
+
+	if d.timer != nil {
+		if !d.timer.Stop() {
+			<-d.channel
+		}
+		d.timer = nil
+	}
+	d.timedout.setFalse()
+
+	select {
+	case <-d.channel:
+		d.channelLock.Lock()
+		d.channel = make(chan struct{})
+		d.channelLock.Unlock()
+	default:
+	}
+
+	if deadline.IsZero() {
+		return nil
+	}
+
+	timeoutIO := func() {
+		d.timedout.setTrue()
+		close(d.channel)
+	}
+
+	now := time.Now()
+	duration := deadline.Sub(now)
+	if deadline.After(now) {
+		// Deadline is in the future, set a timer to wait
+		d.timer = time.AfterFunc(duration, timeoutIO)
+	} else {
+		// Deadline is in the past. Cancel all pending IO now.
+		timeoutIO()
+	}
+	return nil
+}
diff --git a/vendor/github.com/Microsoft/go-winio/fileinfo.go b/vendor/github.com/Microsoft/go-winio/fileinfo.go
new file mode 100644
index 000000000..ada2fbab6
--- /dev/null
+++ b/vendor/github.com/Microsoft/go-winio/fileinfo.go
@@ -0,0 +1,61 @@
+// +build windows
+
+package winio
+
+import (
+	"os"
+	"runtime"
+	"syscall"
+	"unsafe"
+)
+
+//sys getFileInformationByHandleEx(h syscall.Handle, class uint32, buffer *byte, size uint32) (err error) = GetFileInformationByHandleEx
+//sys setFileInformationByHandle(h syscall.Handle, class uint32, buffer *byte, size uint32) (err error) = SetFileInformationByHandle
+
+const (
+	fileBasicInfo = 0
+	fileIDInfo    = 0x12
+)
+
+// FileBasicInfo contains file access time and file attributes information.
+type FileBasicInfo struct {
+	CreationTime, LastAccessTime, LastWriteTime, ChangeTime syscall.Filetime
+	FileAttributes                                          uint32
+	pad                                                     uint32 // padding
+}
+
+// GetFileBasicInfo retrieves times and attributes for a file.
+func GetFileBasicInfo(f *os.File) (*FileBasicInfo, error) {
+	bi := &FileBasicInfo{}
+	if err := getFileInformationByHandleEx(syscall.Handle(f.Fd()), fileBasicInfo, (*byte)(unsafe.Pointer(bi)), uint32(unsafe.Sizeof(*bi))); err != nil {
+		return nil, &os.PathError{Op: "GetFileInformationByHandleEx", Path: f.Name(), Err: err}
+	}
+	runtime.KeepAlive(f)
+	return bi, nil
+}
+
+// SetFileBasicInfo sets times and attributes for a file.
+func SetFileBasicInfo(f *os.File, bi *FileBasicInfo) error {
+	if err := setFileInformationByHandle(syscall.Handle(f.Fd()), fileBasicInfo, (*byte)(unsafe.Pointer(bi)), uint32(unsafe.Sizeof(*bi))); err != nil {
+		return &os.PathError{Op: "SetFileInformationByHandle", Path: f.Name(), Err: err}
+	}
+	runtime.KeepAlive(f)
+	return nil
+}
+
+// FileIDInfo contains the volume serial number and file ID for a file. This pair should be
+// unique on a system.
+type FileIDInfo struct {
+	VolumeSerialNumber uint64
+	FileID             [16]byte
+}
+
+// GetFileID retrieves the unique (volume, file ID) pair for a file.
+func GetFileID(f *os.File) (*FileIDInfo, error) {
+	fileID := &FileIDInfo{}
+	if err := getFileInformationByHandleEx(syscall.Handle(f.Fd()), fileIDInfo, (*byte)(unsafe.Pointer(fileID)), uint32(unsafe.Sizeof(*fileID))); err != nil {
+		return nil, &os.PathError{Op: "GetFileInformationByHandleEx", Path: f.Name(), Err: err}
+	}
+	runtime.KeepAlive(f)
+	return fileID, nil
+}
diff --git a/vendor/github.com/Microsoft/go-winio/go.mod b/vendor/github.com/Microsoft/go-winio/go.mod
new file mode 100644
index 000000000..50b9d6e2e
--- /dev/null
+++ b/vendor/github.com/Microsoft/go-winio/go.mod
@@ -0,0 +1,9 @@
+module github.com/Microsoft/go-winio
+
+go 1.12
+
+require (
+	github.com/pkg/errors v0.8.1
+	github.com/sirupsen/logrus v1.4.1
+	golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3
+)
diff --git a/vendor/github.com/Microsoft/go-winio/go.sum b/vendor/github.com/Microsoft/go-winio/go.sum
new file mode 100644
index 000000000..209aa8cf4
--- /dev/null
+++ b/vendor/github.com/Microsoft/go-winio/go.sum
@@ -0,0 +1,18 @@
+github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
+github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+github.com/konsorten/go-windows-terminal-sequences v1.0.1 h1:mweAR1A6xJ3oS2pRaGiHgQ4OO8tzTaLawm8vnODuwDk=
+github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
+github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
+github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
+github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
+github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
+github.com/sirupsen/logrus v1.4.1 h1:GL2rEmy6nsikmW0r8opw9JIRScdMF5hA8cOYLH7In1k=
+github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q=
+github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
+github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w=
+github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
+golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b h1:ag/x1USPSsqHud38I9BAC88qdNLDHHtQ4mlgQIZPPNA=
+golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3 h1:7TYNF4UdlohbFwpNH04CoPMp1cHUZgO1Ebq5r2hIjfo=
+golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
diff --git a/vendor/github.com/Microsoft/go-winio/hvsock.go b/vendor/github.com/Microsoft/go-winio/hvsock.go
new file mode 100644
index 000000000..dbfe790ee
--- /dev/null
+++ b/vendor/github.com/Microsoft/go-winio/hvsock.go
@@ -0,0 +1,305 @@
+package winio
+
+import (
+	"fmt"
+	"io"
+	"net"
+	"os"
+	"syscall"
+	"time"
+	"unsafe"
+
+	"github.com/Microsoft/go-winio/pkg/guid"
+)
+
+//sys bind(s syscall.Handle, name unsafe.Pointer, namelen int32) (err error) [failretval==socketError] = ws2_32.bind
+
+const (
+	afHvSock = 34 // AF_HYPERV
+
+	socketError = ^uintptr(0)
+)
+
+// An HvsockAddr is an address for a AF_HYPERV socket.
+type HvsockAddr struct {
+	VMID      guid.GUID
+	ServiceID guid.GUID
+}
+
+type rawHvsockAddr struct {
+	Family    uint16
+	_         uint16
+	VMID      guid.GUID
+	ServiceID guid.GUID
+}
+
+// Network returns the address's network name, "hvsock".
+func (addr *HvsockAddr) Network() string {
+	return "hvsock"
+}
+
+func (addr *HvsockAddr) String() string {
+	return fmt.Sprintf("%s:%s", &addr.VMID, &addr.ServiceID)
+}
+
+// VsockServiceID returns an hvsock service ID corresponding to the specified AF_VSOCK port.
+func VsockServiceID(port uint32) guid.GUID {
+	g, _ := guid.FromString("00000000-facb-11e6-bd58-64006a7986d3")
+	g.Data1 = port
+	return g
+}
+
+func (addr *HvsockAddr) raw() rawHvsockAddr {
+	return rawHvsockAddr{
+		Family:    afHvSock,
+		VMID:      addr.VMID,
+		ServiceID: addr.ServiceID,
+	}
+}
+
+func (addr *HvsockAddr) fromRaw(raw *rawHvsockAddr) {
+	addr.VMID = raw.VMID
+	addr.ServiceID = raw.ServiceID
+}
+
+// HvsockListener is a socket listener for the AF_HYPERV address family.
+type HvsockListener struct {
+	sock *win32File
+	addr HvsockAddr
+}
+
+// HvsockConn is a connected socket of the AF_HYPERV address family.
+type HvsockConn struct {
+	sock          *win32File
+	local, remote HvsockAddr
+}
+
+func newHvSocket() (*win32File, error) {
+	fd, err := syscall.Socket(afHvSock, syscall.SOCK_STREAM, 1)
+	if err != nil {
+		return nil, os.NewSyscallError("socket", err)
+	}
+	f, err := makeWin32File(fd)
+	if err != nil {
+		syscall.Close(fd)
+		return nil, err
+	}
+	f.socket = true
+	return f, nil
+}
+
+// ListenHvsock listens for connections on the specified hvsock address.
+func ListenHvsock(addr *HvsockAddr) (_ *HvsockListener, err error) {
+	l := &HvsockListener{addr: *addr}
+	sock, err := newHvSocket()
+	if err != nil {
+		return nil, l.opErr("listen", err)
+	}
+	sa := addr.raw()
+	err = bind(sock.handle, unsafe.Pointer(&sa), int32(unsafe.Sizeof(sa)))
+	if err != nil {
+		return nil, l.opErr("listen", os.NewSyscallError("socket", err))
+	}
+	err = syscall.Listen(sock.handle, 16)
+	if err != nil {
+		return nil, l.opErr("listen", os.NewSyscallError("listen", err))
+	}
+	return &HvsockListener{sock: sock, addr: *addr}, nil
+}
+
+func (l *HvsockListener) opErr(op string, err error) error {
+	return &net.OpError{Op: op, Net: "hvsock", Addr: &l.addr, Err: err}
+}
+
+// Addr returns the listener's network address.
+func (l *HvsockListener) Addr() net.Addr {
+	return &l.addr
+}
+
+// Accept waits for the next connection and returns it.
+func (l *HvsockListener) Accept() (_ net.Conn, err error) {
+	sock, err := newHvSocket()
+	if err != nil {
+		return nil, l.opErr("accept", err)
+	}
+	defer func() {
+		if sock != nil {
+			sock.Close()
+		}
+	}()
+	c, err := l.sock.prepareIo()
+	if err != nil {
+		return nil, l.opErr("accept", err)
+	}
+	defer l.sock.wg.Done()
+
+	// AcceptEx, per documentation, requires an extra 16 bytes per address.
+	const addrlen = uint32(16 + unsafe.Sizeof(rawHvsockAddr{}))
+	var addrbuf [addrlen * 2]byte
+
+	var bytes uint32
+	err = syscall.AcceptEx(l.sock.handle, sock.handle, &addrbuf[0], 0, addrlen, addrlen, &bytes, &c.o)
+	_, err = l.sock.asyncIo(c, nil, bytes, err)
+	if err != nil {
+		return nil, l.opErr("accept", os.NewSyscallError("acceptex", err))
+	}
+	conn := &HvsockConn{
+		sock: sock,
+	}
+	conn.local.fromRaw((*rawHvsockAddr)(unsafe.Pointer(&addrbuf[0])))
+	conn.remote.fromRaw((*rawHvsockAddr)(unsafe.Pointer(&addrbuf[addrlen])))
+	sock = nil
+	return conn, nil
+}
+
+// Close closes the listener, causing any pending Accept calls to fail.
+func (l *HvsockListener) Close() error {
+	return l.sock.Close()
+}
+
+/* Need to finish ConnectEx handling
+func DialHvsock(ctx context.Context, addr *HvsockAddr) (*HvsockConn, error) {
+	sock, err := newHvSocket()
+	if err != nil {
+		return nil, err
+	}
+	defer func() {
+		if sock != nil {
+			sock.Close()
+		}
+	}()
+	c, err := sock.prepareIo()
+	if err != nil {
+		return nil, err
+	}
+	defer sock.wg.Done()
+	var bytes uint32
+	err = windows.ConnectEx(windows.Handle(sock.handle), sa, nil, 0, &bytes, &c.o)
+	_, err = sock.asyncIo(ctx, c, nil, bytes, err)
+	if err != nil {
+		return nil, err
+	}
+	conn := &HvsockConn{
+		sock:   sock,
+		remote: *addr,
+	}
+	sock = nil
+	return conn, nil
+}
+*/
+
+func (conn *HvsockConn) opErr(op string, err error) error {
+	return &net.OpError{Op: op, Net: "hvsock", Source: &conn.local, Addr: &conn.remote, Err: err}
+}
+
+func (conn *HvsockConn) Read(b []byte) (int, error) {
+	c, err := conn.sock.prepareIo()
+	if err != nil {
+		return 0, conn.opErr("read", err)
+	}
+	defer conn.sock.wg.Done()
+	buf := syscall.WSABuf{Buf: &b[0], Len: uint32(len(b))}
+	var flags, bytes uint32
+	err = syscall.WSARecv(conn.sock.handle, &buf, 1, &bytes, &flags, &c.o, nil)
+	n, err := conn.sock.asyncIo(c, &conn.sock.readDeadline, bytes, err)
+	if err != nil {
+		if _, ok := err.(syscall.Errno); ok {
+			err = os.NewSyscallError("wsarecv", err)
+		}
+		return 0, conn.opErr("read", err)
+	} else if n == 0 {
+		err = io.EOF
+	}
+	return n, err
+}
+
+func (conn *HvsockConn) Write(b []byte) (int, error) {
+	t := 0
+	for len(b) != 0 {
+		n, err := conn.write(b)
+		if err != nil {
+			return t + n, err
+		}
+		t += n
+		b = b[n:]
+	}
+	return t, nil
+}
+
+func (conn *HvsockConn) write(b []byte) (int, error) {
+	c, err := conn.sock.prepareIo()
+	if err != nil {
+		return 0, conn.opErr("write", err)
+	}
+	defer conn.sock.wg.Done()
+	buf := syscall.WSABuf{Buf: &b[0], Len: uint32(len(b))}
+	var bytes uint32
+	err = syscall.WSASend(conn.sock.handle, &buf, 1, &bytes, 0, &c.o, nil)
+	n, err := conn.sock.asyncIo(c, &conn.sock.writeDeadline, bytes, err)
+	if err != nil {
+		if _, ok := err.(syscall.Errno); ok {
+			err = os.NewSyscallError("wsasend", err)
+		}
+		return 0, conn.opErr("write", err)
+	}
+	return n, err
+}
+
+// Close closes the socket connection, failing any pending read or write calls.
+func (conn *HvsockConn) Close() error {
+	return conn.sock.Close()
+}
+
+func (conn *HvsockConn) shutdown(how int) error {
+	err := syscall.Shutdown(conn.sock.handle, syscall.SHUT_RD)
+	if err != nil {
+		return os.NewSyscallError("shutdown", err)
+	}
+	return nil
+}
+
+// CloseRead shuts down the read end of the socket.
+func (conn *HvsockConn) CloseRead() error {
+	err := conn.shutdown(syscall.SHUT_RD)
+	if err != nil {
+		return conn.opErr("close", err)
+	}
+	return nil
+}
+
+// CloseWrite shuts down the write end of the socket, notifying the other endpoint that
+// no more data will be written.
+func (conn *HvsockConn) CloseWrite() error {
+	err := conn.shutdown(syscall.SHUT_WR)
+	if err != nil {
+		return conn.opErr("close", err)
+	}
+	return nil
+}
+
+// LocalAddr returns the local address of the connection.
+func (conn *HvsockConn) LocalAddr() net.Addr {
+	return &conn.local
+}
+
+// RemoteAddr returns the remote address of the connection.
+func (conn *HvsockConn) RemoteAddr() net.Addr {
+	return &conn.remote
+}
+
+// SetDeadline implements the net.Conn SetDeadline method.
+func (conn *HvsockConn) SetDeadline(t time.Time) error {
+	conn.SetReadDeadline(t)
+	conn.SetWriteDeadline(t)
+	return nil
+}
+
+// SetReadDeadline implements the net.Conn SetReadDeadline method.
+func (conn *HvsockConn) SetReadDeadline(t time.Time) error {
+	return conn.sock.SetReadDeadline(t)
+}
+
+// SetWriteDeadline implements the net.Conn SetWriteDeadline method.
+func (conn *HvsockConn) SetWriteDeadline(t time.Time) error {
+	return conn.sock.SetWriteDeadline(t)
+}
diff --git a/vendor/github.com/Microsoft/go-winio/pipe.go b/vendor/github.com/Microsoft/go-winio/pipe.go
new file mode 100644
index 000000000..ff96dff1c
--- /dev/null
+++ b/vendor/github.com/Microsoft/go-winio/pipe.go
@@ -0,0 +1,517 @@
+// +build windows
+
+package winio
+
+import (
+	"context"
+	"errors"
+	"fmt"
+	"io"
+	"net"
+	"os"
+	"runtime"
+	"syscall"
+	"time"
+	"unsafe"
+)
+
+//sys connectNamedPipe(pipe syscall.Handle, o *syscall.Overlapped) (err error) = ConnectNamedPipe
+//sys createNamedPipe(name string, flags uint32, pipeMode uint32, maxInstances uint32, outSize uint32, inSize uint32, defaultTimeout uint32, sa *syscall.SecurityAttributes) (handle syscall.Handle, err error)  [failretval==syscall.InvalidHandle] = CreateNamedPipeW
+//sys createFile(name string, access uint32, mode uint32, sa *syscall.SecurityAttributes, createmode uint32, attrs uint32, templatefile syscall.Handle) (handle syscall.Handle, err error) [failretval==syscall.InvalidHandle] = CreateFileW
+//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)
+	cERROR_NO_DATA        = syscall.Errno(232)
+	cERROR_PIPE_CONNECTED = syscall.Errno(535)
+	cERROR_SEM_TIMEOUT    = syscall.Errno(121)
+
+	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 (
+	// ErrPipeListenerClosed is returned for pipe operations on listeners that have been closed.
+	// This error should match net.errClosing since docker takes a dependency on its text.
+	ErrPipeListenerClosed = errors.New("use of closed network connection")
+
+	errPipeWriteClosed = errors.New("pipe has been closed for write")
+)
+
+type win32Pipe struct {
+	*win32File
+	path string
+}
+
+type win32MessageBytePipe struct {
+	win32Pipe
+	writeClosed bool
+	readEOF     bool
+}
+
+type pipeAddress string
+
+func (f *win32Pipe) LocalAddr() net.Addr {
+	return pipeAddress(f.path)
+}
+
+func (f *win32Pipe) RemoteAddr() net.Addr {
+	return pipeAddress(f.path)
+}
+
+func (f *win32Pipe) SetDeadline(t time.Time) error {
+	f.SetReadDeadline(t)
+	f.SetWriteDeadline(t)
+	return nil
+}
+
+// CloseWrite closes the write side of a message pipe in byte mode.
+func (f *win32MessageBytePipe) CloseWrite() error {
+	if f.writeClosed {
+		return errPipeWriteClosed
+	}
+	err := f.win32File.Flush()
+	if err != nil {
+		return err
+	}
+	_, err = f.win32File.Write(nil)
+	if err != nil {
+		return err
+	}
+	f.writeClosed = true
+	return nil
+}
+
+// Write writes bytes to a message pipe in byte mode. Zero-byte writes are ignored, since
+// they are used to implement CloseWrite().
+func (f *win32MessageBytePipe) Write(b []byte) (int, error) {
+	if f.writeClosed {
+		return 0, errPipeWriteClosed
+	}
+	if len(b) == 0 {
+		return 0, nil
+	}
+	return f.win32File.Write(b)
+}
+
+// Read reads bytes from a message pipe in byte mode. A read of a zero-byte message on a message
+// mode pipe will return io.EOF, as will all subsequent reads.
+func (f *win32MessageBytePipe) Read(b []byte) (int, error) {
+	if f.readEOF {
+		return 0, io.EOF
+	}
+	n, err := f.win32File.Read(b)
+	if err == io.EOF {
+		// If this was the result of a zero-byte read, then
+		// it is possible that the read was due to a zero-size
+		// message. Since we are simulating CloseWrite with a
+		// zero-byte message, ensure that all future Read() calls
+		// also return EOF.
+		f.readEOF = true
+	} else if err == syscall.ERROR_MORE_DATA {
+		// ERROR_MORE_DATA indicates that the pipe's read mode is message mode
+		// and the message still has more bytes. Treat this as a success, since
+		// this package presents all named pipes as byte streams.
+		err = nil
+	}
+	return n, err
+}
+
+func (s pipeAddress) Network() string {
+	return "pipe"
+}
+
+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, access uint32) (syscall.Handle, error) {
+	for {
+
+		select {
+		case <-ctx.Done():
+			return syscall.Handle(0), ctx.Err()
+		default:
+			h, err := createFile(*path, access, 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(10 * time.Millisecond)
+		}
+	}
+}
+
+// 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 2 seconds.  (We do not use WaitNamedPipe.)
+func DialPipe(path string, timeout *time.Duration) (net.Conn, error) {
+	var absTimeout time.Time
+	if timeout != nil {
+		absTimeout = time.Now().Add(*timeout)
+	} else {
+		absTimeout = time.Now().Add(2 * time.Second)
+	}
+	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) {
+	return DialPipeAccess(ctx, path, syscall.GENERIC_READ|syscall.GENERIC_WRITE)
+}
+
+// DialPipeAccess attempts to connect to a named pipe by `path` with `access` until `ctx`
+// cancellation or timeout.
+func DialPipeAccess(ctx context.Context, path string, access uint32) (net.Conn, error) {
+	var err error
+	var h syscall.Handle
+	h, err = tryDialPipe(ctx, &path, access)
+	if err != nil {
+		return nil, err
+	}
+
+	var flags uint32
+	err = getNamedPipeInfo(h, &flags, nil, nil, nil)
+	if err != nil {
+		return nil, err
+	}
+
+	f, err := makeWin32File(h)
+	if err != nil {
+		syscall.Close(h)
+		return nil, err
+	}
+
+	// If the pipe is in message mode, return a message byte pipe, which
+	// supports CloseWrite().
+	if flags&cPIPE_TYPE_MESSAGE != 0 {
+		return &win32MessageBytePipe{
+			win32Pipe: win32Pipe{win32File: f, path: path},
+		}, nil
+	}
+	return &win32Pipe{win32File: f, path: path}, nil
+}
+
+type acceptResponse struct {
+	f   *win32File
+	err error
+}
+
+type win32PipeListener struct {
+	firstHandle syscall.Handle
+	path        string
+	config      PipeConfig
+	acceptCh    chan (chan acceptResponse)
+	closeCh     chan int
+	doneCh      chan int
+}
+
+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, nil, &l.config, false)
+	if err != nil {
+		return nil, err
+	}
+	f, err := makeWin32File(h)
+	if err != nil {
+		syscall.Close(h)
+		return nil, err
+	}
+	return f, nil
+}
+
+func (l *win32PipeListener) makeConnectedServerPipe() (*win32File, error) {
+	p, err := l.makeServerPipe()
+	if err != nil {
+		return nil, err
+	}
+
+	// Wait for the client to connect.
+	ch := make(chan error)
+	go func(p *win32File) {
+		ch <- connectPipe(p)
+	}(p)
+
+	select {
+	case err = <-ch:
+		if err != nil {
+			p.Close()
+			p = nil
+		}
+	case <-l.closeCh:
+		// Abort the connect request by closing the handle.
+		p.Close()
+		p = nil
+		err = <-ch
+		if err == nil || err == ErrFileClosed {
+			err = ErrPipeListenerClosed
+		}
+	}
+	return p, err
+}
+
+func (l *win32PipeListener) listenerRoutine() {
+	closed := false
+	for !closed {
+		select {
+		case <-l.closeCh:
+			closed = true
+		case responseCh := <-l.acceptCh:
+			var (
+				p   *win32File
+				err error
+			)
+			for {
+				p, err = l.makeConnectedServerPipe()
+				// If the connection was immediately closed by the client, try
+				// again.
+				if err != cERROR_NO_DATA {
+					break
+				}
+			}
+			responseCh <- acceptResponse{p, err}
+			closed = err == ErrPipeListenerClosed
+		}
+	}
+	syscall.Close(l.firstHandle)
+	l.firstHandle = 0
+	// Notify Close() and Accept() callers that the handle has been closed.
+	close(l.doneCh)
+}
+
+// PipeConfig contain configuration for the pipe listener.
+type PipeConfig struct {
+	// SecurityDescriptor contains a Windows security descriptor in SDDL format.
+	SecurityDescriptor string
+
+	// MessageMode determines whether the pipe is in byte or message mode. In either
+	// case the pipe is read in byte mode by default. The only practical difference in
+	// this implementation is that CloseWrite() is only supported for message mode pipes;
+	// CloseWrite() is implemented as a zero-byte write, but zero-byte writes are only
+	// transferred to the reader (and returned as io.EOF in this implementation)
+	// when the pipe is in message mode.
+	MessageMode bool
+
+	// InputBufferSize specifies the size the input buffer, in bytes.
+	InputBufferSize int32
+
+	// OutputBufferSize specifies the size the input buffer, in bytes.
+	OutputBufferSize int32
+}
+
+// ListenPipe creates a listener on a Windows named pipe path, e.g. \\.\pipe\mypipe.
+// The pipe must not already exist.
+func ListenPipe(path string, c *PipeConfig) (net.Listener, error) {
+	var (
+		sd  []byte
+		err error
+	)
+	if c == nil {
+		c = &PipeConfig{}
+	}
+	if c.SecurityDescriptor != "" {
+		sd, err = SddlToSecurityDescriptor(c.SecurityDescriptor)
+		if err != nil {
+			return nil, err
+		}
+	}
+	h, err := makeServerPipeHandle(path, sd, c, true)
+	if err != nil {
+		return nil, err
+	}
+	l := &win32PipeListener{
+		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
+}
+
+func connectPipe(p *win32File) error {
+	c, err := p.prepareIo()
+	if err != nil {
+		return err
+	}
+	defer p.wg.Done()
+
+	err = connectNamedPipe(p.handle, &c.o)
+	_, err = p.asyncIo(c, nil, 0, err)
+	if err != nil && err != cERROR_PIPE_CONNECTED {
+		return err
+	}
+	return nil
+}
+
+func (l *win32PipeListener) Accept() (net.Conn, error) {
+	ch := make(chan acceptResponse)
+	select {
+	case l.acceptCh <- ch:
+		response := <-ch
+		err := response.err
+		if err != nil {
+			return nil, err
+		}
+		if l.config.MessageMode {
+			return &win32MessageBytePipe{
+				win32Pipe: win32Pipe{win32File: response.f, path: l.path},
+			}, nil
+		}
+		return &win32Pipe{win32File: response.f, path: l.path}, nil
+	case <-l.doneCh:
+		return nil, ErrPipeListenerClosed
+	}
+}
+
+func (l *win32PipeListener) Close() error {
+	select {
+	case l.closeCh <- 1:
+		<-l.doneCh
+	case <-l.doneCh:
+	}
+	return nil
+}
+
+func (l *win32PipeListener) Addr() net.Addr {
+	return pipeAddress(l.path)
+}
diff --git a/vendor/github.com/Microsoft/go-winio/pkg/guid/guid.go b/vendor/github.com/Microsoft/go-winio/pkg/guid/guid.go
new file mode 100644
index 000000000..586406577
--- /dev/null
+++ b/vendor/github.com/Microsoft/go-winio/pkg/guid/guid.go
@@ -0,0 +1,235 @@
+// Package guid provides a GUID type. The backing structure for a GUID is
+// identical to that used by the golang.org/x/sys/windows GUID type.
+// There are two main binary encodings used for a GUID, the big-endian encoding,
+// and the Windows (mixed-endian) encoding. See here for details:
+// https://en.wikipedia.org/wiki/Universally_unique_identifier#Encoding
+package guid
+
+import (
+	"crypto/rand"
+	"crypto/sha1"
+	"encoding"
+	"encoding/binary"
+	"fmt"
+	"strconv"
+
+	"golang.org/x/sys/windows"
+)
+
+// Variant specifies which GUID variant (or "type") of the GUID. It determines
+// how the entirety of the rest of the GUID is interpreted.
+type Variant uint8
+
+// The variants specified by RFC 4122.
+const (
+	// VariantUnknown specifies a GUID variant which does not conform to one of
+	// the variant encodings specified in RFC 4122.
+	VariantUnknown Variant = iota
+	VariantNCS
+	VariantRFC4122
+	VariantMicrosoft
+	VariantFuture
+)
+
+// Version specifies how the bits in the GUID were generated. For instance, a
+// version 4 GUID is randomly generated, and a version 5 is generated from the
+// hash of an input string.
+type Version uint8
+
+var _ = (encoding.TextMarshaler)(GUID{})
+var _ = (encoding.TextUnmarshaler)(&GUID{})
+
+// GUID represents a GUID/UUID. It has the same structure as
+// golang.org/x/sys/windows.GUID so that it can be used with functions expecting
+// that type. It is defined as its own type so that stringification and
+// marshaling can be supported. The representation matches that used by native
+// Windows code.
+type GUID windows.GUID
+
+// NewV4 returns a new version 4 (pseudorandom) GUID, as defined by RFC 4122.
+func NewV4() (GUID, error) {
+	var b [16]byte
+	if _, err := rand.Read(b[:]); err != nil {
+		return GUID{}, err
+	}
+
+	g := FromArray(b)
+	g.setVersion(4) // Version 4 means randomly generated.
+	g.setVariant(VariantRFC4122)
+
+	return g, nil
+}
+
+// NewV5 returns a new version 5 (generated from a string via SHA-1 hashing)
+// GUID, as defined by RFC 4122. The RFC is unclear on the encoding of the name,
+// and the sample code treats it as a series of bytes, so we do the same here.
+//
+// Some implementations, such as those found on Windows, treat the name as a
+// big-endian UTF16 stream of bytes. If that is desired, the string can be
+// encoded as such before being passed to this function.
+func NewV5(namespace GUID, name []byte) (GUID, error) {
+	b := sha1.New()
+	namespaceBytes := namespace.ToArray()
+	b.Write(namespaceBytes[:])
+	b.Write(name)
+
+	a := [16]byte{}
+	copy(a[:], b.Sum(nil))
+
+	g := FromArray(a)
+	g.setVersion(5) // Version 5 means generated from a string.
+	g.setVariant(VariantRFC4122)
+
+	return g, nil
+}
+
+func fromArray(b [16]byte, order binary.ByteOrder) GUID {
+	var g GUID
+	g.Data1 = order.Uint32(b[0:4])
+	g.Data2 = order.Uint16(b[4:6])
+	g.Data3 = order.Uint16(b[6:8])
+	copy(g.Data4[:], b[8:16])
+	return g
+}
+
+func (g GUID) toArray(order binary.ByteOrder) [16]byte {
+	b := [16]byte{}
+	order.PutUint32(b[0:4], g.Data1)
+	order.PutUint16(b[4:6], g.Data2)
+	order.PutUint16(b[6:8], g.Data3)
+	copy(b[8:16], g.Data4[:])
+	return b
+}
+
+// FromArray constructs a GUID from a big-endian encoding array of 16 bytes.
+func FromArray(b [16]byte) GUID {
+	return fromArray(b, binary.BigEndian)
+}
+
+// ToArray returns an array of 16 bytes representing the GUID in big-endian
+// encoding.
+func (g GUID) ToArray() [16]byte {
+	return g.toArray(binary.BigEndian)
+}
+
+// FromWindowsArray constructs a GUID from a Windows encoding array of bytes.
+func FromWindowsArray(b [16]byte) GUID {
+	return fromArray(b, binary.LittleEndian)
+}
+
+// ToWindowsArray returns an array of 16 bytes representing the GUID in Windows
+// encoding.
+func (g GUID) ToWindowsArray() [16]byte {
+	return g.toArray(binary.LittleEndian)
+}
+
+func (g GUID) String() string {
+	return fmt.Sprintf(
+		"%08x-%04x-%04x-%04x-%012x",
+		g.Data1,
+		g.Data2,
+		g.Data3,
+		g.Data4[:2],
+		g.Data4[2:])
+}
+
+// FromString parses a string containing a GUID and returns the GUID. The only
+// format currently supported is the `xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx`
+// format.
+func FromString(s string) (GUID, error) {
+	if len(s) != 36 {
+		return GUID{}, fmt.Errorf("invalid GUID %q", s)
+	}
+	if s[8] != '-' || s[13] != '-' || s[18] != '-' || s[23] != '-' {
+		return GUID{}, fmt.Errorf("invalid GUID %q", s)
+	}
+
+	var g GUID
+
+	data1, err := strconv.ParseUint(s[0:8], 16, 32)
+	if err != nil {
+		return GUID{}, fmt.Errorf("invalid GUID %q", s)
+	}
+	g.Data1 = uint32(data1)
+
+	data2, err := strconv.ParseUint(s[9:13], 16, 16)
+	if err != nil {
+		return GUID{}, fmt.Errorf("invalid GUID %q", s)
+	}
+	g.Data2 = uint16(data2)
+
+	data3, err := strconv.ParseUint(s[14:18], 16, 16)
+	if err != nil {
+		return GUID{}, fmt.Errorf("invalid GUID %q", s)
+	}
+	g.Data3 = uint16(data3)
+
+	for i, x := range []int{19, 21, 24, 26, 28, 30, 32, 34} {
+		v, err := strconv.ParseUint(s[x:x+2], 16, 8)
+		if err != nil {
+			return GUID{}, fmt.Errorf("invalid GUID %q", s)
+		}
+		g.Data4[i] = uint8(v)
+	}
+
+	return g, nil
+}
+
+func (g *GUID) setVariant(v Variant) {
+	d := g.Data4[0]
+	switch v {
+	case VariantNCS:
+		d = (d & 0x7f)
+	case VariantRFC4122:
+		d = (d & 0x3f) | 0x80
+	case VariantMicrosoft:
+		d = (d & 0x1f) | 0xc0
+	case VariantFuture:
+		d = (d & 0x0f) | 0xe0
+	case VariantUnknown:
+		fallthrough
+	default:
+		panic(fmt.Sprintf("invalid variant: %d", v))
+	}
+	g.Data4[0] = d
+}
+
+// Variant returns the GUID variant, as defined in RFC 4122.
+func (g GUID) Variant() Variant {
+	b := g.Data4[0]
+	if b&0x80 == 0 {
+		return VariantNCS
+	} else if b&0xc0 == 0x80 {
+		return VariantRFC4122
+	} else if b&0xe0 == 0xc0 {
+		return VariantMicrosoft
+	} else if b&0xe0 == 0xe0 {
+		return VariantFuture
+	}
+	return VariantUnknown
+}
+
+func (g *GUID) setVersion(v Version) {
+	g.Data3 = (g.Data3 & 0x0fff) | (uint16(v) << 12)
+}
+
+// Version returns the GUID version, as defined in RFC 4122.
+func (g GUID) Version() Version {
+	return Version((g.Data3 & 0xF000) >> 12)
+}
+
+// MarshalText returns the textual representation of the GUID.
+func (g GUID) MarshalText() ([]byte, error) {
+	return []byte(g.String()), nil
+}
+
+// UnmarshalText takes the textual representation of a GUID, and unmarhals it
+// into this GUID.
+func (g *GUID) UnmarshalText(text []byte) error {
+	g2, err := FromString(string(text))
+	if err != nil {
+		return err
+	}
+	*g = g2
+	return nil
+}
diff --git a/vendor/github.com/Microsoft/go-winio/privilege.go b/vendor/github.com/Microsoft/go-winio/privilege.go
new file mode 100644
index 000000000..9c83d36fe
--- /dev/null
+++ b/vendor/github.com/Microsoft/go-winio/privilege.go
@@ -0,0 +1,202 @@
+// +build windows
+
+package winio
+
+import (
+	"bytes"
+	"encoding/binary"
+	"fmt"
+	"runtime"
+	"sync"
+	"syscall"
+	"unicode/utf16"
+
+	"golang.org/x/sys/windows"
+)
+
+//sys adjustTokenPrivileges(token windows.Token, releaseAll bool, input *byte, outputSize uint32, output *byte, requiredSize *uint32) (success bool, err error) [true] = advapi32.AdjustTokenPrivileges
+//sys impersonateSelf(level uint32) (err error) = advapi32.ImpersonateSelf
+//sys revertToSelf() (err error) = advapi32.RevertToSelf
+//sys openThreadToken(thread syscall.Handle, accessMask uint32, openAsSelf bool, token *windows.Token) (err error) = advapi32.OpenThreadToken
+//sys getCurrentThread() (h syscall.Handle) = GetCurrentThread
+//sys lookupPrivilegeValue(systemName string, name string, luid *uint64) (err error) = advapi32.LookupPrivilegeValueW
+//sys lookupPrivilegeName(systemName string, luid *uint64, buffer *uint16, size *uint32) (err error) = advapi32.LookupPrivilegeNameW
+//sys lookupPrivilegeDisplayName(systemName string, name *uint16, buffer *uint16, size *uint32, languageId *uint32) (err error) = advapi32.LookupPrivilegeDisplayNameW
+
+const (
+	SE_PRIVILEGE_ENABLED = 2
+
+	ERROR_NOT_ALL_ASSIGNED syscall.Errno = 1300
+
+	SeBackupPrivilege  = "SeBackupPrivilege"
+	SeRestorePrivilege = "SeRestorePrivilege"
+)
+
+const (
+	securityAnonymous = iota
+	securityIdentification
+	securityImpersonation
+	securityDelegation
+)
+
+var (
+	privNames     = make(map[string]uint64)
+	privNameMutex sync.Mutex
+)
+
+// PrivilegeError represents an error enabling privileges.
+type PrivilegeError struct {
+	privileges []uint64
+}
+
+func (e *PrivilegeError) Error() string {
+	s := ""
+	if len(e.privileges) > 1 {
+		s = "Could not enable privileges "
+	} else {
+		s = "Could not enable privilege "
+	}
+	for i, p := range e.privileges {
+		if i != 0 {
+			s += ", "
+		}
+		s += `"`
+		s += getPrivilegeName(p)
+		s += `"`
+	}
+	return s
+}
+
+// RunWithPrivilege enables a single privilege for a function call.
+func RunWithPrivilege(name string, fn func() error) error {
+	return RunWithPrivileges([]string{name}, fn)
+}
+
+// RunWithPrivileges enables privileges for a function call.
+func RunWithPrivileges(names []string, fn func() error) error {
+	privileges, err := mapPrivileges(names)
+	if err != nil {
+		return err
+	}
+	runtime.LockOSThread()
+	defer runtime.UnlockOSThread()
+	token, err := newThreadToken()
+	if err != nil {
+		return err
+	}
+	defer releaseThreadToken(token)
+	err = adjustPrivileges(token, privileges, SE_PRIVILEGE_ENABLED)
+	if err != nil {
+		return err
+	}
+	return fn()
+}
+
+func mapPrivileges(names []string) ([]uint64, error) {
+	var privileges []uint64
+	privNameMutex.Lock()
+	defer privNameMutex.Unlock()
+	for _, name := range names {
+		p, ok := privNames[name]
+		if !ok {
+			err := lookupPrivilegeValue("", name, &p)
+			if err != nil {
+				return nil, err
+			}
+			privNames[name] = p
+		}
+		privileges = append(privileges, p)
+	}
+	return privileges, nil
+}
+
+// EnableProcessPrivileges enables privileges globally for the process.
+func EnableProcessPrivileges(names []string) error {
+	return enableDisableProcessPrivilege(names, SE_PRIVILEGE_ENABLED)
+}
+
+// DisableProcessPrivileges disables privileges globally for the process.
+func DisableProcessPrivileges(names []string) error {
+	return enableDisableProcessPrivilege(names, 0)
+}
+
+func enableDisableProcessPrivilege(names []string, action uint32) error {
+	privileges, err := mapPrivileges(names)
+	if err != nil {
+		return err
+	}
+
+	p, _ := windows.GetCurrentProcess()
+	var token windows.Token
+	err = windows.OpenProcessToken(p, windows.TOKEN_ADJUST_PRIVILEGES|windows.TOKEN_QUERY, &token)
+	if err != nil {
+		return err
+	}
+
+	defer token.Close()
+	return adjustPrivileges(token, privileges, action)
+}
+
+func adjustPrivileges(token windows.Token, privileges []uint64, action uint32) error {
+	var b bytes.Buffer
+	binary.Write(&b, binary.LittleEndian, uint32(len(privileges)))
+	for _, p := range privileges {
+		binary.Write(&b, binary.LittleEndian, p)
+		binary.Write(&b, binary.LittleEndian, action)
+	}
+	prevState := make([]byte, b.Len())
+	reqSize := uint32(0)
+	success, err := adjustTokenPrivileges(token, false, &b.Bytes()[0], uint32(len(prevState)), &prevState[0], &reqSize)
+	if !success {
+		return err
+	}
+	if err == ERROR_NOT_ALL_ASSIGNED {
+		return &PrivilegeError{privileges}
+	}
+	return nil
+}
+
+func getPrivilegeName(luid uint64) string {
+	var nameBuffer [256]uint16
+	bufSize := uint32(len(nameBuffer))
+	err := lookupPrivilegeName("", &luid, &nameBuffer[0], &bufSize)
+	if err != nil {
+		return fmt.Sprintf("<unknown privilege %d>", luid)
+	}
+
+	var displayNameBuffer [256]uint16
+	displayBufSize := uint32(len(displayNameBuffer))
+	var langID uint32
+	err = lookupPrivilegeDisplayName("", &nameBuffer[0], &displayNameBuffer[0], &displayBufSize, &langID)
+	if err != nil {
+		return fmt.Sprintf("<unknown privilege %s>", string(utf16.Decode(nameBuffer[:bufSize])))
+	}
+
+	return string(utf16.Decode(displayNameBuffer[:displayBufSize]))
+}
+
+func newThreadToken() (windows.Token, error) {
+	err := impersonateSelf(securityImpersonation)
+	if err != nil {
+		return 0, err
+	}
+
+	var token windows.Token
+	err = openThreadToken(getCurrentThread(), syscall.TOKEN_ADJUST_PRIVILEGES|syscall.TOKEN_QUERY, false, &token)
+	if err != nil {
+		rerr := revertToSelf()
+		if rerr != nil {
+			panic(rerr)
+		}
+		return 0, err
+	}
+	return token, nil
+}
+
+func releaseThreadToken(h windows.Token) {
+	err := revertToSelf()
+	if err != nil {
+		panic(err)
+	}
+	h.Close()
+}
diff --git a/vendor/github.com/Microsoft/go-winio/reparse.go b/vendor/github.com/Microsoft/go-winio/reparse.go
new file mode 100644
index 000000000..fc1ee4d3a
--- /dev/null
+++ b/vendor/github.com/Microsoft/go-winio/reparse.go
@@ -0,0 +1,128 @@
+package winio
+
+import (
+	"bytes"
+	"encoding/binary"
+	"fmt"
+	"strings"
+	"unicode/utf16"
+	"unsafe"
+)
+
+const (
+	reparseTagMountPoint = 0xA0000003
+	reparseTagSymlink    = 0xA000000C
+)
+
+type reparseDataBuffer struct {
+	ReparseTag           uint32
+	ReparseDataLength    uint16
+	Reserved             uint16
+	SubstituteNameOffset uint16
+	SubstituteNameLength uint16
+	PrintNameOffset      uint16
+	PrintNameLength      uint16
+}
+
+// ReparsePoint describes a Win32 symlink or mount point.
+type ReparsePoint struct {
+	Target       string
+	IsMountPoint bool
+}
+
+// UnsupportedReparsePointError is returned when trying to decode a non-symlink or
+// mount point reparse point.
+type UnsupportedReparsePointError struct {
+	Tag uint32
+}
+
+func (e *UnsupportedReparsePointError) Error() string {
+	return fmt.Sprintf("unsupported reparse point %x", e.Tag)
+}
+
+// DecodeReparsePoint decodes a Win32 REPARSE_DATA_BUFFER structure containing either a symlink
+// or a mount point.
+func DecodeReparsePoint(b []byte) (*ReparsePoint, error) {
+	tag := binary.LittleEndian.Uint32(b[0:4])
+	return DecodeReparsePointData(tag, b[8:])
+}
+
+func DecodeReparsePointData(tag uint32, b []byte) (*ReparsePoint, error) {
+	isMountPoint := false
+	switch tag {
+	case reparseTagMountPoint:
+		isMountPoint = true
+	case reparseTagSymlink:
+	default:
+		return nil, &UnsupportedReparsePointError{tag}
+	}
+	nameOffset := 8 + binary.LittleEndian.Uint16(b[4:6])
+	if !isMountPoint {
+		nameOffset += 4
+	}
+	nameLength := binary.LittleEndian.Uint16(b[6:8])
+	name := make([]uint16, nameLength/2)
+	err := binary.Read(bytes.NewReader(b[nameOffset:nameOffset+nameLength]), binary.LittleEndian, &name)
+	if err != nil {
+		return nil, err
+	}
+	return &ReparsePoint{string(utf16.Decode(name)), isMountPoint}, nil
+}
+
+func isDriveLetter(c byte) bool {
+	return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')
+}
+
+// EncodeReparsePoint encodes a Win32 REPARSE_DATA_BUFFER structure describing a symlink or
+// mount point.
+func EncodeReparsePoint(rp *ReparsePoint) []byte {
+	// Generate an NT path and determine if this is a relative path.
+	var ntTarget string
+	relative := false
+	if strings.HasPrefix(rp.Target, `\\?\`) {
+		ntTarget = `\??\` + rp.Target[4:]
+	} else if strings.HasPrefix(rp.Target, `\\`) {
+		ntTarget = `\??\UNC\` + rp.Target[2:]
+	} else if len(rp.Target) >= 2 && isDriveLetter(rp.Target[0]) && rp.Target[1] == ':' {
+		ntTarget = `\??\` + rp.Target
+	} else {
+		ntTarget = rp.Target
+		relative = true
+	}
+
+	// The paths must be NUL-terminated even though they are counted strings.
+	target16 := utf16.Encode([]rune(rp.Target + "\x00"))
+	ntTarget16 := utf16.Encode([]rune(ntTarget + "\x00"))
+
+	size := int(unsafe.Sizeof(reparseDataBuffer{})) - 8
+	size += len(ntTarget16)*2 + len(target16)*2
+
+	tag := uint32(reparseTagMountPoint)
+	if !rp.IsMountPoint {
+		tag = reparseTagSymlink
+		size += 4 // Add room for symlink flags
+	}
+
+	data := reparseDataBuffer{
+		ReparseTag:           tag,
+		ReparseDataLength:    uint16(size),
+		SubstituteNameOffset: 0,
+		SubstituteNameLength: uint16((len(ntTarget16) - 1) * 2),
+		PrintNameOffset:      uint16(len(ntTarget16) * 2),
+		PrintNameLength:      uint16((len(target16) - 1) * 2),
+	}
+
+	var b bytes.Buffer
+	binary.Write(&b, binary.LittleEndian, &data)
+	if !rp.IsMountPoint {
+		flags := uint32(0)
+		if relative {
+			flags |= 1
+		}
+		binary.Write(&b, binary.LittleEndian, flags)
+	}
+
+	binary.Write(&b, binary.LittleEndian, ntTarget16)
+	binary.Write(&b, binary.LittleEndian, target16)
+	return b.Bytes()
+}
diff --git a/vendor/github.com/Microsoft/go-winio/sd.go b/vendor/github.com/Microsoft/go-winio/sd.go
new file mode 100644
index 000000000..db1b370a1
--- /dev/null
+++ b/vendor/github.com/Microsoft/go-winio/sd.go
@@ -0,0 +1,98 @@
+// +build windows
+
+package winio
+
+import (
+	"syscall"
+	"unsafe"
+)
+
+//sys lookupAccountName(systemName *uint16, accountName string, sid *byte, sidSize *uint32, refDomain *uint16, refDomainSize *uint32, sidNameUse *uint32) (err error) = advapi32.LookupAccountNameW
+//sys convertSidToStringSid(sid *byte, str **uint16) (err error) = advapi32.ConvertSidToStringSidW
+//sys convertStringSecurityDescriptorToSecurityDescriptor(str string, revision uint32, sd *uintptr, size *uint32) (err error) = advapi32.ConvertStringSecurityDescriptorToSecurityDescriptorW
+//sys convertSecurityDescriptorToStringSecurityDescriptor(sd *byte, revision uint32, secInfo uint32, sddl **uint16, sddlSize *uint32) (err error) = advapi32.ConvertSecurityDescriptorToStringSecurityDescriptorW
+//sys localFree(mem uintptr) = LocalFree
+//sys getSecurityDescriptorLength(sd uintptr) (len uint32) = advapi32.GetSecurityDescriptorLength
+
+const (
+	cERROR_NONE_MAPPED = syscall.Errno(1332)
+)
+
+type AccountLookupError struct {
+	Name string
+	Err  error
+}
+
+func (e *AccountLookupError) Error() string {
+	if e.Name == "" {
+		return "lookup account: empty account name specified"
+	}
+	var s string
+	switch e.Err {
+	case cERROR_NONE_MAPPED:
+		s = "not found"
+	default:
+		s = e.Err.Error()
+	}
+	return "lookup account " + e.Name + ": " + s
+}
+
+type SddlConversionError struct {
+	Sddl string
+	Err  error
+}
+
+func (e *SddlConversionError) Error() string {
+	return "convert " + e.Sddl + ": " + e.Err.Error()
+}
+
+// LookupSidByName looks up the SID of an account by name
+func LookupSidByName(name string) (sid string, err error) {
+	if name == "" {
+		return "", &AccountLookupError{name, cERROR_NONE_MAPPED}
+	}
+
+	var sidSize, sidNameUse, refDomainSize uint32
+	err = lookupAccountName(nil, name, nil, &sidSize, nil, &refDomainSize, &sidNameUse)
+	if err != nil && err != syscall.ERROR_INSUFFICIENT_BUFFER {
+		return "", &AccountLookupError{name, err}
+	}
+	sidBuffer := make([]byte, sidSize)
+	refDomainBuffer := make([]uint16, refDomainSize)
+	err = lookupAccountName(nil, name, &sidBuffer[0], &sidSize, &refDomainBuffer[0], &refDomainSize, &sidNameUse)
+	if err != nil {
+		return "", &AccountLookupError{name, err}
+	}
+	var strBuffer *uint16
+	err = convertSidToStringSid(&sidBuffer[0], &strBuffer)
+	if err != nil {
+		return "", &AccountLookupError{name, err}
+	}
+	sid = syscall.UTF16ToString((*[0xffff]uint16)(unsafe.Pointer(strBuffer))[:])
+	localFree(uintptr(unsafe.Pointer(strBuffer)))
+	return sid, nil
+}
+
+func SddlToSecurityDescriptor(sddl string) ([]byte, error) {
+	var sdBuffer uintptr
+	err := convertStringSecurityDescriptorToSecurityDescriptor(sddl, 1, &sdBuffer, nil)
+	if err != nil {
+		return nil, &SddlConversionError{sddl, err}
+	}
+	defer localFree(sdBuffer)
+	sd := make([]byte, getSecurityDescriptorLength(sdBuffer))
+	copy(sd, (*[0xffff]byte)(unsafe.Pointer(sdBuffer))[:len(sd)])
+	return sd, nil
+}
+
+func SecurityDescriptorToSddl(sd []byte) (string, error) {
+	var sddl *uint16
+	// The returned string length seems to including an aribtrary number of terminating NULs.
+	// Don't use it.
+	err := convertSecurityDescriptorToStringSecurityDescriptor(&sd[0], 1, 0xff, &sddl, nil)
+	if err != nil {
+		return "", err
+	}
+	defer localFree(uintptr(unsafe.Pointer(sddl)))
+	return syscall.UTF16ToString((*[0xffff]uint16)(unsafe.Pointer(sddl))[:]), nil
+}
diff --git a/vendor/github.com/Microsoft/go-winio/syscall.go b/vendor/github.com/Microsoft/go-winio/syscall.go
new file mode 100644
index 000000000..5cb52bc74
--- /dev/null
+++ b/vendor/github.com/Microsoft/go-winio/syscall.go
@@ -0,0 +1,3 @@
+package winio
+
+//go:generate go run $GOROOT/src/syscall/mksyscall_windows.go -output zsyscall_windows.go file.go pipe.go sd.go fileinfo.go privilege.go backup.go hvsock.go
diff --git a/vendor/github.com/Microsoft/go-winio/zsyscall_windows.go b/vendor/github.com/Microsoft/go-winio/zsyscall_windows.go
new file mode 100644
index 000000000..e26b01faf
--- /dev/null
+++ b/vendor/github.com/Microsoft/go-winio/zsyscall_windows.go
@@ -0,0 +1,562 @@
+// Code generated by 'go generate'; DO NOT EDIT.
+
+package winio
+
+import (
+	"syscall"
+	"unsafe"
+
+	"golang.org/x/sys/windows"
+)
+
+var _ unsafe.Pointer
+
+// Do the interface allocations only once for common
+// Errno values.
+const (
+	errnoERROR_IO_PENDING = 997
+)
+
+var (
+	errERROR_IO_PENDING error = syscall.Errno(errnoERROR_IO_PENDING)
+)
+
+// errnoErr returns common boxed Errno values, to prevent
+// allocations at runtime.
+func errnoErr(e syscall.Errno) error {
+	switch e {
+	case 0:
+		return nil
+	case errnoERROR_IO_PENDING:
+		return errERROR_IO_PENDING
+	}
+	// TODO: add more here, after collecting data on the common
+	// error values see on Windows. (perhaps when running
+	// all.bat?)
+	return e
+}
+
+var (
+	modkernel32 = windows.NewLazySystemDLL("kernel32.dll")
+	modws2_32   = windows.NewLazySystemDLL("ws2_32.dll")
+	modntdll    = windows.NewLazySystemDLL("ntdll.dll")
+	modadvapi32 = windows.NewLazySystemDLL("advapi32.dll")
+
+	procCancelIoEx                                           = modkernel32.NewProc("CancelIoEx")
+	procCreateIoCompletionPort                               = modkernel32.NewProc("CreateIoCompletionPort")
+	procGetQueuedCompletionStatus                            = modkernel32.NewProc("GetQueuedCompletionStatus")
+	procSetFileCompletionNotificationModes                   = modkernel32.NewProc("SetFileCompletionNotificationModes")
+	procWSAGetOverlappedResult                               = modws2_32.NewProc("WSAGetOverlappedResult")
+	procConnectNamedPipe                                     = modkernel32.NewProc("ConnectNamedPipe")
+	procCreateNamedPipeW                                     = modkernel32.NewProc("CreateNamedPipeW")
+	procCreateFileW                                          = modkernel32.NewProc("CreateFileW")
+	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")
+	procConvertSecurityDescriptorToStringSecurityDescriptorW = modadvapi32.NewProc("ConvertSecurityDescriptorToStringSecurityDescriptorW")
+	procLocalFree                                            = modkernel32.NewProc("LocalFree")
+	procGetSecurityDescriptorLength                          = modadvapi32.NewProc("GetSecurityDescriptorLength")
+	procGetFileInformationByHandleEx                         = modkernel32.NewProc("GetFileInformationByHandleEx")
+	procSetFileInformationByHandle                           = modkernel32.NewProc("SetFileInformationByHandle")
+	procAdjustTokenPrivileges                                = modadvapi32.NewProc("AdjustTokenPrivileges")
+	procImpersonateSelf                                      = modadvapi32.NewProc("ImpersonateSelf")
+	procRevertToSelf                                         = modadvapi32.NewProc("RevertToSelf")
+	procOpenThreadToken                                      = modadvapi32.NewProc("OpenThreadToken")
+	procGetCurrentThread                                     = modkernel32.NewProc("GetCurrentThread")
+	procLookupPrivilegeValueW                                = modadvapi32.NewProc("LookupPrivilegeValueW")
+	procLookupPrivilegeNameW                                 = modadvapi32.NewProc("LookupPrivilegeNameW")
+	procLookupPrivilegeDisplayNameW                          = modadvapi32.NewProc("LookupPrivilegeDisplayNameW")
+	procBackupRead                                           = modkernel32.NewProc("BackupRead")
+	procBackupWrite                                          = modkernel32.NewProc("BackupWrite")
+	procbind                                                 = modws2_32.NewProc("bind")
+)
+
+func cancelIoEx(file syscall.Handle, o *syscall.Overlapped) (err error) {
+	r1, _, e1 := syscall.Syscall(procCancelIoEx.Addr(), 2, uintptr(file), uintptr(unsafe.Pointer(o)), 0)
+	if r1 == 0 {
+		if e1 != 0 {
+			err = errnoErr(e1)
+		} else {
+			err = syscall.EINVAL
+		}
+	}
+	return
+}
+
+func createIoCompletionPort(file syscall.Handle, port syscall.Handle, key uintptr, threadCount uint32) (newport syscall.Handle, err error) {
+	r0, _, e1 := syscall.Syscall6(procCreateIoCompletionPort.Addr(), 4, uintptr(file), uintptr(port), uintptr(key), uintptr(threadCount), 0, 0)
+	newport = syscall.Handle(r0)
+	if newport == 0 {
+		if e1 != 0 {
+			err = errnoErr(e1)
+		} else {
+			err = syscall.EINVAL
+		}
+	}
+	return
+}
+
+func getQueuedCompletionStatus(port syscall.Handle, bytes *uint32, key *uintptr, o **ioOperation, timeout uint32) (err error) {
+	r1, _, e1 := syscall.Syscall6(procGetQueuedCompletionStatus.Addr(), 5, uintptr(port), uintptr(unsafe.Pointer(bytes)), uintptr(unsafe.Pointer(key)), uintptr(unsafe.Pointer(o)), uintptr(timeout), 0)
+	if r1 == 0 {
+		if e1 != 0 {
+			err = errnoErr(e1)
+		} else {
+			err = syscall.EINVAL
+		}
+	}
+	return
+}
+
+func setFileCompletionNotificationModes(h syscall.Handle, flags uint8) (err error) {
+	r1, _, e1 := syscall.Syscall(procSetFileCompletionNotificationModes.Addr(), 2, uintptr(h), uintptr(flags), 0)
+	if r1 == 0 {
+		if e1 != 0 {
+			err = errnoErr(e1)
+		} else {
+			err = syscall.EINVAL
+		}
+	}
+	return
+}
+
+func wsaGetOverlappedResult(h syscall.Handle, o *syscall.Overlapped, bytes *uint32, wait bool, flags *uint32) (err error) {
+	var _p0 uint32
+	if wait {
+		_p0 = 1
+	} else {
+		_p0 = 0
+	}
+	r1, _, e1 := syscall.Syscall6(procWSAGetOverlappedResult.Addr(), 5, uintptr(h), uintptr(unsafe.Pointer(o)), uintptr(unsafe.Pointer(bytes)), uintptr(_p0), uintptr(unsafe.Pointer(flags)), 0)
+	if r1 == 0 {
+		if e1 != 0 {
+			err = errnoErr(e1)
+		} else {
+			err = syscall.EINVAL
+		}
+	}
+	return
+}
+
+func connectNamedPipe(pipe syscall.Handle, o *syscall.Overlapped) (err error) {
+	r1, _, e1 := syscall.Syscall(procConnectNamedPipe.Addr(), 2, uintptr(pipe), uintptr(unsafe.Pointer(o)), 0)
+	if r1 == 0 {
+		if e1 != 0 {
+			err = errnoErr(e1)
+		} else {
+			err = syscall.EINVAL
+		}
+	}
+	return
+}
+
+func createNamedPipe(name string, flags uint32, pipeMode uint32, maxInstances uint32, outSize uint32, inSize uint32, defaultTimeout uint32, sa *syscall.SecurityAttributes) (handle syscall.Handle, err error) {
+	var _p0 *uint16
+	_p0, err = syscall.UTF16PtrFromString(name)
+	if err != nil {
+		return
+	}
+	return _createNamedPipe(_p0, flags, pipeMode, maxInstances, outSize, inSize, defaultTimeout, sa)
+}
+
+func _createNamedPipe(name *uint16, flags uint32, pipeMode uint32, maxInstances uint32, outSize uint32, inSize uint32, defaultTimeout uint32, sa *syscall.SecurityAttributes) (handle syscall.Handle, err error) {
+	r0, _, e1 := syscall.Syscall9(procCreateNamedPipeW.Addr(), 8, uintptr(unsafe.Pointer(name)), uintptr(flags), uintptr(pipeMode), uintptr(maxInstances), uintptr(outSize), uintptr(inSize), uintptr(defaultTimeout), uintptr(unsafe.Pointer(sa)), 0)
+	handle = syscall.Handle(r0)
+	if handle == syscall.InvalidHandle {
+		if e1 != 0 {
+			err = errnoErr(e1)
+		} else {
+			err = syscall.EINVAL
+		}
+	}
+	return
+}
+
+func createFile(name string, access uint32, mode uint32, sa *syscall.SecurityAttributes, createmode uint32, attrs uint32, templatefile syscall.Handle) (handle syscall.Handle, err error) {
+	var _p0 *uint16
+	_p0, err = syscall.UTF16PtrFromString(name)
+	if err != nil {
+		return
+	}
+	return _createFile(_p0, access, mode, sa, createmode, attrs, templatefile)
+}
+
+func _createFile(name *uint16, access uint32, mode uint32, sa *syscall.SecurityAttributes, createmode uint32, attrs uint32, templatefile syscall.Handle) (handle syscall.Handle, err error) {
+	r0, _, e1 := syscall.Syscall9(procCreateFileW.Addr(), 7, uintptr(unsafe.Pointer(name)), uintptr(access), uintptr(mode), uintptr(unsafe.Pointer(sa)), uintptr(createmode), uintptr(attrs), uintptr(templatefile), 0, 0)
+	handle = syscall.Handle(r0)
+	if handle == syscall.InvalidHandle {
+		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 {
+		if e1 != 0 {
+			err = errnoErr(e1)
+		} else {
+			err = syscall.EINVAL
+		}
+	}
+	return
+}
+
+func getNamedPipeHandleState(pipe syscall.Handle, state *uint32, curInstances *uint32, maxCollectionCount *uint32, collectDataTimeout *uint32, userName *uint16, maxUserNameSize uint32) (err error) {
+	r1, _, e1 := syscall.Syscall9(procGetNamedPipeHandleStateW.Addr(), 7, uintptr(pipe), uintptr(unsafe.Pointer(state)), uintptr(unsafe.Pointer(curInstances)), uintptr(unsafe.Pointer(maxCollectionCount)), uintptr(unsafe.Pointer(collectDataTimeout)), uintptr(unsafe.Pointer(userName)), uintptr(maxUserNameSize), 0, 0)
+	if r1 == 0 {
+		if e1 != 0 {
+			err = errnoErr(e1)
+		} else {
+			err = syscall.EINVAL
+		}
+	}
+	return
+}
+
+func localAlloc(uFlags uint32, length uint32) (ptr uintptr) {
+	r0, _, _ := syscall.Syscall(procLocalAlloc.Addr(), 2, uintptr(uFlags), uintptr(length), 0)
+	ptr = uintptr(r0)
+	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)
+	if err != nil {
+		return
+	}
+	return _lookupAccountName(systemName, _p0, sid, sidSize, refDomain, refDomainSize, sidNameUse)
+}
+
+func _lookupAccountName(systemName *uint16, accountName *uint16, sid *byte, sidSize *uint32, refDomain *uint16, refDomainSize *uint32, sidNameUse *uint32) (err error) {
+	r1, _, e1 := syscall.Syscall9(procLookupAccountNameW.Addr(), 7, uintptr(unsafe.Pointer(systemName)), uintptr(unsafe.Pointer(accountName)), uintptr(unsafe.Pointer(sid)), uintptr(unsafe.Pointer(sidSize)), uintptr(unsafe.Pointer(refDomain)), uintptr(unsafe.Pointer(refDomainSize)), uintptr(unsafe.Pointer(sidNameUse)), 0, 0)
+	if r1 == 0 {
+		if e1 != 0 {
+			err = errnoErr(e1)
+		} else {
+			err = syscall.EINVAL
+		}
+	}
+	return
+}
+
+func convertSidToStringSid(sid *byte, str **uint16) (err error) {
+	r1, _, e1 := syscall.Syscall(procConvertSidToStringSidW.Addr(), 2, uintptr(unsafe.Pointer(sid)), uintptr(unsafe.Pointer(str)), 0)
+	if r1 == 0 {
+		if e1 != 0 {
+			err = errnoErr(e1)
+		} else {
+			err = syscall.EINVAL
+		}
+	}
+	return
+}
+
+func convertStringSecurityDescriptorToSecurityDescriptor(str string, revision uint32, sd *uintptr, size *uint32) (err error) {
+	var _p0 *uint16
+	_p0, err = syscall.UTF16PtrFromString(str)
+	if err != nil {
+		return
+	}
+	return _convertStringSecurityDescriptorToSecurityDescriptor(_p0, revision, sd, size)
+}
+
+func _convertStringSecurityDescriptorToSecurityDescriptor(str *uint16, revision uint32, sd *uintptr, size *uint32) (err error) {
+	r1, _, e1 := syscall.Syscall6(procConvertStringSecurityDescriptorToSecurityDescriptorW.Addr(), 4, uintptr(unsafe.Pointer(str)), uintptr(revision), uintptr(unsafe.Pointer(sd)), uintptr(unsafe.Pointer(size)), 0, 0)
+	if r1 == 0 {
+		if e1 != 0 {
+			err = errnoErr(e1)
+		} else {
+			err = syscall.EINVAL
+		}
+	}
+	return
+}
+
+func convertSecurityDescriptorToStringSecurityDescriptor(sd *byte, revision uint32, secInfo uint32, sddl **uint16, sddlSize *uint32) (err error) {
+	r1, _, e1 := syscall.Syscall6(procConvertSecurityDescriptorToStringSecurityDescriptorW.Addr(), 5, uintptr(unsafe.Pointer(sd)), uintptr(revision), uintptr(secInfo), uintptr(unsafe.Pointer(sddl)), uintptr(unsafe.Pointer(sddlSize)), 0)
+	if r1 == 0 {
+		if e1 != 0 {
+			err = errnoErr(e1)
+		} else {
+			err = syscall.EINVAL
+		}
+	}
+	return
+}
+
+func localFree(mem uintptr) {
+	syscall.Syscall(procLocalFree.Addr(), 1, uintptr(mem), 0, 0)
+	return
+}
+
+func getSecurityDescriptorLength(sd uintptr) (len uint32) {
+	r0, _, _ := syscall.Syscall(procGetSecurityDescriptorLength.Addr(), 1, uintptr(sd), 0, 0)
+	len = uint32(r0)
+	return
+}
+
+func getFileInformationByHandleEx(h syscall.Handle, class uint32, buffer *byte, size uint32) (err error) {
+	r1, _, e1 := syscall.Syscall6(procGetFileInformationByHandleEx.Addr(), 4, uintptr(h), uintptr(class), uintptr(unsafe.Pointer(buffer)), uintptr(size), 0, 0)
+	if r1 == 0 {
+		if e1 != 0 {
+			err = errnoErr(e1)
+		} else {
+			err = syscall.EINVAL
+		}
+	}
+	return
+}
+
+func setFileInformationByHandle(h syscall.Handle, class uint32, buffer *byte, size uint32) (err error) {
+	r1, _, e1 := syscall.Syscall6(procSetFileInformationByHandle.Addr(), 4, uintptr(h), uintptr(class), uintptr(unsafe.Pointer(buffer)), uintptr(size), 0, 0)
+	if r1 == 0 {
+		if e1 != 0 {
+			err = errnoErr(e1)
+		} else {
+			err = syscall.EINVAL
+		}
+	}
+	return
+}
+
+func adjustTokenPrivileges(token windows.Token, releaseAll bool, input *byte, outputSize uint32, output *byte, requiredSize *uint32) (success bool, err error) {
+	var _p0 uint32
+	if releaseAll {
+		_p0 = 1
+	} else {
+		_p0 = 0
+	}
+	r0, _, e1 := syscall.Syscall6(procAdjustTokenPrivileges.Addr(), 6, uintptr(token), uintptr(_p0), uintptr(unsafe.Pointer(input)), uintptr(outputSize), uintptr(unsafe.Pointer(output)), uintptr(unsafe.Pointer(requiredSize)))
+	success = r0 != 0
+	if true {
+		if e1 != 0 {
+			err = errnoErr(e1)
+		} else {
+			err = syscall.EINVAL
+		}
+	}
+	return
+}
+
+func impersonateSelf(level uint32) (err error) {
+	r1, _, e1 := syscall.Syscall(procImpersonateSelf.Addr(), 1, uintptr(level), 0, 0)
+	if r1 == 0 {
+		if e1 != 0 {
+			err = errnoErr(e1)
+		} else {
+			err = syscall.EINVAL
+		}
+	}
+	return
+}
+
+func revertToSelf() (err error) {
+	r1, _, e1 := syscall.Syscall(procRevertToSelf.Addr(), 0, 0, 0, 0)
+	if r1 == 0 {
+		if e1 != 0 {
+			err = errnoErr(e1)
+		} else {
+			err = syscall.EINVAL
+		}
+	}
+	return
+}
+
+func openThreadToken(thread syscall.Handle, accessMask uint32, openAsSelf bool, token *windows.Token) (err error) {
+	var _p0 uint32
+	if openAsSelf {
+		_p0 = 1
+	} else {
+		_p0 = 0
+	}
+	r1, _, e1 := syscall.Syscall6(procOpenThreadToken.Addr(), 4, uintptr(thread), uintptr(accessMask), uintptr(_p0), uintptr(unsafe.Pointer(token)), 0, 0)
+	if r1 == 0 {
+		if e1 != 0 {
+			err = errnoErr(e1)
+		} else {
+			err = syscall.EINVAL
+		}
+	}
+	return
+}
+
+func getCurrentThread() (h syscall.Handle) {
+	r0, _, _ := syscall.Syscall(procGetCurrentThread.Addr(), 0, 0, 0, 0)
+	h = syscall.Handle(r0)
+	return
+}
+
+func lookupPrivilegeValue(systemName string, name string, luid *uint64) (err error) {
+	var _p0 *uint16
+	_p0, err = syscall.UTF16PtrFromString(systemName)
+	if err != nil {
+		return
+	}
+	var _p1 *uint16
+	_p1, err = syscall.UTF16PtrFromString(name)
+	if err != nil {
+		return
+	}
+	return _lookupPrivilegeValue(_p0, _p1, luid)
+}
+
+func _lookupPrivilegeValue(systemName *uint16, name *uint16, luid *uint64) (err error) {
+	r1, _, e1 := syscall.Syscall(procLookupPrivilegeValueW.Addr(), 3, uintptr(unsafe.Pointer(systemName)), uintptr(unsafe.Pointer(name)), uintptr(unsafe.Pointer(luid)))
+	if r1 == 0 {
+		if e1 != 0 {
+			err = errnoErr(e1)
+		} else {
+			err = syscall.EINVAL
+		}
+	}
+	return
+}
+
+func lookupPrivilegeName(systemName string, luid *uint64, buffer *uint16, size *uint32) (err error) {
+	var _p0 *uint16
+	_p0, err = syscall.UTF16PtrFromString(systemName)
+	if err != nil {
+		return
+	}
+	return _lookupPrivilegeName(_p0, luid, buffer, size)
+}
+
+func _lookupPrivilegeName(systemName *uint16, luid *uint64, buffer *uint16, size *uint32) (err error) {
+	r1, _, e1 := syscall.Syscall6(procLookupPrivilegeNameW.Addr(), 4, uintptr(unsafe.Pointer(systemName)), uintptr(unsafe.Pointer(luid)), uintptr(unsafe.Pointer(buffer)), uintptr(unsafe.Pointer(size)), 0, 0)
+	if r1 == 0 {
+		if e1 != 0 {
+			err = errnoErr(e1)
+		} else {
+			err = syscall.EINVAL
+		}
+	}
+	return
+}
+
+func lookupPrivilegeDisplayName(systemName string, name *uint16, buffer *uint16, size *uint32, languageId *uint32) (err error) {
+	var _p0 *uint16
+	_p0, err = syscall.UTF16PtrFromString(systemName)
+	if err != nil {
+		return
+	}
+	return _lookupPrivilegeDisplayName(_p0, name, buffer, size, languageId)
+}
+
+func _lookupPrivilegeDisplayName(systemName *uint16, name *uint16, buffer *uint16, size *uint32, languageId *uint32) (err error) {
+	r1, _, e1 := syscall.Syscall6(procLookupPrivilegeDisplayNameW.Addr(), 5, uintptr(unsafe.Pointer(systemName)), uintptr(unsafe.Pointer(name)), uintptr(unsafe.Pointer(buffer)), uintptr(unsafe.Pointer(size)), uintptr(unsafe.Pointer(languageId)), 0)
+	if r1 == 0 {
+		if e1 != 0 {
+			err = errnoErr(e1)
+		} else {
+			err = syscall.EINVAL
+		}
+	}
+	return
+}
+
+func backupRead(h syscall.Handle, b []byte, bytesRead *uint32, abort bool, processSecurity bool, context *uintptr) (err error) {
+	var _p0 *byte
+	if len(b) > 0 {
+		_p0 = &b[0]
+	}
+	var _p1 uint32
+	if abort {
+		_p1 = 1
+	} else {
+		_p1 = 0
+	}
+	var _p2 uint32
+	if processSecurity {
+		_p2 = 1
+	} else {
+		_p2 = 0
+	}
+	r1, _, e1 := syscall.Syscall9(procBackupRead.Addr(), 7, uintptr(h), uintptr(unsafe.Pointer(_p0)), uintptr(len(b)), uintptr(unsafe.Pointer(bytesRead)), uintptr(_p1), uintptr(_p2), uintptr(unsafe.Pointer(context)), 0, 0)
+	if r1 == 0 {
+		if e1 != 0 {
+			err = errnoErr(e1)
+		} else {
+			err = syscall.EINVAL
+		}
+	}
+	return
+}
+
+func backupWrite(h syscall.Handle, b []byte, bytesWritten *uint32, abort bool, processSecurity bool, context *uintptr) (err error) {
+	var _p0 *byte
+	if len(b) > 0 {
+		_p0 = &b[0]
+	}
+	var _p1 uint32
+	if abort {
+		_p1 = 1
+	} else {
+		_p1 = 0
+	}
+	var _p2 uint32
+	if processSecurity {
+		_p2 = 1
+	} else {
+		_p2 = 0
+	}
+	r1, _, e1 := syscall.Syscall9(procBackupWrite.Addr(), 7, uintptr(h), uintptr(unsafe.Pointer(_p0)), uintptr(len(b)), uintptr(unsafe.Pointer(bytesWritten)), uintptr(_p1), uintptr(_p2), uintptr(unsafe.Pointer(context)), 0, 0)
+	if r1 == 0 {
+		if e1 != 0 {
+			err = errnoErr(e1)
+		} else {
+			err = syscall.EINVAL
+		}
+	}
+	return
+}
+
+func bind(s syscall.Handle, name unsafe.Pointer, namelen int32) (err error) {
+	r1, _, e1 := syscall.Syscall(procbind.Addr(), 3, uintptr(s), uintptr(name), uintptr(namelen))
+	if r1 == socketError {
+		if e1 != 0 {
+			err = errnoErr(e1)
+		} else {
+			err = syscall.EINVAL
+		}
+	}
+	return
+}
diff --git a/vendor/github.com/code-ready/gvisor-tap-vsock/pkg/client/client.go b/vendor/github.com/code-ready/gvisor-tap-vsock/pkg/client/client.go
new file mode 100644
index 000000000..b5ba3d074
--- /dev/null
+++ b/vendor/github.com/code-ready/gvisor-tap-vsock/pkg/client/client.go
@@ -0,0 +1,82 @@
+package client
+
+import (
+	"bytes"
+	"encoding/json"
+	"errors"
+	"fmt"
+	"io/ioutil"
+	"net/http"
+	"strings"
+
+	"github.com/code-ready/gvisor-tap-vsock/pkg/types"
+)
+
+type Client struct {
+	client *http.Client
+	base   string
+}
+
+func New(client *http.Client, base string) *Client {
+	return &Client{
+		client: client,
+		base:   base,
+	}
+}
+
+func (c *Client) List() ([]types.ExposeRequest, error) {
+	res, err := c.client.Get(fmt.Sprintf("%s%s", c.base, "/services/forwarder/all"))
+	if err != nil {
+		return nil, err
+	}
+	defer res.Body.Close()
+	if res.StatusCode != http.StatusOK {
+		return nil, fmt.Errorf("unexpected status: %d", res.StatusCode)
+	}
+	dec := json.NewDecoder(res.Body)
+	var ports []types.ExposeRequest
+	if err := dec.Decode(&ports); err != nil {
+		return nil, err
+	}
+	return ports, nil
+}
+
+func (c *Client) Expose(req *types.ExposeRequest) error {
+	bin, err := json.Marshal(req)
+	if err != nil {
+		return err
+	}
+	res, err := c.client.Post(fmt.Sprintf("%s%s", c.base, "/services/forwarder/expose"), "application/json", bytes.NewReader(bin))
+	if err != nil {
+		return err
+	}
+	defer res.Body.Close()
+	if res.StatusCode != http.StatusOK {
+		err, readErr := ioutil.ReadAll(res.Body)
+		if readErr != nil {
+			return fmt.Errorf("error while reading error message: %v", readErr)
+		}
+		return errors.New(strings.TrimSpace(string(err)))
+	}
+	return nil
+}
+
+func (c *Client) Unexpose(req *types.UnexposeRequest) error {
+	bin, err := json.Marshal(req)
+	if err != nil {
+		return err
+	}
+	res, err := c.client.Post(fmt.Sprintf("%s%s", c.base, "/services/forwarder/unexpose"), "application/json", bytes.NewReader(bin))
+	if err != nil {
+		return err
+	}
+	defer res.Body.Close()
+	if res.StatusCode != http.StatusOK {
+		err, readErr := ioutil.ReadAll(res.Body)
+		if readErr != nil {
+			return fmt.Errorf("error while reading error message: %v", readErr)
+		}
+		return errors.New(strings.TrimSpace(string(err)))
+	}
+	return nil
+}
diff --git a/vendor/github.com/code-ready/gvisor-tap-vsock/pkg/services/forwarder/ports.go b/vendor/github.com/code-ready/gvisor-tap-vsock/pkg/services/forwarder/ports.go
index b9db3fb47..174b726fc 100644
--- a/vendor/github.com/code-ready/gvisor-tap-vsock/pkg/services/forwarder/ports.go
+++ b/vendor/github.com/code-ready/gvisor-tap-vsock/pkg/services/forwarder/ports.go
@@ -95,7 +95,7 @@ func (f *PortsForwarder) Unexpose(local string) error {
 func (f *PortsForwarder) Mux() http.Handler {
 	mux := http.NewServeMux()
 	mux.HandleFunc("/all", func(w http.ResponseWriter, r *http.Request) {
-		var ret []proxy
+		ret := make([]proxy, 0)
 		for _, proxy := range f.proxies {
 			ret = append(ret, proxy)
 		}
diff --git a/vendor/github.com/code-ready/gvisor-tap-vsock/pkg/types/paths.go b/vendor/github.com/code-ready/gvisor-tap-vsock/pkg/types/paths.go
new file mode 100644
index 000000000..d50e5aecb
--- /dev/null
+++ b/vendor/github.com/code-ready/gvisor-tap-vsock/pkg/types/paths.go
@@ -0,0 +1,3 @@
+package types
+
+const ConnectPath = "/connect"
diff --git a/vendor/github.com/code-ready/gvisor-tap-vsock/pkg/virtualnetwork/mux.go b/vendor/github.com/code-ready/gvisor-tap-vsock/pkg/virtualnetwork/mux.go
index 4f65a8ca9..2244b71aa 100644
--- a/vendor/github.com/code-ready/gvisor-tap-vsock/pkg/virtualnetwork/mux.go
+++ b/vendor/github.com/code-ready/gvisor-tap-vsock/pkg/virtualnetwork/mux.go
@@ -7,6 +7,7 @@ import (
 	"net/http"
 	"strconv"
 
+	"github.com/code-ready/gvisor-tap-vsock/pkg/types"
 	"github.com/google/tcpproxy"
 	"github.com/sirupsen/logrus"
 	"gvisor.dev/gvisor/pkg/tcpip"
@@ -26,7 +27,7 @@ func (n *VirtualNetwork) Mux() http.Handler {
 	mux.HandleFunc("/leases", func(w http.ResponseWriter, r *http.Request) {
 		_ = json.NewEncoder(w).Encode(n.networkSwitch.IPs.Leases())
 	})
-	mux.HandleFunc("/connect", func(w http.ResponseWriter, r *http.Request) {
+	mux.HandleFunc(types.ConnectPath, func(w http.ResponseWriter, r *http.Request) {
 		hj, ok := w.(http.Hijacker)
 		if !ok {
 			http.Error(w, "webserver doesn't support hijacking", http.StatusInternalServerError)
diff --git a/vendor/modules.txt b/vendor/modules.txt
index 871573ca9..aefacc767 100644
--- a/vendor/modules.txt
+++ b/vendor/modules.txt
@@ -4,6 +4,10 @@ github.com/Azure/go-ansiterm/winterm
 # github.com/Masterminds/semver v1.5.0
 ## explicit
 github.com/Masterminds/semver
+# github.com/Microsoft/go-winio v0.4.15-0.20200908182639-5b44b70ab3ab
+## explicit
+github.com/Microsoft/go-winio
+github.com/Microsoft/go-winio/pkg/guid
 # github.com/RangelReale/osincli v0.0.0-20160924135400-fababb0555f2
 github.com/RangelReale/osincli
 # github.com/VividCortex/ewma v1.1.1
@@ -32,8 +36,9 @@ github.com/cheggaaa/pb/v3/termutil
 ## explicit
 github.com/code-ready/clicumber/testsuite
 github.com/code-ready/clicumber/util
-# github.com/code-ready/gvisor-tap-vsock v0.0.0-20210128145517-e5f886c34c9f
+# github.com/code-ready/gvisor-tap-vsock v0.0.0-20210216090540-914d522b9c38
 ## explicit
+github.com/code-ready/gvisor-tap-vsock/pkg/client
 github.com/code-ready/gvisor-tap-vsock/pkg/services/dns
 github.com/code-ready/gvisor-tap-vsock/pkg/services/forwarder
 github.com/code-ready/gvisor-tap-vsock/pkg/tap


Test patch:
diff --git a/cmd/crc/cmd/start_test.go b/cmd/crc/cmd/start_test.go
index 2f4fd09e5..52e92ccaa 100644
--- a/cmd/crc/cmd/start_test.go
+++ b/cmd/crc/cmd/start_test.go
@@ -105,7 +105,7 @@ Log in as user:
 
 Use the 'oc' command line interface:
   $ eval $(crc oc-env)
-  $ oc login https://api.crc.testing:6443
+  $ oc login -u developer https://api.crc.testing:6443
 `
 
 const powershellTemplate = `Started the OpenShift cluster.
@@ -123,7 +123,7 @@ Log in as user:
 
 Use the 'oc' command line interface:
   PS> & crc oc-env | Invoke-Expression
-  PS> oc login https://api.crc.testing:6443
+  PS> oc login -u developer https://api.crc.testing:6443
 `
 
 const cmdTemplate = `Started the OpenShift cluster.
@@ -141,7 +141,7 @@ Log in as user:
 
 Use the 'oc' command line interface:
   > @FOR /f "tokens=*" %i IN ('crc oc-env') DO @call %i
-  > oc login https://api.crc.testing:6443
+  > oc login -u developer https://api.crc.testing:6443
 `
 
 func expectedTemplate(shell string) string {
diff --git a/pkg/crc/preflight/preflight_linux_test.go b/pkg/crc/preflight/preflight_linux_test.go
index 6bc0b3b3c..6837fac1c 100644
--- a/pkg/crc/preflight/preflight_linux_test.go
+++ b/pkg/crc/preflight/preflight_linux_test.go
@@ -109,6 +109,7 @@ var checkListForDistros = []checkListForDistro{
 			{check: checkMachineDriverLibvirtInstalled},
 			{cleanup: removeCrcVM},
 			{check: checkVsock},
+			{check: checkIfCRCDaemonRunning},
 			{check: checkBundleExtracted},
 		},
 	},
@@ -163,6 +164,7 @@ var checkListForDistros = []checkListForDistro{
 			{check: checkMachineDriverLibvirtInstalled},
 			{cleanup: removeCrcVM},
 			{check: checkVsock},
+			{check: checkIfCRCDaemonRunning},
 			{check: checkBundleExtracted},
 		},
 	},
@@ -217,6 +219,7 @@ var checkListForDistros = []checkListForDistro{
 			{check: checkMachineDriverLibvirtInstalled},
 			{cleanup: removeCrcVM},
 			{check: checkVsock},
+			{check: checkIfCRCDaemonRunning},
 			{check: checkBundleExtracted},
 		},
 	},
@@ -274,6 +277,7 @@ var checkListForDistros = []checkListForDistro{
 			{cleanup: removeCrcVM},
 			{configKeySuffix: "check-apparmor-profile-setup"},
 			{check: checkVsock},
+			{check: checkIfCRCDaemonRunning},
 			{check: checkBundleExtracted},
 		},
 	},
diff --git a/pkg/crc/preflight/preflight_windows_test.go b/pkg/crc/preflight/preflight_windows_test.go
index 77724abe0..34afd227a 100644
--- a/pkg/crc/preflight/preflight_windows_test.go
+++ b/pkg/crc/preflight/preflight_windows_test.go
@@ -11,13 +11,13 @@ import (
 func TestCountConfigurationOptions(t *testing.T) {
 	cfg := config.New(config.NewEmptyInMemoryStorage())
 	RegisterSettings(cfg)
-	assert.Len(t, cfg.AllConfigs(), 12)
+	assert.Len(t, cfg.AllConfigs(), 13)
 }
 
 func TestCountPreflights(t *testing.T) {
 	assert.Len(t, getPreflightChecks(false, false, network.DefaultMode), 16)
 	assert.Len(t, getPreflightChecks(true, true, network.DefaultMode), 19)
 
-	assert.Len(t, getPreflightChecks(false, false, network.VSockMode), 17)
-	assert.Len(t, getPreflightChecks(true, true, network.VSockMode), 20)
+	assert.Len(t, getPreflightChecks(false, false, network.VSockMode), 18)
+	assert.Len(t, getPreflightChecks(true, true, network.VSockMode), 21)
 }
diff --git a/test/e2e/features/basic.feature b/test/e2e/features/basic.feature
index 747c213ad..ad9ab1f87 100644
--- a/test/e2e/features/basic.feature
+++ b/test/e2e/features/basic.feature
@@ -89,7 +89,7 @@ Feature: Basic test
         When starting CRC with default bundle succeeds
         Then stdout should contain "Started the OpenShift cluster"
         # Check if user can copy-paste login details for developer and kubeadmin users
-        And stdout should match "(?s)(.*)oc login https:\/\/api\.crc\.testing:6443(.*)$"
+        And stdout should match "(?s)(.*)oc login -u developer https:\/\/api\.crc\.testing:6443(.*)$"
         And stdout should match "(?s)(.*)https:\/\/console-openshift-console\.apps-crc\.testing(.*)$"
 
     @darwin @linux @windows