1
1
package io .javaoperatorsdk .operator ;
2
2
3
+ import java .util .Arrays ;
3
4
import java .util .UUID ;
4
5
import java .util .concurrent .CompletableFuture ;
5
6
6
7
import org .slf4j .Logger ;
7
8
import org .slf4j .LoggerFactory ;
8
9
10
+ import io .fabric8 .kubernetes .api .model .authorization .v1 .*;
9
11
import io .fabric8 .kubernetes .client .KubernetesClient ;
10
12
import io .fabric8 .kubernetes .client .extended .leaderelection .LeaderCallbacks ;
11
13
import io .fabric8 .kubernetes .client .extended .leaderelection .LeaderElectionConfig ;
@@ -20,18 +22,26 @@ public class LeaderElectionManager {
20
22
21
23
private static final Logger log = LoggerFactory .getLogger (LeaderElectionManager .class );
22
24
25
+ public static final String NO_PERMISSION_TO_LEASE_RESOURCE_MESSAGE =
26
+ "No permission to lease resource." ;
27
+
23
28
private LeaderElector leaderElector = null ;
24
29
private final ControllerManager controllerManager ;
25
30
private String identity ;
26
31
private CompletableFuture <?> leaderElectionFuture ;
32
+ private KubernetesClient client ;
33
+ private String leaseName ;
34
+ private String leaseNamespace ;
27
35
28
36
public LeaderElectionManager (ControllerManager controllerManager ) {
29
37
this .controllerManager = controllerManager ;
30
38
}
31
39
32
40
public void init (LeaderElectionConfiguration config , KubernetesClient client ) {
41
+ this .client = client ;
33
42
this .identity = identity (config );
34
- final var leaseNamespace =
43
+ this .leaseName = config .getLeaseName ();
44
+ leaseNamespace =
35
45
config .getLeaseNamespace ().orElseGet (
36
46
() -> ConfigurationServiceProvider .instance ().getClientConfiguration ().getNamespace ());
37
47
if (leaseNamespace == null ) {
@@ -40,20 +50,19 @@ public void init(LeaderElectionConfiguration config, KubernetesClient client) {
40
50
log .error (message );
41
51
throw new IllegalArgumentException (message );
42
52
}
43
- final var lock = new LeaseLock (leaseNamespace , config . getLeaseName () , identity );
53
+ final var lock = new LeaseLock (leaseNamespace , leaseName , identity );
44
54
// releaseOnCancel is not used in the underlying implementation
45
55
leaderElector =
46
56
new LeaderElectorBuilder (
47
57
client , ExecutorServiceManager .instance ().executorService ())
48
- .withConfig (
49
- new LeaderElectionConfig (
50
- lock ,
51
- config .getLeaseDuration (),
52
- config .getRenewDeadline (),
53
- config .getRetryPeriod (),
54
- leaderCallbacks (),
55
- true ,
56
- config .getLeaseName ()))
58
+ .withConfig (new LeaderElectionConfig (
59
+ lock ,
60
+ config .getLeaseDuration (),
61
+ config .getRenewDeadline (),
62
+ config .getRetryPeriod (),
63
+ leaderCallbacks (),
64
+ true ,
65
+ config .getLeaseName ()))
57
66
.build ();
58
67
}
59
68
@@ -90,6 +99,7 @@ private String identity(LeaderElectionConfiguration config) {
90
99
91
100
public void start () {
92
101
if (isLeaderElectionEnabled ()) {
102
+ checkLeaseAccess ();
93
103
leaderElectionFuture = leaderElector .start ();
94
104
}
95
105
}
@@ -99,4 +109,21 @@ public void stop() {
99
109
leaderElectionFuture .cancel (false );
100
110
}
101
111
}
112
+
113
+ private void checkLeaseAccess () {
114
+ var verbs = Arrays .asList ("create" , "update" , "get" );
115
+ SelfSubjectRulesReview review = new SelfSubjectRulesReview ();
116
+ review .setSpec (new SelfSubjectRulesReviewSpecBuilder ().withNamespace (leaseNamespace ).build ());
117
+ var reviewResult = client .resource (review ).create ();
118
+ log .debug ("SelfSubjectRulesReview result: {}" , reviewResult );
119
+ var foundRule = reviewResult .getStatus ().getResourceRules ().stream ()
120
+ .filter (rule -> rule .getApiGroups ().contains ("coordination.k8s.io" )
121
+ && rule .getResources ().contains ("leases" )
122
+ && (rule .getVerbs ().containsAll (verbs )) || rule .getVerbs ().contains ("*" ))
123
+ .findAny ();
124
+ if (foundRule .isEmpty ()) {
125
+ throw new OperatorException (NO_PERMISSION_TO_LEASE_RESOURCE_MESSAGE +
126
+ " in namespace: " + leaseNamespace );
127
+ }
128
+ }
102
129
}
0 commit comments