@@ -2,43 +2,44 @@ package controller
2
2
3
3
import (
4
4
"fmt"
5
- "time"
5
+
6
+ "github.com/golang/glog"
6
7
7
8
"k8s.io/api/core/v1"
9
+ "k8s.io/apimachinery/pkg/api/errors"
8
10
"k8s.io/apimachinery/pkg/util/runtime"
9
- informers "k8s.io/client-go/informers/core/v1"
10
- kclientset "k8s.io/client-go/kubernetes"
11
+ utilruntime "k8s.io/apimachinery/pkg/util/runtime"
12
+ "k8s.io/apimachinery/pkg/util/sets"
13
+ corev1informers "k8s.io/client-go/informers/core/v1"
14
+ "k8s.io/client-go/kubernetes"
15
+ corev1listers "k8s.io/client-go/listers/core/v1"
11
16
"k8s.io/client-go/tools/cache"
12
17
"k8s.io/client-go/util/workqueue"
13
18
14
- "github.com/golang/glog"
15
- projectutil "github.com/openshift/origin/pkg/project/util"
19
+ projectapiv1 "github.com/openshift/api/project/v1"
16
20
)
17
21
18
22
// ProjectFinalizerController is responsible for participating in Kubernetes Namespace termination
19
23
type ProjectFinalizerController struct {
20
- client kclientset .Interface
24
+ client kubernetes .Interface
21
25
22
- queue workqueue.RateLimitingInterface
23
- maxRetries int
26
+ queue workqueue.RateLimitingInterface
24
27
25
- controller cache.Controller
26
- cache cache. Store
28
+ cacheSynced cache.InformerSynced
29
+ nsLister corev1listers. NamespaceLister
27
30
28
31
// extracted for testing
29
32
syncHandler func (key string ) error
30
33
}
31
34
32
- func NewProjectFinalizerController (namespaces informers .NamespaceInformer , client kclientset .Interface ) * ProjectFinalizerController {
35
+ func NewProjectFinalizerController (namespaces corev1informers .NamespaceInformer , client kubernetes .Interface ) * ProjectFinalizerController {
33
36
c := & ProjectFinalizerController {
34
- client : client ,
35
- controller : namespaces .Informer ().GetController (),
36
- cache : namespaces .Informer ().GetStore (),
37
- queue : workqueue .NewRateLimitingQueue (workqueue .DefaultControllerRateLimiter ()),
38
- maxRetries : 10 ,
37
+ client : client ,
38
+ cacheSynced : namespaces .Informer ().HasSynced ,
39
+ queue : workqueue .NewRateLimitingQueue (workqueue .DefaultControllerRateLimiter ()),
40
+ nsLister : namespaces .Lister (),
39
41
}
40
- namespaces .Informer ().AddEventHandlerWithResyncPeriod (
41
- // TODO: generalize naiveResourceEventHandler and use it here
42
+ namespaces .Informer ().AddEventHandler (
42
43
cache.ResourceEventHandlerFuncs {
43
44
AddFunc : func (obj interface {}) {
44
45
c .enqueueNamespace (obj )
@@ -47,7 +48,6 @@ func NewProjectFinalizerController(namespaces informers.NamespaceInformer, clien
47
48
c .enqueueNamespace (newObj )
48
49
},
49
50
},
50
- 10 * time .Minute ,
51
51
)
52
52
53
53
c .syncHandler = c .syncNamespace
@@ -60,7 +60,7 @@ func (c *ProjectFinalizerController) Run(stopCh <-chan struct{}, workers int) {
60
60
defer c .queue .ShutDown ()
61
61
62
62
// Wait for the stores to fill
63
- if ! cache .WaitForCacheSync (stopCh , c .controller . HasSynced ) {
63
+ if ! cache .WaitForCacheSync (stopCh , c .cacheSynced ) {
64
64
return
65
65
}
66
66
@@ -73,11 +73,12 @@ func (c *ProjectFinalizerController) Run(stopCh <-chan struct{}, workers int) {
73
73
}
74
74
75
75
func (c * ProjectFinalizerController ) enqueueNamespace (obj interface {}) {
76
- ns , ok := obj .(* v1.Namespace )
77
- if ! ok {
76
+ key , err := cache .DeletionHandlingMetaNamespaceKeyFunc (obj )
77
+ if err != nil {
78
+ utilruntime .HandleError (err )
78
79
return
79
80
}
80
- c .queue .Add (ns . Name )
81
+ c .queue .Add (key )
81
82
}
82
83
83
84
// worker runs a worker thread that just dequeues items, processes them, and marks them done.
@@ -113,29 +114,41 @@ func (c *ProjectFinalizerController) work() bool {
113
114
// syncNamespace will sync the namespace with the given key.
114
115
// This function is not meant to be invoked concurrently with the same key.
115
116
func (c * ProjectFinalizerController ) syncNamespace (key string ) error {
116
- item , exists , err := c .cache .GetByKey (key )
117
+ ns , err := c .nsLister .Get (key )
118
+ if errors .IsNotFound (err ) {
119
+ return nil
120
+ }
117
121
if err != nil {
118
122
return err
119
123
}
120
- if ! exists {
124
+
125
+ found := false
126
+ for _ , finalizerName := range ns .Spec .Finalizers {
127
+ if projectapiv1 .FinalizerOrigin == finalizerName {
128
+ found = true
129
+ }
130
+ }
131
+ if ! found {
121
132
return nil
122
133
}
123
- return c .finalize (item .(* v1.Namespace ))
134
+
135
+ return c .finalize (ns .DeepCopy ())
124
136
}
125
137
126
138
// finalize processes a namespace and deletes content in origin if its terminating
127
139
func (c * ProjectFinalizerController ) finalize (namespace * v1.Namespace ) error {
128
- // if namespace is not terminating, ignore it
129
- if namespace . Status . Phase != v1 . NamespaceTerminating {
130
- return nil
140
+ finalizerSet := sets . NewString ()
141
+ for i := range namespace . Spec . Finalizers {
142
+ finalizerSet . Insert ( string ( namespace . Spec . Finalizers [ i ]))
131
143
}
144
+ finalizerSet .Delete (string (projectapiv1 .FinalizerOrigin ))
132
145
133
- // if we already processed this namespace, ignore it
134
- if projectutil . Finalized ( namespace ) {
135
- return nil
146
+ namespace . Spec . Finalizers = make ([]v1. FinalizerName , 0 , len ( finalizerSet ))
147
+ for _ , value := range finalizerSet . List ( ) {
148
+ namespace . Spec . Finalizers = append ( namespace . Spec . Finalizers , v1 . FinalizerName ( value ))
136
149
}
137
150
138
151
// we have removed content, so mark it finalized by us
139
- _ , err := projectutil . Finalize ( c .client , namespace )
152
+ _ , err := c .client . Core (). Namespaces (). Finalize ( namespace )
140
153
return err
141
154
}
0 commit comments