Repository: code-ready/crc
Pull request #2012 (2021-02-19 09:48:43)

oc commands running in a retry loop can have a 5s timeout. Increase to 30s for others.
Not all commands can have a small timeout (yet). The code is not
designed for that.
This commit increases the default timeout to 30s and uses 5s for some
specific requests (like oc get co or oc get nodes).

```
time="2021-02-19T10:46:41+01:00" level=debug msg="Running SSH command: timeout 5s oc get nodes --context admin --cluster crc --kubeconfig /opt/kubeconfig"
time="2021-02-19T10:46:46+01:00" level=debug msg="error: Temporary error: ssh command error:\ncommand : timeout 5s oc get nodes --context admin --cluster crc --kubeconfig /opt/kubeconfig\nerr     : Process exited with status 124\\n - sleeping 1s"
time="2021-02-19T10:46:47+01:00" level=debug msg="Running SSH command: timeout 5s oc get nodes --context admin --cluster crc --kubeconfig /opt/kubeconfig"
time="2021-02-19T10:46:47+01:00" level=debug msg="Running SSH command: timeout 5s oc get secret --context admin --cluster crc --kubeconfig /opt/kubeconfig"
time="2021-02-19T10:46:48+01:00" level=debug msg="Running SSH command: timeout 5s oc get clusterversion --context admin --cluster crc --kubeconfig /opt/kubeconfig"
time="2021-02-19T10:46:48+01:00" level=debug msg="Running SSH command: timeout 30s oc get clusterversion version -o jsonpath=\"{['spec']['clusterID']}\" --context admin --cluster crc --kubeconfig /opt/kubeconfig"
time="2021-02-19T10:46:48+01:00" level=debug msg="Running SSH command: timeout 30s oc patch clusterversion version -p '{\"spec\":{\"clusterID\":\"89be605e-2aaf-46a8-a865-e3be38130bae\"}}' --type merge --context admin --cluster crc --kubeconfig /opt/kubeconfig"
```

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

This pull-request has been approved by: *<a href="https://github.com/code-ready/crc/pull/2012#" 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":[]} -->
praveenkumar: Without this PR CI is failing, merging it.

Patch:
diff --git a/pkg/crc/cluster/cert-renewal.go b/pkg/crc/cluster/cert-renewal.go
index 01826b7cb..4e042355b 100644
--- a/pkg/crc/cluster/cert-renewal.go
+++ b/pkg/crc/cluster/cert-renewal.go
@@ -13,7 +13,7 @@ import (
 
 func waitForPendingCSRs(ocConfig oc.Config, signerName string) error {
 	return crcerrors.RetryAfter(8*time.Minute, func() error {
-		output, _, err := ocConfig.RunOcCommand("get", "csr")
+		output, _, err := ocConfig.WithFailFast().RunOcCommand("get", "csr")
 		if err != nil {
 			return &crcerrors.RetriableError{Err: err}
 		}
diff --git a/pkg/crc/cluster/cluster.go b/pkg/crc/cluster/cluster.go
index f445cf65d..6ca8654a8 100644
--- a/pkg/crc/cluster/cluster.go
+++ b/pkg/crc/cluster/cluster.go
@@ -312,7 +312,7 @@ func WaitForRequestHeaderClientCaFile(sshRunner *ssh.Runner) error {
 func WaitForAPIServer(ocConfig oc.Config) error {
 	logging.Debugf("Waiting for apiserver availability")
 	waitForAPIServer := func() error {
-		stdout, stderr, err := ocConfig.RunOcCommand("get", "nodes")
+		stdout, stderr, err := ocConfig.WithFailFast().RunOcCommand("get", "nodes")
 		if err != nil {
 			logging.Debug(stderr)
 			return &errors.RetriableError{Err: err}
@@ -330,7 +330,7 @@ func DeleteOpenshiftAPIServerPods(ocConfig oc.Config) error {
 
 	deleteOpenshiftAPIServerPods := func() error {
 		cmdArgs := []string{"delete", "pod", "--all", "-n", "openshift-apiserver"}
-		_, _, err := ocConfig.RunOcCommand(cmdArgs...)
+		_, _, err := ocConfig.WithFailFast().RunOcCommand(cmdArgs...)
 		if err != nil {
 			return &errors.RetriableError{Err: err}
 		}
diff --git a/pkg/crc/cluster/clusteroperator.go b/pkg/crc/cluster/clusteroperator.go
index aaee8ec0f..81a8927a4 100644
--- a/pkg/crc/cluster/clusteroperator.go
+++ b/pkg/crc/cluster/clusteroperator.go
@@ -37,7 +37,7 @@ func getStatus(ocConfig oc.Config, ignoreClusterOperators, selector []string) (*
 		Available: true,
 	}
 
-	data, _, err := ocConfig.RunOcCommandPrivate("get", "co", "-ojson")
+	data, _, err := ocConfig.WithFailFast().RunOcCommandPrivate("get", "co", "-ojson")
 	if err != nil {
 		return nil, err
 	}
diff --git a/pkg/crc/cluster/csr.go b/pkg/crc/cluster/csr.go
index 46025ad15..b4d0c7dcc 100644
--- a/pkg/crc/cluster/csr.go
+++ b/pkg/crc/cluster/csr.go
@@ -14,7 +14,7 @@ import (
 func WaitForOpenshiftResource(ocConfig oc.Config, resource string) error {
 	logging.Debugf("Waiting for availability of resource type '%s'", resource)
 	waitForAPIServer := func() error {
-		stdout, stderr, err := ocConfig.RunOcCommand("get", resource)
+		stdout, stderr, err := ocConfig.WithFailFast().RunOcCommand("get", resource)
 		if err != nil {
 			logging.Debug(stderr)
 			return &crcerrors.RetriableError{Err: err}
diff --git a/pkg/crc/oc/oc.go b/pkg/crc/oc/oc.go
index 751e743b9..b9f74fad6 100644
--- a/pkg/crc/oc/oc.go
+++ b/pkg/crc/oc/oc.go
@@ -8,7 +8,10 @@ import (
 	crcos "github.com/code-ready/crc/pkg/os"
 )
 
-const timeout = "5s"
+const (
+	defaultTimeout = "30s"
+	fastTimeout    = "5s"
+)
 
 type Config struct {
 	Runner           crcos.CommandRunner
@@ -16,6 +19,7 @@ type Config struct {
 	KubeconfigPath   string
 	Context          string
 	Cluster          string
+	Timeout          string
 }
 
 // UseOcWithConfig return the oc executable along with valid kubeconfig
@@ -26,6 +30,18 @@ func UseOCWithConfig(machineName string) Config {
 		KubeconfigPath:   filepath.Join(constants.MachineInstanceDir, machineName, "kubeconfig"),
 		Context:          constants.DefaultContext,
 		Cluster:          constants.DefaultName,
+		Timeout:          defaultTimeout,
+	}
+}
+
+func (oc Config) WithFailFast() Config {
+	return Config{
+		Runner:           oc.Runner,
+		OcExecutablePath: oc.OcExecutablePath,
+		KubeconfigPath:   oc.KubeconfigPath,
+		Context:          oc.Context,
+		Cluster:          oc.Cluster,
+		Timeout:          fastTimeout,
 	}
 }
 
@@ -41,10 +57,10 @@ func (oc Config) runCommand(isPrivate bool, args ...string) (string, string, err
 	}
 
 	if isPrivate {
-		return oc.Runner.RunPrivate("timeout", append([]string{timeout, oc.OcExecutablePath}, args...)...)
+		return oc.Runner.RunPrivate("timeout", append([]string{oc.Timeout, oc.OcExecutablePath}, args...)...)
 	}
 
-	return oc.Runner.Run("timeout", append([]string{timeout, oc.OcExecutablePath}, args...)...)
+	return oc.Runner.Run("timeout", append([]string{oc.Timeout, oc.OcExecutablePath}, args...)...)
 }
 
 func (oc Config) RunOcCommand(args ...string) (string, string, error) {
@@ -66,5 +82,6 @@ func UseOCWithSSH(sshRunner *ssh.Runner) Config {
 		KubeconfigPath:   "/opt/kubeconfig",
 		Context:          constants.DefaultContext,
 		Cluster:          constants.DefaultName,
+		Timeout:          defaultTimeout,
 	}
 }


Test patch:
diff --git a/pkg/crc/oc/oc_linux_test.go b/pkg/crc/oc/oc_linux_test.go
index 54929cd9d..b63a197b1 100644
--- a/pkg/crc/oc/oc_linux_test.go
+++ b/pkg/crc/oc/oc_linux_test.go
@@ -15,6 +15,7 @@ func TestRunCommand(t *testing.T) {
 		KubeconfigPath:   "kubeconfig-file",
 		Context:          "a-context",
 		Cluster:          "a-cluster",
+		Timeout:          defaultTimeout,
 	}
 	stdout, _, err := ocConfig.RunOcCommand("a-command")
 	assert.NoError(t, err)
@@ -26,6 +27,7 @@ func TestRunCommandWithoutContextAndCluster(t *testing.T) {
 		Runner:           crcos.NewLocalCommandRunner(),
 		OcExecutablePath: "/bin/echo",
 		KubeconfigPath:   "kubeconfig-file",
+		Timeout:          defaultTimeout,
 	}
 	stdout, _, err := ocConfig.RunOcCommand("a-command")
 	assert.NoError(t, err)