Repository: code-ready/crc
Pull request #2383 (2021-05-27 14:55:13)

Add method to list all bundles available
Sort them by OpenShift version.

It will be useful when upgrading crc: delete previous bundle, eventually
 be able to load it, etc.



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

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

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

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

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

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

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

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/pkg/crc/machine/bundle/metadata.go b/pkg/crc/machine/bundle/metadata.go
index 5e9acac0a..3cd608a74 100644
--- a/pkg/crc/machine/bundle/metadata.go
+++ b/pkg/crc/machine/bundle/metadata.go
@@ -8,6 +8,8 @@ import (
 	"strconv"
 	"strings"
 	"time"
+
+	"github.com/Masterminds/semver"
 )
 
 // Metadata structure to unmarshal the crc-bundle-info.json file
@@ -31,13 +33,13 @@ type BuildInfo struct {
 }
 
 type ClusterInfo struct {
-	OpenShiftVersion    string `json:"openshiftVersion"`
-	ClusterName         string `json:"clusterName"`
-	BaseDomain          string `json:"baseDomain"`
-	AppsDomain          string `json:"appsDomain"`
-	SSHPrivateKeyFile   string `json:"sshPrivateKeyFile"`
-	KubeConfig          string `json:"kubeConfig"`
-	OpenshiftPullSecret string `json:"openshiftPullSecret,omitempty"`
+	OpenShiftVersion    *semver.Version `json:"openshiftVersion"`
+	ClusterName         string          `json:"clusterName"`
+	BaseDomain          string          `json:"baseDomain"`
+	AppsDomain          string          `json:"appsDomain"`
+	SSHPrivateKeyFile   string          `json:"sshPrivateKeyFile"`
+	KubeConfig          string          `json:"kubeConfig"`
+	OpenshiftPullSecret string          `json:"openshiftPullSecret,omitempty"`
 }
 
 type Node struct {
@@ -157,7 +159,7 @@ func (bundle *CrcBundleInfo) GetBundleBuildTime() (time.Time, error) {
 }
 
 func (bundle *CrcBundleInfo) GetOpenshiftVersion() string {
-	return bundle.ClusterInfo.OpenShiftVersion
+	return bundle.ClusterInfo.OpenShiftVersion.String()
 }
 
 func (bundle *CrcBundleInfo) GetBundleNameWithoutExtension() string {
diff --git a/pkg/crc/machine/bundle/repository.go b/pkg/crc/machine/bundle/repository.go
index 1ffed704d..a78b596b3 100644
--- a/pkg/crc/machine/bundle/repository.go
+++ b/pkg/crc/machine/bundle/repository.go
@@ -7,11 +7,13 @@ import (
 	"os"
 	"path/filepath"
 	"runtime"
+	"sort"
 	"time"
 
 	"github.com/Masterminds/semver"
 	"github.com/code-ready/crc/pkg/crc/constants"
 	crcerrors "github.com/code-ready/crc/pkg/crc/errors"
+	"github.com/code-ready/crc/pkg/crc/logging"
 	"github.com/code-ready/crc/pkg/extract"
 	crcos "github.com/code-ready/crc/pkg/os"
 	"github.com/pkg/errors"
@@ -160,6 +162,29 @@ func (repo *Repository) Extract(path string) error {
 	}, 5*time.Second)
 }
 
+func (repo *Repository) List() ([]CrcBundleInfo, error) {
+	files, err := ioutil.ReadDir(repo.CacheDir)
+	if err != nil {
+		return nil, err
+	}
+	var ret []CrcBundleInfo
+	for _, file := range files {
+		if !file.IsDir() {
+			continue
+		}
+		bundle, err := repo.Get(file.Name())
+		if err != nil {
+			logging.Errorf("cannot load bundle %s: %v", file.Name(), err)
+			continue
+		}
+		ret = append(ret, *bundle)
+	}
+	sort.Slice(ret, func(i, j int) bool {
+		return ret[i].ClusterInfo.OpenShiftVersion.GreaterThan(ret[j].ClusterInfo.OpenShiftVersion)
+	})
+	return ret, nil
+}
+
 var defaultRepo = &Repository{
 	CacheDir: constants.MachineCacheDir,
 	OcBinDir: constants.CrcOcBinDir,
@@ -179,3 +204,7 @@ func Extract(path string) (*CrcBundleInfo, error) {
 	}
 	return defaultRepo.Get(filepath.Base(path))
 }
+
+func List() ([]CrcBundleInfo, error) {
+	return defaultRepo.List()
+}
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
+}


Test patch:
diff --git a/pkg/crc/machine/bundle/copier_test.go b/pkg/crc/machine/bundle/copier_test.go
index ef4a32708..9e36c817d 100644
--- a/pkg/crc/machine/bundle/copier_test.go
+++ b/pkg/crc/machine/bundle/copier_test.go
@@ -15,7 +15,7 @@ import (
 
 func TestGenerateBundle(t *testing.T) {
 	var b CrcBundleInfo
-	assert.NoError(t, json.Unmarshal([]byte(reference), &b))
+	assert.NoError(t, json.Unmarshal([]byte(jsonForBundle("crc_4.7.1")), &b))
 	b.bundleName = "crc_4.7.1"
 	b.Storage.Files[0].Name = constants.OcExecutableName
 
diff --git a/pkg/crc/machine/bundle/metadata_test.go b/pkg/crc/machine/bundle/metadata_test.go
index e5b49d5e9..8fec3402f 100644
--- a/pkg/crc/machine/bundle/metadata_test.go
+++ b/pkg/crc/machine/bundle/metadata_test.go
@@ -2,6 +2,7 @@ package bundle
 
 import (
 	"encoding/json"
+	"fmt"
 	"strings"
 	"testing"
 	"unicode"
@@ -9,12 +10,18 @@ import (
 	"github.com/code-ready/crc/pkg/crc/constants"
 	"github.com/code-ready/crc/pkg/crc/logging"
 
+	"github.com/Masterminds/semver"
 	"github.com/stretchr/testify/assert"
 	"github.com/stretchr/testify/require"
 )
 
-const reference = `{
-  "version": "1.0",
+func jsonForBundle(name string) string {
+	return jsonForBundleWithVersion("1.0", name)
+}
+
+func jsonForBundleWithVersion(version, name string) string {
+	return fmt.Sprintf(`{
+  "version": "%s",
   "type": "snc",
   "buildInfo": {
     "buildTime": "2020-10-26T04:48:26+00:00",
@@ -22,7 +29,7 @@ const reference = `{
     "sncVersion": "git4.1.14-137-g14e7"
   },
   "clusterInfo": {
-    "openshiftVersion": "4.6.1",
+    "openshiftVersion": "%s",
     "clusterName": "crc",
     "baseDomain": "testing",
     "appsDomain": "apps-crc.testing",
@@ -51,7 +58,7 @@ const reference = `{
     ],
     "fileList": [
       {
-        "name": "oc",
+        "name": "%s",
         "type": "oc-executable",
         "size": "72728632",
         "sha256sum": "983f0883a6dffd601afa663d10161bfd8033fd6d45cf587a9cb22e9a681d6047"
@@ -61,7 +68,13 @@ const reference = `{
   "driverInfo": {
     "name": "libvirt"
   }
-}`
+}`, version, openshiftVersion(name), constants.OcExecutableName)
+}
+
+func openshiftVersion(name string) string {
+	split := strings.Split(name, "_")
+	return split[len(split)-1]
+}
 
 var parsedReference = CrcBundleInfo{
 	Version: "1.0",
@@ -72,7 +85,7 @@ var parsedReference = CrcBundleInfo{
 		SncVersion:                "git4.1.14-137-g14e7",
 	},
 	ClusterInfo: ClusterInfo{
-		OpenShiftVersion:  "4.6.1",
+		OpenShiftVersion:  semver.MustParse("4.6.1"),
 		ClusterName:       "crc",
 		BaseDomain:        "testing",
 		AppsDomain:        "apps-crc.testing",
@@ -100,7 +113,7 @@ var parsedReference = CrcBundleInfo{
 		Files: []FileListItem{
 			{
 				File: File{
-					Name:     "oc",
+					Name:     constants.OcExecutableName,
 					Size:     "72728632",
 					Checksum: "983f0883a6dffd601afa663d10161bfd8033fd6d45cf587a9cb22e9a681d6047",
 				},
@@ -116,11 +129,11 @@ var parsedReference = CrcBundleInfo{
 
 func TestUnmarshalMarshal(t *testing.T) {
 	var bundle CrcBundleInfo
-	assert.NoError(t, json.Unmarshal([]byte(reference), &bundle))
+	assert.NoError(t, json.Unmarshal([]byte(jsonForBundle("crc_libvirt_4.6.1")), &bundle))
 	assert.Equal(t, parsedReference, bundle)
 	bin, err := json.Marshal(bundle)
 	assert.NoError(t, err)
-	assert.JSONEq(t, string(bin), reference)
+	assert.JSONEq(t, string(bin), jsonForBundle("crc_libvirt_4.6.1"))
 }
 
 // check that the bundle name has the form "crc_libvirt_4.7.8.crcbundle" or "crc_libvirt_4.7.8_123456.crcbundle"
diff --git a/pkg/crc/machine/bundle/repository_test.go b/pkg/crc/machine/bundle/repository_test.go
index 07f4ca052..4ccd7bc68 100644
--- a/pkg/crc/machine/bundle/repository_test.go
+++ b/pkg/crc/machine/bundle/repository_test.go
@@ -1,7 +1,6 @@
 package bundle
 
 import (
-	"encoding/json"
 	"io/ioutil"
 	"os"
 	"path/filepath"
@@ -9,8 +8,6 @@ import (
 	"testing"
 
 	"github.com/code-ready/crc/pkg/crc/constants"
-
-	"github.com/jinzhu/copier"
 	"github.com/stretchr/testify/assert"
 )
 
@@ -23,7 +20,7 @@ func TestUse(t *testing.T) {
 	assert.NoError(t, err)
 	defer os.RemoveAll(ocBinDir)
 
-	createDummyBundleContent(t, filepath.Join(dir, "crc_libvirt_4.6.1"), "")
+	createDummyBundleContent(t, dir, "crc_libvirt_4.6.1", "1.0")
 
 	repo := &Repository{
 		CacheDir: dir,
@@ -32,7 +29,7 @@ func TestUse(t *testing.T) {
 
 	bundle, err := repo.Use("crc_libvirt_4.6.1.crcbundle")
 	assert.NoError(t, err)
-	assert.Equal(t, "4.6.1", bundle.ClusterInfo.OpenShiftVersion)
+	assert.Equal(t, "4.6.1", bundle.ClusterInfo.OpenShiftVersion.String())
 
 	bin, err := ioutil.ReadFile(filepath.Join(ocBinDir, constants.OcExecutableName))
 	assert.NoError(t, err)
@@ -49,7 +46,7 @@ func TestUseWithOCFile(t *testing.T) {
 	fd.Close()
 	defer os.RemoveAll(fd.Name())
 
-	createDummyBundleContent(t, filepath.Join(dir, "crc_libvirt_4.6.1"), "")
+	createDummyBundleContent(t, dir, "crc_libvirt_4.6.1", "1.0")
 
 	repo := &Repository{
 		CacheDir: dir,
@@ -78,7 +75,7 @@ func TestExtract(t *testing.T) {
 
 	bundle, err := repo.Get(testBundle(t))
 	assert.NoError(t, err)
-	assert.Equal(t, "4.6.1", bundle.ClusterInfo.OpenShiftVersion)
+	assert.Equal(t, "4.6.1", bundle.GetOpenshiftVersion())
 
 	_ = os.Remove(bundle.GetKubeConfigPath())
 	bundle, err = repo.Get(testBundle(t))
@@ -110,42 +107,64 @@ func TestVersionCheck(t *testing.T) {
 	}
 
 	bundlePath := filepath.Join(dir, "crc_libvirt_4.6.1")
-	createDummyBundleContent(t, bundlePath, "0.9")
+	createDummyBundleContent(t, dir, "crc_libvirt_4.6.1", "0.9")
 	_, err = repo.Get("crc_libvirt_4.6.1.crcbundle")
 	assert.EqualError(t, err, "cannot use bundle with version 0.9, bundle version must satisfy ^1.0 constraint")
 	os.RemoveAll(bundlePath)
 
-	createDummyBundleContent(t, bundlePath, "1.1")
+	createDummyBundleContent(t, dir, "crc_libvirt_4.6.1", "1.1")
 	_, err = repo.Get("crc_libvirt_4.6.1.crcbundle")
 	assert.NoError(t, err)
 	os.RemoveAll(bundlePath)
 
-	createDummyBundleContent(t, bundlePath, "2.0")
+	createDummyBundleContent(t, dir, "crc_libvirt_4.6.1", "2.0")
 	_, err = repo.Get("crc_libvirt_4.6.1.crcbundle")
 	assert.EqualError(t, err, "cannot use bundle with version 2.0, bundle version must satisfy ^1.0 constraint")
 	os.RemoveAll(bundlePath)
 }
 
-func writeMetadata(t *testing.T, dir string, bundleInfo *CrcBundleInfo) bool {
-	metadataStr, err := json.Marshal(bundleInfo)
+func TestListBundles(t *testing.T) {
+	dir, err := ioutil.TempDir("", "repo")
 	assert.NoError(t, err)
-	return assert.NoError(t, ioutil.WriteFile(filepath.Join(dir, metadataFilename), []byte(metadataStr), 0600))
-}
+	defer os.RemoveAll(dir)
+
+	ocBinDir, err := ioutil.TempDir("", "oc-bin-dir")
+	assert.NoError(t, err)
+	defer os.RemoveAll(ocBinDir)
 
-func createDummyBundleContent(t *testing.T, bundlePath string, version string) {
-	assert.NoError(t, os.Mkdir(bundlePath, 0755))
+	createDummyBundleContent(t, dir, "crc_libvirt_4.6.15", "1.0")
+	createDummyBundleContent(t, dir, "crc_libvirt_4.7.0", "1.0")
+	createDummyBundleContent(t, dir, "crc_libvirt_4.7.11_1621489482", "1.0")
+	createDummyBundleContent(t, dir, "crc_libvirt_4.8.0-0.nightly-2021-05-26-021757", "1.0")
+	createDummyBundleContent(t, dir, "crc_libvirt_4.10.0", "1.0")
 
-	var bundleInfo CrcBundleInfo
-	assert.NoError(t, copier.Copy(&bundleInfo, &parsedReference))
-	bundleInfo.Storage.Files[0].Name = constants.OcExecutableName
-	if version != "" {
-		bundleInfo.Version = version
+	repo := &Repository{
+		CacheDir: dir,
+		OcBinDir: ocBinDir,
 	}
-	writeMetadata(t, bundlePath, &bundleInfo)
 
-	assert.NoError(t, ioutil.WriteFile(filepath.Join(bundlePath, constants.OcExecutableName), []byte("openshift-client"), 0600))
-	assert.NoError(t, ioutil.WriteFile(filepath.Join(bundlePath, "kubeadmin-password"), []byte("kubeadmin-password"), 0600))
-	assert.NoError(t, ioutil.WriteFile(filepath.Join(bundlePath, "kubeconfig"), []byte("kubeconfig"), 0600))
-	assert.NoError(t, ioutil.WriteFile(filepath.Join(bundlePath, "id_ecdsa_crc"), []byte("id_ecdsa_crc"), 0600))
-	assert.NoError(t, ioutil.WriteFile(filepath.Join(bundlePath, "crc.qcow2"), []byte("crc.qcow2"), 0600))
+	bundles, err := repo.List()
+	assert.NoError(t, err)
+	var names []string
+	for _, bundle := range bundles {
+		names = append(names, bundle.GetBundleName())
+	}
+	assert.Equal(t, []string{
+		"crc_libvirt_4.7.11_1621489482",
+		"crc_libvirt_4.10.0",
+		"crc_libvirt_4.8.0-0.nightly-2021-05-26-021757",
+		"crc_libvirt_4.7.0",
+		"crc_libvirt_4.6.15",
+	}, names)
+}
+
+func createDummyBundleContent(t *testing.T, dir, name, version string) {
+	bundleDir := filepath.Join(dir, name)
+	assert.NoError(t, os.MkdirAll(bundleDir, 0755))
+	assert.NoError(t, ioutil.WriteFile(filepath.Join(bundleDir, metadataFilename), []byte(jsonForBundleWithVersion(version, name)), 0600))
+	assert.NoError(t, ioutil.WriteFile(filepath.Join(bundleDir, constants.OcExecutableName), []byte("openshift-client"), 0600))
+	assert.NoError(t, ioutil.WriteFile(filepath.Join(bundleDir, "kubeadmin-password"), []byte("kubeadmin-password"), 0600))
+	assert.NoError(t, ioutil.WriteFile(filepath.Join(bundleDir, "kubeconfig"), []byte("kubeconfig"), 0600))
+	assert.NoError(t, ioutil.WriteFile(filepath.Join(bundleDir, "id_ecdsa_crc"), []byte("id_ecdsa_crc"), 0600))
+	assert.NoError(t, ioutil.WriteFile(filepath.Join(bundleDir, "crc.qcow2"), []byte("crc.qcow2"), 0600))
 }
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")
 }