Repository: code-ready/crc
Pull request #1822 (2021-01-06 15:59:47)

Several fixes for proxy configuration
While working with mitmproxy and crc, I've found couple of issues.

* the deployment we watched no longer exist. I updated it.
* 60s is not enough clearly. 
* I removed the restart of kubelet/crio. I only needed to change the configuration of kubelet/crio before the start of kubelet.
* default service ip range changed.

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

This pull-request has been approved by: *<a href="https://github.com/code-ready/crc/pull/1822#" 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-embedder/cmd/extract.go b/cmd/crc-embedder/cmd/extract.go
index e99ce853f..f0cab79ed 100644
--- a/cmd/crc-embedder/cmd/extract.go
+++ b/cmd/crc-embedder/cmd/extract.go
@@ -1,10 +1,10 @@
 package cmd
 
 import (
+	"fmt"
+
 	"github.com/code-ready/crc/pkg/crc/logging"
-	"github.com/code-ready/crc/pkg/crc/output"
 	"github.com/code-ready/crc/pkg/embed"
-
 	"github.com/spf13/cobra"
 )
 
@@ -32,5 +32,5 @@ func runExtract(args []string) {
 	if err != nil {
 		logging.Fatalf("Could not extract data embedded in %s: %v", executablePath, err)
 	}
-	output.Outf("Successfully copied embedded '%s' from %s to %s: %v", embedName, executablePath, destFile, err)
+	fmt.Printf("Successfully copied embedded '%s' from %s to %s: %v", embedName, executablePath, destFile, err)
 }
diff --git a/cmd/crc-embedder/cmd/list.go b/cmd/crc-embedder/cmd/list.go
index 3fe8d6d1a..9ab0c52bb 100644
--- a/cmd/crc-embedder/cmd/list.go
+++ b/cmd/crc-embedder/cmd/list.go
@@ -1,10 +1,10 @@
 package cmd
 
 import (
-	"github.com/code-ready/crc/pkg/crc/logging"
-	"github.com/code-ready/crc/pkg/crc/output"
+	"fmt"
 
 	"github.com/YourFin/binappend"
+	"github.com/code-ready/crc/pkg/crc/logging"
 	"github.com/spf13/cobra"
 )
 
@@ -30,8 +30,8 @@ func runList(args []string) {
 	if err != nil {
 		logging.Fatalf("Could not access data embedded in %s: %v", executablePath, err)
 	}
-	output.Outf("Data files embedded in %s:\n", executablePath)
+	fmt.Printf("Data files embedded in %s:\n", executablePath)
 	for _, name := range extractor.AvalibleData() {
-		output.Outln("\t", name)
+		fmt.Println("\t", name)
 	}
 }
diff --git a/cmd/crc-embedder/cmd/root.go b/cmd/crc-embedder/cmd/root.go
index a062cd816..eb00a0634 100644
--- a/cmd/crc-embedder/cmd/root.go
+++ b/cmd/crc-embedder/cmd/root.go
@@ -1,10 +1,10 @@
 package cmd
 
 import (
+	"fmt"
+
 	"github.com/code-ready/crc/pkg/crc/constants"
 	"github.com/code-ready/crc/pkg/crc/logging"
-	"github.com/code-ready/crc/pkg/crc/output"
-
 	"github.com/spf13/cobra"
 )
 
@@ -41,8 +41,8 @@ func runPrerun() {
 }
 
 func runRoot() {
-	output.Outln("No command given")
-	output.Outln("")
+	fmt.Println("No command given")
+	fmt.Println("")
 }
 
 func runPostrun() {
diff --git a/cmd/crc/cmd/config/config.go b/cmd/crc/cmd/config/config.go
index 4aa2e4cdb..d3ba19a85 100644
--- a/cmd/crc/cmd/config/config.go
+++ b/cmd/crc/cmd/config/config.go
@@ -48,7 +48,7 @@ func RegisterSettings(cfg *config.Config) {
 	cfg.AddSetting(EnableClusterMonitoring, false, config.ValidateBool, config.SuccessfullyApplied)
 
 	// Telemeter Configuration
-	cfg.AddSetting(ConsentTelemetry, false, config.ValidateBool, config.SuccessfullyApplied)
+	cfg.AddSetting(ConsentTelemetry, "", config.ValidateYesNo, config.SuccessfullyApplied)
 }
 
 func isPreflightKey(key string) bool {
diff --git a/cmd/crc/cmd/config/get.go b/cmd/crc/cmd/config/get.go
index 2a6cb92f7..9f694eb79 100644
--- a/cmd/crc/cmd/config/get.go
+++ b/cmd/crc/cmd/config/get.go
@@ -5,7 +5,6 @@ import (
 	"fmt"
 
 	"github.com/code-ready/crc/pkg/crc/config"
-	"github.com/code-ready/crc/pkg/crc/output"
 	"github.com/spf13/cobra"
 )
 
@@ -26,7 +25,7 @@ func configGetCmd(config config.Storage) *cobra.Command {
 			case v.IsDefault:
 				return fmt.Errorf("Configuration property '%s' is not set. Default value is '%s'", key, v.AsString())
 			default:
-				output.Outln(key, ":", v.AsString())
+				fmt.Println(key, ":", v.AsString())
 			}
 			return nil
 		},
diff --git a/cmd/crc/cmd/config/set.go b/cmd/crc/cmd/config/set.go
index f6b356b20..0afc89d54 100644
--- a/cmd/crc/cmd/config/set.go
+++ b/cmd/crc/cmd/config/set.go
@@ -2,9 +2,9 @@ package config
 
 import (
 	"errors"
+	"fmt"
 
 	"github.com/code-ready/crc/pkg/crc/config"
-	"github.com/code-ready/crc/pkg/crc/output"
 	"github.com/spf13/cobra"
 )
 
@@ -23,7 +23,7 @@ func configSetCmd(config config.Storage) *cobra.Command {
 			}
 
 			if setMessage != "" {
-				output.Outln(setMessage)
+				fmt.Println(setMessage)
 			}
 			return nil
 		},
diff --git a/cmd/crc/cmd/config/unset.go b/cmd/crc/cmd/config/unset.go
index cfbe6484b..222c20595 100644
--- a/cmd/crc/cmd/config/unset.go
+++ b/cmd/crc/cmd/config/unset.go
@@ -2,9 +2,9 @@ package config
 
 import (
 	"errors"
+	"fmt"
 
 	"github.com/code-ready/crc/pkg/crc/config"
-	"github.com/code-ready/crc/pkg/crc/output"
 	"github.com/spf13/cobra"
 )
 
@@ -22,7 +22,7 @@ func configUnsetCmd(config config.Storage) *cobra.Command {
 				return err
 			}
 			if unsetMessage != "" {
-				output.Outln(unsetMessage)
+				fmt.Println(unsetMessage)
 			}
 			return nil
 		},
diff --git a/cmd/crc/cmd/ip.go b/cmd/crc/cmd/ip.go
index 576178ac0..477040f60 100644
--- a/cmd/crc/cmd/ip.go
+++ b/cmd/crc/cmd/ip.go
@@ -1,7 +1,8 @@
 package cmd
 
 import (
-	"github.com/code-ready/crc/pkg/crc/output"
+	"fmt"
+
 	"github.com/spf13/cobra"
 )
 
@@ -28,6 +29,6 @@ func runIP(arguments []string) error {
 	if err != nil {
 		return err
 	}
-	output.Outln(ip)
+	fmt.Println(ip)
 	return nil
 }
diff --git a/cmd/crc/cmd/oc_env.go b/cmd/crc/cmd/oc_env.go
index 09495bf92..b9ae212df 100644
--- a/cmd/crc/cmd/oc_env.go
+++ b/cmd/crc/cmd/oc_env.go
@@ -4,7 +4,6 @@ import (
 	"fmt"
 
 	"github.com/code-ready/crc/pkg/crc/constants"
-	"github.com/code-ready/crc/pkg/crc/output"
 	"github.com/code-ready/crc/pkg/os/shell"
 	"github.com/spf13/cobra"
 )
@@ -34,13 +33,13 @@ func runOcEnv(args []string) error {
 		return err
 	}
 	proxyConfig := consoleResult.ClusterConfig.ProxyConfig
-	output.Outln(shell.GetPathEnvString(userShell, constants.CrcOcBinDir))
+	fmt.Println(shell.GetPathEnvString(userShell, constants.CrcOcBinDir))
 	if proxyConfig.IsEnabled() {
-		output.Outln(shell.GetEnvString(userShell, "HTTP_PROXY", proxyConfig.HTTPProxy))
-		output.Outln(shell.GetEnvString(userShell, "HTTPS_PROXY", proxyConfig.HTTPSProxy))
-		output.Outln(shell.GetEnvString(userShell, "NO_PROXY", proxyConfig.GetNoProxyString()))
+		fmt.Println(shell.GetEnvString(userShell, "HTTP_PROXY", proxyConfig.HTTPProxy))
+		fmt.Println(shell.GetEnvString(userShell, "HTTPS_PROXY", proxyConfig.HTTPSProxy))
+		fmt.Println(shell.GetEnvString(userShell, "NO_PROXY", proxyConfig.GetNoProxyString()))
 	}
-	output.Outln(shell.GenerateUsageHint(userShell, "crc oc-env"))
+	fmt.Println(shell.GenerateUsageHint(userShell, "crc oc-env"))
 	return nil
 }
 
diff --git a/cmd/crc/cmd/podman_env.go b/cmd/crc/cmd/podman_env.go
index ad37ea0f4..2a2014b07 100644
--- a/cmd/crc/cmd/podman_env.go
+++ b/cmd/crc/cmd/podman_env.go
@@ -5,7 +5,6 @@ import (
 	"fmt"
 
 	"github.com/code-ready/crc/pkg/crc/constants"
-	"github.com/code-ready/crc/pkg/crc/output"
 	"github.com/code-ready/crc/pkg/os/shell"
 	"github.com/spf13/cobra"
 )
@@ -36,12 +35,12 @@ func RunPodmanEnv(args []string) error {
 		return err
 	}
 
-	output.Outln(shell.GetPathEnvString(userShell, constants.CrcBinDir))
-	output.Outln(shell.GetEnvString(userShell, "PODMAN_USER", constants.DefaultSSHUser))
-	output.Outln(shell.GetEnvString(userShell, "PODMAN_HOST", ip))
-	output.Outln(shell.GetEnvString(userShell, "PODMAN_IDENTITY_FILE", constants.GetPrivateKeyPath()))
-	output.Outln(shell.GetEnvString(userShell, "PODMAN_IGNORE_HOSTS", "1"))
-	output.Outln(shell.GenerateUsageHint(userShell, "crc podman-env"))
+	fmt.Println(shell.GetPathEnvString(userShell, constants.CrcBinDir))
+	fmt.Println(shell.GetEnvString(userShell, "PODMAN_USER", constants.DefaultSSHUser))
+	fmt.Println(shell.GetEnvString(userShell, "PODMAN_HOST", ip))
+	fmt.Println(shell.GetEnvString(userShell, "PODMAN_IDENTITY_FILE", constants.GetPrivateKeyPath()))
+	fmt.Println(shell.GetEnvString(userShell, "PODMAN_IGNORE_HOSTS", "1"))
+	fmt.Println(shell.GenerateUsageHint(userShell, "crc podman-env"))
 	return nil
 }
 
diff --git a/cmd/crc/cmd/root.go b/cmd/crc/cmd/root.go
index 1c2b96adf..4c360a139 100644
--- a/cmd/crc/cmd/root.go
+++ b/cmd/crc/cmd/root.go
@@ -13,7 +13,6 @@ import (
 	"github.com/code-ready/crc/pkg/crc/logging"
 	"github.com/code-ready/crc/pkg/crc/machine"
 	"github.com/code-ready/crc/pkg/crc/network"
-	"github.com/code-ready/crc/pkg/crc/output"
 	"github.com/code-ready/crc/pkg/crc/preflight"
 	"github.com/code-ready/crc/pkg/crc/segment"
 	"github.com/spf13/cobra"
@@ -80,7 +79,7 @@ func runPostrun() {
 }
 
 func runRoot() {
-	output.Outln("No command given")
+	fmt.Println("No command given")
 }
 
 func Execute() {
diff --git a/cmd/crc/cmd/setup.go b/cmd/crc/cmd/setup.go
index d8b5ace93..e0e3946d1 100644
--- a/cmd/crc/cmd/setup.go
+++ b/cmd/crc/cmd/setup.go
@@ -8,6 +8,7 @@ import (
 
 	cmdConfig "github.com/code-ready/crc/cmd/crc/cmd/config"
 	"github.com/code-ready/crc/pkg/crc/constants"
+	"github.com/code-ready/crc/pkg/crc/input"
 	"github.com/code-ready/crc/pkg/crc/preflight"
 	"github.com/spf13/cobra"
 )
@@ -31,6 +32,20 @@ var setupCmd = &cobra.Command{
 }
 
 func runSetup(arguments []string) error {
+	if config.Get(cmdConfig.ConsentTelemetry).AsString() == "" {
+		fmt.Println("CodeReady Containers is constantly improving and we would like to know more about usage!")
+		if input.PromptUserForYesOrNo("Would you like to contribute anonymous usage statistics (more details at https://developers.redhat.com/article/tool-data-collection)", false) {
+			if _, err := config.Set(cmdConfig.ConsentTelemetry, "yes"); err != nil {
+				return err
+			}
+			fmt.Printf("Thanks for helping us! You can disable telemetry with the command 'crc config set %s no'.\n", cmdConfig.ConsentTelemetry)
+		} else {
+			if _, err := config.Set(cmdConfig.ConsentTelemetry, "no"); err != nil {
+				return err
+			}
+			fmt.Printf("No worry, you can still enable telemetry manually with the command 'crc config set %s yes'.\n", cmdConfig.ConsentTelemetry)
+		}
+	}
 	err := preflight.SetupHost(config)
 	return render(&setupResult{
 		Success: err == nil,
diff --git a/docs/source/topics/ref_dns-configuration.adoc b/docs/source/topics/ref_dns-configuration.adoc
index 02caeb1cd..b80b654f8 100644
--- a/docs/source/topics/ref_dns-configuration.adoc
+++ b/docs/source/topics/ref_dns-configuration.adoc
@@ -17,7 +17,28 @@ Additional checks are done to verify DNS is properly configured when running [co
 [id="dns-configuration-linux_{context}"]
 == Linux
 
-On Linux, {prod} expects the following DNS configuration:
+On Linux, depending on your distribution, {prod} expects the following DNS configuration:
+
+=== NetworkManager + systemd-resolved
+
+This configuration is used on Fedora 33 or newer, and on Ubuntu Desktop editions.
+
+* {prod} expects NetworkManager to manage networking.
+* {prod} configures `systemd-resolved` to forward requests for the `testing` domain to the `192.168.130.11` DNS server.
+`192.168.130.11` is the IP of the {prod} virtual machine.
+* `systemd-resolved` configuration is done through a NetworkManager dispatcher script in `/etc/NetworkManager/dispatcher.d/99-crc.sh`:
++
+----
+resolvectl domain crc ~testing
+resolvectl dns crc 192.168.130.11
+resolvectl default-route crc false
+
+exit 0
+----
+
+=== NetworkManager + dnsmasq
+
+This configuration is used on Fedora 32 or older, on {rhel}, and on {centos}.
 
 * {prod} expects NetworkManager to manage networking.
 * NetworkManager uses `dnsmasq` through the [filename]`/etc/NetworkManager/conf.d/crc-nm-dnsmasq.conf` configuration file.
diff --git a/pkg/crc/cluster/cluster.go b/pkg/crc/cluster/cluster.go
index a9c83905d..d9866e5a1 100644
--- a/pkg/crc/cluster/cluster.go
+++ b/pkg/crc/cluster/cluster.go
@@ -236,7 +236,7 @@ func AddProxyToKubeletAndCriO(sshRunner *ssh.Runner, proxy *network.ProxyConfig)
 	proxyTemplate := `[Service]
 Environment=HTTP_PROXY=%s
 Environment=HTTPS_PROXY=%s
-Environment=NO_PROXY=.cluster.local,.svc,10.128.0.0/14,172.30.0.0/16,%s`
+Environment=NO_PROXY=.cluster.local,.svc,10.116.0.0/14,172.25.0.0/16,192.168.126.0/24,%s`
 	p := fmt.Sprintf(proxyTemplate, proxy.HTTPProxy, proxy.HTTPSProxy, proxy.GetNoProxyString())
 	// This will create a systemd drop-in configuration for proxy (both for kubelet and crio services) on the VM.
 	err := sshRunner.CopyData([]byte(p), "/etc/systemd/system/crio.service.d/10-default-env.conf", 0644)
diff --git a/pkg/crc/config/config.go b/pkg/crc/config/config.go
index 7cd3cf121..0fe0f538d 100644
--- a/pkg/crc/config/config.go
+++ b/pkg/crc/config/config.go
@@ -9,7 +9,7 @@ import (
 
 const (
 	configPropDoesntExistMsg = "Configuration property '%s' does not exist"
-	invalidProp              = "Value '%s' for configuration property '%s' is invalid, reason: %s"
+	invalidProp              = "Value '%v' for configuration property '%s' is invalid, reason: %s"
 )
 
 type Config struct {
diff --git a/pkg/crc/config/validations.go b/pkg/crc/config/validations.go
index 634c21fe1..5ce5bd6bb 100644
--- a/pkg/crc/config/validations.go
+++ b/pkg/crc/config/validations.go
@@ -95,3 +95,10 @@ func ValidateNoProxy(value interface{}) (bool, string) {
 	}
 	return true, ""
 }
+
+func ValidateYesNo(value interface{}) (bool, string) {
+	if cast.ToString(value) == "yes" || cast.ToString(value) == "no" {
+		return true, ""
+	}
+	return false, "must be yes or no"
+}
diff --git a/pkg/crc/constants/constants.go b/pkg/crc/constants/constants.go
index 14bf0b6c7..dd51d0ac6 100644
--- a/pkg/crc/constants/constants.go
+++ b/pkg/crc/constants/constants.go
@@ -71,14 +71,20 @@ func GetAdminHelperURL() string {
 	return adminHelperURLForOs[runtime.GOOS]
 }
 
-var defaultBundleForOs = map[string]string{
-	"darwin":  fmt.Sprintf("crc_hyperkit_%s.crcbundle", version.GetBundleVersion()),
-	"linux":   fmt.Sprintf("crc_libvirt_%s.crcbundle", version.GetBundleVersion()),
-	"windows": fmt.Sprintf("crc_hyperv_%s.crcbundle", version.GetBundleVersion()),
+func defaultBundleForOs(bundleVersion string) map[string]string {
+	return map[string]string{
+		"darwin":  fmt.Sprintf("crc_hyperkit_%s.crcbundle", bundleVersion),
+		"linux":   fmt.Sprintf("crc_libvirt_%s.crcbundle", bundleVersion),
+		"windows": fmt.Sprintf("crc_hyperv_%s.crcbundle", bundleVersion),
+	}
 }
 
 func GetDefaultBundleForOs(os string) string {
-	return defaultBundleForOs[os]
+	return GetBundleFosOs(os, version.GetBundleVersion())
+}
+
+func GetBundleFosOs(os, bundleVersion string) string {
+	return defaultBundleForOs(bundleVersion)[os]
 }
 
 func GetDefaultBundle() string {
diff --git a/pkg/crc/input/input.go b/pkg/crc/input/input.go
index be5086102..7f77c8729 100644
--- a/pkg/crc/input/input.go
+++ b/pkg/crc/input/input.go
@@ -6,7 +6,6 @@ import (
 	"os"
 	"strings"
 
-	"github.com/code-ready/crc/pkg/crc/output"
 	terminal "golang.org/x/term"
 	survey "gopkg.in/AlecAivazis/survey.v1"
 )
@@ -19,7 +18,7 @@ func PromptUserForYesOrNo(message string, force bool) bool {
 		return false
 	}
 	var response string
-	output.Outf(message + "? [y/N]: ")
+	fmt.Printf(message + "? [y/N]: ")
 	fmt.Scanf("%s", &response)
 
 	return strings.ToLower(response) == "y"
diff --git a/pkg/crc/machine/start.go b/pkg/crc/machine/start.go
index 545c51c18..b844edbab 100644
--- a/pkg/crc/machine/start.go
+++ b/pkg/crc/machine/start.go
@@ -27,7 +27,6 @@ import (
 	"github.com/code-ready/machine/libmachine"
 	"github.com/code-ready/machine/libmachine/drivers"
 	"github.com/code-ready/machine/libmachine/host"
-	"github.com/code-ready/machine/libmachine/log"
 	"github.com/code-ready/machine/libmachine/state"
 	"github.com/docker/go-units"
 	"github.com/pkg/errors"
@@ -260,6 +259,7 @@ func (client *client) Start(startConfig StartConfig) (*StartResult, error) {
 		return nil, errors.Wrap(err, "Error getting proxy configuration")
 	}
 	proxyConfig.ApplyToEnvironment()
+	proxyConfig.AddNoProxy(instanceIP)
 
 	// Create servicePostStartConfig for DNS checks and DNS start.
 	servicePostStartConfig := services.ServicePostStartConfig{
@@ -303,6 +303,10 @@ func (client *client) Start(startConfig StartConfig) (*StartResult, error) {
 		return nil, errors.Wrap(err, "Failed to update VM pull secret")
 	}
 
+	if err := ensureKubeletAndCRIOAreConfiguredForProxy(sshRunner, proxyConfig, instanceIP); err != nil {
+		return nil, errors.Wrap(err, "Failed to update proxy configuration of kubelet and crio")
+	}
+
 	// Check the certs validity inside the vm
 	logging.Info("Verifying validity of the kubelet certificates ...")
 	certsExpired, err := cluster.CheckCertsValidity(sshRunner)
@@ -327,11 +331,8 @@ func (client *client) Start(startConfig StartConfig) (*StartResult, error) {
 		return nil, errors.Wrap(err, "Error waiting for apiserver")
 	}
 
-	if !exists {
-		logging.Info("Configuring cluster for first start")
-		if err := configProxyForCluster(ocConfig, sshRunner, sd, proxyConfig, instanceIP); err != nil {
-			return nil, errors.Wrap(err, "Error Setting cluster config")
-		}
+	if err := ensureProxyIsConfiguredInOpenShift(ocConfig, sshRunner, proxyConfig, instanceIP); err != nil {
+		return nil, errors.Wrap(err, "Failed to update cluster proxy configuration")
 	}
 
 	if err := cluster.EnsurePullSecretPresentInTheCluster(ocConfig, startConfig.PullSecret); err != nil {
@@ -376,14 +377,11 @@ func (client *client) Start(startConfig StartConfig) (*StartResult, error) {
 
 	time.Sleep(time.Minute * 3)
 
+	waitForProxyPropagation(ocConfig, proxyConfig)
+
 	logging.Info("Updating kubeconfig")
 	if err := eventuallyWriteKubeconfig(ocConfig, instanceIP, clusterConfig); err != nil {
-		log.Warnf("Cannot update kubeconfig: %v", err)
-	}
-
-	if proxyConfig.IsEnabled() {
-		logging.Info("Waiting for the proxy configuration to be applied ...")
-		waitForProxyPropagation(ocConfig, proxyConfig)
+		logging.Warnf("Cannot update kubeconfig: %v", err)
 	}
 
 	logging.Warn("The cluster might report a degraded or error state. This is expected since several operators have been disabled to lower the resource usage. For more information, please consult the documentation")
@@ -500,41 +498,29 @@ func updateSSHKeyAndCopyKubeconfig(sshRunner *crcssh.Runner, name string, crcBun
 	return nil
 }
 
-func configProxyForCluster(ocConfig oc.Config, sshRunner *crcssh.Runner, sd *systemd.Commander, proxy *network.ProxyConfig, instanceIP string) (err error) {
+func ensureKubeletAndCRIOAreConfiguredForProxy(sshRunner *crcssh.Runner, proxy *network.ProxyConfig, instanceIP string) (err error) {
 	if !proxy.IsEnabled() {
 		return nil
 	}
-	defer func() {
-		// Restart the crio service
-		if proxy.IsEnabled() {
-			// Restart reload the daemon and then restart the service
-			// So no need to explicit reload the daemon.
-			if ferr := sd.Restart("crio"); ferr != nil {
-				err = ferr
-			}
-			if ferr := sd.Restart("kubelet"); ferr != nil {
-				err = ferr
-			}
-		}
-	}()
-
-	logging.Info("Adding proxy configuration to the cluster ...")
-	proxy.AddNoProxy(instanceIP)
-	if err := cluster.AddProxyConfigToCluster(sshRunner, ocConfig, proxy); err != nil {
-		return err
-	}
-
 	logging.Info("Adding proxy configuration to kubelet and crio service ...")
-	if err := cluster.AddProxyToKubeletAndCriO(sshRunner, proxy); err != nil {
-		return err
-	}
+	return cluster.AddProxyToKubeletAndCriO(sshRunner, proxy)
+}
 
-	return nil
+func ensureProxyIsConfiguredInOpenShift(ocConfig oc.Config, sshRunner *crcssh.Runner, proxy *network.ProxyConfig, instanceIP string) (err error) {
+	if !proxy.IsEnabled() {
+		return nil
+	}
+	logging.Info("Adding proxy configuration to the cluster ...")
+	return cluster.AddProxyConfigToCluster(sshRunner, ocConfig, proxy)
 }
 
 func waitForProxyPropagation(ocConfig oc.Config, proxyConfig *network.ProxyConfig) {
+	if !proxyConfig.IsEnabled() {
+		return
+	}
+	logging.Info("Waiting for the proxy configuration to be applied ...")
 	checkProxySettingsForOperator := func() error {
-		proxySet, err := cluster.CheckProxySettingsForOperator(ocConfig, proxyConfig, "redhat-operators", "openshift-marketplace")
+		proxySet, err := cluster.CheckProxySettingsForOperator(ocConfig, proxyConfig, "marketplace-operator", "openshift-marketplace")
 		if err != nil {
 			logging.Debugf("Error getting proxy setting for openshift-marketplace operator %v", err)
 			return &crcerrors.RetriableError{Err: err}
@@ -546,7 +532,7 @@ func waitForProxyPropagation(ocConfig oc.Config, proxyConfig *network.ProxyConfi
 		return nil
 	}
 
-	if err := crcerrors.RetryAfter(60*time.Second, checkProxySettingsForOperator, 2*time.Second); err != nil {
+	if err := crcerrors.RetryAfter(300*time.Second, checkProxySettingsForOperator, 2*time.Second); err != nil {
 		logging.Debug("Failed to propagate proxy settings to cluster")
 	}
 }
diff --git a/pkg/crc/output/output.go b/pkg/crc/output/output.go
deleted file mode 100644
index 80b50f461..000000000
--- a/pkg/crc/output/output.go
+++ /dev/null
@@ -1,18 +0,0 @@
-package output
-
-import (
-	"fmt"
-	"io"
-)
-
-func Outln(args ...interface{}) {
-	fmt.Println(args...)
-}
-
-func Outf(s string, args ...interface{}) {
-	fmt.Printf(s, args...)
-}
-
-func Fout(w io.Writer, args ...interface{}) (n int, err error) {
-	return fmt.Fprintln(w, args...)
-}
diff --git a/pkg/crc/segment/segment.go b/pkg/crc/segment/segment.go
index e9ac423c4..f81d6131c 100644
--- a/pkg/crc/segment/segment.go
+++ b/pkg/crc/segment/segment.go
@@ -56,7 +56,7 @@ func (c *Client) Close() error {
 }
 
 func (c *Client) Upload(action string, duration time.Duration, err error) error {
-	if !c.config.Get(config.ConsentTelemetry).AsBool() {
+	if c.config.Get(config.ConsentTelemetry).AsString() != "yes" {
 		return nil
 	}
 


Test patch:
diff --git a/pkg/crc/segment/segment_test.go b/pkg/crc/segment/segment_test.go
index abc799f97..0eabde50c 100644
--- a/pkg/crc/segment/segment_test.go
+++ b/pkg/crc/segment/segment_test.go
@@ -60,7 +60,7 @@ func mockServer() (chan []byte, *httptest.Server) {
 	return done, server
 }
 
-func newTestConfig(value bool) (*crcConfig.Config, error) {
+func newTestConfig(value string) (*crcConfig.Config, error) {
 	storage := crcConfig.NewEmptyInMemoryStorage()
 	config := crcConfig.New(storage)
 	cmdConfig.RegisterSettings(config)
@@ -80,7 +80,7 @@ func TestClientUploadWithConsent(t *testing.T) {
 	require.NoError(t, err)
 	defer os.RemoveAll(dir)
 
-	config, err := newTestConfig(true)
+	config, err := newTestConfig("yes")
 	require.NoError(t, err)
 
 	c, err := newCustomClient(config, filepath.Join(dir, "telemetry"), server.URL)
@@ -113,7 +113,7 @@ func TestClientUploadWithOutConsent(t *testing.T) {
 	require.NoError(t, err)
 	defer os.RemoveAll(dir)
 
-	config, err := newTestConfig(false)
+	config, err := newTestConfig("no")
 	require.NoError(t, err)
 
 	c, err := newCustomClient(config, filepath.Join(dir, "telemetry"), server.URL)
diff --git a/test/integration/crcsuite/crcsuite.go b/test/integration/crcsuite/crcsuite.go
index d184aeb95..e2a10cda8 100644
--- a/test/integration/crcsuite/crcsuite.go
+++ b/test/integration/crcsuite/crcsuite.go
@@ -13,6 +13,7 @@ import (
 	"time"
 
 	"github.com/code-ready/crc/pkg/crc/cluster"
+	"github.com/code-ready/crc/pkg/crc/constants"
 	"github.com/cucumber/godog"
 	"github.com/cucumber/messages-go/v10"
 
@@ -25,7 +26,7 @@ var (
 	CRCExecutable  string
 	bundleEmbedded bool
 	bundleName     string
-	bundleURL      string
+	bundleLocation string
 	bundleVersion  string
 	pullSecretFile string
 )
@@ -89,30 +90,17 @@ func FeatureContext(s *godog.Suite) {
 			os.Exit(1)
 		}
 
-		if bundleURL == "embedded" {
+		if bundleLocation == "" {
 			fmt.Println("Expecting the bundle to be embedded in the CRC executable.")
 			bundleEmbedded = true
 			if bundleVersion == "" {
 				fmt.Println("User must specify --bundle-version if bundle is embedded")
 				os.Exit(1)
 			}
-			// assume default hypervisor
-			var hypervisor string
-			switch platform := runtime.GOOS; platform {
-			case "darwin":
-				hypervisor = "hyperkit"
-			case "linux":
-				hypervisor = "libvirt"
-			case "windows":
-				hypervisor = "hyperv"
-			default:
-				fmt.Printf("Unsupported OS: %s", platform)
-				os.Exit(1)
-			}
-			bundleName = fmt.Sprintf("crc_%s_%s.crcbundle", hypervisor, bundleVersion)
+			bundleName = constants.GetBundleFosOs(runtime.GOOS, bundleVersion)
 		} else {
 			bundleEmbedded = false
-			_, bundleName = filepath.Split(bundleURL)
+			_, bundleName = filepath.Split(bundleLocation)
 		}
 
 		if pullSecretFile == "" {
@@ -159,7 +147,7 @@ func FeatureContext(s *godog.Suite) {
 				}
 				// Obtain the bundle to current dir
 				fmt.Println("Obtaining bundle...")
-				bundle, err := DownloadBundle(bundleURL, ".")
+				bundle, err := DownloadBundle(bundleLocation, ".")
 				if err != nil {
 					fmt.Printf("Failed to obtain CRC bundle, %v\n", err)
 					os.Exit(1)
diff --git a/test/integration/crcsuite/prepare.go b/test/integration/crcsuite/prepare.go
index c8a8d688a..5cb7c9185 100644
--- a/test/integration/crcsuite/prepare.go
+++ b/test/integration/crcsuite/prepare.go
@@ -120,7 +120,7 @@ func CopyFilesToTestDir() error {
 
 func ParseFlags() {
 
-	flag.StringVar(&bundleURL, "bundle-location", "embedded", "Path to the bundle to be used in tests")
+	flag.StringVar(&bundleLocation, "bundle-location", "", "Path to the bundle to be used in tests")
 	flag.StringVar(&pullSecretFile, "pull-secret-file", "", "Path to the file containing pull secret")
 	flag.StringVar(&CRCExecutable, "crc-binary", "", "Path to the CRC executable to be tested")
 	flag.StringVar(&bundleVersion, "bundle-version", "", "Version of the bundle used in tests")
diff --git a/test/integration/features/basic.feature b/test/integration/features/basic.feature
index 8c2c9626d..7a1b4da65 100644
--- a/test/integration/features/basic.feature
+++ b/test/integration/features/basic.feature
@@ -84,6 +84,14 @@ Feature: Basic test
         Then stderr should contain "Checking if user is a member of the Hyper-V Administrators group"
         Then stderr should contain "Checking if the Hyper-V virtual switch exist"
 
+    @darwin @linux @windows
+    Scenario: Request start with monitoring stack
+        When setting config property "enable-cluster-monitoring" to value "true" succeeds
+        And setting config property "memory" to value "14000" succeeds
+        Then starting CRC with default bundle fails
+        And stderr should contain "Too little memory"
+        And setting config property "memory" to value "16000" succeeds
+
     @darwin @linux @windows
     Scenario: CRC start
         When starting CRC with default bundle succeeds
@@ -113,6 +121,16 @@ Feature: Basic test
         Then stdout should contain "To login as a regular user, run 'oc login -u developer -p developer"
         And stdout should contain "To login as an admin, run 'oc login -u kubeadmin -p "
 
+    @darwin @linux @windows
+    Scenario: Monitoring stack check
+        Given checking that CRC is running
+        When executing "eval $(crc oc-env)" succeeds
+        And login to the oc cluster succeeds
+        And executing "oc get pods -n openshift-monitoring" succeeds
+        Then stdout matches ".*cluster-monitoring-operator-\w+-\w+\ *2/2\ *Running.*"
+        And unsetting config property "enable-cluster-monitoring" succeeds
+        And unsetting config property "memory" succeeds
+
     @darwin @linux @windows
     Scenario: CRC forcible stop
         When executing "crc stop -f"