Skip to content

Commit

Permalink
Fix Down Scale on RollingUpdate
Browse files Browse the repository at this point in the history
Return valid target number of replicas with E2E test.
  • Loading branch information
aLekSer committed May 31, 2019
1 parent 2f0e42d commit ef999b9
Show file tree
Hide file tree
Showing 2 changed files with 95 additions and 9 deletions.
24 changes: 15 additions & 9 deletions pkg/fleets/controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -223,7 +223,7 @@ func (c *Controller) loggerForFleetKey(key string) *logrus.Entry {
func (c *Controller) loggerForFleet(f *v1alpha1.Fleet) *logrus.Entry {
fleetName := "NilFleet"
if f != nil {
fleetName = f.Namespace + "/" + f.Name
fleetName = f.ObjectMeta.Namespace + "/" + f.ObjectMeta.Name
}
return c.loggerForFleetKey(fleetName).WithField("fleet", f)
}
Expand Down Expand Up @@ -278,6 +278,7 @@ func (c *Controller) syncFleet(key string) error {
}

active, rest := c.filterGameServerSetByActive(fleet, list)

// if there isn't an active gameServerSet, create one (but don't persist yet)
if active == nil {
c.loggerForFleet(fleet).Info("could not find active GameServerSet, creating")
Expand Down Expand Up @@ -416,14 +417,20 @@ func (c *Controller) rollingUpdateDeployment(fleet *stablev1alpha1.Fleet, active
// and returns what its replica value should be set to
func (c *Controller) rollingUpdateActive(fleet *stablev1alpha1.Fleet, active *stablev1alpha1.GameServerSet, rest []*stablev1alpha1.GameServerSet) (int32, error) {
replicas := active.Spec.Replicas
// always leave room for Allocated GameServers
sumAllocated := stablev1alpha1.SumStatusAllocatedReplicas(rest)

// if the active spec replicas are greater than or equal the fleet spec replicas, then we don't
// need to another rolling update upwards.
// Likewise if the active spec replicas don't equal the active status replicas, this means we are
// in the middle of a rolling update, and should wait for it to complete.
if active.Spec.Replicas >= fleet.Spec.Replicas || active.Spec.Replicas != active.Status.Replicas {

if active.Spec.Replicas != active.Status.Replicas {
return replicas, nil
}
if active.Spec.Replicas >= (fleet.Spec.Replicas - sumAllocated) {
return fleet.Spec.Replicas - sumAllocated, nil
}

r, err := intstr.GetValueFromIntOrPercent(fleet.Spec.Strategy.RollingUpdate.MaxSurge, int(fleet.Spec.Replicas), true)
if err != nil {
Expand All @@ -439,12 +446,9 @@ func (c *Controller) rollingUpdateActive(fleet *stablev1alpha1.Fleet, active *st
replicas = fleet.LowerBoundReplicas(replicas - (total - maxSurge))
}

// always leave room for Allocated GameServers
sumAllocated := stablev1alpha1.SumStatusAllocatedReplicas(rest)

// make room for allocated game servers, but not over the fleet replica count
if replicas+sumAllocated > fleet.Spec.Replicas {
replicas = fleet.LowerBoundReplicas(replicas - sumAllocated)
replicas = fleet.LowerBoundReplicas(fleet.Spec.Replicas - sumAllocated)
}

c.loggerForFleet(fleet).WithField("gameserverset", active.ObjectMeta.Name).WithField("replicas", replicas).
Expand Down Expand Up @@ -506,7 +510,10 @@ func (c *Controller) updateFleetStatus(fleet *stablev1alpha1.Fleet) error {
return err
}

fCopy := fleet.DeepCopy()
fCopy, err := c.fleetGetter.Fleets(fleet.ObjectMeta.Namespace).Get(fleet.ObjectMeta.GetName(), metav1.GetOptions{})
if err != nil {
return err
}
fCopy.Status.Replicas = 0
fCopy.Status.ReadyReplicas = 0
fCopy.Status.AllocatedReplicas = 0
Expand All @@ -516,8 +523,7 @@ func (c *Controller) updateFleetStatus(fleet *stablev1alpha1.Fleet) error {
fCopy.Status.ReadyReplicas += gsSet.Status.ReadyReplicas
fCopy.Status.AllocatedReplicas += gsSet.Status.AllocatedReplicas
}

_, err = c.fleetGetter.Fleets(fCopy.Namespace).UpdateStatus(fCopy)
_, err = c.fleetGetter.Fleets(fCopy.ObjectMeta.Namespace).UpdateStatus(fCopy)
return errors.Wrapf(err, "error updating status of fleet %s", fCopy.ObjectMeta.Name)
}

Expand Down
80 changes: 80 additions & 0 deletions test/e2e/fleet_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,86 @@ func TestCreateFullFleetAndCantFleetAllocate(t *testing.T) {
}
}

func TestFleetScaleUpEditAndScaleDown(t *testing.T) {
t.Parallel()

//Use scaleFleetPatch (true) or scaleFleetSubresource (false)
fixtures := []bool{true, false}

for _, usePatch := range fixtures {
t.Run("Use fleet Patch "+fmt.Sprint(usePatch), func(t *testing.T) {
alpha1 := framework.AgonesClient.StableV1alpha1()

flt := defaultFleet()
flt.Spec.Replicas = 1
flt, err := alpha1.Fleets(defaultNs).Create(flt)
if assert.Nil(t, err) {
defer alpha1.Fleets(defaultNs).Delete(flt.ObjectMeta.Name, nil) // nolint:errcheck
}

assert.Equal(t, int32(1), flt.Spec.Replicas)

framework.WaitForFleetCondition(t, flt, e2e.FleetReadyCount(flt.Spec.Replicas))

// scale up
const targetScale = 3
if usePatch {
flt = scaleFleetPatch(t, flt, targetScale)
assert.Equal(t, int32(targetScale), flt.Spec.Replicas)
} else {
flt = scaleFleetSubresource(t, flt, targetScale)
}

framework.WaitForFleetCondition(t, flt, e2e.FleetReadyCount(targetScale))

// get an allocation

fa := &v1alpha1.FleetAllocation{
ObjectMeta: metav1.ObjectMeta{GenerateName: "allocation-", Namespace: defaultNs},
Spec: v1alpha1.FleetAllocationSpec{
FleetName: flt.ObjectMeta.Name,
},
}

fa, err = alpha1.FleetAllocations(defaultNs).Create(fa)
assert.Nil(t, err)
assert.Equal(t, v1alpha1.GameServerStateAllocated, fa.Status.GameServer.Status.State)
framework.WaitForFleetCondition(t, flt, func(fleet *v1alpha1.Fleet) bool {
return fleet.Status.AllocatedReplicas == 1
})

flt, err = alpha1.Fleets(defaultNs).Get(flt.ObjectMeta.GetName(), metav1.GetOptions{})
assert.Nil(t, err)

fltCopy := flt.DeepCopy()
fltCopy.Spec.Template.Spec.Ports[0].ContainerPort++
flt, err = alpha1.Fleets(defaultNs).Update(fltCopy)
assert.Nil(t, err)
time.Sleep(4 * time.Second)
// scale down, with allocation
const scaleDownTarget = 1
if usePatch {
flt = scaleFleetPatch(t, flt, scaleDownTarget)
} else {
flt = scaleFleetSubresource(t, flt, scaleDownTarget)
}

// delete the allocated GameServer

framework.WaitForFleetCondition(t, flt, e2e.FleetReadyCount(0))
gp := int64(1)
err = alpha1.GameServers(defaultNs).Delete(fa.Status.GameServer.ObjectMeta.Name, &metav1.DeleteOptions{GracePeriodSeconds: &gp})
assert.Nil(t, err)

framework.WaitForFleetCondition(t, flt, e2e.FleetReadyCount(1))

framework.WaitForFleetCondition(t, flt, func(fleet *v1alpha1.Fleet) bool {
return fleet.Status.AllocatedReplicas == 0
})
})
}
}

func TestScaleFleetUpAndDownWithFleetAllocation(t *testing.T) {
t.Parallel()

Expand Down

0 comments on commit ef999b9

Please sign in to comment.