6
6
import org .slf4j .Logger ;
7
7
import org .slf4j .LoggerFactory ;
8
8
9
+ import io .fabric8 .kubernetes .api .model .authorization .v1 .ResourceAttributesBuilder ;
10
+ import io .fabric8 .kubernetes .api .model .authorization .v1 .SelfSubjectAccessReview ;
11
+ import io .fabric8 .kubernetes .api .model .authorization .v1 .SelfSubjectAccessReviewSpecBuilder ;
9
12
import io .fabric8 .kubernetes .client .KubernetesClient ;
10
- import io .fabric8 .kubernetes .client .KubernetesClientException ;
11
13
import io .fabric8 .kubernetes .client .extended .leaderelection .LeaderCallbacks ;
12
14
import io .fabric8 .kubernetes .client .extended .leaderelection .LeaderElectionConfig ;
13
15
import io .fabric8 .kubernetes .client .extended .leaderelection .LeaderElector ;
@@ -28,8 +30,9 @@ public class LeaderElectionManager {
28
30
private final ControllerManager controllerManager ;
29
31
private String identity ;
30
32
private CompletableFuture <?> leaderElectionFuture ;
31
- private LeaderElectionConfig leaderElectionConfig ;
32
33
private KubernetesClient client ;
34
+ private String leaseName ;
35
+ private String leaseNamespace ;
33
36
34
37
public LeaderElectionManager (ControllerManager controllerManager ) {
35
38
this .controllerManager = controllerManager ;
@@ -38,7 +41,8 @@ public LeaderElectionManager(ControllerManager controllerManager) {
38
41
public void init (LeaderElectionConfiguration config , KubernetesClient client ) {
39
42
this .client = client ;
40
43
this .identity = identity (config );
41
- final var leaseNamespace =
44
+ this .leaseName = config .getLeaseName ();
45
+ leaseNamespace =
42
46
config .getLeaseNamespace ().orElseGet (
43
47
() -> ConfigurationServiceProvider .instance ().getClientConfiguration ().getNamespace ());
44
48
if (leaseNamespace == null ) {
@@ -47,21 +51,19 @@ public void init(LeaderElectionConfiguration config, KubernetesClient client) {
47
51
log .error (message );
48
52
throw new IllegalArgumentException (message );
49
53
}
50
- final var lock = new LeaseLock (leaseNamespace , config . getLeaseName () , identity );
54
+ final var lock = new LeaseLock (leaseNamespace , leaseName , identity );
51
55
// releaseOnCancel is not used in the underlying implementation
52
- leaderElectionConfig = new LeaderElectionConfig (
53
- lock ,
54
- config .getLeaseDuration (),
55
- config .getRenewDeadline (),
56
- config .getRetryPeriod (),
57
- leaderCallbacks (),
58
- true ,
59
- config .getLeaseName ());
60
-
61
56
leaderElector =
62
57
new LeaderElectorBuilder (
63
58
client , ExecutorServiceManager .instance ().executorService ())
64
- .withConfig (leaderElectionConfig )
59
+ .withConfig (new LeaderElectionConfig (
60
+ lock ,
61
+ config .getLeaseDuration (),
62
+ config .getRenewDeadline (),
63
+ config .getRetryPeriod (),
64
+ leaderCallbacks (),
65
+ true ,
66
+ config .getLeaseName ()))
65
67
.build ();
66
68
}
67
69
@@ -110,14 +112,30 @@ public void stop() {
110
112
}
111
113
112
114
private void checkLeaseAccess () {
113
- try {
114
- leaderElectionConfig .getLock ().get (client );
115
- } catch (KubernetesClientException e ) {
116
- if (e .getCode () == 403 ) {
117
- throw new OperatorException (NO_PERMISSION_TO_LEASE_RESOURCE_MESSAGE , e );
118
- } else {
119
- throw e ;
115
+ var verbs = new String [] {"create" , "update" , "get" };
116
+ for (String verb : verbs ) {
117
+ var allowed = checkLeaseAccess (verb );
118
+ if (!allowed ) {
119
+ throw new OperatorException (NO_PERMISSION_TO_LEASE_RESOURCE_MESSAGE );
120
120
}
121
121
}
122
122
}
123
+
124
+ private boolean checkLeaseAccess (String verb ) {
125
+ var res = client .resource (selfSubjectReview (verb , leaseName , leaseNamespace )).create ();
126
+ return res .getStatus ().getAllowed ();
127
+ }
128
+
129
+ private SelfSubjectAccessReview selfSubjectReview (String verb , String name , String namespace ) {
130
+ var res = new SelfSubjectAccessReview ();
131
+ res .setSpec (new SelfSubjectAccessReviewSpecBuilder ()
132
+ .withResourceAttributes (new ResourceAttributesBuilder ()
133
+ .withGroup ("coordination.k8s.io" )
134
+ .withNamespace (namespace )
135
+ .withName (name )
136
+ .withVerb (verb )
137
+ .build ())
138
+ .build ());
139
+ return res ;
140
+ }
123
141
}
0 commit comments