Repository: code-ready/crc
Pull request #1883 (2021-01-25 07:57:44)

Upgrade code-ready/machine, refactor libmachine
The main changes is the new logger. It is now using logrus.

Debug output:
```
time="2021-01-25T08:53:40+01:00" level=info msg="Creating CodeReady Containers VM for OpenShift 4.6.9..."
time="2021-01-25T08:53:40+01:00" level=debug msg="Found binary path at /home/guillaumerose/.crc/bin/crc-driver-libvirt"
time="2021-01-25T08:53:40+01:00" level=debug msg="Launching plugin server for driver libvirt"
time="2021-01-25T08:53:40+01:00" level=debug msg="Plugin server listening at address 127.0.0.1:34831"
time="2021-01-25T08:53:40+01:00" level=debug msg="() Calling .GetVersion"
time="2021-01-25T08:53:40+01:00" level=debug msg="Using API Version 1"
time="2021-01-25T08:53:40+01:00" level=debug msg="() Calling .SetConfigRaw"
time="2021-01-25T08:53:40+01:00" level=debug msg="() Calling .GetMachineName"
time="2021-01-25T08:53:40+01:00" level=debug msg="(crc) Calling .GetMachineName"
time="2021-01-25T08:53:40+01:00" level=debug msg="(crc) Calling .DriverName"
time="2021-01-25T08:53:40+01:00" level=debug msg="Running pre-create checks..."
time="2021-01-25T08:53:40+01:00" level=debug msg="(crc) Calling .PreCreateCheck"
time="2021-01-25T08:53:40+01:00" level=debug msg="(crc) DBG | About to check libvirt version"
time="2021-01-25T08:53:40+01:00" level=debug msg="(crc) DBG | Validating storage pool"
time="2021-01-25T08:53:40+01:00" level=debug msg="(crc) Calling .GetConfigRaw"
time="2021-01-25T08:53:40+01:00" level=debug msg="Creating machine..."
time="2021-01-25T08:53:40+01:00" level=debug msg="(crc) Calling .Create"
time="2021-01-25T08:53:40+01:00" level=debug msg="(crc) DBG | Preparing /home/guillaumerose/.crc/machines/crc/crc.qcow2 for machine use"
time="2021-01-25T08:53:40+01:00" level=debug msg="(crc) DBG | image creation took 79.867012ms"
time="2021-01-25T08:53:40+01:00" level=debug msg="(crc) DBG | Verifying executable bit set on /home/guillaumerose/.crc/machines/crc"
time="2021-01-25T08:53:40+01:00" level=debug msg="(crc) DBG | Setting executable bit set on /home/guillaumerose/.crc/machines/crc"
time="2021-01-25T08:53:40+01:00" level=debug msg="(crc) DBG | Verifying executable bit set on /home/guillaumerose/.crc/machines"
```

Fixes https://github.com/code-ready/crc/issues/1886

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

This pull-request has been approved by: *<a href="https://github.com/code-ready/crc/pull/1883#" title="Author self-approved">guillaumerose</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)~~ [guillaumerose]

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":[]} -->
openshift-ci[bot]: @guillaumerose: The following test **failed**, say `/retest` to rerun all failed tests:

Test name | Commit | Details | Rerun command
--- | --- | --- | ---
ci/prow/e2e-crc | cd4dd2e2ecf4476f25d357801eabb715da93c0ac | [link](https://prow.ci.openshift.org/view/gs/origin-ci-test/pr-logs/pull/code-ready_crc/1883/pull-ci-code-ready-crc-master-e2e-crc/1353613010416963584) | `/test e2e-crc`

[Full PR test history](https://prow.ci.openshift.org/pr-history?org=code-ready&repo=crc&pr=1883). [Your PR dashboard](https://prow.ci.openshift.org/pr?query=is:pr+state:open+author:guillaumerose).

<details>

Instructions for interacting with me using PR comments are available [here](https://git.k8s.io/community/contributors/guide/pull-requests.md).  If you have questions or suggestions related to my behavior, please file an issue against the [kubernetes/test-infra](https://github.com/kubernetes/test-infra/issues/new?title=Prow%20issue:) repository. I understand the commands that are listed [here](https://go.k8s.io/bot-commands).
</details>
<!-- test report -->
guillaumerose: All done except for the MachineInState change that is now only used here so we can adapt it.

Patch:
diff --git a/cmd/crc/cmd/daemon.go b/cmd/crc/cmd/daemon.go
index fd1b37875..13d0fc267 100644
--- a/cmd/crc/cmd/daemon.go
+++ b/cmd/crc/cmd/daemon.go
@@ -5,9 +5,11 @@ import (
 	"net"
 	"net/http"
 	"os"
+	"os/signal"
 	"path/filepath"
 	"regexp"
 	"runtime"
+	"syscall"
 	"time"
 
 	"github.com/code-ready/crc/pkg/crc/api"
@@ -37,8 +39,6 @@ var daemonCmd = &cobra.Command{
 		logging.CloseLogging()
 		logging.InitLogrus(logging.LogLevel, constants.DaemonLogFilePath)
 
-		go runDaemon()
-
 		var endpoints []string
 		if runtime.GOOS == "windows" {
 			endpoints = append(endpoints, transport.DefaultURL)
@@ -130,7 +130,21 @@ func run(configuration *types.Configuration, endpoints []string) error {
 			}
 		}()
 	}
-	return <-errCh
+
+	go func() {
+		if err := runDaemon(); err != nil {
+			errCh <- err
+		}
+	}()
+
+	c := make(chan os.Signal, 1)
+	signal.Notify(c, os.Interrupt, syscall.SIGTERM)
+	select {
+	case <-c:
+		return nil
+	case err := <-errCh:
+		return err
+	}
 }
 
 func newConfig() (crcConfig.Storage, error) {
@@ -138,12 +152,12 @@ func newConfig() (crcConfig.Storage, error) {
 	return config, err
 }
 
-func runDaemon() {
+func runDaemon() error {
 	// Remove if an old socket is present
 	os.Remove(constants.DaemonSocketPath)
-	crcAPIServer, err := api.CreateAPIServer(constants.DaemonSocketPath, newConfig, newMachineWithConfig)
+	apiServer, err := api.CreateServer(constants.DaemonSocketPath, newConfig, newMachineWithConfig)
 	if err != nil {
-		logging.Fatal("Failed to launch daemon", err)
+		return err
 	}
-	crcAPIServer.Serve()
+	return apiServer.Serve()
 }
diff --git a/cmd/crc/cmd/root.go b/cmd/crc/cmd/root.go
index 4c360a139..98267b396 100644
--- a/cmd/crc/cmd/root.go
+++ b/cmd/crc/cmd/root.go
@@ -160,12 +160,9 @@ func newMachine() machine.Client {
 }
 
 func newMachineWithConfig(config crcConfig.Storage) machine.Client {
-	return machine.NewClient(
-		constants.DefaultName,
-		isDebugLog(),
-		network.ParseMode(config.Get(cmdConfig.NetworkMode).AsString()),
-		config.Get(cmdConfig.EnableClusterMonitoring).AsBool(),
-	)
+	networkMode := network.ParseMode(config.Get(cmdConfig.NetworkMode).AsString())
+	enableMonitoring := config.Get(cmdConfig.EnableClusterMonitoring).AsBool()
+	return machine.NewClient(constants.DefaultName, networkMode, enableMonitoring)
 }
 
 func addForceFlag(cmd *cobra.Command) {
diff --git a/go.mod b/go.mod
index 241e1d808..097ca5940 100644
--- a/go.mod
+++ b/go.mod
@@ -10,7 +10,7 @@ require (
 	github.com/cheggaaa/pb/v3 v3.0.5
 	github.com/code-ready/clicumber v0.0.0-20200728062640-1203dda97f67
 	github.com/code-ready/gvisor-tap-vsock v0.0.0-20201105131011-9258bacc7a6c
-	github.com/code-ready/machine v0.0.0-20201202090222-9558ae8c05b9
+	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
 	github.com/docker/docker v1.13.1 // indirect
@@ -43,7 +43,7 @@ require (
 	github.com/spf13/cobra v1.1.1
 	github.com/spf13/pflag v1.0.5
 	github.com/spf13/viper v1.7.1
-	github.com/stretchr/testify v1.6.1
+	github.com/stretchr/testify v1.7.0
 	github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8
 	github.com/xtgo/uuid v0.0.0-20140804021211-a0b114877d4c // indirect
 	golang.org/x/crypto v0.0.0-20201203163018-be400aefbc4c
diff --git a/go.sum b/go.sum
index e167954b3..999ac0858 100644
--- a/go.sum
+++ b/go.sum
@@ -130,7 +130,6 @@ github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869 h1:DDGfHa7BWjL4Yn
 github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869/go.mod h1:Ekp36dRnpXw/yCqJaO+ZrUyxD+3VXMFFr56k5XYrpB4=
 github.com/boltdb/bolt v1.3.1/go.mod h1:clJnj/oiGkjum5o1McbSZDSLxVThjynRyGBgiAx27Ps=
 github.com/bshuster-repo/logrus-logstash-hook v0.4.1/go.mod h1:zsTqEiSzDgAa/8GZR7E1qaXrhYNDKBYy5/dWPTIflbk=
-github.com/bugsnag/bugsnag-go v1.5.1/go.mod h1:2oa8nejYd4cQ/b0hMIopN0lCRxU0bueqREvZLWFrtK8=
 github.com/bugsnag/bugsnag-go v1.5.3/go.mod h1:2oa8nejYd4cQ/b0hMIopN0lCRxU0bueqREvZLWFrtK8=
 github.com/bugsnag/panicwrap v1.2.0/go.mod h1:D/8v3kj0zr8ZAKg1AQ6crr+5VwKN5eIywRkfhyM/+dE=
 github.com/caddyserver/caddy v1.0.3/go.mod h1:G+ouvOY32gENkJC+jhgl62TyhvqEsFaDiZ4uw0RzP1E=
@@ -164,8 +163,8 @@ github.com/code-ready/clicumber v0.0.0-20200728062640-1203dda97f67 h1:C+EVPWw8sj
 github.com/code-ready/clicumber v0.0.0-20200728062640-1203dda97f67/go.mod h1:ZPZUcYGpv/FQGnwakUuhiHP9x/IIcU2SKbn8xPe4ROc=
 github.com/code-ready/gvisor-tap-vsock v0.0.0-20201105131011-9258bacc7a6c h1:j8S82O8ovWK7nmNJAQf+dFH/RCtXCZneBi33nx2fMPo=
 github.com/code-ready/gvisor-tap-vsock v0.0.0-20201105131011-9258bacc7a6c/go.mod h1:tySPFyGlPN7nyc3u8RH2FAhRDC9JvbQVzJBOrlRJKgU=
-github.com/code-ready/machine v0.0.0-20201202090222-9558ae8c05b9 h1:fUAQ1rYNefX/QPuU0HL7qxc1bURY3qDq/gca+NxiXt8=
-github.com/code-ready/machine v0.0.0-20201202090222-9558ae8c05b9/go.mod h1:g30jKsf0FV9yJjsqZFAuFzVxwJE2h5cqDXSuMUV1G/U=
+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=
 github.com/container-storage-interface/spec v1.2.0/go.mod h1:6URME8mwIBbpVyZV93Ce5St17xBiQJQY67NDsuohiy4=
 github.com/containerd/cgroups v0.0.0-20181219155423-39b18af02c41/go.mod h1:X9rLEHIqSf/wfK8NsPqxJmeZgW4pcfzdXITDrUSJ6uI=
@@ -520,7 +519,6 @@ github.com/imdario/mergo v0.3.11 h1:3tnifQM4i+fbajXKBHXWEH+KvNHqojZ778UH75j3bGA=
 github.com/imdario/mergo v0.3.11/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA=
 github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM=
 github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
-github.com/intel-go/cpuid v0.0.0-20181003105527-1a4a6f06a1c6/go.mod h1:RmeVYf9XrPRbRc3XIx0gLYA8qOFvNoPOfaEZduRlEp4=
 github.com/ishidawataru/sctp v0.0.0-20190723014705-7c296d48a2b5/go.mod h1:DM4VvS+hD/kDi1U1QsX2fnZowwBhqD0Dk3bRPKF/Oc8=
 github.com/jackc/fake v0.0.0-20150926172116-812a484cc733/go.mod h1:WrMFNQdiFJ80sQsxDoMokWK1W5TQtxBFNpzWTD84ibQ=
 github.com/jackc/pgx v3.2.0+incompatible/go.mod h1:0ZGrqGqkRlliWnWB4zKnWtjbSWbGkVEFm4TeybAXq+I=
@@ -863,8 +861,8 @@ github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXf
 github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
 github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
 github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
-github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0=
-github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
+github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
+github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
 github.com/subosito/gotenv v1.2.0 h1:Slr1R9HxAlEKefgq5jn9U+DnETlIUa6HfgEzj0g5d7s=
 github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw=
 github.com/syndtr/gocapability v0.0.0-20180916011248-d98352740cb2/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww=
@@ -940,7 +938,6 @@ golang.org/x/crypto v0.0.0-20190228161510-8dd112bcdc25/go.mod h1:djNgcEr1/C05ACk
 golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
 golang.org/x/crypto v0.0.0-20190320223903-b7391e95e576/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
 golang.org/x/crypto v0.0.0-20190325154230-a5d413f7728c/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
-golang.org/x/crypto v0.0.0-20190422183909-d864b10871cd/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
 golang.org/x/crypto v0.0.0-20190426145343-a29dc8fdc734/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
 golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
 golang.org/x/crypto v0.0.0-20190530122614-20be4c3c3ed5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
@@ -1341,6 +1338,8 @@ 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=
 gotest.tools v0.0.0-20190624233834-05ebafbffc79/go.mod h1:R//lfYlUuTOTfblYI3lGoAAAebUdzjvbmQsuB7Ykd90=
 gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo=
 gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw=
diff --git a/pkg/crc/api/api.go b/pkg/crc/api/api.go
index 076b35e8d..2a0b6bab6 100644
--- a/pkg/crc/api/api.go
+++ b/pkg/crc/api/api.go
@@ -9,17 +9,17 @@ import (
 	"github.com/code-ready/crc/pkg/crc/logging"
 )
 
-func CreateAPIServer(socketPath string, config newConfigFunc, machine newMachineFunc) (CrcAPIServer, error) {
+func CreateServer(socketPath string, config newConfigFunc, machine newMachineFunc) (Server, error) {
 	listener, err := net.Listen("unix", socketPath)
 	if err != nil {
 		logging.Error("Failed to create socket: ", err.Error())
-		return CrcAPIServer{}, err
+		return Server{}, err
 	}
-	return createAPIServerWithListener(listener, config, machine)
+	return createServerWithListener(listener, config, machine)
 }
 
-func createAPIServerWithListener(listener net.Listener, config newConfigFunc, machine newMachineFunc) (CrcAPIServer, error) {
-	apiServer := CrcAPIServer{
+func createServerWithListener(listener net.Listener, config newConfigFunc, machine newMachineFunc) (Server, error) {
+	apiServer := Server{
 		listener:               listener,
 		clusterOpsRequestsChan: make(chan clusterOpsRequest, 10),
 		handlerFactory: func() (RequestHandler, error) {
@@ -36,7 +36,7 @@ func createAPIServerWithListener(listener net.Listener, config newConfigFunc, ma
 	return apiServer, nil
 }
 
-func (api CrcAPIServer) Serve() {
+func (api Server) Serve() error {
 	go api.handleClusterOperations() // go routine that handles start, stop and delete calls
 	for {
 		conn, err := api.listener.Accept()
@@ -48,13 +48,13 @@ func (api CrcAPIServer) Serve() {
 	}
 }
 
-func (api CrcAPIServer) handleClusterOperations() {
+func (api Server) handleClusterOperations() {
 	for req := range api.clusterOpsRequestsChan {
 		api.handleRequest(req.command, req.socket)
 	}
 }
 
-func (api CrcAPIServer) handleRequest(req commandRequest, conn net.Conn) {
+func (api Server) handleRequest(req commandRequest, conn net.Conn) {
 	defer conn.Close()
 	var result string
 
@@ -91,7 +91,7 @@ func (api CrcAPIServer) handleRequest(req commandRequest, conn net.Conn) {
 	writeStringToSocket(conn, result)
 }
 
-func (api CrcAPIServer) handleConnections(conn net.Conn) {
+func (api Server) handleConnections(conn net.Conn) {
 	inBuffer := make([]byte, 1024)
 	var req commandRequest
 	numBytes, err := conn.Read(inBuffer)
diff --git a/pkg/crc/api/types.go b/pkg/crc/api/types.go
index 90ffeb477..827658758 100644
--- a/pkg/crc/api/types.go
+++ b/pkg/crc/api/types.go
@@ -16,7 +16,7 @@ type commandError struct {
 	Err string
 }
 
-type CrcAPIServer struct {
+type Server struct {
 	handlerFactory         newHandlerFunc
 	listener               net.Listener
 	clusterOpsRequestsChan chan clusterOpsRequest
diff --git a/pkg/crc/machine/client.go b/pkg/crc/machine/client.go
index a6bb181f5..1e5b63ba1 100644
--- a/pkg/crc/machine/client.go
+++ b/pkg/crc/machine/client.go
@@ -20,15 +20,13 @@ type Client interface {
 
 type client struct {
 	name              string
-	debug             bool
 	networkMode       network.Mode
 	monitoringEnabled bool
 }
 
-func NewClient(name string, debug bool, networkMode network.Mode, monitoringEnabled bool) Client {
+func NewClient(name string, networkMode network.Mode, monitoringEnabled bool) Client {
 	return &client{
 		name:              name,
-		debug:             debug,
 		networkMode:       networkMode,
 		monitoringEnabled: monitoringEnabled,
 	}
diff --git a/pkg/crc/machine/console.go b/pkg/crc/machine/console.go
index ccbc8b1f8..6e9fb3078 100644
--- a/pkg/crc/machine/console.go
+++ b/pkg/crc/machine/console.go
@@ -7,11 +7,8 @@ func (client *client) GetConsoleURL() (*ConsoleResult, error) {
 	// Here we are only checking if the VM exist and not the status of the VM.
 	// We might need to improve and use crc status logic, only
 	// return if the Openshift is running as part of status.
-	libMachineAPIClient, cleanup, err := createLibMachineClient(client.debug)
+	libMachineAPIClient, cleanup := createLibMachineClient()
 	defer cleanup()
-	if err != nil {
-		return nil, errors.Wrap(err, "Cannot initialize libmachine")
-	}
 	host, err := libMachineAPIClient.Load(client.name)
 	if err != nil {
 		return nil, errors.Wrap(err, "Cannot load machine")
diff --git a/pkg/crc/machine/delete.go b/pkg/crc/machine/delete.go
index 30c7543f9..ca24ad5f1 100644
--- a/pkg/crc/machine/delete.go
+++ b/pkg/crc/machine/delete.go
@@ -6,12 +6,9 @@ import (
 )
 
 func (client *client) Delete() error {
-	libMachineAPIClient, cleanup, err := createLibMachineClient(false)
+	libMachineAPIClient, cleanup := createLibMachineClient()
 	defer logging.BackupLogFile()
 	defer cleanup()
-	if err != nil {
-		return errors.Wrap(err, "Cannot initialize libmachine")
-	}
 	host, err := libMachineAPIClient.Load(client.name)
 
 	if err != nil {
diff --git a/pkg/crc/machine/exists.go b/pkg/crc/machine/exists.go
index 029677036..1394e119c 100644
--- a/pkg/crc/machine/exists.go
+++ b/pkg/crc/machine/exists.go
@@ -3,11 +3,8 @@ package machine
 import "fmt"
 
 func (client *client) Exists() (bool, error) {
-	libMachineAPIClient, cleanup, err := createLibMachineClient(client.debug)
+	libMachineAPIClient, cleanup := createLibMachineClient()
 	defer cleanup()
-	if err != nil {
-		return false, err
-	}
 	exists, err := libMachineAPIClient.Exists(client.name)
 	if err != nil {
 		return false, fmt.Errorf("Error checking if the host exists: %s", err)
diff --git a/pkg/crc/machine/ip.go b/pkg/crc/machine/ip.go
index 77ed5a585..9cff84da3 100644
--- a/pkg/crc/machine/ip.go
+++ b/pkg/crc/machine/ip.go
@@ -3,11 +3,8 @@ package machine
 import "github.com/pkg/errors"
 
 func (client *client) IP() (string, error) {
-	libMachineAPIClient, cleanup, err := createLibMachineClient(client.debug)
+	libMachineAPIClient, cleanup := createLibMachineClient()
 	defer cleanup()
-	if err != nil {
-		return "", errors.Wrap(err, "Cannot initialize libmachine")
-	}
 	host, err := libMachineAPIClient.Load(client.name)
 
 	if err != nil {
diff --git a/pkg/crc/machine/machine.go b/pkg/crc/machine/machine.go
index cdb1599c2..18fd4b06e 100644
--- a/pkg/crc/machine/machine.go
+++ b/pkg/crc/machine/machine.go
@@ -3,16 +3,13 @@ package machine
 import (
 	"encoding/base64"
 	"fmt"
-	"os"
 
 	"github.com/code-ready/crc/pkg/crc/constants"
-	"github.com/code-ready/crc/pkg/crc/logging"
 	"github.com/code-ready/crc/pkg/crc/machine/bundle"
 	"github.com/code-ready/crc/pkg/crc/network"
 	"github.com/code-ready/crc/pkg/libmachine"
 	"github.com/code-ready/crc/pkg/libmachine/host"
 	"github.com/code-ready/machine/libmachine/drivers"
-	"github.com/code-ready/machine/libmachine/log"
 )
 
 func getClusterConfig(bundleInfo *bundle.CrcBundleInfo) (*ClusterConfig, error) {
@@ -52,18 +49,11 @@ func getBundleMetadataFromDriver(driver drivers.Driver) (string, *bundle.CrcBund
 	return bundleName, metadata, err
 }
 
-func createLibMachineClient(debug bool) (*libmachine.Client, func(), error) {
-	logfile, err := setMachineLogging(debug)
-	if err != nil {
-		return nil, func() {}, err
-	}
+func createLibMachineClient() (*libmachine.Client, func()) {
 	client := libmachine.NewClient(constants.MachineBaseDir)
 	return client, func() {
 		client.Close()
-		if logfile != nil {
-			logfile.Close()
-		}
-	}, nil
+	}
 }
 
 func getSSHPort(vsockNetwork bool) int {
@@ -80,21 +70,6 @@ func getIP(h *host.Host, vsockNetwork bool) (string, error) {
 	return h.Driver.GetIP()
 }
 
-func setMachineLogging(logs bool) (*os.File, error) {
-	if !logs {
-		log.SetDebug(true)
-		logfile, err := logging.OpenLogFile(constants.LogFilePath)
-		if err != nil {
-			return nil, err
-		}
-		log.SetOutWriter(logfile)
-		log.SetErrWriter(logfile)
-		return logfile, nil
-	}
-	log.SetDebug(true)
-	return nil, nil
-}
-
 func getProxyConfig(baseDomainName string) (*network.ProxyConfig, error) {
 	proxy, err := network.NewProxyConfig()
 	if err != nil {
diff --git a/pkg/crc/machine/poweroff.go b/pkg/crc/machine/poweroff.go
index a2ac1b51b..2f4d6b850 100644
--- a/pkg/crc/machine/poweroff.go
+++ b/pkg/crc/machine/poweroff.go
@@ -3,11 +3,8 @@ package machine
 import "github.com/pkg/errors"
 
 func (client *client) PowerOff() error {
-	libMachineAPIClient, cleanup, err := createLibMachineClient(false)
+	libMachineAPIClient, cleanup := createLibMachineClient()
 	defer cleanup()
-	if err != nil {
-		return errors.Wrap(err, "Cannot initialize libmachine")
-	}
 
 	host, err := libMachineAPIClient.Load(client.name)
 	if err != nil {
diff --git a/pkg/crc/machine/start.go b/pkg/crc/machine/start.go
index f5ac9fe91..8cf2954cb 100644
--- a/pkg/crc/machine/start.go
+++ b/pkg/crc/machine/start.go
@@ -94,11 +94,8 @@ func (client *client) Start(startConfig StartConfig) (*StartResult, error) {
 
 	var crcBundleMetadata *bundle.CrcBundleInfo
 
-	libMachineAPIClient, cleanup, err := createLibMachineClient(client.debug)
+	libMachineAPIClient, cleanup := createLibMachineClient()
 	defer cleanup()
-	if err != nil {
-		return nil, errors.Wrap(err, "Cannot initialize libmachine")
-	}
 
 	// Pre-VM start
 	var host *host.Host
diff --git a/pkg/crc/machine/status.go b/pkg/crc/machine/status.go
index 54467cf5c..28507e339 100644
--- a/pkg/crc/machine/status.go
+++ b/pkg/crc/machine/status.go
@@ -11,13 +11,10 @@ import (
 )
 
 func (client *client) Status() (*ClusterStatusResult, error) {
-	libMachineAPIClient, cleanup, err := createLibMachineClient(false)
+	libMachineAPIClient, cleanup := createLibMachineClient()
 	defer cleanup()
-	if err != nil {
-		return nil, errors.Wrap(err, "Cannot initialize libmachine")
-	}
 
-	_, err = libMachineAPIClient.Exists(client.name)
+	_, err := libMachineAPIClient.Exists(client.name)
 	if err != nil {
 		return nil, errors.Wrap(err, "Cannot check if machine exists")
 	}
diff --git a/pkg/crc/machine/stop.go b/pkg/crc/machine/stop.go
index a2496cb0c..3b38f20ce 100644
--- a/pkg/crc/machine/stop.go
+++ b/pkg/crc/machine/stop.go
@@ -7,11 +7,8 @@ import (
 )
 
 func (client *client) Stop() (state.State, error) {
-	libMachineAPIClient, cleanup, err := createLibMachineClient(client.debug)
+	libMachineAPIClient, cleanup := createLibMachineClient()
 	defer cleanup()
-	if err != nil {
-		return state.None, errors.Wrap(err, "Cannot initialize libmachine")
-	}
 	host, err := libMachineAPIClient.Load(client.name)
 
 	if err != nil {
diff --git a/pkg/crc/preflight/preflight_checks_tray_windows.go b/pkg/crc/preflight/preflight_checks_tray_windows.go
index 93ffce098..b1a506d37 100644
--- a/pkg/crc/preflight/preflight_checks_tray_windows.go
+++ b/pkg/crc/preflight/preflight_checks_tray_windows.go
@@ -100,8 +100,9 @@ func fixTrayInstalled() error {
 }
 
 func removeTray() error {
+	trayShortcutPath := filepath.Join(constants.StartupFolder, constants.TrayShortcutName)
 	_ = stopTray()
-	return goos.Remove(filepath.Join(constants.StartupFolder, constants.TrayShortcutName))
+	return os.RemoveFileIfExists(trayShortcutPath)
 }
 
 func stopTray() error {
@@ -116,10 +117,10 @@ func stopTray() error {
 func removeDaemon() error {
 	_ = stopDaemon()
 	var mErr errors.MultiError
-	if err := goos.Remove(constants.DaemonBatchFilePath); err != nil {
+	if err := os.RemoveFileIfExists(constants.DaemonBatchFilePath); err != nil {
 		mErr.Collect(err)
 	}
-	if err := goos.Remove(constants.DaemonPSScriptPath); err != nil {
+	if err := os.RemoveFileIfExists(constants.DaemonPSScriptPath); err != nil {
 		mErr.Collect(err)
 	}
 	if len(mErr.Errors) == 0 {
diff --git a/pkg/crc/preflight/preflight_windows.go b/pkg/crc/preflight/preflight_windows.go
index 57832981a..5ac5f376d 100644
--- a/pkg/crc/preflight/preflight_windows.go
+++ b/pkg/crc/preflight/preflight_windows.go
@@ -97,11 +97,6 @@ var traySetupChecks = [...]Check{
 		cleanup:            removeTray,
 		flags:              SetupOnly,
 	},
-	{
-		cleanupDescription: "Stopping crc tray if running",
-		cleanup:            stopTray,
-		flags:              CleanUpOnly,
-	},
 }
 
 var vsockChecks = [...]Check{
diff --git a/pkg/drivers/hyperv/copy.go b/pkg/drivers/hyperv/copy.go
new file mode 100644
index 000000000..798870845
--- /dev/null
+++ b/pkg/drivers/hyperv/copy.go
@@ -0,0 +1,33 @@
+package hyperv
+
+import (
+	"io"
+	"os"
+)
+
+func copyFile(src, dst string) error {
+	in, err := os.Open(src)
+	if err != nil {
+		return err
+	}
+
+	defer in.Close()
+
+	out, err := os.Create(dst)
+	if err != nil {
+		return err
+	}
+
+	defer out.Close()
+
+	if _, err = io.Copy(out, in); err != nil {
+		return err
+	}
+
+	fi, err := os.Stat(src)
+	if err != nil {
+		return err
+	}
+
+	return os.Chmod(dst, fi.Mode())
+}
diff --git a/pkg/drivers/hyperv/hyperv.go b/pkg/drivers/hyperv/hyperv.go
index 3c054d24a..465e7a508 100644
--- a/pkg/drivers/hyperv/hyperv.go
+++ b/pkg/drivers/hyperv/hyperv.go
@@ -7,7 +7,6 @@ import (
 	"time"
 
 	log "github.com/code-ready/crc/pkg/crc/logging"
-	"github.com/code-ready/crc/pkg/libmachine/mcnutils"
 	"github.com/code-ready/machine/libmachine/drivers"
 	"github.com/code-ready/machine/libmachine/state"
 )
@@ -144,7 +143,7 @@ func (d *Driver) getDiskPath() string {
 }
 
 func (d *Driver) Create() error {
-	if err := mcnutils.CopyFile(d.ImageSourcePath, d.getDiskPath()); err != nil {
+	if err := copyFile(d.ImageSourcePath, d.getDiskPath()); err != nil {
 		return err
 	}
 
@@ -159,11 +158,11 @@ func (d *Driver) Create() error {
 		if err != nil {
 			return err
 		}
-		log.Infof("Using switch %q", virtualSwitch)
+		log.Debugf("Using switch %q", virtualSwitch)
 		args = append(args, "-SwitchName", quote(virtualSwitch))
 	}
 
-	log.Infof("Creating VM...")
+	log.Debugf("Creating VM...")
 	if err := cmd(args...); err != nil {
 		return err
 	}
@@ -204,7 +203,7 @@ func (d *Driver) Create() error {
 		return err
 	}
 
-	log.Infof("Starting VM...")
+	log.Debugf("Starting VM...")
 	return d.Start()
 }
 
@@ -241,7 +240,7 @@ func (d *Driver) waitForIP() (string, error) {
 		return "", errors.New("no virtual switch given")
 	}
 
-	log.Infof("Waiting for host to start...")
+	log.Debugf("Waiting for host to start...")
 
 	for {
 		ip, _ := d.GetIP()
@@ -255,7 +254,7 @@ func (d *Driver) waitForIP() (string, error) {
 
 // waitStopped waits until the host is stopped
 func (d *Driver) waitStopped() error {
-	log.Infof("Waiting for host to stop...")
+	log.Debugf("Waiting for host to stop...")
 
 	for {
 		s, err := d.GetState()
diff --git a/pkg/libmachine/host/host.go b/pkg/libmachine/host/host.go
index f257ca694..d197a0284 100644
--- a/pkg/libmachine/host/host.go
+++ b/pkg/libmachine/host/host.go
@@ -2,19 +2,21 @@ package host
 
 import (
 	"errors"
+	"fmt"
 	"net/rpc"
-	"regexp"
+	"strings"
+	"time"
 
+	crcerrors "github.com/code-ready/crc/pkg/crc/errors"
 	log "github.com/code-ready/crc/pkg/crc/logging"
-	"github.com/code-ready/crc/pkg/libmachine/mcnerror"
-	"github.com/code-ready/crc/pkg/libmachine/mcnutils"
 	"github.com/code-ready/machine/libmachine/drivers"
 	"github.com/code-ready/machine/libmachine/state"
 )
 
-var (
-	validHostNamePattern = regexp.MustCompile(`^[a-zA-Z0-9][a-zA-Z0-9\-\.]*$`)
-)
+// ConfigVersion dictates which version of the config.json format is
+// used. It needs to be bumped if there is a breaking change, and
+// therefore migration, introduced to the config file format.
+const Version = 3
 
 type Host struct {
 	ConfigVersion int
@@ -29,53 +31,46 @@ type Metadata struct {
 	ConfigVersion int
 }
 
-func ValidateHostName(name string) bool {
-	return validHostNamePattern.MatchString(name)
-}
-
 func (h *Host) runActionForState(action func() error, desiredState state.State) error {
-	if drivers.MachineInState(h.Driver, desiredState)() {
-		return mcnerror.ErrHostAlreadyInState{
-			Name:  h.Name,
-			State: desiredState,
-		}
+	if err := MachineInState(h.Driver, desiredState)(); err == nil {
+		return fmt.Errorf("machine is already %s", strings.ToLower(desiredState.String()))
 	}
 
 	if err := action(); err != nil {
 		return err
 	}
 
-	return mcnutils.WaitFor(drivers.MachineInState(h.Driver, desiredState))
+	return crcerrors.RetryAfter(3*time.Minute, MachineInState(h.Driver, desiredState), 3*time.Second)
 }
 
 func (h *Host) Start() error {
-	log.Infof("Starting %q...", h.Name)
+	log.Debugf("Starting %q...", h.Name)
 	if err := h.runActionForState(h.Driver.Start, state.Running); err != nil {
 		return err
 	}
 
-	log.Infof("Machine %q was started.", h.Name)
+	log.Debugf("Machine %q was started.", h.Name)
 
 	return nil
 }
 
 func (h *Host) Stop() error {
-	log.Infof("Stopping %q...", h.Name)
+	log.Debugf("Stopping %q...", h.Name)
 	if err := h.runActionForState(h.Driver.Stop, state.Stopped); err != nil {
 		return err
 	}
 
-	log.Infof("Machine %q was stopped.", h.Name)
+	log.Debugf("Machine %q was stopped.", h.Name)
 	return nil
 }
 
 func (h *Host) Kill() error {
-	log.Infof("Killing %q...", h.Name)
+	log.Debugf("Killing %q...", h.Name)
 	if err := h.runActionForState(h.Driver.Kill, state.Stopped); err != nil {
 		return err
 	}
 
-	log.Infof("Machine %q was killed.", h.Name)
+	log.Debugf("Machine %q was killed.", h.Name)
 	return nil
 }
 
@@ -92,3 +87,18 @@ func (h *Host) UpdateConfig(rawConfig []byte) error {
 
 	return nil
 }
+
+func MachineInState(d drivers.Driver, desiredState state.State) func() error {
+	return func() error {
+		currentState, err := d.GetState()
+		if err != nil {
+			return err
+		}
+		if currentState == desiredState {
+			return nil
+		}
+		return crcerrors.RetriableError{
+			Err: fmt.Errorf("expected machine state %s, got %s", desiredState.String(), currentState.String()),
+		}
+	}
+}
diff --git a/pkg/libmachine/host/migrate.go b/pkg/libmachine/host/migrate.go
index e5d3a7dc6..631000bd9 100644
--- a/pkg/libmachine/host/migrate.go
+++ b/pkg/libmachine/host/migrate.go
@@ -6,7 +6,6 @@ import (
 	"fmt"
 
 	"github.com/code-ready/crc/pkg/drivers/none"
-	"github.com/code-ready/crc/pkg/libmachine/version"
 )
 
 var (
@@ -37,7 +36,7 @@ func MigrateHost(name string, data []byte) (*Host, error) {
 		return nil, err
 	}
 
-	if hostMetadata.ConfigVersion != version.ConfigVersion {
+	if hostMetadata.ConfigVersion != Version {
 		return nil, errUnexpectedConfigVersion
 	}
 
diff --git a/pkg/libmachine/libmachine.go b/pkg/libmachine/libmachine.go
index 8a7109a1f..e85bd18e4 100644
--- a/pkg/libmachine/libmachine.go
+++ b/pkg/libmachine/libmachine.go
@@ -4,17 +4,17 @@ import (
 	"encoding/json"
 	"fmt"
 	"io"
+	"time"
 
+	crcerrors "github.com/code-ready/crc/pkg/crc/errors"
 	log "github.com/code-ready/crc/pkg/crc/logging"
 	"github.com/code-ready/crc/pkg/drivers/hyperv"
 	"github.com/code-ready/crc/pkg/libmachine/host"
-	"github.com/code-ready/crc/pkg/libmachine/mcnerror"
-	"github.com/code-ready/crc/pkg/libmachine/mcnutils"
 	"github.com/code-ready/crc/pkg/libmachine/persist"
-	"github.com/code-ready/crc/pkg/libmachine/version"
 	"github.com/code-ready/machine/libmachine/drivers"
 	rpcdriver "github.com/code-ready/machine/libmachine/drivers/rpc"
 	"github.com/code-ready/machine/libmachine/state"
+	"github.com/pkg/errors"
 )
 
 type API interface {
@@ -22,7 +22,6 @@ type API interface {
 	NewHost(driverName string, driverPath string, rawDriver []byte) (*host.Host, error)
 	Create(h *host.Host) error
 	persist.Store
-	GetMachinesDir() string
 }
 
 type Client struct {
@@ -53,7 +52,7 @@ func (api *Client) NewHost(driverName string, driverPath string, rawDriver []byt
 	}
 
 	return &host.Host{
-		ConfigVersion: version.ConfigVersion,
+		ConfigVersion: host.Version,
 		Name:          driver.GetMachineName(),
 		Driver:        driver,
 		DriverName:    driver.DriverName(),
@@ -88,19 +87,17 @@ func (api *Client) Load(name string) (*host.Host, error) {
 // Create is the wrapper method which covers all of the boilerplate around
 // actually creating, provisioning, and persisting an instance in the store.
 func (api *Client) Create(h *host.Host) error {
-	log.Info("Running pre-create checks...")
+	log.Debug("Running pre-create checks...")
 
 	if err := h.Driver.PreCreateCheck(); err != nil {
-		return mcnerror.ErrDuringPreCreate{
-			Cause: err,
-		}
+		return errors.Wrap(err, "error with pre-create check")
 	}
 
 	if err := api.Save(h); err != nil {
 		return fmt.Errorf("Error saving host to store before attempting creation: %s", err)
 	}
 
-	log.Info("Creating machine...")
+	log.Debug("Creating machine...")
 
 	if err := api.performCreate(h); err != nil {
 		return fmt.Errorf("Error creating machine: %s", err)
@@ -123,17 +120,12 @@ func (api *Client) performCreate(h *host.Host) error {
 		return fmt.Errorf("Error saving host to store after attempting creation: %s", err)
 	}
 
-	// TODO: Not really a fan of just checking "none" or "ci-test" here.
-	if h.Driver.DriverName() == "none" || h.Driver.DriverName() == "ci-test" {
-		return nil
-	}
-
-	log.Info("Waiting for machine to be running, this may take a few minutes...")
-	if err := mcnutils.WaitFor(drivers.MachineInState(h.Driver, state.Running)); err != nil {
+	log.Debug("Waiting for machine to be running, this may take a few minutes...")
+	if err := crcerrors.RetryAfter(3*time.Minute, host.MachineInState(h.Driver, state.Running), 3*time.Second); err != nil {
 		return fmt.Errorf("Error waiting for machine to be running: %s", err)
 	}
 
-	log.Info("Machine is up and running!")
+	log.Debug("Machine is up and running!")
 	return nil
 }
 
diff --git a/pkg/libmachine/mcnerror/errors.go b/pkg/libmachine/mcnerror/errors.go
deleted file mode 100644
index 31e440a7a..000000000
--- a/pkg/libmachine/mcnerror/errors.go
+++ /dev/null
@@ -1,33 +0,0 @@
-package mcnerror
-
-import (
-	"fmt"
-	"strings"
-
-	"github.com/code-ready/machine/libmachine/state"
-)
-
-type ErrHostDoesNotExist struct {
-	Name string
-}
-
-func (e ErrHostDoesNotExist) Error() string {
-	return fmt.Sprintf("Machine %q does not exist. Use \"crc start\" to add a new one.", e.Name)
-}
-
-type ErrDuringPreCreate struct {
-	Cause error
-}
-
-func (e ErrDuringPreCreate) Error() string {
-	return fmt.Sprintf("Error with pre-create check: %q", e.Cause)
-}
-
-type ErrHostAlreadyInState struct {
-	Name  string
-	State state.State
-}
-
-func (e ErrHostAlreadyInState) Error() string {
-	return fmt.Sprintf("Machine %q is already %s.", e.Name, strings.ToLower(e.State.String()))
-}
diff --git a/pkg/libmachine/mcnutils/utils.go b/pkg/libmachine/mcnutils/utils.go
deleted file mode 100644
index 6ad3e7690..000000000
--- a/pkg/libmachine/mcnutils/utils.go
+++ /dev/null
@@ -1,104 +0,0 @@
-package mcnutils
-
-import (
-	"crypto/rand"
-	"encoding/hex"
-	"fmt"
-	"io"
-	"os"
-	"strconv"
-	"time"
-)
-
-type MultiError struct {
-	Errs []error
-}
-
-func (e MultiError) Error() string {
-	aggregate := ""
-	for _, err := range e.Errs {
-		aggregate += err.Error() + "\n"
-	}
-	return aggregate
-}
-
-func CopyFile(src, dst string) error {
-	in, err := os.Open(src)
-	if err != nil {
-		return err
-	}
-
-	defer in.Close()
-
-	out, err := os.Create(dst)
-	if err != nil {
-		return err
-	}
-
-	defer out.Close()
-
-	if _, err = io.Copy(out, in); err != nil {
-		return err
-	}
-
-	fi, err := os.Stat(src)
-	if err != nil {
-		return err
-	}
-
-	return os.Chmod(dst, fi.Mode())
-}
-
-func WaitForSpecificOrError(f func() (bool, error), maxAttempts int, waitInterval time.Duration) error {
-	for i := 0; i < maxAttempts; i++ {
-		stop, err := f()
-		if err != nil {
-			return err
-		}
-		if stop {
-			return nil
-		}
-		time.Sleep(waitInterval)
-	}
-	return fmt.Errorf("Maximum number of retries (%d) exceeded", maxAttempts)
-}
-
-func WaitForSpecific(f func() bool, maxAttempts int, waitInterval time.Duration) error {
-	return WaitForSpecificOrError(func() (bool, error) {
-		return f(), nil
-	}, maxAttempts, waitInterval)
-}
-
-func WaitFor(f func() bool) error {
-	return WaitForSpecific(f, 60, 3*time.Second)
-}
-
-// TruncateID returns a shorten id
-// Following two functions are from github.com/docker/docker/utils module. It
-// was way overkill to include the whole module, so we just have these bits
-// that we're using here.
-func TruncateID(id string) string {
-	shortLen := 12
-	if len(id) < shortLen {
-		shortLen = len(id)
-	}
-	return id[:shortLen]
-}
-
-// GenerateRandomID returns an unique id
-func GenerateRandomID() string {
-	for {
-		id := make([]byte, 32)
-		if _, err := io.ReadFull(rand.Reader, id); err != nil {
-			panic(err) // This shouldn't happen
-		}
-		value := hex.EncodeToString(id)
-		// if we try to parse the truncated for as an int and we don't have
-		// an error then the value is all numeric and causes issues when
-		// used as a hostname. ref #3869
-		if _, err := strconv.ParseInt(TruncateID(value), 10, 64); err == nil {
-			continue
-		}
-		return value
-	}
-}
diff --git a/pkg/libmachine/persist/filestore.go b/pkg/libmachine/persist/filestore.go
index 2ee5e0b6b..9d93d1cd5 100644
--- a/pkg/libmachine/persist/filestore.go
+++ b/pkg/libmachine/persist/filestore.go
@@ -9,23 +9,18 @@ import (
 
 	log "github.com/code-ready/crc/pkg/crc/logging"
 	"github.com/code-ready/crc/pkg/libmachine/host"
-	"github.com/code-ready/crc/pkg/libmachine/mcnerror"
 )
 
 type Filestore struct {
-	Path string
+	MachinesDir string
 }
 
 func NewFilestore(path string) *Filestore {
 	return &Filestore{
-		Path: path,
+		MachinesDir: filepath.Join(path, "machines"),
 	}
 }
 
-func (s Filestore) GetMachinesDir() string {
-	return filepath.Join(s.Path, "machines")
-}
-
 func (s Filestore) saveToFile(data []byte, file string) error {
 	if _, err := os.Stat(file); os.IsNotExist(err) {
 		return ioutil.WriteFile(file, data, 0600)
@@ -59,7 +54,7 @@ func (s Filestore) Save(host *host.Host) error {
 		return err
 	}
 
-	hostPath := filepath.Join(s.GetMachinesDir(), host.Name)
+	hostPath := filepath.Join(s.MachinesDir, host.Name)
 
 	// Ensure that the directory we want to save to exists.
 	if err := os.MkdirAll(hostPath, 0700); err != nil {
@@ -70,12 +65,12 @@ func (s Filestore) Save(host *host.Host) error {
 }
 
 func (s Filestore) Remove(name string) error {
-	hostPath := filepath.Join(s.GetMachinesDir(), name)
+	hostPath := filepath.Join(s.MachinesDir, name)
 	return os.RemoveAll(hostPath)
 }
 
 func (s Filestore) SetExists(name string) error {
-	filename := filepath.Join(s.GetMachinesDir(), name, fmt.Sprintf(".%s-exist", name))
+	filename := filepath.Join(s.MachinesDir, name, fmt.Sprintf(".%s-exist", name))
 	file, err := os.OpenFile(filename, os.O_RDONLY|os.O_CREATE, 0666)
 	if err != nil {
 		return err
@@ -87,7 +82,7 @@ func (s Filestore) SetExists(name string) error {
 }
 
 func (s Filestore) Exists(name string) (bool, error) {
-	filename := filepath.Join(s.GetMachinesDir(), name, fmt.Sprintf(".%s-exist", name))
+	filename := filepath.Join(s.MachinesDir, name, fmt.Sprintf(".%s-exist", name))
 	_, err := os.Stat(filename)
 	log.Debugf("Checking file: %s", filename)
 
@@ -101,14 +96,12 @@ func (s Filestore) Exists(name string) (bool, error) {
 }
 
 func (s Filestore) Load(name string) (*host.Host, error) {
-	hostPath := filepath.Join(s.GetMachinesDir(), name)
+	hostPath := filepath.Join(s.MachinesDir, name)
 
 	if _, err := os.Stat(hostPath); os.IsNotExist(err) {
-		return nil, mcnerror.ErrHostDoesNotExist{
-			Name: name,
-		}
+		return nil, fmt.Errorf("machine %s does not exist", name)
 	}
-	data, err := ioutil.ReadFile(filepath.Join(s.GetMachinesDir(), name, "config.json"))
+	data, err := ioutil.ReadFile(filepath.Join(s.MachinesDir, name, "config.json"))
 	if err != nil {
 		return nil, err
 	}
diff --git a/pkg/libmachine/version/version.go b/pkg/libmachine/version/version.go
deleted file mode 100644
index 3cacffdb0..000000000
--- a/pkg/libmachine/version/version.go
+++ /dev/null
@@ -1,11 +0,0 @@
-package version
-
-var (
-	// APIVersion dictates which version of the libmachine API this is.
-	APIVersion = 1
-
-	// ConfigVersion dictates which version of the config.json format is
-	// used. It needs to be bumped if there is a breaking change, and
-	// therefore migration, introduced to the config file format.
-	ConfigVersion = 3
-)
diff --git a/pkg/os/util.go b/pkg/os/util.go
index 14e154e07..0554a15dd 100644
--- a/pkg/os/util.go
+++ b/pkg/os/util.go
@@ -102,3 +102,10 @@ func FileExists(path string) bool {
 	}
 	return !info.IsDir()
 }
+
+func RemoveFileIfExists(path string) error {
+	if FileExists(path) {
+		return os.Remove(path)
+	}
+	return nil
+}
diff --git a/vendor/github.com/code-ready/machine/libmachine/drivers/drivers.go b/vendor/github.com/code-ready/machine/libmachine/drivers/drivers.go
index 038addae2..c139be692 100644
--- a/vendor/github.com/code-ready/machine/libmachine/drivers/drivers.go
+++ b/vendor/github.com/code-ready/machine/libmachine/drivers/drivers.go
@@ -3,8 +3,8 @@ package drivers
 import (
 	"errors"
 
-	"github.com/code-ready/machine/libmachine/log"
 	"github.com/code-ready/machine/libmachine/state"
+	log "github.com/sirupsen/logrus"
 )
 
 // Driver defines how a host is created and controlled. Different types of
diff --git a/vendor/github.com/code-ready/machine/libmachine/drivers/plugin/localbinary/plugin.go b/vendor/github.com/code-ready/machine/libmachine/drivers/plugin/localbinary/plugin.go
index b90a57a24..bf74e72b1 100644
--- a/vendor/github.com/code-ready/machine/libmachine/drivers/plugin/localbinary/plugin.go
+++ b/vendor/github.com/code-ready/machine/libmachine/drivers/plugin/localbinary/plugin.go
@@ -10,7 +10,7 @@ import (
 	"strings"
 	"time"
 
-	"github.com/code-ready/machine/libmachine/log"
+	log "github.com/sirupsen/logrus"
 )
 
 var (
@@ -27,26 +27,6 @@ const (
 	PluginEnvDriverName = "MACHINE_PLUGIN_DRIVER_NAME"
 )
 
-type PluginStreamer interface {
-	// Return a channel for receiving the output of the stream line by
-	// line.
-	//
-	// It happens to be the case that we do this all inside of the main
-	// plugin struct today, but that may not be the case forever.
-	AttachStream(*bufio.Scanner) <-chan string
-}
-
-type PluginServer interface {
-	// Get the address where the plugin server is listening.
-	Address() (string, error)
-
-	// Serve kicks off the plugin server.
-	Serve() error
-
-	// Close shuts down the initialized server.
-	Close() error
-}
-
 type McnBinaryExecutor interface {
 	// Execute the driver plugin.  Returns scanners for plugin binary
 	// stdout and stderr.
@@ -56,13 +36,6 @@ type McnBinaryExecutor interface {
 	Close() error
 }
 
-// DriverPlugin interface wraps the underlying mechanics of starting a driver
-// plugin server and then figuring out where it can be dialed.
-type DriverPlugin interface {
-	PluginServer
-	PluginStreamer
-}
-
 type Plugin struct {
 	Executor    McnBinaryExecutor
 	Addr        string
diff --git a/vendor/github.com/code-ready/machine/libmachine/drivers/rpc/client_driver.go b/vendor/github.com/code-ready/machine/libmachine/drivers/rpc/client_driver.go
index 9df073c4c..8cab51f1c 100644
--- a/vendor/github.com/code-ready/machine/libmachine/drivers/rpc/client_driver.go
+++ b/vendor/github.com/code-ready/machine/libmachine/drivers/rpc/client_driver.go
@@ -2,16 +2,15 @@ package rpcdriver
 
 import (
 	"fmt"
+	"io"
 	"net/rpc"
 	"sync"
 	"time"
 
-	"io"
-
 	"github.com/code-ready/machine/libmachine/drivers/plugin/localbinary"
-	"github.com/code-ready/machine/libmachine/log"
 	"github.com/code-ready/machine/libmachine/state"
 	"github.com/code-ready/machine/libmachine/version"
+	log "github.com/sirupsen/logrus"
 )
 
 var (
@@ -36,7 +35,7 @@ func NewRPCClientDriverFactory() RPCClientDriverFactory {
 }
 
 type RPCClientDriver struct {
-	plugin          localbinary.DriverPlugin
+	plugin          io.Closer
 	heartbeatDoneCh chan bool
 	Client          *InternalClient
 }
@@ -117,7 +116,7 @@ func (f *DefaultRPCClientDriverFactory) NewRPCClientDriver(driverName string, dr
 	go func() {
 		if err := p.Serve(); err != nil {
 			// TODO: Is this best approach?
-			log.Warn(err)
+			log.Warnf(err.Error())
 			return
 		}
 	}()
@@ -156,7 +155,7 @@ func (f *DefaultRPCClientDriverFactory) NewRPCClientDriver(driverName string, dr
 	if serverVersion != version.APIVersion {
 		return nil, fmt.Errorf("Driver binary uses an incompatible API version (%d)", serverVersion)
 	}
-	log.Debug("Using API Version ", serverVersion)
+	log.Debugf("Using API Version %d", serverVersion)
 
 	go func(c *RPCClientDriver) {
 		for {
@@ -167,7 +166,7 @@ func (f *DefaultRPCClientDriverFactory) NewRPCClientDriver(driverName string, dr
 				if err := c.Client.Call(HeartbeatMethod, struct{}{}, nil); err != nil {
 					log.Warnf("Wrapper Docker Machine process exiting due to closed plugin server (%s)", err)
 					if err := c.close(); err != nil {
-						log.Warn(err)
+						log.Warnf(err.Error())
 					}
 				}
 			}
@@ -198,15 +197,15 @@ func (c *RPCClientDriver) close() error {
 	c.heartbeatDoneCh <- true
 	close(c.heartbeatDoneCh)
 
-	log.Debug("Making call to close driver server")
+	log.Debugf("Making call to close driver server")
 
 	if err := c.Client.Call(CloseMethod, struct{}{}, nil); err != nil {
 		log.Debugf("Failed to make call to close driver server: %s", err)
 	} else {
-		log.Debug("Successfully made call to close driver server")
+		log.Debugf("Successfully made call to close driver server")
 	}
 
-	log.Debug("Making call to close connection to plugin binary")
+	log.Debugf("Making call to close connection to plugin binary")
 
 	return c.plugin.Close()
 }
diff --git a/vendor/github.com/code-ready/machine/libmachine/log/fmt_machine_logger.go b/vendor/github.com/code-ready/machine/libmachine/log/fmt_machine_logger.go
deleted file mode 100644
index 285e69949..000000000
--- a/vendor/github.com/code-ready/machine/libmachine/log/fmt_machine_logger.go
+++ /dev/null
@@ -1,84 +0,0 @@
-package log
-
-import (
-	"fmt"
-	"io"
-	"os"
-)
-
-type FmtMachineLogger struct {
-	outWriter io.Writer
-	errWriter io.Writer
-	debug     bool
-	history   *HistoryRecorder
-}
-
-// NewFmtMachineLogger creates a MachineLogger implementation used by the drivers
-func NewFmtMachineLogger() MachineLogger {
-	return &FmtMachineLogger{
-		outWriter: os.Stdout,
-		errWriter: os.Stderr,
-		debug:     false,
-		history:   NewHistoryRecorder(),
-	}
-}
-
-func (ml *FmtMachineLogger) SetDebug(debug bool) {
-	ml.debug = debug
-}
-
-func (ml *FmtMachineLogger) SetOutWriter(out io.Writer) {
-	ml.outWriter = out
-}
-
-func (ml *FmtMachineLogger) SetErrWriter(err io.Writer) {
-	ml.errWriter = err
-}
-
-func (ml *FmtMachineLogger) Debug(args ...interface{}) {
-	ml.history.Record(args...)
-	if ml.debug {
-		fmt.Fprintln(ml.errWriter, args...)
-	}
-}
-
-func (ml *FmtMachineLogger) Debugf(fmtString string, args ...interface{}) {
-	ml.history.Recordf(fmtString, args...)
-	if ml.debug {
-		fmt.Fprintf(ml.errWriter, fmtString+"\n", args...)
-	}
-}
-
-func (ml *FmtMachineLogger) Error(args ...interface{}) {
-	ml.history.Record(args...)
-	fmt.Fprintln(ml.errWriter, args...)
-}
-
-func (ml *FmtMachineLogger) Errorf(fmtString string, args ...interface{}) {
-	ml.history.Recordf(fmtString, args...)
-	fmt.Fprintf(ml.errWriter, fmtString+"\n", args...)
-}
-
-func (ml *FmtMachineLogger) Info(args ...interface{}) {
-	ml.history.Record(args...)
-	fmt.Fprintln(ml.outWriter, args...)
-}
-
-func (ml *FmtMachineLogger) Infof(fmtString string, args ...interface{}) {
-	ml.history.Recordf(fmtString, args...)
-	fmt.Fprintf(ml.outWriter, fmtString+"\n", args...)
-}
-
-func (ml *FmtMachineLogger) Warn(args ...interface{}) {
-	ml.history.Record(args...)
-	fmt.Fprintln(ml.outWriter, args...)
-}
-
-func (ml *FmtMachineLogger) Warnf(fmtString string, args ...interface{}) {
-	ml.history.Recordf(fmtString, args...)
-	fmt.Fprintf(ml.outWriter, fmtString+"\n", args...)
-}
-
-func (ml *FmtMachineLogger) History() []string {
-	return ml.history.records
-}
diff --git a/vendor/github.com/code-ready/machine/libmachine/log/history_recorder.go b/vendor/github.com/code-ready/machine/libmachine/log/history_recorder.go
deleted file mode 100644
index defdbad69..000000000
--- a/vendor/github.com/code-ready/machine/libmachine/log/history_recorder.go
+++ /dev/null
@@ -1,34 +0,0 @@
-package log
-
-import (
-	"fmt"
-	"sync"
-)
-
-type HistoryRecorder struct {
-	lock    *sync.Mutex
-	records []string
-}
-
-func NewHistoryRecorder() *HistoryRecorder {
-	return &HistoryRecorder{
-		lock:    &sync.Mutex{},
-		records: []string{},
-	}
-}
-
-func (ml *HistoryRecorder) History() []string {
-	return ml.records
-}
-
-func (ml *HistoryRecorder) Record(args ...interface{}) {
-	ml.lock.Lock()
-	defer ml.lock.Unlock()
-	ml.records = append(ml.records, fmt.Sprint(args...))
-}
-
-func (ml *HistoryRecorder) Recordf(fmtString string, args ...interface{}) {
-	ml.lock.Lock()
-	defer ml.lock.Unlock()
-	ml.records = append(ml.records, fmt.Sprintf(fmtString, args...))
-}
diff --git a/vendor/github.com/code-ready/machine/libmachine/log/log.go b/vendor/github.com/code-ready/machine/libmachine/log/log.go
deleted file mode 100644
index 5a5823bc8..000000000
--- a/vendor/github.com/code-ready/machine/libmachine/log/log.go
+++ /dev/null
@@ -1,74 +0,0 @@
-package log
-
-import (
-	"io"
-	"regexp"
-)
-
-const redactedText = "<REDACTED>"
-
-var (
-	logger = NewFmtMachineLogger()
-
-	// (?s) enables '.' to match '\n' -- see https://golang.org/pkg/regexp/syntax/
-	certRegex = regexp.MustCompile("(?s)-----BEGIN CERTIFICATE-----.*-----END CERTIFICATE-----")
-	keyRegex  = regexp.MustCompile("(?s)-----BEGIN RSA PRIVATE KEY-----.*-----END RSA PRIVATE KEY-----")
-)
-
-func stripSecrets(original []string) []string {
-	stripped := []string{}
-	for _, line := range original {
-		line = certRegex.ReplaceAllString(line, redactedText)
-		line = keyRegex.ReplaceAllString(line, redactedText)
-		stripped = append(stripped, line)
-	}
-	return stripped
-}
-
-func Debug(args ...interface{}) {
-	logger.Debug(args...)
-}
-
-func Debugf(fmtString string, args ...interface{}) {
-	logger.Debugf(fmtString, args...)
-}
-
-func Error(args ...interface{}) {
-	logger.Error(args...)
-}
-
-func Errorf(fmtString string, args ...interface{}) {
-	logger.Errorf(fmtString, args...)
-}
-
-func Info(args ...interface{}) {
-	logger.Info(args...)
-}
-
-func Infof(fmtString string, args ...interface{}) {
-	logger.Infof(fmtString, args...)
-}
-
-func Warn(args ...interface{}) {
-	logger.Warn(args...)
-}
-
-func Warnf(fmtString string, args ...interface{}) {
-	logger.Warnf(fmtString, args...)
-}
-
-func SetDebug(debug bool) {
-	logger.SetDebug(debug)
-}
-
-func SetOutWriter(out io.Writer) {
-	logger.SetOutWriter(out)
-}
-
-func SetErrWriter(err io.Writer) {
-	logger.SetErrWriter(err)
-}
-
-func History() []string {
-	return stripSecrets(logger.History())
-}
diff --git a/vendor/github.com/code-ready/machine/libmachine/log/machine_logger.go b/vendor/github.com/code-ready/machine/libmachine/log/machine_logger.go
deleted file mode 100644
index 19f613e23..000000000
--- a/vendor/github.com/code-ready/machine/libmachine/log/machine_logger.go
+++ /dev/null
@@ -1,24 +0,0 @@
-package log
-
-import "io"
-
-type MachineLogger interface {
-	SetDebug(debug bool)
-
-	SetOutWriter(io.Writer)
-	SetErrWriter(io.Writer)
-
-	Debug(args ...interface{})
-	Debugf(fmtString string, args ...interface{})
-
-	Error(args ...interface{})
-	Errorf(fmtString string, args ...interface{})
-
-	Info(args ...interface{})
-	Infof(fmtString string, args ...interface{})
-
-	Warn(args ...interface{})
-	Warnf(fmtString string, args ...interface{})
-
-	History() []string
-}
diff --git a/vendor/github.com/code-ready/machine/libmachine/version/version.go b/vendor/github.com/code-ready/machine/libmachine/version/version.go
index 3cacffdb0..801e1a3ab 100644
--- a/vendor/github.com/code-ready/machine/libmachine/version/version.go
+++ b/vendor/github.com/code-ready/machine/libmachine/version/version.go
@@ -3,9 +3,4 @@ package version
 var (
 	// APIVersion dictates which version of the libmachine API this is.
 	APIVersion = 1
-
-	// ConfigVersion dictates which version of the config.json format is
-	// used. It needs to be bumped if there is a breaking change, and
-	// therefore migration, introduced to the config file format.
-	ConfigVersion = 3
 )
diff --git a/vendor/gopkg.in/yaml.v3/.travis.yml b/vendor/gopkg.in/yaml.v3/.travis.yml
deleted file mode 100644
index 04d4dae09..000000000
--- a/vendor/gopkg.in/yaml.v3/.travis.yml
+++ /dev/null
@@ -1,16 +0,0 @@
-language: go
-
-go:
-    - "1.4.x"
-    - "1.5.x"
-    - "1.6.x"
-    - "1.7.x"
-    - "1.8.x"
-    - "1.9.x"
-    - "1.10.x"
-    - "1.11.x"
-    - "1.12.x"
-    - "1.13.x"
-    - "tip"
-
-go_import_path: gopkg.in/yaml.v3
diff --git a/vendor/gopkg.in/yaml.v3/apic.go b/vendor/gopkg.in/yaml.v3/apic.go
index 65846e674..ae7d049f1 100644
--- a/vendor/gopkg.in/yaml.v3/apic.go
+++ b/vendor/gopkg.in/yaml.v3/apic.go
@@ -108,6 +108,7 @@ func yaml_emitter_initialize(emitter *yaml_emitter_t) {
 		raw_buffer: make([]byte, 0, output_raw_buffer_size),
 		states:     make([]yaml_emitter_state_t, 0, initial_stack_size),
 		events:     make([]yaml_event_t, 0, initial_queue_size),
+		best_width: -1,
 	}
 }
 
diff --git a/vendor/gopkg.in/yaml.v3/decode.go b/vendor/gopkg.in/yaml.v3/decode.go
index be63169b7..df36e3a30 100644
--- a/vendor/gopkg.in/yaml.v3/decode.go
+++ b/vendor/gopkg.in/yaml.v3/decode.go
@@ -35,6 +35,7 @@ type parser struct {
 	doc      *Node
 	anchors  map[string]*Node
 	doneInit bool
+	textless bool
 }
 
 func newParser(b []byte) *parser {
@@ -108,14 +109,18 @@ func (p *parser) peek() yaml_event_type_t {
 func (p *parser) fail() {
 	var where string
 	var line int
-	if p.parser.problem_mark.line != 0 {
+	if p.parser.context_mark.line != 0 {
+		line = p.parser.context_mark.line
+		// Scanner errors don't iterate line before returning error
+		if p.parser.error == yaml_SCANNER_ERROR {
+			line++
+		}
+	} else if p.parser.problem_mark.line != 0 {
 		line = p.parser.problem_mark.line
 		// Scanner errors don't iterate line before returning error
 		if p.parser.error == yaml_SCANNER_ERROR {
 			line++
 		}
-	} else if p.parser.context_mark.line != 0 {
-		line = p.parser.context_mark.line
 	}
 	if line != 0 {
 		where = "line " + strconv.Itoa(line) + ": "
@@ -169,17 +174,20 @@ func (p *parser) node(kind Kind, defaultTag, tag, value string) *Node {
 	} else if kind == ScalarNode {
 		tag, _ = resolve("", value)
 	}
-	return &Node{
-		Kind:        kind,
-		Tag:         tag,
-		Value:       value,
-		Style:       style,
-		Line:        p.event.start_mark.line + 1,
-		Column:      p.event.start_mark.column + 1,
-		HeadComment: string(p.event.head_comment),
-		LineComment: string(p.event.line_comment),
-		FootComment: string(p.event.foot_comment),
+	n := &Node{
+		Kind:  kind,
+		Tag:   tag,
+		Value: value,
+		Style: style,
+	}
+	if !p.textless {
+		n.Line = p.event.start_mark.line + 1
+		n.Column = p.event.start_mark.column + 1
+		n.HeadComment = string(p.event.head_comment)
+		n.LineComment = string(p.event.line_comment)
+		n.FootComment = string(p.event.foot_comment)
 	}
+	return n
 }
 
 func (p *parser) parseChild(parent *Node) *Node {
@@ -497,8 +505,13 @@ func (d *decoder) unmarshal(n *Node, out reflect.Value) (good bool) {
 		good = d.mapping(n, out)
 	case SequenceNode:
 		good = d.sequence(n, out)
+	case 0:
+		if n.IsZero() {
+			return d.null(out)
+		}
+		fallthrough
 	default:
-		panic("internal error: unknown node kind: " + strconv.Itoa(int(n.Kind)))
+		failf("cannot decode node with unknown kind %d", n.Kind)
 	}
 	return good
 }
@@ -533,6 +546,17 @@ func resetMap(out reflect.Value) {
 	}
 }
 
+func (d *decoder) null(out reflect.Value) bool {
+	if out.CanAddr() {
+		switch out.Kind() {
+		case reflect.Interface, reflect.Ptr, reflect.Map, reflect.Slice:
+			out.Set(reflect.Zero(out.Type()))
+			return true
+		}
+	}
+	return false
+}
+
 func (d *decoder) scalar(n *Node, out reflect.Value) bool {
 	var tag string
 	var resolved interface{}
@@ -550,14 +574,7 @@ func (d *decoder) scalar(n *Node, out reflect.Value) bool {
 		}
 	}
 	if resolved == nil {
-		if out.CanAddr() {
-			switch out.Kind() {
-			case reflect.Interface, reflect.Ptr, reflect.Map, reflect.Slice:
-				out.Set(reflect.Zero(out.Type()))
-				return true
-			}
-		}
-		return false
+		return d.null(out)
 	}
 	if resolvedv := reflect.ValueOf(resolved); out.Type() == resolvedv.Type() {
 		// We've resolved to exactly the type we want, so use that.
@@ -791,8 +808,10 @@ func (d *decoder) mapping(n *Node, out reflect.Value) (good bool) {
 		}
 	}
 
+	mapIsNew := false
 	if out.IsNil() {
 		out.Set(reflect.MakeMap(outt))
+		mapIsNew = true
 	}
 	for i := 0; i < l; i += 2 {
 		if isMerge(n.Content[i]) {
@@ -809,7 +828,7 @@ func (d *decoder) mapping(n *Node, out reflect.Value) (good bool) {
 				failf("invalid map key: %#v", k.Interface())
 			}
 			e := reflect.New(et).Elem()
-			if d.unmarshal(n.Content[i+1], e) {
+			if d.unmarshal(n.Content[i+1], e) || n.Content[i+1].ShortTag() == nullTag && (mapIsNew || !out.MapIndex(k).IsValid()) {
 				out.SetMapIndex(k, e)
 			}
 		}
diff --git a/vendor/gopkg.in/yaml.v3/emitterc.go b/vendor/gopkg.in/yaml.v3/emitterc.go
index ab2a06619..0f47c9ca8 100644
--- a/vendor/gopkg.in/yaml.v3/emitterc.go
+++ b/vendor/gopkg.in/yaml.v3/emitterc.go
@@ -235,10 +235,13 @@ func yaml_emitter_increase_indent(emitter *yaml_emitter_t, flow, indentless bool
 			emitter.indent = 0
 		}
 	} else if !indentless {
-		emitter.indent += emitter.best_indent
-		// [Go] If inside a block sequence item, discount the space taken by the indicator.
-		if emitter.best_indent > 2 && emitter.states[len(emitter.states)-1] == yaml_EMIT_BLOCK_SEQUENCE_ITEM_STATE {
-			emitter.indent -= 2
+		// [Go] This was changed so that indentations are more regular.
+		if emitter.states[len(emitter.states)-1] == yaml_EMIT_BLOCK_SEQUENCE_ITEM_STATE {
+			// The first indent inside a sequence will just skip the "- " indicator.
+			emitter.indent += 2
+		} else {
+			// Everything else aligns to the chosen indentation.
+			emitter.indent = emitter.best_indent*((emitter.indent+emitter.best_indent)/emitter.best_indent)
 		}
 	}
 	return true
@@ -725,16 +728,9 @@ func yaml_emitter_emit_flow_mapping_value(emitter *yaml_emitter_t, event *yaml_e
 // Expect a block item node.
 func yaml_emitter_emit_block_sequence_item(emitter *yaml_emitter_t, event *yaml_event_t, first bool) bool {
 	if first {
-		// [Go] The original logic here would not indent the sequence when inside a mapping.
-		// In Go we always indent it, but take the sequence indicator out of the indentation.
-		indentless := emitter.best_indent == 2 && emitter.mapping_context && (emitter.column == 0 || !emitter.indention)
-		original := emitter.indent
-		if !yaml_emitter_increase_indent(emitter, false, indentless) {
+		if !yaml_emitter_increase_indent(emitter, false, false) {
 			return false
 		}
-		if emitter.indent > original+2 {
-			emitter.indent -= 2
-		}
 	}
 	if event.typ == yaml_SEQUENCE_END_EVENT {
 		emitter.indent = emitter.indents[len(emitter.indents)-1]
@@ -785,6 +781,13 @@ func yaml_emitter_emit_block_mapping_key(emitter *yaml_emitter_t, event *yaml_ev
 	if !yaml_emitter_write_indent(emitter) {
 		return false
 	}
+	if len(emitter.line_comment) > 0 {
+		// [Go] A line comment was provided for the key. That's unusual as the
+		//      scanner associates line comments with the value. Either way,
+		//      save the line comment and render it appropriately later.
+		emitter.key_line_comment = emitter.line_comment
+		emitter.line_comment = nil
+	}
 	if yaml_emitter_check_simple_key(emitter) {
 		emitter.states = append(emitter.states, yaml_EMIT_BLOCK_MAPPING_SIMPLE_VALUE_STATE)
 		return yaml_emitter_emit_node(emitter, event, false, false, true, true)
@@ -810,6 +813,27 @@ func yaml_emitter_emit_block_mapping_value(emitter *yaml_emitter_t, event *yaml_
 			return false
 		}
 	}
+	if len(emitter.key_line_comment) > 0 {
+		// [Go] Line comments are generally associated with the value, but when there's
+		//      no value on the same line as a mapping key they end up attached to the
+		//      key itself.
+		if event.typ == yaml_SCALAR_EVENT {
+			if len(emitter.line_comment) == 0 {
+				// A scalar is coming and it has no line comments by itself yet,
+				// so just let it handle the line comment as usual. If it has a
+				// line comment, we can't have both so the one from the key is lost.
+				emitter.line_comment = emitter.key_line_comment
+				emitter.key_line_comment = nil
+			}
+		} else if event.sequence_style() != yaml_FLOW_SEQUENCE_STYLE && (event.typ == yaml_MAPPING_START_EVENT || event.typ == yaml_SEQUENCE_START_EVENT) {
+			// An indented block follows, so write the comment right now.
+			emitter.line_comment, emitter.key_line_comment = emitter.key_line_comment, emitter.line_comment
+			if !yaml_emitter_process_line_comment(emitter) {
+				return false
+			}
+			emitter.line_comment, emitter.key_line_comment = emitter.key_line_comment, emitter.line_comment
+		}
+	}
 	emitter.states = append(emitter.states, yaml_EMIT_BLOCK_MAPPING_KEY_STATE)
 	if !yaml_emitter_emit_node(emitter, event, false, false, true, false) {
 		return false
@@ -823,6 +847,10 @@ func yaml_emitter_emit_block_mapping_value(emitter *yaml_emitter_t, event *yaml_
 	return true
 }
 
+func yaml_emitter_silent_nil_event(emitter *yaml_emitter_t, event *yaml_event_t) bool {
+	return event.typ == yaml_SCALAR_EVENT && event.implicit && !emitter.canonical && len(emitter.scalar_data.value) == 0
+}
+
 // Expect a node.
 func yaml_emitter_emit_node(emitter *yaml_emitter_t, event *yaml_event_t,
 	root bool, sequence bool, mapping bool, simple_key bool) bool {
@@ -1866,7 +1894,7 @@ func yaml_emitter_write_literal_scalar(emitter *yaml_emitter_t, value []byte) bo
 	if !yaml_emitter_write_block_scalar_hints(emitter, value) {
 		return false
 	}
-	if !put_break(emitter) {
+	if !yaml_emitter_process_line_comment(emitter) {
 		return false
 	}
 	//emitter.indention = true
@@ -1903,10 +1931,10 @@ func yaml_emitter_write_folded_scalar(emitter *yaml_emitter_t, value []byte) boo
 	if !yaml_emitter_write_block_scalar_hints(emitter, value) {
 		return false
 	}
-
-	if !put_break(emitter) {
+	if !yaml_emitter_process_line_comment(emitter) {
 		return false
 	}
+
 	//emitter.indention = true
 	emitter.whitespace = true
 
diff --git a/vendor/gopkg.in/yaml.v3/encode.go b/vendor/gopkg.in/yaml.v3/encode.go
index 1f37271ce..de9e72a3e 100644
--- a/vendor/gopkg.in/yaml.v3/encode.go
+++ b/vendor/gopkg.in/yaml.v3/encode.go
@@ -119,6 +119,14 @@ func (e *encoder) marshal(tag string, in reflect.Value) {
 	case *Node:
 		e.nodev(in)
 		return
+	case Node:
+		if !in.CanAddr() {
+			var n = reflect.New(in.Type()).Elem()
+			n.Set(in)
+			in = n
+		}
+		e.nodev(in.Addr())
+		return
 	case time.Time:
 		e.timev(tag, in)
 		return
@@ -422,18 +430,23 @@ func (e *encoder) nodev(in reflect.Value) {
 }
 
 func (e *encoder) node(node *Node, tail string) {
+	// Zero nodes behave as nil.
+	if node.Kind == 0 && node.IsZero() {
+		e.nilv()
+		return
+	}
+
 	// If the tag was not explicitly requested, and dropping it won't change the
 	// implicit tag of the value, don't include it in the presentation.
 	var tag = node.Tag
 	var stag = shortTag(tag)
-	var rtag string
 	var forceQuoting bool
 	if tag != "" && node.Style&TaggedStyle == 0 {
 		if node.Kind == ScalarNode {
 			if stag == strTag && node.Style&(SingleQuotedStyle|DoubleQuotedStyle|LiteralStyle|FoldedStyle) != 0 {
 				tag = ""
 			} else {
-				rtag, _ = resolve("", node.Value)
+				rtag, _ := resolve("", node.Value)
 				if rtag == stag {
 					tag = ""
 				} else if stag == strTag {
@@ -442,6 +455,7 @@ func (e *encoder) node(node *Node, tail string) {
 				}
 			}
 		} else {
+			var rtag string
 			switch node.Kind {
 			case MappingNode:
 				rtag = mapTag
@@ -471,7 +485,7 @@ func (e *encoder) node(node *Node, tail string) {
 		if node.Style&FlowStyle != 0 {
 			style = yaml_FLOW_SEQUENCE_STYLE
 		}
-		e.must(yaml_sequence_start_event_initialize(&e.event, []byte(node.Anchor), []byte(tag), tag == "", style))
+		e.must(yaml_sequence_start_event_initialize(&e.event, []byte(node.Anchor), []byte(longTag(tag)), tag == "", style))
 		e.event.head_comment = []byte(node.HeadComment)
 		e.emit()
 		for _, node := range node.Content {
@@ -487,7 +501,7 @@ func (e *encoder) node(node *Node, tail string) {
 		if node.Style&FlowStyle != 0 {
 			style = yaml_FLOW_MAPPING_STYLE
 		}
-		yaml_mapping_start_event_initialize(&e.event, []byte(node.Anchor), []byte(tag), tag == "", style)
+		yaml_mapping_start_event_initialize(&e.event, []byte(node.Anchor), []byte(longTag(tag)), tag == "", style)
 		e.event.tail_comment = []byte(tail)
 		e.event.head_comment = []byte(node.HeadComment)
 		e.emit()
@@ -528,11 +542,11 @@ func (e *encoder) node(node *Node, tail string) {
 	case ScalarNode:
 		value := node.Value
 		if !utf8.ValidString(value) {
-			if tag == binaryTag {
+			if stag == binaryTag {
 				failf("explicitly tagged !!binary data must be base64-encoded")
 			}
-			if tag != "" {
-				failf("cannot marshal invalid UTF-8 data as %s", shortTag(tag))
+			if stag != "" {
+				failf("cannot marshal invalid UTF-8 data as %s", stag)
 			}
 			// It can't be encoded directly as YAML so use a binary tag
 			// and encode it as base64.
@@ -557,5 +571,7 @@ func (e *encoder) node(node *Node, tail string) {
 		}
 
 		e.emitScalar(value, node.Anchor, tag, style, []byte(node.HeadComment), []byte(node.LineComment), []byte(node.FootComment), []byte(tail))
+	default:
+		failf("cannot encode node with unknown kind %d", node.Kind)
 	}
 }
diff --git a/vendor/gopkg.in/yaml.v3/parserc.go b/vendor/gopkg.in/yaml.v3/parserc.go
index aea9050b8..ac66fccc0 100644
--- a/vendor/gopkg.in/yaml.v3/parserc.go
+++ b/vendor/gopkg.in/yaml.v3/parserc.go
@@ -648,6 +648,10 @@ func yaml_parser_parse_node(parser *yaml_parser_t, event *yaml_event_t, block, i
 			implicit:   implicit,
 			style:      yaml_style_t(yaml_BLOCK_MAPPING_STYLE),
 		}
+		if parser.stem_comment != nil {
+			event.head_comment = parser.stem_comment
+			parser.stem_comment = nil
+		}
 		return true
 	}
 	if len(anchor) > 0 || len(tag) > 0 {
@@ -694,25 +698,13 @@ func yaml_parser_parse_block_sequence_entry(parser *yaml_parser_t, event *yaml_e
 
 	if token.typ == yaml_BLOCK_ENTRY_TOKEN {
 		mark := token.end_mark
-		prior_head := len(parser.head_comment)
+		prior_head_len := len(parser.head_comment)
 		skip_token(parser)
+		yaml_parser_split_stem_comment(parser, prior_head_len)
 		token = peek_token(parser)
 		if token == nil {
 			return false
 		}
-		if prior_head > 0 && token.typ == yaml_BLOCK_SEQUENCE_START_TOKEN {
-			// [Go] It's a sequence under a sequence entry, so the former head comment
-			//      is for the list itself, not the first list item under it.
-			parser.stem_comment = parser.head_comment[:prior_head]
-			if len(parser.head_comment) == prior_head {
-				parser.head_comment = nil
-			} else {
-				// Copy suffix to prevent very strange bugs if someone ever appends
-				// further bytes to the prefix in the stem_comment slice above.
-				parser.head_comment = append([]byte(nil), parser.head_comment[prior_head+1:]...)
-			}
-
-		}
 		if token.typ != yaml_BLOCK_ENTRY_TOKEN && token.typ != yaml_BLOCK_END_TOKEN {
 			parser.states = append(parser.states, yaml_PARSE_BLOCK_SEQUENCE_ENTRY_STATE)
 			return yaml_parser_parse_node(parser, event, true, false)
@@ -754,7 +746,9 @@ func yaml_parser_parse_indentless_sequence_entry(parser *yaml_parser_t, event *y
 
 	if token.typ == yaml_BLOCK_ENTRY_TOKEN {
 		mark := token.end_mark
+		prior_head_len := len(parser.head_comment)
 		skip_token(parser)
+		yaml_parser_split_stem_comment(parser, prior_head_len)
 		token = peek_token(parser)
 		if token == nil {
 			return false
@@ -780,6 +774,32 @@ func yaml_parser_parse_indentless_sequence_entry(parser *yaml_parser_t, event *y
 	return true
 }
 
+// Split stem comment from head comment.
+//
+// When a sequence or map is found under a sequence entry, the former head comment
+// is assigned to the underlying sequence or map as a whole, not the individual
+// sequence or map entry as would be expected otherwise. To handle this case the
+// previous head comment is moved aside as the stem comment.
+func yaml_parser_split_stem_comment(parser *yaml_parser_t, stem_len int) {
+	if stem_len == 0 {
+		return
+	}
+
+	token := peek_token(parser)
+	if token.typ != yaml_BLOCK_SEQUENCE_START_TOKEN && token.typ != yaml_BLOCK_MAPPING_START_TOKEN {
+		return
+	}
+
+	parser.stem_comment = parser.head_comment[:stem_len]
+	if len(parser.head_comment) == stem_len {
+		parser.head_comment = nil
+	} else {
+		// Copy suffix to prevent very strange bugs if someone ever appends
+		// further bytes to the prefix in the stem_comment slice above.
+		parser.head_comment = append([]byte(nil), parser.head_comment[stem_len+1:]...)
+	}
+}
+
 // Parse the productions:
 // block_mapping        ::= BLOCK-MAPPING_START
 //                          *******************
diff --git a/vendor/gopkg.in/yaml.v3/scannerc.go b/vendor/gopkg.in/yaml.v3/scannerc.go
index 57e954ca5..ca0070108 100644
--- a/vendor/gopkg.in/yaml.v3/scannerc.go
+++ b/vendor/gopkg.in/yaml.v3/scannerc.go
@@ -749,6 +749,11 @@ func yaml_parser_fetch_next_token(parser *yaml_parser_t) (ok bool) {
 		if !ok {
 			return
 		}
+		if len(parser.tokens) > 0 && parser.tokens[len(parser.tokens)-1].typ == yaml_BLOCK_ENTRY_TOKEN {
+			// Sequence indicators alone have no line comments. It becomes
+			// a head comment for whatever follows.
+			return
+		}
 		if !yaml_parser_scan_line_comment(parser, comment_mark) {
 			ok = false
 			return
@@ -2255,10 +2260,9 @@ func yaml_parser_scan_block_scalar(parser *yaml_parser_t, token *yaml_token_t, l
 		}
 	}
 	if parser.buffer[parser.buffer_pos] == '#' {
-		// TODO Test this and then re-enable it.
-		//if !yaml_parser_scan_line_comment(parser, start_mark) {
-		//	return false
-		//}
+		if !yaml_parser_scan_line_comment(parser, start_mark) {
+			return false
+		}
 		for !is_breakz(parser.buffer, parser.buffer_pos) {
 			skip(parser)
 			if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
@@ -2856,13 +2860,12 @@ func yaml_parser_scan_line_comment(parser *yaml_parser_t, token_mark yaml_mark_t
 						return false
 					}
 					skip_line(parser)
-				} else {
-					if parser.mark.index >= seen {
-						if len(text) == 0 {
-							start_mark = parser.mark
-						}
-						text = append(text, parser.buffer[parser.buffer_pos])
+				} else if parser.mark.index >= seen {
+					if len(text) == 0 {
+						start_mark = parser.mark
 					}
+					text = read(parser, text)
+				} else {
 					skip(parser)
 				}
 			}
@@ -2888,6 +2891,10 @@ func yaml_parser_scan_comments(parser *yaml_parser_t, scan_mark yaml_mark_t) boo
 
 	var token_mark = token.start_mark
 	var start_mark yaml_mark_t
+	var next_indent = parser.indent
+	if next_indent < 0 {
+		next_indent = 0
+	}
 
 	var recent_empty = false
 	var first_empty = parser.newlines <= 1
@@ -2919,15 +2926,18 @@ func yaml_parser_scan_comments(parser *yaml_parser_t, scan_mark yaml_mark_t) boo
 			continue
 		}
 		c := parser.buffer[parser.buffer_pos+peek]
-		if is_breakz(parser.buffer, parser.buffer_pos+peek) || parser.flow_level > 0 && (c == ']' || c == '}') {
+		var close_flow = parser.flow_level > 0 && (c == ']' || c == '}')
+		if close_flow || is_breakz(parser.buffer, parser.buffer_pos+peek) {
 			// Got line break or terminator.
-			if !recent_empty {
-				if first_empty && (start_mark.line == foot_line || start_mark.column-1 < parser.indent) {
+			if close_flow || !recent_empty {
+				if close_flow || first_empty && (start_mark.line == foot_line && token.typ != yaml_VALUE_TOKEN || start_mark.column-1 < next_indent) {
 					// This is the first empty line and there were no empty lines before,
 					// so this initial part of the comment is a foot of the prior token
 					// instead of being a head for the following one. Split it up.
+					// Alternatively, this might also be the last comment inside a flow
+					// scope, so it must be a footer.
 					if len(text) > 0 {
-						if start_mark.column-1 < parser.indent {
+						if start_mark.column-1 < next_indent {
 							// If dedented it's unrelated to the prior token.
 							token_mark = start_mark
 						}
@@ -2958,7 +2968,7 @@ func yaml_parser_scan_comments(parser *yaml_parser_t, scan_mark yaml_mark_t) boo
 			continue
 		}
 
-		if len(text) > 0 && column < parser.indent+1 && column != start_mark.column {
+		if len(text) > 0 && (close_flow || column-1 < next_indent && column != start_mark.column) {
 			// The comment at the different indentation is a foot of the
 			// preceding data rather than a head of the upcoming one.
 			parser.comments = append(parser.comments, yaml_comment_t{
@@ -2999,10 +3009,9 @@ func yaml_parser_scan_comments(parser *yaml_parser_t, scan_mark yaml_mark_t) boo
 					return false
 				}
 				skip_line(parser)
+			} else if parser.mark.index >= seen {
+				text = read(parser, text)
 			} else {
-				if parser.mark.index >= seen {
-					text = append(text, parser.buffer[parser.buffer_pos])
-				}
 				skip(parser)
 			}
 		}
@@ -3010,6 +3019,10 @@ func yaml_parser_scan_comments(parser *yaml_parser_t, scan_mark yaml_mark_t) boo
 		peek = 0
 		column = 0
 		line = parser.mark.line
+		next_indent = parser.indent
+		if next_indent < 0 {
+			next_indent = 0
+		}
 	}
 
 	if len(text) > 0 {
diff --git a/vendor/gopkg.in/yaml.v3/yaml.go b/vendor/gopkg.in/yaml.v3/yaml.go
index b5d35a50d..8cec6da48 100644
--- a/vendor/gopkg.in/yaml.v3/yaml.go
+++ b/vendor/gopkg.in/yaml.v3/yaml.go
@@ -89,7 +89,7 @@ func Unmarshal(in []byte, out interface{}) (err error) {
 	return unmarshal(in, out, false)
 }
 
-// A Decorder reads and decodes YAML values from an input stream.
+// A Decoder reads and decodes YAML values from an input stream.
 type Decoder struct {
 	parser      *parser
 	knownFields bool
@@ -194,7 +194,7 @@ func unmarshal(in []byte, out interface{}, strict bool) (err error) {
 //                  Zero valued structs will be omitted if all their public
 //                  fields are zero, unless they implement an IsZero
 //                  method (see the IsZeroer interface type), in which
-//                  case the field will be included if that method returns true.
+//                  case the field will be excluded if IsZero returns true.
 //
 //     flow         Marshal using a flow style (useful for structs,
 //                  sequences and maps).
@@ -252,6 +252,24 @@ func (e *Encoder) Encode(v interface{}) (err error) {
 	return nil
 }
 
+// Encode encodes value v and stores its representation in n.
+//
+// See the documentation for Marshal for details about the
+// conversion of Go values into YAML.
+func (n *Node) Encode(v interface{}) (err error) {
+	defer handleErr(&err)
+	e := newEncoder()
+	defer e.destroy()
+	e.marshalDoc("", reflect.ValueOf(v))
+	e.finish()
+	p := newParser(e.out)
+	p.textless = true
+	defer p.destroy()
+	doc := p.parse()
+	*n = *doc.Content[0]
+	return nil
+}
+
 // SetIndent changes the used indentation used when encoding.
 func (e *Encoder) SetIndent(spaces int) {
 	if spaces < 0 {
@@ -328,6 +346,12 @@ const (
 // and maps, Node is an intermediate representation that allows detailed
 // control over the content being decoded or encoded.
 //
+// It's worth noting that although Node offers access into details such as
+// line numbers, colums, and comments, the content when re-encoded will not
+// have its original textual representation preserved. An effort is made to
+// render the data plesantly, and to preserve comments near the data they
+// describe, though.
+//
 // Values that make use of the Node type interact with the yaml package in the
 // same way any other type would do, by encoding and decoding yaml data
 // directly or indirectly into them.
@@ -391,6 +415,13 @@ type Node struct {
 	Column int
 }
 
+// IsZero returns whether the node has all of its fields unset.
+func (n *Node) IsZero() bool {
+	return n.Kind == 0 && n.Style == 0 && n.Tag == "" && n.Value == "" && n.Anchor == "" && n.Alias == nil && n.Content == nil &&
+		n.HeadComment == "" && n.LineComment == "" && n.FootComment == "" && n.Line == 0 && n.Column == 0
+}
+
+
 // LongTag returns the long form of the tag that indicates the data type for
 // the node. If the Tag field isn't explicitly defined, one will be computed
 // based on the node properties.
@@ -418,6 +449,11 @@ func (n *Node) ShortTag() string {
 		case ScalarNode:
 			tag, _ := resolve("", n.Value)
 			return tag
+		case 0:
+			// Special case to make the zero value convenient.
+			if n.IsZero() {
+				return nullTag
+			}
 		}
 		return ""
 	}
diff --git a/vendor/gopkg.in/yaml.v3/yamlh.go b/vendor/gopkg.in/yaml.v3/yamlh.go
index 2719cfbb0..7c6d00770 100644
--- a/vendor/gopkg.in/yaml.v3/yamlh.go
+++ b/vendor/gopkg.in/yaml.v3/yamlh.go
@@ -787,6 +787,8 @@ type yaml_emitter_t struct {
 	foot_comment []byte
 	tail_comment []byte
 
+	key_line_comment []byte
+
 	// Dumper stuff
 
 	opened bool // If the stream was already opened?
diff --git a/vendor/modules.txt b/vendor/modules.txt
index 97f56d23b..aa91cdf2b 100644
--- a/vendor/modules.txt
+++ b/vendor/modules.txt
@@ -40,14 +40,13 @@ github.com/code-ready/gvisor-tap-vsock/pkg/tap
 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/code-ready/machine v0.0.0-20201202090222-9558ae8c05b9
+# github.com/code-ready/machine v0.0.0-20210122113819-281ccfbb4566
 ## explicit
 github.com/code-ready/machine/drivers/hyperkit
 github.com/code-ready/machine/drivers/libvirt
 github.com/code-ready/machine/libmachine/drivers
 github.com/code-ready/machine/libmachine/drivers/plugin/localbinary
 github.com/code-ready/machine/libmachine/drivers/rpc
-github.com/code-ready/machine/libmachine/log
 github.com/code-ready/machine/libmachine/state
 github.com/code-ready/machine/libmachine/version
 # github.com/cucumber/gherkin-go/v11 v11.0.0
@@ -219,7 +218,7 @@ github.com/spf13/pflag
 # github.com/spf13/viper v1.7.1
 ## explicit
 github.com/spf13/viper
-# github.com/stretchr/testify v1.6.1
+# github.com/stretchr/testify v1.7.0
 ## explicit
 github.com/stretchr/testify/assert
 github.com/stretchr/testify/require
@@ -336,7 +335,7 @@ gopkg.in/ini.v1
 # gopkg.in/yaml.v2 v2.4.0
 ## explicit
 gopkg.in/yaml.v2
-# gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c
+# gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b
 gopkg.in/yaml.v3
 # gvisor.dev/gvisor v0.0.0-20201024190640-a58d741adc72
 gvisor.dev/gvisor/pkg/gohacks


Test patch:
diff --git a/pkg/crc/api/api_test.go b/pkg/crc/api/api_test.go
index d96231958..4811efa4f 100644
--- a/pkg/crc/api/api_test.go
+++ b/pkg/crc/api/api_test.go
@@ -11,13 +11,13 @@ import (
 	"strings"
 	"testing"
 
-	"github.com/code-ready/crc/pkg/crc/machine"
-
 	cmdConfig "github.com/code-ready/crc/cmd/crc/cmd/config"
 	"github.com/code-ready/crc/pkg/crc/config"
+	"github.com/code-ready/crc/pkg/crc/machine"
 	"github.com/code-ready/crc/pkg/crc/machine/fakemachine"
 	"github.com/code-ready/crc/pkg/crc/preflight"
 	"github.com/code-ready/crc/pkg/crc/version"
+	log "github.com/sirupsen/logrus"
 	"github.com/stretchr/testify/assert"
 	"github.com/stretchr/testify/require"
 )
@@ -32,11 +32,15 @@ func TestApi(t *testing.T) {
 	require.NoError(t, err)
 
 	client := fakemachine.NewClient()
-	api, err := createAPIServerWithListener(listener, setupNewInMemoryConfig, func(_ config.Storage) machine.Client {
+	api, err := createServerWithListener(listener, setupNewInMemoryConfig, func(_ config.Storage) machine.Client {
 		return client
 	})
 	require.NoError(t, err)
-	go api.Serve()
+	go func() {
+		if err := api.Serve(); err != nil {
+			log.Error(err)
+		}
+	}()
 
 	tt := []struct {
 		command       string
@@ -217,11 +221,15 @@ func setupAPIServer(t *testing.T) (string, func()) {
 	require.NoError(t, err)
 
 	client := fakemachine.NewClient()
-	api, err := createAPIServerWithListener(listener, setupNewInMemoryConfig, func(_ config.Storage) machine.Client {
+	api, err := createServerWithListener(listener, setupNewInMemoryConfig, func(_ config.Storage) machine.Client {
 		return client
 	})
 	require.NoError(t, err)
-	go api.Serve()
+	go func() {
+		if err := api.Serve(); err != nil {
+			log.Error(err)
+		}
+	}()
 
 	return socket, func() { os.RemoveAll(dir) }
 }
diff --git a/pkg/crc/preflight/preflight_windows_test.go b/pkg/crc/preflight/preflight_windows_test.go
index cd4091389..37ba75340 100644
--- a/pkg/crc/preflight/preflight_windows_test.go
+++ b/pkg/crc/preflight/preflight_windows_test.go
@@ -16,8 +16,8 @@ func TestCountConfigurationOptions(t *testing.T) {
 
 func TestCountPreflights(t *testing.T) {
 	assert.Len(t, getPreflightChecks(false, network.DefaultMode), 15)
-	assert.Len(t, getPreflightChecks(true, network.DefaultMode), 19)
+	assert.Len(t, getPreflightChecks(true, network.DefaultMode), 18)
 
 	assert.Len(t, getPreflightChecks(false, network.VSockMode), 16)
-	assert.Len(t, getPreflightChecks(true, network.VSockMode), 20)
+	assert.Len(t, getPreflightChecks(true, network.VSockMode), 19)
 }
diff --git a/pkg/libmachine/mcnutils/utils_test.go b/pkg/drivers/hyperv/copy_test.go
similarity index 51%
rename from pkg/libmachine/mcnutils/utils_test.go
rename to pkg/drivers/hyperv/copy_test.go
index e447b41db..21d586942 100644
--- a/pkg/libmachine/mcnutils/utils_test.go
+++ b/pkg/drivers/hyperv/copy_test.go
@@ -1,4 +1,4 @@
-package mcnutils
+package hyperv
 
 import (
 	"io/ioutil"
@@ -38,7 +38,7 @@ func TestCopyFile(t *testing.T) {
 
 	destFilePath := filepath.Join(os.TempDir(), destFi.Name())
 
-	if err := CopyFile(srcFilePath, destFilePath); err != nil {
+	if err := copyFile(srcFilePath, destFilePath); err != nil {
 		t.Fatal(err)
 	}
 
@@ -51,35 +51,3 @@ func TestCopyFile(t *testing.T) {
 		t.Fatalf("expected data \"%s\"; received \"%s\"", testStr, string(data))
 	}
 }
-
-func TestGenerateRandomID(t *testing.T) {
-	id := GenerateRandomID()
-
-	if len(id) != 64 {
-		t.Fatalf("Id returned is incorrect: %s", id)
-	}
-}
-
-func TestShortenId(t *testing.T) {
-	id := GenerateRandomID()
-	truncID := TruncateID(id)
-	if len(truncID) != 12 {
-		t.Fatalf("Id returned is incorrect: truncate on %s returned %s", id, truncID)
-	}
-}
-
-func TestShortenIdEmpty(t *testing.T) {
-	id := ""
-	truncID := TruncateID(id)
-	if len(truncID) > len(id) {
-		t.Fatalf("Id returned is incorrect: truncate on %s returned %s", id, truncID)
-	}
-}
-
-func TestShortenIdInvalid(t *testing.T) {
-	id := "1234"
-	truncID := TruncateID(id)
-	if len(truncID) != len(id) {
-		t.Fatalf("Id returned is incorrect: truncate on %s returned %s", id, truncID)
-	}
-}
diff --git a/pkg/libmachine/host/host_test.go b/pkg/libmachine/host/host_test.go
deleted file mode 100644
index 9b724352f..000000000
--- a/pkg/libmachine/host/host_test.go
+++ /dev/null
@@ -1,37 +0,0 @@
-package host
-
-import (
-	"testing"
-
-	_ "github.com/code-ready/crc/pkg/drivers/none"
-)
-
-func TestValidateHostnameValid(t *testing.T) {
-	hosts := []string{
-		"zomg",
-		"test-ing",
-		"some.h0st",
-	}
-
-	for _, v := range hosts {
-		isValid := ValidateHostName(v)
-		if !isValid {
-			t.Fatalf("Thought a valid hostname was invalid: %s", v)
-		}
-	}
-}
-
-func TestValidateHostnameInvalid(t *testing.T) {
-	hosts := []string{
-		"zom_g",
-		"test$ing",
-		"some😄host",
-	}
-
-	for _, v := range hosts {
-		isValid := ValidateHostName(v)
-		if isValid {
-			t.Fatalf("Thought an invalid hostname was valid: %s", v)
-		}
-	}
-}
diff --git a/pkg/libmachine/hosttest/default_test_host.go b/pkg/libmachine/hosttest/default_test_host.go
deleted file mode 100644
index 1bd92d365..000000000
--- a/pkg/libmachine/hosttest/default_test_host.go
+++ /dev/null
@@ -1,22 +0,0 @@
-package hosttest
-
-import (
-	"github.com/code-ready/crc/pkg/drivers/none"
-	"github.com/code-ready/crc/pkg/libmachine/host"
-	"github.com/code-ready/crc/pkg/libmachine/version"
-)
-
-const (
-	DefaultHostName = "test-host"
-)
-
-func GetDefaultTestHost() (*host.Host, error) {
-	driver := none.NewDriver(DefaultHostName, "/tmp/artifacts")
-
-	return &host.Host{
-		ConfigVersion: version.ConfigVersion,
-		Name:          DefaultHostName,
-		Driver:        driver,
-		DriverName:    "none",
-	}, nil
-}
diff --git a/pkg/libmachine/persist/filestore_test.go b/pkg/libmachine/persist/filestore_test.go
index bd8a62d7d..d6a478921 100644
--- a/pkg/libmachine/persist/filestore_test.go
+++ b/pkg/libmachine/persist/filestore_test.go
@@ -2,204 +2,131 @@ package persist
 
 import (
 	"encoding/json"
-	"fmt"
 	"io/ioutil"
 	"os"
 	"path/filepath"
-	"regexp"
 	"testing"
 
 	"github.com/code-ready/crc/pkg/drivers/none"
 	"github.com/code-ready/crc/pkg/libmachine/host"
-	"github.com/code-ready/crc/pkg/libmachine/hosttest"
+	"github.com/stretchr/testify/assert"
 )
 
-func cleanup() {
-	os.RemoveAll(os.Getenv("MACHINE_STORAGE_PATH"))
-}
-
-func getTestStore() Filestore {
+func getTestStore() (Filestore, func(), error) {
 	tmpDir, err := ioutil.TempDir("", "machine-test-")
 	if err != nil {
-		fmt.Println(err)
-		os.Exit(1)
+		return Filestore{}, nil, err
 	}
-
 	return Filestore{
-		Path: tmpDir,
-	}
+			MachinesDir: tmpDir,
+		}, func() {
+			os.RemoveAll(tmpDir)
+		}, nil
 }
 
 func TestStoreSave(t *testing.T) {
+	store, cleanup, err := getTestStore()
+	assert.NoError(t, err)
 	defer cleanup()
 
-	store := getTestStore()
-
-	h, err := hosttest.GetDefaultTestHost()
-	if err != nil {
-		t.Fatal(err)
-	}
-
-	if err := store.Save(h); err != nil {
-		t.Fatal(err)
-	}
+	h := testHost()
 
-	path := filepath.Join(store.GetMachinesDir(), h.Name)
-	if _, err := os.Stat(path); os.IsNotExist(err) {
-		t.Fatalf("Host path doesn't exist: %s", path)
-	}
+	assert.NoError(t, store.Save(h))
 
-	files, _ := ioutil.ReadDir(path)
-	for _, f := range files {
-		r := regexp.MustCompile("config.json.tmp*")
-		if r.MatchString(f.Name()) {
-			t.Fatalf("Failed to remove temp filestore:%s", f.Name())
-		}
-	}
+	path := filepath.Join(store.MachinesDir, h.Name)
+	assert.DirExists(t, path)
 }
 
 func TestStoreSaveOmitRawDriver(t *testing.T) {
+	store, cleanup, err := getTestStore()
+	assert.NoError(t, err)
 	defer cleanup()
 
-	store := getTestStore()
-
-	h, err := hosttest.GetDefaultTestHost()
-	if err != nil {
-		t.Fatal(err)
-	}
-
-	if err := store.Save(h); err != nil {
-		t.Fatal(err)
-	}
+	h := testHost()
 
-	configJSONPath := filepath.Join(store.GetMachinesDir(), h.Name, "config.json")
+	assert.NoError(t, store.Save(h))
 
-	f, err := os.Open(configJSONPath)
-	if err != nil {
-		t.Fatal(err)
-	}
+	configJSONPath := filepath.Join(store.MachinesDir, h.Name, "config.json")
 
-	configData, err := ioutil.ReadAll(f)
-	if err != nil {
-		t.Fatal(err)
-	}
+	configData, err := ioutil.ReadFile(configJSONPath)
+	assert.NoError(t, err)
 
 	fakeHost := make(map[string]interface{})
 
-	if err := json.Unmarshal(configData, &fakeHost); err != nil {
-		t.Fatal(err)
-	}
-
-	if rawDriver, ok := fakeHost["RawDriver"]; ok {
-		t.Fatal("Should not have gotten a value for RawDriver reading host from disk but got one: ", rawDriver)
-	}
+	assert.NoError(t, json.Unmarshal(configData, &fakeHost))
 
+	_, ok := fakeHost["RawDriver"]
+	assert.False(t, ok)
 }
 
 func TestStoreRemove(t *testing.T) {
+	store, cleanup, err := getTestStore()
+	assert.NoError(t, err)
 	defer cleanup()
 
-	store := getTestStore()
+	h := testHost()
 
-	h, err := hosttest.GetDefaultTestHost()
-	if err != nil {
-		t.Fatal(err)
-	}
+	assert.NoError(t, store.Save(h))
 
-	if err := store.Save(h); err != nil {
-		t.Fatal(err)
-	}
-
-	path := filepath.Join(store.GetMachinesDir(), h.Name)
-	if _, err := os.Stat(path); os.IsNotExist(err) {
-		t.Fatalf("Host path doesn't exist: %s", path)
-	}
+	path := filepath.Join(store.MachinesDir, h.Name)
+	assert.DirExists(t, path)
 
 	err = store.Remove(h.Name)
-	if err != nil {
-		t.Fatal(err)
-	}
+	assert.NoError(t, err)
 
-	if _, err := os.Stat(path); err == nil {
-		t.Fatalf("Host path still exists after remove: %s", path)
-	}
+	assert.NoDirExists(t, path)
 }
 
 func TestStoreExists(t *testing.T) {
+	store, cleanup, err := getTestStore()
+	assert.NoError(t, err)
 	defer cleanup()
-	store := getTestStore()
 
-	h, err := hosttest.GetDefaultTestHost()
-	if err != nil {
-		t.Fatal(err)
-	}
+	h := testHost()
 
 	exists, err := store.Exists(h.Name)
-	if err != nil {
-		t.Fatal(err)
-	}
-	if exists {
-		t.Fatal("Host should not exist before saving")
-	}
+	assert.NoError(t, err)
+	assert.False(t, exists)
 
-	if err := store.Save(h); err != nil {
-		t.Fatal(err)
-	}
+	assert.NoError(t, store.Save(h))
 
-	if err := store.SetExists(h.Name); err != nil {
-		t.Fatal(err)
-	}
+	assert.NoError(t, store.SetExists(h.Name))
 
 	exists, err = store.Exists(h.Name)
-	if err != nil {
-		t.Fatal(err)
-	}
+	assert.NoError(t, err)
+	assert.True(t, exists)
 
-	if !exists {
-		t.Fatal("Host should exist after saving")
-	}
-
-	if err := store.Remove(h.Name); err != nil {
-		t.Fatal(err)
-	}
+	assert.NoError(t, store.Remove(h.Name))
 
 	exists, err = store.Exists(h.Name)
-	if err != nil {
-		t.Fatal(err)
-	}
-
-	if exists {
-		t.Fatal("Host should not exist after removing")
-	}
+	assert.NoError(t, err)
+	assert.False(t, exists)
 }
 
 func TestStoreLoad(t *testing.T) {
+	store, cleanup, err := getTestStore()
+	assert.NoError(t, err)
 	defer cleanup()
 
-	store := getTestStore()
+	h := testHost()
 
-	h, err := hosttest.GetDefaultTestHost()
-	if err != nil {
-		t.Fatal(err)
-	}
-
-	if err := store.Save(h); err != nil {
-		t.Fatal(err)
-	}
+	assert.NoError(t, store.Save(h))
 
 	h, err = store.Load(h.Name)
-	if err != nil {
-		t.Fatal(err)
-	}
+	assert.NoError(t, err)
 
 	rawDataDriver, ok := h.Driver.(*host.RawDataDriver)
-	if !ok {
-		t.Fatal("Expected driver loaded from store to be of type *host.RawDataDriver and it was not")
-	}
+	assert.True(t, ok)
 
-	realDriver := none.NewDriver(h.Name, store.Path)
+	realDriver := none.NewDriver(h.Name, store.MachinesDir)
+	assert.NoError(t, json.Unmarshal(rawDataDriver.Data, &realDriver))
+}
 
-	if err := json.Unmarshal(rawDataDriver.Data, &realDriver); err != nil {
-		t.Fatalf("Error unmarshaling rawDataDriver data into concrete 'none' driver: %s", err)
+func testHost() *host.Host {
+	return &host.Host{
+		ConfigVersion: host.Version,
+		Name:          "test-host",
+		Driver:        none.NewDriver("test-host", "/tmp/artifacts"),
+		DriverName:    "none",
 	}
 }
diff --git a/test/integration/crcsuite/collect.go b/test/integration/crcsuite/collect.go
index 32d8edbb4..85297cd61 100644
--- a/test/integration/crcsuite/collect.go
+++ b/test/integration/crcsuite/collect.go
@@ -177,7 +177,7 @@ type VMCommandCollector struct {
 }
 
 func (collector *VMCommandCollector) Collect(w Writer) error {
-	client := machine.NewClient(constants.DefaultName, true, network.DefaultMode, false)
+	client := machine.NewClient(constants.DefaultName, network.DefaultMode, false)
 	ip, err := client.IP()
 	if err != nil {
 		return err
@@ -198,7 +198,7 @@ type ContainerLogCollector struct {
 }
 
 func (collector *ContainerLogCollector) Collect(w Writer) error {
-	client := machine.NewClient(constants.DefaultName, true, network.DefaultMode, false)
+	client := machine.NewClient(constants.DefaultName, network.DefaultMode, false)
 	ip, err := client.IP()
 	if err != nil {
 		return err
diff --git a/vendor/github.com/stretchr/testify/assert/assertion_compare.go b/vendor/github.com/stretchr/testify/assert/assertion_compare.go
index dc200395c..41649d267 100644
--- a/vendor/github.com/stretchr/testify/assert/assertion_compare.go
+++ b/vendor/github.com/stretchr/testify/assert/assertion_compare.go
@@ -13,12 +13,42 @@ const (
 	compareGreater
 )
 
+var (
+	intType   = reflect.TypeOf(int(1))
+	int8Type  = reflect.TypeOf(int8(1))
+	int16Type = reflect.TypeOf(int16(1))
+	int32Type = reflect.TypeOf(int32(1))
+	int64Type = reflect.TypeOf(int64(1))
+
+	uintType   = reflect.TypeOf(uint(1))
+	uint8Type  = reflect.TypeOf(uint8(1))
+	uint16Type = reflect.TypeOf(uint16(1))
+	uint32Type = reflect.TypeOf(uint32(1))
+	uint64Type = reflect.TypeOf(uint64(1))
+
+	float32Type = reflect.TypeOf(float32(1))
+	float64Type = reflect.TypeOf(float64(1))
+
+	stringType = reflect.TypeOf("")
+)
+
 func compare(obj1, obj2 interface{}, kind reflect.Kind) (CompareType, bool) {
+	obj1Value := reflect.ValueOf(obj1)
+	obj2Value := reflect.ValueOf(obj2)
+
+	// throughout this switch we try and avoid calling .Convert() if possible,
+	// as this has a pretty big performance impact
 	switch kind {
 	case reflect.Int:
 		{
-			intobj1 := obj1.(int)
-			intobj2 := obj2.(int)
+			intobj1, ok := obj1.(int)
+			if !ok {
+				intobj1 = obj1Value.Convert(intType).Interface().(int)
+			}
+			intobj2, ok := obj2.(int)
+			if !ok {
+				intobj2 = obj2Value.Convert(intType).Interface().(int)
+			}
 			if intobj1 > intobj2 {
 				return compareGreater, true
 			}
@@ -31,8 +61,14 @@ func compare(obj1, obj2 interface{}, kind reflect.Kind) (CompareType, bool) {
 		}
 	case reflect.Int8:
 		{
-			int8obj1 := obj1.(int8)
-			int8obj2 := obj2.(int8)
+			int8obj1, ok := obj1.(int8)
+			if !ok {
+				int8obj1 = obj1Value.Convert(int8Type).Interface().(int8)
+			}
+			int8obj2, ok := obj2.(int8)
+			if !ok {
+				int8obj2 = obj2Value.Convert(int8Type).Interface().(int8)
+			}
 			if int8obj1 > int8obj2 {
 				return compareGreater, true
 			}
@@ -45,8 +81,14 @@ func compare(obj1, obj2 interface{}, kind reflect.Kind) (CompareType, bool) {
 		}
 	case reflect.Int16:
 		{
-			int16obj1 := obj1.(int16)
-			int16obj2 := obj2.(int16)
+			int16obj1, ok := obj1.(int16)
+			if !ok {
+				int16obj1 = obj1Value.Convert(int16Type).Interface().(int16)
+			}
+			int16obj2, ok := obj2.(int16)
+			if !ok {
+				int16obj2 = obj2Value.Convert(int16Type).Interface().(int16)
+			}
 			if int16obj1 > int16obj2 {
 				return compareGreater, true
 			}
@@ -59,8 +101,14 @@ func compare(obj1, obj2 interface{}, kind reflect.Kind) (CompareType, bool) {
 		}
 	case reflect.Int32:
 		{
-			int32obj1 := obj1.(int32)
-			int32obj2 := obj2.(int32)
+			int32obj1, ok := obj1.(int32)
+			if !ok {
+				int32obj1 = obj1Value.Convert(int32Type).Interface().(int32)
+			}
+			int32obj2, ok := obj2.(int32)
+			if !ok {
+				int32obj2 = obj2Value.Convert(int32Type).Interface().(int32)
+			}
 			if int32obj1 > int32obj2 {
 				return compareGreater, true
 			}
@@ -73,8 +121,14 @@ func compare(obj1, obj2 interface{}, kind reflect.Kind) (CompareType, bool) {
 		}
 	case reflect.Int64:
 		{
-			int64obj1 := obj1.(int64)
-			int64obj2 := obj2.(int64)
+			int64obj1, ok := obj1.(int64)
+			if !ok {
+				int64obj1 = obj1Value.Convert(int64Type).Interface().(int64)
+			}
+			int64obj2, ok := obj2.(int64)
+			if !ok {
+				int64obj2 = obj2Value.Convert(int64Type).Interface().(int64)
+			}
 			if int64obj1 > int64obj2 {
 				return compareGreater, true
 			}
@@ -87,8 +141,14 @@ func compare(obj1, obj2 interface{}, kind reflect.Kind) (CompareType, bool) {
 		}
 	case reflect.Uint:
 		{
-			uintobj1 := obj1.(uint)
-			uintobj2 := obj2.(uint)
+			uintobj1, ok := obj1.(uint)
+			if !ok {
+				uintobj1 = obj1Value.Convert(uintType).Interface().(uint)
+			}
+			uintobj2, ok := obj2.(uint)
+			if !ok {
+				uintobj2 = obj2Value.Convert(uintType).Interface().(uint)
+			}
 			if uintobj1 > uintobj2 {
 				return compareGreater, true
 			}
@@ -101,8 +161,14 @@ func compare(obj1, obj2 interface{}, kind reflect.Kind) (CompareType, bool) {
 		}
 	case reflect.Uint8:
 		{
-			uint8obj1 := obj1.(uint8)
-			uint8obj2 := obj2.(uint8)
+			uint8obj1, ok := obj1.(uint8)
+			if !ok {
+				uint8obj1 = obj1Value.Convert(uint8Type).Interface().(uint8)
+			}
+			uint8obj2, ok := obj2.(uint8)
+			if !ok {
+				uint8obj2 = obj2Value.Convert(uint8Type).Interface().(uint8)
+			}
 			if uint8obj1 > uint8obj2 {
 				return compareGreater, true
 			}
@@ -115,8 +181,14 @@ func compare(obj1, obj2 interface{}, kind reflect.Kind) (CompareType, bool) {
 		}
 	case reflect.Uint16:
 		{
-			uint16obj1 := obj1.(uint16)
-			uint16obj2 := obj2.(uint16)
+			uint16obj1, ok := obj1.(uint16)
+			if !ok {
+				uint16obj1 = obj1Value.Convert(uint16Type).Interface().(uint16)
+			}
+			uint16obj2, ok := obj2.(uint16)
+			if !ok {
+				uint16obj2 = obj2Value.Convert(uint16Type).Interface().(uint16)
+			}
 			if uint16obj1 > uint16obj2 {
 				return compareGreater, true
 			}
@@ -129,8 +201,14 @@ func compare(obj1, obj2 interface{}, kind reflect.Kind) (CompareType, bool) {
 		}
 	case reflect.Uint32:
 		{
-			uint32obj1 := obj1.(uint32)
-			uint32obj2 := obj2.(uint32)
+			uint32obj1, ok := obj1.(uint32)
+			if !ok {
+				uint32obj1 = obj1Value.Convert(uint32Type).Interface().(uint32)
+			}
+			uint32obj2, ok := obj2.(uint32)
+			if !ok {
+				uint32obj2 = obj2Value.Convert(uint32Type).Interface().(uint32)
+			}
 			if uint32obj1 > uint32obj2 {
 				return compareGreater, true
 			}
@@ -143,8 +221,14 @@ func compare(obj1, obj2 interface{}, kind reflect.Kind) (CompareType, bool) {
 		}
 	case reflect.Uint64:
 		{
-			uint64obj1 := obj1.(uint64)
-			uint64obj2 := obj2.(uint64)
+			uint64obj1, ok := obj1.(uint64)
+			if !ok {
+				uint64obj1 = obj1Value.Convert(uint64Type).Interface().(uint64)
+			}
+			uint64obj2, ok := obj2.(uint64)
+			if !ok {
+				uint64obj2 = obj2Value.Convert(uint64Type).Interface().(uint64)
+			}
 			if uint64obj1 > uint64obj2 {
 				return compareGreater, true
 			}
@@ -157,8 +241,14 @@ func compare(obj1, obj2 interface{}, kind reflect.Kind) (CompareType, bool) {
 		}
 	case reflect.Float32:
 		{
-			float32obj1 := obj1.(float32)
-			float32obj2 := obj2.(float32)
+			float32obj1, ok := obj1.(float32)
+			if !ok {
+				float32obj1 = obj1Value.Convert(float32Type).Interface().(float32)
+			}
+			float32obj2, ok := obj2.(float32)
+			if !ok {
+				float32obj2 = obj2Value.Convert(float32Type).Interface().(float32)
+			}
 			if float32obj1 > float32obj2 {
 				return compareGreater, true
 			}
@@ -171,8 +261,14 @@ func compare(obj1, obj2 interface{}, kind reflect.Kind) (CompareType, bool) {
 		}
 	case reflect.Float64:
 		{
-			float64obj1 := obj1.(float64)
-			float64obj2 := obj2.(float64)
+			float64obj1, ok := obj1.(float64)
+			if !ok {
+				float64obj1 = obj1Value.Convert(float64Type).Interface().(float64)
+			}
+			float64obj2, ok := obj2.(float64)
+			if !ok {
+				float64obj2 = obj2Value.Convert(float64Type).Interface().(float64)
+			}
 			if float64obj1 > float64obj2 {
 				return compareGreater, true
 			}
@@ -185,8 +281,14 @@ func compare(obj1, obj2 interface{}, kind reflect.Kind) (CompareType, bool) {
 		}
 	case reflect.String:
 		{
-			stringobj1 := obj1.(string)
-			stringobj2 := obj2.(string)
+			stringobj1, ok := obj1.(string)
+			if !ok {
+				stringobj1 = obj1Value.Convert(stringType).Interface().(string)
+			}
+			stringobj2, ok := obj2.(string)
+			if !ok {
+				stringobj2 = obj2Value.Convert(stringType).Interface().(string)
+			}
 			if stringobj1 > stringobj2 {
 				return compareGreater, true
 			}
@@ -240,6 +342,24 @@ func LessOrEqual(t TestingT, e1 interface{}, e2 interface{}, msgAndArgs ...inter
 	return compareTwoValues(t, e1, e2, []CompareType{compareLess, compareEqual}, "\"%v\" is not less than or equal to \"%v\"", msgAndArgs)
 }
 
+// Positive asserts that the specified element is positive
+//
+//    assert.Positive(t, 1)
+//    assert.Positive(t, 1.23)
+func Positive(t TestingT, e interface{}, msgAndArgs ...interface{}) bool {
+	zero := reflect.Zero(reflect.TypeOf(e))
+	return compareTwoValues(t, e, zero.Interface(), []CompareType{compareGreater}, "\"%v\" is not positive", msgAndArgs)
+}
+
+// Negative asserts that the specified element is negative
+//
+//    assert.Negative(t, -1)
+//    assert.Negative(t, -1.23)
+func Negative(t TestingT, e interface{}, msgAndArgs ...interface{}) bool {
+	zero := reflect.Zero(reflect.TypeOf(e))
+	return compareTwoValues(t, e, zero.Interface(), []CompareType{compareLess}, "\"%v\" is not negative", msgAndArgs)
+}
+
 func compareTwoValues(t TestingT, e1 interface{}, e2 interface{}, allowedComparesResults []CompareType, failMessage string, msgAndArgs ...interface{}) bool {
 	if h, ok := t.(tHelper); ok {
 		h.Helper()
diff --git a/vendor/github.com/stretchr/testify/assert/assertion_format.go b/vendor/github.com/stretchr/testify/assert/assertion_format.go
index 49370eb16..4dfd1229a 100644
--- a/vendor/github.com/stretchr/testify/assert/assertion_format.go
+++ b/vendor/github.com/stretchr/testify/assert/assertion_format.go
@@ -114,6 +114,24 @@ func Errorf(t TestingT, err error, msg string, args ...interface{}) bool {
 	return Error(t, err, append([]interface{}{msg}, args...)...)
 }
 
+// ErrorAsf asserts that at least one of the errors in err's chain matches target, and if so, sets target to that error value.
+// This is a wrapper for errors.As.
+func ErrorAsf(t TestingT, err error, target interface{}, msg string, args ...interface{}) bool {
+	if h, ok := t.(tHelper); ok {
+		h.Helper()
+	}
+	return ErrorAs(t, err, target, append([]interface{}{msg}, args...)...)
+}
+
+// ErrorIsf asserts that at least one of the errors in err's chain matches target.
+// This is a wrapper for errors.Is.
+func ErrorIsf(t TestingT, err error, target error, msg string, args ...interface{}) bool {
+	if h, ok := t.(tHelper); ok {
+		h.Helper()
+	}
+	return ErrorIs(t, err, target, append([]interface{}{msg}, args...)...)
+}
+
 // Eventuallyf asserts that given condition will be met in waitFor time,
 // periodically checking target function each tick.
 //
@@ -321,6 +339,54 @@ func InEpsilonSlicef(t TestingT, expected interface{}, actual interface{}, epsil
 	return InEpsilonSlice(t, expected, actual, epsilon, append([]interface{}{msg}, args...)...)
 }
 
+// IsDecreasingf asserts that the collection is decreasing
+//
+//    assert.IsDecreasingf(t, []int{2, 1, 0}, "error message %s", "formatted")
+//    assert.IsDecreasingf(t, []float{2, 1}, "error message %s", "formatted")
+//    assert.IsDecreasingf(t, []string{"b", "a"}, "error message %s", "formatted")
+func IsDecreasingf(t TestingT, object interface{}, msg string, args ...interface{}) bool {
+	if h, ok := t.(tHelper); ok {
+		h.Helper()
+	}
+	return IsDecreasing(t, object, append([]interface{}{msg}, args...)...)
+}
+
+// IsIncreasingf asserts that the collection is increasing
+//
+//    assert.IsIncreasingf(t, []int{1, 2, 3}, "error message %s", "formatted")
+//    assert.IsIncreasingf(t, []float{1, 2}, "error message %s", "formatted")
+//    assert.IsIncreasingf(t, []string{"a", "b"}, "error message %s", "formatted")
+func IsIncreasingf(t TestingT, object interface{}, msg string, args ...interface{}) bool {
+	if h, ok := t.(tHelper); ok {
+		h.Helper()
+	}
+	return IsIncreasing(t, object, append([]interface{}{msg}, args...)...)
+}
+
+// IsNonDecreasingf asserts that the collection is not decreasing
+//
+//    assert.IsNonDecreasingf(t, []int{1, 1, 2}, "error message %s", "formatted")
+//    assert.IsNonDecreasingf(t, []float{1, 2}, "error message %s", "formatted")
+//    assert.IsNonDecreasingf(t, []string{"a", "b"}, "error message %s", "formatted")
+func IsNonDecreasingf(t TestingT, object interface{}, msg string, args ...interface{}) bool {
+	if h, ok := t.(tHelper); ok {
+		h.Helper()
+	}
+	return IsNonDecreasing(t, object, append([]interface{}{msg}, args...)...)
+}
+
+// IsNonIncreasingf asserts that the collection is not increasing
+//
+//    assert.IsNonIncreasingf(t, []int{2, 1, 1}, "error message %s", "formatted")
+//    assert.IsNonIncreasingf(t, []float{2, 1}, "error message %s", "formatted")
+//    assert.IsNonIncreasingf(t, []string{"b", "a"}, "error message %s", "formatted")
+func IsNonIncreasingf(t TestingT, object interface{}, msg string, args ...interface{}) bool {
+	if h, ok := t.(tHelper); ok {
+		h.Helper()
+	}
+	return IsNonIncreasing(t, object, append([]interface{}{msg}, args...)...)
+}
+
 // IsTypef asserts that the specified objects are of the same type.
 func IsTypef(t TestingT, expectedType interface{}, object interface{}, msg string, args ...interface{}) bool {
 	if h, ok := t.(tHelper); ok {
@@ -375,6 +441,17 @@ func LessOrEqualf(t TestingT, e1 interface{}, e2 interface{}, msg string, args .
 	return LessOrEqual(t, e1, e2, append([]interface{}{msg}, args...)...)
 }
 
+// Negativef asserts that the specified element is negative
+//
+//    assert.Negativef(t, -1, "error message %s", "formatted")
+//    assert.Negativef(t, -1.23, "error message %s", "formatted")
+func Negativef(t TestingT, e interface{}, msg string, args ...interface{}) bool {
+	if h, ok := t.(tHelper); ok {
+		h.Helper()
+	}
+	return Negative(t, e, append([]interface{}{msg}, args...)...)
+}
+
 // Neverf asserts that the given condition doesn't satisfy in waitFor time,
 // periodically checking the target function each tick.
 //
@@ -476,6 +553,15 @@ func NotEqualValuesf(t TestingT, expected interface{}, actual interface{}, msg s
 	return NotEqualValues(t, expected, actual, append([]interface{}{msg}, args...)...)
 }
 
+// NotErrorIsf asserts that at none of the errors in err's chain matches target.
+// This is a wrapper for errors.Is.
+func NotErrorIsf(t TestingT, err error, target error, msg string, args ...interface{}) bool {
+	if h, ok := t.(tHelper); ok {
+		h.Helper()
+	}
+	return NotErrorIs(t, err, target, append([]interface{}{msg}, args...)...)
+}
+
 // NotNilf asserts that the specified object is not nil.
 //
 //    assert.NotNilf(t, err, "error message %s", "formatted")
@@ -572,6 +658,17 @@ func PanicsWithValuef(t TestingT, expected interface{}, f PanicTestFunc, msg str
 	return PanicsWithValue(t, expected, f, append([]interface{}{msg}, args...)...)
 }
 
+// Positivef asserts that the specified element is positive
+//
+//    assert.Positivef(t, 1, "error message %s", "formatted")
+//    assert.Positivef(t, 1.23, "error message %s", "formatted")
+func Positivef(t TestingT, e interface{}, msg string, args ...interface{}) bool {
+	if h, ok := t.(tHelper); ok {
+		h.Helper()
+	}
+	return Positive(t, e, append([]interface{}{msg}, args...)...)
+}
+
 // Regexpf asserts that a specified regexp matches a string.
 //
 //  assert.Regexpf(t, regexp.MustCompile("start"), "it's starting", "error message %s", "formatted")
diff --git a/vendor/github.com/stretchr/testify/assert/assertion_forward.go b/vendor/github.com/stretchr/testify/assert/assertion_forward.go
index 9db889427..25337a6f0 100644
--- a/vendor/github.com/stretchr/testify/assert/assertion_forward.go
+++ b/vendor/github.com/stretchr/testify/assert/assertion_forward.go
@@ -204,6 +204,42 @@ func (a *Assertions) Error(err error, msgAndArgs ...interface{}) bool {
 	return Error(a.t, err, msgAndArgs...)
 }
 
+// ErrorAs asserts that at least one of the errors in err's chain matches target, and if so, sets target to that error value.
+// This is a wrapper for errors.As.
+func (a *Assertions) ErrorAs(err error, target interface{}, msgAndArgs ...interface{}) bool {
+	if h, ok := a.t.(tHelper); ok {
+		h.Helper()
+	}
+	return ErrorAs(a.t, err, target, msgAndArgs...)
+}
+
+// ErrorAsf asserts that at least one of the errors in err's chain matches target, and if so, sets target to that error value.
+// This is a wrapper for errors.As.
+func (a *Assertions) ErrorAsf(err error, target interface{}, msg string, args ...interface{}) bool {
+	if h, ok := a.t.(tHelper); ok {
+		h.Helper()
+	}
+	return ErrorAsf(a.t, err, target, msg, args...)
+}
+
+// ErrorIs asserts that at least one of the errors in err's chain matches target.
+// This is a wrapper for errors.Is.
+func (a *Assertions) ErrorIs(err error, target error, msgAndArgs ...interface{}) bool {
+	if h, ok := a.t.(tHelper); ok {
+		h.Helper()
+	}
+	return ErrorIs(a.t, err, target, msgAndArgs...)
+}
+
+// ErrorIsf asserts that at least one of the errors in err's chain matches target.
+// This is a wrapper for errors.Is.
+func (a *Assertions) ErrorIsf(err error, target error, msg string, args ...interface{}) bool {
+	if h, ok := a.t.(tHelper); ok {
+		h.Helper()
+	}
+	return ErrorIsf(a.t, err, target, msg, args...)
+}
+
 // Errorf asserts that a function returned an error (i.e. not `nil`).
 //
 //   actualObj, err := SomeFunction()
@@ -631,6 +667,102 @@ func (a *Assertions) InEpsilonf(expected interface{}, actual interface{}, epsilo
 	return InEpsilonf(a.t, expected, actual, epsilon, msg, args...)
 }
 
+// IsDecreasing asserts that the collection is decreasing
+//
+//    a.IsDecreasing([]int{2, 1, 0})
+//    a.IsDecreasing([]float{2, 1})
+//    a.IsDecreasing([]string{"b", "a"})
+func (a *Assertions) IsDecreasing(object interface{}, msgAndArgs ...interface{}) bool {
+	if h, ok := a.t.(tHelper); ok {
+		h.Helper()
+	}
+	return IsDecreasing(a.t, object, msgAndArgs...)
+}
+
+// IsDecreasingf asserts that the collection is decreasing
+//
+//    a.IsDecreasingf([]int{2, 1, 0}, "error message %s", "formatted")
+//    a.IsDecreasingf([]float{2, 1}, "error message %s", "formatted")
+//    a.IsDecreasingf([]string{"b", "a"}, "error message %s", "formatted")
+func (a *Assertions) IsDecreasingf(object interface{}, msg string, args ...interface{}) bool {
+	if h, ok := a.t.(tHelper); ok {
+		h.Helper()
+	}
+	return IsDecreasingf(a.t, object, msg, args...)
+}
+
+// IsIncreasing asserts that the collection is increasing
+//
+//    a.IsIncreasing([]int{1, 2, 3})
+//    a.IsIncreasing([]float{1, 2})
+//    a.IsIncreasing([]string{"a", "b"})
+func (a *Assertions) IsIncreasing(object interface{}, msgAndArgs ...interface{}) bool {
+	if h, ok := a.t.(tHelper); ok {
+		h.Helper()
+	}
+	return IsIncreasing(a.t, object, msgAndArgs...)
+}
+
+// IsIncreasingf asserts that the collection is increasing
+//
+//    a.IsIncreasingf([]int{1, 2, 3}, "error message %s", "formatted")
+//    a.IsIncreasingf([]float{1, 2}, "error message %s", "formatted")
+//    a.IsIncreasingf([]string{"a", "b"}, "error message %s", "formatted")
+func (a *Assertions) IsIncreasingf(object interface{}, msg string, args ...interface{}) bool {
+	if h, ok := a.t.(tHelper); ok {
+		h.Helper()
+	}
+	return IsIncreasingf(a.t, object, msg, args...)
+}
+
+// IsNonDecreasing asserts that the collection is not decreasing
+//
+//    a.IsNonDecreasing([]int{1, 1, 2})
+//    a.IsNonDecreasing([]float{1, 2})
+//    a.IsNonDecreasing([]string{"a", "b"})
+func (a *Assertions) IsNonDecreasing(object interface{}, msgAndArgs ...interface{}) bool {
+	if h, ok := a.t.(tHelper); ok {
+		h.Helper()
+	}
+	return IsNonDecreasing(a.t, object, msgAndArgs...)
+}
+
+// IsNonDecreasingf asserts that the collection is not decreasing
+//
+//    a.IsNonDecreasingf([]int{1, 1, 2}, "error message %s", "formatted")
+//    a.IsNonDecreasingf([]float{1, 2}, "error message %s", "formatted")
+//    a.IsNonDecreasingf([]string{"a", "b"}, "error message %s", "formatted")
+func (a *Assertions) IsNonDecreasingf(object interface{}, msg string, args ...interface{}) bool {
+	if h, ok := a.t.(tHelper); ok {
+		h.Helper()
+	}
+	return IsNonDecreasingf(a.t, object, msg, args...)
+}
+
+// IsNonIncreasing asserts that the collection is not increasing
+//
+//    a.IsNonIncreasing([]int{2, 1, 1})
+//    a.IsNonIncreasing([]float{2, 1})
+//    a.IsNonIncreasing([]string{"b", "a"})
+func (a *Assertions) IsNonIncreasing(object interface{}, msgAndArgs ...interface{}) bool {
+	if h, ok := a.t.(tHelper); ok {
+		h.Helper()
+	}
+	return IsNonIncreasing(a.t, object, msgAndArgs...)
+}
+
+// IsNonIncreasingf asserts that the collection is not increasing
+//
+//    a.IsNonIncreasingf([]int{2, 1, 1}, "error message %s", "formatted")
+//    a.IsNonIncreasingf([]float{2, 1}, "error message %s", "formatted")
+//    a.IsNonIncreasingf([]string{"b", "a"}, "error message %s", "formatted")
+func (a *Assertions) IsNonIncreasingf(object interface{}, msg string, args ...interface{}) bool {
+	if h, ok := a.t.(tHelper); ok {
+		h.Helper()
+	}
+	return IsNonIncreasingf(a.t, object, msg, args...)
+}
+
 // IsType asserts that the specified objects are of the same type.
 func (a *Assertions) IsType(expectedType interface{}, object interface{}, msgAndArgs ...interface{}) bool {
 	if h, ok := a.t.(tHelper); ok {
@@ -739,6 +871,28 @@ func (a *Assertions) Lessf(e1 interface{}, e2 interface{}, msg string, args ...i
 	return Lessf(a.t, e1, e2, msg, args...)
 }
 
+// Negative asserts that the specified element is negative
+//
+//    a.Negative(-1)
+//    a.Negative(-1.23)
+func (a *Assertions) Negative(e interface{}, msgAndArgs ...interface{}) bool {
+	if h, ok := a.t.(tHelper); ok {
+		h.Helper()
+	}
+	return Negative(a.t, e, msgAndArgs...)
+}
+
+// Negativef asserts that the specified element is negative
+//
+//    a.Negativef(-1, "error message %s", "formatted")
+//    a.Negativef(-1.23, "error message %s", "formatted")
+func (a *Assertions) Negativef(e interface{}, msg string, args ...interface{}) bool {
+	if h, ok := a.t.(tHelper); ok {
+		h.Helper()
+	}
+	return Negativef(a.t, e, msg, args...)
+}
+
 // Never asserts that the given condition doesn't satisfy in waitFor time,
 // periodically checking the target function each tick.
 //
@@ -941,6 +1095,24 @@ func (a *Assertions) NotEqualf(expected interface{}, actual interface{}, msg str
 	return NotEqualf(a.t, expected, actual, msg, args...)
 }
 
+// NotErrorIs asserts that at none of the errors in err's chain matches target.
+// This is a wrapper for errors.Is.
+func (a *Assertions) NotErrorIs(err error, target error, msgAndArgs ...interface{}) bool {
+	if h, ok := a.t.(tHelper); ok {
+		h.Helper()
+	}
+	return NotErrorIs(a.t, err, target, msgAndArgs...)
+}
+
+// NotErrorIsf asserts that at none of the errors in err's chain matches target.
+// This is a wrapper for errors.Is.
+func (a *Assertions) NotErrorIsf(err error, target error, msg string, args ...interface{}) bool {
+	if h, ok := a.t.(tHelper); ok {
+		h.Helper()
+	}
+	return NotErrorIsf(a.t, err, target, msg, args...)
+}
+
 // NotNil asserts that the specified object is not nil.
 //
 //    a.NotNil(err)
@@ -1133,6 +1305,28 @@ func (a *Assertions) Panicsf(f PanicTestFunc, msg string, args ...interface{}) b
 	return Panicsf(a.t, f, msg, args...)
 }
 
+// Positive asserts that the specified element is positive
+//
+//    a.Positive(1)
+//    a.Positive(1.23)
+func (a *Assertions) Positive(e interface{}, msgAndArgs ...interface{}) bool {
+	if h, ok := a.t.(tHelper); ok {
+		h.Helper()
+	}
+	return Positive(a.t, e, msgAndArgs...)
+}
+
+// Positivef asserts that the specified element is positive
+//
+//    a.Positivef(1, "error message %s", "formatted")
+//    a.Positivef(1.23, "error message %s", "formatted")
+func (a *Assertions) Positivef(e interface{}, msg string, args ...interface{}) bool {
+	if h, ok := a.t.(tHelper); ok {
+		h.Helper()
+	}
+	return Positivef(a.t, e, msg, args...)
+}
+
 // Regexp asserts that a specified regexp matches a string.
 //
 //  a.Regexp(regexp.MustCompile("start"), "it's starting")
diff --git a/vendor/github.com/stretchr/testify/assert/assertion_order.go b/vendor/github.com/stretchr/testify/assert/assertion_order.go
new file mode 100644
index 000000000..1c3b47182
--- /dev/null
+++ b/vendor/github.com/stretchr/testify/assert/assertion_order.go
@@ -0,0 +1,81 @@
+package assert
+
+import (
+	"fmt"
+	"reflect"
+)
+
+// isOrdered checks that collection contains orderable elements.
+func isOrdered(t TestingT, object interface{}, allowedComparesResults []CompareType, failMessage string, msgAndArgs ...interface{}) bool {
+	objKind := reflect.TypeOf(object).Kind()
+	if objKind != reflect.Slice && objKind != reflect.Array {
+		return false
+	}
+
+	objValue := reflect.ValueOf(object)
+	objLen := objValue.Len()
+
+	if objLen <= 1 {
+		return true
+	}
+
+	value := objValue.Index(0)
+	valueInterface := value.Interface()
+	firstValueKind := value.Kind()
+
+	for i := 1; i < objLen; i++ {
+		prevValue := value
+		prevValueInterface := valueInterface
+
+		value = objValue.Index(i)
+		valueInterface = value.Interface()
+
+		compareResult, isComparable := compare(prevValueInterface, valueInterface, firstValueKind)
+
+		if !isComparable {
+			return Fail(t, fmt.Sprintf("Can not compare type \"%s\" and \"%s\"", reflect.TypeOf(value), reflect.TypeOf(prevValue)), msgAndArgs...)
+		}
+
+		if !containsValue(allowedComparesResults, compareResult) {
+			return Fail(t, fmt.Sprintf(failMessage, prevValue, value), msgAndArgs...)
+		}
+	}
+
+	return true
+}
+
+// IsIncreasing asserts that the collection is increasing
+//
+//    assert.IsIncreasing(t, []int{1, 2, 3})
+//    assert.IsIncreasing(t, []float{1, 2})
+//    assert.IsIncreasing(t, []string{"a", "b"})
+func IsIncreasing(t TestingT, object interface{}, msgAndArgs ...interface{}) bool {
+	return isOrdered(t, object, []CompareType{compareLess}, "\"%v\" is not less than \"%v\"", msgAndArgs)
+}
+
+// IsNonIncreasing asserts that the collection is not increasing
+//
+//    assert.IsNonIncreasing(t, []int{2, 1, 1})
+//    assert.IsNonIncreasing(t, []float{2, 1})
+//    assert.IsNonIncreasing(t, []string{"b", "a"})
+func IsNonIncreasing(t TestingT, object interface{}, msgAndArgs ...interface{}) bool {
+	return isOrdered(t, object, []CompareType{compareEqual, compareGreater}, "\"%v\" is not greater than or equal to \"%v\"", msgAndArgs)
+}
+
+// IsDecreasing asserts that the collection is decreasing
+//
+//    assert.IsDecreasing(t, []int{2, 1, 0})
+//    assert.IsDecreasing(t, []float{2, 1})
+//    assert.IsDecreasing(t, []string{"b", "a"})
+func IsDecreasing(t TestingT, object interface{}, msgAndArgs ...interface{}) bool {
+	return isOrdered(t, object, []CompareType{compareGreater}, "\"%v\" is not greater than \"%v\"", msgAndArgs)
+}
+
+// IsNonDecreasing asserts that the collection is not decreasing
+//
+//    assert.IsNonDecreasing(t, []int{1, 1, 2})
+//    assert.IsNonDecreasing(t, []float{1, 2})
+//    assert.IsNonDecreasing(t, []string{"a", "b"})
+func IsNonDecreasing(t TestingT, object interface{}, msgAndArgs ...interface{}) bool {
+	return isOrdered(t, object, []CompareType{compareLess, compareEqual}, "\"%v\" is not less than or equal to \"%v\"", msgAndArgs)
+}
diff --git a/vendor/github.com/stretchr/testify/assert/assertions.go b/vendor/github.com/stretchr/testify/assert/assertions.go
index 914a10d83..bcac4401f 100644
--- a/vendor/github.com/stretchr/testify/assert/assertions.go
+++ b/vendor/github.com/stretchr/testify/assert/assertions.go
@@ -172,8 +172,8 @@ func isTest(name, prefix string) bool {
 	if len(name) == len(prefix) { // "Test" is ok
 		return true
 	}
-	rune, _ := utf8.DecodeRuneInString(name[len(prefix):])
-	return !unicode.IsLower(rune)
+	r, _ := utf8.DecodeRuneInString(name[len(prefix):])
+	return !unicode.IsLower(r)
 }
 
 func messageFromMsgAndArgs(msgAndArgs ...interface{}) string {
@@ -1622,6 +1622,7 @@ var spewConfig = spew.ConfigState{
 	DisableCapacities:       true,
 	SortKeys:                true,
 	DisableMethods:          true,
+	MaxDepth:                10,
 }
 
 type tHelper interface {
@@ -1693,3 +1694,81 @@ func Never(t TestingT, condition func() bool, waitFor time.Duration, tick time.D
 		}
 	}
 }
+
+// ErrorIs asserts that at least one of the errors in err's chain matches target.
+// This is a wrapper for errors.Is.
+func ErrorIs(t TestingT, err, target error, msgAndArgs ...interface{}) bool {
+	if h, ok := t.(tHelper); ok {
+		h.Helper()
+	}
+	if errors.Is(err, target) {
+		return true
+	}
+
+	var expectedText string
+	if target != nil {
+		expectedText = target.Error()
+	}
+
+	chain := buildErrorChainString(err)
+
+	return Fail(t, fmt.Sprintf("Target error should be in err chain:\n"+
+		"expected: %q\n"+
+		"in chain: %s", expectedText, chain,
+	), msgAndArgs...)
+}
+
+// NotErrorIs asserts that at none of the errors in err's chain matches target.
+// This is a wrapper for errors.Is.
+func NotErrorIs(t TestingT, err, target error, msgAndArgs ...interface{}) bool {
+	if h, ok := t.(tHelper); ok {
+		h.Helper()
+	}
+	if !errors.Is(err, target) {
+		return true
+	}
+
+	var expectedText string
+	if target != nil {
+		expectedText = target.Error()
+	}
+
+	chain := buildErrorChainString(err)
+
+	return Fail(t, fmt.Sprintf("Target error should not be in err chain:\n"+
+		"found: %q\n"+
+		"in chain: %s", expectedText, chain,
+	), msgAndArgs...)
+}
+
+// ErrorAs asserts that at least one of the errors in err's chain matches target, and if so, sets target to that error value.
+// This is a wrapper for errors.As.
+func ErrorAs(t TestingT, err error, target interface{}, msgAndArgs ...interface{}) bool {
+	if h, ok := t.(tHelper); ok {
+		h.Helper()
+	}
+	if errors.As(err, target) {
+		return true
+	}
+
+	chain := buildErrorChainString(err)
+
+	return Fail(t, fmt.Sprintf("Should be in error chain:\n"+
+		"expected: %q\n"+
+		"in chain: %s", target, chain,
+	), msgAndArgs...)
+}
+
+func buildErrorChainString(err error) string {
+	if err == nil {
+		return ""
+	}
+
+	e := errors.Unwrap(err)
+	chain := fmt.Sprintf("%q", err.Error())
+	for e != nil {
+		chain += fmt.Sprintf("\n\t%q", e.Error())
+		e = errors.Unwrap(e)
+	}
+	return chain
+}
diff --git a/vendor/github.com/stretchr/testify/require/require.go b/vendor/github.com/stretchr/testify/require/require.go
index ec4624b28..51820df2e 100644
--- a/vendor/github.com/stretchr/testify/require/require.go
+++ b/vendor/github.com/stretchr/testify/require/require.go
@@ -256,6 +256,54 @@ func Error(t TestingT, err error, msgAndArgs ...interface{}) {
 	t.FailNow()
 }
 
+// ErrorAs asserts that at least one of the errors in err's chain matches target, and if so, sets target to that error value.
+// This is a wrapper for errors.As.
+func ErrorAs(t TestingT, err error, target interface{}, msgAndArgs ...interface{}) {
+	if h, ok := t.(tHelper); ok {
+		h.Helper()
+	}
+	if assert.ErrorAs(t, err, target, msgAndArgs...) {
+		return
+	}
+	t.FailNow()
+}
+
+// ErrorAsf asserts that at least one of the errors in err's chain matches target, and if so, sets target to that error value.
+// This is a wrapper for errors.As.
+func ErrorAsf(t TestingT, err error, target interface{}, msg string, args ...interface{}) {
+	if h, ok := t.(tHelper); ok {
+		h.Helper()
+	}
+	if assert.ErrorAsf(t, err, target, msg, args...) {
+		return
+	}
+	t.FailNow()
+}
+
+// ErrorIs asserts that at least one of the errors in err's chain matches target.
+// This is a wrapper for errors.Is.
+func ErrorIs(t TestingT, err error, target error, msgAndArgs ...interface{}) {
+	if h, ok := t.(tHelper); ok {
+		h.Helper()
+	}
+	if assert.ErrorIs(t, err, target, msgAndArgs...) {
+		return
+	}
+	t.FailNow()
+}
+
+// ErrorIsf asserts that at least one of the errors in err's chain matches target.
+// This is a wrapper for errors.Is.
+func ErrorIsf(t TestingT, err error, target error, msg string, args ...interface{}) {
+	if h, ok := t.(tHelper); ok {
+		h.Helper()
+	}
+	if assert.ErrorIsf(t, err, target, msg, args...) {
+		return
+	}
+	t.FailNow()
+}
+
 // Errorf asserts that a function returned an error (i.e. not `nil`).
 //
 //   actualObj, err := SomeFunction()
@@ -806,6 +854,126 @@ func InEpsilonf(t TestingT, expected interface{}, actual interface{}, epsilon fl
 	t.FailNow()
 }
 
+// IsDecreasing asserts that the collection is decreasing
+//
+//    assert.IsDecreasing(t, []int{2, 1, 0})
+//    assert.IsDecreasing(t, []float{2, 1})
+//    assert.IsDecreasing(t, []string{"b", "a"})
+func IsDecreasing(t TestingT, object interface{}, msgAndArgs ...interface{}) {
+	if h, ok := t.(tHelper); ok {
+		h.Helper()
+	}
+	if assert.IsDecreasing(t, object, msgAndArgs...) {
+		return
+	}
+	t.FailNow()
+}
+
+// IsDecreasingf asserts that the collection is decreasing
+//
+//    assert.IsDecreasingf(t, []int{2, 1, 0}, "error message %s", "formatted")
+//    assert.IsDecreasingf(t, []float{2, 1}, "error message %s", "formatted")
+//    assert.IsDecreasingf(t, []string{"b", "a"}, "error message %s", "formatted")
+func IsDecreasingf(t TestingT, object interface{}, msg string, args ...interface{}) {
+	if h, ok := t.(tHelper); ok {
+		h.Helper()
+	}
+	if assert.IsDecreasingf(t, object, msg, args...) {
+		return
+	}
+	t.FailNow()
+}
+
+// IsIncreasing asserts that the collection is increasing
+//
+//    assert.IsIncreasing(t, []int{1, 2, 3})
+//    assert.IsIncreasing(t, []float{1, 2})
+//    assert.IsIncreasing(t, []string{"a", "b"})
+func IsIncreasing(t TestingT, object interface{}, msgAndArgs ...interface{}) {
+	if h, ok := t.(tHelper); ok {
+		h.Helper()
+	}
+	if assert.IsIncreasing(t, object, msgAndArgs...) {
+		return
+	}
+	t.FailNow()
+}
+
+// IsIncreasingf asserts that the collection is increasing
+//
+//    assert.IsIncreasingf(t, []int{1, 2, 3}, "error message %s", "formatted")
+//    assert.IsIncreasingf(t, []float{1, 2}, "error message %s", "formatted")
+//    assert.IsIncreasingf(t, []string{"a", "b"}, "error message %s", "formatted")
+func IsIncreasingf(t TestingT, object interface{}, msg string, args ...interface{}) {
+	if h, ok := t.(tHelper); ok {
+		h.Helper()
+	}
+	if assert.IsIncreasingf(t, object, msg, args...) {
+		return
+	}
+	t.FailNow()
+}
+
+// IsNonDecreasing asserts that the collection is not decreasing
+//
+//    assert.IsNonDecreasing(t, []int{1, 1, 2})
+//    assert.IsNonDecreasing(t, []float{1, 2})
+//    assert.IsNonDecreasing(t, []string{"a", "b"})
+func IsNonDecreasing(t TestingT, object interface{}, msgAndArgs ...interface{}) {
+	if h, ok := t.(tHelper); ok {
+		h.Helper()
+	}
+	if assert.IsNonDecreasing(t, object, msgAndArgs...) {
+		return
+	}
+	t.FailNow()
+}
+
+// IsNonDecreasingf asserts that the collection is not decreasing
+//
+//    assert.IsNonDecreasingf(t, []int{1, 1, 2}, "error message %s", "formatted")
+//    assert.IsNonDecreasingf(t, []float{1, 2}, "error message %s", "formatted")
+//    assert.IsNonDecreasingf(t, []string{"a", "b"}, "error message %s", "formatted")
+func IsNonDecreasingf(t TestingT, object interface{}, msg string, args ...interface{}) {
+	if h, ok := t.(tHelper); ok {
+		h.Helper()
+	}
+	if assert.IsNonDecreasingf(t, object, msg, args...) {
+		return
+	}
+	t.FailNow()
+}
+
+// IsNonIncreasing asserts that the collection is not increasing
+//
+//    assert.IsNonIncreasing(t, []int{2, 1, 1})
+//    assert.IsNonIncreasing(t, []float{2, 1})
+//    assert.IsNonIncreasing(t, []string{"b", "a"})
+func IsNonIncreasing(t TestingT, object interface{}, msgAndArgs ...interface{}) {
+	if h, ok := t.(tHelper); ok {
+		h.Helper()
+	}
+	if assert.IsNonIncreasing(t, object, msgAndArgs...) {
+		return
+	}
+	t.FailNow()
+}
+
+// IsNonIncreasingf asserts that the collection is not increasing
+//
+//    assert.IsNonIncreasingf(t, []int{2, 1, 1}, "error message %s", "formatted")
+//    assert.IsNonIncreasingf(t, []float{2, 1}, "error message %s", "formatted")
+//    assert.IsNonIncreasingf(t, []string{"b", "a"}, "error message %s", "formatted")
+func IsNonIncreasingf(t TestingT, object interface{}, msg string, args ...interface{}) {
+	if h, ok := t.(tHelper); ok {
+		h.Helper()
+	}
+	if assert.IsNonIncreasingf(t, object, msg, args...) {
+		return
+	}
+	t.FailNow()
+}
+
 // IsType asserts that the specified objects are of the same type.
 func IsType(t TestingT, expectedType interface{}, object interface{}, msgAndArgs ...interface{}) {
 	if h, ok := t.(tHelper); ok {
@@ -944,6 +1112,34 @@ func Lessf(t TestingT, e1 interface{}, e2 interface{}, msg string, args ...inter
 	t.FailNow()
 }
 
+// Negative asserts that the specified element is negative
+//
+//    assert.Negative(t, -1)
+//    assert.Negative(t, -1.23)
+func Negative(t TestingT, e interface{}, msgAndArgs ...interface{}) {
+	if h, ok := t.(tHelper); ok {
+		h.Helper()
+	}
+	if assert.Negative(t, e, msgAndArgs...) {
+		return
+	}
+	t.FailNow()
+}
+
+// Negativef asserts that the specified element is negative
+//
+//    assert.Negativef(t, -1, "error message %s", "formatted")
+//    assert.Negativef(t, -1.23, "error message %s", "formatted")
+func Negativef(t TestingT, e interface{}, msg string, args ...interface{}) {
+	if h, ok := t.(tHelper); ok {
+		h.Helper()
+	}
+	if assert.Negativef(t, e, msg, args...) {
+		return
+	}
+	t.FailNow()
+}
+
 // Never asserts that the given condition doesn't satisfy in waitFor time,
 // periodically checking the target function each tick.
 //
@@ -1200,6 +1396,30 @@ func NotEqualf(t TestingT, expected interface{}, actual interface{}, msg string,
 	t.FailNow()
 }
 
+// NotErrorIs asserts that at none of the errors in err's chain matches target.
+// This is a wrapper for errors.Is.
+func NotErrorIs(t TestingT, err error, target error, msgAndArgs ...interface{}) {
+	if h, ok := t.(tHelper); ok {
+		h.Helper()
+	}
+	if assert.NotErrorIs(t, err, target, msgAndArgs...) {
+		return
+	}
+	t.FailNow()
+}
+
+// NotErrorIsf asserts that at none of the errors in err's chain matches target.
+// This is a wrapper for errors.Is.
+func NotErrorIsf(t TestingT, err error, target error, msg string, args ...interface{}) {
+	if h, ok := t.(tHelper); ok {
+		h.Helper()
+	}
+	if assert.NotErrorIsf(t, err, target, msg, args...) {
+		return
+	}
+	t.FailNow()
+}
+
 // NotNil asserts that the specified object is not nil.
 //
 //    assert.NotNil(t, err)
@@ -1446,6 +1666,34 @@ func Panicsf(t TestingT, f assert.PanicTestFunc, msg string, args ...interface{}
 	t.FailNow()
 }
 
+// Positive asserts that the specified element is positive
+//
+//    assert.Positive(t, 1)
+//    assert.Positive(t, 1.23)
+func Positive(t TestingT, e interface{}, msgAndArgs ...interface{}) {
+	if h, ok := t.(tHelper); ok {
+		h.Helper()
+	}
+	if assert.Positive(t, e, msgAndArgs...) {
+		return
+	}
+	t.FailNow()
+}
+
+// Positivef asserts that the specified element is positive
+//
+//    assert.Positivef(t, 1, "error message %s", "formatted")
+//    assert.Positivef(t, 1.23, "error message %s", "formatted")
+func Positivef(t TestingT, e interface{}, msg string, args ...interface{}) {
+	if h, ok := t.(tHelper); ok {
+		h.Helper()
+	}
+	if assert.Positivef(t, e, msg, args...) {
+		return
+	}
+	t.FailNow()
+}
+
 // Regexp asserts that a specified regexp matches a string.
 //
 //  assert.Regexp(t, regexp.MustCompile("start"), "it's starting")
diff --git a/vendor/github.com/stretchr/testify/require/require_forward.go b/vendor/github.com/stretchr/testify/require/require_forward.go
index 103d7dcb6..ed54a9d83 100644
--- a/vendor/github.com/stretchr/testify/require/require_forward.go
+++ b/vendor/github.com/stretchr/testify/require/require_forward.go
@@ -205,6 +205,42 @@ func (a *Assertions) Error(err error, msgAndArgs ...interface{}) {
 	Error(a.t, err, msgAndArgs...)
 }
 
+// ErrorAs asserts that at least one of the errors in err's chain matches target, and if so, sets target to that error value.
+// This is a wrapper for errors.As.
+func (a *Assertions) ErrorAs(err error, target interface{}, msgAndArgs ...interface{}) {
+	if h, ok := a.t.(tHelper); ok {
+		h.Helper()
+	}
+	ErrorAs(a.t, err, target, msgAndArgs...)
+}
+
+// ErrorAsf asserts that at least one of the errors in err's chain matches target, and if so, sets target to that error value.
+// This is a wrapper for errors.As.
+func (a *Assertions) ErrorAsf(err error, target interface{}, msg string, args ...interface{}) {
+	if h, ok := a.t.(tHelper); ok {
+		h.Helper()
+	}
+	ErrorAsf(a.t, err, target, msg, args...)
+}
+
+// ErrorIs asserts that at least one of the errors in err's chain matches target.
+// This is a wrapper for errors.Is.
+func (a *Assertions) ErrorIs(err error, target error, msgAndArgs ...interface{}) {
+	if h, ok := a.t.(tHelper); ok {
+		h.Helper()
+	}
+	ErrorIs(a.t, err, target, msgAndArgs...)
+}
+
+// ErrorIsf asserts that at least one of the errors in err's chain matches target.
+// This is a wrapper for errors.Is.
+func (a *Assertions) ErrorIsf(err error, target error, msg string, args ...interface{}) {
+	if h, ok := a.t.(tHelper); ok {
+		h.Helper()
+	}
+	ErrorIsf(a.t, err, target, msg, args...)
+}
+
 // Errorf asserts that a function returned an error (i.e. not `nil`).
 //
 //   actualObj, err := SomeFunction()
@@ -632,6 +668,102 @@ func (a *Assertions) InEpsilonf(expected interface{}, actual interface{}, epsilo
 	InEpsilonf(a.t, expected, actual, epsilon, msg, args...)
 }
 
+// IsDecreasing asserts that the collection is decreasing
+//
+//    a.IsDecreasing([]int{2, 1, 0})
+//    a.IsDecreasing([]float{2, 1})
+//    a.IsDecreasing([]string{"b", "a"})
+func (a *Assertions) IsDecreasing(object interface{}, msgAndArgs ...interface{}) {
+	if h, ok := a.t.(tHelper); ok {
+		h.Helper()
+	}
+	IsDecreasing(a.t, object, msgAndArgs...)
+}
+
+// IsDecreasingf asserts that the collection is decreasing
+//
+//    a.IsDecreasingf([]int{2, 1, 0}, "error message %s", "formatted")
+//    a.IsDecreasingf([]float{2, 1}, "error message %s", "formatted")
+//    a.IsDecreasingf([]string{"b", "a"}, "error message %s", "formatted")
+func (a *Assertions) IsDecreasingf(object interface{}, msg string, args ...interface{}) {
+	if h, ok := a.t.(tHelper); ok {
+		h.Helper()
+	}
+	IsDecreasingf(a.t, object, msg, args...)
+}
+
+// IsIncreasing asserts that the collection is increasing
+//
+//    a.IsIncreasing([]int{1, 2, 3})
+//    a.IsIncreasing([]float{1, 2})
+//    a.IsIncreasing([]string{"a", "b"})
+func (a *Assertions) IsIncreasing(object interface{}, msgAndArgs ...interface{}) {
+	if h, ok := a.t.(tHelper); ok {
+		h.Helper()
+	}
+	IsIncreasing(a.t, object, msgAndArgs...)
+}
+
+// IsIncreasingf asserts that the collection is increasing
+//
+//    a.IsIncreasingf([]int{1, 2, 3}, "error message %s", "formatted")
+//    a.IsIncreasingf([]float{1, 2}, "error message %s", "formatted")
+//    a.IsIncreasingf([]string{"a", "b"}, "error message %s", "formatted")
+func (a *Assertions) IsIncreasingf(object interface{}, msg string, args ...interface{}) {
+	if h, ok := a.t.(tHelper); ok {
+		h.Helper()
+	}
+	IsIncreasingf(a.t, object, msg, args...)
+}
+
+// IsNonDecreasing asserts that the collection is not decreasing
+//
+//    a.IsNonDecreasing([]int{1, 1, 2})
+//    a.IsNonDecreasing([]float{1, 2})
+//    a.IsNonDecreasing([]string{"a", "b"})
+func (a *Assertions) IsNonDecreasing(object interface{}, msgAndArgs ...interface{}) {
+	if h, ok := a.t.(tHelper); ok {
+		h.Helper()
+	}
+	IsNonDecreasing(a.t, object, msgAndArgs...)
+}
+
+// IsNonDecreasingf asserts that the collection is not decreasing
+//
+//    a.IsNonDecreasingf([]int{1, 1, 2}, "error message %s", "formatted")
+//    a.IsNonDecreasingf([]float{1, 2}, "error message %s", "formatted")
+//    a.IsNonDecreasingf([]string{"a", "b"}, "error message %s", "formatted")
+func (a *Assertions) IsNonDecreasingf(object interface{}, msg string, args ...interface{}) {
+	if h, ok := a.t.(tHelper); ok {
+		h.Helper()
+	}
+	IsNonDecreasingf(a.t, object, msg, args...)
+}
+
+// IsNonIncreasing asserts that the collection is not increasing
+//
+//    a.IsNonIncreasing([]int{2, 1, 1})
+//    a.IsNonIncreasing([]float{2, 1})
+//    a.IsNonIncreasing([]string{"b", "a"})
+func (a *Assertions) IsNonIncreasing(object interface{}, msgAndArgs ...interface{}) {
+	if h, ok := a.t.(tHelper); ok {
+		h.Helper()
+	}
+	IsNonIncreasing(a.t, object, msgAndArgs...)
+}
+
+// IsNonIncreasingf asserts that the collection is not increasing
+//
+//    a.IsNonIncreasingf([]int{2, 1, 1}, "error message %s", "formatted")
+//    a.IsNonIncreasingf([]float{2, 1}, "error message %s", "formatted")
+//    a.IsNonIncreasingf([]string{"b", "a"}, "error message %s", "formatted")
+func (a *Assertions) IsNonIncreasingf(object interface{}, msg string, args ...interface{}) {
+	if h, ok := a.t.(tHelper); ok {
+		h.Helper()
+	}
+	IsNonIncreasingf(a.t, object, msg, args...)
+}
+
 // IsType asserts that the specified objects are of the same type.
 func (a *Assertions) IsType(expectedType interface{}, object interface{}, msgAndArgs ...interface{}) {
 	if h, ok := a.t.(tHelper); ok {
@@ -740,6 +872,28 @@ func (a *Assertions) Lessf(e1 interface{}, e2 interface{}, msg string, args ...i
 	Lessf(a.t, e1, e2, msg, args...)
 }
 
+// Negative asserts that the specified element is negative
+//
+//    a.Negative(-1)
+//    a.Negative(-1.23)
+func (a *Assertions) Negative(e interface{}, msgAndArgs ...interface{}) {
+	if h, ok := a.t.(tHelper); ok {
+		h.Helper()
+	}
+	Negative(a.t, e, msgAndArgs...)
+}
+
+// Negativef asserts that the specified element is negative
+//
+//    a.Negativef(-1, "error message %s", "formatted")
+//    a.Negativef(-1.23, "error message %s", "formatted")
+func (a *Assertions) Negativef(e interface{}, msg string, args ...interface{}) {
+	if h, ok := a.t.(tHelper); ok {
+		h.Helper()
+	}
+	Negativef(a.t, e, msg, args...)
+}
+
 // Never asserts that the given condition doesn't satisfy in waitFor time,
 // periodically checking the target function each tick.
 //
@@ -942,6 +1096,24 @@ func (a *Assertions) NotEqualf(expected interface{}, actual interface{}, msg str
 	NotEqualf(a.t, expected, actual, msg, args...)
 }
 
+// NotErrorIs asserts that at none of the errors in err's chain matches target.
+// This is a wrapper for errors.Is.
+func (a *Assertions) NotErrorIs(err error, target error, msgAndArgs ...interface{}) {
+	if h, ok := a.t.(tHelper); ok {
+		h.Helper()
+	}
+	NotErrorIs(a.t, err, target, msgAndArgs...)
+}
+
+// NotErrorIsf asserts that at none of the errors in err's chain matches target.
+// This is a wrapper for errors.Is.
+func (a *Assertions) NotErrorIsf(err error, target error, msg string, args ...interface{}) {
+	if h, ok := a.t.(tHelper); ok {
+		h.Helper()
+	}
+	NotErrorIsf(a.t, err, target, msg, args...)
+}
+
 // NotNil asserts that the specified object is not nil.
 //
 //    a.NotNil(err)
@@ -1134,6 +1306,28 @@ func (a *Assertions) Panicsf(f assert.PanicTestFunc, msg string, args ...interfa
 	Panicsf(a.t, f, msg, args...)
 }
 
+// Positive asserts that the specified element is positive
+//
+//    a.Positive(1)
+//    a.Positive(1.23)
+func (a *Assertions) Positive(e interface{}, msgAndArgs ...interface{}) {
+	if h, ok := a.t.(tHelper); ok {
+		h.Helper()
+	}
+	Positive(a.t, e, msgAndArgs...)
+}
+
+// Positivef asserts that the specified element is positive
+//
+//    a.Positivef(1, "error message %s", "formatted")
+//    a.Positivef(1.23, "error message %s", "formatted")
+func (a *Assertions) Positivef(e interface{}, msg string, args ...interface{}) {
+	if h, ok := a.t.(tHelper); ok {
+		h.Helper()
+	}
+	Positivef(a.t, e, msg, args...)
+}
+
 // Regexp asserts that a specified regexp matches a string.
 //
 //  a.Regexp(regexp.MustCompile("start"), "it's starting")