From 90ebc1ad297dcb9d6dd80d0e079f64a41788960d Mon Sep 17 00:00:00 2001 From: Prashanth Balasubramanian Date: Fri, 26 Jun 2015 17:55:14 -0700 Subject: [PATCH] Sort overlapping rcs --- pkg/controller/controller_utils.go | 13 ++++++ pkg/controller/replication_controller.go | 1 + pkg/controller/replication_controller_test.go | 42 +++++++++++++++++++ pkg/util/time.go | 5 +++ 4 files changed, 61 insertions(+) diff --git a/pkg/controller/controller_utils.go b/pkg/controller/controller_utils.go index f32403f3c7..f5fb686800 100644 --- a/pkg/controller/controller_utils.go +++ b/pkg/controller/controller_utils.go @@ -289,6 +289,19 @@ func (s activePods) Less(i, j int) bool { return false } +// overlappingControllers sorts a list of controllers by creation timestamp, using their names as a tie breaker. +type overlappingControllers []api.ReplicationController + +func (o overlappingControllers) Len() int { return len(o) } +func (o overlappingControllers) Swap(i, j int) { o[i], o[j] = o[j], o[i] } + +func (o overlappingControllers) Less(i, j int) bool { + if o[i].CreationTimestamp.Equal(o[j].CreationTimestamp) { + return o[i].Name < o[j].Name + } + return o[i].CreationTimestamp.Before(o[j].CreationTimestamp) +} + // filterActivePods returns pods that have not terminated. func filterActivePods(pods []api.Pod) []*api.Pod { var result []*api.Pod diff --git a/pkg/controller/replication_controller.go b/pkg/controller/replication_controller.go index ef153d8873..8e31c14a26 100644 --- a/pkg/controller/replication_controller.go +++ b/pkg/controller/replication_controller.go @@ -209,6 +209,7 @@ func (rm *ReplicationManager) getPodControllers(pod *api.Pod) *api.ReplicationCo glog.V(4).Infof("No controllers found for pod %v, replication manager will avoid syncing", pod.Name) return nil } + sort.Sort(overlappingControllers(controllers)) return &controllers[0] } diff --git a/pkg/controller/replication_controller_test.go b/pkg/controller/replication_controller_test.go index 6472ff5a06..f7f49a7699 100644 --- a/pkg/controller/replication_controller_test.go +++ b/pkg/controller/replication_controller_test.go @@ -1108,3 +1108,45 @@ func TestRCManagerNotReady(t *testing.T) { manager.syncReplicationController(rcKey) validateSyncReplication(t, &fakePodControl, 1, 0) } + +// shuffle returns a new shuffled list of container controllers. +func shuffle(controllers []*api.ReplicationController) []*api.ReplicationController { + numControllers := len(controllers) + randIndexes := rand.Perm(numControllers) + shuffled := make([]*api.ReplicationController, numControllers) + for i := 0; i < numControllers; i++ { + shuffled[i] = controllers[randIndexes[i]] + } + return shuffled +} + +func TestOverlappingRCs(t *testing.T) { + client := client.NewOrDie(&client.Config{Host: "", Version: testapi.Version()}) + + for i := 0; i < 5; i++ { + manager := NewReplicationManager(client, 10) + manager.podStoreSynced = alwaysReady + + // Create 10 rcs, shuffled them randomly and insert them into the rc manager's store + var controllers []*api.ReplicationController + for j := 1; j < 10; j++ { + controllerSpec := newReplicationController(1) + controllerSpec.CreationTimestamp = util.Date(2014, time.December, j, 0, 0, 0, 0, time.Local) + controllerSpec.Name = string(util.NewUUID()) + controllers = append(controllers, controllerSpec) + } + shuffledControllers := shuffle(controllers) + for j, _ := range shuffledControllers { + manager.controllerStore.Store.Add(shuffledControllers[j]) + } + // Add a pod and make sure only the oldest rc is synced + pods := newPodList(nil, 1, api.PodPending, controllers[0]) + rcKey := getKey(controllers[0], t) + + manager.addPod(&pods.Items[0]) + queueRC, _ := manager.queue.Get() + if queueRC != rcKey { + t.Fatalf("Expected to find key %v in queue, found %v", rcKey, queueRC) + } + } +} diff --git a/pkg/util/time.go b/pkg/util/time.go index 9b36bf8253..001a507763 100644 --- a/pkg/util/time.go +++ b/pkg/util/time.go @@ -59,6 +59,11 @@ func (t Time) Before(u Time) bool { return t.Time.Before(u.Time) } +// Equal reports whether the time instant t is equal to u. +func (t Time) Equal(u Time) bool { + return t.Time.Equal(u.Time) +} + // Unix returns the local time corresponding to the given Unix time // by wrapping time.Unix. func Unix(sec int64, nsec int64) Time {