1010import java .time .Duration ;
1111import java .util .ArrayList ;
1212import java .util .HashMap ;
13+ import java .util .LinkedList ;
1314import java .util .List ;
1415import java .util .Map ;
1516import java .util .function .Consumer ;
1617import java .util .function .Function ;
1718import java .util .stream .Stream ;
1819
20+ import io .fabric8 .kubernetes .client .dsl .NamespaceListVisitFromServerGetDeleteRecreateWaitApplicable ;
1921import org .junit .jupiter .api .extension .ExtensionContext ;
2022import org .slf4j .Logger ;
2123import org .slf4j .LoggerFactory ;
4042public class LocallyRunOperatorExtension extends AbstractOperatorExtension {
4143
4244 private static final Logger LOGGER = LoggerFactory .getLogger (LocallyRunOperatorExtension .class );
45+ private static final int CRD_DELETE_TIMEOUT = 1000 ;
4346
4447 private final Operator operator ;
4548 private final List <ReconcilerSpec > reconcilers ;
@@ -48,6 +51,7 @@ public class LocallyRunOperatorExtension extends AbstractOperatorExtension {
4851 private final List <Class <? extends CustomResource >> additionalCustomResourceDefinitions ;
4952 private final Map <Reconciler , RegisteredController > registeredControllers ;
5053 private final Map <String , String > crdMappings ;
54+ private static final LinkedList <AppliedCRD > appliedCRDs = new LinkedList <>();
5155
5256 private LocallyRunOperatorExtension (
5357 List <ReconcilerSpec > reconcilers ,
@@ -144,6 +148,7 @@ private static void applyCrd(String crdString, String path, KubernetesClient cli
144148 LOGGER .debug ("Applying CRD: {}" , crdString );
145149 final var crd = client .load (new ByteArrayInputStream (crdString .getBytes ()));
146150 crd .serverSideApply ();
151+ appliedCRDs .add (new AppliedCRD (crdString , path ));
147152 Thread .sleep (CRD_READY_WAIT ); // readiness is not applicable for CRD, just wait a little
148153 LOGGER .debug ("Applied CRD with path: {}" , path );
149154 } catch (InterruptedException ex ) {
@@ -290,6 +295,14 @@ protected void before(ExtensionContext context) {
290295 protected void after (ExtensionContext context ) {
291296 super .after (context );
292297
298+ var kubernetesClient = getKubernetesClient ();
299+
300+ while (!appliedCRDs .isEmpty ()) {
301+ deleteCrd (appliedCRDs .poll (), kubernetesClient );
302+ }
303+
304+ kubernetesClient .close ();
305+
293306 try {
294307 this .operator .stop ();
295308 } catch (Exception e ) {
@@ -306,6 +319,19 @@ protected void after(ExtensionContext context) {
306319 localPortForwards .clear ();
307320 }
308321
322+ private void deleteCrd (AppliedCRD appliedCRD , KubernetesClient client ) {
323+ try {
324+ LOGGER .debug ("Deleting CRD: {}" , appliedCRD .crdString );
325+ final var crd = client .load (new ByteArrayInputStream (appliedCRD .crdString .getBytes ()));
326+ crd .withTimeoutInMillis (CRD_DELETE_TIMEOUT ).delete ();
327+ LOGGER .debug ("Deleted CRD with path: {}" , appliedCRD .path );
328+ } catch (Exception ex ) {
329+ throw new IllegalStateException ("Cannot delete CRD yaml: " + appliedCRD .path , ex );
330+ }
331+ }
332+
333+ private record AppliedCRD (String crdString , String path ) {}
334+
309335 @ SuppressWarnings ("rawtypes" )
310336 public static class Builder extends AbstractBuilder <Builder > {
311337 private final List <ReconcilerSpec > reconcilers ;
0 commit comments