1+ /*
2+ * SPDX-License-Identifier: Apache-2.0
3+ * Copyright (c) The original authors
4+ *
5+ * Licensed under the Apache Software License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0
6+ */
7+ package io .streamthoughts .jikkou .schema .registry .reconciler ;
8+
9+ import static org .junit .jupiter .api .Assertions .assertEquals ;
10+ import static org .junit .jupiter .api .Assertions .assertTrue ;
11+
12+ import io .streamthoughts .jikkou .core .ReconciliationContext ;
13+ import io .streamthoughts .jikkou .core .ReconciliationMode ;
14+ import io .streamthoughts .jikkou .core .config .Configuration ;
15+ import io .streamthoughts .jikkou .core .data .SchemaHandle ;
16+ import io .streamthoughts .jikkou .core .data .SchemaType ;
17+ import io .streamthoughts .jikkou .core .models .ApiChangeResultList ;
18+ import io .streamthoughts .jikkou .core .models .CoreAnnotations ;
19+ import io .streamthoughts .jikkou .core .models .ObjectMeta ;
20+ import io .streamthoughts .jikkou .core .models .ResourceList ;
21+ import io .streamthoughts .jikkou .core .models .change .ResourceChange ;
22+ import io .streamthoughts .jikkou .core .reconciler .ChangeResult ;
23+ import io .streamthoughts .jikkou .core .reconciler .Operation ;
24+ import io .streamthoughts .jikkou .core .selector .Selectors ;
25+ import io .streamthoughts .jikkou .schema .registry .BaseExtensionProviderIT ;
26+ import io .streamthoughts .jikkou .schema .registry .SchemaRegistryAnnotations ;
27+ import io .streamthoughts .jikkou .schema .registry .models .V1SchemaRegistrySubject ;
28+ import io .streamthoughts .jikkou .schema .registry .models .V1SchemaRegistrySubjectSpec ;
29+ import java .util .List ;
30+ import java .util .Map ;
31+ import org .junit .jupiter .api .Test ;
32+
33+ class SchemaRegistrySubjectDeleteTest extends BaseExtensionProviderIT {
34+
35+ @ Test
36+ void shouldSoftDeleteSchemaSubject () {
37+ // Given - register a schema first
38+ V1SchemaRegistrySubject resource = createSubjectResource (TEST_SUBJECT );
39+ api .reconcile (
40+ ResourceList .of (List .of (resource )),
41+ ReconciliationMode .CREATE ,
42+ ReconciliationContext .builder ().dryRun (false ).build ());
43+
44+ // When - delete the schema (soft delete only)
45+ V1SchemaRegistrySubject deleteResource = V1SchemaRegistrySubject .builder ()
46+ .withMetadata (ObjectMeta .builder ()
47+ .withName (TEST_SUBJECT )
48+ .withAnnotations (Map .of (
49+ CoreAnnotations .JIKKOU_IO_DELETE , true ))
50+ .build ())
51+ .withSpec (V1SchemaRegistrySubjectSpec .builder ()
52+ .withSchemaType (SchemaType .AVRO )
53+ .withSchema (new SchemaHandle (AVRO_SCHEMA ))
54+ .build ())
55+ .build ();
56+
57+ ApiChangeResultList result = api .reconcile (
58+ ResourceList .of (List .of (deleteResource )),
59+ ReconciliationMode .DELETE ,
60+ ReconciliationContext .builder ().dryRun (false ).build ());
61+
62+ // Then
63+ List <ChangeResult > results = result .results ();
64+ assertEquals (1 , results .size ());
65+ ResourceChange change = results .getFirst ().change ();
66+ assertEquals (Operation .DELETE , change .getSpec ().getOp ());
67+
68+ // Verify subject is no longer listed
69+ ResourceList <V1SchemaRegistrySubject > subjects =
70+ api .listResources (V1SchemaRegistrySubject .class , Selectors .NO_SELECTOR , Configuration .empty ());
71+ assertTrue (subjects .stream ().noneMatch (s -> TEST_SUBJECT .equals (s .getMetadata ().getName ())));
72+ }
73+
74+ @ Test
75+ void shouldPermanentlyDeleteSchemaSubject () {
76+ // Given - register a schema first
77+ V1SchemaRegistrySubject resource = createSubjectResource (TEST_SUBJECT );
78+ api .reconcile (
79+ ResourceList .of (List .of (resource )),
80+ ReconciliationMode .CREATE ,
81+ ReconciliationContext .builder ().dryRun (false ).build ());
82+
83+ // When - permanently delete the schema (soft + hard delete)
84+ V1SchemaRegistrySubject deleteResource = V1SchemaRegistrySubject .builder ()
85+ .withMetadata (ObjectMeta .builder ()
86+ .withName (TEST_SUBJECT )
87+ .withAnnotations (Map .of (
88+ CoreAnnotations .JIKKOU_IO_DELETE , true ,
89+ SchemaRegistryAnnotations .SCHEMA_REGISTRY_PERMANANTE_DELETE , true ))
90+ .build ())
91+ .withSpec (V1SchemaRegistrySubjectSpec .builder ()
92+ .withSchemaType (SchemaType .AVRO )
93+ .withSchema (new SchemaHandle (AVRO_SCHEMA ))
94+ .build ())
95+ .build ();
96+
97+ ApiChangeResultList result = api .reconcile (
98+ ResourceList .of (List .of (deleteResource )),
99+ ReconciliationMode .DELETE ,
100+ ReconciliationContext .builder ().dryRun (false ).build ());
101+
102+ // Then
103+ List <ChangeResult > results = result .results ();
104+ assertEquals (1 , results .size ());
105+ ResourceChange change = results .getFirst ().change ();
106+ assertEquals (Operation .DELETE , change .getSpec ().getOp ());
107+
108+ // Verify subject is no longer listed
109+ ResourceList <V1SchemaRegistrySubject > subjects =
110+ api .listResources (V1SchemaRegistrySubject .class , Selectors .NO_SELECTOR , Configuration .empty ());
111+ assertTrue (subjects .stream ().noneMatch (s -> TEST_SUBJECT .equals (s .getMetadata ().getName ())));
112+
113+ // Verify the subject can be re-registered (only possible after hard delete)
114+ V1SchemaRegistrySubject reRegister = createSubjectResource (TEST_SUBJECT );
115+ ApiChangeResultList reRegisterResult = api .reconcile (
116+ ResourceList .of (List .of (reRegister )),
117+ ReconciliationMode .CREATE ,
118+ ReconciliationContext .builder ().dryRun (false ).build ());
119+ assertEquals (1 , reRegisterResult .results ().size ());
120+ assertEquals (Operation .CREATE , reRegisterResult .results ().getFirst ().change ().getSpec ().getOp ());
121+ }
122+
123+ private V1SchemaRegistrySubject createSubjectResource (String subjectName ) {
124+ return V1SchemaRegistrySubject .builder ()
125+ .withMetadata (ObjectMeta .builder ()
126+ .withName (subjectName )
127+ .build ())
128+ .withSpec (V1SchemaRegistrySubjectSpec .builder ()
129+ .withSchemaType (SchemaType .AVRO )
130+ .withSchema (new SchemaHandle (AVRO_SCHEMA ))
131+ .build ())
132+ .build ();
133+ }
134+ }
0 commit comments