Skip to content

Commit 946d766

Browse files
Merge pull request #20300 from deads2k/rebase-05-origin-finalizer
strip off the old openshift namespace finalizer
2 parents 20aa554 + a18f846 commit 946d766

File tree

5 files changed

+115
-168
lines changed

5 files changed

+115
-168
lines changed

pkg/oc/cli/cmd/project.go

-13
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
package cmd
22

33
import (
4-
"bytes"
54
"errors"
65
"fmt"
76
"net/url"
@@ -358,18 +357,6 @@ func getProjects(projectClient projectclient.ProjectInterface, kClient kclientse
358357
return projects.Items, nil
359358
}
360359

361-
func clusterAndAuthEquality(clientCfg *restclient.Config, cluster clientcmdapi.Cluster, authInfo clientcmdapi.AuthInfo) bool {
362-
return cluster.Server == clientCfg.Host &&
363-
cluster.InsecureSkipTLSVerify == clientCfg.Insecure &&
364-
cluster.CertificateAuthority == clientCfg.CAFile &&
365-
bytes.Equal(cluster.CertificateAuthorityData, clientCfg.CAData) &&
366-
authInfo.Token == clientCfg.BearerToken &&
367-
authInfo.ClientCertificate == clientCfg.TLSClientConfig.CertFile &&
368-
bytes.Equal(authInfo.ClientCertificateData, clientCfg.TLSClientConfig.CertData) &&
369-
authInfo.ClientKey == clientCfg.TLSClientConfig.KeyFile &&
370-
bytes.Equal(authInfo.ClientKeyData, clientCfg.TLSClientConfig.KeyData)
371-
}
372-
373360
// TODO these kind of funcs could be moved to some kind of clientcmd util
374361
func hasMultipleServers(config clientcmdapi.Config) bool {
375362
server := ""

pkg/project/controller/project_finalizer_controller.go

+46-33
Original file line numberDiff line numberDiff line change
@@ -2,43 +2,44 @@ package controller
22

33
import (
44
"fmt"
5-
"time"
5+
6+
"github.com/golang/glog"
67

78
"k8s.io/api/core/v1"
9+
"k8s.io/apimachinery/pkg/api/errors"
810
"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"
1116
"k8s.io/client-go/tools/cache"
1217
"k8s.io/client-go/util/workqueue"
1318

14-
"github.com/golang/glog"
15-
projectutil "github.com/openshift/origin/pkg/project/util"
19+
projectapiv1 "github.com/openshift/api/project/v1"
1620
)
1721

1822
// ProjectFinalizerController is responsible for participating in Kubernetes Namespace termination
1923
type ProjectFinalizerController struct {
20-
client kclientset.Interface
24+
client kubernetes.Interface
2125

22-
queue workqueue.RateLimitingInterface
23-
maxRetries int
26+
queue workqueue.RateLimitingInterface
2427

25-
controller cache.Controller
26-
cache cache.Store
28+
cacheSynced cache.InformerSynced
29+
nsLister corev1listers.NamespaceLister
2730

2831
// extracted for testing
2932
syncHandler func(key string) error
3033
}
3134

32-
func NewProjectFinalizerController(namespaces informers.NamespaceInformer, client kclientset.Interface) *ProjectFinalizerController {
35+
func NewProjectFinalizerController(namespaces corev1informers.NamespaceInformer, client kubernetes.Interface) *ProjectFinalizerController {
3336
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(),
3941
}
40-
namespaces.Informer().AddEventHandlerWithResyncPeriod(
41-
// TODO: generalize naiveResourceEventHandler and use it here
42+
namespaces.Informer().AddEventHandler(
4243
cache.ResourceEventHandlerFuncs{
4344
AddFunc: func(obj interface{}) {
4445
c.enqueueNamespace(obj)
@@ -47,7 +48,6 @@ func NewProjectFinalizerController(namespaces informers.NamespaceInformer, clien
4748
c.enqueueNamespace(newObj)
4849
},
4950
},
50-
10*time.Minute,
5151
)
5252

5353
c.syncHandler = c.syncNamespace
@@ -60,7 +60,7 @@ func (c *ProjectFinalizerController) Run(stopCh <-chan struct{}, workers int) {
6060
defer c.queue.ShutDown()
6161

6262
// Wait for the stores to fill
63-
if !cache.WaitForCacheSync(stopCh, c.controller.HasSynced) {
63+
if !cache.WaitForCacheSync(stopCh, c.cacheSynced) {
6464
return
6565
}
6666

@@ -73,11 +73,12 @@ func (c *ProjectFinalizerController) Run(stopCh <-chan struct{}, workers int) {
7373
}
7474

7575
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)
7879
return
7980
}
80-
c.queue.Add(ns.Name)
81+
c.queue.Add(key)
8182
}
8283

8384
// worker runs a worker thread that just dequeues items, processes them, and marks them done.
@@ -113,29 +114,41 @@ func (c *ProjectFinalizerController) work() bool {
113114
// syncNamespace will sync the namespace with the given key.
114115
// This function is not meant to be invoked concurrently with the same key.
115116
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+
}
117121
if err != nil {
118122
return err
119123
}
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 {
121132
return nil
122133
}
123-
return c.finalize(item.(*v1.Namespace))
134+
135+
return c.finalize(ns.DeepCopy())
124136
}
125137

126138
// finalize processes a namespace and deletes content in origin if its terminating
127139
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]))
131143
}
144+
finalizerSet.Delete(string(projectapiv1.FinalizerOrigin))
132145

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))
136149
}
137150

138151
// 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)
140153
return err
141154
}

pkg/project/controller/project_finalizer_controller_test.go

+9-3
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,10 @@ import (
66
"k8s.io/api/core/v1"
77
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
88
"k8s.io/apimachinery/pkg/runtime/schema"
9+
"k8s.io/client-go/kubernetes/fake"
910
clientgotesting "k8s.io/client-go/testing"
1011

1112
projectapiv1 "github.com/openshift/api/project/v1"
12-
"k8s.io/client-go/kubernetes/fake"
1313
)
1414

1515
func TestSyncNamespaceThatIsTerminating(t *testing.T) {
@@ -74,12 +74,18 @@ func TestSyncNamespaceThatIsActive(t *testing.T) {
7474
if err != nil {
7575
t.Errorf("Unexpected error when handling namespace %v", err)
7676
}
77+
expectedActionSet := []clientgotesting.Action{
78+
clientgotesting.NewListAction(
79+
schema.GroupVersionResource{Group: "", Version: "v1", Resource: "namespace"},
80+
schema.GroupVersionKind{Group: "", Version: "v1", Kind: "Namespace"},
81+
"", metav1.ListOptions{}),
82+
}
7783
kubeActionSet := []clientgotesting.Action{}
7884
for i := range mockKubeClient.Actions() {
7985
kubeActionSet = append(kubeActionSet, mockKubeClient.Actions()[i])
8086
}
8187

82-
if (len(kubeActionSet)) != 0 {
83-
t.Errorf("Expected no actions from contoller, but got: %#v", kubeActionSet)
88+
if (len(kubeActionSet)) != len(expectedActionSet) {
89+
t.Errorf("Expected actions: %v, but got: %v", expectedActionSet, kubeActionSet)
8490
}
8591
}

pkg/project/util/util.go

+1-112
Original file line numberDiff line numberDiff line change
@@ -1,122 +1,11 @@
11
package util
22

33
import (
4-
"k8s.io/api/core/v1"
5-
kerrors "k8s.io/apimachinery/pkg/api/errors"
6-
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
7-
"k8s.io/apimachinery/pkg/util/sets"
8-
clientset "k8s.io/client-go/kubernetes"
9-
kapi "k8s.io/kubernetes/pkg/apis/core"
10-
"k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset"
11-
12-
projectapiv1 "github.com/openshift/api/project/v1"
134
oapi "github.com/openshift/origin/pkg/api"
145
projectapi "github.com/openshift/origin/pkg/project/apis/project"
6+
kapi "k8s.io/kubernetes/pkg/apis/core"
157
)
168

17-
// Associated returns true if the spec.finalizers contains the origin finalizer
18-
func Associated(namespace *kapi.Namespace) bool {
19-
for i := range namespace.Spec.Finalizers {
20-
if projectapi.FinalizerOrigin == namespace.Spec.Finalizers[i] {
21-
return true
22-
}
23-
}
24-
return false
25-
}
26-
27-
// Associate adds the origin finalizer to spec.finalizers if its not there already
28-
func Associate(kubeClient internalclientset.Interface, namespace *kapi.Namespace) (*kapi.Namespace, error) {
29-
if Associated(namespace) {
30-
return namespace, nil
31-
}
32-
return finalizeInternal(kubeClient, namespace, true)
33-
}
34-
35-
// Finalized returns true if the spec.finalizers does not contain the origin finalizer
36-
func Finalized(namespace *v1.Namespace) bool {
37-
for i := range namespace.Spec.Finalizers {
38-
if projectapiv1.FinalizerOrigin == namespace.Spec.Finalizers[i] {
39-
return false
40-
}
41-
}
42-
return true
43-
}
44-
45-
// Finalize will remove the origin finalizer from the namespace
46-
func Finalize(kubeClient clientset.Interface, namespace *v1.Namespace) (result *v1.Namespace, err error) {
47-
if Finalized(namespace) {
48-
return namespace, nil
49-
}
50-
51-
// there is a potential for a resource conflict with base kubernetes finalizer
52-
// as a result, we handle resource conflicts in case multiple finalizers try
53-
// to finalize at same time
54-
for {
55-
result, err = finalizeInternalV1(kubeClient, namespace, false)
56-
if err == nil {
57-
return result, nil
58-
}
59-
60-
if !kerrors.IsConflict(err) {
61-
return nil, err
62-
}
63-
64-
namespace, err = kubeClient.Core().Namespaces().Get(namespace.Name, metav1.GetOptions{})
65-
if err != nil {
66-
return nil, err
67-
}
68-
}
69-
}
70-
71-
// finalizeInternal will update the namespace finalizer list to either have or not have origin finalizer
72-
// TODO: remove me
73-
func finalizeInternal(kubeClient internalclientset.Interface, namespace *kapi.Namespace, withOrigin bool) (*kapi.Namespace, error) {
74-
namespaceFinalize := kapi.Namespace{}
75-
namespaceFinalize.ObjectMeta = namespace.ObjectMeta
76-
namespaceFinalize.Spec = namespace.Spec
77-
78-
finalizerSet := sets.NewString()
79-
for i := range namespace.Spec.Finalizers {
80-
finalizerSet.Insert(string(namespace.Spec.Finalizers[i]))
81-
}
82-
83-
if withOrigin {
84-
finalizerSet.Insert(string(projectapi.FinalizerOrigin))
85-
} else {
86-
finalizerSet.Delete(string(projectapi.FinalizerOrigin))
87-
}
88-
89-
namespaceFinalize.Spec.Finalizers = make([]kapi.FinalizerName, 0, len(finalizerSet))
90-
for _, value := range finalizerSet.List() {
91-
namespaceFinalize.Spec.Finalizers = append(namespaceFinalize.Spec.Finalizers, kapi.FinalizerName(value))
92-
}
93-
return kubeClient.Core().Namespaces().Finalize(&namespaceFinalize)
94-
}
95-
96-
// finalizeInternalV1 will update the namespace finalizer list to either have or not have origin finalizer
97-
func finalizeInternalV1(kubeClient clientset.Interface, namespace *v1.Namespace, withOrigin bool) (*v1.Namespace, error) {
98-
namespaceFinalize := v1.Namespace{}
99-
namespaceFinalize.ObjectMeta = namespace.ObjectMeta
100-
namespaceFinalize.Spec = namespace.Spec
101-
102-
finalizerSet := sets.NewString()
103-
for i := range namespace.Spec.Finalizers {
104-
finalizerSet.Insert(string(namespace.Spec.Finalizers[i]))
105-
}
106-
107-
if withOrigin {
108-
finalizerSet.Insert(string(projectapiv1.FinalizerOrigin))
109-
} else {
110-
finalizerSet.Delete(string(projectapiv1.FinalizerOrigin))
111-
}
112-
113-
namespaceFinalize.Spec.Finalizers = make([]v1.FinalizerName, 0, len(finalizerSet))
114-
for _, value := range finalizerSet.List() {
115-
namespaceFinalize.Spec.Finalizers = append(namespaceFinalize.Spec.Finalizers, v1.FinalizerName(value))
116-
}
117-
return kubeClient.Core().Namespaces().Finalize(&namespaceFinalize)
118-
}
119-
1209
// ConvertNamespace transforms a Namespace into a Project
12110
func ConvertNamespace(namespace *kapi.Namespace) *projectapi.Project {
12211
return &projectapi.Project{

0 commit comments

Comments
 (0)