Skip to content

Commit

Permalink
CRD implementation of alpha player tracking
Browse files Browse the repository at this point in the history
Update to CRD implementation, and pkg/api/gameserver.go and default
value implementation.

Work on googleforgames#1033
  • Loading branch information
markmandel committed Feb 8, 2020
1 parent 5319b13 commit c88ab60
Show file tree
Hide file tree
Showing 8 changed files with 445 additions and 16 deletions.
26 changes: 26 additions & 0 deletions install/helm/agones/templates/crds/_gameserverspecvalidation.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -148,4 +148,30 @@ properties:
type: integer
minimum: 1
maximum: 2147483648
alpha:
type: object
title: Alpha properties for the GameServer
properties:
players:
type: object
title: Configuration of player capacity
properties:
initialCapacity:
type: integer
title: The intial player capacity that this Game Server has
minimum: 0
webhook:
type: object
title: webhook to call when a player connects or disconnects
properties:
service:
properties:
name:
type: string
namespace:
type: string
path:
type: string
url:
type: string
{{- end }}
78 changes: 78 additions & 0 deletions install/yaml/install.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -394,6 +394,32 @@ spec:
type: integer
minimum: 1
maximum: 2147483648
alpha:
type: object
title: Alpha properties for the GameServer
properties:
players:
type: object
title: Configuration of player capacity
properties:
initialCapacity:
type: integer
title: The intial player capacity that this Game Server has
minimum: 0
webhook:
type: object
title: webhook to call when a player connects or disconnects
properties:
service:
properties:
name:
type: string
namespace:
type: string
path:
type: string
url:
type: string
subresources:
# status enables the status subresource.
status: {}
Expand Down Expand Up @@ -678,6 +704,32 @@ spec:
type: integer
minimum: 1
maximum: 2147483648
alpha:
type: object
title: Alpha properties for the GameServer
properties:
players:
type: object
title: Configuration of player capacity
properties:
initialCapacity:
type: integer
title: The intial player capacity that this Game Server has
minimum: 0
webhook:
type: object
title: webhook to call when a player connects or disconnects
properties:
service:
properties:
name:
type: string
namespace:
type: string
path:
type: string
url:
type: string

---
# Source: agones/templates/crds/gameserverallocationpolicy.yaml
Expand Down Expand Up @@ -973,6 +1025,32 @@ spec:
type: integer
minimum: 1
maximum: 2147483648
alpha:
type: object
title: Alpha properties for the GameServer
properties:
players:
type: object
title: Configuration of player capacity
properties:
initialCapacity:
type: integer
title: The intial player capacity that this Game Server has
minimum: 0
webhook:
type: object
title: webhook to call when a player connects or disconnects
properties:
service:
properties:
name:
type: string
namespace:
type: string
path:
type: string
url:
type: string
subresources:
# status enables the status subresource.
status: {}
Expand Down
42 changes: 37 additions & 5 deletions pkg/apis/agones/v1/gameserver.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,14 @@ import (
"fmt"
"net"

"github.com/mattbaird/jsonpatch"
"agones.dev/agones/pkg/util/runtime"

"agones.dev/agones/pkg"
"agones.dev/agones/pkg/apis"
"agones.dev/agones/pkg/apis/agones"
"github.com/mattbaird/jsonpatch"
"github.com/pkg/errors"
admregv1b "k8s.io/api/admissionregistration/v1beta1"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/labels"
Expand Down Expand Up @@ -150,6 +152,20 @@ type GameServerSpec struct {
SdkServer SdkServer `json:"sdkServer,omitempty"`
// Template describes the Pod that will be created for the GameServer
Template corev1.PodTemplateSpec `json:"template"`
// AlphaSpec describes the alpha properties for the GameServer
Alpha AlphaSpec `json:"alpha,omitempty"`
}

// AlphaSpec is the alpha properties of the GameServer
type AlphaSpec struct {
Players PlayersSpec `json:"players"`
}

// PlayersSpec tracks the initial player capacity, and what webhooks to send events to when there are
// connection/disconnection events.
type PlayersSpec struct {
InitialCapacity int64 `json:"initialCapacity,omitempty"`
Webhook *admregv1b.WebhookClientConfig `json:"webhook,omitempty"`
}

// GameServerState is the state for the GameServer
Expand Down Expand Up @@ -210,6 +226,7 @@ type GameServerStatus struct {
Address string `json:"address"`
NodeName string `json:"nodeName"`
ReservedUntil *metav1.Time `json:"reservedUntil"`
Alpha AlphaStatus `json:"alpha"`
}

// GameServerStatusPort shows the port that was allocated to a
Expand All @@ -219,6 +236,17 @@ type GameServerStatusPort struct {
Port int32 `json:"port"`
}

// AlphaStatus is the alpha status values for a GameServer
type AlphaStatus struct {
Players PlayerStatus `json:"players"`
}

// PlayerStatus stores the current player capacity values
type PlayerStatus struct {
Count int64 `json:"count"`
Capacity int64 `json:"capacity"`
}

// ApplyDefaults applies default values to the GameServer if they are not already populated
func (gs *GameServer) ApplyDefaults() {
// VersionAnnotation is the annotation that stores
Expand All @@ -230,7 +258,7 @@ func (gs *GameServer) ApplyDefaults() {
gs.ObjectMeta.Finalizers = append(gs.ObjectMeta.Finalizers, agones.GroupName)

gs.Spec.ApplyDefaults()
gs.applyStateDefaults()
gs.applyStatusDefaults()
}

// ApplyDefaults applies default values to the GameServerSpec if they are not already populated
Expand Down Expand Up @@ -277,15 +305,19 @@ func (gss *GameServerSpec) applyHealthDefaults() {
}
}

// applyStateDefaults applies state defaults
func (gs *GameServer) applyStateDefaults() {
// applyStatusDefaults applies Status defaults
func (gs *GameServer) applyStatusDefaults() {
if gs.Status.State == "" {
gs.Status.State = GameServerStateCreating
// applyStateDefaults() should be called after applyPortDefaults()
// applyStatusDefaults() should be called after applyPortDefaults()
if gs.HasPortPolicy(Dynamic) || gs.HasPortPolicy(Passthrough) {
gs.Status.State = GameServerStatePortAllocation
}
}

if runtime.FeatureEnabled(runtime.FeaturePlayerTracking) {
gs.Status.Alpha.Players.Capacity = gs.Spec.Alpha.Players.InitialCapacity
}
}

// applyPortDefaults applies default values for all ports
Expand Down
35 changes: 26 additions & 9 deletions pkg/apis/agones/v1/gameserver_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,11 @@ package v1
import (
"fmt"
"strings"
"sync"
"testing"

"agones.dev/agones/pkg/util/runtime"

"agones.dev/agones/pkg"
"agones.dev/agones/pkg/apis"
"agones.dev/agones/pkg/apis/agones"
Expand Down Expand Up @@ -62,21 +65,25 @@ func TestGameServerApplyDefaults(t *testing.T) {
t.Parallel()

type expected struct {
protocol corev1.Protocol
state GameServerState
policy PortPolicy
health Health
scheduling apis.SchedulingStrategy
sdkServer SdkServer
protocol corev1.Protocol
state GameServerState
policy PortPolicy
health Health
scheduling apis.SchedulingStrategy
sdkServer SdkServer
alphaPlayerCapacity int64
}
data := map[string]struct {
gameServer GameServer
container string
expected expected
gameServer GameServer
container string
featureFlags string
expected expected
}{
"set basic defaults on a very simple gameserver": {
featureFlags: runtime.FeaturePlayerTracking + "=true",
gameServer: GameServer{
Spec: GameServerSpec{
Alpha: AlphaSpec{Players: PlayersSpec{InitialCapacity: 10}},
Ports: []GameServerPort{{ContainerPort: 999}},
Template: corev1.PodTemplateSpec{
Spec: corev1.PodSpec{Containers: []corev1.Container{
Expand All @@ -100,6 +107,7 @@ func TestGameServerApplyDefaults(t *testing.T) {
GRPCPort: 9357,
HTTPPort: 9358,
},
alphaPlayerCapacity: 10,
},
},
"defaults on passthrough": {
Expand Down Expand Up @@ -180,6 +188,7 @@ func TestGameServerApplyDefaults(t *testing.T) {
gameServer: GameServer{
Spec: GameServerSpec{
Ports: []GameServerPort{{PortPolicy: Static}},
Alpha: AlphaSpec{Players: PlayersSpec{InitialCapacity: 10}},
Template: corev1.PodTemplateSpec{
Spec: corev1.PodSpec{Containers: []corev1.Container{{Name: "testing", Image: "testing/image"}}}}},
},
Expand Down Expand Up @@ -319,8 +328,15 @@ func TestGameServerApplyDefaults(t *testing.T) {
},
}

// otherwise the race condition detector is not happy.
mtx := sync.Mutex{}
for name, test := range data {
t.Run(name, func(t *testing.T) {
mtx.Lock()
err := runtime.ParseFeatures(test.featureFlags)
mtx.Unlock()
assert.NoError(t, err)

test.gameServer.ApplyDefaults()

assert.Equal(t, pkg.Version, test.gameServer.Annotations[VersionAnnotation])
Expand All @@ -333,6 +349,7 @@ func TestGameServerApplyDefaults(t *testing.T) {
assert.Equal(t, test.expected.scheduling, test.gameServer.Spec.Scheduling)
assert.Equal(t, test.expected.health, test.gameServer.Spec.Health)
assert.Equal(t, test.expected.sdkServer, test.gameServer.Spec.SdkServer)
assert.Equal(t, test.expected.alphaPlayerCapacity, test.gameServer.Status.Alpha.Players.Capacity)
})
}
}
Expand Down
Loading

0 comments on commit c88ab60

Please sign in to comment.