Skip to content

Commit

Permalink
Metadata propagation from fleet allocation to game server
Browse files Browse the repository at this point in the history
In the fleet allocation configuration you can add optional custom metadata that will be added to the game server in the moment of allocation

Generated files
  • Loading branch information
Victor Prodan authored and markmandel committed Jul 31, 2018
1 parent f90b55a commit 54e374b
Show file tree
Hide file tree
Showing 6 changed files with 106 additions and 10 deletions.
11 changes: 11 additions & 0 deletions docs/fleet_spec.md
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,14 @@ spec:
# The name of the fleet to allocate from. Must be an existing Fleet in the same namespace
# as this FleetAllocation
fleetName: fleet-example
# Custom metadata that is added to game server status in the moment of allocation
# You can use this to tell the server necessary session data
# ⚠️⚠️⚠️ **This is currently a development feature and has not been released** ⚠️⚠️⚠️
metadata:
labels:
mode: deathmatch
annotations:
map: garden22
```

We recommend using `metadata > generateName`, to declare to Kubernetes that a unique
Expand All @@ -88,3 +96,6 @@ The `spec` field is the actual `FleetAllocation` specification and it is compose

- `fleetName` is the name of an existing Fleet. If this doesn't exist, and error will be returned
when the `FleetAllocation` is created
- `metadata` is an optional list of custom labels and/or annotations that will be used to patch
the game server's metadata in the moment of allocation.
⚠️⚠️⚠️ **This is currently a development feature and has not been released** ⚠️⚠️⚠️
9 changes: 8 additions & 1 deletion examples/fleetallocation.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -28,4 +28,11 @@ metadata:
spec:
# The name of the fleet to allocate from. Must be an existing Fleet in the same namespace
# as this FleetAllocation
fleetName: fleet-example
fleetName: fleet-example
# Custom metadata that is added to game server status in the moment of allocation
# You can use this to tell the server necessary session data
metadata:
labels:
mode: deathmatch
annotations:
map: garden22
9 changes: 8 additions & 1 deletion pkg/apis/stable/v1alpha1/fleetallocation.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,14 @@ type FleetAllocationList struct {
// FleetAllocationSpec is the spec for a Fleet
// Allocation
type FleetAllocationSpec struct {
FleetName string `json:"fleetName"`
FleetName string `json:"fleetName"`
MetaPatch FleetAllocationMeta `json:"metadata,omitempty"`
}

// FleetAllocationMeta is the metadata used to patch the GameServer metadata on allocation
type FleetAllocationMeta struct {
Labels map[string]string `json:"labels,omitempty"`
Annotations map[string]string `json:"annotations,omitempty"`
}

// FleetAllocationStatus will contain the
Expand Down
33 changes: 32 additions & 1 deletion pkg/apis/stable/v1alpha1/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

30 changes: 28 additions & 2 deletions pkg/fleetallocation/controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@ func (c *Controller) creationMutationHandler(review admv1beta1.AdmissionReview)
return review, errors.Wrapf(err, "error retrieving fleet %s", fa.Name)
}

gs, err := c.allocate(fleet)
gs, err := c.allocate(fleet, &fa.Spec.MetaPatch)
if err != nil {
review.Response.Allowed = false
review.Response.Result = &metav1.Status{
Expand Down Expand Up @@ -250,7 +250,7 @@ func (c *Controller) mutationValidationHandler(review admv1beta1.AdmissionReview
}

// allocate allocated a GameServer from a given Fleet
func (c *Controller) allocate(f *stablev1alpha1.Fleet) (*stablev1alpha1.GameServer, error) {
func (c *Controller) allocate(f *stablev1alpha1.Fleet, fam *stablev1alpha1.FleetAllocationMeta) (*stablev1alpha1.GameServer, error) {
var allocation *stablev1alpha1.GameServer
// can only allocate one at a time, as we don't want two separate processes
// trying to allocate the same GameServer to different clients
Expand Down Expand Up @@ -280,6 +280,10 @@ func (c *Controller) allocate(f *stablev1alpha1.Fleet) (*stablev1alpha1.GameServ
gsCopy := allocation.DeepCopy()
gsCopy.Status.State = stablev1alpha1.Allocated

if fam != nil {
c.patchMetadata(gsCopy, fam)
}

gs, err := c.gameServerGetter.GameServers(f.ObjectMeta.Namespace).Update(gsCopy)
if err != nil {
return gs, errors.Wrapf(err, "error updating GameServer %s", gsCopy.ObjectMeta.Name)
Expand All @@ -288,3 +292,25 @@ func (c *Controller) allocate(f *stablev1alpha1.Fleet) (*stablev1alpha1.GameServ

return gs, nil
}

// patch the labels and annotations of an allocated GameServer with metadata from a FleetAllocation
func (c *Controller) patchMetadata(gs *stablev1alpha1.GameServer, fam *stablev1alpha1.FleetAllocationMeta) {
// patch ObjectMeta labels
if fam.Labels != nil {
if gs.ObjectMeta.Labels == nil {
gs.ObjectMeta.Labels = make(map[string]string, len(fam.Labels))
}
for key, value := range fam.Labels {
gs.ObjectMeta.Labels[key] = value
}
}
// apply annotations patch
if fam.Annotations != nil {
if gs.ObjectMeta.Annotations == nil {
gs.ObjectMeta.Annotations = make(map[string]string, len(fam.Annotations))
}
for key, value := range fam.Annotations {
gs.ObjectMeta.Annotations[key] = value
}
}
}
24 changes: 19 additions & 5 deletions pkg/fleetallocation/controller_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,10 @@ func TestControllerAllocate(t *testing.T) {
f, gsSet, gsList := defaultFixtures(4)
c, m := newFakeController()
n := metav1.Now()
l := map[string]string{"mode": "deathmatch"}
a := map[string]string{"map": "searide"}
fam := &v1alpha1.FleetAllocationMeta{Labels: l, Annotations: a}

gsList[3].ObjectMeta.DeletionTimestamp = &n

m.AgonesClient.AddReactor("list", "fleets", func(action k8stesting.Action) (bool, runtime.Object, error) {
Expand Down Expand Up @@ -172,25 +176,35 @@ func TestControllerAllocate(t *testing.T) {
_, cancel := agtesting.StartInformers(m)
defer cancel()

gs, err := c.allocate(f)
gs, err := c.allocate(f, fam)
assert.Nil(t, err)
assert.Equal(t, v1alpha1.Allocated, gs.Status.State)
assert.True(t, updated)
for key, value := range fam.Labels {
v, ok := gs.ObjectMeta.Labels[key]
assert.True(t, ok)
assert.Equal(t, v, value)
}
for key, value := range fam.Annotations {
v, ok := gs.ObjectMeta.Annotations[key]
assert.True(t, ok)
assert.Equal(t, v, value)
}

updated = false
gs, err = c.allocate(f)
gs, err = c.allocate(f, nil)
assert.Nil(t, err)
assert.Equal(t, v1alpha1.Allocated, gs.Status.State)
assert.True(t, updated)

updated = false
gs, err = c.allocate(f)
gs, err = c.allocate(f, nil)
assert.Nil(t, err)
assert.Equal(t, v1alpha1.Allocated, gs.Status.State)
assert.True(t, updated)

updated = false
_, err = c.allocate(f)
_, err = c.allocate(f, nil)
assert.NotNil(t, err)
assert.Equal(t, ErrNoGameServerReady, err)
assert.False(t, updated)
Expand Down Expand Up @@ -230,7 +244,7 @@ func TestControllerAllocateMutex(t *testing.T) {
allocate := func() {
defer wg.Done()
for i := 1; i <= 10; i++ {
_, err := c.allocate(f)
_, err := c.allocate(f, nil)
assert.Nil(t, err)
}
}
Expand Down

0 comments on commit 54e374b

Please sign in to comment.