func add()

in pkg/controller/integrationkit/integrationkit_controller.go [69:176]


func add(_ context.Context, mgr manager.Manager, r reconcile.Reconciler) error {
	c, err := controller.New("integrationkit-controller", mgr, controller.Options{Reconciler: r})
	if err != nil {
		return err
	}

	// Watch for changes to primary resource IntegrationKit
	err = c.Watch(&source.Kind{Type: &v1.IntegrationKit{}},
		&handler.EnqueueRequestForObject{},
		platform.FilteringFuncs{
			UpdateFunc: func(e event.UpdateEvent) bool {
				oldIntegrationKit, ok := e.ObjectOld.(*v1.IntegrationKit)
				if !ok {
					return false
				}
				newIntegrationKit, ok := e.ObjectNew.(*v1.IntegrationKit)
				if !ok {
					return false
				}
				// Ignore updates to the integration kit status in which case metadata.Generation
				// does not change, or except when the integration kit phase changes as it's used
				// to transition from one phase to another
				return oldIntegrationKit.Generation != newIntegrationKit.Generation ||
					oldIntegrationKit.Status.Phase != newIntegrationKit.Status.Phase
			},
			DeleteFunc: func(e event.DeleteEvent) bool {
				// Evaluates to false if the object has been confirmed deleted
				return !e.DeleteStateUnknown
			},
		},
	)
	if err != nil {
		return err
	}

	// Watch for changes to secondary resource Builds and requeue the owner IntegrationKit
	err = c.Watch(&source.Kind{Type: &v1.Build{}},
		&handler.EnqueueRequestForOwner{
			IsController: true,
			OwnerType:    &v1.IntegrationKit{},
		},
		platform.FilteringFuncs{
			UpdateFunc: func(e event.UpdateEvent) bool {
				oldBuild, ok := e.ObjectOld.(*v1.Build)
				if !ok {
					return false
				}
				newBuild, ok := e.ObjectNew.(*v1.Build)
				if !ok {
					return false
				}
				// Ignore updates to the build CR except when the build phase changes
				// as it's used to transition the integration kit from one phase
				// to another during the image build
				return oldBuild.Status.Phase != newBuild.Status.Phase
			},
		},
	)
	if err != nil {
		return err
	}

	// Watch for IntegrationPlatform phase transitioning to ready and enqueue
	// requests for any integration kits that are in phase waiting for platform
	err = c.Watch(&source.Kind{Type: &v1.IntegrationPlatform{}},
		handler.EnqueueRequestsFromMapFunc(func(a ctrl.Object) []reconcile.Request {
			var requests []reconcile.Request
			p, ok := a.(*v1.IntegrationPlatform)
			if !ok {
				log.Error(fmt.Errorf("type assertion failed: %v", a), "Failed to list integration kits")
				return requests
			}

			if p.Status.Phase == v1.IntegrationPlatformPhaseReady {
				list := &v1.IntegrationKitList{}

				if err := mgr.GetClient().List(context.TODO(), list, ctrl.InNamespace(p.Namespace)); err != nil {
					log.Error(err, "Failed to list integration kits")
					return requests
				}

				for _, kit := range list.Items {
					if v, ok := kit.Annotations[v1.PlatformSelectorAnnotation]; ok && v != p.Name {
						log.Infof("Integration kit %s is waiting for selected integration platform '%s' - skip it now", kit.Name, v)
						continue
					}

					if kit.Status.Phase == v1.IntegrationKitPhaseWaitingForPlatform {
						log.Infof("Platform %s ready, wake-up integration kit: %s", p.Name, kit.Name)
						requests = append(requests, reconcile.Request{
							NamespacedName: types.NamespacedName{
								Namespace: kit.Namespace,
								Name:      kit.Name,
							},
						})
					}
				}
			}

			return requests
		}),
	)
	if err != nil {
		return err
	}

	return nil
}