func()

in pkg/monitor/cluster/clusterwideproxystatus.go [34:264]


func (mon *Monitor) emitCWPStatus(ctx context.Context) error {
	proxyConfig, err := mon.configcli.ConfigV1().Proxies().Get(ctx, cluster, metav1.GetOptions{})
	if err != nil {
		mon.log.Errorf("Error in getting the cluster wide proxy: %v", err)
		return err
	}
	if proxyConfig.Spec.HTTPProxy == "" && proxyConfig.Spec.HTTPSProxy == "" && proxyConfig.Spec.NoProxy == "" {
		mon.emitGauge(cwp, 1, map[string]string{
			"status":  strconv.FormatBool(false),
			"Message": "CWP Not Enabled",
		})
	} else {
		// Create the noProxy map for efficient lookups
		no_proxy_list := strings.Split(proxyConfig.Status.NoProxy, ",")
		if proxyConfig.Status.NoProxy == "" {
			mon.emitGauge(cwp, 1, map[string]string{
				"status":  strconv.FormatBool(true),
				"Message": "CWP NOT Enabled Successfully. Check the network operator status or review the noProxy items ",
			})
			no_proxy_list = strings.Split(proxyConfig.Spec.NoProxy, ",")
		}
		noProxyMap := make(map[string]bool)
		var missing_no_proxy_list []string
		for _, proxy := range no_proxy_list {
			proxy = strings.TrimSpace(proxy)
			noProxyMap[proxy] = true
		}

		// Check mandatory no_proxy entries
		for _, mandatory_no_proxy := range strings.Split(mandatory_no_proxies, ",") {
			if !noProxyMap[mandatory_no_proxy] {
				missing_no_proxy_list = append(missing_no_proxy_list, mandatory_no_proxy)
			}
		}
		if !noProxyMap[AzureDNS] {
			dnsConfigcluster, err := mon.operatorcli.OperatorV1().DNSes().Get(ctx, "default", metav1.GetOptions{})
			if err != nil {
				mon.log.Errorf("Error in getting DNS configuration: %v", err)
				return err
			}
			if len(dnsConfigcluster.Spec.Servers) == 0 {
				missing_no_proxy_list = append(missing_no_proxy_list, AzureDNS)
			}
		}

		mastersubnetID, err := azure.ParseResourceID(mon.oc.Properties.MasterProfile.SubnetID)
		if err != nil {
			mon.log.Errorf("failed to parse the mastersubnetID: %v", err)
			return err
		}
		token, err := mon.env.FPNewClientCertificateCredential(mon.tenantID, nil)
		if err != nil {
			mon.log.Errorf("failed to obtain FP Client Credentials: %v", err)
			return err
		}

		// Create client factory
		clientFactory, err := armnetwork.NewClientFactory(mastersubnetID.SubscriptionID, token, nil)
		if err != nil {
			mon.log.Errorf("failed to create client: %v", err)
			return err
		}

		// Check master subnet
		masterVnetID, _, err := apisubnet.Split(mon.oc.Properties.MasterProfile.SubnetID)
		if err != nil {
			mon.log.Errorf("failed to get the masterVnetID: %v", err)
			return err
		}
		mastervnetId, err := azure.ParseResourceID(masterVnetID)
		if err != nil {
			mon.log.Errorf("failed to parse the masterVnetID: %v", err)
			return err
		}
		res, err := clientFactory.NewSubnetsClient().Get(ctx, mastersubnetID.ResourceGroup, mastervnetId.ResourceName, mastersubnetID.ResourceName, &armnetwork.SubnetsClientGetOptions{Expand: nil})
		if err != nil {
			mon.log.Errorf("failed to finish the NewSubnetsClient request: %v", err)
			return err
		}

		if res.Properties.AddressPrefix != nil {
			if !noProxyMap[*res.Properties.AddressPrefix] {
				missing_no_proxy_list = append(missing_no_proxy_list, *res.Properties.AddressPrefix)
			}
		}

		// Check worker profiles
		for _, workerProfile := range mon.oc.Properties.WorkerProfiles {
			workersubnetID, err := azure.ParseResourceID(workerProfile.SubnetID)
			if err != nil {
				mon.log.Errorf("failed to parse the workersubnetID: %v", err)
				return err
			}
			workerVnetID, _, err := apisubnet.Split(workerProfile.SubnetID)
			if err != nil {
				mon.log.Errorf("failed to feth the workerVnetID: %v", err)
				return err
			}
			workervnetId, err := azure.ParseResourceID(workerVnetID)
			if err != nil {
				mon.log.Errorf("failed to parse the workerVnetID: %v", err)
				return err
			}
			workerres, err := clientFactory.NewSubnetsClient().Get(ctx, workersubnetID.ResourceGroup, workervnetId.ResourceName, workersubnetID.ResourceName, &armnetwork.SubnetsClientGetOptions{Expand: nil})
			if err != nil {
				mon.log.Errorf("failed to finish the request: %v", err)
			}
			if workerres.Properties.AddressPrefix != nil {
				workermachinesCIDR := *workerres.Properties.AddressPrefix
				if !noProxyMap[workermachinesCIDR] {
					missing_no_proxy_list = append(missing_no_proxy_list, workermachinesCIDR)
				}
			}
		}

		// Network Configuration Check
		networkConfig, err := mon.configcli.ConfigV1().Networks().Get(ctx, cluster, metav1.GetOptions{})
		if err != nil {
			mon.log.Errorf("Error in getting network info: %v", err)
			return err
		}
		for _, network := range networkConfig.Spec.ClusterNetwork {
			if !noProxyMap[network.CIDR] {
				missing_no_proxy_list = append(missing_no_proxy_list, network.CIDR)
			}
		}
		for _, network := range networkConfig.Spec.ServiceNetwork {
			if !noProxyMap[network] {
				missing_no_proxy_list = append(missing_no_proxy_list, network)
			}
		}

		// Gateway Domains Check
		clusterdetails, err := mon.arocli.AroV1alpha1().Clusters().Get(ctx, arov1alpha1.SingletonClusterName, metav1.GetOptions{})
		if err != nil {
			mon.log.Errorf("Error in getting cluster information: %v", err)
			return err
		}
		for _, gatewayDomain := range clusterdetails.Spec.GatewayDomains {
			gatewayDomain = strings.ToLower(gatewayDomain)
			if !noProxyMap[gatewayDomain] {
				parts := strings.Split(gatewayDomain, ".")
				domainfound := false
				// Loop until there are at least 3 parts
				for len(parts) >= 3 {
					//  skipping the first part of the domain
					remainingParts := strings.Join(parts[1:], ".")
					// If remaining parts are found in the noProxyMap, stop checking further
					if noProxyMap[remainingParts] {
						domainfound = true
						break
					}
					// Otherwise, remove the first part and continue the check
					parts = parts[1:]
				}
				// If no valid domain was found, add the original domain to the missing list
				if !domainfound {
					missing_no_proxy_list = append(missing_no_proxy_list, gatewayDomain)
				}
			}
		}
		clusterDomain := clusterdetails.Spec.Domain
		clusterDomaincheck := noProxyMap[clusterDomain] || noProxyMap["."+clusterDomain]
		// As per our OpenShift and ARO documentation, we expect customers to add api.clusterdomain, api-int.clusterdomain, and .apps.clusterdomain.
		// However, for existing customers with CWP enabled, they have only included clusterDomain in their noProxy list,
		// and these clusters are functioning as expected.
		// Our SRE testing has also not identified any functionality issues with this configuration.
		// Therefore, we will make this check optional if the clusterDomain is already included in the list.
		// This check is not aligned with our documentation,
		// but we are implementing it this way for code optimization.
		if !clusterDomaincheck {
			if !(noProxyMap[".apps."+clusterDomain]) {
				missing_no_proxy_list = append(missing_no_proxy_list, clusterDomain)
			}

			// Infrastructure Configuration Check
			infraConfig, err := mon.configcli.ConfigV1().Infrastructures().Get(ctx, cluster, metav1.GetOptions{})
			if err != nil {
				mon.log.Errorf("Error in getting Infrasturcture info: %v", err)
				return err
			}

			// APIServerInternal URL Check
			apiServerIntURL, err := url.Parse(infraConfig.Status.APIServerInternalURL)
			if err != nil {
				mon.log.Errorf("Error in parsing APIServerProfile: %v", err)
				return err
			}
			apiServerIntdomain := strings.Split(apiServerIntURL.Host, ":")[0]
			if !(noProxyMap[apiServerIntdomain]) {
				missing_no_proxy_list = append(missing_no_proxy_list, apiServerIntdomain)
			}

			// APIServerProfile URL Check
			apiServerProfileURL, err := url.Parse(mon.oc.Properties.APIServerProfile.URL)
			if err != nil {
				mon.log.Errorf("Error in parsing APIServerProfile: %v", err)
				return err
			}
			apiServerProfiledomain := strings.Split(apiServerProfileURL.Host, ":")[0]
			if !(noProxyMap[apiServerProfiledomain]) {
				missing_no_proxy_list = append(missing_no_proxy_list, apiServerProfiledomain)
			}
		}

		if len(missing_no_proxy_list) > 0 {
			status := true
			message := "CWP enabled but missing  " + strings.Join(missing_no_proxy_list, ",") + " in the no_proxy list"
			mon.emitGauge(cwp, 1, map[string]string{
				"status":  strconv.FormatBool(status),
				"Message": message,
			})
			mon.log.Info(message)
			if mon.hourlyRun {
				mon.log.WithFields(logrus.Fields{
					"metric":  cwp,
					"status":  strconv.FormatBool(status),
					"Message": message,
				}).Print()
			}
		} else {
			mon.emitGauge(cwp, 1, map[string]string{
				"status":  strconv.FormatBool(false),
				"Message": "CWP enabled successfully",
			})
			mon.log.Infof("CWP enabled successfully")
		}
	}

	return nil
}