Skip to content

Commit

Permalink
Updates counters lists schema status CRDs for gameservers fleets (goo…
Browse files Browse the repository at this point in the history
…gleforgames#2965)

* Updates counters and lists schema and status CRDs for gameservers and fleets

* Adds validation for counters and lists CRDs

* Pulls feature gate validation out of the validate func

* Adds generated crd api docs
  • Loading branch information
igooch authored Feb 16, 2023
1 parent 61fe95d commit ce56e29
Show file tree
Hide file tree
Showing 9 changed files with 1,686 additions and 1,260 deletions.
14 changes: 9 additions & 5 deletions examples/gameserver.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -88,15 +88,19 @@ spec:
#
# [Stage:Alpha]
# [FeatureFlag:CountsAndLists]
# Lists provides the configuration for generic (player, room, session, etc.) tracking features.
# Counts and Lists provides the configuration for generic (player, room, session, etc.) tracking features.
# Commented out since Alpha, and disabled by default
# counters:
# games:
# count: 1
# capacity: 100
# sessions:
# capacity: 999
# lists:
# - name: playerlist
# count: 0
# players:
# capacity: 1000
# values:
# - name: roomlist
# count: 3
# rooms:
# capacity: 333
# values:
# - room1
Expand Down
27 changes: 13 additions & 14 deletions install/helm/agones/templates/crds/_gameserverspecschema.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -155,33 +155,32 @@ properties:
minimum: 0
{{- if .featureCountsAndLists }}
counters:
type: array
title: Array of player, room, session, etc. counters
type: object
title: Map of player, room, session, etc. counters
nullable: true
maxItems: 1000
items:
maxProperties: 1000
additionalProperties:
type: object
properties:
name: # counter name
type: string
count: # initial count
type: integer
default: 0
minimum: 0
capacity: # max capacity of the counter
type: integer
minimum: 0
lists:
type: array
title: Array of player, room, session, etc. lists
type: object
title: Map of player, room, session, etc. lists
nullable: true
maxItems: 1000
items:
maxProperties: 1000
additionalProperties:
type: object
properties:
name: # array name (players, sessions, rooms, etc.)
type: string
count: # initial number of items in the values array
type: integer
capacity: # max capacity of the array (can be less than or equal to value of maxItems)
type: integer
minimum: 0
maximum: 1000 # must be equal to values.maxItems
values:
type: array
x-kubernetes-list-type: set # Requires items in the array to be unique
Expand Down
37 changes: 19 additions & 18 deletions install/helm/agones/templates/crds/_gameserverstatus.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -67,36 +67,37 @@ status:
type: string
{{- if .featureCountsAndLists }}
counters:
type: array
type: object
title: Map of player, room, session, etc. counters
nullable: true
maxItems: 1000
items:
maxProperties: 1000
additionalProperties:
type: object
properties:
name:
type: string
count:
count: # initial count
type: integer
capacity:
default: 0
minimum: 0
capacity: # max capacity of the counter
type: integer
minimum: 0
lists:
type: array
type: object
title: Map of player, room, session, etc. lists
nullable: true
maxItems: 1000
items:
maxProperties: 1000
additionalProperties:
type: object
properties:
name:
type: string
count:
type: integer
capacity:
capacity: # max capacity of the array (can be less than or equal to value of values.maxItems)
type: integer
minimum: 0
maximum: 1000 # must be equal to values.maxItems
values:
type: array
x-kubernetes-list-type: set
maxItems: 1000
items:
x-kubernetes-list-type: set # Requires items in the array to be unique
maxItems: 1000 # max possible size of the value array (cannot be updated)
items: # name of the item (player1, session1, room1, etc.)
type: string
{{- end }}
{{- if .featureSafeToEvict }}
Expand Down
37 changes: 19 additions & 18 deletions install/helm/agones/templates/crds/fleet.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -131,36 +131,37 @@ spec:
minimum: 0
{{- if $featureGates.CountsAndLists }}
counters:
type: array
type: object
title: Map of player, room, session, etc. counters
nullable: true
maxItems: 1000
items:
maxProperties: 1000
additionalProperties:
type: object
properties:
name:
type: string
count:
count: # initial count
type: integer
capacity:
default: 0
minimum: 0
capacity: # max capacity of the counter
type: integer
minimum: 0
lists:
type: array
type: object
title: Map of player, room, session, etc. lists
nullable: true
maxItems: 1000
items:
maxProperties: 1000
additionalProperties:
type: object
properties:
name:
type: string
count:
type: integer
capacity:
capacity: # max capacity of the array (can be less than or equal to value of maxItems)
type: integer
minimum: 0
maximum: 1000 # must be equal to values.maxItems
values:
type: array
x-kubernetes-list-type: set
maxItems: 1000
items:
x-kubernetes-list-type: set # Requires items in the array to be unique
maxItems: 1000 # max possible size of the value array (cannot be updated)
items: # name of the item (player1, session1, room1, etc.)
type: string
{{- end }}
subresources:
Expand Down
37 changes: 19 additions & 18 deletions install/helm/agones/templates/crds/gameserverset.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -114,36 +114,37 @@ spec:
minimum: 0
{{- if $featureGates.CountsAndLists }}
counters:
type: array
type: object
title: Map of player, room, session, etc. counters
nullable: true
maxItems: 1000
items:
maxProperties: 1000
additionalProperties:
type: object
properties:
name:
type: string
count:
count: # initial count
type: integer
capacity:
default: 0
minimum: 0
capacity: # max capacity of the counter
type: integer
minimum: 0
lists:
type: array
type: object
title: Map of player, room, session, etc. lists
nullable: true
maxItems: 1000
items:
maxProperties: 1000
additionalProperties:
type: object
properties:
name:
type: string
count:
type: integer
capacity:
capacity: # max capacity of the array (can be less than or equal to value of maxItems)
type: integer
minimum: 0
maximum: 1000 # must be equal to values.maxItems
values:
type: array
x-kubernetes-list-type: set
maxItems: 1000
items:
x-kubernetes-list-type: set # Requires items in the array to be unique
maxItems: 1000 # max possible size of the value array (cannot be updated)
items: # name of the item (player1, session1, room1, etc.)
type: string
{{- end }}
subresources:
Expand Down
51 changes: 46 additions & 5 deletions pkg/apis/agones/v1/gameserver.go
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,10 @@ type GameServerSpec struct {
// (Alpha, PlayerTracking feature flag) Players provides the configuration for player tracking features.
// +optional
Players *PlayersSpec `json:"players,omitempty"`
// (Alpha, CountsAndLists feature flag) Counters and Lists provides the configuration for generic tracking features.
// +optional
Counters map[string]CounterSpec `json:"counters,omitempty"`
Lists map[string]ListSpec `json:"lists,omitempty"`
// (Alpha, SafeToEvict feature flag) Eviction specifies the eviction tolerance of the GameServer. Defaults to "Never".
// +optional
Eviction Eviction `json:"eviction,omitempty"`
Expand All @@ -198,6 +202,18 @@ type PlayersSpec struct {
InitialCapacity int64 `json:"initialCapacity,omitempty"`
}

// CounterSpec tracks if counter specified (for giving error message if feature gate not set)
type CounterSpec struct {
Count int64 `json:"count,omitempty"`
Capacity int64 `json:"capacity,omitempty"`
}

// ListSpec tracks the list capacity
type ListSpec struct {
Capacity int64 `json:"capacity,omitempty"`
Values []string `json:"values,omitempty"`
}

// Eviction specifies the eviction tolerance of the GameServer
type Eviction struct {
// (Alpha, SafeToEvict feature flag)
Expand Down Expand Up @@ -421,11 +437,8 @@ func (gs *GameServer) applyEvictionStatus() {
}
}

// Validate validates the GameServerSpec configuration.
// devAddress is a specific IP address used for local Gameservers, for fleets "" is used
// If a GameServer Spec is invalid there will be > 0 values in
// the returned array
func (gss *GameServerSpec) Validate(apiHooks APIHooks, devAddress string) ([]metav1.StatusCause, bool) {
// validateFeatureGates checks if fields are set when the associated feature gate is not set.
func (gss *GameServerSpec) validateFeatureGates() []metav1.StatusCause {
var causes []metav1.StatusCause

if !runtime.FeatureEnabled(runtime.FeaturePlayerTracking) {
Expand All @@ -438,6 +451,23 @@ func (gss *GameServerSpec) Validate(apiHooks APIHooks, devAddress string) ([]met
}
}

if !runtime.FeatureEnabled(runtime.FeatureCountsAndLists) {
if gss.Counters != nil {
causes = append(causes, metav1.StatusCause{
Type: metav1.CauseTypeFieldValueNotSupported,
Field: "counters",
Message: fmt.Sprintf("Value cannot be set unless feature flag %s is enabled", runtime.FeatureCountsAndLists),
})
}
if gss.Lists != nil {
causes = append(causes, metav1.StatusCause{
Type: metav1.CauseTypeFieldValueNotSupported,
Field: "lists",
Message: fmt.Sprintf("Value cannot be set unless feature flag %s is enabled", runtime.FeatureCountsAndLists),
})
}
}

if !runtime.FeatureEnabled(runtime.FeatureSafeToEvict) {
if gss.Eviction.Safe != "" {
causes = append(causes, metav1.StatusCause{
Expand All @@ -448,6 +478,17 @@ func (gss *GameServerSpec) Validate(apiHooks APIHooks, devAddress string) ([]met
}
}

return causes
}

// Validate validates the GameServerSpec configuration.
// devAddress is a specific IP address used for local Gameservers, for fleets "" is used
// If a GameServer Spec is invalid there will be > 0 values in the returned array
func (gss *GameServerSpec) Validate(apiHooks APIHooks, devAddress string) ([]metav1.StatusCause, bool) {
var causes []metav1.StatusCause

causes = append(causes, gss.validateFeatureGates()...)

if devAddress != "" {
// verify that the value is a valid IP address.
if net.ParseIP(devAddress) == nil {
Expand Down
56 changes: 56 additions & 0 deletions pkg/apis/agones/v1/gameserver_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1112,6 +1112,62 @@ func TestGameServerValidateFeatures(t *testing.T) {
isValid: true,
causesExpected: []metav1.StatusCause{},
},
{
description: "CountsAndLists is disabled, Counters field specified",
feature: fmt.Sprintf("%s=false", runtime.FeatureCountsAndLists),
gs: GameServer{
Spec: GameServerSpec{
Container: "testing",
Counters: map[string]CounterSpec{},
Template: corev1.PodTemplateSpec{
Spec: corev1.PodSpec{Containers: []corev1.Container{{Name: "testing", Image: "testing/image"}}}}},
},
isValid: false,
causesExpected: []metav1.StatusCause{
{Type: metav1.CauseTypeFieldValueNotSupported, Message: "Value cannot be set unless feature flag CountsAndLists is enabled", Field: "counters"},
},
},
{
description: "CountsAndLists is disabled, Lists field specified",
feature: fmt.Sprintf("%s=false", runtime.FeatureCountsAndLists),
gs: GameServer{
Spec: GameServerSpec{
Container: "testing",
Lists: map[string]ListSpec{},
Template: corev1.PodTemplateSpec{
Spec: corev1.PodSpec{Containers: []corev1.Container{{Name: "testing", Image: "testing/image"}}}}},
},
isValid: false,
causesExpected: []metav1.StatusCause{
{Type: metav1.CauseTypeFieldValueNotSupported, Message: "Value cannot be set unless feature flag CountsAndLists is enabled", Field: "lists"},
},
},
{
description: "CountsAndLists is enabled, Counters field specified",
feature: fmt.Sprintf("%s=true", runtime.FeatureCountsAndLists),
gs: GameServer{
Spec: GameServerSpec{
Container: "testing",
Counters: map[string]CounterSpec{},
Template: corev1.PodTemplateSpec{
Spec: corev1.PodSpec{Containers: []corev1.Container{{Name: "testing", Image: "testing/image"}}}}},
},
isValid: true,
causesExpected: []metav1.StatusCause{},
},
{
description: "CountsAndLists is enabled, Lists field specified",
feature: fmt.Sprintf("%s=true", runtime.FeatureCountsAndLists),
gs: GameServer{
Spec: GameServerSpec{
Container: "testing",
Lists: map[string]ListSpec{},
Template: corev1.PodTemplateSpec{
Spec: corev1.PodSpec{Containers: []corev1.Container{{Name: "testing", Image: "testing/image"}}}}},
},
isValid: true,
causesExpected: []metav1.StatusCause{},
},
}

for _, tc := range testCases {
Expand Down
Loading

0 comments on commit ce56e29

Please sign in to comment.