func OperatorOrCollect()

in pkg/install/operator.go [91:353]


func OperatorOrCollect(ctx context.Context, cmd *cobra.Command, c client.Client, cfg OperatorConfiguration, collection *kubernetes.Collection, force bool) error {
	isOpenShift, err := isOpenShift(c, cfg.ClusterType)
	if err != nil {
		return err
	}

	customizer := func(o ctrl.Object) ctrl.Object {
		if cfg.CustomImage != "" {
			if d, ok := o.(*appsv1.Deployment); ok {
				if d.Labels["camel.apache.org/component"] == "operator" {
					d.Spec.Template.Spec.Containers[0].Image = cfg.CustomImage
				}
			}
		}

		if cfg.CustomImagePullPolicy != "" {
			if d, ok := o.(*appsv1.Deployment); ok {
				if d.Labels["camel.apache.org/component"] == "operator" {
					d.Spec.Template.Spec.Containers[0].ImagePullPolicy = corev1.PullPolicy(cfg.CustomImagePullPolicy)
				}
			}
		}

		if cfg.Tolerations != nil {
			if d, ok := o.(*appsv1.Deployment); ok {
				if d.Labels["camel.apache.org/component"] == "operator" {
					tolerations, err := kubernetes.NewTolerations(cfg.Tolerations)
					if err != nil {
						fmt.Fprintln(cmd.ErrOrStderr(), "Warning: could not parse the configured tolerations!")
					}
					d.Spec.Template.Spec.Tolerations = tolerations
				}
			}
		}

		if cfg.ResourcesRequirements != nil {
			if d, ok := o.(*appsv1.Deployment); ok {
				if d.Labels["camel.apache.org/component"] == "operator" {
					resourceReq, err := kubernetes.NewResourceRequirements(cfg.ResourcesRequirements)
					if err != nil {
						fmt.Fprintln(cmd.ErrOrStderr(), "Warning: could not parse the configured resources requests!")
					}
					for i := 0; i < len(d.Spec.Template.Spec.Containers); i++ {
						d.Spec.Template.Spec.Containers[i].Resources = resourceReq
					}
				}
			}
		}

		if cfg.EnvVars != nil {
			if d, ok := o.(*appsv1.Deployment); ok {
				if d.Labels["camel.apache.org/component"] == "operator" {
					envVars, _, _, err := env.ParseEnv(cfg.EnvVars, nil)
					if err != nil {
						fmt.Fprintln(cmd.ErrOrStderr(), "Warning: could not parse environment variables!")
					}
					for i := 0; i < len(d.Spec.Template.Spec.Containers); i++ {
						d.Spec.Template.Spec.Containers[i].Env = append(d.Spec.Template.Spec.Containers[i].Env, envVars...)
					}
				}
			}
		}

		if cfg.NodeSelectors != nil {
			if d, ok := o.(*appsv1.Deployment); ok {
				if d.Labels["camel.apache.org/component"] == "operator" {
					nodeSelector, err := kubernetes.NewNodeSelectors(cfg.NodeSelectors)
					if err != nil {
						fmt.Fprintln(cmd.ErrOrStderr(), "Warning: could not parse the configured node selectors!")
					}
					d.Spec.Template.Spec.NodeSelector = nodeSelector
				}
			}
		}

		if d, ok := o.(*appsv1.Deployment); ok {
			if d.Labels["camel.apache.org/component"] == "operator" {
				// Metrics endpoint port
				d.Spec.Template.Spec.Containers[0].Args = append(d.Spec.Template.Spec.Containers[0].Args,
					fmt.Sprintf("--monitoring-port=%d", cfg.Monitoring.Port))
				d.Spec.Template.Spec.Containers[0].Ports[0].ContainerPort = cfg.Monitoring.Port
				// Health endpoint port
				d.Spec.Template.Spec.Containers[0].Args = append(d.Spec.Template.Spec.Containers[0].Args,
					fmt.Sprintf("--health-port=%d", cfg.Health.Port))
				d.Spec.Template.Spec.Containers[0].LivenessProbe.HTTPGet.Port = intstr.FromInt(int(cfg.Health.Port))
			}
		}
		if cfg.Debugging.Enabled {
			if d, ok := o.(*appsv1.Deployment); ok {
				if d.Labels["camel.apache.org/component"] == "operator" {
					d.Spec.Template.Spec.Containers[0].Command = []string{"dlv",
						fmt.Sprintf("--listen=:%d", cfg.Debugging.Port), "--headless=true", "--api-version=2",
						"exec", cfg.Debugging.Path, "--", "operator", "--leader-election=false"}
					d.Spec.Template.Spec.Containers[0].Ports = append(d.Spec.Template.Spec.Containers[0].Ports, corev1.ContainerPort{
						Name:          "delve",
						ContainerPort: cfg.Debugging.Port,
					})
					// In debug mode, the Liveness probe must be removed otherwise K8s will consider the pod as dead
					// while debugging
					d.Spec.Template.Spec.Containers[0].LivenessProbe = nil
				}
			}
		}

		if cfg.Global {
			if d, ok := o.(*appsv1.Deployment); ok {
				if d.Labels["camel.apache.org/component"] == "operator" {
					// Make the operator watch all namespaces
					envvar.SetVal(&d.Spec.Template.Spec.Containers[0].Env, "WATCH_NAMESPACE", "")
				}
			}

			// Turn Role & RoleBinding into their equivalent cluster types
			if r, ok := o.(*rbacv1.Role); ok {
				if strings.HasPrefix(r.Name, "camel-k-operator") {
					o = &rbacv1.ClusterRole{
						ObjectMeta: metav1.ObjectMeta{
							Namespace: cfg.Namespace,
							Name:      r.Name,
							Labels: map[string]string{
								"app": "camel-k",
							},
						},
						Rules: r.Rules,
					}
				}
			}

			if rb, ok := o.(*rbacv1.RoleBinding); ok {
				if strings.HasPrefix(rb.Name, "camel-k-operator") {
					rb.Subjects[0].Namespace = cfg.Namespace

					o = &rbacv1.ClusterRoleBinding{
						ObjectMeta: metav1.ObjectMeta{
							Namespace: cfg.Namespace,
							Name:      fmt.Sprintf("%s-%s", rb.Name, cfg.Namespace),
							Labels: map[string]string{
								"app": "camel-k",
							},
						},
						Subjects: rb.Subjects,
						RoleRef: rbacv1.RoleRef{
							APIGroup: rb.RoleRef.APIGroup,
							Kind:     "ClusterRole",
							Name:     rb.RoleRef.Name,
						},
					}
				}
			}
		}

		if isOpenShift {
			// Remove Ingress permissions as it's not needed on OpenShift
			// This should ideally be removed from the common RBAC manifest.
			RemoveIngressRoleCustomizer(o)
		}

		return o
	}

	// Install Kubernetes RBAC resources (roles and bindings)
	if err := installKubernetesRoles(ctx, c, cfg.Namespace, customizer, collection, force); err != nil {
		return err
	}

	// Install OpenShift RBAC resources if needed (roles and bindings)
	if isOpenShift {
		if err := installOpenShiftRoles(ctx, c, cfg.Namespace, customizer, collection, force); err != nil {
			return err
		}
		if err := installClusterRoleBinding(ctx, c, collection, cfg.Namespace, "camel-k-operator-console-openshift", "/rbac/openshift/operator-cluster-role-console-binding-openshift.yaml"); err != nil {
			if k8serrors.IsForbidden(err) {
				fmt.Fprintln(cmd.ErrOrStderr(), "Warning: the operator will not be able to manage ConsoleCLIDownload resources. Try installing the operator as cluster-admin.")
			} else {
				return err
			}
		}
	}

	// Deploy the operator
	if err := installOperator(ctx, c, cfg.Namespace, customizer, collection, force); err != nil {
		return err
	}

	// Additionally, install Knative resources (roles and bindings)
	isKnative, err := knative.IsInstalled(c)
	if err != nil {
		return err
	}
	if isKnative {
		if err := installKnative(ctx, c, cfg.Namespace, customizer, collection, force); err != nil {
			return err
		}
		if err := installClusterRoleBinding(ctx, c, collection, cfg.Namespace, "camel-k-operator-bind-addressable-resolver", "/rbac/operator-cluster-role-binding-addressable-resolver.yaml"); err != nil {
			if k8serrors.IsForbidden(err) {
				fmt.Fprintln(cmd.ErrOrStderr(), "Warning: the operator will not be able to bind Knative addressable-resolver ClusterRole. Try installing the operator as cluster-admin.")
			} else {
				return err
			}
		}
	}

	if err = installEvents(ctx, c, cfg.Namespace, customizer, collection, force); err != nil {
		if k8serrors.IsAlreadyExists(err) {
			return err
		}
		fmt.Fprintln(cmd.ErrOrStderr(), "Warning: the operator will not be able to publish Kubernetes events. Try installing as cluster-admin to allow it to generate events.")
	}

	if err = installKedaBindings(ctx, c, cfg.Namespace, customizer, collection, force); err != nil {
		if k8serrors.IsAlreadyExists(err) {
			return err
		}
		fmt.Fprintln(cmd.ErrOrStderr(), "Warning: the operator will not be able to create KEDA resources. Try installing as cluster-admin.")
	}

	if err = installPodMonitors(ctx, c, cfg.Namespace, customizer, collection, force); err != nil {
		if k8serrors.IsAlreadyExists(err) {
			return err
		}
		fmt.Fprintln(cmd.ErrOrStderr(), "Warning: the operator will not be able to create PodMonitor resources. Try installing as cluster-admin.")
	}

	if err := installStrimziBindings(ctx, c, cfg.Namespace, customizer, collection, force); err != nil {
		if k8serrors.IsAlreadyExists(err) {
			return err
		}
		fmt.Fprintln(cmd.ErrOrStderr(), "Warning: the operator will not be able to lookup strimzi kafka resources. Try installing as cluster-admin to allow the lookup of strimzi kafka resources.")
	}

	if err = installLeaseBindings(ctx, c, cfg.Namespace, customizer, collection, force); err != nil {
		if k8serrors.IsAlreadyExists(err) {
			return err
		}
		fmt.Fprintln(cmd.ErrOrStderr(), "Warning: the operator will not be able to create Leases. Try installing as cluster-admin to allow management of Lease resources.")
	}

	if err = installClusterRoleBinding(ctx, c, collection, cfg.Namespace, "camel-k-operator-custom-resource-definitions", "/rbac/operator-cluster-role-binding-custom-resource-definitions.yaml"); err != nil {
		fmt.Fprintln(cmd.ErrOrStderr(), "Warning: the operator will not be able to get CustomResourceDefinitions resources and the service-binding trait will fail if used. Try installing the operator as cluster-admin.")
	}

	if err = installNamespacedRoleBinding(ctx, c, collection, cfg.Namespace, "/rbac/operator-role-binding-local-registry.yaml"); err != nil {
		if !k8serrors.IsAlreadyExists(err) {
			fmt.Fprintf(cmd.ErrOrStderr(), "Warning: the operator may not be able to detect a local image registry (%s)\n", err.Error())
		}
	}

	if cfg.Monitoring.Enabled {
		if err := installMonitoringResources(ctx, c, cfg.Namespace, customizer, collection, force); err != nil {
			switch {
			case k8serrors.IsForbidden(err):
				fmt.Fprintln(cmd.ErrOrStderr(), "Warning: the creation of monitoring resources is not allowed. Try installing as cluster-admin to allow the creation of monitoring resources.")
				// TU to check ?
			case meta.IsNoMatchError(errors.Unwrap(err)):
				fmt.Fprintln(cmd.ErrOrStderr(), "Warning: the creation of the monitoring resources failed: ", err)
			default:
				return err
			}
		}
	}

	return nil
}