|
13 | 13 | import io.fabric8.kubernetes.client.dsl.MixedOperation; |
14 | 14 | import io.fabric8.kubernetes.client.informers.ResourceEventHandler; |
15 | 15 | import io.javaoperatorsdk.operator.api.config.informer.InformerEventSourceConfiguration; |
| 16 | +import io.javaoperatorsdk.operator.api.reconciler.Context; |
16 | 17 | import io.javaoperatorsdk.operator.api.reconciler.EventSourceContext; |
17 | 18 | import io.javaoperatorsdk.operator.processing.event.Event; |
18 | 19 | import io.javaoperatorsdk.operator.processing.event.EventHandler; |
19 | 20 | import io.javaoperatorsdk.operator.processing.event.ResourceID; |
20 | 21 | import io.javaoperatorsdk.operator.processing.event.source.PrimaryToSecondaryMapper; |
21 | 22 |
|
22 | 23 | /** |
23 | | - * Wraps informer(s) so it is connected to the eventing system of the framework. Note that since |
24 | | - * it's it is built on top of Informers, it also support caching resources using caching from |
25 | | - * fabric8 client Informer caches and additional caches described below. |
| 24 | + * Wraps informer(s) so they are connected to the eventing system of the framework. Note that since |
| 25 | + * this is built on top of Fabric8 client Informers, it also supports caching resources using caching from |
| 26 | + * informer caches as well as additional caches described below. |
26 | 27 | * |
27 | 28 | * <p>InformerEventSource also supports two features to better handle events and caching of |
28 | | - * resources on top of Informers from fabric8 Kubernetes client. These two features implementation |
29 | | - * wise are related to each other: <br> |
| 29 | + * resources on top of Informers from the Fabric8 Kubernetes client. These two features |
| 30 | + * are related to each other as follows: |
30 | 31 | * |
31 | | - * <p>1. API that allows to make sure the cache contains the fresh resource after an update. This is |
32 | | - * important for {@link io.javaoperatorsdk.operator.api.reconciler.dependent.DependentResource} and |
33 | | - * mainly for {@link |
34 | | - * io.javaoperatorsdk.operator.processing.dependent.kubernetes.KubernetesDependentResource} so after |
35 | | - * reconcile if getResource() called always return the fresh resource. To achieve this |
36 | | - * handleRecentResourceUpdate() and handleRecentResourceCreate() needs to be called explicitly after |
37 | | - * resource created/updated using the kubernetes client. (These calls are done automatically by |
38 | | - * KubernetesDependentResource implementation.). In the background this will store the new resource |
39 | | - * in a temporary cache {@link TemporaryResourceCache} which do additional checks. After a new event |
40 | | - * is received the cachec object is removed from this cache, since in general then it is already in |
41 | | - * the cache of informer. <br> |
| 32 | + * <ol> |
| 33 | + * <li>Ensuring the cache contains the fresh resource after an update. This is |
| 34 | + * important for {@link |
| 35 | + * io.javaoperatorsdk.operator.api.reconciler.dependent.DependentResource} and mainly for |
| 36 | + * {@link |
| 37 | + * io.javaoperatorsdk.operator.processing.dependent.kubernetes.KubernetesDependentResource} so |
| 38 | + * that {@link io.javaoperatorsdk.operator.api.reconciler.dependent.DependentResource#getSecondaryResource(HasMetadata, Context)} always returns the latest version of the resource after a reconciliation. To achieve this |
| 39 | + * {@link #handleRecentResourceUpdate(ResourceID, HasMetadata, HasMetadata)} and {@link #handleRecentResourceCreate(ResourceID, HasMetadata)} need to be called explicitly |
| 40 | + * after a resource is created or updated using the kubernetes client. These calls are done |
| 41 | + * automatically by the KubernetesDependentResource implementation. In the background this will |
| 42 | + * store the new resource in a temporary cache {@link TemporaryResourceCache} which does |
| 43 | + * additional checks. After a new event is received the cached object is removed from this |
| 44 | + * cache, since it is then usually already in the informer cache. |
| 45 | + * <li>Avoiding unneeded reconciliations after resources are created or updated. This filters out events that are the results of updates and creates made |
| 46 | + * by the controller itself because we typically don't want the associated informer to trigger an event causing a useless reconciliation (as the change originates from the reconciler itself). This is achieved |
| 47 | + * by |
| 48 | + * TODO: update as this mentions methods that don't exist anymore and isn't very clear |
42 | 49 | * |
43 | | - * <p>2. Additional API is provided that is meant to be used with the combination of the previous |
44 | | - * one, and the goal is to filter out events that are the results of updates and creates made by the |
45 | | - * controller itself. For example if in reconciler a ConfigMaps is created, there should be an |
46 | | - * Informer in place to handle change events of that ConfigMap, but since it has bean created (or |
47 | | - * updated) by the reconciler this should not trigger an additional reconciliation by default. In |
48 | | - * order to achieve this prepareForCreateOrUpdateEventFiltering(..) method needs to be called before |
49 | | - * the operation of the k8s client. And the operation from point 1. after the k8s client call. See |
50 | | - * it's usage in CreateUpdateEventFilterTestReconciler integration test for the usage. (Again this |
51 | | - * is managed for the developer if using dependent resources.) <br> |
52 | | - * Roughly it works in a way that before the K8S API call is made, we set mark the resource ID, and |
53 | | - * from that point informer won't propagate events further just will start record them. After the |
54 | | - * client operation is done, it's checked and analysed what events were received and based on that |
55 | | - * it will propagate event or not and/or put the new resource into the temporal cache - so if the |
56 | | - * event not arrived yet about the update will be able to filter it in the future. |
| 50 | + * {@link #prepareForCreateOrUpdateEventFiltering(..) method needs to be called before the operation |
| 51 | + * of the k8s client. And the operation from point 1. after the k8s client call. See its |
| 52 | + * usage in CreateUpdateEventFilterTestReconciler integration test for the usage. (Again this |
| 53 | + * is managed for the developer if using dependent resources.) <br> |
| 54 | + * Roughly it works in a way that before the K8S API call is made, we set mark the resource |
| 55 | + * ID, and from that point informer won't propagate events further just will start record |
| 56 | + * them. After the client operation is done, it's checked and analysed what events were |
| 57 | + * received and based on that it will propagate event or not and/or put the new resource into |
| 58 | + * the temporal cache - so if the event not arrived yet about the update will be able to |
| 59 | + * filter it in the future. |
| 60 | + * </ol> |
57 | 61 | * |
58 | | - * @param <R> resource type watching |
59 | | - * @param <P> type of the primary resource |
| 62 | + * @param <R> resource type being watched |
| 63 | + * @param <P> type of the associated primary resource |
60 | 64 | */ |
61 | 65 | public class InformerEventSource<R extends HasMetadata, P extends HasMetadata> |
62 | 66 | extends ManagedInformerEventSource<R, P, InformerEventSourceConfiguration<R>> |
63 | 67 | implements ResourceEventHandler<R> { |
64 | 68 |
|
65 | | - private static final Logger log = LoggerFactory.getLogger(InformerEventSource.class); |
66 | 69 | public static final String PREVIOUS_ANNOTATION_KEY = "javaoperatorsdk.io/previous"; |
| 70 | + private static final Logger log = LoggerFactory.getLogger(InformerEventSource.class); |
67 | 71 | // we need direct control for the indexer to propagate the just update resource also to the index |
68 | 72 | private final PrimaryToSecondaryIndex<R> primaryToSecondaryIndex; |
69 | 73 | private final PrimaryToSecondaryMapper<P> primaryToSecondaryMapper; |
|
0 commit comments