Repository: code-ready/crc
Pull request #2390 (2021-05-31 13:19:51)

start: Display help message when preflights fail
The message instructing to run `crc setup` when one of the preflight
check failed when running `crc start` is no longer shown after commit
c1d9b48. This happens because the type of the error for preflight
failures changed. This commit adjusts the check to use the right type.


## Testing

What is the _bottom-line_ functionality that needs testing? Describe in pseudo-code or in English. Use verifiable statements that tie your changes to existing functionality.

1. Check that when one of the preflight checks is failing, crc setup fails (I used `virsh -c qemu:///system net-destroy crc && crc start`)
2. stderr contains a message instructing to run crc setup, which is not the case before this PR

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

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

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]: @cfergeau: The following test **failed**, say `/retest` to rerun all failed tests:

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

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

<details>

Instructions for interacting with me using PR comments are available [here](https://git.k8s.io/community/contributors/guide/pull-requests.md).  If you have questions or suggestions related to my behavior, please file an issue against the [kubernetes/test-infra](https://github.com/kubernetes/test-infra/issues/new?title=Prow%20issue:) repository. I understand the commands that are listed [here](https://go.k8s.io/bot-commands).
</details>
<!-- test report -->
guillaumerose: What if we add `Unwrap()` to CodeExitError ? Does it avoid an other if ?
cfergeau: > What if we add `Unwrap()` to CodeExitError ? Does it avoid an other if ?

It's indeed nicer with an Unwrap(), thanks for the suggestion. However this means that for now we need to copy/paste `CodeExitError` implementation in crc, as this needs to get in upstream kubernetes, and then in the openshift fork before we can use it as an `import`.
cfergeau: I've created https://github.com/kubernetes/kubernetes/pull/102478
openshift-ci[bot]: @cfergeau: The following test **failed**, say `/retest` to rerun all failed tests:

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

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

<details>

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

Patch:
diff --git a/cmd/crc/cmd/start.go b/cmd/crc/cmd/start.go
index 97ace0f51..fc2d184da 100644
--- a/cmd/crc/cmd/start.go
+++ b/cmd/crc/cmd/start.go
@@ -21,10 +21,10 @@ import (
 	"github.com/code-ready/crc/pkg/crc/preflight"
 	"github.com/code-ready/crc/pkg/crc/validation"
 	crcversion "github.com/code-ready/crc/pkg/crc/version"
+	crcos "github.com/code-ready/crc/pkg/os"
 	"github.com/code-ready/crc/pkg/os/shell"
 	"github.com/spf13/cobra"
 	"github.com/spf13/pflag"
-	"k8s.io/client-go/util/exec"
 )
 
 func init() {
@@ -83,7 +83,7 @@ func runStart(ctx context.Context) (*types.StartResult, error) {
 		}
 
 		if err := preflight.StartPreflightChecks(config); err != nil {
-			return nil, exec.CodeExitError{
+			return nil, crcos.CodeExitError{
 				Err:  err,
 				Code: preflightFailedExitCode,
 			}
diff --git a/go.mod b/go.mod
index a840b4f08..48765b73c 100644
--- a/go.mod
+++ b/go.mod
@@ -9,7 +9,7 @@ require (
 	github.com/asaskevich/govalidator v0.0.0-20200907205600-7a23bdc65eef
 	github.com/cavaliercoder/grab v2.0.0+incompatible
 	github.com/cheggaaa/pb/v3 v3.0.5
-	github.com/code-ready/admin-helper v0.0.0-20210317085515-2d7f65e95985
+	github.com/code-ready/admin-helper v0.0.0-20210518083720-ee7100e9f7ae
 	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 da717631f..c5b096376 100644
--- a/go.sum
+++ b/go.sum
@@ -141,8 +141,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-20210317085515-2d7f65e95985 h1:SWez+YUYr+AMTuqZFNxQ3L9KrG3ABNojr7+458Lwj5E=
-github.com/code-ready/admin-helper v0.0.0-20210317085515-2d7f65e95985/go.mod h1:4HSCLxIh62FmyT+XNNdPT7svzEcdcFvrlyzeUa1sqHY=
+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/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=
diff --git a/packaging/package.sh b/packaging/package.sh
index ac5296045..4058e216a 100755
--- a/packaging/package.sh
+++ b/packaging/package.sh
@@ -24,14 +24,14 @@ binDir="${BASEDIR}/root/Applications/CodeReady Containers.app/Contents/Resources
 version=$(cat "${BASEDIR}/VERSION")
 
 sign "${binDir}/crc"
-sign "${binDir}/admin-helper-darwin"
+sign "${binDir}/crc-admin-helper-darwin"
 sign "${binDir}/crc-driver-hyperkit"
 
 sign "${BASEDIR}/root/Applications/CodeReady Containers.app"
 
 codesign --verify --verbose "${binDir}/hyperkit"
 
-sudo chmod +sx "${binDir}/hyperkit" "${binDir}/admin-helper-darwin" "${binDir}/crc-driver-hyperkit"
+sudo chmod +sx "${binDir}/hyperkit" "${binDir}/crc-admin-helper-darwin" "${binDir}/crc-driver-hyperkit"
 
 pkgbuild --identifier com.redhat.crc --version ${version} \
   --scripts "${BASEDIR}/darwin/scripts" \
diff --git a/packaging/windows/product.wxs.in b/packaging/windows/product.wxs.in
index b2420972e..8044028c0 100755
--- a/packaging/windows/product.wxs.in
+++ b/packaging/windows/product.wxs.in
@@ -47,7 +47,7 @@
                         <File Id="CrcExe" Source="SourceDir\crc.exe" KeyPath="yes" DiskId="3" />
                     </Component>
                     <Component Id="AdminHelper" Guid="*">
-                        <File Id="AdminHelper" Source="SourceDir\admin-helper-windows.exe" KeyPath="yes" DiskId="3" />
+                        <File Id="AdminHelper" Source="SourceDir\crc-admin-helper-windows.exe" KeyPath="yes" DiskId="3" />
                     </Component>
                     <Component Id="CrcTray" Guid="*">
                         <File Id="CrcTray" Source="SourceDir\crc-tray.exe" KeyPath="yes" DiskId="3" />
@@ -91,4 +91,4 @@
         <!-- this should help to propagate env var changes -->
         <CustomActionRef Id="WixBroadcastEnvironmentChange" />
     </Product>
-</Wix>
\ No newline at end of file
+</Wix>
diff --git a/pkg/crc/adminhelper/hosts.go b/pkg/crc/adminhelper/hosts.go
index 1b338a881..1e901341a 100644
--- a/pkg/crc/adminhelper/hosts.go
+++ b/pkg/crc/adminhelper/hosts.go
@@ -8,7 +8,7 @@ import (
 )
 
 var (
-	adminHelperPath = filepath.Join(constants.BinDir(), constants.AdminHelperExecutableName)
+	adminHelperPath = filepath.Join(constants.BinDir(), constants.GetAdminHelperExecutable())
 )
 
 // UpdateHostsFile updates the host's /etc/hosts file with Instance IP.
diff --git a/pkg/crc/cache/cache.go b/pkg/crc/cache/cache.go
index ca9612a4e..ba2f3d97d 100644
--- a/pkg/crc/cache/cache.go
+++ b/pkg/crc/cache/cache.go
@@ -68,7 +68,7 @@ func getVersionGeneric(executablePath string, args ...string) (string, error) {
 func NewAdminHelperCache() *Cache {
 	url := constants.GetAdminHelperURL()
 	version := path.Base(path.Dir(url))
-	return New(constants.AdminHelperExecutableName,
+	return New(constants.GetAdminHelperExecutable(),
 		url,
 		constants.CrcBinDir,
 		version,
diff --git a/pkg/crc/constants/constants.go b/pkg/crc/constants/constants.go
index e7a126dcb..98a9d62b7 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.3"
+	DefaultAdminHelperCliBase = "https://github.com/code-ready/admin-helper/releases/download/0.0.4"
 	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"
@@ -42,18 +42,26 @@ const (
 	AppsDomain    = ".apps-crc.testing"
 )
 
-var adminHelperURLForOs = map[string]string{
-	"darwin":  fmt.Sprintf("%s/%s", DefaultAdminHelperCliBase, "admin-helper-darwin"),
-	"linux":   fmt.Sprintf("%s/%s", DefaultAdminHelperCliBase, "admin-helper-linux"),
-	"windows": fmt.Sprintf("%s/%s", DefaultAdminHelperCliBase, "admin-helper-windows.exe"),
+var adminHelperExecutableForOs = map[string]string{
+	"darwin":  "crc-admin-helper-darwin",
+	"linux":   "crc-admin-helper-linux",
+	"windows": "crc-admin-helper-windows.exe",
+}
+
+func GetAdminHelperExecutableForOs(os string) string {
+	return adminHelperExecutableForOs[os]
+}
+
+func GetAdminHelperExecutable() string {
+	return GetAdminHelperExecutableForOs(runtime.GOOS)
 }
 
 func GetAdminHelperURLForOs(os string) string {
-	return adminHelperURLForOs[os]
+	return fmt.Sprintf("%s/%s", DefaultAdminHelperCliBase, GetAdminHelperExecutableForOs(os))
 }
 
 func GetAdminHelperURL() string {
-	return adminHelperURLForOs[runtime.GOOS]
+	return GetAdminHelperURLForOs(runtime.GOOS)
 }
 
 func defaultBundleForOs(bundleVersion string) map[string]string {
diff --git a/pkg/crc/constants/constants_darwin.go b/pkg/crc/constants/constants_darwin.go
index f8e306116..417a147f1 100644
--- a/pkg/crc/constants/constants_darwin.go
+++ b/pkg/crc/constants/constants_darwin.go
@@ -7,9 +7,8 @@ import (
 )
 
 const (
-	OcExecutableName          = "oc"
-	TrayExecutableName        = "CodeReady Containers.app"
-	AdminHelperExecutableName = "admin-helper-darwin"
+	OcExecutableName   = "oc"
+	TrayExecutableName = "CodeReady Containers.app"
 )
 
 var (
diff --git a/pkg/crc/constants/constants_linux.go b/pkg/crc/constants/constants_linux.go
index 8aa5ea5f0..1492b5b68 100644
--- a/pkg/crc/constants/constants_linux.go
+++ b/pkg/crc/constants/constants_linux.go
@@ -5,9 +5,8 @@ import (
 )
 
 const (
-	OcExecutableName          = "oc"
-	AdminHelperExecutableName = "admin-helper-linux"
-	TapSocketPath             = ""
+	OcExecutableName = "oc"
+	TapSocketPath    = ""
 )
 
 var DaemonHTTPSocketPath = filepath.Join(CrcBaseDir, "crc-http.sock")
diff --git a/pkg/crc/constants/constants_windows.go b/pkg/crc/constants/constants_windows.go
index 83a6cb76f..2952d05f0 100644
--- a/pkg/crc/constants/constants_windows.go
+++ b/pkg/crc/constants/constants_windows.go
@@ -7,7 +7,6 @@ import (
 
 const (
 	OcExecutableName            = "oc.exe"
-	AdminHelperExecutableName   = "admin-helper-windows.exe"
 	TrayExecutableName          = "crc-tray.exe"
 	TrayShortcutName            = "crc-tray.lnk"
 	DaemonBatchFileName         = "crc-daemon-autostart.bat"
diff --git a/pkg/crc/preflight/preflight_checks_common.go b/pkg/crc/preflight/preflight_checks_common.go
index 2cdb89e5b..9b319fb6e 100644
--- a/pkg/crc/preflight/preflight_checks_common.go
+++ b/pkg/crc/preflight/preflight_checks_common.go
@@ -32,11 +32,18 @@ var bundleCheck = Check{
 var genericPreflightChecks = [...]Check{
 	{
 		configKeySuffix:  "check-admin-helper-cached",
-		checkDescription: "Checking if admin-helper executable is cached",
+		checkDescription: "Checking if crc-admin-helper executable is cached",
 		check:            checkAdminHelperExecutableCached,
-		fixDescription:   "Caching admin-helper executable",
+		fixDescription:   "Caching crc-admin-helper executable",
 		fix:              fixAdminHelperExecutableCached,
 	},
+	{
+		configKeySuffix:  "check-obsolete-admin-helper",
+		checkDescription: "Checking for obsolete admin-helper executable",
+		check:            checkOldAdminHelperExecutableCached,
+		fixDescription:   "Removing obsolete admin-helper executable",
+		fix:              fixOldAdminHelperExecutableCached,
+	},
 	{
 
 		configKeySuffix:  "check-supported-cpu-arch",
@@ -141,12 +148,12 @@ func checkAdminHelperExecutableCached() error {
 
 	helper := cache.NewAdminHelperCache()
 	if !helper.IsCached() {
-		return errors.New("admin-helper executable is not cached")
+		return errors.New("crc-admin-helper executable is not cached")
 	}
 	if err := helper.CheckVersion(); err != nil {
-		return errors.Wrap(err, "unexpected version of the admin-helper executable")
+		return errors.Wrap(err, "unexpected version of the crc-admin-helper executable")
 	}
-	logging.Debug("admin-helper executable already cached")
+	logging.Debug("crc-admin-helper executable already cached")
 	return checkSuid(helper.GetExecutablePath())
 }
 
@@ -157,12 +164,46 @@ func fixAdminHelperExecutableCached() error {
 
 	helper := cache.NewAdminHelperCache()
 	if err := helper.EnsureIsCached(); err != nil {
-		return errors.Wrap(err, "Unable to download admin-helper executable")
+		return errors.Wrap(err, "Unable to download crc-admin-helper executable")
 	}
-	logging.Debug("admin-helper executable cached")
+	logging.Debug("crc-admin-helper executable cached")
 	return setSuid(helper.GetExecutablePath())
 }
 
+var oldAdminHelpers = []string{"admin-helper-linux", "admin-helper-darwin", "admin-helper-windows.exe"}
+
+/* These 2 checks can be removed after a few releases */
+func checkOldAdminHelperExecutableCached() error {
+	logging.Debugf("Checking if an older admin-helper executable is installed")
+	for _, oldExecutable := range oldAdminHelpers {
+		oldPath := filepath.Join(constants.CrcBinDir, oldExecutable)
+		if _, err := os.Stat(oldPath); !os.IsNotExist(err) {
+			return fmt.Errorf("Found old admin-helper executable '%s'", oldExecutable)
+		}
+	}
+
+	logging.Debugf("No older admin-helper executable found")
+
+	return nil
+}
+
+func fixOldAdminHelperExecutableCached() error {
+	logging.Debugf("Removing older admin-helper executable")
+	for _, oldExecutable := range oldAdminHelpers {
+		oldPath := filepath.Join(constants.CrcBinDir, oldExecutable)
+		if err := os.Remove(oldPath); err != nil {
+			if !os.IsNotExist(err) {
+				logging.Debugf("Failed to remove  %s: %v", oldPath, err)
+				return err
+			}
+		} else {
+			logging.Debugf("Successfully removed %s", oldPath)
+		}
+	}
+
+	return nil
+}
+
 func removeCRCMachinesDir() error {
 	logging.Debug("Deleting machines directory")
 	if err := os.RemoveAll(constants.MachineInstanceDir); err != nil {
diff --git a/pkg/os/execerror.go b/pkg/os/execerror.go
new file mode 100644
index 000000000..303dd41bd
--- /dev/null
+++ b/pkg/os/execerror.go
@@ -0,0 +1,57 @@
+/*
+Copyright 2014 The Kubernetes Authors.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License 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 os
+
+// ExitError is an interface that presents an API similar to os.ProcessState, which is
+// what ExitError from os/exec is.  This is designed to make testing a bit easier and
+// probably loses some of the cross-platform properties of the underlying library.
+type ExitError interface {
+	String() string
+	Error() string
+	Exited() bool
+	ExitStatus() int
+	Unwrap() error
+}
+
+// CodeExitError is an implementation of ExitError consisting of an error object
+// and an exit code (the upper bits of os.exec.ExitStatus).
+type CodeExitError struct {
+	Err  error
+	Code int
+}
+
+var _ ExitError = CodeExitError{}
+
+func (e CodeExitError) Error() string {
+	return e.Err.Error()
+}
+
+func (e CodeExitError) String() string {
+	return e.Err.Error()
+}
+
+func (e CodeExitError) Exited() bool {
+	return true
+}
+
+func (e CodeExitError) ExitStatus() int {
+	return e.Code
+}
+
+func (e CodeExitError) Unwrap() error {
+	return e.Err
+}
diff --git a/vendor/modules.txt b/vendor/modules.txt
index 9f3784ab1..0af3afde9 100644
--- a/vendor/modules.txt
+++ b/vendor/modules.txt
@@ -32,7 +32,7 @@ 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-20210317085515-2d7f65e95985
+# github.com/code-ready/admin-helper v0.0.0-20210518083720-ee7100e9f7ae
 ## explicit
 github.com/code-ready/admin-helper/pkg/hosts
 # github.com/code-ready/clicumber v0.0.0-20210201104241-cecb794bdf9a


Test patch:
diff --git a/pkg/crc/preflight/preflight_darwin_test.go b/pkg/crc/preflight/preflight_darwin_test.go
index e937ffda2..2cafe6962 100644
--- a/pkg/crc/preflight/preflight_darwin_test.go
+++ b/pkg/crc/preflight/preflight_darwin_test.go
@@ -12,13 +12,13 @@ import (
 func TestCountConfigurationOptions(t *testing.T) {
 	cfg := config.New(config.NewEmptyInMemoryStorage())
 	RegisterSettings(cfg)
-	assert.Len(t, cfg.AllConfigs(), 9)
+	assert.Len(t, cfg.AllConfigs(), 10)
 }
 
 func TestCountPreflights(t *testing.T) {
-	assert.Len(t, getPreflightChecks(true, false, network.SystemNetworkingMode), 15)
-	assert.Len(t, getPreflightChecks(true, true, network.SystemNetworkingMode), 15)
+	assert.Len(t, getPreflightChecks(true, false, network.SystemNetworkingMode), 16)
+	assert.Len(t, getPreflightChecks(true, true, network.SystemNetworkingMode), 16)
 
-	assert.Len(t, getPreflightChecks(true, false, network.UserNetworkingMode), 14)
-	assert.Len(t, getPreflightChecks(true, true, network.UserNetworkingMode), 14)
+	assert.Len(t, getPreflightChecks(true, false, network.UserNetworkingMode), 15)
+	assert.Len(t, getPreflightChecks(true, true, network.UserNetworkingMode), 15)
 }
diff --git a/pkg/crc/preflight/preflight_linux_test.go b/pkg/crc/preflight/preflight_linux_test.go
index 526cea9f5..7cc456890 100644
--- a/pkg/crc/preflight/preflight_linux_test.go
+++ b/pkg/crc/preflight/preflight_linux_test.go
@@ -65,6 +65,7 @@ var checkListForDistros = []checkListForDistro{
 			{check: checkIfRunningAsNormalUser},
 			{check: checkRunningInsideWSL2},
 			{check: checkAdminHelperExecutableCached},
+			{check: checkOldAdminHelperExecutableCached},
 			{check: checkSupportedCPUArch},
 			{configKeySuffix: "check-ram"},
 			{cleanup: removeCRCMachinesDir},
@@ -99,6 +100,7 @@ var checkListForDistros = []checkListForDistro{
 			{check: checkIfRunningAsNormalUser},
 			{check: checkRunningInsideWSL2},
 			{check: checkAdminHelperExecutableCached},
+			{check: checkOldAdminHelperExecutableCached},
 			{check: checkSupportedCPUArch},
 			{configKeySuffix: "check-ram"},
 			{cleanup: removeCRCMachinesDir},
@@ -132,6 +134,7 @@ var checkListForDistros = []checkListForDistro{
 			{check: checkIfRunningAsNormalUser},
 			{check: checkRunningInsideWSL2},
 			{check: checkAdminHelperExecutableCached},
+			{check: checkOldAdminHelperExecutableCached},
 			{check: checkSupportedCPUArch},
 			{configKeySuffix: "check-ram"},
 			{cleanup: removeCRCMachinesDir},
@@ -159,6 +162,7 @@ var checkListForDistros = []checkListForDistro{
 			{check: checkIfRunningAsNormalUser},
 			{check: checkRunningInsideWSL2},
 			{check: checkAdminHelperExecutableCached},
+			{check: checkOldAdminHelperExecutableCached},
 			{check: checkSupportedCPUArch},
 			{configKeySuffix: "check-ram"},
 			{cleanup: removeCRCMachinesDir},
@@ -193,6 +197,7 @@ var checkListForDistros = []checkListForDistro{
 			{check: checkIfRunningAsNormalUser},
 			{check: checkRunningInsideWSL2},
 			{check: checkAdminHelperExecutableCached},
+			{check: checkOldAdminHelperExecutableCached},
 			{check: checkSupportedCPUArch},
 			{configKeySuffix: "check-ram"},
 			{cleanup: removeCRCMachinesDir},
@@ -226,6 +231,7 @@ var checkListForDistros = []checkListForDistro{
 			{check: checkIfRunningAsNormalUser},
 			{check: checkRunningInsideWSL2},
 			{check: checkAdminHelperExecutableCached},
+			{check: checkOldAdminHelperExecutableCached},
 			{check: checkSupportedCPUArch},
 			{configKeySuffix: "check-ram"},
 			{cleanup: removeCRCMachinesDir},
@@ -253,6 +259,7 @@ var checkListForDistros = []checkListForDistro{
 			{check: checkIfRunningAsNormalUser},
 			{check: checkRunningInsideWSL2},
 			{check: checkAdminHelperExecutableCached},
+			{check: checkOldAdminHelperExecutableCached},
 			{check: checkSupportedCPUArch},
 			{configKeySuffix: "check-ram"},
 			{cleanup: removeCRCMachinesDir},
@@ -287,6 +294,7 @@ var checkListForDistros = []checkListForDistro{
 			{check: checkIfRunningAsNormalUser},
 			{check: checkRunningInsideWSL2},
 			{check: checkAdminHelperExecutableCached},
+			{check: checkOldAdminHelperExecutableCached},
 			{check: checkSupportedCPUArch},
 			{configKeySuffix: "check-ram"},
 			{cleanup: removeCRCMachinesDir},
@@ -320,6 +328,7 @@ var checkListForDistros = []checkListForDistro{
 			{check: checkIfRunningAsNormalUser},
 			{check: checkRunningInsideWSL2},
 			{check: checkAdminHelperExecutableCached},
+			{check: checkOldAdminHelperExecutableCached},
 			{check: checkSupportedCPUArch},
 			{configKeySuffix: "check-ram"},
 			{cleanup: removeCRCMachinesDir},
@@ -347,6 +356,7 @@ var checkListForDistros = []checkListForDistro{
 			{check: checkIfRunningAsNormalUser},
 			{check: checkRunningInsideWSL2},
 			{check: checkAdminHelperExecutableCached},
+			{check: checkOldAdminHelperExecutableCached},
 			{check: checkSupportedCPUArch},
 			{configKeySuffix: "check-ram"},
 			{cleanup: removeCRCMachinesDir},
@@ -382,6 +392,7 @@ var checkListForDistros = []checkListForDistro{
 			{check: checkIfRunningAsNormalUser},
 			{check: checkRunningInsideWSL2},
 			{check: checkAdminHelperExecutableCached},
+			{check: checkOldAdminHelperExecutableCached},
 			{check: checkSupportedCPUArch},
 			{configKeySuffix: "check-ram"},
 			{cleanup: removeCRCMachinesDir},
@@ -416,6 +427,7 @@ var checkListForDistros = []checkListForDistro{
 			{check: checkIfRunningAsNormalUser},
 			{check: checkRunningInsideWSL2},
 			{check: checkAdminHelperExecutableCached},
+			{check: checkOldAdminHelperExecutableCached},
 			{check: checkSupportedCPUArch},
 			{configKeySuffix: "check-ram"},
 			{cleanup: removeCRCMachinesDir},
diff --git a/pkg/crc/preflight/preflight_windows_test.go b/pkg/crc/preflight/preflight_windows_test.go
index 072022792..3feeb5cb8 100644
--- a/pkg/crc/preflight/preflight_windows_test.go
+++ b/pkg/crc/preflight/preflight_windows_test.go
@@ -11,13 +11,13 @@ import (
 func TestCountConfigurationOptions(t *testing.T) {
 	cfg := config.New(config.NewEmptyInMemoryStorage())
 	RegisterSettings(cfg)
-	assert.Len(t, cfg.AllConfigs(), 12)
+	assert.Len(t, cfg.AllConfigs(), 13)
 }
 
 func TestCountPreflights(t *testing.T) {
-	assert.Len(t, getPreflightChecks(false, false, network.SystemNetworkingMode), 17)
-	assert.Len(t, getPreflightChecks(true, true, network.SystemNetworkingMode), 17)
+	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.UserNetworkingMode), 18)
-	assert.Len(t, getPreflightChecks(true, true, network.UserNetworkingMode), 18)
+	assert.Len(t, getPreflightChecks(false, false, network.UserNetworkingMode), 19)
+	assert.Len(t, getPreflightChecks(true, true, network.UserNetworkingMode), 19)
 }
diff --git a/test/e2e/crcsuite/ux/uxsuite.go b/test/e2e/crcsuite/ux/uxsuite.go
index 755494d61..e95b73cd2 100644
--- a/test/e2e/crcsuite/ux/uxsuite.go
+++ b/test/e2e/crcsuite/ux/uxsuite.go
@@ -38,8 +38,8 @@ func FeatureContext(s *godog.Suite, bundleLocation *string, pullSecretFile *stri
 			clickTrayButton)
 		s.Step(`^cluster should be (.*)$`,
 			waitForClusterInState)
-		s.Step(`^set the pull secret file$`,
-			trayHandler.SetPullSecretFileLocation)
+		s.Step(`^set the pull secret$`,
+			trayHandler.SetPullSecret)
 		s.Step(`^tray should show cluster as (.*)$`,
 			checkClusterStateOnTray)
 		s.Step(`^(.*) CRC from installer$`,
diff --git a/test/e2e/features/basic.feature b/test/e2e/features/basic.feature
index bec2316f5..da666af24 100644
--- a/test/e2e/features/basic.feature
+++ b/test/e2e/features/basic.feature
@@ -39,6 +39,7 @@ Feature: Basic test
     @linux
     Scenario: CRC setup on Linux
         When executing "crc setup --check-only" fails
+        Then executing "crc start" fails
         And executing "crc setup" succeeds
         And stderr should contain "Checking if CRC bundle is extracted in '$HOME/.crc'"
         And stderr should contain "Checking if running as non-root"
@@ -57,6 +58,14 @@ Feature: Basic test
         And stdout should contain "Your system is correctly setup for using CodeReady Containers, you can now run 'crc start -b $bundlename' to start the OpenShift cluster" if bundle is not embedded
         And stdout should contain "Your system is correctly setup for using CodeReady Containers, you can now run 'crc start' to start the OpenShift cluster" if bundle is embedded
 
+    @linux
+    Scenario: Missing CRC setup
+	Given executing "rm ~/.crc/bin/crc-driver-libvirt" succeeds
+        Then executing "crc setup --check-only" fails
+        And starting CRC with default bundle fails
+	And stderr should contain "Preflight checks failed during `crc start`, please try to run `crc setup` first in case you haven't done so yet"
+	And executing "crc setup" succeeds
+
     @darwin
     Scenario: CRC setup on Mac
         When executing "crc setup --check-only" fails
diff --git a/test/e2e/features/ux.feature b/test/e2e/features/ux.feature
index 45e7b79a8..e82c12440 100644
--- a/test/e2e/features/ux.feature
+++ b/test/e2e/features/ux.feature
@@ -21,7 +21,7 @@ Feature: UX Test
     Scenario: Start the cluster
         Given fresh tray installation   
         When start the cluster from the tray
-        And set the pull secret file 
+        And set the pull secret
         Then cluster should be running
         And tray should show cluster as running
         And user should get notified with cluster state as running
diff --git a/test/extended/crc/ux/tray/applescripts/setPullSecret.applescript b/test/extended/crc/ux/tray/applescripts/setPullSecret.applescript
new file mode 100644
index 000000000..ece2c3f9b
--- /dev/null
+++ b/test/extended/crc/ux/tray/applescripts/setPullSecret.applescript
@@ -0,0 +1,45 @@
+on run{bundleIdentifer, pullSecretFile} 
+    set terminal to get_terminal()
+    # Ensure clipoard is empty
+    execute_command("pbcopy < /dev/null", terminal)
+    # Copy pull secret content to clipboard
+    execute_command("cat " & pullSecretFile & " | pbcopy", terminal)
+    # close terminal
+    close_terminal(terminal)
+    # Set the content
+    paste_pullsecret_content(bundleIdentifer, the clipboard as text)  
+end run
+
+on paste_pullsecret_content(bundleIdentifer, pullsecretContent)
+tell application "System Events"
+	tell (first application process whose bundle identifier is bundleIdentifer)
+		tell window "Paste the Pull Secret"	
+			set value of text area 1 of scroll area 1 to pullsecretContent
+            click button "OK"
+        end tell
+	end tell
+end tell
+end paste_pullsecret_content
+
+on get_terminal()
+tell application "Terminal"
+        set crcTerminal to do script ("")
+        return crcTerminal
+end tell
+end get_terminal
+
+on execute_command(command, crcTerminal)
+tell application "Terminal"
+   do script (command) in crcTerminal
+   delay 2
+end tell
+end execute_command
+
+on close_terminal(crcTerminal)
+tell application "Terminal"
+	do script ("") in crcTerminal
+        close window 1
+        delay 1
+        tell application "System Events" to keystroke return
+end tell
+end close_terminal 
diff --git a/test/extended/crc/ux/tray/applescripts/setPullSecretFileLocation.applescript b/test/extended/crc/ux/tray/applescripts/setPullSecretFileLocation.applescript
deleted file mode 100644
index 992bf823c..000000000
--- a/test/extended/crc/ux/tray/applescripts/setPullSecretFileLocation.applescript
+++ /dev/null
@@ -1,12 +0,0 @@
-on run {bundleIdentifer, pullSecretFile}
-    tell application "System Events" 
-        tell (first application process whose bundle identifier is bundleIdentifer) 
-            tell window "Select Pull Secret"
-                set value of text field 1 to pullSecretFile    
-                tell button "OK" 
-                    click
-                end tell
-            end tell 
-        end tell 
-    end tell
-end run
diff --git a/test/extended/crc/ux/tray/tray.go b/test/extended/crc/ux/tray/tray.go
index f2051084a..de0d07ae3 100644
--- a/test/extended/crc/ux/tray/tray.go
+++ b/test/extended/crc/ux/tray/tray.go
@@ -8,7 +8,7 @@ type Tray interface {
 	ClickStop() error
 	ClickDelete() error
 	ClickQuit() error
-	SetPullSecretFileLocation() error
+	SetPullSecret() error
 	IsClusterRunning() error
 	IsClusterStopped() error
 	CopyOCLoginCommandAsKubeadmin() error
diff --git a/test/extended/crc/ux/tray/tray_unix.go b/test/extended/crc/ux/tray/tray_unix.go
index c7d07a255..c6f5797aa 100644
--- a/test/extended/crc/ux/tray/tray_unix.go
+++ b/test/extended/crc/ux/tray/tray_unix.go
@@ -13,14 +13,14 @@ import (
 )
 
 const (
-	scriptsRelativePath       string = "applescripts"
-	checkTrayIconIsVisible    string = "checkTrayIconIsVisible.applescript"
-	clickTrayMenuItem         string = "clickTrayMenuItem.applescript"
-	setPullSecretFileLocation string = "setPullSecretFileLocation.applescript"
-	getTrayFieldlValue        string = "getTrayFieldlValue.applescript"
-	installTray               string = "installTray.applescript"
-	getOCLoginCommand         string = "getOCLoginCommand.applescript"
-	runOCLoginCommand         string = "runOCLoginCommand.applescript"
+	scriptsRelativePath    string = "applescripts"
+	checkTrayIconIsVisible string = "checkTrayIconIsVisible.applescript"
+	clickTrayMenuItem      string = "clickTrayMenuItem.applescript"
+	setPullSecret          string = "setPullSecret.applescript"
+	getTrayFieldlValue     string = "getTrayFieldlValue.applescript"
+	installTray            string = "installTray.applescript"
+	getOCLoginCommand      string = "getOCLoginCommand.applescript"
+	runOCLoginCommand      string = "runOCLoginCommand.applescript"
 
 	bundleIdentifier string = "com.redhat.codeready.containers"
 	appPath          string = "/Applications/CodeReady Containers.app"
@@ -108,9 +108,9 @@ func (a applescriptHandler) ClickQuit() error {
 	return clickButtonByAction(actionQuit)
 }
 
-func (a applescriptHandler) SetPullSecretFileLocation() error {
+func (a applescriptHandler) SetPullSecret() error {
 	return applescript.ExecuteApplescript(
-		setPullSecretFileLocation, bundleIdentifier, *a.pullSecretFileLocation)
+		setPullSecret, bundleIdentifier, *a.pullSecretFileLocation)
 }
 
 func (a applescriptHandler) IsClusterRunning() error {
diff --git a/test/extended/crc/ux/tray/tray_windows.go b/test/extended/crc/ux/tray/tray_windows.go
index f9f968b61..68a812276 100644
--- a/test/extended/crc/ux/tray/tray_windows.go
+++ b/test/extended/crc/ux/tray/tray_windows.go
@@ -50,7 +50,7 @@ func (h handler) ClickQuit() error {
 	return fmt.Errorf("not implemented yet")
 }
 
-func (h handler) SetPullSecretFileLocation() error {
+func (h handler) SetPullSecret() error {
 	return fmt.Errorf("not implemented yet")
 }