github.com/argoproj-labs/argocd-operator@v0.10.0/controllers/argocd/notifications.go (about) 1 package argocd 2 3 import ( 4 "context" 5 "fmt" 6 "reflect" 7 "time" 8 9 monitoringv1 "github.com/coreos/prometheus-operator/pkg/apis/monitoring/v1" 10 appsv1 "k8s.io/api/apps/v1" 11 corev1 "k8s.io/api/core/v1" 12 rbacv1 "k8s.io/api/rbac/v1" 13 "k8s.io/apimachinery/pkg/api/errors" 14 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 15 v1 "k8s.io/apimachinery/pkg/apis/meta/v1" 16 "k8s.io/apimachinery/pkg/types" 17 "k8s.io/apimachinery/pkg/util/intstr" 18 "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" 19 20 "github.com/argoproj-labs/argocd-operator/api/v1alpha1" 21 argoproj "github.com/argoproj-labs/argocd-operator/api/v1beta1" 22 "github.com/argoproj-labs/argocd-operator/common" 23 "github.com/argoproj-labs/argocd-operator/controllers/argoutil" 24 ) 25 26 const ( 27 DefaultNotificationsConfigurationInstanceName = "default-notifications-configuration" 28 ) 29 30 func (r *ReconcileArgoCD) reconcileNotificationsController(cr *argoproj.ArgoCD) error { 31 32 log.Info("reconciling notifications serviceaccount") 33 sa, err := r.reconcileNotificationsServiceAccount(cr) 34 if err != nil { 35 return err 36 } 37 38 log.Info("reconciling notifications role") 39 role, err := r.reconcileNotificationsRole(cr) 40 if err != nil { 41 return err 42 } 43 44 log.Info("reconciling notifications role binding") 45 if err := r.reconcileNotificationsRoleBinding(cr, role, sa); err != nil { 46 return err 47 } 48 49 log.Info("reconciling NotificationsConfiguration") 50 if err := r.reconcileNotificationsConfigurationCR(cr); err != nil { 51 return err 52 } 53 54 log.Info("reconciling notifications secret") 55 if err := r.reconcileNotificationsSecret(cr); err != nil { 56 return err 57 } 58 59 log.Info("reconciling notifications deployment") 60 if err := r.reconcileNotificationsDeployment(cr, sa); err != nil { 61 return err 62 } 63 64 log.Info("reconciling notifications metrics service") 65 if err := r.reconcileNotificationsMetricsService(cr); err != nil { 66 return err 67 } 68 69 if prometheusAPIFound { 70 log.Info("reconciling notifications metrics service monitor") 71 if err := r.reconcileNotificationsServiceMonitor(cr); err != nil { 72 return err 73 } 74 } 75 76 return nil 77 } 78 79 func (r *ReconcileArgoCD) reconcileNotificationsConfigurationCR(cr *argoproj.ArgoCD) error { 80 81 defaultNotificationsConfigurationCR := &v1alpha1.NotificationsConfiguration{ 82 ObjectMeta: metav1.ObjectMeta{ 83 Name: DefaultNotificationsConfigurationInstanceName, 84 Namespace: cr.Namespace, 85 }, 86 Spec: v1alpha1.NotificationsConfigurationSpec{ 87 Triggers: getDefaultNotificationsTriggers(), 88 Templates: getDefaultNotificationsTemplates(), 89 }, 90 } 91 92 if !cr.Spec.Notifications.Enabled { 93 log.Info("Deleting NotificationsConfiguration as notifications is disabled") 94 return r.Client.Delete(context.TODO(), defaultNotificationsConfigurationCR) 95 } 96 97 if err := argoutil.FetchObject(r.Client, cr.Namespace, DefaultNotificationsConfigurationInstanceName, 98 defaultNotificationsConfigurationCR); err != nil { 99 100 if !errors.IsNotFound(err) { 101 return fmt.Errorf("failed to get the NotificationsConfiguration associated with %s : %s", 102 cr.Name, err) 103 } 104 105 // NotificationsConfiguration doesn't exist and shouldn't, nothing to do here 106 if !cr.Spec.Notifications.Enabled { 107 return nil 108 } 109 110 err := r.Client.Create(context.TODO(), defaultNotificationsConfigurationCR) 111 if err != nil { 112 return err 113 } 114 } 115 116 return nil 117 } 118 119 // The code to create/delete notifications resources is written within the reconciliation logic itself. However, these functions must be called 120 // in the right order depending on whether resources are getting created or deleted. During creation we must create the role and sa first. 121 // RoleBinding and deployment are dependent on these resouces. During deletion the order is reversed. 122 // Deployment and RoleBinding must be deleted before the role and sa. deleteNotificationsResources will only be called during 123 // delete events, so we don't need to worry about duplicate, recurring reconciliation calls 124 func (r *ReconcileArgoCD) deleteNotificationsResources(cr *argoproj.ArgoCD) error { 125 126 sa := &corev1.ServiceAccount{} 127 role := &rbacv1.Role{} 128 129 if err := argoutil.FetchObject(r.Client, cr.Namespace, fmt.Sprintf("%s-%s", cr.Name, common.ArgoCDNotificationsControllerComponent), sa); err != nil { 130 if !errors.IsNotFound(err) { 131 return err 132 } 133 } 134 if err := argoutil.FetchObject(r.Client, cr.Namespace, fmt.Sprintf("%s-%s", cr.Name, common.ArgoCDNotificationsControllerComponent), role); err != nil { 135 if !errors.IsNotFound(err) { 136 return err 137 } 138 } 139 140 log.Info("reconciling notifications deployment") 141 if err := r.reconcileNotificationsDeployment(cr, sa); err != nil { 142 return err 143 } 144 145 log.Info("reconciling notifications service") 146 if err := r.reconcileNotificationsMetricsService(cr); err != nil { 147 return err 148 } 149 150 log.Info("reconciling notifications service monitor") 151 if err := r.reconcileNotificationsServiceMonitor(cr); err != nil { 152 return err 153 } 154 155 log.Info("reconciling notifications secret") 156 if err := r.reconcileNotificationsSecret(cr); err != nil { 157 return err 158 } 159 160 log.Info("reconciling notifications role binding") 161 if err := r.reconcileNotificationsRoleBinding(cr, role, sa); err != nil { 162 return err 163 } 164 165 log.Info("reconciling notifications role") 166 _, err := r.reconcileNotificationsRole(cr) 167 if err != nil { 168 return err 169 } 170 171 log.Info("reconciling notifications serviceaccount") 172 _, err = r.reconcileNotificationsServiceAccount(cr) 173 if err != nil { 174 return err 175 } 176 177 log.Info("reconciling notificationsconfiguration") 178 err = r.reconcileNotificationsConfigurationCR(cr) 179 if err != nil { 180 return err 181 } 182 183 return nil 184 } 185 186 func (r *ReconcileArgoCD) reconcileNotificationsServiceAccount(cr *argoproj.ArgoCD) (*corev1.ServiceAccount, error) { 187 188 sa := newServiceAccountWithName(common.ArgoCDNotificationsControllerComponent, cr) 189 190 if err := argoutil.FetchObject(r.Client, cr.Namespace, sa.Name, sa); err != nil { 191 if !errors.IsNotFound(err) { 192 return nil, fmt.Errorf("failed to get the serviceAccount associated with %s : %s", sa.Name, err) 193 } 194 195 // SA doesn't exist and shouldn't, nothing to do here 196 if !cr.Spec.Notifications.Enabled { 197 return nil, nil 198 } 199 200 // SA doesn't exist but should, so it should be created 201 if err := controllerutil.SetControllerReference(cr, sa, r.Scheme); err != nil { 202 return nil, err 203 } 204 205 log.Info(fmt.Sprintf("Creating serviceaccount %s", sa.Name)) 206 err := r.Client.Create(context.TODO(), sa) 207 if err != nil { 208 return nil, err 209 } 210 } 211 212 // SA exists but shouldn't, so it should be deleted 213 if !cr.Spec.Notifications.Enabled { 214 log.Info(fmt.Sprintf("Deleting serviceaccount %s as notifications is disabled", sa.Name)) 215 return nil, r.Client.Delete(context.TODO(), sa) 216 } 217 218 return sa, nil 219 } 220 221 func (r *ReconcileArgoCD) reconcileNotificationsRole(cr *argoproj.ArgoCD) (*rbacv1.Role, error) { 222 223 policyRules := policyRuleForNotificationsController() 224 desiredRole := newRole(common.ArgoCDNotificationsControllerComponent, policyRules, cr) 225 226 existingRole := &rbacv1.Role{} 227 if err := argoutil.FetchObject(r.Client, cr.Namespace, desiredRole.Name, existingRole); err != nil { 228 if !errors.IsNotFound(err) { 229 return nil, fmt.Errorf("failed to get the role associated with %s : %s", desiredRole.Name, err) 230 } 231 232 // role does not exist and shouldn't, nothing to do here 233 if !cr.Spec.Notifications.Enabled { 234 return nil, nil 235 } 236 237 // role does not exist but should, so it should be created 238 if err := controllerutil.SetControllerReference(cr, desiredRole, r.Scheme); err != nil { 239 return nil, err 240 } 241 242 log.Info(fmt.Sprintf("Creating role %s", desiredRole.Name)) 243 err := r.Client.Create(context.TODO(), desiredRole) 244 if err != nil { 245 return nil, err 246 } 247 return desiredRole, nil 248 } 249 250 // role exists but shouldn't, so it should be deleted 251 if !cr.Spec.Notifications.Enabled { 252 log.Info(fmt.Sprintf("Deleting role %s as notifications is disabled", existingRole.Name)) 253 return nil, r.Client.Delete(context.TODO(), existingRole) 254 } 255 256 // role exists and should. Reconcile role if changed 257 if !reflect.DeepEqual(existingRole.Rules, desiredRole.Rules) { 258 existingRole.Rules = desiredRole.Rules 259 if err := controllerutil.SetControllerReference(cr, existingRole, r.Scheme); err != nil { 260 return nil, err 261 } 262 return existingRole, r.Client.Update(context.TODO(), existingRole) 263 } 264 265 return desiredRole, nil 266 } 267 268 func (r *ReconcileArgoCD) reconcileNotificationsRoleBinding(cr *argoproj.ArgoCD, role *rbacv1.Role, sa *corev1.ServiceAccount) error { 269 270 desiredRoleBinding := newRoleBindingWithname(common.ArgoCDNotificationsControllerComponent, cr) 271 desiredRoleBinding.RoleRef = rbacv1.RoleRef{ 272 APIGroup: rbacv1.GroupName, 273 Kind: "Role", 274 Name: role.Name, 275 } 276 277 desiredRoleBinding.Subjects = []rbacv1.Subject{ 278 { 279 Kind: rbacv1.ServiceAccountKind, 280 Name: sa.Name, 281 Namespace: sa.Namespace, 282 }, 283 } 284 285 // fetch existing rolebinding by name 286 existingRoleBinding := &rbacv1.RoleBinding{} 287 if err := r.Client.Get(context.TODO(), types.NamespacedName{Name: desiredRoleBinding.Name, Namespace: cr.Namespace}, existingRoleBinding); err != nil { 288 if !errors.IsNotFound(err) { 289 return fmt.Errorf("failed to get the rolebinding associated with %s : %s", desiredRoleBinding.Name, err) 290 } 291 292 // roleBinding does not exist and shouldn't, nothing to do here 293 if !cr.Spec.Notifications.Enabled { 294 return nil 295 } 296 297 // roleBinding does not exist but should, so it should be created 298 if err := controllerutil.SetControllerReference(cr, desiredRoleBinding, r.Scheme); err != nil { 299 return err 300 } 301 302 log.Info(fmt.Sprintf("Creating roleBinding %s", desiredRoleBinding.Name)) 303 return r.Client.Create(context.TODO(), desiredRoleBinding) 304 } 305 306 // roleBinding exists but shouldn't, so it should be deleted 307 if !cr.Spec.Notifications.Enabled { 308 log.Info(fmt.Sprintf("Deleting roleBinding %s as notifications is disabled", existingRoleBinding.Name)) 309 return r.Client.Delete(context.TODO(), existingRoleBinding) 310 } 311 312 // roleBinding exists and should. Reconcile roleBinding if changed 313 if !reflect.DeepEqual(existingRoleBinding.RoleRef, desiredRoleBinding.RoleRef) { 314 // if the RoleRef changes, delete the existing role binding and create a new one 315 if err := r.Client.Delete(context.TODO(), existingRoleBinding); err != nil { 316 return err 317 } 318 } else if !reflect.DeepEqual(existingRoleBinding.Subjects, desiredRoleBinding.Subjects) { 319 existingRoleBinding.Subjects = desiredRoleBinding.Subjects 320 if err := controllerutil.SetControllerReference(cr, existingRoleBinding, r.Scheme); err != nil { 321 return err 322 } 323 return r.Client.Update(context.TODO(), existingRoleBinding) 324 } 325 326 return nil 327 } 328 329 func (r *ReconcileArgoCD) reconcileNotificationsDeployment(cr *argoproj.ArgoCD, sa *corev1.ServiceAccount) error { 330 331 desiredDeployment := newDeploymentWithSuffix("notifications-controller", "controller", cr) 332 333 desiredDeployment.Spec.Strategy = appsv1.DeploymentStrategy{ 334 Type: appsv1.RecreateDeploymentStrategyType, 335 } 336 337 if replicas := getArgoCDNotificationsControllerReplicas(cr); replicas != nil { 338 desiredDeployment.Spec.Replicas = replicas 339 } 340 341 notificationEnv := cr.Spec.Notifications.Env 342 // Let user specify their own environment first 343 notificationEnv = argoutil.EnvMerge(notificationEnv, proxyEnvVars(), false) 344 345 podSpec := &desiredDeployment.Spec.Template.Spec 346 podSpec.SecurityContext = &corev1.PodSecurityContext{ 347 RunAsNonRoot: boolPtr(true), 348 } 349 AddSeccompProfileForOpenShift(r.Client, podSpec) 350 podSpec.ServiceAccountName = sa.ObjectMeta.Name 351 podSpec.Volumes = []corev1.Volume{ 352 { 353 Name: "tls-certs", 354 VolumeSource: corev1.VolumeSource{ 355 ConfigMap: &corev1.ConfigMapVolumeSource{ 356 LocalObjectReference: corev1.LocalObjectReference{ 357 Name: common.ArgoCDTLSCertsConfigMapName, 358 }, 359 }, 360 }, 361 }, 362 { 363 Name: "argocd-repo-server-tls", 364 VolumeSource: corev1.VolumeSource{ 365 Secret: &corev1.SecretVolumeSource{ 366 SecretName: common.ArgoCDRepoServerTLSSecretName, 367 Optional: boolPtr(true), 368 }, 369 }, 370 }, 371 } 372 373 podSpec.Containers = []corev1.Container{{ 374 Command: getNotificationsCommand(cr), 375 Image: getArgoContainerImage(cr), 376 ImagePullPolicy: corev1.PullAlways, 377 Name: common.ArgoCDNotificationsControllerComponent, 378 Env: notificationEnv, 379 Resources: getNotificationsResources(cr), 380 LivenessProbe: &corev1.Probe{ 381 ProbeHandler: corev1.ProbeHandler{ 382 TCPSocket: &corev1.TCPSocketAction{ 383 Port: intstr.IntOrString{ 384 IntVal: int32(9001), 385 }, 386 }, 387 }, 388 }, 389 SecurityContext: &corev1.SecurityContext{ 390 AllowPrivilegeEscalation: boolPtr(false), 391 Capabilities: &corev1.Capabilities{ 392 Drop: []corev1.Capability{ 393 "ALL", 394 }, 395 }, 396 }, 397 VolumeMounts: []corev1.VolumeMount{ 398 { 399 Name: "tls-certs", 400 MountPath: "/app/config/tls", 401 }, 402 { 403 Name: "argocd-repo-server-tls", 404 MountPath: "/app/config/reposerver/tls", 405 }, 406 }, 407 WorkingDir: "/app", 408 }} 409 410 // fetch existing deployment by name 411 deploymentChanged := false 412 existingDeployment := &appsv1.Deployment{} 413 if err := r.Client.Get(context.TODO(), types.NamespacedName{Name: desiredDeployment.Name, Namespace: cr.Namespace}, existingDeployment); err != nil { 414 if !errors.IsNotFound(err) { 415 return fmt.Errorf("failed to get the deployment associated with %s : %s", existingDeployment.Name, err) 416 } 417 418 // deployment does not exist and shouldn't, nothing to do here 419 if !cr.Spec.Notifications.Enabled { 420 return nil 421 } 422 423 // deployment does not exist but should, so it should be created 424 if err := controllerutil.SetControllerReference(cr, desiredDeployment, r.Scheme); err != nil { 425 return err 426 } 427 428 log.Info(fmt.Sprintf("Creating deployment %s", desiredDeployment.Name)) 429 return r.Client.Create(context.TODO(), desiredDeployment) 430 } 431 432 // deployment exists but shouldn't, so it should be deleted 433 if !cr.Spec.Notifications.Enabled { 434 log.Info(fmt.Sprintf("Deleting deployment %s as notifications is disabled", existingDeployment.Name)) 435 return r.Client.Delete(context.TODO(), existingDeployment) 436 } 437 438 // deployment exists and should. Reconcile deployment if changed 439 updateNodePlacement(existingDeployment, desiredDeployment, &deploymentChanged) 440 441 if existingDeployment.Spec.Template.Spec.Containers[0].Image != desiredDeployment.Spec.Template.Spec.Containers[0].Image { 442 existingDeployment.Spec.Template.Spec.Containers[0].Image = desiredDeployment.Spec.Template.Spec.Containers[0].Image 443 existingDeployment.Spec.Template.ObjectMeta.Labels["image.upgraded"] = time.Now().UTC().Format("01022006-150406-MST") 444 deploymentChanged = true 445 } 446 447 if !reflect.DeepEqual(existingDeployment.Spec.Template.Spec.Containers[0].Command, desiredDeployment.Spec.Template.Spec.Containers[0].Command) { 448 existingDeployment.Spec.Template.Spec.Containers[0].Command = desiredDeployment.Spec.Template.Spec.Containers[0].Command 449 deploymentChanged = true 450 } 451 452 if !reflect.DeepEqual(existingDeployment.Spec.Template.Spec.Containers[0].Env, 453 desiredDeployment.Spec.Template.Spec.Containers[0].Env) { 454 existingDeployment.Spec.Template.Spec.Containers[0].Env = desiredDeployment.Spec.Template.Spec.Containers[0].Env 455 deploymentChanged = true 456 } 457 458 if !reflect.DeepEqual(existingDeployment.Spec.Template.Spec.Volumes, desiredDeployment.Spec.Template.Spec.Volumes) { 459 existingDeployment.Spec.Template.Spec.Volumes = desiredDeployment.Spec.Template.Spec.Volumes 460 deploymentChanged = true 461 } 462 463 if !reflect.DeepEqual(existingDeployment.Spec.Replicas, desiredDeployment.Spec.Replicas) { 464 existingDeployment.Spec.Replicas = desiredDeployment.Spec.Replicas 465 deploymentChanged = true 466 } 467 468 if !reflect.DeepEqual(existingDeployment.Spec.Template.Spec.Containers[0].VolumeMounts, desiredDeployment.Spec.Template.Spec.Containers[0].VolumeMounts) { 469 existingDeployment.Spec.Template.Spec.Containers[0].VolumeMounts = desiredDeployment.Spec.Template.Spec.Containers[0].VolumeMounts 470 deploymentChanged = true 471 } 472 473 if !reflect.DeepEqual(existingDeployment.Spec.Template.Spec.Containers[0].Resources, desiredDeployment.Spec.Template.Spec.Containers[0].Resources) { 474 existingDeployment.Spec.Template.Spec.Containers[0].Resources = desiredDeployment.Spec.Template.Spec.Containers[0].Resources 475 deploymentChanged = true 476 } 477 478 if !reflect.DeepEqual(existingDeployment.Spec.Template.Spec.ServiceAccountName, desiredDeployment.Spec.Template.Spec.ServiceAccountName) { 479 existingDeployment.Spec.Template.Spec.ServiceAccountName = desiredDeployment.Spec.Template.Spec.ServiceAccountName 480 deploymentChanged = true 481 } 482 483 if !reflect.DeepEqual(existingDeployment.Labels, desiredDeployment.Labels) { 484 existingDeployment.Labels = desiredDeployment.Labels 485 deploymentChanged = true 486 } 487 488 if !reflect.DeepEqual(existingDeployment.Spec.Template.Labels, desiredDeployment.Spec.Template.Labels) { 489 existingDeployment.Spec.Template.Labels = desiredDeployment.Spec.Template.Labels 490 deploymentChanged = true 491 } 492 493 if !reflect.DeepEqual(existingDeployment.Spec.Selector, desiredDeployment.Spec.Selector) { 494 existingDeployment.Spec.Selector = desiredDeployment.Spec.Selector 495 deploymentChanged = true 496 } 497 498 if deploymentChanged { 499 return r.Client.Update(context.TODO(), existingDeployment) 500 } 501 502 return nil 503 504 } 505 506 // reconcileNotificationsService will ensure that the Service for the Notifications controller metrics is present. 507 func (r *ReconcileArgoCD) reconcileNotificationsMetricsService(cr *argoproj.ArgoCD) error { 508 509 var component = "notifications-controller" 510 var suffix = "notifications-controller-metrics" 511 512 svc := newServiceWithSuffix(suffix, component, cr) 513 if argoutil.IsObjectFound(r.Client, cr.Namespace, svc.Name, svc) { 514 // Service found, do nothing 515 return nil 516 } 517 518 svc.Spec.Selector = map[string]string{ 519 common.ArgoCDKeyName: nameWithSuffix(component, cr), 520 } 521 522 svc.Spec.Ports = []corev1.ServicePort{ 523 { 524 Name: "metrics", 525 Port: common.NotificationsControllerMetricsPort, 526 Protocol: corev1.ProtocolTCP, 527 TargetPort: intstr.FromInt(common.NotificationsControllerMetricsPort), 528 }, 529 } 530 531 if err := controllerutil.SetControllerReference(cr, svc, r.Scheme); err != nil { 532 return err 533 } 534 return r.Client.Create(context.TODO(), svc) 535 } 536 537 // reconcileNotificationsServiceMonitor will ensure that the ServiceMonitor for the Notifications controller metrics is present. 538 func (r *ReconcileArgoCD) reconcileNotificationsServiceMonitor(cr *argoproj.ArgoCD) error { 539 540 name := fmt.Sprintf("%s-%s", cr.Name, "notifications-controller-metrics") 541 serviceMonitor := newServiceMonitorWithName(name, cr) 542 if argoutil.IsObjectFound(r.Client, cr.Namespace, serviceMonitor.Name, serviceMonitor) { 543 // Service found, do nothing 544 return nil 545 } 546 547 serviceMonitor.Spec.Selector = v1.LabelSelector{ 548 MatchLabels: map[string]string{ 549 common.ArgoCDKeyName: name, 550 }, 551 } 552 553 serviceMonitor.Spec.Endpoints = []monitoringv1.Endpoint{ 554 { 555 Port: "metrics", 556 Scheme: "http", 557 Interval: "30s", 558 }, 559 } 560 561 return r.Client.Create(context.TODO(), serviceMonitor) 562 } 563 564 // reconcileNotificationsSecret only creates/deletes the argocd-notifications-secret based on whether notifications is enabled/disabled in the CR 565 // It does not reconcile/overwrite any fields or information in the secret itself 566 func (r *ReconcileArgoCD) reconcileNotificationsSecret(cr *argoproj.ArgoCD) error { 567 568 desiredSecret := argoutil.NewSecretWithName(cr, "argocd-notifications-secret") 569 570 secretExists := true 571 existingSecret := &corev1.Secret{} 572 if err := argoutil.FetchObject(r.Client, cr.Namespace, desiredSecret.Name, existingSecret); err != nil { 573 if !errors.IsNotFound(err) { 574 return fmt.Errorf("failed to get the secret associated with %s : %s", desiredSecret.Name, err) 575 } 576 secretExists = false 577 } 578 579 if secretExists { 580 // secret exists but shouldn't, so it should be deleted 581 if !cr.Spec.Notifications.Enabled { 582 log.Info(fmt.Sprintf("Deleting secret %s as notifications is disabled", existingSecret.Name)) 583 return r.Client.Delete(context.TODO(), existingSecret) 584 } 585 586 // secret exists and should, nothing to do here 587 return nil 588 } 589 590 // secret doesn't exist and shouldn't, nothing to do here 591 if !cr.Spec.Notifications.Enabled { 592 return nil 593 } 594 595 // secret doesn't exist but should, so it should be created 596 if err := controllerutil.SetControllerReference(cr, desiredSecret, r.Scheme); err != nil { 597 return err 598 } 599 600 log.Info(fmt.Sprintf("Creating secret %s", desiredSecret.Name)) 601 err := r.Client.Create(context.TODO(), desiredSecret) 602 if err != nil { 603 return err 604 } 605 606 return nil 607 } 608 609 func getNotificationsCommand(cr *argoproj.ArgoCD) []string { 610 611 cmd := make([]string, 0) 612 cmd = append(cmd, "argocd-notifications") 613 614 cmd = append(cmd, "--loglevel") 615 cmd = append(cmd, getLogLevel(cr.Spec.Notifications.LogLevel)) 616 617 if cr.Spec.Repo.IsEnabled() { 618 cmd = append(cmd, "--argocd-repo-server", getRepoServerAddress(cr)) 619 } else { 620 log.Info("Repo Server is disabled. This would affect the functioning of Notification Controller.") 621 } 622 623 return cmd 624 } 625 626 // getNotificationsResources will return the ResourceRequirements for the Notifications container. 627 func getNotificationsResources(cr *argoproj.ArgoCD) corev1.ResourceRequirements { 628 resources := corev1.ResourceRequirements{} 629 630 // Allow override of resource requirements from CR 631 if cr.Spec.Notifications.Resources != nil { 632 resources = *cr.Spec.Notifications.Resources 633 } 634 635 return resources 636 }