Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Updates counters lists schema status CRDs for gameservers fleets #2965

Merged
merged 4 commits into from
Feb 16, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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:
igooch marked this conversation as resolved.
Show resolved Hide resolved
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"`
}
igooch marked this conversation as resolved.
Show resolved Hide resolved

// 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) {
igooch marked this conversation as resolved.
Show resolved Hide resolved
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