From be0718de4df52ef71836e3f4d9898b4752ae72f6 Mon Sep 17 00:00:00 2001 From: Mark Mandel Date: Wed, 6 Mar 2019 16:46:08 -0800 Subject: [PATCH] Refactor AllocationCounter to GameServerCounter Precursor to #638 - this moves the AllocationCounter code to a more central GameServerCounter (which I think is a better name) that tracks the number of Ready and Allocated GameServers that are available on each node. These details are useful for sorting for `Packed` scheduling strategies. Once this PR is completed, we can use this Count() values provided by this controller in the GameServerSet scale down logic, to ensure that GameServers on the least used nodes are removed first when using a Packed strategy. --- cmd/controller/main.go | 8 +- pkg/gameserverallocations/controller.go | 32 +++--- pkg/gameserverallocations/controller_test.go | 18 +-- pkg/gameserverallocations/find.go | 10 +- .../prenodecounter.go} | 75 +++++++------ .../prenodecounter_test.go} | 103 +++++++++--------- 6 files changed, 127 insertions(+), 119 deletions(-) rename pkg/{gameserverallocations/allocationcounter.go => gameservers/prenodecounter.go} (73%) rename pkg/{gameserverallocations/allocationcounter_test.go => gameservers/prenodecounter_test.go} (66%) diff --git a/cmd/controller/main.go b/cmd/controller/main.go index e07e5b9904..c7b1105848 100644 --- a/cmd/controller/main.go +++ b/cmd/controller/main.go @@ -184,6 +184,8 @@ func main() { allocationMutex := &sync.Mutex{} + gsCounter := gameservers.NewPerNodeCounter(kubeInformerFactory, agonesInformerFactory) + gsController := gameservers.NewController(wh, health, ctlConf.MinPort, ctlConf.MaxPort, ctlConf.SidecarImage, ctlConf.AlwaysPullSidecar, ctlConf.SidecarCPURequest, ctlConf.SidecarCPULimit, @@ -193,13 +195,13 @@ func main() { fleetController := fleets.NewController(wh, health, kubeClient, extClient, agonesClient, agonesInformerFactory) faController := fleetallocation.NewController(wh, allocationMutex, kubeClient, extClient, agonesClient, agonesInformerFactory) - gasController := gameserverallocations.NewController(wh, health, kubeClient, - kubeInformerFactory, extClient, agonesClient, agonesInformerFactory, topNGSForAllocation) + gasController := gameserverallocations.NewController(wh, health, gsCounter, topNGSForAllocation, + kubeClient, extClient, agonesClient, agonesInformerFactory) fasController := fleetautoscalers.NewController(wh, health, kubeClient, extClient, agonesClient, agonesInformerFactory) rs = append(rs, - httpsServer, gsController, gsSetController, fleetController, faController, fasController, gasController, server) + httpsServer, gsCounter, gsController, gsSetController, fleetController, faController, fasController, gasController, server) stop := signals.NewStopChannel() diff --git a/pkg/gameserverallocations/controller.go b/pkg/gameserverallocations/controller.go index 3138a76d99..48e641689f 100644 --- a/pkg/gameserverallocations/controller.go +++ b/pkg/gameserverallocations/controller.go @@ -27,6 +27,7 @@ import ( getterv1alpha1 "agones.dev/agones/pkg/client/clientset/versioned/typed/stable/v1alpha1" "agones.dev/agones/pkg/client/informers/externalversions" listerv1alpha1 "agones.dev/agones/pkg/client/listers/stable/v1alpha1" + "agones.dev/agones/pkg/gameservers" "agones.dev/agones/pkg/util/crd" "agones.dev/agones/pkg/util/logfields" "agones.dev/agones/pkg/util/runtime" @@ -43,7 +44,6 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/labels" "k8s.io/apimachinery/pkg/util/wait" - "k8s.io/client-go/informers" "k8s.io/client-go/kubernetes" "k8s.io/client-go/kubernetes/scheme" typedcorev1 "k8s.io/client-go/kubernetes/typed/core/v1" @@ -61,8 +61,12 @@ var ( // Controller is a the GameServerAllocation controller type Controller struct { - baseLogger *logrus.Entry - counter *AllocationCounter + baseLogger *logrus.Entry + counter *gameservers.PerNodeCounter + readyGameServers gameServerCacheEntry + // Instead of selecting the top one, controller selects a random one + // from the topNGameServerCount of Ready gameservers + topNGameServerCount int crdGetter v1beta1.CustomResourceDefinitionInterface gameServerSynced cache.InformerSynced gameServerGetter getterv1alpha1.GameServersGetter @@ -73,10 +77,6 @@ type Controller struct { workerqueue *workerqueue.WorkerQueue gsWorkerqueue *workerqueue.WorkerQueue recorder record.EventRecorder - readyGameServers gameServerCacheEntry - // Instead of selecting the top one, controller selects a random one - // from the topNGameServerCount of Ready gameservers - topNGameServerCount int } // gameserver cache to keep the Ready state gameserver. @@ -133,7 +133,7 @@ func (e *gameServerCacheEntry) Range(f func(key string, gs *v1alpha1.GameServer) // findComparator is a comparator function specifically for the // findReadyGameServerForAllocation method for determining // scheduling strategy -type findComparator func(bestCount, currentCount NodeCount) bool +type findComparator func(bestCount, currentCount gameservers.NodeCount) bool var allocationRetry = wait.Backoff{ Steps: 5, @@ -145,24 +145,24 @@ var allocationRetry = wait.Backoff{ // NewController returns a controller for a GameServerAllocation func NewController(wh *webhooks.WebHook, health healthcheck.Handler, + counter *gameservers.PerNodeCounter, + topNGameServerCnt int, kubeClient kubernetes.Interface, - kubeInformerFactory informers.SharedInformerFactory, extClient extclientset.Interface, agonesClient versioned.Interface, agonesInformerFactory externalversions.SharedInformerFactory, - topNGameServerCnt int, ) *Controller { agonesInformer := agonesInformerFactory.Stable().V1alpha1() c := &Controller{ - counter: NewAllocationCounter(kubeInformerFactory, agonesInformerFactory), + counter: counter, + topNGameServerCount: topNGameServerCnt, crdGetter: extClient.ApiextensionsV1beta1().CustomResourceDefinitions(), gameServerSynced: agonesInformer.GameServers().Informer().HasSynced, gameServerGetter: agonesClient.StableV1alpha1(), gameServerLister: agonesInformer.GameServers().Lister(), gameServerAllocationSynced: agonesInformer.GameServerAllocations().Informer().HasSynced, gameServerAllocationGetter: agonesClient.StableV1alpha1(), - topNGameServerCount: topNGameServerCnt, } c.baseLogger = runtime.NewLoggerWithType(c) c.workerqueue = workerqueue.NewWorkerQueue(c.syncDelete, c.baseLogger, logfields.GameServerAllocationKey, stable.GroupName+".GameServerAllocationController") @@ -217,13 +217,7 @@ func (c *Controller) Run(workers int, stop <-chan struct{}) error { return err } - err = c.counter.Run(stop) - if err != nil { - return err - } - c.stop = stop - c.baseLogger.Info("Wait for cache sync") if !cache.WaitForCacheSync(stop, c.gameServerAllocationSynced, c.gameServerSynced) { return errors.New("failed to wait for caches to sync") @@ -444,7 +438,7 @@ func (c *Controller) syncDelete(key string) error { // preferred selectors, as well as the passed in comparator func (c *Controller) findReadyGameServerForAllocation(gsa *v1alpha1.GameServerAllocation, comparator findComparator) (*v1alpha1.GameServer, error) { // track the best node count - var bestCount *NodeCount + var bestCount *gameservers.NodeCount // the current GameServer from the node with the most GameServers (allocated, ready) var bestGS *v1alpha1.GameServer diff --git a/pkg/gameserverallocations/controller_test.go b/pkg/gameserverallocations/controller_test.go index 2e880ec114..d2a4f7322e 100644 --- a/pkg/gameserverallocations/controller_test.go +++ b/pkg/gameserverallocations/controller_test.go @@ -24,6 +24,7 @@ import ( "time" "agones.dev/agones/pkg/apis/stable/v1alpha1" + "agones.dev/agones/pkg/gameservers" agtesting "agones.dev/agones/pkg/testing" "agones.dev/agones/pkg/util/webhooks" applypatch "github.com/evanphx/json-patch" @@ -186,7 +187,7 @@ func TestControllerAllocate(t *testing.T) { err := c.syncReadyGSServerCache() assert.Nil(t, err) - err = c.counter.Run(stop) + err = c.counter.Run(0, stop) assert.Nil(t, err) gsa := v1alpha1.GameServerAllocation{ObjectMeta: metav1.ObjectMeta{Name: "gsa-1"}, @@ -263,7 +264,7 @@ func TestControllerAllocatePriority(t *testing.T) { err := c.syncReadyGSServerCache() assert.Nil(t, err) - err = c.counter.Run(stop) + err = c.counter.Run(0, stop) assert.Nil(t, err) gas := &v1alpha1.GameServerAllocation{ObjectMeta: metav1.ObjectMeta{Name: "fa-1"}, @@ -351,7 +352,7 @@ func TestControllerWithoutAllocateMutex(t *testing.T) { err := c.syncReadyGSServerCache() assert.Nil(t, err) - err = c.counter.Run(stop) + err = c.counter.Run(0, stop) assert.Nil(t, err) wg := sync.WaitGroup{} @@ -417,7 +418,7 @@ func TestControllerFindPackedReadyGameServer(t *testing.T) { err := c.syncReadyGSServerCache() assert.Nil(t, err) - err = c.counter.Run(stop) + err = c.counter.Run(0, stop) assert.Nil(t, err) gs, err := c.findReadyGameServerForAllocation(gsa, packedComparator) @@ -479,7 +480,7 @@ func TestControllerFindPackedReadyGameServer(t *testing.T) { err := c.syncReadyGSServerCache() assert.Nil(t, err) - err = c.counter.Run(stop) + err = c.counter.Run(0, stop) assert.Nil(t, err) gs, err := c.findReadyGameServerForAllocation(prefGsa, packedComparator) @@ -544,7 +545,7 @@ func TestControllerFindPackedReadyGameServer(t *testing.T) { err := c.syncReadyGSServerCache() assert.Nil(t, err) - err = c.counter.Run(stop) + err = c.counter.Run(0, stop) assert.Nil(t, err) gs, err := c.findReadyGameServerForAllocation(gsa, packedComparator) @@ -601,7 +602,7 @@ func TestControllerFindDistributedReadyGameServer(t *testing.T) { err := c.syncReadyGSServerCache() assert.Nil(t, err) - err = c.counter.Run(stop) + err = c.counter.Run(0, stop) assert.Nil(t, err) gs, err := c.findReadyGameServerForAllocation(gsa, distributedComparator) @@ -808,7 +809,8 @@ func defaultFixtures(gsLen int) (*v1alpha1.Fleet, *v1alpha1.GameServerSet, []v1a func newFakeController() (*Controller, agtesting.Mocks) { m := agtesting.NewMocks() wh := webhooks.NewWebHook(http.NewServeMux()) - c := NewController(wh, healthcheck.NewHandler(), m.KubeClient, m.KubeInformerFactory, m.ExtClient, m.AgonesClient, m.AgonesInformerFactory, 1) + counter := gameservers.NewPerNodeCounter(m.KubeInformerFactory, m.AgonesInformerFactory) + c := NewController(wh, healthcheck.NewHandler(), counter, 1, m.KubeClient, m.ExtClient, m.AgonesClient, m.AgonesInformerFactory) c.recorder = m.FakeRecorder return c, m } diff --git a/pkg/gameserverallocations/find.go b/pkg/gameserverallocations/find.go index 88df2083d9..99cd257662 100644 --- a/pkg/gameserverallocations/find.go +++ b/pkg/gameserverallocations/find.go @@ -14,12 +14,14 @@ package gameserverallocations +import "agones.dev/agones/pkg/gameservers" + // packedComparator prioritises Nodes with GameServers that are allocated, and then Nodes with the most // Ready GameServers -- this will bin pack allocated game servers together. -func packedComparator(bestCount, currentCount NodeCount) bool { - if currentCount.allocated == bestCount.allocated && currentCount.ready > bestCount.ready { +func packedComparator(bestCount, currentCount gameservers.NodeCount) bool { + if currentCount.Allocated == bestCount.Allocated && currentCount.Ready > bestCount.Ready { return true - } else if currentCount.allocated > bestCount.allocated { + } else if currentCount.Allocated > bestCount.Allocated { return true } @@ -28,6 +30,6 @@ func packedComparator(bestCount, currentCount NodeCount) bool { // distributedComparator is the inverse of the packed comparator, // looking to distribute allocated gameservers on as many nodes as possible. -func distributedComparator(bestCount, currentCount NodeCount) bool { +func distributedComparator(bestCount, currentCount gameservers.NodeCount) bool { return !packedComparator(bestCount, currentCount) } diff --git a/pkg/gameserverallocations/allocationcounter.go b/pkg/gameservers/prenodecounter.go similarity index 73% rename from pkg/gameserverallocations/allocationcounter.go rename to pkg/gameservers/prenodecounter.go index f5a22a4182..483c6d4d61 100644 --- a/pkg/gameserverallocations/allocationcounter.go +++ b/pkg/gameservers/prenodecounter.go @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -package gameserverallocations +package gameservers import ( "sync" @@ -29,11 +29,11 @@ import ( "k8s.io/client-go/tools/cache" ) -// AllocationCounter counts how many Allocated and +// PerNodeCounter counts how many Allocated and // Ready GameServers currently exist on each node. -// This is useful for scheduling allocations on the -// right Nodes. -type AllocationCounter struct { +// This is useful for scheduling allocations, fleet management +// mostly under a Packed strategy +type PerNodeCounter struct { logger *logrus.Entry gameServerSynced cache.InformerSynced gameServerLister listerv1alpha1.GameServerLister @@ -44,19 +44,21 @@ type AllocationCounter struct { // NodeCount is just a convenience data structure for // keeping relevant GameServer counts about Nodes type NodeCount struct { - ready int64 - allocated int64 + // Ready is ready count + Ready int64 + // Allocated is allocated out + Allocated int64 } -// NewAllocationCounter returns a new AllocationCounter -func NewAllocationCounter( +// NewPerNodeCounter returns a new PerNodeCounter +func NewPerNodeCounter( kubeInformerFactory informers.SharedInformerFactory, - agonesInformerFactory externalversions.SharedInformerFactory) *AllocationCounter { + agonesInformerFactory externalversions.SharedInformerFactory) *PerNodeCounter { gameServers := agonesInformerFactory.Stable().V1alpha1().GameServers() gsInformer := gameServers.Informer() - ac := &AllocationCounter{ + ac := &PerNodeCounter{ gameServerSynced: gsInformer.HasSynced, gameServerLister: gameServers.Lister(), countMutex: sync.RWMutex{}, @@ -131,17 +133,18 @@ func NewAllocationCounter( } // Run sets up the current state GameServer counts across nodes -func (ac *AllocationCounter) Run(stop <-chan struct{}) error { - ac.countMutex.Lock() - defer ac.countMutex.Unlock() +// non blocking Run function. +func (pnc *PerNodeCounter) Run(_ int, stop <-chan struct{}) error { + pnc.countMutex.Lock() + defer pnc.countMutex.Unlock() - ac.logger.Info("Running") + pnc.logger.Info("Running") - if !cache.WaitForCacheSync(stop, ac.gameServerSynced) { + if !cache.WaitForCacheSync(stop, pnc.gameServerSynced) { return errors.New("failed to wait for caches to sync") } - gsList, err := ac.gameServerLister.List(labels.Everything()) + gsList, err := pnc.gameServerLister.List(labels.Everything()) if err != nil { return errors.Wrap(err, "error attempting to list all GameServers") } @@ -155,49 +158,49 @@ func (ac *AllocationCounter) Run(stop <-chan struct{}) error { switch gs.Status.State { case v1alpha1.GameServerStateReady: - counts[gs.Status.NodeName].ready++ + counts[gs.Status.NodeName].Ready++ case v1alpha1.GameServerStateAllocated: - counts[gs.Status.NodeName].allocated++ + counts[gs.Status.NodeName].Allocated++ } } - ac.counts = counts + pnc.counts = counts return nil } // Counts returns the NodeCount map in a thread safe way -func (ac *AllocationCounter) Counts() map[string]NodeCount { - ac.countMutex.RLock() - defer ac.countMutex.RUnlock() +func (pnc *PerNodeCounter) Counts() map[string]NodeCount { + pnc.countMutex.RLock() + defer pnc.countMutex.RUnlock() - result := make(map[string]NodeCount, len(ac.counts)) + result := make(map[string]NodeCount, len(pnc.counts)) // return a copy, so it's thread safe - for k, v := range ac.counts { + for k, v := range pnc.counts { result[k] = *v } return result } -func (ac *AllocationCounter) inc(gs *v1alpha1.GameServer, ready, allocated int64) { - ac.countMutex.Lock() - defer ac.countMutex.Unlock() +func (pnc *PerNodeCounter) inc(gs *v1alpha1.GameServer, ready, allocated int64) { + pnc.countMutex.Lock() + defer pnc.countMutex.Unlock() - _, ok := ac.counts[gs.Status.NodeName] + _, ok := pnc.counts[gs.Status.NodeName] if !ok { - ac.counts[gs.Status.NodeName] = &NodeCount{} + pnc.counts[gs.Status.NodeName] = &NodeCount{} } - ac.counts[gs.Status.NodeName].allocated += allocated - ac.counts[gs.Status.NodeName].ready += ready + pnc.counts[gs.Status.NodeName].Allocated += allocated + pnc.counts[gs.Status.NodeName].Ready += ready // just in case - if ac.counts[gs.Status.NodeName].allocated < 0 { - ac.counts[gs.Status.NodeName].allocated = 0 + if pnc.counts[gs.Status.NodeName].Allocated < 0 { + pnc.counts[gs.Status.NodeName].Allocated = 0 } - if ac.counts[gs.Status.NodeName].ready < 0 { - ac.counts[gs.Status.NodeName].ready = 0 + if pnc.counts[gs.Status.NodeName].Ready < 0 { + pnc.counts[gs.Status.NodeName].Ready = 0 } } diff --git a/pkg/gameserverallocations/allocationcounter_test.go b/pkg/gameservers/prenodecounter_test.go similarity index 66% rename from pkg/gameserverallocations/allocationcounter_test.go rename to pkg/gameservers/prenodecounter_test.go index 772196b6b3..e74f9282c6 100644 --- a/pkg/gameserverallocations/allocationcounter_test.go +++ b/pkg/gameservers/prenodecounter_test.go @@ -1,4 +1,4 @@ -// Copyright 2018 Google Inc. All Rights Reserved. +// Copyright 2019 Google Inc. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -12,27 +12,32 @@ // See the License for the specific language governing permissions and // limitations under the License. -package gameserverallocations +package gameservers import ( "testing" - "k8s.io/apimachinery/pkg/runtime" - "agones.dev/agones/pkg/apis/stable/v1alpha1" agtesting "agones.dev/agones/pkg/testing" "github.com/stretchr/testify/assert" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/watch" k8stesting "k8s.io/client-go/testing" "k8s.io/client-go/tools/cache" ) -func TestAllocationCounterGameServerEvents(t *testing.T) { +const ( + defaultNs = "default" + name1 = "node1" + name2 = "node2" +) + +func TestPerNodeCounterGameServerEvents(t *testing.T) { t.Parallel() - ac, m := newFakeAllocationCounter() + pnc, m := newFakePerNodeCounter() watch := watch.NewFake() m.AgonesClient.AddWatchReactor("gameservers", k8stesting.DefaultWatchReactor(watch, nil)) @@ -41,79 +46,79 @@ func TestAllocationCounterGameServerEvents(t *testing.T) { stop, cancel := agtesting.StartInformers(m) defer cancel() - assert.Empty(t, ac.Counts()) + assert.Empty(t, pnc.Counts()) gs := &v1alpha1.GameServer{ ObjectMeta: metav1.ObjectMeta{Name: "gs1", Namespace: defaultNs}, Status: v1alpha1.GameServerStatus{ - State: v1alpha1.GameServerStateStarting, NodeName: n1}} + State: v1alpha1.GameServerStateStarting, NodeName: name1}} watch.Add(gs.DeepCopy()) cache.WaitForCacheSync(stop, hasSynced) - assert.Empty(t, ac.Counts()) + assert.Empty(t, pnc.Counts()) gs.Status.State = v1alpha1.GameServerStateReady watch.Add(gs.DeepCopy()) cache.WaitForCacheSync(stop, hasSynced) - counts := ac.Counts() + counts := pnc.Counts() assert.Len(t, counts, 1) - assert.Equal(t, int64(1), counts[n1].ready) - assert.Equal(t, int64(0), counts[n1].allocated) + assert.Equal(t, int64(1), counts[name1].Ready) + assert.Equal(t, int64(0), counts[name1].Allocated) gs.Status.State = v1alpha1.GameServerStateAllocated watch.Add(gs.DeepCopy()) cache.WaitForCacheSync(stop, hasSynced) - counts = ac.Counts() + counts = pnc.Counts() assert.Len(t, counts, 1) - assert.Equal(t, int64(0), counts[n1].ready) - assert.Equal(t, int64(1), counts[n1].allocated) + assert.Equal(t, int64(0), counts[name1].Ready) + assert.Equal(t, int64(1), counts[name1].Allocated) gs.Status.State = v1alpha1.GameServerStateShutdown watch.Add(gs.DeepCopy()) cache.WaitForCacheSync(stop, hasSynced) - counts = ac.Counts() + counts = pnc.Counts() assert.Len(t, counts, 1) - assert.Equal(t, int64(0), counts[n1].ready) - assert.Equal(t, int64(0), counts[n1].allocated) + assert.Equal(t, int64(0), counts[name1].Ready) + assert.Equal(t, int64(0), counts[name1].Allocated) gs.ObjectMeta.Name = "gs2" gs.Status.State = v1alpha1.GameServerStateReady - gs.Status.NodeName = n2 + gs.Status.NodeName = name2 watch.Add(gs.DeepCopy()) cache.WaitForCacheSync(stop, hasSynced) - counts = ac.Counts() + counts = pnc.Counts() assert.Len(t, counts, 2) - assert.Equal(t, int64(0), counts[n1].ready) - assert.Equal(t, int64(0), counts[n1].allocated) - assert.Equal(t, int64(1), counts[n2].ready) - assert.Equal(t, int64(0), counts[n2].allocated) + assert.Equal(t, int64(0), counts[name1].Ready) + assert.Equal(t, int64(0), counts[name1].Allocated) + assert.Equal(t, int64(1), counts[name2].Ready) + assert.Equal(t, int64(0), counts[name2].Allocated) gs.ObjectMeta.Name = "gs3" // not likely, but to test the flow gs.Status.State = v1alpha1.GameServerStateAllocated - gs.Status.NodeName = n2 + gs.Status.NodeName = name2 watch.Add(gs.DeepCopy()) cache.WaitForCacheSync(stop, hasSynced) - counts = ac.Counts() + counts = pnc.Counts() assert.Len(t, counts, 2) - assert.Equal(t, int64(0), counts[n1].ready) - assert.Equal(t, int64(0), counts[n1].allocated) - assert.Equal(t, int64(1), counts[n2].ready) - assert.Equal(t, int64(1), counts[n2].allocated) + assert.Equal(t, int64(0), counts[name1].Ready) + assert.Equal(t, int64(0), counts[name1].Allocated) + assert.Equal(t, int64(1), counts[name2].Ready) + assert.Equal(t, int64(1), counts[name2].Allocated) } -func TestAllocationCountNodeEvents(t *testing.T) { +func TestPerNodeCounterNodeEvents(t *testing.T) { t.Parallel() - ac, m := newFakeAllocationCounter() + pnc, m := newFakePerNodeCounter() gsWatch := watch.NewFake() nodeWatch := watch.NewFake() @@ -126,32 +131,32 @@ func TestAllocationCountNodeEvents(t *testing.T) { stop, cancel := agtesting.StartInformers(m) defer cancel() - assert.Empty(t, ac.Counts()) + assert.Empty(t, pnc.Counts()) gs := &v1alpha1.GameServer{ ObjectMeta: metav1.ObjectMeta{Name: "gs1", Namespace: defaultNs}, Status: v1alpha1.GameServerStatus{ - State: v1alpha1.GameServerStateReady, NodeName: n1}} - node := &corev1.Node{ObjectMeta: metav1.ObjectMeta{Namespace: defaultNs, Name: n1}} + State: v1alpha1.GameServerStateReady, NodeName: name1}} + node := &corev1.Node{ObjectMeta: metav1.ObjectMeta{Namespace: defaultNs, Name: name1}} gsWatch.Add(gs.DeepCopy()) nodeWatch.Add(node.DeepCopy()) cache.WaitForCacheSync(stop, gsSynced, nodeSynced) - assert.Len(t, ac.Counts(), 1) + assert.Len(t, pnc.Counts(), 1) nodeWatch.Delete(node.DeepCopy()) cache.WaitForCacheSync(stop, nodeSynced) - assert.Empty(t, ac.Counts()) + assert.Empty(t, pnc.Counts()) } -func TestAllocationCounterRun(t *testing.T) { +func TestPerNodeCounterRun(t *testing.T) { t.Parallel() - ac, m := newFakeAllocationCounter() + pnc, m := newFakePerNodeCounter() gs1 := &v1alpha1.GameServer{ ObjectMeta: metav1.ObjectMeta{Name: "gs1", Namespace: defaultNs}, Status: v1alpha1.GameServerStatus{ - State: v1alpha1.GameServerStateReady, NodeName: n1}} + State: v1alpha1.GameServerStateReady, NodeName: name1}} gs2 := gs1.DeepCopy() gs2.ObjectMeta.Name = "gs2" @@ -160,7 +165,7 @@ func TestAllocationCounterRun(t *testing.T) { gs3 := gs1.DeepCopy() gs3.ObjectMeta.Name = "gs3" gs3.Status.State = v1alpha1.GameServerStateStarting - gs3.Status.NodeName = n2 + gs3.Status.NodeName = name2 gs4 := gs1.DeepCopy() gs4.ObjectMeta.Name = "gs4" @@ -173,21 +178,21 @@ func TestAllocationCounterRun(t *testing.T) { stop, cancel := agtesting.StartInformers(m) defer cancel() - err := ac.Run(stop) + err := pnc.Run(0, stop) assert.Nil(t, err) - counts := ac.Counts() + counts := pnc.Counts() assert.Len(t, counts, 2) - assert.Equal(t, int64(1), counts[n1].ready) - assert.Equal(t, int64(2), counts[n1].allocated) - assert.Equal(t, int64(0), counts[n2].ready) - assert.Equal(t, int64(0), counts[n2].allocated) + assert.Equal(t, int64(1), counts[name1].Ready) + assert.Equal(t, int64(2), counts[name1].Allocated) + assert.Equal(t, int64(0), counts[name2].Ready) + assert.Equal(t, int64(0), counts[name2].Allocated) } // newFakeController returns a controller, backed by the fake Clientset -func newFakeAllocationCounter() (*AllocationCounter, agtesting.Mocks) { +func newFakePerNodeCounter() (*PerNodeCounter, agtesting.Mocks) { m := agtesting.NewMocks() - c := NewAllocationCounter(m.KubeInformerFactory, m.AgonesInformerFactory) + c := NewPerNodeCounter(m.KubeInformerFactory, m.AgonesInformerFactory) return c, m }