Skip to content
Permalink
Browse files

CRD implementation of alpha player tracking (#1324)

* CRD implementation of alpha player tracking

Update to CRD implementation, and pkg/api/gameserver.go and default
value implementation.

Work on #1033

* Including feature flag locking.

Required to allow tests to pass with race checking enabled.
  • Loading branch information
markmandel committed Feb 14, 2020
1 parent 2316a45 commit 59a2e437967e1d7ea56552cf8b2968ebaa6b46ed
@@ -148,4 +148,32 @@ 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 initial player capacity of this Game Server
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
caBundle:
type: string
{{- end }}
@@ -394,6 +394,34 @@ 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 initial player capacity of this Game Server
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
caBundle:
type: string
subresources:
# status enables the status subresource.
status: {}
@@ -680,6 +708,34 @@ 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 initial player capacity of this Game Server
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
caBundle:
type: string

---
# Source: agones/templates/crds/gameserverallocationpolicy.yaml
@@ -982,6 +1038,34 @@ 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 initial player capacity of this Game Server
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
caBundle:
type: string
subresources:
# status enables the status subresource.
status: {}
@@ -19,12 +19,13 @@ import (
"fmt"
"net"

"github.com/mattbaird/jsonpatch"

"agones.dev/agones/pkg"
"agones.dev/agones/pkg/apis"
"agones.dev/agones/pkg/apis/agones"
"agones.dev/agones/pkg/util/runtime"
"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"
@@ -150,6 +151,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"`
// Alpha describes the alpha properties for the GameServer.
Alpha AlphaSpec `json:"alpha,omitempty"`
}

// AlphaSpec contains 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
@@ -210,6 +225,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
@@ -219,6 +235,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
@@ -230,7 +257,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
@@ -277,15 +304,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
@@ -22,6 +22,7 @@ import (
"agones.dev/agones/pkg"
"agones.dev/agones/pkg/apis"
"agones.dev/agones/pkg/apis/agones"
"agones.dev/agones/pkg/util/runtime"
"github.com/stretchr/testify/assert"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
@@ -62,21 +63,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{
@@ -100,6 +105,7 @@ func TestGameServerApplyDefaults(t *testing.T) {
GRPCPort: 9357,
HTTPPort: 9358,
},
alphaPlayerCapacity: 10,
},
},
"defaults on passthrough": {
@@ -180,6 +186,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"}}}}},
},
@@ -319,8 +326,14 @@ func TestGameServerApplyDefaults(t *testing.T) {
},
}

runtime.FeatureTestMutex.Lock()
defer runtime.FeatureTestMutex.Unlock()

for name, test := range data {
t.Run(name, func(t *testing.T) {
err := runtime.ParseFeatures(test.featureFlags)
assert.NoError(t, err)

test.gameServer.ApplyDefaults()

assert.Equal(t, pkg.Version, test.gameServer.Annotations[VersionAnnotation])
@@ -333,6 +346,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)
})
}
}

0 comments on commit 59a2e43

Please sign in to comment.
You can’t perform that action at this time.