File tree Expand file tree Collapse file tree 6 files changed +60
-6
lines changed
tests/KubeOps.TestOperator Expand file tree Collapse file tree 6 files changed +60
-6
lines changed Original file line number Diff line number Diff line change @@ -215,8 +215,15 @@ internal IOperatorBuilder AddOperatorBase(OperatorSettings settings)
215
215
. ForwardToPrometheus ( ) ;
216
216
217
217
// Support for leader election via V1Leases.
218
- Services . AddHostedService < LeaderElector > ( ) ;
219
- Services . AddSingleton < ILeaderElection , LeaderElection > ( ) ;
218
+ if ( settings . EnableLeaderElection )
219
+ {
220
+ Services . AddHostedService < LeaderElector > ( ) ;
221
+ Services . AddSingleton < ILeaderElection , LeaderElection > ( ) ;
222
+ }
223
+ else
224
+ {
225
+ Services . AddSingleton < ILeaderElection , DisabledLeaderElection > ( ) ;
226
+ }
220
227
221
228
// Register event handler
222
229
Services . AddTransient < IEventManager , EventManager > ( ) ;
Original file line number Diff line number Diff line change
1
+ using System ;
2
+ using System . Reactive . Linq ;
3
+ using System . Reactive . Subjects ;
4
+
5
+ namespace KubeOps . Operator . Leadership
6
+ {
7
+ internal class DisabledLeaderElection : ILeaderElection , IDisposable
8
+ {
9
+ private readonly BehaviorSubject < LeaderState > _leadershipChange = new ( LeaderState . Leader ) ;
10
+
11
+ public IObservable < LeaderState > LeadershipChange => _leadershipChange . DistinctUntilChanged ( ) ;
12
+
13
+ public void Dispose ( )
14
+ {
15
+ _leadershipChange . Dispose ( ) ;
16
+ }
17
+
18
+ void ILeaderElection . LeadershipChanged ( LeaderState state )
19
+ {
20
+ }
21
+ }
22
+ }
Original file line number Diff line number Diff line change 16
16
17
17
namespace KubeOps . Operator . Leadership
18
18
{
19
- [ EntityRbac ( typeof ( V1Lease ) , Verbs = RbacVerb . All ) ]
20
- [ EntityRbac ( typeof ( V1Deployment ) , Verbs = RbacVerb . Get | RbacVerb . List ) ]
21
19
internal class LeaderElector : IHostedService
22
20
{
23
21
private readonly ILogger < LeaderElector > _logger ;
Original file line number Diff line number Diff line change @@ -55,6 +55,21 @@ public sealed class OperatorSettings
55
55
/// </summary>
56
56
public string ReadinessEndpoint { get ; set ; } = "/ready" ;
57
57
58
+ /// <summary>
59
+ /// <para>
60
+ /// Defines if the leader elector should run. You may disable this,
61
+ /// if you don't intend to run your operator multiple times.
62
+ /// </para>
63
+ /// <para>
64
+ /// If this is disabled, and an operator runs in multiple instance
65
+ /// (in the same namespace) it can lead to a "split brain" problem.
66
+ /// </para>
67
+ /// <para>
68
+ /// This could be disabled when developing locally.
69
+ /// </para>
70
+ /// </summary>
71
+ public bool EnableLeaderElection { get ; set ; } = true ;
72
+
58
73
/// <summary>
59
74
/// The interval in seconds in which this particular instance of the operator
60
75
/// will check for leader election.
Original file line number Diff line number Diff line change @@ -12,8 +12,9 @@ internal class RbacBuilder : IRbacBuilder
12
12
private readonly List < Type > _componentTypes ;
13
13
14
14
private readonly bool _hasWebhooks ;
15
+ private readonly bool _hasLeaderElection ;
15
16
16
- public RbacBuilder ( IComponentRegistrar componentRegistrar )
17
+ public RbacBuilder ( IComponentRegistrar componentRegistrar , OperatorSettings settings )
17
18
{
18
19
var controllerTypes = componentRegistrar . ControllerRegistrations
19
20
. Select ( t => t . ControllerType )
@@ -37,6 +38,7 @@ public RbacBuilder(IComponentRegistrar componentRegistrar)
37
38
. ToList ( ) ;
38
39
39
40
_hasWebhooks = validatorTypes . Any ( ) || mutatorTypes . Any ( ) ;
41
+ _hasLeaderElection = settings . EnableLeaderElection ;
40
42
}
41
43
42
44
public V1ClusterRole BuildManagerRbac ( )
@@ -61,6 +63,16 @@ public V1ClusterRole BuildManagerRbac()
61
63
rules = rules . Concat ( servicePolicies ) . ToList ( ) ;
62
64
}
63
65
66
+ if ( _hasLeaderElection )
67
+ {
68
+ rules = rules
69
+ . Concat ( new EntityRbacAttribute ( typeof ( V1Lease ) ) { Verbs = RbacVerb . All } . CreateRbacPolicies ( ) )
70
+ . Concat (
71
+ new EntityRbacAttribute ( typeof ( V1Deployment ) ) { Verbs = RbacVerb . Get | RbacVerb . List }
72
+ . CreateRbacPolicies ( ) )
73
+ . ToList ( ) ;
74
+ }
75
+
64
76
return new V1ClusterRole (
65
77
null ,
66
78
$ "{ V1ClusterRole . KubeGroup } /{ V1ClusterRole . KubeApiVersion } ",
Original file line number Diff line number Diff line change @@ -9,7 +9,7 @@ public class Startup
9
9
{
10
10
public void ConfigureServices ( IServiceCollection services )
11
11
{
12
- services . AddKubernetesOperator ( ) . AddWebhookLocaltunnel ( ) ;
12
+ services . AddKubernetesOperator ( s => s . EnableLeaderElection = false ) . AddWebhookLocaltunnel ( ) ;
13
13
services . AddTransient < IManager , TestManager . TestManager > ( ) ;
14
14
}
15
15
You can’t perform that action at this time.
0 commit comments