11package io .javaoperatorsdk .operator .processing .dependent ;
22
3+ import java .util .ArrayList ;
4+ import java .util .List ;
35import java .util .Optional ;
46
57import org .slf4j .Logger ;
@@ -20,25 +22,73 @@ public abstract class AbstractDependentResource<R, P extends HasMetadata>
2022
2123 protected final boolean creatable = this instanceof Creator ;
2224 protected final boolean updatable = this instanceof Updater ;
25+ protected final boolean bulk = this instanceof BulkDependentResource ;
2326
2427 protected Creator <R , P > creator ;
2528 protected Updater <R , P > updater ;
29+ protected BulkDependentResource <R , P > bulkDependentResource ;
2630
27- private ResourceDiscriminator <R , P > resourceDiscriminator ;
31+ private final List < ResourceDiscriminator <R , P >> resourceDiscriminator = new ArrayList <>( 1 ) ;
2832
2933 @ SuppressWarnings ("unchecked" )
3034 public AbstractDependentResource () {
3135 creator = creatable ? (Creator <R , P >) this : null ;
3236 updater = updatable ? (Updater <R , P >) this : null ;
37+
38+ bulkDependentResource = bulk ? (BulkDependentResource <R , P >) this : null ;
3339 }
3440
3541 @ Override
3642 public ReconcileResult <R > reconcile (P primary , Context <P > context ) {
37- Optional <R > maybeActual = getSecondaryResource (primary , context );
43+ if (bulk ) {
44+ final var count = bulkDependentResource .count (primary , context );
45+ deleteBulkResourcesIfRequired (count , lastKnownBulkSize (), primary , context );
46+ adjustDiscriminators (count );
47+ @ SuppressWarnings ("unchecked" )
48+ final ReconcileResult <R >[] results = new ReconcileResult [count ];
49+ for (int i = 0 ; i < count ; i ++) {
50+ results [i ] = reconcileIndexAware (primary , i , context );
51+ }
52+ return ReconcileResult .aggregatedResult (results );
53+ } else {
54+ return reconcileIndexAware (primary , 0 , context );
55+ }
56+ }
57+
58+ protected void deleteBulkResourcesIfRequired (int targetCount , int actualCount , P primary ,
59+ Context <P > context ) {
60+ if (targetCount >= actualCount ) {
61+ return ;
62+ }
63+ for (int i = targetCount ; i < actualCount ; i ++) {
64+ var resource = getSecondaryResourceIndexAware (primary , i , context );
65+ var index = i ;
66+ resource .ifPresent (
67+ r -> bulkDependentResource .deleteBulkResourceWithIndex (primary , r , index , context ));
68+ }
69+ }
70+
71+ private void adjustDiscriminators (int count ) {
72+ if (resourceDiscriminator .size () == count ) {
73+ return ;
74+ }
75+ if (resourceDiscriminator .size () < count ) {
76+ for (int i = resourceDiscriminator .size (); i < count ; i ++) {
77+ resourceDiscriminator .add (bulkDependentResource .getResourceDiscriminator (i ));
78+ }
79+ }
80+ if (resourceDiscriminator .size () > count ) {
81+ resourceDiscriminator .subList (count , resourceDiscriminator .size ()).clear ();
82+ }
83+ }
84+
85+ protected ReconcileResult <R > reconcileIndexAware (P primary , int i , Context <P > context ) {
86+ Optional <R > maybeActual = bulk ? getSecondaryResourceIndexAware (primary , i , context )
87+ : getSecondaryResource (primary , context );
3888 if (creatable || updatable ) {
3989 if (maybeActual .isEmpty ()) {
4090 if (creatable ) {
41- var desired = desired (primary , context );
91+ var desired = desiredIndexAware (primary , i , context );
4292 throwIfNull (desired , primary , "Desired" );
4393 logForOperation ("Creating" , primary , desired );
4494 var createdResource = handleCreate (desired , primary , context );
@@ -47,9 +97,15 @@ public ReconcileResult<R> reconcile(P primary, Context<P> context) {
4797 } else {
4898 final var actual = maybeActual .get ();
4999 if (updatable ) {
50- final var match = updater .match (actual , primary , context );
100+ final Matcher .Result <R > match ;
101+ if (bulk ) {
102+ match = updater .match (actual , primary , i , context );
103+ } else {
104+ match = updater .match (actual , primary , context );
105+ }
51106 if (!match .matched ()) {
52- final var desired = match .computedDesired ().orElse (desired (primary , context ));
107+ final var desired =
108+ match .computedDesired ().orElse (desiredIndexAware (primary , i , context ));
53109 throwIfNull (desired , primary , "Desired" );
54110 logForOperation ("Updating" , primary , desired );
55111 var updatedResource = handleUpdate (actual , desired , primary , context );
@@ -67,9 +123,18 @@ public ReconcileResult<R> reconcile(P primary, Context<P> context) {
67123 return ReconcileResult .noOperation (maybeActual .orElse (null ));
68124 }
69125
126+ private R desiredIndexAware (P primary , int i , Context <P > context ) {
127+ return bulk ? desired (primary , i , context )
128+ : desired (primary , context );
129+ }
130+
70131 public Optional <R > getSecondaryResource (P primary , Context <P > context ) {
71- return resourceDiscriminator == null ? context .getSecondaryResource (resourceType ())
72- : resourceDiscriminator .distinguish (resourceType (), primary , context );
132+ return resourceDiscriminator .isEmpty () ? context .getSecondaryResource (resourceType ())
133+ : resourceDiscriminator .get (0 ).distinguish (resourceType (), primary , context );
134+ }
135+
136+ protected Optional <R > getSecondaryResourceIndexAware (P primary , int index , Context <P > context ) {
137+ return context .getSecondaryResource (resourceType (), resourceDiscriminator .get (index ));
73138 }
74139
75140 private void throwIfNull (R desired , P primary , String descriptor ) {
@@ -97,7 +162,7 @@ protected R handleCreate(R desired, P primary, Context<P> context) {
97162 }
98163
99164 /**
100- * Allows sub-classes to perform additional processing (e.g. caching) on the created resource if
165+ * Allows subclasses to perform additional processing (e.g. caching) on the created resource if
101166 * needed.
102167 *
103168 * @param primaryResourceId the {@link ResourceID} of the primary resource associated with the
@@ -129,12 +194,29 @@ protected R desired(P primary, Context<P> context) {
129194 "desired method must be implemented if this DependentResource can be created and/or updated" );
130195 }
131196
132- public void setResourceDiscriminator (
197+ protected R desired (P primary , int index , Context <P > context ) {
198+ throw new IllegalStateException (
199+ "Must be implemented for bulk DependentResource creation" );
200+ }
201+
202+ public AbstractDependentResource <R , P > setResourceDiscriminator (
133203 ResourceDiscriminator <R , P > resourceDiscriminator ) {
134- this .resourceDiscriminator = resourceDiscriminator ;
204+ if (resourceDiscriminator != null ) {
205+ this .resourceDiscriminator .add (resourceDiscriminator );
206+ }
207+ return this ;
135208 }
136209
137210 public ResourceDiscriminator <R , P > getResourceDiscriminator () {
138- return resourceDiscriminator ;
211+ if (this .resourceDiscriminator .isEmpty ()) {
212+ return null ;
213+ } else {
214+ return this .resourceDiscriminator .get (0 );
215+ }
139216 }
217+
218+ protected int lastKnownBulkSize () {
219+ return resourceDiscriminator .size ();
220+ }
221+
140222}
0 commit comments