Repository: code-ready/crc
Pull request #2418 (2021-06-10 10:21:26)

Make rootless as default socket for podman-env command
We thought that enabling root socket, make a step less for developers to deploy
an application on OpenShift but during testing it might only work if developer
don't tag the image with registry which have `localhost/<imageName>`. Also our
goal is to teach user about Openshift about how to use internal registry so
it does divert from the production clusters. I think if a user really want
the application directly from the dockerfile without building it localy then
`oc new-build` would be best choice.


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

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

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

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

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

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

Approvers can indicate their approval by writing `/approve` in a comment
Approvers can cancel approval by writing `/approve cancel` in a comment
</details>
<!-- META={"approvers":[]} -->
openshift-ci[bot]: [APPROVALNOTIFIER] This PR is **APPROVED**

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

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

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

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

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

Approvers can indicate their approval by writing `/approve` in a comment
Approvers can cancel approval by writing `/approve cancel` in a comment
</details>
<!-- META={"approvers":[]} -->
gbraad: So, how to disable this? Perhaps food to describe this in the command output as an option.
cfergeau: > So, how to disable this? Perhaps good to describe this in the command output as an option.

"disable this"? Do you mean how to switch between `rootless`/`non rootless`? This can done with `--rootless=false` which is odd..
gbraad: > This can done with --rootless=false which is odd..

Right, and that is what either has to be documented/added in the message ... or simple, this won't do.
Perhaps the option is entirely not useful as we target a VM, but might be a different experience from a Linux box.
openshift-ci[bot]: [APPROVALNOTIFIER] This PR is **APPROVED**

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

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

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

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

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

Approvers can indicate their approval by writing `/approve` in a comment
Approvers can cancel approval by writing `/approve cancel` in a comment
</details>
<!-- META={"approvers":[]} -->
guillaumerose: I updated the PR:
* flag is now `root`
* by default it is false
openshift-ci[bot]: [APPROVALNOTIFIER] This PR is **APPROVED**

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

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

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

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

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

Approvers can indicate their approval by writing `/approve` in a comment
Approvers can cancel approval by writing `/approve cancel` in a comment
</details>
<!-- META={"approvers":[]} -->
anjannath: To have podman command talk to the root socket now user needs to do `crc podman-env --root=true`

cfergeau: Wondering if it would not be simpler/safer to revert ebb0e28cb4fba89 instead while we figure out a clearer story around podman. If the goal of using `--root` is to be able to bind to port 80, setting `CAP_NET_BIND_SERVICE` on the podman binary in the VM could be an alternative.

Patch:
diff --git a/cmd/crc/cmd/podman_env.go b/cmd/crc/cmd/podman_env.go
index dbda33da8..d4ab4681e 100644
--- a/cmd/crc/cmd/podman_env.go
+++ b/cmd/crc/cmd/podman_env.go
@@ -9,7 +9,7 @@ import (
 )
 
 var (
-	rootless bool
+	root bool
 )
 
 var podmanEnvCmd = &cobra.Command{
@@ -37,9 +37,9 @@ func runPodmanEnv() error {
 		return err
 	}
 
-	socket := "/run/podman/podman.sock"
-	if rootless {
-		socket = "/run/user/1000/podman/podman.sock"
+	socket := "/run/user/1000/podman/podman.sock"
+	if root {
+		socket = "/run/podman/podman.sock"
 	}
 	fmt.Println(shell.GetPathEnvString(userShell, constants.CrcOcBinDir))
 	fmt.Println(shell.GetEnvString(userShell, "CONTAINER_SSHKEY", connectionDetails.SSHKeys[0]))
@@ -54,7 +54,7 @@ func runPodmanEnv() error {
 }
 
 func init() {
-	podmanEnvCmd.Flags().BoolVar(&rootless, "rootless", false, "Use rootless podman in the virtual machine")
+	podmanEnvCmd.Flags().BoolVar(&root, "root", false, "Use root podman in the virtual machine")
 	podmanEnvCmd.Flags().StringVar(&forceShell, "shell", "", "Set the environment for the specified shell: [fish, cmd, powershell, tcsh, bash, zsh]. Default is auto-detect.")
 	rootCmd.AddCommand(podmanEnvCmd)
 }
diff --git a/go.mod b/go.mod
index ca15049bc..070580662 100644
--- a/go.mod
+++ b/go.mod
@@ -10,7 +10,7 @@ require (
 	github.com/asaskevich/govalidator v0.0.0-20210307081110-f21760c49a8d
 	github.com/cavaliercoder/grab v2.0.0+incompatible
 	github.com/cheggaaa/pb/v3 v3.0.8
-	github.com/code-ready/admin-helper v0.0.0-20210518083720-ee7100e9f7ae
+	github.com/code-ready/admin-helper v0.0.0-20210602075518-d22477037442
 	github.com/code-ready/clicumber v0.0.0-20210201104241-cecb794bdf9a
 	github.com/code-ready/gvisor-tap-vsock v0.0.0-20210308122700-d61f9aac135c
 	github.com/code-ready/machine v0.0.0-20210122113819-281ccfbb4566
diff --git a/go.sum b/go.sum
index ffdb0aa39..5fdbd7321 100644
--- a/go.sum
+++ b/go.sum
@@ -143,8 +143,8 @@ github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGX
 github.com/cockroachdb/apd v1.1.0/go.mod h1:8Sl8LxpKi29FqWXR16WEFZRNSz3SoPzUzeMeY4+DwBQ=
 github.com/cockroachdb/cockroach-go v0.0.0-20181001143604-e0a95dfd547c/go.mod h1:XGLbWH/ujMcbPbhZq52Nv6UrCghb1yGn//133kEsvDk=
 github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8=
-github.com/code-ready/admin-helper v0.0.0-20210518083720-ee7100e9f7ae h1:2oPNH50PMnFXA+bfa7bHcg8XtVOt/maFb0A7V8qkKbc=
-github.com/code-ready/admin-helper v0.0.0-20210518083720-ee7100e9f7ae/go.mod h1:4HSCLxIh62FmyT+XNNdPT7svzEcdcFvrlyzeUa1sqHY=
+github.com/code-ready/admin-helper v0.0.0-20210602075518-d22477037442 h1:uuCCqdNeZs2nETXs7qQ2i8wxthI8WgTZylQdyvTXcIA=
+github.com/code-ready/admin-helper v0.0.0-20210602075518-d22477037442/go.mod h1:JIRSIX+K3gN+A4DGJIcnG/opLnj5zOVG+H2h2eA9Wgo=
 github.com/code-ready/clicumber v0.0.0-20210201104241-cecb794bdf9a h1:VOQmCj9Y8pAPU4C0rIvF2ByUBuuqnaR9JSvb9C8uBQE=
 github.com/code-ready/clicumber v0.0.0-20210201104241-cecb794bdf9a/go.mod h1:ZPZUcYGpv/FQGnwakUuhiHP9x/IIcU2SKbn8xPe4ROc=
 github.com/code-ready/gvisor-tap-vsock v0.0.0-20210308122700-d61f9aac135c h1:UOg6w7Uv5hWvFVABjJpawCEmAK99vG96SozUaulqVCk=
@@ -548,6 +548,7 @@ github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7
 github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
 github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
 github.com/kardianos/osext v0.0.0-20190222173326-2bc1f35cddc0/go.mod h1:1NbS8ALrpOvjt0rHPNLyCIeMtbizbir8U//inJ+zuB8=
+github.com/kardianos/service v1.2.0/go.mod h1:CIMRFEJVL+0DS1a3Nx06NaMn4Dz63Ng6O7dl0qH0zVM=
 github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 h1:Z9n2FFNUXsshfwJMBgNA0RU6/i7WVaAegv3PtuIHPMs=
 github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8=
 github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q=
@@ -1142,6 +1143,7 @@ golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7w
 golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20201015000850-e3ed0017c211/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20201026133411-418715ba6fdd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20201112073958-5cba982894dd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
diff --git a/pkg/crc/adminhelper/hosts.go b/pkg/crc/adminhelper/hosts.go
index 1e901341a..2f6f7379b 100644
--- a/pkg/crc/adminhelper/hosts.go
+++ b/pkg/crc/adminhelper/hosts.go
@@ -4,11 +4,12 @@ import (
 	"path/filepath"
 
 	"github.com/code-ready/admin-helper/pkg/hosts"
+	"github.com/code-ready/admin-helper/pkg/types"
 	"github.com/code-ready/crc/pkg/crc/constants"
 )
 
 var (
-	adminHelperPath = filepath.Join(constants.BinDir(), constants.GetAdminHelperExecutable())
+	BinPath = filepath.Join(constants.BinDir(), constants.GetAdminHelperExecutable())
 )
 
 // UpdateHostsFile updates the host's /etc/hosts file with Instance IP.
@@ -36,13 +37,27 @@ func AddToHostsFile(instanceIP string, hostnames ...string) error {
 	if len(filtered) == 0 {
 		return nil
 	}
-	return execute(append([]string{"add", instanceIP}, hostnames...)...)
+
+	return instance().Add(&types.AddRequest{
+		IP:    instanceIP,
+		Hosts: filtered,
+	})
 }
 
 func RemoveFromHostsFile(hostnames ...string) error {
-	return execute(append([]string{"rm"}, hostnames...)...)
+	return instance().Remove(&types.RemoveRequest{
+		Hosts: hostnames,
+	})
 }
 
 func CleanHostsFile() error {
-	return execute("clean", constants.ClusterDomain, constants.AppsDomain)
+	return instance().Clean(&types.CleanRequest{
+		Domains: []string{constants.ClusterDomain, constants.AppsDomain},
+	})
+}
+
+type helper interface {
+	Add(req *types.AddRequest) error
+	Remove(req *types.RemoveRequest) error
+	Clean(req *types.CleanRequest) error
 }
diff --git a/pkg/crc/adminhelper/hosts_nowin.go b/pkg/crc/adminhelper/hosts_nowin.go
index feb2a2e2a..74a6878b4 100644
--- a/pkg/crc/adminhelper/hosts_nowin.go
+++ b/pkg/crc/adminhelper/hosts_nowin.go
@@ -3,10 +3,30 @@
 package adminhelper
 
 import (
+	"github.com/code-ready/admin-helper/pkg/types"
 	crcos "github.com/code-ready/crc/pkg/os"
 )
 
 func execute(args ...string) error {
-	_, _, err := crcos.RunWithDefaultLocale(adminHelperPath, args...)
+	_, _, err := crcos.RunWithDefaultLocale(BinPath, args...)
 	return err
 }
+
+func instance() helper {
+	return &cliHelper{}
+}
+
+type cliHelper struct {
+}
+
+func (c *cliHelper) Add(req *types.AddRequest) error {
+	return execute(append([]string{"add", req.IP}, req.Hosts...)...)
+}
+
+func (c *cliHelper) Remove(req *types.RemoveRequest) error {
+	return execute(append([]string{"rm"}, req.Hosts...)...)
+}
+
+func (c *cliHelper) Clean(req *types.CleanRequest) error {
+	return execute(append([]string{"clean"}, req.Domains...)...)
+}
diff --git a/pkg/crc/adminhelper/hosts_windows.go b/pkg/crc/adminhelper/hosts_windows.go
index 54fac5255..9c09d2741 100644
--- a/pkg/crc/adminhelper/hosts_windows.go
+++ b/pkg/crc/adminhelper/hosts_windows.go
@@ -1,12 +1,26 @@
 package adminhelper
 
 import (
-	"strings"
+	"context"
+	"net"
+	"net/http"
+	"time"
 
-	"github.com/code-ready/crc/pkg/os/windows/powershell"
+	"github.com/Microsoft/go-winio"
+	"github.com/code-ready/admin-helper/pkg/client"
 )
 
-func execute(args ...string) error {
-	_, _, err := powershell.ExecuteAsAdmin("modifying hosts file", strings.Join(append([]string{adminHelperPath}, args...), " "))
-	return err
+func instance() helper {
+	return Client()
+}
+
+func Client() *client.Client {
+	return client.New(&http.Client{
+		Transport: &http.Transport{
+			DialContext: func(ctx context.Context, network, addr string) (net.Conn, error) {
+				return winio.DialPipeContext(ctx, `\\.\pipe\crc-admin-helper`)
+			},
+		},
+		Timeout: 3 * time.Second,
+	}, "http://unix")
 }
diff --git a/pkg/crc/constants/constants.go b/pkg/crc/constants/constants.go
index 98a9d62b7..32f5c7053 100644
--- a/pkg/crc/constants/constants.go
+++ b/pkg/crc/constants/constants.go
@@ -27,7 +27,7 @@ const (
 	DaemonLogFile             = "crcd.log"
 	CrcLandingPageURL         = "https://cloud.redhat.com/openshift/create/local" // #nosec G101
 	DefaultPodmanURLBase      = "https://storage.googleapis.com/libpod-master-releases"
-	DefaultAdminHelperCliBase = "https://github.com/code-ready/admin-helper/releases/download/0.0.4"
+	DefaultAdminHelperCliBase = "https://github.com/code-ready/admin-helper/releases/download/0.0.6"
 	CRCMacTrayDownloadURL     = "https://github.com/code-ready/tray-macos/releases/download/v%s/crc-tray-macos.tar.gz"
 	CRCWindowsTrayDownloadURL = "https://github.com/code-ready/tray-windows/releases/download/v%s/crc-tray-windows.zip"
 	DefaultContext            = "admin"
diff --git a/pkg/crc/preflight/preflight_checks_common.go b/pkg/crc/preflight/preflight_checks_common.go
index b1724980e..548560392 100644
--- a/pkg/crc/preflight/preflight_checks_common.go
+++ b/pkg/crc/preflight/preflight_checks_common.go
@@ -76,13 +76,6 @@ var genericPreflightChecks = []Check{
 
 		labels: None,
 	},
-	{
-		cleanupDescription: "Removing hosts file records added by CRC",
-		cleanup:            removeHostsFileEntry,
-		flags:              CleanUpOnly,
-
-		labels: None,
-	},
 	{
 		cleanupDescription: "Removing older logs",
 		cleanup:            removeOldLogs,
@@ -99,6 +92,14 @@ var genericPreflightChecks = []Check{
 	},
 }
 
+var cleanUpHostsFile = Check{
+	cleanupDescription: "Removing hosts file records added by CRC",
+	cleanup:            removeHostsFileEntry,
+	flags:              CleanUpOnly,
+
+	labels: None,
+}
+
 func checkSupportedCPUArch() error {
 	if runtime.GOARCH != "amd64" {
 		logging.Debugf("GOARCH is %s", runtime.GOARCH)
diff --git a/pkg/crc/preflight/preflight_darwin.go b/pkg/crc/preflight/preflight_darwin.go
index a88e20cd5..11b041c24 100644
--- a/pkg/crc/preflight/preflight_darwin.go
+++ b/pkg/crc/preflight/preflight_darwin.go
@@ -134,6 +134,7 @@ func getChecks(mode network.Mode) []Check {
 
 	checks = append(checks, nonWinPreflightChecks...)
 	checks = append(checks, genericPreflightChecks...)
+	checks = append(checks, cleanUpHostsFile)
 	checks = append(checks, hyperkitPreflightChecks(mode)...)
 	checks = append(checks, daemonSetupChecks...)
 	checks = append(checks, resolverPreflightChecks...)
diff --git a/pkg/crc/preflight/preflight_linux.go b/pkg/crc/preflight/preflight_linux.go
index fe7ade6df..4f92a7be2 100644
--- a/pkg/crc/preflight/preflight_linux.go
+++ b/pkg/crc/preflight/preflight_linux.go
@@ -312,6 +312,7 @@ func getChecks(distro *linux.OsRelease) []Check {
 	checks = append(checks, nonWinPreflightChecks...)
 	checks = append(checks, wsl2PreflightCheck)
 	checks = append(checks, genericPreflightChecks...)
+	checks = append(checks, cleanUpHostsFile)
 	checks = append(checks, libvirtPreflightChecks(distro)...)
 	checks = append(checks, ubuntuPreflightChecks...)
 	checks = append(checks, nmPreflightChecks...)
diff --git a/pkg/crc/preflight/preflight_windows.go b/pkg/crc/preflight/preflight_windows.go
index 0ff7a2d1d..d8779baf9 100644
--- a/pkg/crc/preflight/preflight_windows.go
+++ b/pkg/crc/preflight/preflight_windows.go
@@ -3,8 +3,13 @@ package preflight
 import (
 	"errors"
 	"fmt"
+	"os"
+	"path/filepath"
 	"strings"
 
+	"github.com/code-ready/crc/pkg/crc/adminhelper"
+	"github.com/code-ready/crc/pkg/crc/constants"
+	crcerrors "github.com/code-ready/crc/pkg/crc/errors"
 	"github.com/code-ready/crc/pkg/crc/network"
 	"github.com/code-ready/crc/pkg/crc/version"
 	"github.com/code-ready/crc/pkg/os/windows/powershell"
@@ -47,13 +52,46 @@ var hypervPreflightChecks = []Check{
 
 		labels: labels{Os: Windows},
 	},
+	{
+		configKeySuffix:  "check-crc-users-group-exists",
+		checkDescription: "Checking if crc-users group exists",
+		check: func() error {
+			_, _, err := powershell.Execute("Get-LocalGroup -Name crc-users")
+			return err
+		},
+		fixDescription: "Creating crc-users group",
+		fix: func() error {
+			_, _, err := powershell.ExecuteAsAdmin("create crc-users group", "New-LocalGroup -Name crc-users")
+			return err
+		},
+		labels: labels{Os: Windows},
+	},
 	{
 		configKeySuffix:  "check-user-in-hyperv-group",
-		checkDescription: "Checking if user is a member of the Hyper-V Administrators group",
-		check:            checkIfUserPartOfHyperVAdmins,
-		fixDescription:   "Adding user to the Hyper-V Administrators group",
-		fix:              fixUserPartOfHyperVAdmins,
-
+		checkDescription: "Checking if current user is in Hyper-V group and crc-users group",
+		check: func() error {
+			if err := adminHelperGroup.check(); err != nil {
+				return err
+			}
+			return hypervGroup.check()
+		},
+		fixDescription: "Adding current user to group",
+		fix: func() error {
+			m := crcerrors.MultiError{}
+			if err := adminHelperGroup.check(); err != nil {
+				m.Collect(adminHelperGroup.fix())
+			}
+			if err := hypervGroup.check(); err != nil {
+				m.Collect(hypervGroup.fix())
+			}
+			if len(m.Errors) == 0 {
+				return nil
+			}
+			if m.Errors[0] == errReboot {
+				return errReboot
+			}
+			return m
+		},
 		labels: labels{Os: Windows},
 	},
 	{
@@ -141,6 +179,57 @@ var vsockChecks = []Check{
 	},
 }
 
+var errReboot = errors.New("Please reboot your system and run 'crc setup' to complete the setup process")
+
+var adminHelperGroup = Check{
+	check: func() error {
+		_, _, err := powershell.Execute(fmt.Sprintf("Get-LocalGroupMember -Name crc-users -Member '%s'", os.Getenv("USERNAME")))
+		return err
+	},
+	fix: func() error {
+		_, _, err := powershell.ExecuteAsAdmin("adding current user to crc-users group", fmt.Sprintf("Add-LocalGroupMember -Group crc-users -Member '%s'", os.Getenv("USERNAME")))
+		if err != nil {
+			return err
+		}
+		return errReboot
+	},
+}
+
+var hypervGroup = Check{
+	check: checkIfUserPartOfHyperVAdmins,
+	fix:   fixUserPartOfHyperVAdmins,
+}
+
+var adminHelperChecks = []Check{
+	{
+		configKeySuffix:  "check-admin-helper-daemon-installed",
+		checkDescription: "Checking if admin-helper daemon is installed",
+		check: func() error {
+			version, err := adminhelper.Client().Version()
+			if err != nil {
+				return err
+			}
+			expected := filepath.Base(constants.DefaultAdminHelperCliBase)
+			if version != expected {
+				return fmt.Errorf("unexpected admin-helper daemon version (expected: %s, got: %s)", expected, version)
+			}
+			return nil
+		},
+		fixDescription: "Installing admin-helper daemon",
+		fix: func() error {
+			_, _, err := powershell.ExecuteAsAdmin("install admin-helper daemon", fmt.Sprintf("& '%s' uninstall-daemon; & '%s' install-daemon", adminhelper.BinPath, adminhelper.BinPath))
+			return err
+		},
+		cleanupDescription: "Uninstalling admin-helper daemon",
+		cleanup: func() error {
+			_, _, err := powershell.ExecuteAsAdmin("uninstall admin-helper daemon", fmt.Sprintf("& '%s' uninstall-daemon", adminhelper.BinPath))
+			return err
+		},
+		labels: labels{Os: Windows},
+	},
+	cleanUpHostsFile,
+}
+
 const (
 	// This key is required to activate the vsock communication
 	registryDirectory = `HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Virtualization\GuestCommunicationServices`
@@ -202,10 +291,10 @@ func getChecks() []Check {
 	checks := []Check{}
 	checks = append(checks, genericPreflightChecks...)
 	checks = append(checks, hypervPreflightChecks...)
+	checks = append(checks, adminHelperChecks...)
 	checks = append(checks, vsockChecks...)
 	checks = append(checks, traySetupChecks...)
 	checks = append(checks, bundleCheck)
-
 	return checks
 }
 
diff --git a/pkg/crc/version/version.go b/pkg/crc/version/version.go
index d73b49915..9fd1894fe 100644
--- a/pkg/crc/version/version.go
+++ b/pkg/crc/version/version.go
@@ -33,7 +33,7 @@ const (
 	// Tray version to be embedded in executable
 	crcMacTrayVersion = "1.0.9"
 	// Windows forms application version type major.minor.buildnumber.revesion
-	crcWindowsTrayVersion = "0.6.0.0"
+	crcWindowsTrayVersion = "0.7.0.0"
 )
 
 type CrcReleaseInfo struct {
diff --git a/pkg/os/windows/powershell/powershell_windows.go b/pkg/os/windows/powershell/powershell_windows.go
index 1499dc310..0a1d4c272 100644
--- a/pkg/os/windows/powershell/powershell_windows.go
+++ b/pkg/os/windows/powershell/powershell_windows.go
@@ -95,7 +95,13 @@ func runAsCmds(powershell string) []string {
 		`  $procInfo.WindowStyle = [Diagnostics.ProcessWindowStyle]::Hidden`,
 		`  $procInfo.Arguments = "-ExecutionPolicy RemoteSigned & '" + $script:MyInvocation.MyCommand.Path + "'"`,
 		`  $procInfo.Verb = "runas";`,
-		`  [System.Diagnostics.Process]::Start($procInfo);`,
+		`  $p = New-Object System.Diagnostics.Process`,
+		`  $p.StartInfo = $procInfo`,
+		`  $p.Start() | Out-Null`,
+		`  $p.WaitForExit()`,
+		`  if ($p.ExitCode -ne 0) {`,
+		`    throw "Unexpected failure";`,
+		`  }`,
 		`  Exit;`,
 		`}`,
 	}
diff --git a/vendor/github.com/code-ready/admin-helper/pkg/client/client.go b/vendor/github.com/code-ready/admin-helper/pkg/client/client.go
new file mode 100644
index 000000000..1cdf57ce4
--- /dev/null
+++ b/vendor/github.com/code-ready/admin-helper/pkg/client/client.go
@@ -0,0 +1,101 @@
+package client
+
+import (
+	"bytes"
+	"encoding/json"
+	"errors"
+	"fmt"
+	"io/ioutil"
+	"net/http"
+	"strings"
+
+	"github.com/code-ready/admin-helper/pkg/types"
+)
+
+type Client struct {
+	client *http.Client
+	base   string
+}
+
+func New(client *http.Client, base string) *Client {
+	return &Client{
+		client: client,
+		base:   base,
+	}
+}
+
+func (c *Client) Version() (string, error) {
+	res, err := c.client.Get(fmt.Sprintf("%s%s", c.base, "/version"))
+	if err != nil {
+		return "", err
+	}
+	defer res.Body.Close()
+	if res.StatusCode != http.StatusOK {
+		return "", fmt.Errorf("unexpected status: %d", res.StatusCode)
+	}
+	body, err := ioutil.ReadAll(res.Body)
+	if err != nil {
+		return "", err
+	}
+	return strings.TrimSpace(string(body)), nil
+}
+
+func (c *Client) Add(req *types.AddRequest) error {
+	bin, err := json.Marshal(req)
+	if err != nil {
+		return err
+	}
+	res, err := c.client.Post(fmt.Sprintf("%s%s", c.base, "/add"), "application/json", bytes.NewReader(bin))
+	if err != nil {
+		return err
+	}
+	defer res.Body.Close()
+	if res.StatusCode != http.StatusOK {
+		err, readErr := ioutil.ReadAll(res.Body)
+		if readErr != nil {
+			return fmt.Errorf("error while reading error message: %v", readErr)
+		}
+		return errors.New(strings.TrimSpace(string(err)))
+	}
+	return nil
+}
+
+func (c *Client) Remove(req *types.RemoveRequest) error {
+	bin, err := json.Marshal(req)
+	if err != nil {
+		return err
+	}
+	res, err := c.client.Post(fmt.Sprintf("%s%s", c.base, "/remove"), "application/json", bytes.NewReader(bin))
+	if err != nil {
+		return err
+	}
+	defer res.Body.Close()
+	if res.StatusCode != http.StatusOK {
+		err, readErr := ioutil.ReadAll(res.Body)
+		if readErr != nil {
+			return fmt.Errorf("error while reading error message: %v", readErr)
+		}
+		return errors.New(strings.TrimSpace(string(err)))
+	}
+	return nil
+}
+
+func (c *Client) Clean(req *types.CleanRequest) error {
+	bin, err := json.Marshal(req)
+	if err != nil {
+		return err
+	}
+	res, err := c.client.Post(fmt.Sprintf("%s%s", c.base, "/clean"), "application/json", bytes.NewReader(bin))
+	if err != nil {
+		return err
+	}
+	defer res.Body.Close()
+	if res.StatusCode != http.StatusOK {
+		err, readErr := ioutil.ReadAll(res.Body)
+		if readErr != nil {
+			return fmt.Errorf("error while reading error message: %v", readErr)
+		}
+		return errors.New(strings.TrimSpace(string(err)))
+	}
+	return nil
+}
diff --git a/vendor/github.com/code-ready/admin-helper/pkg/types/requests.go b/vendor/github.com/code-ready/admin-helper/pkg/types/requests.go
new file mode 100644
index 000000000..7b9ef40ec
--- /dev/null
+++ b/vendor/github.com/code-ready/admin-helper/pkg/types/requests.go
@@ -0,0 +1,14 @@
+package types
+
+type AddRequest struct {
+	IP    string   `json:"ip"`
+	Hosts []string `json:"hosts"`
+}
+
+type RemoveRequest struct {
+	Hosts []string `json:"hosts"`
+}
+
+type CleanRequest struct {
+	Domains []string `json:"domains"`
+}
diff --git a/vendor/modules.txt b/vendor/modules.txt
index 3259cc3bb..8114a70db 100644
--- a/vendor/modules.txt
+++ b/vendor/modules.txt
@@ -33,9 +33,11 @@ github.com/cavaliercoder/grab
 ## explicit
 github.com/cheggaaa/pb/v3
 github.com/cheggaaa/pb/v3/termutil
-# github.com/code-ready/admin-helper v0.0.0-20210518083720-ee7100e9f7ae
+# github.com/code-ready/admin-helper v0.0.0-20210602075518-d22477037442
 ## explicit
+github.com/code-ready/admin-helper/pkg/client
 github.com/code-ready/admin-helper/pkg/hosts
+github.com/code-ready/admin-helper/pkg/types
 # github.com/code-ready/clicumber v0.0.0-20210201104241-cecb794bdf9a
 ## explicit
 github.com/code-ready/clicumber/testsuite


Test patch:
diff --git a/pkg/crc/preflight/preflight_linux_test.go b/pkg/crc/preflight/preflight_linux_test.go
index 7cc456890..31952142f 100644
--- a/pkg/crc/preflight/preflight_linux_test.go
+++ b/pkg/crc/preflight/preflight_linux_test.go
@@ -69,9 +69,9 @@ var checkListForDistros = []checkListForDistro{
 			{check: checkSupportedCPUArch},
 			{configKeySuffix: "check-ram"},
 			{cleanup: removeCRCMachinesDir},
-			{cleanup: removeHostsFileEntry},
 			{cleanup: removeOldLogs},
 			{cleanup: cluster.ForgetPullSecret},
+			{cleanup: removeHostsFileEntry},
 			{check: checkVirtualizationEnabled},
 			{check: checkKvmEnabled},
 			{check: checkLibvirtInstalled},
@@ -104,9 +104,9 @@ var checkListForDistros = []checkListForDistro{
 			{check: checkSupportedCPUArch},
 			{configKeySuffix: "check-ram"},
 			{cleanup: removeCRCMachinesDir},
-			{cleanup: removeHostsFileEntry},
 			{cleanup: removeOldLogs},
 			{cleanup: cluster.ForgetPullSecret},
+			{cleanup: removeHostsFileEntry},
 			{check: checkVirtualizationEnabled},
 			{check: checkKvmEnabled},
 			{check: checkLibvirtInstalled},
@@ -138,9 +138,9 @@ var checkListForDistros = []checkListForDistro{
 			{check: checkSupportedCPUArch},
 			{configKeySuffix: "check-ram"},
 			{cleanup: removeCRCMachinesDir},
-			{cleanup: removeHostsFileEntry},
 			{cleanup: removeOldLogs},
 			{cleanup: cluster.ForgetPullSecret},
+			{cleanup: removeHostsFileEntry},
 			{check: checkVirtualizationEnabled},
 			{check: checkKvmEnabled},
 			{check: checkLibvirtInstalled},
@@ -166,9 +166,9 @@ var checkListForDistros = []checkListForDistro{
 			{check: checkSupportedCPUArch},
 			{configKeySuffix: "check-ram"},
 			{cleanup: removeCRCMachinesDir},
-			{cleanup: removeHostsFileEntry},
 			{cleanup: removeOldLogs},
 			{cleanup: cluster.ForgetPullSecret},
+			{cleanup: removeHostsFileEntry},
 			{check: checkVirtualizationEnabled},
 			{check: checkKvmEnabled},
 			{check: checkLibvirtInstalled},
@@ -201,9 +201,9 @@ var checkListForDistros = []checkListForDistro{
 			{check: checkSupportedCPUArch},
 			{configKeySuffix: "check-ram"},
 			{cleanup: removeCRCMachinesDir},
-			{cleanup: removeHostsFileEntry},
 			{cleanup: removeOldLogs},
 			{cleanup: cluster.ForgetPullSecret},
+			{cleanup: removeHostsFileEntry},
 			{check: checkVirtualizationEnabled},
 			{check: checkKvmEnabled},
 			{check: checkLibvirtInstalled},
@@ -235,9 +235,9 @@ var checkListForDistros = []checkListForDistro{
 			{check: checkSupportedCPUArch},
 			{configKeySuffix: "check-ram"},
 			{cleanup: removeCRCMachinesDir},
-			{cleanup: removeHostsFileEntry},
 			{cleanup: removeOldLogs},
 			{cleanup: cluster.ForgetPullSecret},
+			{cleanup: removeHostsFileEntry},
 			{check: checkVirtualizationEnabled},
 			{check: checkKvmEnabled},
 			{check: checkLibvirtInstalled},
@@ -263,9 +263,9 @@ var checkListForDistros = []checkListForDistro{
 			{check: checkSupportedCPUArch},
 			{configKeySuffix: "check-ram"},
 			{cleanup: removeCRCMachinesDir},
-			{cleanup: removeHostsFileEntry},
 			{cleanup: removeOldLogs},
 			{cleanup: cluster.ForgetPullSecret},
+			{cleanup: removeHostsFileEntry},
 			{check: checkVirtualizationEnabled},
 			{check: checkKvmEnabled},
 			{check: checkLibvirtInstalled},
@@ -298,9 +298,9 @@ var checkListForDistros = []checkListForDistro{
 			{check: checkSupportedCPUArch},
 			{configKeySuffix: "check-ram"},
 			{cleanup: removeCRCMachinesDir},
-			{cleanup: removeHostsFileEntry},
 			{cleanup: removeOldLogs},
 			{cleanup: cluster.ForgetPullSecret},
+			{cleanup: removeHostsFileEntry},
 			{check: checkVirtualizationEnabled},
 			{check: checkKvmEnabled},
 			{check: checkLibvirtInstalled},
@@ -332,9 +332,9 @@ var checkListForDistros = []checkListForDistro{
 			{check: checkSupportedCPUArch},
 			{configKeySuffix: "check-ram"},
 			{cleanup: removeCRCMachinesDir},
-			{cleanup: removeHostsFileEntry},
 			{cleanup: removeOldLogs},
 			{cleanup: cluster.ForgetPullSecret},
+			{cleanup: removeHostsFileEntry},
 			{check: checkVirtualizationEnabled},
 			{check: checkKvmEnabled},
 			{check: checkLibvirtInstalled},
@@ -360,9 +360,9 @@ var checkListForDistros = []checkListForDistro{
 			{check: checkSupportedCPUArch},
 			{configKeySuffix: "check-ram"},
 			{cleanup: removeCRCMachinesDir},
-			{cleanup: removeHostsFileEntry},
 			{cleanup: removeOldLogs},
 			{cleanup: cluster.ForgetPullSecret},
+			{cleanup: removeHostsFileEntry},
 			{check: checkVirtualizationEnabled},
 			{check: checkKvmEnabled},
 			{check: checkLibvirtInstalled},
@@ -396,9 +396,9 @@ var checkListForDistros = []checkListForDistro{
 			{check: checkSupportedCPUArch},
 			{configKeySuffix: "check-ram"},
 			{cleanup: removeCRCMachinesDir},
-			{cleanup: removeHostsFileEntry},
 			{cleanup: removeOldLogs},
 			{cleanup: cluster.ForgetPullSecret},
+			{cleanup: removeHostsFileEntry},
 			{check: checkVirtualizationEnabled},
 			{check: checkKvmEnabled},
 			{check: checkLibvirtInstalled},
@@ -431,9 +431,9 @@ var checkListForDistros = []checkListForDistro{
 			{check: checkSupportedCPUArch},
 			{configKeySuffix: "check-ram"},
 			{cleanup: removeCRCMachinesDir},
-			{cleanup: removeHostsFileEntry},
 			{cleanup: removeOldLogs},
 			{cleanup: cluster.ForgetPullSecret},
+			{cleanup: removeHostsFileEntry},
 			{check: checkVirtualizationEnabled},
 			{check: checkKvmEnabled},
 			{check: checkLibvirtInstalled},
diff --git a/pkg/crc/preflight/preflight_windows_test.go b/pkg/crc/preflight/preflight_windows_test.go
index 3feeb5cb8..0362822d3 100644
--- a/pkg/crc/preflight/preflight_windows_test.go
+++ b/pkg/crc/preflight/preflight_windows_test.go
@@ -11,13 +11,13 @@ import (
 func TestCountConfigurationOptions(t *testing.T) {
 	cfg := config.New(config.NewEmptyInMemoryStorage())
 	RegisterSettings(cfg)
-	assert.Len(t, cfg.AllConfigs(), 13)
+	assert.Len(t, cfg.AllConfigs(), 15)
 }
 
 func TestCountPreflights(t *testing.T) {
-	assert.Len(t, getPreflightChecks(false, false, network.SystemNetworkingMode), 18)
-	assert.Len(t, getPreflightChecks(true, true, network.SystemNetworkingMode), 18)
+	assert.Len(t, getPreflightChecks(false, false, network.SystemNetworkingMode), 20)
+	assert.Len(t, getPreflightChecks(true, true, network.SystemNetworkingMode), 20)
 
-	assert.Len(t, getPreflightChecks(false, false, network.UserNetworkingMode), 19)
-	assert.Len(t, getPreflightChecks(true, true, network.UserNetworkingMode), 19)
+	assert.Len(t, getPreflightChecks(false, false, network.UserNetworkingMode), 21)
+	assert.Len(t, getPreflightChecks(true, true, network.UserNetworkingMode), 21)
 }