Skip to content
This repository has been archived by the owner on Mar 28, 2020. It is now read-only.

Commit

Permalink
pkg/controller: Fix CR with same name in different namespaces
Browse files Browse the repository at this point in the history
This patch uses <namespace>/<cluster-name> as key to store the cluster in Controller struct to avoid over-writing same named CR's in different namespaces.

Fixes #1954

Please read https://github.com/coreos/etcd-operator/blob/master/CONTRIBUTING.md#contribution-flow
  • Loading branch information
hexfusion authored Dec 13, 2018
2 parents b3b2f83 + 041baa1 commit 65b572c
Show file tree
Hide file tree
Showing 5 changed files with 50 additions and 14 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@

### Fixed

- Fixed a bug where `same CR names` in different namespaces with cluster-wide operator were not working as expected [#2026](https://github.com/coreos/etcd-operator/pull/2026)

### Deprecated

### Security
Expand Down
2 changes: 1 addition & 1 deletion pkg/cluster/cluster.go
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ type Cluster struct {
}

func New(config Config, cl *api.EtcdCluster) *Cluster {
lg := logrus.WithField("pkg", "cluster").WithField("cluster-name", cl.Name)
lg := logrus.WithField("pkg", "cluster").WithField("cluster-name", cl.Name).WithField("cluster-namespace", cl.Namespace)

c := &Cluster{
logger: lg,
Expand Down
20 changes: 12 additions & 8 deletions pkg/controller/controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ func (c *Controller) handleClusterEvent(event *Event) (bool, error) {
if clus.Status.IsFailed() {
clustersFailed.Inc()
if event.Type == kwatch.Deleted {
delete(c.clusters, clus.Name)
delete(c.clusters, getNamespacedName(clus))
return false, nil
}
return false, fmt.Errorf("ignore failed cluster (%s). Please delete its CR", clus.Name)
Expand All @@ -87,30 +87,30 @@ func (c *Controller) handleClusterEvent(event *Event) (bool, error) {

switch event.Type {
case kwatch.Added:
if _, ok := c.clusters[clus.Name]; ok {
if _, ok := c.clusters[getNamespacedName(clus)]; ok {
return false, fmt.Errorf("unsafe state. cluster (%s) was created before but we received event (%s)", clus.Name, event.Type)
}

nc := cluster.New(c.makeClusterConfig(), clus)

c.clusters[clus.Name] = nc
c.clusters[getNamespacedName(clus)] = nc

clustersCreated.Inc()
clustersTotal.Inc()

case kwatch.Modified:
if _, ok := c.clusters[clus.Name]; !ok {
if _, ok := c.clusters[getNamespacedName(clus)]; !ok {
return false, fmt.Errorf("unsafe state. cluster (%s) was never created but we received event (%s)", clus.Name, event.Type)
}
c.clusters[clus.Name].Update(clus)
c.clusters[getNamespacedName(clus)].Update(clus)
clustersModified.Inc()

case kwatch.Deleted:
if _, ok := c.clusters[clus.Name]; !ok {
if _, ok := c.clusters[getNamespacedName(clus)]; !ok {
return false, fmt.Errorf("unsafe state. cluster (%s) was never created but we received event (%s)", clus.Name, event.Type)
}
c.clusters[clus.Name].Delete()
delete(c.clusters, clus.Name)
c.clusters[getNamespacedName(clus)].Delete()
delete(c.clusters, getNamespacedName(clus))
clustersDeleted.Inc()
clustersTotal.Dec()
}
Expand All @@ -132,3 +132,7 @@ func (c *Controller) initCRD() error {
}
return k8sutil.WaitCRDReady(c.KubeExtCli, api.EtcdClusterCRDName)
}

func getNamespacedName(c *api.EtcdCluster) string {
return fmt.Sprintf("%s%c%s", c.Namespace, '/', c.Name)
}
38 changes: 34 additions & 4 deletions pkg/controller/controller_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,14 +62,14 @@ func TestHandleClusterEventDeleteFailedCluster(t *testing.T) {
Object: clus,
}

c.clusters[name] = &cluster.Cluster{}
c.clusters[getNamespacedName(clus)] = &cluster.Cluster{}

if _, err := c.handleClusterEvent(e); err != nil {
t.Fatal(err)
}

if c.clusters[name] != nil {
t.Errorf("failed cluster not cleaned up after delete event, cluster struct: %v", c.clusters[name])
if c.clusters[getNamespacedName(clus)] != nil {
t.Errorf("failed cluster not cleaned up after delete event, cluster struct: %v", c.clusters[getNamespacedName(clus)])
}
}

Expand All @@ -78,7 +78,8 @@ func TestHandleClusterEventClusterwide(t *testing.T) {

clus := &api.EtcdCluster{
ObjectMeta: metav1.ObjectMeta{
Name: "test",
Name: "test",
Namespace: "a",
Annotations: map[string]string{
"etcd.database.coreos.com/scope": "clusterwide",
},
Expand Down Expand Up @@ -110,6 +111,35 @@ func TestHandleClusterEventClusterwideIgnored(t *testing.T) {
}
}

func TestHandleClusterEventClusterwideAddTwoCR(t *testing.T) {
c := New(Config{ClusterWide: true})
clusA := &api.EtcdCluster{
ObjectMeta: metav1.ObjectMeta{
Name: "test",
Namespace: "a",
},
}
clusB := &api.EtcdCluster{
ObjectMeta: metav1.ObjectMeta{
Name: "test",
Namespace: "b",
},
}
e := &Event{
Type: watch.Added,
Object: clusA,
}
ignored, errA := c.handleClusterEvent(e)
if !ignored && errA != nil {
t.Errorf("cluster should be Added")
}
e.Object = clusB
ignored, errB := c.handleClusterEvent(e)
if !ignored && errB != nil {
t.Errorf("cluster should be Added")
}
}

func TestHandleClusterEventNamespacedIgnored(t *testing.T) {
c := New(Config{})

Expand Down
2 changes: 1 addition & 1 deletion pkg/controller/informer.go
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ func (c *Controller) syncEtcdClus(clus *api.EtcdCluster) {
// re-watch or restart could give ADD event.
// If for an ADD event the cluster spec is invalid then it is not added to the local cache
// so modifying that cluster will result in another ADD event
if _, ok := c.clusters[clus.Name]; ok {
if _, ok := c.clusters[getNamespacedName(clus)]; ok {
ev.Type = kwatch.Modified
}

Expand Down

0 comments on commit 65b572c

Please sign in to comment.