88import io .fabric8 .kubernetes .api .model .ObjectMetaBuilder ;
99import io .fabric8 .kubernetes .api .model .rbac .ClusterRole ;
1010import io .fabric8 .kubernetes .api .model .rbac .ClusterRoleBinding ;
11+ import io .fabric8 .kubernetes .api .model .rbac .Role ;
12+ import io .fabric8 .kubernetes .api .model .rbac .RoleBinding ;
1113import io .fabric8 .kubernetes .client .ConfigBuilder ;
1214import io .fabric8 .kubernetes .client .KubernetesClient ;
1315import io .fabric8 .kubernetes .client .KubernetesClientBuilder ;
1416import io .fabric8 .kubernetes .client .utils .KubernetesResourceUtil ;
1517import io .javaoperatorsdk .operator .api .config .ConfigurationServiceProvider ;
18+ import io .javaoperatorsdk .operator .health .InformerHealthIndicator ;
1619import io .javaoperatorsdk .operator .junit .LocallyRunOperatorExtension ;
1720import io .javaoperatorsdk .operator .processing .event .source .controller .ControllerResourceEventSource ;
21+ import io .javaoperatorsdk .operator .sample .informerrelatedbehavior .ConfigMapDependentResource ;
1822import io .javaoperatorsdk .operator .sample .informerrelatedbehavior .InformerRelatedBehaviorTestCustomResource ;
1923import io .javaoperatorsdk .operator .sample .informerrelatedbehavior .InformerRelatedBehaviorTestReconciler ;
2024
4044class InformerRelatedBehaviorITS {
4145
4246 public static final String TEST_RESOURCE_NAME = "test1" ;
47+ public static final String ADDITIONAL_NAMESPACE_NAME = "additionalns" ;
4348
4449 KubernetesClient adminClient = new KubernetesClientBuilder ().build ();
4550 InformerRelatedBehaviorTestReconciler reconciler ;
@@ -54,6 +59,8 @@ void beforeEach(TestInfo testInfo) {
5459 actualNamespace = KubernetesResourceUtil .sanitizeName (method .getName ());
5560 adminClient .resource (namespace ()).createOrReplace ();
5661 });
62+ // cleans up binding before test, not all test cases use cluster role
63+ removeClusterRoleBinding ();
5764 }
5865
5966 @ AfterEach
@@ -101,6 +108,51 @@ void startsUpWhenNoPermissionToSecondaryResource() {
101108 assertReconciled ();
102109 }
103110
111+ @ Test
112+ void startsUpIfNoPermissionToOneOfTwoNamespaces () {
113+ var otherNamespace =
114+ adminClient .resource (namespace (ADDITIONAL_NAMESPACE_NAME )).createOrReplace ();
115+ try {
116+ addRoleBindingsToTestNamespaces ();
117+ var operator = startOperator (false , false , actualNamespace , ADDITIONAL_NAMESPACE_NAME );
118+ assertInformerNotWatchingForAdditionalNamespace (operator );
119+
120+ adminClient .resource (testCustomResource ()).createOrReplace ();
121+ waitForWatchReconnect ();
122+ assertReconciled ();
123+
124+ } finally {
125+ adminClient .resource (otherNamespace ).delete ();
126+ await ().untilAsserted (() -> {
127+ var ns = adminClient .namespaces ().resource (otherNamespace ).fromServer ().get ();
128+ assertThat (ns ).isNull ();
129+ });
130+ }
131+ }
132+
133+ private void assertInformerNotWatchingForAdditionalNamespace (Operator operator ) {
134+ assertThat (operator .getRuntimeInfo ().allEventSourcesAreHealthy ()).isFalse ();
135+ var unhealthyEventSources =
136+ operator .getRuntimeInfo ().unhealthyInformerWrappingEventSourceHealthIndicator ()
137+ .get (INFORMER_RELATED_BEHAVIOR_TEST_RECONCILER );
138+
139+ InformerHealthIndicator controllerHealthIndicator =
140+ (InformerHealthIndicator ) unhealthyEventSources
141+ .get (ControllerResourceEventSource .class .getSimpleName ())
142+ .informerHealthIndicators ().get (ADDITIONAL_NAMESPACE_NAME );
143+ assertThat (controllerHealthIndicator ).isNotNull ();
144+ assertThat (controllerHealthIndicator .getTargetNamespace ()).isEqualTo (ADDITIONAL_NAMESPACE_NAME );
145+ assertThat (controllerHealthIndicator .isWatching ()).isFalse ();
146+
147+ InformerHealthIndicator configMapHealthIndicator =
148+ (InformerHealthIndicator ) unhealthyEventSources
149+ .get (ConfigMapDependentResource .class .getSimpleName ())
150+ .informerHealthIndicators ().get (ADDITIONAL_NAMESPACE_NAME );
151+ assertThat (configMapHealthIndicator ).isNotNull ();
152+ assertThat (configMapHealthIndicator .getTargetNamespace ()).isEqualTo (ADDITIONAL_NAMESPACE_NAME );
153+ assertThat (configMapHealthIndicator .isWatching ()).isFalse ();
154+ }
155+
104156 @ Test
105157 void resilientForLoosingPermissionForCustomResource () throws InterruptedException {
106158 setFullResourcesAccess ();
@@ -240,7 +292,8 @@ Operator startOperator(boolean stopOnInformerErrorDuringStartup) {
240292 return startOperator (stopOnInformerErrorDuringStartup , true );
241293 }
242294
243- Operator startOperator (boolean stopOnInformerErrorDuringStartup , boolean addStopHandler ) {
295+ Operator startOperator (boolean stopOnInformerErrorDuringStartup , boolean addStopHandler ,
296+ String ... namespaces ) {
244297 ConfigurationServiceProvider .reset ();
245298 reconciler = new InformerRelatedBehaviorTestReconciler ();
246299
@@ -252,7 +305,11 @@ Operator startOperator(boolean stopOnInformerErrorDuringStartup, boolean addStop
252305 co .withInformerStoppedHandler ((informer , ex ) -> replacementStopHandlerCalled = true );
253306 }
254307 });
255- operator .register (reconciler );
308+ operator .register (reconciler , o -> {
309+ if (namespaces .length > 0 ) {
310+ o .settingNamespaces (namespaces );
311+ }
312+ });
256313 operator .start ();
257314 return operator ;
258315 }
@@ -272,6 +329,16 @@ private void setFullResourcesAccess() {
272329 applyClusterRoleBinding ();
273330 }
274331
332+ private void addRoleBindingsToTestNamespaces () {
333+ var role = ReconcilerUtils
334+ .loadYaml (Role .class , this .getClass (), "rback-test-only-main-ns-access.yaml" );
335+ adminClient .resource (role ).inNamespace (actualNamespace ).createOrReplace ();
336+ var roleBinding = ReconcilerUtils
337+ .loadYaml (RoleBinding .class , this .getClass (),
338+ "rback-test-only-main-ns-access-binding.yaml" );
339+ adminClient .resource (roleBinding ).inNamespace (actualNamespace ).createOrReplace ();
340+ }
341+
275342 private void applyClusterRoleBinding () {
276343 var clusterRoleBinding = ReconcilerUtils
277344 .loadYaml (ClusterRoleBinding .class , this .getClass (), "rback-test-role-binding.yaml" );
@@ -285,10 +352,20 @@ private void applyClusterRole(String filename) {
285352 }
286353
287354 private Namespace namespace () {
355+ return namespace (actualNamespace );
356+ }
357+
358+ private Namespace namespace (String name ) {
288359 Namespace n = new Namespace ();
289360 n .setMetadata (new ObjectMetaBuilder ()
290- .withName (actualNamespace )
361+ .withName (name )
291362 .build ());
292363 return n ;
293364 }
365+
366+ private void removeClusterRoleBinding () {
367+ var clusterRoleBinding = ReconcilerUtils
368+ .loadYaml (ClusterRoleBinding .class , this .getClass (), "rback-test-role-binding.yaml" );
369+ adminClient .resource (clusterRoleBinding ).delete ();
370+ }
294371}
0 commit comments