4
4
"context"
5
5
"fmt"
6
6
"strings"
7
+ "sync"
7
8
"time"
8
9
9
10
"github.com/go-logr/logr"
@@ -51,10 +52,16 @@ type Config struct {
51
52
52
53
// NginxProvisioner handles provisioning nginx kubernetes resources.
53
54
type NginxProvisioner struct {
54
- store * store
55
- k8sClient client.Client
56
- baseLabelSelector metav1.LabelSelector
57
- cfg Config
55
+ store * store
56
+ k8sClient client.Client
57
+ // resourcesToDeleteOnStartup contains a list of Gateway names that no longer exist
58
+ // but have nginx resources tied to them that need to be deleted.
59
+ resourcesToDeleteOnStartup []types.NamespacedName
60
+ baseLabelSelector metav1.LabelSelector
61
+ cfg Config
62
+ leader bool
63
+
64
+ lock sync.RWMutex
58
65
}
59
66
60
67
// NewNginxProvisioner returns a new instance of a Provisioner that will deploy nginx resources.
@@ -76,10 +83,11 @@ func NewNginxProvisioner(
76
83
}
77
84
78
85
provisioner := & NginxProvisioner {
79
- k8sClient : mgr .GetClient (),
80
- store : store ,
81
- baseLabelSelector : selector ,
82
- cfg : cfg ,
86
+ k8sClient : mgr .GetClient (),
87
+ store : store ,
88
+ baseLabelSelector : selector ,
89
+ resourcesToDeleteOnStartup : []types.NamespacedName {},
90
+ cfg : cfg ,
83
91
}
84
92
85
93
handler , err := newEventHandler (store , provisioner , selector , cfg .GCName )
@@ -95,13 +103,53 @@ func NewNginxProvisioner(
95
103
return provisioner , eventLoop , nil
96
104
}
97
105
106
+ // Enable is called when the Pod becomes leader and allows the provisioner to manage resources.
107
+ func (p * NginxProvisioner ) Enable (ctx context.Context ) {
108
+ p .lock .Lock ()
109
+ p .leader = true
110
+ p .lock .Unlock ()
111
+
112
+ p .lock .RLock ()
113
+ for _ , gatewayNSName := range p .resourcesToDeleteOnStartup {
114
+ if err := p .deprovisionNginx (ctx , gatewayNSName ); err != nil {
115
+ p .cfg .Logger .Error (err , "error deprovisioning nginx resources on startup" )
116
+ }
117
+ }
118
+ p .lock .RUnlock ()
119
+
120
+ p .lock .Lock ()
121
+ p .resourcesToDeleteOnStartup = []types.NamespacedName {}
122
+ p .lock .Unlock ()
123
+ }
124
+
125
+ // isLeader returns whether or not this provisioner is the leader.
126
+ func (p * NginxProvisioner ) isLeader () bool {
127
+ p .lock .RLock ()
128
+ defer p .lock .RUnlock ()
129
+
130
+ return p .leader
131
+ }
132
+
133
+ // setResourceToDelete is called when there are resources to delete, but this pod is not leader.
134
+ // Once it becomes leader, it will delete those resources.
135
+ func (p * NginxProvisioner ) setResourceToDelete (gatewayNSName types.NamespacedName ) {
136
+ p .lock .Lock ()
137
+ defer p .lock .Unlock ()
138
+
139
+ p .resourcesToDeleteOnStartup = append (p .resourcesToDeleteOnStartup , gatewayNSName )
140
+ }
141
+
98
142
//nolint:gocyclo // will refactor at some point
99
143
func (p * NginxProvisioner ) provisionNginx (
100
144
ctx context.Context ,
101
145
resourceName string ,
102
146
gateway * gatewayv1.Gateway ,
103
147
nProxyCfg * graph.EffectiveNginxProxy ,
104
148
) error {
149
+ if ! p .isLeader () {
150
+ return nil
151
+ }
152
+
105
153
objects := p .buildNginxResourceObjects (resourceName , gateway , nProxyCfg )
106
154
107
155
p .cfg .Logger .Info (
@@ -208,6 +256,9 @@ func (p *NginxProvisioner) reprovisionNginx(
208
256
gateway * gatewayv1.Gateway ,
209
257
nProxyCfg * graph.EffectiveNginxProxy ,
210
258
) error {
259
+ if ! p .isLeader () {
260
+ return nil
261
+ }
211
262
objects := p .buildNginxResourceObjects (resourceName , gateway , nProxyCfg )
212
263
213
264
p .cfg .Logger .Info (
@@ -236,6 +287,10 @@ func (p *NginxProvisioner) reprovisionNginx(
236
287
}
237
288
238
289
func (p * NginxProvisioner ) deprovisionNginx (ctx context.Context , gatewayNSName types.NamespacedName ) error {
290
+ if ! p .isLeader () {
291
+ return nil
292
+ }
293
+
239
294
p .cfg .Logger .Info (
240
295
"Removing nginx resources for Gateway" ,
241
296
"name" , gatewayNSName .Name ,
0 commit comments