Repository: firecracker-microvm/firecracker-containerd
Pull request #590 (2022-03-05 05:29:50)

chore: upgrade golangci-lint to v1.44.2
*Issue #, if available:*
#567 

*Description of changes:*
Bump golangci-lint from v1.21.0 to v1.44.2

Removes deprecated linters and adds recommended replacement linters
'revive' and 'exportloopref'.

Marks G306 and G307 as excluded until those errors can be audited
seperately.

Removes an instance of unused variable flagged by 'unused' linter.

Updates few instances of local variable names to be inline with 'revive'
naming standards.

Updates few instances of exported function names to be inline with
'revive' naming standards.

Fixes a few instances where 'append' result was not stored in original
slice.

By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license.



Patch:
diff --git a/.golangci.yml b/.golangci.yml
index cbd9584..230f084 100644
--- a/.golangci.yml
+++ b/.golangci.yml
@@ -13,18 +13,16 @@ linters:
     - ineffassign
     - deadcode
     - typecheck
-    - golint
     - gosec
     - unconvert
     - goconst
     - goimports
     - misspell
     - prealloc
-    - scopelint
     - gocritic
-    - interfacer # Suggests narrower interface types
-    - scopelint # Checks for unpinned variables
     - gofmt
+    - revive
+    - exportloopref
 
 issues:
   exclude-use-default: false
@@ -33,3 +31,5 @@ issues:
     - G103 # Use of unsafe calls should be audited
     - G204 # Subprocess launched with variable
     - G304 # Potential file inclusion via variable
+    - G306 # WriteFile permissions 0600 or less to be audited
+    - G307 # Deferring unsafe method "Close" on type "*os.File" to be audited
diff --git a/Makefile b/Makefile
index e72050f..c94a0d1 100644
--- a/Makefile
+++ b/Makefile
@@ -112,7 +112,7 @@ tidy:
 	go mod tidy
 
 deps:
-	curl -sfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh| sh -s -- -b $(BINPATH) v1.21.0
+	curl -sfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh| sh -s -- -b $(BINPATH) v1.44.2
 	$(BINPATH)/golangci-lint --version
 	GOBIN=$(BINPATH) GO111MODULE=off go get -u github.com/vbatts/git-validation
 	GOBIN=$(BINPATH) GO111MODULE=off go get -u github.com/kunalkushwaha/ltag
diff --git a/agent/main.go b/agent/main.go
index 2fc5919..4015af7 100644
--- a/agent/main.go
+++ b/agent/main.go
@@ -27,7 +27,6 @@ import (
 	taskAPI "github.com/containerd/containerd/runtime/v2/task"
 	"github.com/containerd/containerd/sys/reaper"
 	"github.com/containerd/ttrpc"
-	"github.com/firecracker-microvm/firecracker-go-sdk/vsock"
 	"github.com/opencontainers/runc/libcontainer/system"
 	"github.com/sirupsen/logrus"
 	"golang.org/x/sync/errgroup"
@@ -35,6 +34,7 @@ import (
 
 	"github.com/firecracker-microvm/firecracker-containerd/eventbridge"
 	"github.com/firecracker-microvm/firecracker-containerd/internal/event"
+	"github.com/firecracker-microvm/firecracker-containerd/internal/vm"
 
 	drivemount "github.com/firecracker-microvm/firecracker-containerd/proto/service/drivemount/ttrpc"
 	ioproxy "github.com/firecracker-microvm/firecracker-containerd/proto/service/ioproxy/ttrpc"
@@ -120,7 +120,7 @@ func main() {
 	// Run ttrpc over vsock
 
 	vsockLogger := log.G(shimCtx).WithField("port", port)
-	listener, err := vsock.Listener(shimCtx, vsockLogger, uint32(port))
+	listener, err := vm.VSockListener(shimCtx, vsockLogger, uint32(port))
 	if err != nil {
 		log.G(shimCtx).WithError(err).Fatalf("failed to listen to vsock on port %d", port)
 	}
diff --git a/agent/service.go b/agent/service.go
index 23db27c..f57470d 100644
--- a/agent/service.go
+++ b/agent/service.go
@@ -189,11 +189,11 @@ func (ts *TaskService) Create(requestCtx context.Context, req *taskAPI.CreateTas
 		return nil
 	})
 
-	isVmLocalRootFs := len(req.Rootfs) > 0 && vm.IsLocalMount(req.Rootfs[0])
+	isVMLocalRootFs := len(req.Rootfs) > 0 && vm.IsLocalMount(req.Rootfs[0])
 
 	// If the rootfs is inside the VM, then the DriveMount call didn't happen and therefore
 	// the bundledir was not created. Create it here.
-	if isVmLocalRootFs {
+	if isVMLocalRootFs {
 		if err := os.MkdirAll(bundleDir.RootfsPath(), 0700); err != nil {
 			return nil, errors.Wrapf(err, "Failed to create bundle's rootfs path from inside the vm %q", bundleDir.RootfsPath())
 		}
@@ -219,7 +219,7 @@ func (ts *TaskService) Create(requestCtx context.Context, req *taskAPI.CreateTas
 	// If the rootfs is inside the VM then:
 	// a) the rootfs mount type has a prefix that we used to identify this which needs to be stripped before passing to runc
 	// b) we were not able to inspect the container's rootfs from the client when setting up the spec. Do that here.
-	if isVmLocalRootFs {
+	if isVMLocalRootFs {
 		req.Rootfs[0] = vm.StripLocalMountIdentifier(req.Rootfs[0])
 		rootfsMount := mount.Mount{
 			Type:    req.Rootfs[0].Type,
diff --git a/docs/design-approaches.md b/docs/design-approaches.md
index 01a0373..c550534 100644
--- a/docs/design-approaches.md
+++ b/docs/design-approaches.md
@@ -25,7 +25,7 @@ definitions.
 
 * Containerd - OCI compatible container runtime. Receives container lifecycle/management requests and performs them
   using configured plugins/options.
-* Runtime - An implementation of the runtime v2 [spec](https://github.com/containerd/containerd/tree/main/runtime/v2)
+* Runtime - An implementation of the runtime v2 [spec](https://github.com/containerd/containerd/tree/master/runtime/v2)
   for containerd. Unlike the default implementation which runs runc directly, our runtime will be responsible for
   managing Firecracker instances as well as communicating container requests to the inside-the-vm-agent.
 * Agent - A process inside of the running VM. Manages containers, handles communication with the Runtime and utilizes
@@ -42,8 +42,8 @@ definitions.
 ![design-overview](img/design-overview.png)
 
 1. Orchestrator accepts task definition request from control-plane and breaks it into sub-requests suitable for sending to
-   containerd (using `CreateTaskRequest` [struct](https://github.com/containerd/containerd/blob/main/api/services/tasks/v1/tasks.pb.go#L79),
-   additional parameters can be passed to runtime though `Options` [field](https://github.com/containerd/containerd/blob/main/api/services/tasks/v1/tasks.pb.go#L93))
+   containerd (using `CreateTaskRequest` [struct](https://github.com/containerd/containerd/blob/master/api/services/tasks/v1/tasks.pb.go#L79),
+   additional parameters can be passed to runtime though `Options` [field](https://github.com/containerd/containerd/blob/master/api/services/tasks/v1/tasks.pb.go#L93))
 2. containerd uses firecracker-containerd runtime and block device snapshotter. Requests are passed to runtime. Runtime
    is responsible for communicating with Agent, attaching/managing block devices and controlling container execution
    lifecycle.
@@ -94,9 +94,9 @@ any communication protocol can be chosen (ttrpc, grpc, http, ...) for exchanging
 The orchestrator knows about task definitions (e.g. aware about high level picture), makes decisions based on given
 information, and submits requests to containerd.
 
-The orchestrator talks to all subsystems using containerd's [APIs](https://github.com/containerd/containerd/tree/main/api).
-In order to manage containers lifecycle it can use [task](https://github.com/containerd/containerd/tree/main/services/tasks)
-service, extra configuration can be specified thought option [fields](https://github.com/containerd/containerd/blob/main/api/services/tasks/v1/tasks.proto#L74).
+The orchestrator talks to all subsystems using containerd's [APIs](https://github.com/containerd/containerd/tree/master/api).
+In order to manage containers lifecycle it can use [task](https://github.com/containerd/containerd/tree/master/services/tasks)
+service, extra configuration can be specified thought option [fields](https://github.com/containerd/containerd/blob/master/api/services/tasks/v1/tasks.proto#L74).
 Missing functionality (like firecracker control service) can be added as an extension to `containerd`.
 Containerd supports GRPC plugins, so FC control can reuse existing GRPC [server](https://github.com/containerd/containerd/blob/a15b6e2097c48b632dbdc63254bad4c62b69e709/services/server/server.go#L78)
 and live in same process as `containerd`. Orchestrator's client uses same GRPC connection (`containerd` has
@@ -165,7 +165,7 @@ Firecracker team is exploring options around Firecracker handling some aspects o
 
 Because there is no way to attach block devices upon request, the suggested approach is to use fake block devices (`/dev/null` or
 sparse files) to reserve drive ids before running Firecracker instance. When container needs to be run, fake device is
-replaced (via [PatchGuestDriveByID](https://github.com/firecracker-microvm/firecracker-go-sdk/blob/main/firecracker.go#L238))
+replaced (via [PatchGuestDriveByID](https://github.com/firecracker-microvm/firecracker-go-sdk/blob/master/firecracker.go#L238))
 with real container image received as [mount](https://github.com/firecracker-microvm/firecracker-containerd/blob/0e39b738ab466358b1059bb283b19726476310a1/runtime/service.go#L651)
 from snapshotter. Fake device can be represented by `/dev/null`, however Firecracker doesn't allow to attach same block
 device more than once (even with different drive ids). So alias should be used. Another approach is to use sparse files
diff --git a/docs/getting-started.md b/docs/getting-started.md
index eb84f10..46d9ec1 100644
--- a/docs/getting-started.md
+++ b/docs/getting-started.md
@@ -39,7 +39,7 @@ You need to have the following things in order to use firecracker-containerd:
   </details>
 * git
 * A recent installation of [Docker CE](https://docker.com).
-* Go 1.16 or later, which you can download from [here](https://golang.org/dl/).
+* Go 1.13 or later, which you can download from [here](https://golang.org/dl/).
 
 ## Setup
 
diff --git a/docs/quickstart.md b/docs/quickstart.md
index 11cb75c..5dd964a 100644
--- a/docs/quickstart.md
+++ b/docs/quickstart.md
@@ -28,14 +28,14 @@ files into `/usr/local/bin`.
 
 cd ~
 
-# Install git, Go 1.16, make, curl
+# Install git, Go 1.13, make, curl
 sudo mkdir -p /etc/apt/sources.list.d
 echo "deb http://ftp.debian.org/debian buster-backports main" | \
   sudo tee /etc/apt/sources.list.d/buster-backports.list
 sudo DEBIAN_FRONTEND=noninteractive apt-get update
 sudo DEBIAN_FRONTEND=noninteractive apt-get \
   install --yes \
-  golang-1.16 \
+  golang-1.13 \
   make \
   git \
   curl \
@@ -44,8 +44,8 @@ sudo DEBIAN_FRONTEND=noninteractive apt-get \
   bc \
   gnupg
 
-# Debian's Go 1.16 package installs "go" command under /usr/lib/go-1.16/bin
-export PATH=/usr/lib/go-1.16/bin:$PATH
+# Debian's Go 1.13 package installs "go" command under /usr/lib/go-1.13/bin
+export PATH=/usr/lib/go-1.13/bin:$PATH
 
 cd ~
 
@@ -75,9 +75,10 @@ A similar script to install dependencies for rpm based linux distro e.g. Amazon
 
 cd ~
 
-# Install git, make, curl
+# Install git, Go 1.13, make, curl
 sudo yum -y update
 sudo yum -y install \
+  golang \
   make \
   git \
   curl \
@@ -87,14 +88,7 @@ sudo yum -y install \
   gnupg
 
 
-# Amazon Linux 2 packages can sometimes be dated, so let's install using
-# the Go installer. The installer will handle any path changes and just
-# need to source environment variables afterwards for the existing shell session.
-curl -LO https://get.golang.org/$(uname)/go_installer && \
-  chmod +x go_installer && \
-  ./go_installer -version 1.16 && \
-  rm go_installer && \
-  source .bash_profile
+# Amazon Linux 2 installs go binary is installed in /usr/bin. So no PATH changes required.
 
 cd ~
 
diff --git a/docs/shim-design.md b/docs/shim-design.md
index c1fe964..c0145e4 100644
--- a/docs/shim-design.md
+++ b/docs/shim-design.md
@@ -48,9 +48,9 @@ The purpose of this doc is to determine which model best fits our use case in te
     * A unique identifier associated with each firecracker microVM that's used to reference which VM a given container is intended to run in.
         * In practice, there will likely be a 1-to-1 mapping between each ECS task or each EKS Pod to a `vm_id`.
 * (containerd) **Container**
-    * In containerd, a “[Container](https://github.com/containerd/containerd/blob/main/api/services/containers/v1/containers.proto#L38)” refers not to a running container but the metadata configuring a container.
+    * In containerd, a “[Container](https://github.com/containerd/containerd/blob/master/api/services/containers/v1/containers.proto#L38)” refers not to a running container but the metadata configuring a container.
 * (containerd) **Task**
-    * In containerd, a “[Task](https://github.com/containerd/containerd/blob/main/api/services/tasks/v1/tasks.proto#L56)” (not to be confused with an ECS Task), essentially refers to a running container; it is a running process using the configuration as specified in a previously defined Container object
+    * In containerd, a “[Task](https://github.com/containerd/containerd/blob/master/api/services/tasks/v1/tasks.proto#L56)” (not to be confused with an ECS Task), essentially refers to a running container; it is a running process using the configuration as specified in a previously defined Container object
 * **“shim start” routine**
     * In the runtime v2 model, when containerd starts a new Task, it will always invoke the runtime binary specified in the Container object and run its “shim start” routine. This is the point where the runtime shim will decide whether it should keep running or if containerd should instead use a different, pre-existing shim process.
     * [Our current shim start routine is here.](https://github.com/firecracker-microvm/firecracker-containerd/blob/3f204844eed9b70f25e062f3a947dda582809757/runtime/service.go#L106)
@@ -61,14 +61,14 @@ The purpose of this doc is to determine which model best fits our use case in te
 
 ## Containerd Runtime v2 Essentials
 
-There's a few details of containerd's runtime v2 model that are essential to understand before diving into how it can fit into our use case. [The runtime v2 docs](https://github.com/containerd/containerd/blob/main/runtime/v2/README.md) and their [getting started guide](https://github.com/containerd/containerd/blob/main/docs/getting-started.md) have more details, but the important parts of the typical flow in creating a container within the runtime v2 model are summarized below:
+There's a few details of containerd's runtime v2 model that are essential to understand before diving into how it can fit into our use case. [The runtime v2 docs](https://github.com/containerd/containerd/blob/master/runtime/v2/README.md) and their [getting started guide](https://github.com/containerd/containerd/blob/master/docs/getting-started.md) have more details, but the important parts of the typical flow in creating a container within the runtime v2 model are summarized below:
 
 ![containerd runtime v2 model](img/runtimev2-flow.png)
 
-1. The client makes a [CreateContainerRequest](https://github.com/containerd/containerd/blob/main/api/services/containers/v1/containers.proto#L38), which includes metadata for the intended container configuration (i.e. OCI runtime spec), which runtime the container should be spawned with (i.e. `aws.firecracker`) and a unique `container_id`
+1. The client makes a [CreateContainerRequest](https://github.com/containerd/containerd/blob/master/api/services/containers/v1/containers.proto#L38), which includes metadata for the intended container configuration (i.e. OCI runtime spec), which runtime the container should be spawned with (i.e. `aws.firecracker`) and a unique `container_id`
     1. This stores the metadata for the container definition within containerd, **but it does not actually spawn the container yet**
-2. The client now wants to actually create a running task for the container it just defined, which it does by issuing a [CreateTaskRequest](https://github.com/containerd/containerd/blob/main/api/services/tasks/v1/tasks.proto#L56) that includes the `container_id` provided in the previous `CreateContainerRequest`
-3. Containerd will now always `fork/exec` to the runtime's shim binary and invoke the “start” routine. **The shim is expected to [“either start a new shim or return an address to an existing shim based on the shim's logic.”](https://github.com/containerd/containerd/blob/main/runtime/v2/README.md#start)**
+2. The client now wants to actually create a running task for the container it just defined, which it does by issuing a [CreateTaskRequest](https://github.com/containerd/containerd/blob/master/api/services/tasks/v1/tasks.proto#L56) that includes the `container_id` provided in the previous `CreateContainerRequest`
+3. Containerd will now always `fork/exec` to the runtime's shim binary and invoke the “start” routine. **The shim is expected to [“either start a new shim or return an address to an existing shim based on the shim's logic.”](https://github.com/containerd/containerd/blob/master/runtime/v2/README.md#start)**
     1. (code) [containerd starting the shim binary](https://github.com/containerd/containerd/blob/9b882c44f8834613e53fc11045c10397a7d94e61/runtime/v2/manager.go#L126)
 4. At this point, the shim can optionally retrieve some more metadata if needed to make a decision on how to proceed. It has a few IDs/paths available to it that can be used to retrieve that metadata:
     1. The `container_id` for the container that is going to be spawned into a running task. The `container_id` is the “id” field in [our shim's NewService func](https://github.com/firecracker-microvm/firecracker-containerd/blob/3f204844eed9b70f25e062f3a947dda582809757/runtime/service.go#L79). It can be used to make a [GetContainerRequest](https://github.com/containerd/containerd/blob/68c44f8cc8a3a4990928c96f8207688ecf6df2f9/api/services/containers/v1/containers.proto#L30) to containerd, which will return all available container metadata.
@@ -85,7 +85,7 @@ There's a few details of containerd's runtime v2 model that are essential to und
 
 The requirements for our use case are:
 
-1. [Containerd's requirements for runtime v2 shims](https://github.com/containerd/containerd/tree/main/runtime/v2)
+1. [Containerd's requirements for runtime v2 shims](https://github.com/containerd/containerd/tree/master/runtime/v2)
 2. Ability to group containers into a single microVM via an identifier for the microVM (`vm_id`). Containers must be able to be created within the microVM after the VM has already started.
 
 # Decisions to be Made
@@ -102,7 +102,7 @@ The high-level issues this docs will address (each gets its own section):
 
 1. Fine grain details of how microVMs will be configured other than that running VMs can be specified with a `vm_id`.
 2. Details on exactly which field we will use to specify which `vm_id` a given container is using. There are multiple possibilities, all of which work with the options being presented here:
-    1. [OCI Config Annotation](https://github.com/opencontainers/runtime-spec/blob/main/config.md#annotations)
+    1. [OCI Config Annotation](https://github.com/opencontainers/runtime-spec/blob/master/config.md#annotations)
     2. [CreateContainerRequest.Container.Extensions](https://github.com/containerd/containerd/blob/68c44f8cc8a3a4990928c96f8207688ecf6df2f9/api/services/containers/v1/containers.proto#L100)
     3. [CreateTaskRequest.Options](https://github.com/containerd/containerd/blob/68c44f8cc8a3a4990928c96f8207688ecf6df2f9/api/services/tasks/v1/tasks.proto#L74)
 3. Details on how vsock communication will work. This doc will not make assumptions on which of the host or guest shim will be the listener/connector.
diff --git a/firecracker-control/cmd/containerd/main.go b/firecracker-control/cmd/containerd/main.go
index 0284777..25d6646 100644
--- a/firecracker-control/cmd/containerd/main.go
+++ b/firecracker-control/cmd/containerd/main.go
@@ -21,7 +21,7 @@ import (
 	"github.com/containerd/containerd/pkg/seed"
 
 	// Register containerd builtins
-	// See https://github.com/containerd/containerd/blob/main/cmd/containerd/builtins.go
+	// See https://github.com/containerd/containerd/blob/master/cmd/containerd/builtins.go
 	_ "github.com/containerd/containerd/diff/walking/plugin"
 	_ "github.com/containerd/containerd/events/plugin"
 	_ "github.com/containerd/containerd/gc/scheduler"
@@ -41,7 +41,7 @@ import (
 	_ "github.com/containerd/containerd/services/version"
 
 	// Linux specific builtins
-	// See https://github.com/containerd/containerd/blob/main/cmd/containerd/builtins_linux.go
+	// See https://github.com/containerd/containerd/blob/master/cmd/containerd/builtins_linux.go
 	_ "github.com/containerd/containerd/metrics/cgroups"
 	_ "github.com/containerd/containerd/runtime/v1/linux"
 	_ "github.com/containerd/containerd/runtime/v2"
diff --git a/go.mod b/go.mod
index 8e4752c..157a543 100644
--- a/go.mod
+++ b/go.mod
@@ -1,7 +1,5 @@
 module github.com/firecracker-microvm/firecracker-containerd
 
-go 1.16
-
 require (
 	github.com/StackExchange/wmi v0.0.0-20181212234831-e0a55b97c705 // indirect
 	github.com/awslabs/tc-redirect-tap v0.0.0-20211025175357-e30dfca224c2
@@ -13,12 +11,13 @@ require (
 	github.com/containerd/typeurl v1.0.2
 	github.com/containernetworking/cni v1.0.1
 	github.com/containernetworking/plugins v1.0.1
-	github.com/firecracker-microvm/firecracker-go-sdk v0.22.1-0.20220302172044-565c88a871e2
+	github.com/firecracker-microvm/firecracker-go-sdk v0.22.1-0.20220214213810-2380785d98b7
 	github.com/go-ole/go-ole v1.2.4 // indirect
 	github.com/gofrs/uuid v3.3.0+incompatible
 	github.com/gogo/protobuf v1.3.2
 	github.com/hashicorp/go-multierror v1.1.1
 	github.com/klauspost/compress v1.13.6 // indirect
+	github.com/mdlayher/vsock v1.1.0
 	github.com/miekg/dns v1.1.25
 	github.com/opencontainers/image-spec v1.0.2-0.20211117181255-693428a734f5
 	github.com/opencontainers/runc v1.1.0
@@ -40,3 +39,5 @@ replace (
 	google.golang.org/genproto => google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63
 	google.golang.org/grpc => google.golang.org/grpc v1.38.1
 )
+
+go 1.11
diff --git a/go.sum b/go.sum
index 9724dcb..72bb2e5 100644
--- a/go.sum
+++ b/go.sum
@@ -87,6 +87,7 @@ github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb0
 github.com/NYTimes/gziphandler v1.1.1/go.mod h1:n/CVRwUEOgIxrgPvAQhUUr9oeUtvrhMomdKFjzJNB0c=
 github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
 github.com/PuerkitoBio/purell v1.0.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0=
+github.com/PuerkitoBio/purell v1.1.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0=
 github.com/PuerkitoBio/purell v1.1.1 h1:WEQqlqaGbrPkxLJWfBwQmfEAE1Z7ONdDLqrN38tNFfI=
 github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0=
 github.com/PuerkitoBio/urlesc v0.0.0-20160726150825-5bd2802263f2/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE=
@@ -95,6 +96,7 @@ github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdko
 github.com/Shopify/logrus-bugsnag v0.0.0-20171204204709-577dee27f20d/go.mod h1:HI8ITrYtUY+O+ZhtlqUnD8+KwNPOyugEhfP9fdUIaEQ=
 github.com/StackExchange/wmi v0.0.0-20181212234831-e0a55b97c705 h1:UUppSQnhf4Yc6xGxSkoQpPhb7RVzuv5Nb1mwJ5VId9s=
 github.com/StackExchange/wmi v0.0.0-20181212234831-e0a55b97c705/go.mod h1:3eOhrUMpNV+6aFIbp5/iudMxNCF27Vw2OZgy4xEx0Fg=
+github.com/agnivade/levenshtein v1.0.1/go.mod h1:CURSv5d9Uaml+FovSIICkLbAUZ9S4RqaHDIsdSBg7lM=
 github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
 github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
 github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
@@ -102,15 +104,18 @@ github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRF
 github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho=
 github.com/alexflint/go-filemutex v0.0.0-20171022225611-72bdc8eae2ae/go.mod h1:CgnQgUtFrFz9mxFNtED3jI5tLDjKlOM+oUF/sTk6ps0=
 github.com/alexflint/go-filemutex v1.1.0/go.mod h1:7P4iRhttt/nUvUOrYIhcpMzv2G6CY9UnI16Z+UJqRyk=
+github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883/go.mod h1:rCTlJbsFo29Kk6CurOXKm700vrz8f0KW0JNfpkRJY/8=
 github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=
 github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o=
 github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8=
 github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY=
 github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8=
+github.com/asaskevich/govalidator v0.0.0-20180720115003-f9ffefc3facf/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY=
 github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY=
+github.com/asaskevich/govalidator v0.0.0-20200108200545-475eaeb16496/go.mod h1:oGkLhpf+kjZl6xBf758TQhh5XrAeiJv/7FRz/2spLIg=
+github.com/asaskevich/govalidator v0.0.0-20200428143746-21a406dcc535/go.mod h1:oGkLhpf+kjZl6xBf758TQhh5XrAeiJv/7FRz/2spLIg=
+github.com/asaskevich/govalidator v0.0.0-20200907205600-7a23bdc65eef h1:46PFijGLmAjMPwCCCo7Jf0W6f9slllCkkv7vyc1yOSg=
 github.com/asaskevich/govalidator v0.0.0-20200907205600-7a23bdc65eef/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw=
-github.com/asaskevich/govalidator v0.0.0-20210307081110-f21760c49a8d h1:Byv0BzEl3/e6D5CLfI0j/7hiIEtvGVFPCZ7Ei2oq8iQ=
-github.com/asaskevich/govalidator v0.0.0-20210307081110-f21760c49a8d/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw=
 github.com/aws/aws-sdk-go v1.15.11/go.mod h1:mFuSZ37Z9YOHbQEwBWztmVzqXrEkub65tZoCYDt7FT0=
 github.com/aws/aws-sdk-go v1.34.28/go.mod h1:H7NKnBqNVzoTJpGfLrQkkD+ytBA93eiDYi/+8rV9s48=
 github.com/awslabs/tc-redirect-tap v0.0.0-20211025175357-e30dfca224c2 h1:adfgQeMA2JpYPIQ4vaumP4xA0anx19jRDZLGq47jh4k=
@@ -325,6 +330,7 @@ github.com/docker/go-events v0.0.0-20190806004212-e31b211e4f1c/go.mod h1:Uw6Uezg
 github.com/docker/go-metrics v0.0.0-20180209012529-399ea8c73916/go.mod h1:/u0gXw0Gay3ceNrsHubL3BtdOL2fHf93USgMTe0W5dI=
 github.com/docker/go-metrics v0.0.1 h1:AgB/0SvBxihN0X8OR4SjsblXkbMvalQ8cjmtKQ2rQV8=
 github.com/docker/go-metrics v0.0.1/go.mod h1:cG1hvH2utMXtqgqqYE9plW6lDxS3/5ayHzueweSI3Vw=
+github.com/docker/go-units v0.3.3/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
 github.com/docker/go-units v0.4.0 h1:3uh0PgVws3nIA0Q+MwDC8yjEPf9zjRfZZWXZYDct3Tw=
 github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
 github.com/docker/libtrust v0.0.0-20150114040149-fa567046d9b1/go.mod h1:cyGadeNEkKy96OOhEzfZl+yxihPEzKnqJwvfuSUqbZE=
@@ -343,8 +349,8 @@ github.com/evanphx/json-patch v4.9.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLi
 github.com/evanphx/json-patch v4.11.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
 github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
 github.com/felixge/httpsnoop v1.0.1/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
-github.com/firecracker-microvm/firecracker-go-sdk v0.22.1-0.20220302172044-565c88a871e2 h1:vUEzKnC8if0UyjpXh8zZl0VW/xVidcyXt0xn7nwZOx4=
-github.com/firecracker-microvm/firecracker-go-sdk v0.22.1-0.20220302172044-565c88a871e2/go.mod h1:bNZ9JikG9OmPPqXMRJfHmSlIH0dMKeAA6HUyTtSyPlw=
+github.com/firecracker-microvm/firecracker-go-sdk v0.22.1-0.20220214213810-2380785d98b7 h1:qbS7P1pKuEszDq9ht4E6KqPcl6dbueZdWIXJjfpNTf8=
+github.com/firecracker-microvm/firecracker-go-sdk v0.22.1-0.20220214213810-2380785d98b7/go.mod h1:rxTSXup+QDUKci0+VkR+hdYLp2e88r+6en8P+1EsfRA=
 github.com/form3tech-oss/jwt-go v3.2.2+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k=
 github.com/form3tech-oss/jwt-go v3.2.3+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k=
 github.com/frankban/quicktest v1.11.3 h1:8sXhOn0uLys67V8EsXLc6eszDs8VXWxL3iRvebPhedY=
@@ -357,6 +363,8 @@ github.com/garyburd/redigo v0.0.0-20150301180006-535138d7bcd7/go.mod h1:NR3MbYis
 github.com/getsentry/raven-go v0.2.0/go.mod h1:KungGk8q33+aIAZUIVWZDr2OfAEBsO49PX4NzFV5kcQ=
 github.com/ghodss/yaml v0.0.0-20150909031657-73d445a93680/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
 github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
+github.com/globalsign/mgo v0.0.0-20180905125535-1ca0a4f7cbcb/go.mod h1:xkRDCp4j0OGD1HRkm4kmhM+pmpv3AKq5SU7GMg4oO/Q=
+github.com/globalsign/mgo v0.0.0-20181015135952-eeefdecb41b8/go.mod h1:xkRDCp4j0OGD1HRkm4kmhM+pmpv3AKq5SU7GMg4oO/Q=
 github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
 github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
 github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
@@ -379,50 +387,114 @@ github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
 github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
 github.com/go-ole/go-ole v1.2.4 h1:nNBDSCOigTSiarFpYE9J/KtEA1IOW4CNeqT9TQDqCxI=
 github.com/go-ole/go-ole v1.2.4/go.mod h1:XCwSNxSkXRo4vlyPy93sltvi/qJq0jqQhjqQNIwKuxM=
-github.com/go-openapi/analysis v0.21.2 h1:hXFrOYFHUAMQdu6zwAiKKJHJQ8kqZs1ux/ru1P1wLJU=
-github.com/go-openapi/analysis v0.21.2/go.mod h1:HZwRk4RRisyG8vx2Oe6aqeSQcoxRp47Xkp3+K6q+LdY=
+github.com/go-openapi/analysis v0.0.0-20180825180245-b006789cd277/go.mod h1:k70tL6pCuVxPJOHXQ+wIac1FUrvNkHolPie/cLEU6hI=
+github.com/go-openapi/analysis v0.17.0/go.mod h1:IowGgpVeD0vNm45So8nr+IcQ3pxVtpRoBWb8PVZO0ik=
+github.com/go-openapi/analysis v0.18.0/go.mod h1:IowGgpVeD0vNm45So8nr+IcQ3pxVtpRoBWb8PVZO0ik=
+github.com/go-openapi/analysis v0.19.2/go.mod h1:3P1osvZa9jKjb8ed2TPng3f0i/UY9snX6gxi44djMjk=
+github.com/go-openapi/analysis v0.19.4/go.mod h1:3P1osvZa9jKjb8ed2TPng3f0i/UY9snX6gxi44djMjk=
+github.com/go-openapi/analysis v0.19.5/go.mod h1:hkEAkxagaIvIP7VTn8ygJNkd4kAYON2rCu0v0ObL0AU=
+github.com/go-openapi/analysis v0.19.10/go.mod h1:qmhS3VNFxBlquFJ0RGoDtylO9y4pgTAUNE9AEEMdlJQ=
+github.com/go-openapi/analysis v0.19.16/go.mod h1:GLInF007N83Ad3m8a/CbQ5TPzdnGT7workfHwuVjNVk=
+github.com/go-openapi/analysis v0.20.0/go.mod h1:BMchjvaHDykmRMsK40iPtvyOfFdMMxlOmQr9FBZk+Og=
+github.com/go-openapi/analysis v0.20.1 h1:zdVbw8yoD4SWZeq+cWdGgquaB0W4VrsJvDJHJND/Ktc=
+github.com/go-openapi/analysis v0.20.1/go.mod h1:BMchjvaHDykmRMsK40iPtvyOfFdMMxlOmQr9FBZk+Og=
+github.com/go-openapi/errors v0.17.0/go.mod h1:LcZQpmvG4wyF5j4IhA73wkLFQg+QJXOQHVjmcZxhka0=
+github.com/go-openapi/errors v0.18.0/go.mod h1:LcZQpmvG4wyF5j4IhA73wkLFQg+QJXOQHVjmcZxhka0=
+github.com/go-openapi/errors v0.19.2/go.mod h1:qX0BLWsyaKfvhluLejVpVNwNRdXZhEbTA4kxxpKBC94=
+github.com/go-openapi/errors v0.19.3/go.mod h1:qX0BLWsyaKfvhluLejVpVNwNRdXZhEbTA4kxxpKBC94=
+github.com/go-openapi/errors v0.19.6/go.mod h1:cM//ZKUKyO06HSwqAelJ5NsEMMcpa6VpXe8DOa1Mi1M=
+github.com/go-openapi/errors v0.19.7/go.mod h1:cM//ZKUKyO06HSwqAelJ5NsEMMcpa6VpXe8DOa1Mi1M=
 github.com/go-openapi/errors v0.19.8/go.mod h1:cM//ZKUKyO06HSwqAelJ5NsEMMcpa6VpXe8DOa1Mi1M=
 github.com/go-openapi/errors v0.19.9/go.mod h1:cM//ZKUKyO06HSwqAelJ5NsEMMcpa6VpXe8DOa1Mi1M=
+github.com/go-openapi/errors v0.20.1/go.mod h1:cM//ZKUKyO06HSwqAelJ5NsEMMcpa6VpXe8DOa1Mi1M=
 github.com/go-openapi/errors v0.20.2 h1:dxy7PGTqEh94zj2E3h1cUmQQWiM1+aeCROfAr02EmK8=
 github.com/go-openapi/errors v0.20.2/go.mod h1:cM//ZKUKyO06HSwqAelJ5NsEMMcpa6VpXe8DOa1Mi1M=
 github.com/go-openapi/jsonpointer v0.0.0-20160704185906-46af16f9f7b1/go.mod h1:+35s3my2LFTysnkMfxsJBAMHj/DoqoB9knIWoYG/Vk0=
+github.com/go-openapi/jsonpointer v0.17.0/go.mod h1:cOnomiV+CVVwFLk0A/MExoFMjwdsUdVpsRhURCKh+3M=
+github.com/go-openapi/jsonpointer v0.18.0/go.mod h1:cOnomiV+CVVwFLk0A/MExoFMjwdsUdVpsRhURCKh+3M=
 github.com/go-openapi/jsonpointer v0.19.2/go.mod h1:3akKfEdA7DF1sugOqz1dVQHBcuDBPKZGEoHC/NkiQRg=
 github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg=
 github.com/go-openapi/jsonpointer v0.19.5 h1:gZr+CIYByUqjcgeLXnQu2gHYQC9o73G2XUeOFYEICuY=
 github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg=
 github.com/go-openapi/jsonreference v0.0.0-20160704190145-13c6e3589ad9/go.mod h1:W3Z9FmVs9qj+KR4zFKmDPGiLdk1D9Rlm7cyMvf57TTg=
+github.com/go-openapi/jsonreference v0.17.0/go.mod h1:g4xxGn04lDIRh0GJb5QlpE3HfopLOL6uZrK/VgnsK9I=
+github.com/go-openapi/jsonreference v0.18.0/go.mod h1:g4xxGn04lDIRh0GJb5QlpE3HfopLOL6uZrK/VgnsK9I=
 github.com/go-openapi/jsonreference v0.19.2/go.mod h1:jMjeRr2HHw6nAVajTXJ4eiUwohSTlpa0o73RUL1owJc=
 github.com/go-openapi/jsonreference v0.19.3/go.mod h1:rjx6GuL8TTa9VaixXglHmQmIL98+wF9xc8zWvFonSJ8=
 github.com/go-openapi/jsonreference v0.19.5/go.mod h1:RdybgQwPxbL4UEjuAruzK1x3nE69AqPYEJeo/TWfEeg=
 github.com/go-openapi/jsonreference v0.19.6 h1:UBIxjkht+AWIgYzCDSv2GN+E/togfwXUJFRTWhl2Jjs=
 github.com/go-openapi/jsonreference v0.19.6/go.mod h1:diGHMEHg2IqXZGKxqyvWdfWU/aim5Dprw5bqpKkTvns=
-github.com/go-openapi/loads v0.21.1 h1:Wb3nVZpdEzDTcly8S4HMkey6fjARRzb7iEaySimlDW0=
-github.com/go-openapi/loads v0.21.1/go.mod h1:/DtAMXXneXFjbQMGEtbamCZb+4x7eGwkvZCvBmwUG+g=
-github.com/go-openapi/runtime v0.23.1 h1:/Drg9R96eMmgKJHVWZADz78XbE39/6QiIiB45mc+epo=
-github.com/go-openapi/runtime v0.23.1/go.mod h1:AKurw9fNre+h3ELZfk6ILsfvPN+bvvlaU/M9q/r9hpk=
+github.com/go-openapi/loads v0.17.0/go.mod h1:72tmFy5wsWx89uEVddd0RjRWPZm92WRLhf7AC+0+OOU=
+github.com/go-openapi/loads v0.18.0/go.mod h1:72tmFy5wsWx89uEVddd0RjRWPZm92WRLhf7AC+0+OOU=
+github.com/go-openapi/loads v0.19.0/go.mod h1:72tmFy5wsWx89uEVddd0RjRWPZm92WRLhf7AC+0+OOU=
+github.com/go-openapi/loads v0.19.2/go.mod h1:QAskZPMX5V0C2gvfkGZzJlINuP7Hx/4+ix5jWFxsNPs=
+github.com/go-openapi/loads v0.19.3/go.mod h1:YVfqhUCdahYwR3f3iiwQLhicVRvLlU/WO5WPaZvcvSI=
+github.com/go-openapi/loads v0.19.5/go.mod h1:dswLCAdonkRufe/gSUC3gN8nTSaB9uaS2es0x5/IbjY=
+github.com/go-openapi/loads v0.19.6/go.mod h1:brCsvE6j8mnbmGBh103PT/QLHfbyDxA4hsKvYBNEGVc=
+github.com/go-openapi/loads v0.19.7/go.mod h1:brCsvE6j8mnbmGBh103PT/QLHfbyDxA4hsKvYBNEGVc=
+github.com/go-openapi/loads v0.20.0/go.mod h1:2LhKquiE513rN5xC6Aan6lYOSddlL8Mp20AW9kpviM4=
+github.com/go-openapi/loads v0.20.2/go.mod h1:hTVUotJ+UonAMMZsvakEgmWKgtulweO9vYP2bQYKA/o=
+github.com/go-openapi/loads v0.21.0 h1:jYtUO4wwP7psAweisP/MDoOpdzsYEESdoPcsWjHDR68=
+github.com/go-openapi/loads v0.21.0/go.mod h1:rHYve9nZrQ4CJhyeIIFJINGCg1tQpx2yJrrNo8sf1ws=
+github.com/go-openapi/runtime v0.0.0-20180920151709-4f900dc2ade9/go.mod h1:6v9a6LTXWQCdL8k1AO3cvqx5OtZY/Y9wKTgaoP6YRfA=
+github.com/go-openapi/runtime v0.19.0/go.mod h1:OwNfisksmmaZse4+gpV3Ne9AyMOlP1lt4sK4FXt0O64=
+github.com/go-openapi/runtime v0.19.4/go.mod h1:X277bwSUBxVlCYR3r7xgZZGKVvBd/29gLDlFGtJ8NL4=
+github.com/go-openapi/runtime v0.19.15/go.mod h1:dhGWCTKRXlAfGnQG0ONViOZpjfg0m2gUt9nTQPQZuoo=
+github.com/go-openapi/runtime v0.19.16/go.mod h1:5P9104EJgYcizotuXhEuUrzVc+j1RiSjahULvYmlv98=
+github.com/go-openapi/runtime v0.19.24/go.mod h1:Lm9YGCeecBnUUkFTxPC4s1+lwrkJ0pthx8YvyjCfkgk=
+github.com/go-openapi/runtime v0.21.1 h1:/KIG00BzA2x2HRStX2tnhbqbQdPcFlkgsYCiNY20FZs=
+github.com/go-openapi/runtime v0.21.1/go.mod h1:aQg+kaIQEn+A2CRSY1TxbM8+sT9g2V3aLc1FbIAnbbs=
 github.com/go-openapi/spec v0.0.0-20160808142527-6aced65f8501/go.mod h1:J8+jY1nAiCcj+friV/PDoE1/3eeccG9LYBs0tYvLOWc=
+github.com/go-openapi/spec v0.17.0/go.mod h1:XkF/MOi14NmjsfZ8VtAKf8pIlbZzyoTvZsdfssdxcBI=
+github.com/go-openapi/spec v0.18.0/go.mod h1:XkF/MOi14NmjsfZ8VtAKf8pIlbZzyoTvZsdfssdxcBI=
+github.com/go-openapi/spec v0.19.2/go.mod h1:sCxk3jxKgioEJikev4fgkNmwS+3kuYdJtcsZsD5zxMY=
 github.com/go-openapi/spec v0.19.3/go.mod h1:FpwSN1ksY1eteniUU7X0N/BgJ7a4WvBFVA8Lj9mJglo=
+github.com/go-openapi/spec v0.19.6/go.mod h1:Hm2Jr4jv8G1ciIAo+frC/Ft+rR2kQDh8JHKHb3gWUSk=
+github.com/go-openapi/spec v0.19.8/go.mod h1:Hm2Jr4jv8G1ciIAo+frC/Ft+rR2kQDh8JHKHb3gWUSk=
+github.com/go-openapi/spec v0.19.15/go.mod h1:+81FIL1JwC5P3/Iuuozq3pPE9dXdIEGxFutcFKaVbmU=
+github.com/go-openapi/spec v0.20.0/go.mod h1:+81FIL1JwC5P3/Iuuozq3pPE9dXdIEGxFutcFKaVbmU=
+github.com/go-openapi/spec v0.20.1/go.mod h1:93x7oh+d+FQsmsieroS4cmR3u0p/ywH649a3qwC9OsQ=
+github.com/go-openapi/spec v0.20.3/go.mod h1:gG4F8wdEDN+YPBMVnzE85Rbhf+Th2DTvA9nFPQ5AYEg=
 github.com/go-openapi/spec v0.20.4 h1:O8hJrt0UMnhHcluhIdUgCLRWyM2x7QkBXRvOs7m+O1M=
 github.com/go-openapi/spec v0.20.4/go.mod h1:faYFR1CvsJZ0mNsmsphTMSoRrNV3TEDoAM7FOEWeq8I=
+github.com/go-openapi/strfmt v0.17.0/go.mod h1:P82hnJI0CXkErkXi8IKjPbNBM6lV6+5pLP5l494TcyU=
+github.com/go-openapi/strfmt v0.18.0/go.mod h1:P82hnJI0CXkErkXi8IKjPbNBM6lV6+5pLP5l494TcyU=
+github.com/go-openapi/strfmt v0.19.0/go.mod h1:+uW+93UVvGGq2qGaZxdDeJqSAqBqBdl+ZPMF/cC8nDY=
+github.com/go-openapi/strfmt v0.19.2/go.mod h1:0yX7dbo8mKIvc3XSKp7MNfxw4JytCfCD6+bY1AVL9LU=
+github.com/go-openapi/strfmt v0.19.3/go.mod h1:0yX7dbo8mKIvc3XSKp7MNfxw4JytCfCD6+bY1AVL9LU=
+github.com/go-openapi/strfmt v0.19.4/go.mod h1:eftuHTlB/dI8Uq8JJOyRlieZf+WkkxUuk0dgdHXr2Qk=
+github.com/go-openapi/strfmt v0.19.5/go.mod h1:eftuHTlB/dI8Uq8JJOyRlieZf+WkkxUuk0dgdHXr2Qk=
+github.com/go-openapi/strfmt v0.19.11/go.mod h1:UukAYgTaQfqJuAFlNxxMWNvMYiwiXtLsF2VwmoFtbtc=
+github.com/go-openapi/strfmt v0.20.0/go.mod h1:UukAYgTaQfqJuAFlNxxMWNvMYiwiXtLsF2VwmoFtbtc=
+github.com/go-openapi/strfmt v0.20.2/go.mod h1:43urheQI9dNtE5lTZQfuFJvjYJKPrxicATpEfZwHUNk=
 github.com/go-openapi/strfmt v0.21.0/go.mod h1:ZRQ409bWMj+SOgXofQAGTIo2Ebu72Gs+WaRADcS5iNg=
+github.com/go-openapi/strfmt v0.21.1 h1:G6s2t5V5kGCHLVbSdZ/6lI8Wm4OzoPFkc3/cjAsKQrM=
 github.com/go-openapi/strfmt v0.21.1/go.mod h1:I/XVKeLc5+MM5oPNN7P6urMOpuLXEcNrCX/rPGuWb0k=
-github.com/go-openapi/strfmt v0.21.2 h1:5NDNgadiX1Vhemth/TH4gCGopWSTdDjxl60H3B7f+os=
-github.com/go-openapi/strfmt v0.21.2/go.mod h1:I/XVKeLc5+MM5oPNN7P6urMOpuLXEcNrCX/rPGuWb0k=
 github.com/go-openapi/swag v0.0.0-20160704191624-1d0bd113de87/go.mod h1:DXUve3Dpr1UfpPtxFw+EFuQ41HhCWZfha5jSVRG7C7I=
+github.com/go-openapi/swag v0.17.0/go.mod h1:AByQ+nYG6gQg71GINrmuDXCPWdL640yX49/kXLo40Tg=
+github.com/go-openapi/swag v0.18.0/go.mod h1:AByQ+nYG6gQg71GINrmuDXCPWdL640yX49/kXLo40Tg=
 github.com/go-openapi/swag v0.19.2/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk=
 github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk=
+github.com/go-openapi/swag v0.19.7/go.mod h1:ao+8BpOPyKdpQz3AOJfbeEVpLmWAvlT1IfTe5McPyhY=
+github.com/go-openapi/swag v0.19.9/go.mod h1:ao+8BpOPyKdpQz3AOJfbeEVpLmWAvlT1IfTe5McPyhY=
+github.com/go-openapi/swag v0.19.12/go.mod h1:eFdyEBkTdoAf/9RXBvj4cr1nH7GD8Kzo5HTt47gr72M=
+github.com/go-openapi/swag v0.19.13/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ=
 github.com/go-openapi/swag v0.19.14/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ=
 github.com/go-openapi/swag v0.19.15/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ=
 github.com/go-openapi/swag v0.21.1 h1:wm0rhTb5z7qpJRHBdPOMuY4QjVUMbF6/kwoYeRAOrKU=
 github.com/go-openapi/swag v0.21.1/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ=
-github.com/go-openapi/validate v0.21.0 h1:+Wqk39yKOhfpLqNLEC0/eViCkzM5FVXVqrvt526+wcI=
-github.com/go-openapi/validate v0.21.0/go.mod h1:rjnrwK57VJ7A8xqfpAOEKRH8yQSGUriMu5/zuPSQ1hg=
-github.com/go-ping/ping v0.0.0-20211130115550-779d1e919534 h1:dhy9OQKGBh4zVXbjwbxxHjRxMJtLXj3zfgpBYQaR4Q4=
-github.com/go-ping/ping v0.0.0-20211130115550-779d1e919534/go.mod h1:xIFjORFzTxqIV/tDVGO4eDy/bLuSyawEeojSm3GfRGk=
+github.com/go-openapi/validate v0.18.0/go.mod h1:Uh4HdOzKt19xGIGm1qHf/ofbX1YQ4Y+MYsct2VUrAJ4=
+github.com/go-openapi/validate v0.19.2/go.mod h1:1tRCw7m3jtI8eNWEEliiAqUIcBztB2KDnRCRMUi7GTA=
+github.com/go-openapi/validate v0.19.3/go.mod h1:90Vh6jjkTn+OT1Eefm0ZixWNFjhtOH7vS9k0lo6zwJo=
+github.com/go-openapi/validate v0.19.10/go.mod h1:RKEZTUWDkxKQxN2jDT7ZnZi2bhZlbNMAuKvKB+IaGx8=
+github.com/go-openapi/validate v0.19.12/go.mod h1:Rzou8hA/CBw8donlS6WNEUQupNvUZ0waH08tGe6kAQ4=
+github.com/go-openapi/validate v0.19.15/go.mod h1:tbn/fdOwYHgrhPBzidZfJC2MIVvs9GA7monOmWBbeCI=
+github.com/go-openapi/validate v0.20.1/go.mod h1:b60iJT+xNNLfaQJUqLI7946tYiFEOuE9E4k54HpKcJ0=
+github.com/go-openapi/validate v0.20.3 h1:GZPPhhKSZrE8HjB4eEkoYAZmoWA4+tCemSgINH1/vKw=
+github.com/go-openapi/validate v0.20.3/go.mod h1:goDdqVGiigM3jChcrYJxD2joalke3ZXeftD16byIjA4=
 github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
+github.com/go-stack/stack v1.8.0 h1:5SgMzNM5HxrEjV0ww2lTmX6E2Izsfxas4+YHWRs3Lsk=
 github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
-github.com/go-stack/stack v1.8.1 h1:ntEHSVwIt7PNXNpgPmVfMrNhLtgjlmnZha2kOpuRiDw=
-github.com/go-stack/stack v1.8.1/go.mod h1:dcoOX6HbPZSZptuspn9bctJ+N/CnF5gGygcUP3XYfe4=
 github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE=
 github.com/gobuffalo/attrs v0.0.0-20190224210810-a9411de4debd/go.mod h1:4duuawTqi2wkkpB4ePgWMaai6/Kc6WEz83bhFwpHzj0=
 github.com/gobuffalo/depgen v0.0.0-20190329151759-d478694a28d3/go.mod h1:3STtPUQYuzV0gBVOY3vy6CfMm/ljR4pABfrTeHNLHUY=
@@ -659,12 +731,14 @@ github.com/linuxkit/virtsock v0.0.0-20201010232012-f8cee7dfc7a3/go.mod h1:3r6x7q
 github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
 github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
 github.com/mailru/easyjson v0.0.0-20160728113105-d5b7844b561a/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
+github.com/mailru/easyjson v0.0.0-20180823135443-60711f1a8329/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
+github.com/mailru/easyjson v0.0.0-20190312143242-1de009706dbe/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
 github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
 github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
 github.com/mailru/easyjson v0.7.0/go.mod h1:KAzv3t3aY1NaHWoQz1+4F1ccyAH66Jk7yos7ldAVICs=
+github.com/mailru/easyjson v0.7.1/go.mod h1:KAzv3t3aY1NaHWoQz1+4F1ccyAH66Jk7yos7ldAVICs=
+github.com/mailru/easyjson v0.7.6 h1:8yTIVnZgCoiM1TgqoeTl+LfU5Jg6/xL3QhGQnimLYnA=
 github.com/mailru/easyjson v0.7.6/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
-github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0=
-github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
 github.com/markbates/oncer v0.0.0-20181203154359-bf2de49a0be2/go.mod h1:Ld9puTsIW75CHf65OeIOkyKbteujpZVXDpWK6YGZbxE=
 github.com/markbates/safe v1.0.1/go.mod h1:nAqgmRi7cY2nqMc92/bSEeQA+R4OheNU2T1kNSCBdG0=
 github.com/marstr/guid v1.1.0/go.mod h1:74gB1z2wpxxInTG6yaqA7KrtM0NZ+RbrcqDvYHefzho=
@@ -681,8 +755,8 @@ github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182aff
 github.com/maxbrunsfeld/counterfeiter/v6 v6.2.2/go.mod h1:eD9eIE7cdwcMi9rYluz88Jz2VyhSmden33/aXg4oVIY=
 github.com/mdlayher/socket v0.2.0 h1:EY4YQd6hTAg2tcXF84p5DTHazShE50u5HeBzBaNgjkA=
 github.com/mdlayher/socket v0.2.0/go.mod h1:QLlNPkFR88mRUNQIzRBMfXxwKal8H7u1h3bL1CV+f0E=
-github.com/mdlayher/vsock v1.1.1 h1:8lFuiXQnmICBrCIIA9PMgVSke6Fg6V4+r0v7r55k88I=
-github.com/mdlayher/vsock v1.1.1/go.mod h1:Y43jzcy7KM3QB+/FK15pfqGxDMCMzUXWegEfIbSM18U=
+github.com/mdlayher/vsock v1.1.0 h1:2k9udP/hUkLUOboGxXMHOk4f0GWWZwS3IuE3Ee/YYfk=
+github.com/mdlayher/vsock v1.1.0/go.mod h1:nsVhPsVuBBwAKh6i6PzdNoke6/TNYTjkxoRKAp/+pXs=
 github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg=
 github.com/miekg/dns v1.1.25 h1:dFwPR6SfLtrSwgDcIq2bcU/gVutB4sNApq2HBdqcakg=
 github.com/miekg/dns v1.1.25/go.mod h1:bPDLeHnStXmXAq1m/Ch/hvfNHr14JKNPMBo3VZKjuso=
@@ -697,10 +771,11 @@ github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS4
 github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY=
 github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
 github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
+github.com/mitchellh/mapstructure v1.3.2/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
 github.com/mitchellh/mapstructure v1.3.3/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
+github.com/mitchellh/mapstructure v1.4.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
+github.com/mitchellh/mapstructure v1.4.1 h1:CpVNEelQCZBooIPDn+AR3NpivK/TIKU8bDxdASFVQag=
 github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
-github.com/mitchellh/mapstructure v1.4.3 h1:OVowDSCllw/YjdLkam3/sm7wEtOy59d8ndGgCcyj8cs=
-github.com/mitchellh/mapstructure v1.4.3/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
 github.com/mitchellh/osext v0.0.0-20151018003038-5e2d6d41470f/go.mod h1:OkQIRizQZAeMln+1tSwduZz7+Af5oFlKirV/MSYes2A=
 github.com/moby/locker v1.0.1 h1:fOXqR41zeveg4fFODix+1Ch4mj/gT0NE1XJbp/epuBg=
 github.com/moby/locker v1.0.1/go.mod h1:S7SDdo5zpBK84bzzVlKr2V0hz+7x9hWbYC/kq7oQppc=
@@ -799,6 +874,7 @@ github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFSt
 github.com/opentracing/opentracing-go v1.2.0 h1:uEJPy/1a5RIPAJ0Ov+OIO8OxWu77jEv+1B0VhjKrZUs=
 github.com/opentracing/opentracing-go v1.2.0/go.mod h1:GxEUsuufX4nBwe+T+Wl9TAgYrxe9dPLANfrWvHYVTgc=
 github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
+github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k=
 github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
 github.com/pelletier/go-toml v1.7.0/go.mod h1:vwGMzjaWMwyfHwgIBhI2YUM4fB6nL6lVAvS1LBMMhTE=
 github.com/pelletier/go-toml v1.8.1/go.mod h1:T2/BmBdy8dvIRq1a/8aqjN41wvWlN4lrapLU/GW4pbc=
@@ -868,6 +944,7 @@ github.com/sclevine/spec v1.2.0/go.mod h1:W4J29eT/Kzv7/b9IWLB055Z+qvVC9vt0Arko24
 github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc=
 github.com/seccomp/libseccomp-golang v0.9.1/go.mod h1:GbW5+tmTXfcxTToHLXlScSlAvWlF4P2Ca7zGrPiEpWo=
 github.com/seccomp/libseccomp-golang v0.9.2-0.20210429002308-3879420cc921/go.mod h1:JA8cRccbGaA1s33RQf7Y1+q9gHmZX1yB/z9WDN1C6fg=
+github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo=
 github.com/shirou/gopsutil v2.18.12+incompatible h1:1eaJvGomDnH74/5cF4CTmTbLHAriGFsTZppLXDX93OM=
 github.com/shirou/gopsutil v2.18.12+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA=
 github.com/shirou/w32 v0.0.0-20160930032740-bb4de0191aa4 h1:udFKJ0aHUL60LboW/A+DfgoHVedieIzIXE8uylPue0U=
@@ -890,6 +967,8 @@ github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9
 github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM=
 github.com/soheilhy/cmux v0.1.5/go.mod h1:T7TcVDs9LWfQgPlPsdngu6I6QIoyIFZDDC6sNE1GqG0=
 github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
+github.com/sparrc/go-ping v0.0.0-20190613174326-4e5b6552494c h1:gqEdF4VwBu3lTKGHS9rXE9x1/pEaSwCXRLOZRF6qtlw=
+github.com/sparrc/go-ping v0.0.0-20190613174326-4e5b6552494c/go.mod h1:eMyUVp6f/5jnzM+3zahzl7q6UXLbgSc3MKg/+ow9QW0=
 github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ=
 github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk=
 github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
@@ -940,6 +1019,7 @@ github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijb
 github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
 github.com/urfave/cli v1.22.2 h1:gsqYFH8bb9ekPA12kRo0hfjngWQjkJPlN9R0N78BoUo=
 github.com/urfave/cli v1.22.2/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
+github.com/vektah/gqlparser v1.1.2/go.mod h1:1ycwN7Ij5njmMkPPAOaRFY4rET2Enx7IkVv3vaXspKw=
 github.com/vishvananda/netlink v0.0.0-20181108222139-023a6dafdcdf/go.mod h1:+SR5DhBJrl6ZM7CoCKvpw5BKroDKQ+PJqOg65H/2ktk=
 github.com/vishvananda/netlink v1.1.0/go.mod h1:cTgwzPIzzgDAYoQrMm0EdrjRUBkTqKYppBueQtXaqoE=
 github.com/vishvananda/netlink v1.1.1-0.20201029203352-d40f9887b852/go.mod h1:twkDnbuQxJYemMlGd4JFIcuhgX83tXhKS2B/PRMpOho=
@@ -1034,10 +1114,12 @@ golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnf
 golang.org/x/crypto v0.0.0-20181009213950-7c1a557ab941/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
 golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
 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-20190422162423-af44ce270edf/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE=
 golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
 golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
 golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
+golang.org/x/crypto v0.0.0-20190617133340-57b3e21c3d56/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
 golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
 golang.org/x/crypto v0.0.0-20190923035154-9ee001bba392/go.mod h1:/lpIB1dKB+9EgE3H3cr1v9wB50oz8l4C4h62xy7jSTY=
 golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
@@ -1069,6 +1151,7 @@ golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHl
 golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs=
 golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
 golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
+golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5 h1:2M3HP5CCK1Si9FQhwnzYhXdG6DXeebvUHFpre8QvbyI=
 golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
 golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE=
 golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o=
@@ -1080,9 +1163,11 @@ golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
 golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
 golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
 golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
+golang.org/x/mod v0.4.2 h1:Gz96sIWK3OalVv/I/qNygP42zyoKp3xptRVCWRFEBvo=
 golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
 golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
 golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
+golang.org/x/net v0.0.0-20181005035420-146acd28ed58/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
 golang.org/x/net v0.0.0-20181011144130-49bb7cea24b1/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
 golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
 golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@@ -1090,6 +1175,7 @@ golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73r
 golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
 golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
 golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
+golang.org/x/net v0.0.0-20190320064053-1272bf9dcd53/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
 golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
 golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
 golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
@@ -1116,6 +1202,7 @@ golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/
 golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
 golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
 golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
+golang.org/x/net v0.0.0-20200602114024-627f9648deb9/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
 golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
 golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
 golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
@@ -1174,6 +1261,7 @@ golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5h
 golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190321052220-f7bb7a8bee54/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20190403152447-81d4e9dc473e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20190419153524-e8e3143a4f4a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@@ -1300,6 +1388,7 @@ golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGm
 golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
 golang.org/x/tools v0.0.0-20181011042414-1f849cf54d09/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
 golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
+golang.org/x/tools v0.0.0-20190125232054-d66bd3c5d5a6/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
 golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
 golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
 golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
@@ -1313,6 +1402,7 @@ golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBn
 golang.org/x/tools v0.0.0-20190531172133-b3315ee88b7d/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
 golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
 golang.org/x/tools v0.0.0-20190614205625-5aca471b1d59/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
+golang.org/x/tools v0.0.0-20190617190820-da514acc4774/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
 golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
 golang.org/x/tools v0.0.0-20190624222133-a101b041ded4/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
 golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
@@ -1361,6 +1451,7 @@ golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4f
 golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
 golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0=
 golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
+golang.org/x/tools v0.1.5 h1:ouewzE6p+/VEB31YYnTbEJdi8pFqKp4P4n85vwo3DHA=
 golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
 golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
 golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
diff --git a/internal/vm/oci.go b/internal/vm/oci.go
index a07a13e..7b20e00 100644
--- a/internal/vm/oci.go
+++ b/internal/vm/oci.go
@@ -42,7 +42,7 @@ import (
 )
 
 // UpdateUserInSpec modifies a serialized json spec object with user information from inside the container.
-// If the client used firecrackeroci.WithVmLocalImageConfig or firecrakceroci.WithVmLocalUser, this
+// If the client used firecrackeroci.WithVMLocalImageConfig or firecrackeroci.WithVMLocalUser, this
 // method will do the mapping between username -> uid, group name -> gid, and lookup additional groups for the user.
 // This is used to split where the user configures a spec via containerd's oci methods in the client
 // from where the data is actually present (from the agent inside the VM)
diff --git a/internal/vm/vsock.go b/internal/vm/vsock.go
index 5162309..c613e40 100644
--- a/internal/vm/vsock.go
+++ b/internal/vm/vsock.go
@@ -14,13 +14,121 @@
 package vm
 
 import (
+	"bufio"
 	"context"
+	"fmt"
+	"net"
+	"strings"
 	"time"
 
-	"github.com/firecracker-microvm/firecracker-go-sdk/vsock"
+	"github.com/mdlayher/vsock"
+	"github.com/pkg/errors"
 	"github.com/sirupsen/logrus"
 )
 
+const (
+	vsockRetryTimeout      = 20 * time.Second
+	vsockRetryInterval     = 100 * time.Millisecond
+	unixDialTimeout        = 100 * time.Millisecond
+	vsockConnectMsgTimeout = 100 * time.Millisecond
+	vsockAckMsgTimeout     = 1 * time.Second
+)
+
+// VSockDial attempts to connect to the Firecracker host-side vsock at the provided unix
+// path and port. It will retry connect attempts if a temporary error is encountered (up
+// to a fixed timeout) or the provided request is canceled.
+func VSockDial(ctx context.Context, logger *logrus.Entry, udsPath string, port uint32) (net.Conn, error) {
+	ticker := time.NewTicker(vsockRetryInterval)
+	defer ticker.Stop()
+	tickerCh := ticker.C
+	var attemptCount int
+	for {
+		attemptCount++
+		logger := logger.WithField("attempt", attemptCount)
+
+		select {
+		case <-ctx.Done():
+			return nil, ctx.Err()
+		case <-tickerCh:
+			conn, err := tryConnect(logger, udsPath, port)
+			if isTemporaryNetErr(err) {
+				err = errors.Wrap(err, "temporary vsock dial failure")
+				logger.WithError(err).Debug()
+				continue
+			} else if err != nil {
+				err = errors.Wrap(err, "non-temporary vsock dial failure")
+				logger.WithError(err).Error()
+				return nil, err
+			}
+
+			return conn, nil
+		}
+	}
+}
+
+type vsockListener struct {
+	listener net.Listener
+	port     uint32
+	ctx      context.Context
+	logger   *logrus.Entry
+}
+
+// VSockListener returns a net.Listener implementation for guest-side Firecracker vsock
+// connections.
+func VSockListener(ctx context.Context, logger *logrus.Entry, port uint32) (net.Listener, error) {
+	listener, err := vsock.Listen(port, nil)
+	if err != nil {
+		return nil, err
+	}
+
+	return vsockListener{
+		listener: listener,
+		port:     port,
+		ctx:      ctx,
+		logger:   logger,
+	}, nil
+}
+
+func (l vsockListener) Accept() (net.Conn, error) {
+	ctx, cancel := context.WithTimeout(l.ctx, vsockRetryTimeout)
+	defer cancel()
+
+	var attemptCount int
+	ticker := time.NewTicker(vsockRetryInterval)
+	defer ticker.Stop()
+	tickerCh := ticker.C
+	for {
+		attemptCount++
+		logger := l.logger.WithField("attempt", attemptCount)
+
+		select {
+		case <-ctx.Done():
+			return nil, ctx.Err()
+		case <-tickerCh:
+			conn, err := tryAccept(logger, l.listener, l.port)
+			if isTemporaryNetErr(err) {
+				err = errors.Wrap(err, "temporary vsock accept failure")
+				logger.WithError(err).Debug()
+				continue
+			} else if err != nil {
+				err = errors.Wrap(err, "non-temporary vsock accept failure")
+				logger.WithError(err).Error()
+				return nil, err
+			}
+
+			return conn, nil
+		}
+	}
+}
+
+func (l vsockListener) Close() error {
+	return l.listener.Close()
+}
+
+func (l vsockListener) Addr() net.Addr {
+	return l.listener.Addr()
+}
+
 // VSockDialConnector returns an IOConnector for establishing vsock connections
 // that are dialed from the host to a guest listener.
 func VSockDialConnector(timeout time.Duration, udsPath string, port uint32) IOConnector {
@@ -32,7 +140,7 @@ func VSockDialConnector(timeout time.Duration, udsPath string, port uint32) IOCo
 			timeoutCtx, cancel := context.WithTimeout(procCtx, timeout)
 			defer cancel()
 
-			conn, err := vsock.DialContext(timeoutCtx, udsPath, port, vsock.WithLogger(logger))
+			conn, err := VSockDial(timeoutCtx, logger, udsPath, port)
 			returnCh <- IOConnectorResult{
 				ReadWriteCloser: conn,
 				Err:             err,
@@ -49,7 +157,7 @@ func VSockAcceptConnector(port uint32) IOConnector {
 	return func(procCtx context.Context, logger *logrus.Entry) <-chan IOConnectorResult {
 		returnCh := make(chan IOConnectorResult)
 
-		listener, err := vsock.Listener(procCtx, logger, port)
+		listener, err := VSockListener(procCtx, logger, port)
 		if err != nil {
 			returnCh <- IOConnectorResult{
 				Err: err,
@@ -72,3 +180,143 @@ func VSockAcceptConnector(port uint32) IOConnector {
 		return returnCh
 	}
 }
+
+func vsockConnectMsg(port uint32) string {
+	// The message a host-side connection must write after connecting to a firecracker
+	// vsock unix socket in order to establish a connection with a guest-side listener
+	// at the provided port number. This is specified in Firecracker documentation:
+	// https://github.com/firecracker-microvm/firecracker/blob/main/docs/vsock.md#host-initiated-connections
+	return fmt.Sprintf("CONNECT %d\n", port)
+}
+
+// tryConnect attempts to dial a guest vsock listener at the provided host-side
+// unix socket and provided guest-listener port.
+func tryConnect(logger *logrus.Entry, udsPath string, port uint32) (net.Conn, error) {
+	conn, err := net.DialTimeout("unix", udsPath, unixDialTimeout)
+	if err != nil {
+		return nil, errors.Wrapf(err, "failed to dial %q within %s", udsPath, unixDialTimeout)
+	}
+
+	defer func() {
+		if err != nil {
+			closeErr := conn.Close()
+			if closeErr != nil {
+				logger.WithError(closeErr).Error(
+					"failed to close vsock socket after previous error")
+			}
+		}
+	}()
+
+	msg := vsockConnectMsg(port)
+	err = tryConnWrite(conn, msg, vsockConnectMsgTimeout)
+	if err != nil {
+		return nil, vsockConnectMsgError{
+			cause: errors.Wrapf(err, `failed to write %q within %s`, msg, vsockConnectMsgTimeout),
+		}
+	}
+
+	line, err := tryConnReadUntil(conn, '\n', vsockAckMsgTimeout)
+	if err != nil {
+		return nil, vsockAckError{
+			cause: errors.Wrapf(err, `failed to read "OK <port>" within %s`, vsockAckMsgTimeout),
+		}
+	}
+
+	// The line would be "OK <assigned_hostside_port>\n", but we don't use the hostside port here.
+	// https://github.com/firecracker-microvm/firecracker/blob/main/docs/vsock.md#host-initiated-connections
+	if !strings.HasPrefix(line, "OK ") {
+		return nil, vsockAckError{
+			cause: errors.Errorf(`expected to read "OK <port>", but instead read %q`, line),
+		}
+	}
+	return conn, nil
+}
+
+// tryAccept attempts to accept a single host-side connection from the provided
+// guest-side listener at the provided port.
+func tryAccept(logger *logrus.Entry, listener net.Listener, port uint32) (net.Conn, error) {
+	conn, err := listener.Accept()
+	if err != nil {
+		return nil, err
+	}
+
+	defer func() {
+		if err != nil {
+			closeErr := conn.Close()
+			if closeErr != nil {
+				logger.WithError(closeErr).Error(
+					"failed to close vsock after previous error")
+			}
+		}
+	}()
+
+	return conn, nil
+}
+
+// tryConnReadUntil will try to do a read from the provided conn until the specified
+// end character is encounteed. Returning an error if the read does not complete
+// within the provided timeout. It will reset socket deadlines to none after returning.
+// It's only intended to be used for connect/ack messages, not general purpose reads
+// after the vsock connection is established fully.
+func tryConnReadUntil(conn net.Conn, end byte, timeout time.Duration) (string, error) {
+	conn.SetDeadline(time.Now().Add(timeout))
+	defer conn.SetDeadline(time.Time{})
+
+	return bufio.NewReaderSize(conn, 32).ReadString(end)
+}
+
+// tryConnWrite will try to do a write to the provided conn, returning an error if
+// the write fails, is partial or does not complete within the provided timeout. It
+// will reset socket deadlines to none after returning. It's only intended to be
+// used for connect/ack messages, not general purpose writes after the vsock
+// connection is established fully.
+func tryConnWrite(conn net.Conn, expectedWrite string, timeout time.Duration) error {
+	conn.SetDeadline(time.Now().Add(timeout))
+	defer conn.SetDeadline(time.Time{})
+
+	bytesWritten, err := conn.Write([]byte(expectedWrite))
+	if err != nil {
+		return err
+	}
+	if bytesWritten != len(expectedWrite) {
+		return errors.Errorf("incomplete write, expected %d bytes but wrote %d",
+			len(expectedWrite), bytesWritten)
+	}
+
+	return nil
+}
+
+type vsockConnectMsgError struct {
+	cause error
+}
+
+func (e vsockConnectMsgError) Error() string {
+	return errors.Wrap(e.cause, "vsock connect message failure").Error()
+}
+
+func (e vsockConnectMsgError) Temporary() bool {
+	return false
+}
+
+type vsockAckError struct {
+	cause error
+}
+
+func (e vsockAckError) Error() string {
+	return errors.Wrap(e.cause, "vsock ack message failure").Error()
+}
+
+func (e vsockAckError) Temporary() bool {
+	return true
+}
+
+// isTemporaryNetErr returns whether the provided error is a retriable
+// error, according to the interface defined here:
+// https://golang.org/pkg/net/#Error
+func isTemporaryNetErr(err error) bool {
+	type tempError interface {
+		Temporary() bool
+	}
+	var terr tempError
+	return err != nil && errors.As(err, &terr) && terr.Temporary()
+}
diff --git a/runtime/README.md b/runtime/README.md
index b331a2c..e08d707 100644
--- a/runtime/README.md
+++ b/runtime/README.md
@@ -3,7 +3,7 @@
 This is the runtime component enabling containerd to control the Firecracker
 VMM.  This component runs on the host, outside your microVM. In general, it
 strives for
-[OCI runtime](https://github.com/opencontainers/runtime-spec/blob/main/spec.md)
+[OCI runtime](https://github.com/opencontainers/runtime-spec/blob/master/spec.md)
 compliance within the bounds of Firecracker's feature set.
 
 ## Building
@@ -20,7 +20,7 @@ installed and configured.
 
 Copy `containerd-shim-aws-firecracker` to /bin (or something else on the PATH)
 following the naming guidelines for a containerd
-[runtime v2](https://github.com/containerd/containerd/blob/main/runtime/v2/README.md)
+[runtime v2](https://github.com/containerd/containerd/blob/master/runtime/v2/README.md)
 shim:
 
 	* If the runtime is invoked as aws.firecracker
diff --git a/runtime/firecrackeroci/vm.go b/runtime/firecrackeroci/vm.go
index 4ac89b5..79d10f2 100644
--- a/runtime/firecrackeroci/vm.go
+++ b/runtime/firecrackeroci/vm.go
@@ -47,11 +47,11 @@ var (
 	}
 )
 
-// WithVmLocalImageConfig configures a spec with the content of the image's config.
+// WithVMLocalImageConfig configures a spec with the content of the image's config.
 // It is similar to containerd's oci.WithImageConfig except that it does not access
 // the image's rootfs on the host. Instead, it configures what it can on the host and
 // passes information to the agent running in the VM to inspect the image's rootfs.
-func WithVmLocalImageConfig(image containerd.Image) oci.SpecOpts {
+func WithVMLocalImageConfig(image containerd.Image) oci.SpecOpts {
 	return func(ctx context.Context, client oci.Client, container *containers.Container, spec *oci.Spec) error {
 		ic, err := image.Config(ctx)
 		if err != nil {
@@ -85,7 +85,8 @@ func WithVmLocalImageConfig(image containerd.Image) oci.SpecOpts {
 		}
 		spec.Process.Env = replaceOrAppendEnvValues(defaults, spec.Process.Env)
 		cmd := config.Cmd
-		spec.Process.Args = append(config.Entrypoint, cmd...)
+		spec.Process.Args = append([]string{}, config.Entrypoint...)
+		spec.Process.Args = append(spec.Process.Args, cmd...)
 
 		cwd := config.WorkingDir
 		if cwd == "" {
@@ -93,17 +94,17 @@ func WithVmLocalImageConfig(image containerd.Image) oci.SpecOpts {
 		}
 		spec.Process.Cwd = cwd
 		if config.User != "" {
-			WithVmLocalUser(config.User)(ctx, client, container, spec)
+			WithVMLocalUser(config.User)(ctx, client, container, spec)
 		}
 		return nil
 	}
 }
 
-// WithVmLocalUser configures the user of the spec.
+// WithVMLocalUser configures the user of the spec.
 // It is similar to oci.WithUser except that it doesn't map
 // username -> uid or group name -> gid. It passes the user to the
 // agent running inside the VM to do that mapping.
-func WithVmLocalUser(user string) oci.SpecOpts {
+func WithVMLocalUser(user string) oci.SpecOpts {
 	return func(ctx context.Context, client oci.Client, container *containers.Container, spec *oci.Spec) error {
 		// This is technically an LCOW specific field, but we piggy back
 		// to get the string user into the VM where will will do the uid/gid mapping
diff --git a/runtime/service.go b/runtime/service.go
index cbb868c..f3d4b6e 100644
--- a/runtime/service.go
+++ b/runtime/service.go
@@ -44,7 +44,6 @@ import (
 	"github.com/containerd/ttrpc"
 	"github.com/firecracker-microvm/firecracker-go-sdk"
 	"github.com/firecracker-microvm/firecracker-go-sdk/client/models"
-	"github.com/firecracker-microvm/firecracker-go-sdk/vsock"
 	"github.com/gofrs/uuid"
 	"github.com/gogo/protobuf/types"
 	"github.com/hashicorp/go-multierror"
@@ -82,8 +81,6 @@ const (
 	defaultShutdownTimeout     = 5 * time.Second
 	defaultVSockConnectTimeout = 5 * time.Second
 
-	jailerStopTimeout = 3 * time.Second
-
 	// StartEventName is the topic published to when a VM starts
 	StartEventName = "/firecracker-vm/start"
 
@@ -602,7 +599,7 @@ func (s *service) createVM(requestCtx context.Context, request *proto.CreateVMRe
 	}
 
 	s.logger.Info("calling agent")
-	conn, err := vsock.DialContext(requestCtx, relVSockPath, defaultVsockPort, vsock.WithLogger(s.logger))
+	conn, err := vm.VSockDial(requestCtx, s.logger, relVSockPath, defaultVsockPort)
 	if err != nil {
 		return errors.Wrapf(err, "failed to dial the VM over vsock")
 	}
@@ -900,7 +897,7 @@ func (s *service) GetBalloonStats(requestCtx context.Context, req *proto.GetBall
 	return resp, nil
 }
 
-//UpdateBalloonStats will update an existing balloon device statistics interval, before or after machine startup.
+// UpdateBalloonStats will update an existing balloon device statistics interval, before or after machine startup.
 func (s *service) UpdateBalloonStats(requestCtx context.Context, req *proto.UpdateBalloonStatsRequest) (*types.Empty, error) {
 	defer logPanicAndDie(s.logger)
 
@@ -1176,11 +1173,11 @@ func (s *service) Create(requestCtx context.Context, request *taskAPI.CreateTask
 	}
 	rootfsMnt := request.Rootfs[0]
 
-	isVmLocalRootfs := vm.IsLocalMount(rootfsMnt)
+	isVMLocalRootfs := vm.IsLocalMount(rootfsMnt)
 
 	// Only mount the container's rootfs as a block device if the mount doesn't
 	// signal that it is only accessible from inside the VM.
-	if !isVmLocalRootfs {
+	if !isVMLocalRootfs {
 		err = s.containerStubHandler.Reserve(requestCtx, request.ID,
 			rootfsMnt.Source, vmBundleDir.RootfsPath(), "ext4", nil, s.driveMountClient, s.machine)
 		if err != nil {
@@ -1217,7 +1214,7 @@ func (s *service) Create(requestCtx context.Context, request *taskAPI.CreateTask
 	// override the request with the bundle dir that should be used inside the VM
 	request.Bundle = vmBundleDir.RootPath()
 
-	if !isVmLocalRootfs {
+	if !isVMLocalRootfs {
 		// If the rootfs is not inside the VM, it is mounted via a MountDrive call,
 		// so unset Rootfs in the request.
 		// We unfortunately can't rely on just having the runc shim inside the VM do


Test patch:
diff --git a/internal/common_test.go b/internal/common_test.go
index 6723006..d91bc42 100644
--- a/internal/common_test.go
+++ b/internal/common_test.go
@@ -70,7 +70,8 @@ func TestGenerateStubContent(t *testing.T) {
 	stubContent, err := GenerateStubContent(driveID)
 	assert.NoError(t, err)
 
-	expected := append(MagicStubBytes, byte(len(driveID)))
+	expected := append([]byte{}, MagicStubBytes...)
+	expected = append(expected, byte(len(driveID)))
 	expected = append(expected, []byte(driveID)...)
 	assert.Equal(t, string(expected), stubContent)
 }
@@ -83,7 +84,8 @@ func TestGenerateStubContent_LongID(t *testing.T) {
 
 func TestParseStubContent(t *testing.T) {
 	expectedDriveID := "foo"
-	contents := append(MagicStubBytes, byte(len(expectedDriveID)))
+	contents := append([]byte{}, MagicStubBytes...)
+	contents = append(contents, byte(len(expectedDriveID)))
 	contents = append(contents, []byte(expectedDriveID)...)
 	contents = append(contents, []byte("junkcontent")...)
 
diff --git a/internal/vm/dir_test.go b/internal/vm/dir_test.go
index 3660cae..a3fec01 100644
--- a/internal/vm/dir_test.go
+++ b/internal/vm/dir_test.go
@@ -14,17 +14,22 @@
 package vm
 
 import (
+	"io/ioutil"
+	"os"
 	"path"
 	"strings"
 	"testing"
 
 	"github.com/stretchr/testify/assert"
+	"github.com/stretchr/testify/require"
 )
 
 var invalidContainerIDs = []string{"", "id?", "*", "id/1", "id\\"}
 
 func TestShimDir(t *testing.T) {
-	runDir := t.TempDir()
+	runDir, err := ioutil.TempDir("", "run")
+	require.NoError(t, err)
+	defer os.RemoveAll(runDir)
 
 	tests := []struct {
 		name   string
diff --git a/internal/vm/ioproxy_test.go b/internal/vm/ioproxy_test.go
index 6108409..05cdaf7 100644
--- a/internal/vm/ioproxy_test.go
+++ b/internal/vm/ioproxy_test.go
@@ -41,12 +41,14 @@ func fileConnector(path string, flag int) IOConnector {
 }
 
 func TestProxy(t *testing.T) {
-	dir := t.TempDir()
+	dir, err := ioutil.TempDir("", t.Name())
+	require.NoError(t, err)
+	defer os.RemoveAll(dir)
 
 	ctx := context.Background()
 	content := "hello world"
 
-	err := ioutil.WriteFile(filepath.Join(dir, "input"), []byte(content), 0600)
+	err = ioutil.WriteFile(filepath.Join(dir, "input"), []byte(content), 0600)
 	require.NoError(t, err)
 
 	pair := &IOConnectorPair{
diff --git a/internal/vm/vsock_test.go b/internal/vm/vsock_test.go
new file mode 100644
index 0000000..5a05926
--- /dev/null
+++ b/internal/vm/vsock_test.go
@@ -0,0 +1,27 @@
+// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License"). You may
+// not use this file except in compliance with the License. A copy of the
+// License is located at
+//
+//	http://aws.amazon.com/apache2.0/
+//
+// or in the "license" file accompanying this file. This file is distributed
+// on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
+// express or implied. See the License for the specific language governing
+// permissions and limitations under the License.
+
+package vm
+
+import (
+	"errors"
+	"testing"
+
+	"github.com/stretchr/testify/assert"
+)
+
+func TestTemporaryNetErr(t *testing.T) {
+	assert.False(t, isTemporaryNetErr(nil))
+	assert.False(t, isTemporaryNetErr(errors.New("hello")))
+	assert.True(t, isTemporaryNetErr(&vsockAckError{cause: errors.New("hello")}))
+}
diff --git a/runtime/drive_handler_test.go b/runtime/drive_handler_test.go
index d41fdf6..14ddc99 100644
--- a/runtime/drive_handler_test.go
+++ b/runtime/drive_handler_test.go
@@ -15,12 +15,13 @@ package main
 
 import (
 	"context"
-	"io/ioutil"
 	"os"
 	"path/filepath"
 	"strconv"
 	"testing"
 
+	"io/ioutil"
+
 	"github.com/containerd/containerd/log"
 	"github.com/firecracker-microvm/firecracker-containerd/internal/vm"
 	"github.com/firecracker-microvm/firecracker-containerd/proto"
@@ -53,10 +54,12 @@ func TestContainerStubs(t *testing.T) {
 	ctx := context.Background()
 	logger := log.G(ctx)
 
-	tmpDir := t.TempDir()
+	tmpDir, err := ioutil.TempDir("", "TestCreateContainerStubs")
+	require.NoError(t, err, "failed to create temporary directory")
+	defer os.RemoveAll(tmpDir)
 
 	stubDir := filepath.Join(tmpDir, "stubs")
-	err := os.MkdirAll(stubDir, 0700)
+	err = os.MkdirAll(stubDir, 0700)
 	require.NoError(t, err, "failed to create stub dir")
 
 	patchedSrcDir := filepath.Join(tmpDir, "patchedSrcs")
@@ -124,10 +127,12 @@ func TestDriveMountStubs(t *testing.T) {
 	ctx := context.Background()
 	logger := log.G(ctx)
 
-	tmpDir := t.TempDir()
+	tmpDir, err := ioutil.TempDir("", "Test-CreateContainerStubs")
+	require.NoError(t, err, "failed to create temporary directory")
+	defer os.RemoveAll(tmpDir)
 
 	stubDir := filepath.Join(tmpDir, "stubs")
-	err := os.MkdirAll(stubDir, 0700)
+	err = os.MkdirAll(stubDir, 0700)
 	require.NoError(t, err, "failed to create stub dir")
 
 	patchedSrcDir := filepath.Join(tmpDir, "patchedSrcs")
diff --git a/runtime/jailer_integ_test.go b/runtime/jailer_integ_test.go
index 843b9fc..cf986bc 100644
--- a/runtime/jailer_integ_test.go
+++ b/runtime/jailer_integ_test.go
@@ -87,7 +87,7 @@ func TestAttachBlockDevice_Isolated(t *testing.T) {
 }
 
 func fsSafeTestName(tb testing.TB) string {
-	return strings.Replace(tb.Name(), "/", "-", -1)
+	return strings.ReplaceAll(tb.Name(), "/", "-")
 }
 
 func testJailer(t *testing.T, jailerConfig *proto.JailerConfig) {
diff --git a/runtime/jailer_test.go b/runtime/jailer_test.go
index 6a6dba0..c323544 100644
--- a/runtime/jailer_test.go
+++ b/runtime/jailer_test.go
@@ -15,6 +15,7 @@ package main
 
 import (
 	"context"
+	"io/ioutil"
 	"os"
 	"os/exec"
 	"path/filepath"
@@ -61,12 +62,14 @@ func createSparseFile(path string, size int) error {
 }
 
 func TestCopyFile_sparse(t *testing.T) {
-	dir := t.TempDir()
+	dir, err := ioutil.TempDir("", t.Name())
+	require.NoError(t, err)
+	defer os.RemoveAll(dir)
 
 	expectedSize := 1024
 
 	src := filepath.Join(dir, "original-sparse-file")
-	err := createSparseFile(src, expectedSize)
+	err = createSparseFile(src, expectedSize)
 	require.NoError(t, err)
 
 	dst := filepath.Join(dir, "copied-as-sparse")
@@ -101,7 +104,9 @@ func TestJailer_invalidUIDGID(t *testing.T) {
 func TestNewJailer_Isolated(t *testing.T) {
 	prepareIntegTest(t)
 
-	ociBundlePath := t.TempDir()
+	ociBundlePath, err := ioutil.TempDir("", t.Name())
+	require.NoError(t, err)
+	defer os.RemoveAll(ociBundlePath)
 	b, err := exec.Command(
 		"cp",
 		"firecracker-runc-config.json.example",
diff --git a/runtime/runc_jailer_test.go b/runtime/runc_jailer_test.go
index 698e033..366342f 100644
--- a/runtime/runc_jailer_test.go
+++ b/runtime/runc_jailer_test.go
@@ -35,8 +35,10 @@ import (
 
 func TestBuildJailedRootHandler_Isolated(t *testing.T) {
 	internal.RequiresIsolation(t)
-	dir := t.TempDir()
+	dir, err := ioutil.TempDir("", "TestBuildJailedRootHandler")
+	require.NoError(t, err, "failed to create temporary directory")
 
+	defer os.RemoveAll(dir)
 	kernelImagePath := filepath.Join(dir, "kernel-image")
 	kernelImageFd, err := os.OpenFile(kernelImagePath, os.O_CREATE, 0600)
 	require.NoError(t, err, "failed to create kernel image")
@@ -105,11 +107,12 @@ func TestMkdirAllWithPermissions_Isolated(t *testing.T) {
 	// requires isolation so we can change uid/gid of files
 	internal.RequiresIsolation(t)
 
-	tmpdir := t.TempDir()
+	tmpdir, err := ioutil.TempDir("", "TestMkdirAllWithPermissions")
+	require.NoError(t, err, "failed to create temporary directory")
 
 	existingPath := filepath.Join(tmpdir, "exists")
 	existingMode := os.FileMode(0700)
-	err := os.Mkdir(existingPath, existingMode)
+	err = os.Mkdir(existingPath, existingMode)
 	require.NoError(t, err, "failed to create existing part of test directory")
 
 	nonExistingPath := filepath.Join(existingPath, "nonexistent")
@@ -136,7 +139,9 @@ func TestBindMountToJail_Isolated(t *testing.T) {
 	// The user must be root to call chown.
 	internal.RequiresIsolation(t)
 
-	dir := t.TempDir()
+	dir, err := ioutil.TempDir("", t.Name())
+	require.NoError(t, err)
+	defer os.RemoveAll(dir)
 
 	f, err := os.Create(filepath.Join(dir, "src1"))
 	require.NoError(t, err)
@@ -191,12 +196,13 @@ func TestFifoHandler_Isolated(t *testing.T) {
 	for _, tc := range testcases {
 		tc := tc
 		t.Run(tc.name, func(t *testing.T) {
-			dir := t.TempDir()
+			dir, err := ioutil.TempDir("", testNameToVMID(t.Name()))
+			require.NoError(t, err)
 
 			logPath := filepath.Join(dir, tc.logPath)
 			metricsPath := filepath.Join(dir, tc.metricsPath)
 
-			err := os.MkdirAll(filepath.Dir(logPath), 0750)
+			err = os.MkdirAll(filepath.Dir(logPath), 0750)
 			require.NoError(t, err)
 			err = ioutil.WriteFile(logPath, []byte("log"), 0644)
 			require.NoError(t, err)
diff --git a/runtime/service_integ_test.go b/runtime/service_integ_test.go
index 00f948e..e6babd8 100644
--- a/runtime/service_integ_test.go
+++ b/runtime/service_integ_test.go
@@ -2196,7 +2196,9 @@ func TestCreateVM_Isolated(t *testing.T) {
 		}
 		vmID := testNameToVMID(t.Name())
 
-		tempDir := t.TempDir()
+		tempDir, err := ioutil.TempDir("", vmID)
+		require.NoError(t, err)
+		defer os.RemoveAll(tempDir)
 
 		logFile := filepath.Join(tempDir, "log.fifo")
 		metricsFile := filepath.Join(tempDir, "metrics.fifo")
@@ -2218,7 +2220,7 @@ func TestCreateVM_Isolated(t *testing.T) {
 			// Ensure the response fields are populated correctly
 			assert.Equal(t, request.VMID, resp.VMID)
 
-			_, err := fcClient.StopVM(ctx, &proto.StopVMRequest{VMID: request.VMID})
+			_, err = fcClient.StopVM(ctx, &proto.StopVMRequest{VMID: request.VMID})
 			require.Equal(t, status.Code(err), codes.OK)
 		}
 	}
@@ -2316,7 +2318,9 @@ func TestPauseResume_Isolated(t *testing.T) {
 	runTest := func(t *testing.T, request *proto.CreateVMRequest, state func(ctx context.Context, resp *proto.CreateVMResponse)) {
 		vmID := testNameToVMID(t.Name())
 
-		tempDir := t.TempDir()
+		tempDir, err := ioutil.TempDir("", vmID)
+		require.NoError(t, err)
+		defer os.RemoveAll(tempDir)
 
 		logFile := filepath.Join(tempDir, "log.fifo")
 		metricsFile := filepath.Join(tempDir, "metrics.fifo")
@@ -2343,7 +2347,7 @@ func TestPauseResume_Isolated(t *testing.T) {
 		assert.Equal(t, request.VMID, resp.VMID)
 
 		// Resume the VM since state() may pause the VM.
-		_, err := fcClient.ResumeVM(ctx, &proto.ResumeVMRequest{VMID: vmID})
+		_, err = fcClient.ResumeVM(ctx, &proto.ResumeVMRequest{VMID: vmID})
 		require.NoError(t, err)
 
 		_, err = fcClient.StopVM(ctx, &proto.StopVMRequest{VMID: vmID})
diff --git a/runtime/service_test.go b/runtime/service_test.go
index 9f3db97..b5b7047 100644
--- a/runtime/service_test.go
+++ b/runtime/service_test.go
@@ -16,6 +16,7 @@ package main
 import (
 	"context"
 	"fmt"
+	"io/ioutil"
 	"os"
 	"path/filepath"
 	"testing"
@@ -233,7 +234,9 @@ func TestBuildVMConfiguration(t *testing.T) {
 				config:    tc.config,
 			}
 
-			tempDir := t.TempDir()
+			tempDir, err := ioutil.TempDir(os.TempDir(), namespace)
+			assert.NoError(t, err)
+			defer os.RemoveAll(tempDir)
 
 			svc.shimDir = vm.Dir(tempDir)
 			svc.jailer = newNoopJailer(context.Background(), svc.logger, svc.shimDir)
@@ -301,7 +304,13 @@ func TestDebugConfig(t *testing.T) {
 		},
 	}
 
-	path := t.TempDir()
+	cwd, err := os.Getwd()
+	require.NoError(t, err, "failed to get working dir")
+
+	path, err := ioutil.TempDir(cwd, "TestDebugConfig")
+	assert.NoError(t, err, "failed to create temp directory")
+
+	defer os.RemoveAll(path)
 
 	for i, c := range cases {
 		c := c