in pkg/install/operator.go [91:343]
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 := range len(d.Spec.Template.Spec.Containers) {
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 := range len(d.Spec.Template.Spec.Containers) {
for _, envVar := range envVars {
envvar.SetVar(&d.Spec.Template.Spec.Containers[i].Env, envVar)
}
}
}
}
}
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", "")
}
}
// Configure subject on ClusterRoleBindings
if crb, ok := o.(*rbacv1.ClusterRoleBinding); ok {
if strings.HasPrefix(crb.Name, "camel-k-operator") {
crb.ObjectMeta.Name = fmt.Sprintf("%s-%s", crb.ObjectMeta.Name, cfg.Namespace)
bound := false
for i, subject := range crb.Subjects {
if subject.Name == "camel-k-operator" {
if subject.Namespace == cfg.Namespace {
bound = true
break
} else if subject.Namespace == "" || subject.Namespace == "placeholder" {
crb.Subjects[i].Namespace = cfg.Namespace
bound = true
break
}
}
}
if !bound {
crb.Subjects = append(crb.Subjects, rbacv1.Subject{
Kind: "ServiceAccount",
Namespace: cfg.Namespace,
Name: "camel-k-operator",
})
}
}
}
}
if isOpenShift {
// Remove Ingress permissions as it's not needed on OpenShift
// This should ideally be removed from the common RBAC manifest.
RemoveIngressRoleCustomizer(o)
if d, ok := o.(*appsv1.Deployment); ok {
securityContext, _ := openshift.GetOpenshiftSecurityContextRestricted(ctx, c, cfg.Namespace)
if securityContext != nil {
d.Spec.Template.Spec.Containers[0].SecurityContext = securityContext
} else {
d.Spec.Template.Spec.Containers[0].SecurityContext = kubernetes.DefaultOperatorSecurityContext()
}
}
}
return o
}
// Install Kubernetes RBAC resources (roles and bindings)
if err := installKubernetesRoles(ctx, c, cfg.Namespace, customizer, collection, force, cfg.Global); 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, cfg.Global); err != nil {
return err
}
if err := installClusterRoleBinding(ctx, c, collection, cfg.Namespace, "camel-k-operator-console-openshift", "/config/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
}
if err = installEvents(ctx, c, cfg.Namespace, customizer, collection, force, cfg.Global); 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 = installKnativeBindings(ctx, c, cfg.Namespace, customizer, collection, force, cfg.Global); err != nil {
if k8serrors.IsAlreadyExists(err) {
return err
}
fmt.Fprintln(cmd.ErrOrStderr(), "Warning: the operator will not be able to create Knative resources. Try installing as cluster-admin.")
}
if err = installKedaBindings(ctx, c, cfg.Namespace, customizer, collection, force, cfg.Global); 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, cfg.Global); 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, cfg.Global); 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, cfg.Global); 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", "/config/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, "/config/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
}