diff --git a/go.mod b/go.mod index 32b90464b0..9143925f2a 100644 --- a/go.mod +++ b/go.mod @@ -20,6 +20,7 @@ require ( github.com/joonix/log v0.0.0-20180502111528-d2d3f2f4a806 github.com/mattbaird/jsonpatch v0.0.0-20171005235357-81af80346b1a github.com/mennanov/fmutils v0.2.0 + github.com/mitchellh/hashstructure/v2 v2.0.2 github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 github.com/pkg/errors v0.9.1 github.com/prometheus/client_golang v1.14.0 diff --git a/go.sum b/go.sum index 91709f832c..3f43b1a96f 100644 --- a/go.sum +++ b/go.sum @@ -312,6 +312,8 @@ github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceT github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI= github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg= +github.com/mitchellh/hashstructure/v2 v2.0.2 h1:vGKWl0YJqUNxE8d+h8f6NJLcCJrgbhC4NcD46KavDd4= +github.com/mitchellh/hashstructure/v2 v2.0.2/go.mod h1:MG3aRVU/N29oo/V/IhBX8GR/zz4kQkprJgF2EVszyDE= github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY= github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= diff --git a/pkg/apis/allocation/v1/gameserverallocation.go b/pkg/apis/allocation/v1/gameserverallocation.go index 5926e79fd3..e10e0342a0 100644 --- a/pkg/apis/allocation/v1/gameserverallocation.go +++ b/pkg/apis/allocation/v1/gameserverallocation.go @@ -21,7 +21,7 @@ import ( "agones.dev/agones/pkg/apis" agonesv1 "agones.dev/agones/pkg/apis/agones/v1" "agones.dev/agones/pkg/util/runtime" - apimachineryvalidation "k8s.io/apimachinery/pkg/api/validation" + hashstructure "github.com/mitchellh/hashstructure/v2" apivalidation "k8s.io/apimachinery/pkg/api/validation" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1validation "k8s.io/apimachinery/pkg/apis/meta/v1/validation" @@ -69,12 +69,12 @@ type GameServerAllocationList struct { type GameServerAllocationSpec struct { // MultiClusterPolicySelector if specified, multi-cluster policies are applied. // Otherwise, allocation will happen locally. - MultiClusterSetting MultiClusterSetting `json:"multiClusterSetting,omitempty"` + MultiClusterSetting MultiClusterSetting `json:"multiClusterSetting,omitempty" hash:"ignore"` // Deprecated: use field Selectors instead. If Selectors is set, this field is ignored. // Required is the GameServer selector from which to choose GameServers from. // Defaults to all GameServers. - Required GameServerSelector `json:"required,omitempty"` + Required GameServerSelector `json:"required,omitempty" hash:"ignore"` // Deprecated: use field Selectors instead. If Selectors is set, this field is ignored. // Preferred is an ordered list of preferred GameServer selectors @@ -82,12 +82,12 @@ type GameServerAllocationSpec struct { // If the first selector is not matched, the selection attempts the second selector, and so on. // If any of the preferred selectors are matched, the required selector is not considered. // This is useful for things like smoke testing of new game servers. - Preferred []GameServerSelector `json:"preferred,omitempty"` + Preferred []GameServerSelector `json:"preferred,omitempty" hash:"ignore"` // (Alpha, CountsAndLists feature flag) The first Priority on the array of Priorities is the most // important for sorting. The allocator will use the first priority for sorting GameServers by - // available Capacity in the Selector set and acts as a tie-breaker after sorting the game servers - // by State and Strategy. Impacts which GameServer is checked first. + // available Capacity in the Selector set. Acts as a tie-breaker after sorting the game servers + // by State and Strategy Packed. Impacts which GameServer is checked first. // +optional Priorities []agonesv1.Priority `json:"priorities,omitempty"` @@ -95,20 +95,20 @@ type GameServerAllocationSpec struct { // If the first selector is not matched, the selection attempts the second selector, and so on. // This is useful for things like smoke testing of new game servers. // Note: This field can only be set if neither Required or Preferred is set. - Selectors []GameServerSelector `json:"selectors,omitempty"` + Selectors []GameServerSelector `json:"selectors,omitempty" hash:"ignore"` // Scheduling strategy. Defaults to "Packed". Scheduling apis.SchedulingStrategy `json:"scheduling"` // MetaPatch is optional custom metadata that is added to the game server at allocation // You can use this to tell the server necessary session data - MetaPatch MetaPatch `json:"metadata,omitempty"` + MetaPatch MetaPatch `json:"metadata,omitempty" hash:"ignore"` // (Alpha, CountsAndLists feature flag) Counters and Lists provide a set of actions to perform // on Counters and Lists during allocation. // +optional - Counters map[string]CounterAction `json:"counters,omitempty"` - Lists map[string]ListAction `json:"lists,omitempty"` + Counters map[string]CounterAction `json:"counters,omitempty" hash:"ignore"` + Lists map[string]ListAction `json:"lists,omitempty" hash:"ignore"` } // GameServerSelector contains all the filter options for selecting @@ -378,11 +378,11 @@ func (s *GameServerSelector) Validate(fldPath *field.Path) field.ErrorList { if runtime.FeatureEnabled(runtime.FeaturePlayerAllocationFilter) && s.Players != nil { if s.Players.MinAvailable < 0 { - allErrs = append(allErrs, field.Invalid(fldPath.Child("players").Child("minAvailable"), s.Players.MinAvailable, apimachineryvalidation.IsNegativeErrorMsg)) + allErrs = append(allErrs, field.Invalid(fldPath.Child("players").Child("minAvailable"), s.Players.MinAvailable, apivalidation.IsNegativeErrorMsg)) } if s.Players.MaxAvailable < 0 { - allErrs = append(allErrs, field.Invalid(fldPath.Child("players").Child("maxAvailable"), s.Players.MaxAvailable, apimachineryvalidation.IsNegativeErrorMsg)) + allErrs = append(allErrs, field.Invalid(fldPath.Child("players").Child("maxAvailable"), s.Players.MaxAvailable, apivalidation.IsNegativeErrorMsg)) } if s.Players.MinAvailable > s.Players.MaxAvailable { @@ -415,19 +415,19 @@ func validateCounters(counters map[string]CounterSelector, fldPath *field.Path) for key, counterSelector := range counters { keyPath := fldPath.Key(key) if counterSelector.MinCount < 0 { - allErrs = append(allErrs, field.Invalid(keyPath.Child("minCount"), counterSelector.MinCount, apimachineryvalidation.IsNegativeErrorMsg)) + allErrs = append(allErrs, field.Invalid(keyPath.Child("minCount"), counterSelector.MinCount, apivalidation.IsNegativeErrorMsg)) } if counterSelector.MaxCount < 0 { - allErrs = append(allErrs, field.Invalid(keyPath.Child("maxCount"), counterSelector.MaxCount, apimachineryvalidation.IsNegativeErrorMsg)) + allErrs = append(allErrs, field.Invalid(keyPath.Child("maxCount"), counterSelector.MaxCount, apivalidation.IsNegativeErrorMsg)) } if (counterSelector.MaxCount < counterSelector.MinCount) && (counterSelector.MaxCount != 0) { allErrs = append(allErrs, field.Invalid(keyPath, counterSelector.MaxCount, fmt.Sprintf("maxCount must zero or greater than minCount %d", counterSelector.MinCount))) } if counterSelector.MinAvailable < 0 { - allErrs = append(allErrs, field.Invalid(keyPath.Child("minAvailable"), counterSelector.MinAvailable, apimachineryvalidation.IsNegativeErrorMsg)) + allErrs = append(allErrs, field.Invalid(keyPath.Child("minAvailable"), counterSelector.MinAvailable, apivalidation.IsNegativeErrorMsg)) } if counterSelector.MaxAvailable < 0 { - allErrs = append(allErrs, field.Invalid(keyPath.Child("maxAvailable"), counterSelector.MaxAvailable, apimachineryvalidation.IsNegativeErrorMsg)) + allErrs = append(allErrs, field.Invalid(keyPath.Child("maxAvailable"), counterSelector.MaxAvailable, apivalidation.IsNegativeErrorMsg)) } if (counterSelector.MaxAvailable < counterSelector.MinAvailable) && (counterSelector.MaxAvailable != 0) { allErrs = append(allErrs, field.Invalid(keyPath, counterSelector.MaxAvailable, fmt.Sprintf("maxAvailable must zero or greater than minAvailable %d", counterSelector.MinAvailable))) @@ -443,10 +443,10 @@ func validateLists(lists map[string]ListSelector, fldPath *field.Path) field.Err for key, listSelector := range lists { keyPath := fldPath.Key(key) if listSelector.MinAvailable < 0 { - allErrs = append(allErrs, field.Invalid(keyPath.Child("minAvailable"), listSelector.MinAvailable, apimachineryvalidation.IsNegativeErrorMsg)) + allErrs = append(allErrs, field.Invalid(keyPath.Child("minAvailable"), listSelector.MinAvailable, apivalidation.IsNegativeErrorMsg)) } if listSelector.MaxAvailable < 0 { - allErrs = append(allErrs, field.Invalid(keyPath.Child("maxAvailable"), listSelector.MaxAvailable, apimachineryvalidation.IsNegativeErrorMsg)) + allErrs = append(allErrs, field.Invalid(keyPath.Child("maxAvailable"), listSelector.MaxAvailable, apivalidation.IsNegativeErrorMsg)) } if (listSelector.MaxAvailable < listSelector.MinAvailable) && (listSelector.MaxAvailable != 0) { allErrs = append(allErrs, field.Invalid(keyPath, listSelector.MaxAvailable, fmt.Sprintf("maxAvailable must zero or greater than minAvailable %d", listSelector.MinAvailable))) @@ -549,3 +549,15 @@ func (gsa *GameServerAllocation) Converter() { gsa.Spec.Selectors = selectors } } + +// SortKey generates and returns the hash of the GameServerAllocationSpec []Priority and Scheduling. +// Note: The hash:"ignore" in GameServerAllocationSpec means that these fields will not be considered +// in hashing. The hash is used for determining when GameServerAllocations have equal or different +// []Priority and Scheduling. +func (gsa *GameServerAllocation) SortKey() (uint64, error) { + hash, err := hashstructure.Hash(gsa.Spec, hashstructure.FormatV2, nil) + if err != nil { + return 0, err + } + return hash, nil +} diff --git a/pkg/apis/allocation/v1/gameserverallocation_test.go b/pkg/apis/allocation/v1/gameserverallocation_test.go index 9a26274e45..e8899b34e3 100644 --- a/pkg/apis/allocation/v1/gameserverallocation_test.go +++ b/pkg/apis/allocation/v1/gameserverallocation_test.go @@ -1132,3 +1132,117 @@ func TestGameServerAllocationConverter(t *testing.T) { gsa.Converter() assert.Equal(t, gsaExpected, gsa) } + +func TestSortKey(t *testing.T) { + t.Parallel() + + runtime.FeatureTestMutex.Lock() + defer runtime.FeatureTestMutex.Unlock() + assert.NoError(t, runtime.ParseFeatures(fmt.Sprintf("%s=true", runtime.FeatureCountsAndLists))) + + gameServerAllocation1 := &GameServerAllocation{ + Spec: GameServerAllocationSpec{ + Scheduling: "Packed", + Priorities: []agonesv1.Priority{ + { + Type: "List", + Key: "foo", + Order: "Descending", + }, + }, + }, + } + + gameServerAllocation2 := &GameServerAllocation{ + Spec: GameServerAllocationSpec{ + Selectors: []GameServerSelector{ + {LabelSelector: metav1.LabelSelector{MatchLabels: map[string]string{"foo": "bar"}}}, + }, + Scheduling: "Packed", + Priorities: []agonesv1.Priority{ + { + Type: "List", + Key: "foo", + Order: "Descending", + }, + }, + }, + } + + gameServerAllocation3 := &GameServerAllocation{ + Spec: GameServerAllocationSpec{ + Scheduling: "Packed", + Priorities: []agonesv1.Priority{ + { + Type: "Counter", + Key: "foo", + Order: "Descending", + }, + }, + }, + } + + gameServerAllocation4 := &GameServerAllocation{ + Spec: GameServerAllocationSpec{ + Scheduling: "Distributed", + Priorities: []agonesv1.Priority{ + { + Type: "List", + Key: "foo", + Order: "Descending", + }, + }, + }, + } + + gameServerAllocation5 := &GameServerAllocation{} + + gameServerAllocation6 := &GameServerAllocation{ + Spec: GameServerAllocationSpec{ + Priorities: []agonesv1.Priority{}, + }, + } + + testScenarios := map[string]struct { + gsa1 *GameServerAllocation + gsa2 *GameServerAllocation + wantEqual bool + }{ + "equivalent GameServerAllocation": { + gsa1: gameServerAllocation1, + gsa2: gameServerAllocation2, + wantEqual: true, + }, + "different Scheduling GameServerAllocation": { + gsa1: gameServerAllocation1, + gsa2: gameServerAllocation4, + wantEqual: false, + }, + "equivalent empty GameServerAllocation": { + gsa1: gameServerAllocation5, + gsa2: gameServerAllocation6, + wantEqual: true, + }, + "different Priorities GameServerAllocation": { + gsa1: gameServerAllocation1, + gsa2: gameServerAllocation3, + wantEqual: false, + }, + } + + for test, testScenario := range testScenarios { + t.Run(test, func(t *testing.T) { + key1, err := testScenario.gsa1.SortKey() + assert.NoError(t, err) + key2, err := testScenario.gsa2.SortKey() + assert.NoError(t, err) + + if testScenario.wantEqual { + assert.Equal(t, key1, key2) + } else { + assert.NotEqual(t, key1, key2) + } + }) + } + +} diff --git a/pkg/gameserverallocations/allocation_cache.go b/pkg/gameserverallocations/allocation_cache.go index 7d9b45669a..73bb692c84 100644 --- a/pkg/gameserverallocations/allocation_cache.go +++ b/pkg/gameserverallocations/allocation_cache.go @@ -262,7 +262,8 @@ func (c *AllocationCache) ListSortedGameServers(gsa *allocationv1.GameServerAllo return list } -// compareGameServers compares two game servers based on a CountsAndLists Priority +// compareGameServers compares two game servers based on a CountsAndLists Priority using available +// capacity (Capacity - Count for Counters, and Capacity - len(Values) for Lists) as the comparison. // Returns -1 if gs1 < gs2; 1 if gs1 > gs2; 0 if gs1 == gs2; 0 if neither gamer server has the Priority. // If only one game server has the Priority, prefer that server. I.e. nil < gsX when Priority // Order is Descending (3, 2, 1, 0, nil), and nil > gsX when Order is Ascending (0, 1, 2, 3, nil). @@ -275,13 +276,15 @@ func compareGameServers(p *agonesv1.Priority, gs1, gs2 *agonesv1.GameServer) int counter2, ok2 := gs2.Status.Counters[p.Key] // If both game servers have the Counter if ok1 && ok2 { - if counter1.Count < counter2.Count { + availCapacity1 := counter1.Capacity - counter1.Count + availCapacity2 := counter2.Capacity - counter2.Count + if availCapacity1 < availCapacity2 { return -1 } - if counter1.Count > counter2.Count { + if availCapacity1 > availCapacity2 { return 1 } - if counter1.Count == counter2.Count { + if availCapacity1 == availCapacity2 { return 0 } } @@ -293,13 +296,15 @@ func compareGameServers(p *agonesv1.Priority, gs1, gs2 *agonesv1.GameServer) int list2, ok2 := gs2.Status.Lists[p.Key] // If both game servers have the List if ok1 && ok2 { - if len(list1.Values) < len(list2.Values) { + availCapacity1 := list1.Capacity - int64(len(list1.Values)) + availCapacity2 := list2.Capacity - int64(len(list2.Values)) + if availCapacity1 < availCapacity2 { return -1 } - if len(list1.Values) > len(list2.Values) { + if availCapacity1 > availCapacity2 { return 1 } - if len(list1.Values) == len(list2.Values) { + if availCapacity1 == availCapacity2 { return 0 } } @@ -309,13 +314,11 @@ func compareGameServers(p *agonesv1.Priority, gs1, gs2 *agonesv1.GameServer) int // If only one game server has the Priority, prefer that server. I.e. nil < gsX when Order is // Descending (3, 2, 1, 0, nil), and nil > gsX when Order is Ascending (0, 1, 2, 3, nil). if (gs1ok && p.Order == agonesv1.GameServerPriorityDescending) || - (gs1ok && p.Order == "") || (gs2ok && p.Order == agonesv1.GameServerPriorityAscending) { return 1 } if (gs1ok && p.Order == agonesv1.GameServerPriorityAscending) || - (gs2ok && p.Order == agonesv1.GameServerPriorityDescending) || - (gs2ok && p.Order == "") { + (gs2ok && p.Order == agonesv1.GameServerPriorityDescending) { return -1 } // If neither game server has the Priority diff --git a/pkg/gameserverallocations/allocation_cache_test.go b/pkg/gameserverallocations/allocation_cache_test.go index 733dd55d7e..a6071f57a4 100644 --- a/pkg/gameserverallocations/allocation_cache_test.go +++ b/pkg/gameserverallocations/allocation_cache_test.go @@ -57,7 +57,7 @@ func TestAllocationCacheListSortedGameServers(t *testing.T) { Counters: map[string]agonesv1.CounterStatus{ "players": { Count: 4, - Capacity: 40, + Capacity: 40, // Available Capacity == 36 }, }}, } @@ -69,7 +69,7 @@ func TestAllocationCacheListSortedGameServers(t *testing.T) { Counters: map[string]agonesv1.CounterStatus{ "players": { Count: 14, - Capacity: 40, + Capacity: 40, // Available Capacity == 26 }, }}, } @@ -154,7 +154,7 @@ func TestAllocationCacheListSortedGameServers(t *testing.T) { }, test: func(t *testing.T, list []*agonesv1.GameServer) { assert.Len(t, list, 6) - if !assert.Equal(t, []*agonesv1.GameServer{&gs3, &gs6, &gs5, &gs1, &gs2, &gs4}, list) { + if !assert.Equal(t, []*agonesv1.GameServer{&gs3, &gs5, &gs6, &gs1, &gs2, &gs4}, list) { for _, gs := range list { logrus.WithField("game", gs.Name).Info("game server") } @@ -177,7 +177,7 @@ func TestAllocationCacheListSortedGameServers(t *testing.T) { }, test: func(t *testing.T, list []*agonesv1.GameServer) { assert.Len(t, list, 6) - if !assert.Equal(t, []*agonesv1.GameServer{&gs3, &gs5, &gs6, &gs1, &gs2, &gs4}, list) { + if !assert.Equal(t, []*agonesv1.GameServer{&gs3, &gs6, &gs5, &gs1, &gs2, &gs4}, list) { for _, gs := range list { logrus.WithField("game", gs.Name).Info("game server") } @@ -232,24 +232,24 @@ func TestAllocationCacheCompareGameServers(t *testing.T) { Lists: map[string]agonesv1.ListStatus{ "players": { Values: []string{"player1"}, - Capacity: 100, + Capacity: 100, // Available Capacity == 99 }, "layers": { Values: []string{"layer1", "layer2", "layer3"}, - Capacity: 100, + Capacity: 100, // Available Capacity == 97 }}}} gs2 := agonesv1.GameServer{ObjectMeta: metav1.ObjectMeta{Name: "gs2", Namespace: defaultNs, UID: "2"}, Status: agonesv1.GameServerStatus{NodeName: "node1", State: agonesv1.GameServerStateReady, Lists: map[string]agonesv1.ListStatus{ "players": { Values: []string{}, - Capacity: 100, + Capacity: 100, // Available Capacity == 100 }, }, Counters: map[string]agonesv1.CounterStatus{ "assets": { Count: 101, - Capacity: 1000, + Capacity: 1000, // Available Capacity = 899 }, }}} gs3 := agonesv1.GameServer{ObjectMeta: metav1.ObjectMeta{Name: "gs3", Namespace: defaultNs, UID: "3"}, @@ -257,16 +257,16 @@ func TestAllocationCacheCompareGameServers(t *testing.T) { Lists: map[string]agonesv1.ListStatus{ "players": { Values: []string{"player2", "player3"}, - Capacity: 100, + Capacity: 100, // Available Capacity == 98 }}, Counters: map[string]agonesv1.CounterStatus{ "sessions": { Count: 9, - Capacity: 1000, + Capacity: 1000, // Available Capacity == 991 }, "assets": { Count: 100, - Capacity: 1000, + Capacity: 1000, // Available Capacity == 900 }, }}} gs4 := agonesv1.GameServer{ObjectMeta: metav1.ObjectMeta{Name: "gs4", Namespace: defaultNs, UID: "4"}, @@ -274,41 +274,41 @@ func TestAllocationCacheCompareGameServers(t *testing.T) { Counters: map[string]agonesv1.CounterStatus{ "sessions": { Count: 99, - Capacity: 1000, + Capacity: 1000, // Available Capacity == 901 }, }, Lists: map[string]agonesv1.ListStatus{ "players": { Values: []string{"player4"}, - Capacity: 100, + Capacity: 100, // Available Capacity == 99 }, "layers": { Values: []string{"layer4, layer5"}, - Capacity: 100, + Capacity: 100, // Available Capacity == 98 }}}} gs5 := agonesv1.GameServer{ObjectMeta: metav1.ObjectMeta{Name: "gs5", Namespace: defaultNs, UID: "5"}, Status: agonesv1.GameServerStatus{NodeName: "node1", State: agonesv1.GameServerStateReady, Counters: map[string]agonesv1.CounterStatus{ "sessions": { Count: 9, - Capacity: 1000, + Capacity: 1000, // Available Capacity == 991 }, "assets": { Count: 99, - Capacity: 1000, + Capacity: 1000, // Available Capacity == 901 }, }, Lists: map[string]agonesv1.ListStatus{ "layers": { Values: []string{}, - Capacity: 100, + Capacity: 100, // Available Capacity == 100 }}}} gs6 := agonesv1.GameServer{ObjectMeta: metav1.ObjectMeta{Name: "gs6", Namespace: defaultNs, UID: "6"}, Status: agonesv1.GameServerStatus{NodeName: "node1", State: agonesv1.GameServerStateReady, Counters: map[string]agonesv1.CounterStatus{ "sessions": { Count: 999, - Capacity: 1000, + Capacity: 1000, // Available Capacity == 1 }, }}} @@ -330,7 +330,7 @@ func TestAllocationCacheCompareGameServers(t *testing.T) { }, }, }, - want: []*agonesv1.GameServer{&gs5, &gs4, &gs6}, + want: []*agonesv1.GameServer{&gs6, &gs4, &gs5}, }, "Sort by one Priority Counter Descending": { list: []agonesv1.GameServer{gs4, gs5, gs6}, @@ -345,7 +345,7 @@ func TestAllocationCacheCompareGameServers(t *testing.T) { }, }, }, - want: []*agonesv1.GameServer{&gs6, &gs4, &gs5}, + want: []*agonesv1.GameServer{&gs5, &gs4, &gs6}, }, "Sort by two Priority Counter Ascending and Ascending": { list: []agonesv1.GameServer{gs3, gs5, gs6, gs4, gs1, gs2}, @@ -365,7 +365,7 @@ func TestAllocationCacheCompareGameServers(t *testing.T) { }, }, }, - want: []*agonesv1.GameServer{&gs5, &gs3, &gs4, &gs6, &gs2, &gs1}, + want: []*agonesv1.GameServer{&gs6, &gs4, &gs3, &gs5, &gs2, &gs1}, }, "Sort by two Priority Counter Ascending and Descending": { list: []agonesv1.GameServer{gs3, gs5, gs6, gs4, gs1, gs2}, @@ -385,7 +385,7 @@ func TestAllocationCacheCompareGameServers(t *testing.T) { }, }, }, - want: []*agonesv1.GameServer{&gs3, &gs5, &gs4, &gs6, &gs2, &gs1}, + want: []*agonesv1.GameServer{&gs6, &gs4, &gs5, &gs3, &gs2, &gs1}, }, "Sort by one Priority Counter game server without Counter": { list: []agonesv1.GameServer{gs1, gs5, gs6, gs4}, @@ -400,7 +400,7 @@ func TestAllocationCacheCompareGameServers(t *testing.T) { }, }, }, - want: []*agonesv1.GameServer{&gs5, &gs4, &gs6, &gs1}, + want: []*agonesv1.GameServer{&gs6, &gs4, &gs5, &gs1}, }, "Sort by one Priority List Ascending": { list: []agonesv1.GameServer{gs3, gs2, gs1}, @@ -415,7 +415,7 @@ func TestAllocationCacheCompareGameServers(t *testing.T) { }, }, }, - want: []*agonesv1.GameServer{&gs2, &gs1, &gs3}, + want: []*agonesv1.GameServer{&gs3, &gs1, &gs2}, }, "Sort by one Priority List Descending": { list: []agonesv1.GameServer{gs3, gs2, gs1}, @@ -430,7 +430,7 @@ func TestAllocationCacheCompareGameServers(t *testing.T) { }, }, }, - want: []*agonesv1.GameServer{&gs3, &gs1, &gs2}, + want: []*agonesv1.GameServer{&gs2, &gs1, &gs3}, }, "Sort by two Priority List Descending and Ascending": { list: []agonesv1.GameServer{gs1, gs2, gs3, gs4}, @@ -450,7 +450,7 @@ func TestAllocationCacheCompareGameServers(t *testing.T) { }, }, }, - want: []*agonesv1.GameServer{&gs3, &gs4, &gs1, &gs2}, + want: []*agonesv1.GameServer{&gs2, &gs1, &gs4, &gs3}, }, "Sort by two Priority List Descending and Descending": { list: []agonesv1.GameServer{gs6, gs5, gs4, gs3, gs2, gs1}, @@ -470,7 +470,7 @@ func TestAllocationCacheCompareGameServers(t *testing.T) { }, }, }, - want: []*agonesv1.GameServer{&gs3, &gs1, &gs4, &gs2, &gs5, &gs6}, + want: []*agonesv1.GameServer{&gs2, &gs4, &gs1, &gs3, &gs5, &gs6}, }, } diff --git a/pkg/gameserverallocations/allocator.go b/pkg/gameserverallocations/allocator.go index 5d85305e78..67db3bdb69 100644 --- a/pkg/gameserverallocations/allocator.go +++ b/pkg/gameserverallocations/allocator.go @@ -496,18 +496,40 @@ func (c *Allocator) ListenAndAllocate(ctx context.Context, updateWorkerCount int // continued. var list []*agonesv1.GameServer + var sortKey uint64 requestCount := 0 for { select { case req := <-c.pendingRequests: // refresh the list after every 100 allocations made in a single batch - requestCount++ if requestCount >= maxBatchBeforeRefresh { list = nil requestCount = 0 } + if runtime.FeatureEnabled(runtime.FeatureCountsAndLists) { + // SortKey returns the sorting values (list of Priorities) as a determinstic key. + // In case gsa.Spec.Priorities is nil this will still return a sortKey. + // In case of error this will return 0 for the sortKey. + newSortKey, err := req.gsa.SortKey() + if err != nil { + c.baseLogger.WithError(err).Warn("error getting sortKey for GameServerAllocationSpec", err) + } + // Set sortKey if this is the first request, or the previous request errored on creating a sortKey. + if sortKey == uint64(0) { + sortKey = newSortKey + } + + if newSortKey != sortKey { + sortKey = newSortKey + list = nil + requestCount = 0 + } + } + + requestCount++ + if list == nil { list = c.allocationCache.ListSortedGameServers(req.gsa) } diff --git a/pkg/gameserverallocations/allocator_test.go b/pkg/gameserverallocations/allocator_test.go index 83d0b806b3..19b922ad7f 100644 --- a/pkg/gameserverallocations/allocator_test.go +++ b/pkg/gameserverallocations/allocator_test.go @@ -280,6 +280,7 @@ func TestAllocatorApplyAllocationToGameServer(t *testing.T) { func TestAllocatorApplyAllocationToGameServerCountsListsActions(t *testing.T) { t.Parallel() + m := agtesting.NewMocks() ctx := context.Background() mp := allocationv1.MetaPatch{} @@ -618,6 +619,117 @@ func TestAllocatorRunLocalAllocations(t *testing.T) { }) } +func TestAllocatorRunLocalAllocationsCountsAndLists(t *testing.T) { + t.Parallel() + + runtime.FeatureTestMutex.Lock() + defer runtime.FeatureTestMutex.Unlock() + assert.NoError(t, runtime.ParseFeatures(string(runtime.FeatureCountsAndLists)+"=true")) + + a, m := newFakeAllocator() + + gs1 := agonesv1.GameServer{ObjectMeta: metav1.ObjectMeta{Name: "gs1", Namespace: defaultNs, UID: "1"}, + Status: agonesv1.GameServerStatus{NodeName: "node1", State: agonesv1.GameServerStateReady, + Counters: map[string]agonesv1.CounterStatus{ + "foo": { // Available Capacity == 1000 + Count: 0, + Capacity: 1000, + }}}} + gs2 := agonesv1.GameServer{ObjectMeta: metav1.ObjectMeta{Name: "gs2", Namespace: defaultNs, UID: "2"}, + Status: agonesv1.GameServerStatus{NodeName: "node1", State: agonesv1.GameServerStateReady, + Counters: map[string]agonesv1.CounterStatus{ + "foo": { // Available Capacity == 900 + Count: 100, + Capacity: 1000, + }}}} + gs3 := agonesv1.GameServer{ObjectMeta: metav1.ObjectMeta{Name: "gs3", Namespace: defaultNs, UID: "3"}, + Status: agonesv1.GameServerStatus{NodeName: "node1", State: agonesv1.GameServerStateReady, + Counters: map[string]agonesv1.CounterStatus{ + "foo": { // Available Capacity == 1 + Count: 999, + Capacity: 1000, + }}}} + + gsList := []agonesv1.GameServer{gs1, gs2, gs3} + + m.AgonesClient.AddReactor("list", "gameservers", func(action k8stesting.Action) (bool, k8sruntime.Object, error) { + return true, &agonesv1.GameServerList{Items: gsList}, nil + }) + + m.AgonesClient.AddReactor("update", "gameservers", func(action k8stesting.Action) (bool, k8sruntime.Object, error) { + uo := action.(k8stesting.UpdateAction) + gs := uo.GetObject().(*agonesv1.GameServer) + return true, gs, nil + }) + + ctx, cancel := agtesting.StartInformers(m, a.allocationCache.gameServerSynced) + defer cancel() + + // This call initializes the cache + err := a.allocationCache.syncCache() + assert.Nil(t, err) + + err = a.allocationCache.counter.Run(ctx, 0) + assert.Nil(t, err) + + READY := agonesv1.GameServerStateReady + + gsa1 := &allocationv1.GameServerAllocation{ + ObjectMeta: metav1.ObjectMeta{Namespace: defaultNs}, + Spec: allocationv1.GameServerAllocationSpec{ + Scheduling: apis.Packed, + Selectors: []allocationv1.GameServerSelector{{ + GameServerState: &READY, + }}, + Priorities: []agonesv1.Priority{ + {Type: agonesv1.GameServerPriorityCounter, + Key: "foo", + Order: agonesv1.GameServerPriorityAscending}, + }, + }} + gsa2 := &allocationv1.GameServerAllocation{ + ObjectMeta: metav1.ObjectMeta{Namespace: defaultNs}, + Spec: allocationv1.GameServerAllocationSpec{ + Scheduling: apis.Packed, + Selectors: []allocationv1.GameServerSelector{{ + GameServerState: &READY, + }}, + Priorities: []agonesv1.Priority{ + {Type: agonesv1.GameServerPriorityCounter, + Key: "foo", + Order: agonesv1.GameServerPriorityDescending}, + }, + }} + + // line up 3 in a batch (first sort by Ascending then Descending then Ascending) + j1 := request{gsa: gsa1.DeepCopy(), response: make(chan response)} + a.pendingRequests <- j1 + j2 := request{gsa: gsa2.DeepCopy(), response: make(chan response)} + a.pendingRequests <- j2 + j3 := request{gsa: gsa1.DeepCopy(), response: make(chan response)} + a.pendingRequests <- j3 + + go a.ListenAndAllocate(ctx, 3) + + res1 := <-j1.response + assert.NoError(t, res1.err) + assert.NotNil(t, res1.gs) + assert.Equal(t, agonesv1.GameServerStateAllocated, res1.gs.Status.State) + assert.Equal(t, gs3.ObjectMeta.Name, res1.gs.ObjectMeta.Name) + + res2 := <-j2.response + assert.NoError(t, res2.err) + assert.NotNil(t, res2.gs) + assert.Equal(t, agonesv1.GameServerStateAllocated, res2.gs.Status.State) + assert.Equal(t, gs1.ObjectMeta.Name, res2.gs.ObjectMeta.Name) + + res3 := <-j3.response + assert.NoError(t, res3.err) + assert.NotNil(t, res3.gs) + assert.Equal(t, agonesv1.GameServerStateAllocated, res3.gs.Status.State) + assert.Equal(t, gs2.ObjectMeta.Name, res3.gs.ObjectMeta.Name) +} + func TestControllerAllocationUpdateWorkers(t *testing.T) { t.Run("no error", func(t *testing.T) { a, m := newFakeAllocator() diff --git a/site/content/en/docs/Reference/agones_crd_api_reference.html b/site/content/en/docs/Reference/agones_crd_api_reference.html index 6702dae8d3..8d96bac63f 100644 --- a/site/content/en/docs/Reference/agones_crd_api_reference.html +++ b/site/content/en/docs/Reference/agones_crd_api_reference.html @@ -4180,30 +4180,34 @@

GameServerAll

Packages:

-

autoscaling.agones.dev/v1

+

agones.dev/v1

Package v1 is the v1 version of the API.

Resource Types: -

FleetAutoscaler +

Fleet

-

FleetAutoscaler is the data structure for a FleetAutoscaler resource

+

Fleet is the data structure for a Fleet resource

@@ -4219,7 +4223,7 @@

FleetAutoscaler string

@@ -4228,7 +4232,7 @@

FleetAutoscaler kind
string -

+ @@ -4259,130 +4263,111 @@

FleetAutoscaler

-autoscaling.agones.dev/v1 +agones.dev/v1
FleetAutoscalerFleet
@@ -4248,8 +4252,8 @@

FleetAutoscaler

spec
- -FleetAutoscalerSpec + +FleetSpec
- -
-fleetName
+replicas
-string +int32
+

Replicas are the number of GameServers that should be in this set. Defaults to 0.

-policy
+allocationOverflow
- -FleetAutoscalerPolicy + +AllocationOverflow
-

Autoscaling policy

+(Optional) +

[Stage: Alpha] +[FeatureFlag:FleetAllocationOverflow] +Labels and/or Annotations to apply to overflowing GameServers when the number of Allocated GameServers is more +than the desired replicas on the underlying GameServerSet

-sync
+strategy
- -FleetAutoscalerSync + +Kubernetes apps/v1.DeploymentStrategy
-(Optional) -

Sync defines when FleetAutoscalers runs autoscaling

-
+

Deployment strategy

-status
+scheduling
- -FleetAutoscalerStatus - +agones.dev/agones/pkg/apis.SchedulingStrategy +

Scheduling strategy. Defaults to “Packed”.

- - -

BufferPolicy -

-

-(Appears on: -FleetAutoscalerPolicy) -

-

-

BufferPolicy controls the desired behavior of the buffer policy.

-

- - - - - - - - + +
FieldDescription
-maxReplicas
+priorities
-int32 + +[]Priority +
-

MaxReplicas is the maximum amount of replicas that the fleet may have. -It must be bigger than both MinReplicas and BufferSize

+(Optional) +

(Alpha, CountsAndLists feature flag) The first Priority on the array of Priorities is the most +important for sorting. The Fleetautoscaler will use the first priority for sorting GameServers +by total Capacity in the Fleet and acts as a tie-breaker after sorting the game servers by +State and Strategy. Impacts scale down logic.

-minReplicas
+template
-int32 + +GameServerTemplateSpec +
-

MinReplicas is the minimum amount of replicas that the fleet must have -If zero, it is ignored. -If non zero, it must be smaller than MaxReplicas and bigger than BufferSize

+

Template the GameServer template to apply for this Fleet

+
-bufferSize
+status
-k8s.io/apimachinery/pkg/util/intstr.IntOrString + +FleetStatus + -

BufferSize defines how many replicas the autoscaler tries to have ready all the time -Value can be an absolute number (ex: 5) or a percentage of desired gs instances (ex: 15%) -Absolute number is calculated from percentage by rounding up. -Example: when this is set to 20%, the autoscaler will make sure that 20% -of the fleet’s game server replicas are ready. When this is set to 20, -the autoscaler will make sure that there are 20 available game servers -Must be bigger than 0 -Note: by “ready” we understand in this case “non-allocated”; this is done to ensure robustness -and computation stability in different edge case (fleet just created, not enough -capacity in the cluster etc)

-

CounterPolicy +

GameServer

-(Appears on: -FleetAutoscalerPolicy) -

-

-

CounterPolicy controls the desired behavior of the Counter autoscaler policy.

+

GameServer is the data structure for a GameServer resource. +It is worth noting that while there is a GameServerStatus Status entry for the GameServer, it is not +defined as a subresource - unlike Fleet and other Agones resources. +This is so that we can retain the ability to change multiple aspects of a GameServer in a single atomic operation, +which is particularly useful for operations such as allocation.

@@ -4394,239 +4379,186 @@

CounterPolicy

+apiVersion
+string - + - - -
-key
- -string - -
-

Key is the name of the Counter. Required field.

+ +agones.dev/v1 +
-maxCapacity
- -int64 - -
-

MaxCapacity is the maximum aggregate Counter total capacity across the fleet. -MaxCapacity must be bigger than both MinCapacity and BufferSize. Required field.

+kind
+string
GameServer
-minCapacity
+metadata
-int64 + +Kubernetes meta/v1.ObjectMeta +
-

MinCapacity is the minimum aggregate Counter total capacity across the fleet. -If zero, MinCapacity is ignored. -If non zero, MinCapacity must be smaller than MaxCapacity and bigger than BufferSize.

+Refer to the Kubernetes API documentation for the fields of the +metadata field.
-bufferSize
+spec
-k8s.io/apimachinery/pkg/util/intstr.IntOrString + +GameServerSpec +
-

BufferSize is the size of a buffer of counted items that are available in the Fleet (available -capacity). Value can be an absolute number (ex: 5) or a percentage of desired gs instances -(ex: 5%). An absolute number is calculated from percentage by rounding up. -Must be bigger than 0. Required field.

-
-

FixedIntervalSync -

-

-(Appears on: -FleetAutoscalerSync) -

-

-

FixedIntervalSync controls the desired behavior of the fixed interval based sync.

-

+
+
- - - - - - - - -
FieldDescription
-seconds
+container
-int32 +string
-

Seconds defines how often we run fleet autoscaling in seconds

+

Container specifies which Pod container is the game server. Only required if there is more than one +container defined

-

FleetAutoscaleRequest -

-

-(Appears on: -FleetAutoscaleReview) -

-

-

FleetAutoscaleRequest defines the request to webhook autoscaler endpoint

-

- - - - - - - - - -
FieldDescription
-uid
+ports
-k8s.io/apimachinery/pkg/types.UID + +[]GameServerPort +
-

UID is an identifier for the individual request/response. It allows us to distinguish instances of requests which are -otherwise identical (parallel requests, requests when earlier requests did not modify etc) -The UID is meant to track the round trip (request/response) between the Autoscaler and the WebHook, not the user request. -It is suitable for correlating log entries between the webhook and apiserver, for either auditing or debugging.

+

Ports are the array of ports that can be exposed via the game server

-name
+health
-string + +Health +
-

Name is the name of the Fleet being scaled

+

Health configures health checking

-namespace
+scheduling
-string +agones.dev/agones/pkg/apis.SchedulingStrategy
-

Namespace is the namespace associated with the request (if any).

+

Scheduling strategy. Defaults to “Packed”

-status
+sdkServer
- -FleetStatus + +SdkServer
-

The Fleet’s status values

+

SdkServer specifies parameters for the Agones SDK Server sidecar container

-

FleetAutoscaleResponse -

-

-(Appears on: -FleetAutoscaleReview) -

-

-

FleetAutoscaleResponse defines the response of webhook autoscaler endpoint

-

- - - - - - - - - -
FieldDescription
-uid
+template
-k8s.io/apimachinery/pkg/types.UID + +Kubernetes core/v1.PodTemplateSpec +
-

UID is an identifier for the individual request/response. -This should be copied over from the corresponding FleetAutoscaleRequest.

+

Template describes the Pod that will be created for the GameServer

-scale
+players
-bool + +PlayersSpec +
-

Set to false if no scaling should occur to the Fleet

+(Optional) +

(Alpha, PlayerTracking feature flag) Players provides the configuration for player tracking features.

-replicas
+counters
-int32 + +map[string]agones.dev/agones/pkg/apis/agones/v1.CounterStatus +
-

The targeted replica count

+(Optional) +

(Alpha, CountsAndLists feature flag) Counters and Lists provides the configuration for generic tracking features.

-

FleetAutoscaleReview -

-

-

FleetAutoscaleReview is passed to the webhook with a populated Request value, -and then returned with a populated Response.

-

- - - - + + - - + +
FieldDescription +lists
+ + +map[string]agones.dev/agones/pkg/apis/agones/v1.ListStatus + + +
+
-request
+eviction
- -FleetAutoscaleRequest + +Eviction
+(Optional) +

Eviction specifies the eviction tolerance of the GameServer. Defaults to “Never”.

+
-response
+status
- -FleetAutoscaleResponse + +GameServerStatus @@ -4635,14 +4567,12 @@

FleetAutoscaleReview -

FleetAutoscalerPolicy +

GameServerSet

-(Appears on: -FleetAutoscalerSpec) -

-

-

FleetAutoscalerPolicy describes how to scale a fleet

+

GameServerSet is the data structure for a set of GameServers. +This matches philosophically with the relationship between +Deployments and ReplicaSets

@@ -4654,153 +4584,143 @@

FleetAutoscalerPolicy

+ + + + - +
+
+
-type
- - -FleetAutoscalerPolicyType - - +apiVersion
+string
+ +agones.dev/v1 +
-

Type of autoscaling policy.

+kind
+string
GameServerSet
-buffer
+metadata
- -BufferPolicy + +Kubernetes meta/v1.ObjectMeta
-(Optional) -

Buffer policy config params. Present only if FleetAutoscalerPolicyType = Buffer.

+Refer to the Kubernetes API documentation for the fields of the +metadata field.
-webhook
+spec
- -WebhookPolicy + +GameServerSetSpec
-(Optional) -

Webhook policy config params. Present only if FleetAutoscalerPolicyType = Webhook.

-
- -
-counter
+replicas
- -CounterPolicy - +int32
-(Optional) -

[Stage:Alpha] -[FeatureFlag:CountsAndLists] -Counter policy config params. Present only if FleetAutoscalerPolicyType = Counter.

+

Replicas are the number of GameServers that should be in this set

-list
+allocationOverflow
- -ListPolicy + +AllocationOverflow
(Optional) -

[Stage:Alpha] -[FeatureFlag:CountsAndLists] -List policy config params. Present only if FleetAutoscalerPolicyType = List.

+

[Stage: Alpha] +[FeatureFlag:FleetAllocationOverflow] +Labels and Annotations to apply to GameServers when the number of Allocated GameServers drops below +the desired replicas on the underlying GameServerSet

-

FleetAutoscalerPolicyType -(string alias)

-

-(Appears on: -FleetAutoscalerPolicy) -

-

-

FleetAutoscalerPolicyType is the policy for autoscaling -for a given Fleet

-

-

FleetAutoscalerSpec -

-

-(Appears on: -FleetAutoscaler) -

-

-

FleetAutoscalerSpec is the spec for a Fleet Scaler

-

- - - - + + - - + +
FieldDescription +scheduling
+ +agones.dev/agones/pkg/apis.SchedulingStrategy + +
+

Scheduling strategy. Defaults to “Packed”.

+
-fleetName
+priorities
-string + +[]Priority +
+(Optional) +

(Alpha, CountsAndLists feature flag) The first Priority on the array of Priorities is the most +important for sorting. The Fleetautoscaler will use the first priority for sorting GameServers +by total Capacity in the Fleet and acts as a tie-breaker after sorting the game servers by +State and Strategy. Impacts scale down logic.

-policy
+template
- -FleetAutoscalerPolicy + +GameServerTemplateSpec
-

Autoscaling policy

+

Template the GameServer template to apply for this GameServerSet

+
-sync
+status
- -FleetAutoscalerSync + +GameServerSetStatus -(Optional) -

Sync defines when FleetAutoscalers runs autoscaling

-

FleetAutoscalerStatus +

AggregatedCounterStatus

(Appears on: -FleetAutoscaler) +FleetStatus, +GameServerSetStatus)

-

FleetAutoscalerStatus defines the current status of a FleetAutoscaler

+

AggregatedCounterStatus stores total and allocated Counter tracking values

@@ -4812,75 +4732,55 @@

FleetAutoscalerStatus

- - - -
-currentReplicas
+allocatedCount
-int32 +int64
-

CurrentReplicas is the current number of gameserver replicas -of the fleet managed by this autoscaler, as last seen by the autoscaler

-desiredReplicas
+allocatedCapacity
-int32 +int64
-

DesiredReplicas is the desired number of gameserver replicas -of the fleet managed by this autoscaler, as last calculated by the autoscaler

-lastScaleTime
+count
- -Kubernetes meta/v1.Time - - -
-(Optional) -

lastScaleTime is the last time the FleetAutoscaler scaled the attached fleet,

-
-ableToScale
- -bool +int64
-

AbleToScale indicates that we can access the target fleet

-scalingLimited
+capacity
-bool +int64
-

ScalingLimited indicates that the calculated scale would be above or below the range -defined by MinReplicas and MaxReplicas, and has thus been capped.

-

FleetAutoscalerSync +

AggregatedListStatus

(Appears on: -FleetAutoscalerSpec) +FleetStatus, +GameServerSetStatus)

-

FleetAutoscalerSync describes when to sync a fleet

+

AggregatedListStatus stores total and allocated List tracking values

@@ -4892,50 +4792,55 @@

FleetAutoscalerSync

+ + + + + + + +
-type
+allocatedCount
- -FleetAutoscalerSyncType - +int64
-

Type of autoscaling sync.

-fixedInterval
+allocatedCapacity
- -FixedIntervalSync - +int64 + +
+
+count
+ +int64 + +
+
+capacity
+ +int64
-(Optional) -

FixedInterval config params. Present only if FleetAutoscalerSyncType = FixedInterval.

-

FleetAutoscalerSyncType -(string alias)

-

-(Appears on: -FleetAutoscalerSync) -

-

-

FleetAutoscalerSyncType is the sync strategy for a given Fleet

-

-

ListPolicy +

AggregatedPlayerStatus

(Appears on: -FleetAutoscalerPolicy) +FleetStatus, +GameServerSetStatus)

-

ListPolicy controls the desired behavior of the List autoscaler policy.

+

AggregatedPlayerStatus stores total player tracking values

@@ -4947,66 +4852,81 @@

ListPolicy

+ +
-key
+count
-string +int64
-

Key is the name of the List. Required field.

-maxCapacity
+capacity
int64
-

MaxCapacity is the maximum aggregate List total capacity across the fleet. -MaxCapacity must be bigger than both MinCapacity and BufferSize. Required field.

+

AllocationOverflow +

+

+(Appears on: +FleetSpec, +GameServerSetSpec) +

+

+

AllocationOverflow specifies what labels and/or annotations to apply on Allocated GameServers +if the desired number of the underlying GameServerSet drops below the number of Allocated GameServers +attached to it.

+

+ + + + + + + +
FieldDescription
-minCapacity
+labels
-int64 +map[string]string
-

MinCapacity is the minimum aggregate List total capacity across the fleet. -If zero, it is ignored. -If non zero, it must be smaller than MaxCapacity and bigger than BufferSize.

+(Optional) +

Labels to be applied to the GameServer

-bufferSize
+annotations
-k8s.io/apimachinery/pkg/util/intstr.IntOrString +map[string]string
-

BufferSize is the size of a buffer based on the List capacity that is available over the -current aggregate List length in the Fleet (available capacity). It can be specified either -as an absolute value (i.e. 5) or percentage format (i.e. 5%). -Must be bigger than 0. Required field.

+(Optional) +

Annotations to be applied to the GameServer

-

WebhookPolicy +

CounterStatus

(Appears on: -FleetAutoscalerPolicy) +GameServerSpec, +GameServerStatus)

-

WebhookPolicy controls the desired behavior of the webhook policy. -It contains the description of the webhook autoscaler service -used to form url which is accessible inside the cluster

+

CounterStatus stores the current counter values

@@ -5018,79 +4938,79 @@

WebhookPolicy

+ +
-url
+count
-string +int64
-(Optional) -

url gives the location of the webhook, in standard URL form -(scheme://host:port/path). Exactly one of url or service -must be specified.

-

The host should not refer to a service running in the cluster; use -the service field instead. The host might be resolved via external -DNS in some apiservers (e.g., kube-apiserver cannot resolve -in-cluster DNS as that would be a layering violation). host may -also be an IP address.

-

Please note that using localhost or 127.0.0.1 as a host is -risky unless you take great care to run this webhook on all hosts -which run an apiserver which might need to make calls to this -webhook. Such installs are likely to be non-portable, i.e., not easy -to turn up in a new cluster.

-

The scheme must be “https”; the URL must begin with “https://”.

-

A path is optional, and if present may be any string permissible in -a URL. You may use the path to pass an arbitrary string to the -webhook, for example, a cluster identifier.

-

Attempting to use a user or basic auth e.g. “user:password@” is not -allowed. Fragments (“#…”) and query parameters (“?…”) are not -allowed, either.

-service
+capacity
- -Kubernetes admissionregistration/v1.ServiceReference - +int64
-(Optional) -

service is a reference to the service for this webhook. Either -service or url must be specified.

-

If the webhook is running within the cluster, then you should use service.

+

Eviction +

+

+(Appears on: +GameServerSpec, +GameServerStatus) +

+

+

Eviction specifies the eviction tolerance of the GameServer

+

+ + + + + + + +
FieldDescription
-caBundle
+safe
-[]byte + +EvictionSafe +
-(Optional) -

caBundle is a PEM encoded CA bundle which will be used to validate the webhook’s server certificate. -If unspecified, system trust roots on the apiserver are used.

+

Game server supports termination via SIGTERM: +- Always: Allow eviction for both Cluster Autoscaler and node drain for upgrades +- OnUpgrade: Allow eviction for upgrades alone +- Never (default): Pod should run to completion

-
-

multicluster.agones.dev/v1

+

EvictionSafe +(string alias)

-

Package v1 is the v1 version of the API.

+(Appears on: +Eviction)

-Resource Types: - -

GameServerAllocationPolicy +

+

EvictionSafe specified whether the game server supports termination via SIGTERM

+

+

FleetSpec

-

GameServerAllocationPolicy is the Schema for the gameserverallocationpolicies API

+(Appears on: +Fleet) +

+

+

FleetSpec is the spec for a Fleet

@@ -5102,93 +5022,97 @@

GameServerAllocat

- - - - - - - + + +
-apiVersion
-string
- -multicluster.agones.dev/v1 - +replicas
+ +int32 +
-kind
-string +

Replicas are the number of GameServers that should be in this set. Defaults to 0.

GameServerAllocationPolicy
-metadata
+allocationOverflow
- -Kubernetes meta/v1.ObjectMeta + +AllocationOverflow
-Refer to the Kubernetes API documentation for the fields of the -metadata field. -
-spec
+(Optional) +

[Stage: Alpha] +[FeatureFlag:FleetAllocationOverflow] +Labels and/or Annotations to apply to overflowing GameServers when the number of Allocated GameServers is more +than the desired replicas on the underlying GameServerSet

+
+strategy
- -GameServerAllocationPolicySpec + +Kubernetes apps/v1.DeploymentStrategy
-
-
- +

Deployment strategy

+ + - -
-priority
+scheduling
-int32 +agones.dev/agones/pkg/apis.SchedulingStrategy
+

Scheduling strategy. Defaults to “Packed”.

-weight
+priorities
-int + +[]Priority +
+(Optional) +

(Alpha, CountsAndLists feature flag) The first Priority on the array of Priorities is the most +important for sorting. The Fleetautoscaler will use the first priority for sorting GameServers +by total Capacity in the Fleet and acts as a tie-breaker after sorting the game servers by +State and Strategy. Impacts scale down logic.

-connectionInfo
+template
- -ClusterConnectionInfo + +GameServerTemplateSpec
-
+

Template the GameServer template to apply for this Fleet

-

ClusterConnectionInfo +

FleetStatus

(Appears on: -GameServerAllocationPolicySpec) +Fleet, +FleetAutoscaleRequest)

-

ClusterConnectionInfo defines the connection information for a cluster

+

FleetStatus is the status of a Fleet

@@ -5200,67 +5124,106 @@

ClusterConnectionInfo

+ + + + + + + +
-clusterName
+replicas
-string +int32
-

Optional: the name of the targeted cluster

+

Replicas the total number of current GameServer replicas

-allocationEndpoints
+readyReplicas
-[]string +int32
-

The endpoints for the allocator service in the targeted cluster. -If the AllocationEndpoints is not set, the allocation happens on local cluster. -If there are multiple endpoints any of the endpoints that can handle allocation request should suffice

+

ReadyReplicas are the number of Ready GameServer replicas

-secretName
+reservedReplicas
-string +int32
-

The name of the secret that contains TLS client certificates to connect the allocator server in the targeted cluster

+

ReservedReplicas are the total number of Reserved GameServer replicas in this fleet. +Reserved instances won’t be deleted on scale down, but won’t cause an autoscaler to scale up.

-namespace
+allocatedReplicas
-string +int32
-

The cluster namespace from which to allocate gameservers

+

AllocatedReplicas are the number of Allocated GameServer replicas

-serverCa
+players
-[]byte + +AggregatedPlayerStatus +
-

The PEM encoded server CA, used by the allocator client to authenticate the remote server.

+(Optional) +

[Stage:Alpha] +[FeatureFlag:PlayerTracking] +Players are the current total player capacity and count for this Fleet

+
+counters
+ + +map[string]agones.dev/agones/pkg/apis/agones/v1.AggregatedCounterStatus + + +
+(Optional) +

(Alpha, CountsAndLists feature flag) Counters provides aggregated Counter capacity and Counter +count for this Fleet.

+
+lists
+ + +map[string]agones.dev/agones/pkg/apis/agones/v1.AggregatedListStatus + + +
+(Optional) +

(Alpha, CountsAndLists feature flag) Lists provides aggregated List capacityv and List values +for this Fleet.

-

ConnectionInfoIterator +

GameServerPort

-

ConnectionInfoIterator an iterator on ClusterConnectionInfo

+(Appears on: +GameServerSpec) +

+

+

GameServerPort defines a set of Ports that +are to be exposed via the GameServer

@@ -5272,118 +5235,89 @@

ConnectionInfoIterato

- - - - - -
-currPriority
- -int - -
-

currPriority Current priority index from the orderedPriorities

-
-orderedPriorities
+name
-[]int32 +string
-

orderedPriorities list of ordered priorities

+

Name is the descriptive name of the port

-priorityToCluster
+portPolicy
-map[int32]map[string][]*agones.dev/agones/pkg/apis/multicluster/v1.GameServerAllocationPolicy + +PortPolicy +
-

priorityToCluster Map of priority to cluster-policies map

+

PortPolicy defines the policy for how the HostPort is populated. +Dynamic port will allocate a HostPort within the selected MIN_PORT and MAX_PORT range passed to the controller +at installation time. +When Static portPolicy is specified, HostPort is required, to specify the port that game clients will +connect to

-clusterBlackList
+container
-map[string]bool +string
-

clusterBlackList the cluster blacklist for the clusters that has already returned

+(Optional) +

Container is the name of the container on which to open the port. Defaults to the game server container.

-

GameServerAllocationPolicySpec -

-

-(Appears on: -GameServerAllocationPolicy) -

-

-

GameServerAllocationPolicySpec defines the desired state of GameServerAllocationPolicy

-

- - - - - - - -
FieldDescription
-priority
+containerPort
int32
+

ContainerPort is the port that is being opened on the specified container’s process

-weight
+hostPort
-int +int32
+

HostPort the port exposed on the host for clients to connect to

-connectionInfo
+protocol
- -ClusterConnectionInfo + +Kubernetes core/v1.Protocol
+

Protocol is the network protocol being used. Defaults to UDP. TCP and TCPUDP are other options.

-
-

agones.dev/v1

+

GameServerSetSpec +

-

Package v1 is the v1 version of the API.

+(Appears on: +GameServerSet)

-Resource Types: - -

Fleet -

-

Fleet is the data structure for a Fleet resource

+

GameServerSetSpec the specification for GameServerSet

@@ -5395,208 +5329,213 @@

Fleet

- - - - - -
-apiVersion
-string
- -agones.dev/v1 - +replicas
+ +int32 +
-kind
-string +

Replicas are the number of GameServers that should be in this set

Fleet
-metadata
+allocationOverflow
- -Kubernetes meta/v1.ObjectMeta + +AllocationOverflow
-Refer to the Kubernetes API documentation for the fields of the -metadata field. +(Optional) +

[Stage: Alpha] +[FeatureFlag:FleetAllocationOverflow] +Labels and Annotations to apply to GameServers when the number of Allocated GameServers drops below +the desired replicas on the underlying GameServerSet

-spec
+scheduling
- -FleetSpec - +agones.dev/agones/pkg/apis.SchedulingStrategy
-
-
- +

Scheduling strategy. Defaults to “Packed”.

+ + + +
-replicas
+priorities
-int32 + +[]Priority +
-

Replicas are the number of GameServers that should be in this set. Defaults to 0.

+(Optional) +

(Alpha, CountsAndLists feature flag) The first Priority on the array of Priorities is the most +important for sorting. The Fleetautoscaler will use the first priority for sorting GameServers +by total Capacity in the Fleet and acts as a tie-breaker after sorting the game servers by +State and Strategy. Impacts scale down logic.

-allocationOverflow
+template
- -AllocationOverflow + +GameServerTemplateSpec
-(Optional) -

[Stage: Alpha] -[FeatureFlag:FleetAllocationOverflow] -Labels and/or Annotations to apply to overflowing GameServers when the number of Allocated GameServers is more -than the desired replicas on the underlying GameServerSet

+

Template the GameServer template to apply for this GameServerSet

+

GameServerSetStatus +

+

+(Appears on: +GameServerSet) +

+

+

GameServerSetStatus is the status of a GameServerSet

+

+ + + + + + + + - -
FieldDescription
-strategy
+replicas
- -Kubernetes apps/v1.DeploymentStrategy - +int32
-

Deployment strategy

+

Replicas is the total number of current GameServer replicas

-scheduling
+readyReplicas
-agones.dev/agones/pkg/apis.SchedulingStrategy +int32
-

Scheduling strategy. Defaults to “Packed”.

+

ReadyReplicas is the number of Ready GameServer replicas

-priorities
+reservedReplicas
- -[]Priority - +int32
-(Optional) -

(Alpha, CountsAndLists feature flag) The first Priority on the array of Priorities is the most -important for sorting. The Fleetautoscaler will use the first priority for sorting GameServers -by total Capacity in the Fleet and acts as a tie-breaker after sorting the game servers by -State and Strategy. Impacts scale down logic.

+

ReservedReplicas is the number of Reserved GameServer replicas

-template
+allocatedReplicas
- -GameServerTemplateSpec - +int32
-

Template the GameServer template to apply for this Fleet

-
+

AllocatedReplicas is the number of Allocated GameServer replicas

-status
+shutdownReplicas
- -FleetStatus - +int32
+

ShutdownReplicas is the number of Shutdown GameServers replicas

-

GameServer -

-

-

GameServer is the data structure for a GameServer resource. -It is worth noting that while there is a GameServerStatus Status entry for the GameServer, it is not -defined as a subresource - unlike Fleet and other Agones resources. -This is so that we can retain the ability to change multiple aspects of a GameServer in a single atomic operation, -which is particularly useful for operations such as allocation.

-

- - - - - - - - - - - - + + +
FieldDescription
-apiVersion
-string
- -agones.dev/v1 - +players
+ + +AggregatedPlayerStatus + +
-kind
-string +(Optional) +

[Stage:Alpha] +[FeatureFlag:PlayerTracking] +Players is the current total player capacity and count for this GameServerSet

GameServer
-metadata
+counters
- -Kubernetes meta/v1.ObjectMeta + +map[string]agones.dev/agones/pkg/apis/agones/v1.AggregatedCounterStatus
-Refer to the Kubernetes API documentation for the fields of the -metadata field. +(Optional) +

(Alpha, CountsAndLists feature flag) Counters provides aggregated Counter capacity and Counter +count for this GameServerSet.

-spec
+lists
- -GameServerSpec + +map[string]agones.dev/agones/pkg/apis/agones/v1.AggregatedListStatus
-
-
+(Optional) +

(Alpha, CountsAndLists feature flag) Lists provides aggregated List capacity and List values +for this GameServerSet.

+
+

GameServerSpec +

+

+(Appears on: +GameServer, +GameServerTemplateSpec) +

+

+

GameServerSpec is the spec for a GameServer resource

+

+ + + + + + + -
FieldDescription
container
@@ -5726,29 +5665,26 @@

GameServer

Eviction specifies the eviction tolerance of the GameServer. Defaults to “Never”.

- - - - -status
- - -GameServerStatus - - - - - - -

GameServerSet +

GameServerState +(string alias)

+

+(Appears on: +GameServerSelector, +GameServerStatus) +

+

+

GameServerState is the state for the GameServer

+

+

GameServerStatus

-

GameServerSet is the data structure for a set of GameServers. -This matches philosophically with the relationship between -Deployments and ReplicaSets

+(Appears on: +GameServer) +

+

+

GameServerStatus is the status for a GameServer resource

@@ -5760,143 +5696,129 @@

GameServerSet

- - - -
-apiVersion
-string
- -agones.dev/v1 - +state
+ + +GameServerState + +
-kind
-string +

GameServerState is the current state of a GameServer, e.g. Creating, Starting, Ready, etc

GameServerSet
-metadata
+ports
- -Kubernetes meta/v1.ObjectMeta + +[]GameServerStatusPort
-Refer to the Kubernetes API documentation for the fields of the -metadata field.
-spec
+address
- -GameServerSetSpec - +string
-
-
- + + - -
-replicas
+nodeName
-int32 +string
-

Replicas are the number of GameServers that should be in this set

-allocationOverflow
+reservedUntil
- -AllocationOverflow + +Kubernetes meta/v1.Time
-(Optional) -

[Stage: Alpha] -[FeatureFlag:FleetAllocationOverflow] -Labels and Annotations to apply to GameServers when the number of Allocated GameServers drops below -the desired replicas on the underlying GameServerSet

-scheduling
+players
-agones.dev/agones/pkg/apis.SchedulingStrategy + +PlayerStatus +
-

Scheduling strategy. Defaults to “Packed”.

+(Optional) +

[Stage:Alpha] +[FeatureFlag:PlayerTracking]

-priorities
+counters
- -[]Priority + +map[string]agones.dev/agones/pkg/apis/agones/v1.CounterStatus
(Optional) -

(Alpha, CountsAndLists feature flag) The first Priority on the array of Priorities is the most -important for sorting. The Fleetautoscaler will use the first priority for sorting GameServers -by total Capacity in the Fleet and acts as a tie-breaker after sorting the game servers by -State and Strategy. Impacts scale down logic.

+

(Alpha, CountsAndLists feature flag) Counters and Lists provides the configuration for generic tracking features.

-template
+lists
- -GameServerTemplateSpec + +map[string]agones.dev/agones/pkg/apis/agones/v1.ListStatus
-

Template the GameServer template to apply for this GameServerSet

-
+(Optional)
-status
+eviction
- -GameServerSetStatus + +Eviction
+(Optional) +

Eviction specifies the eviction tolerance of the GameServer.

-

AggregatedCounterStatus +

GameServerStatusPort

(Appears on: -FleetStatus, -GameServerSetStatus) +GameServerAllocationStatus, +GameServerStatus)

-

AggregatedCounterStatus stores total and allocated Counter tracking values

+

GameServerStatusPort shows the port that was allocated to a +GameServer.

@@ -5908,29 +5830,9 @@

AggregatedCounterStatus

- - - - - - - -
-allocatedCount
- -int64 - -
-
-allocatedCapacity
- -int64 - -
-
-count
+name
-int64 +string
@@ -5938,9 +5840,9 @@

AggregatedCounterStatus

-capacity
+port
-int64 +int32
@@ -5948,15 +5850,15 @@

AggregatedCounterStatus

-

AggregatedListStatus +

GameServerTemplateSpec

(Appears on: -FleetStatus, -GameServerSetStatus) +FleetSpec, +GameServerSetSpec)

-

AggregatedListStatus stores total and allocated List tracking values

+

GameServerTemplateSpec is a template for GameServers

@@ -5968,155 +5870,141 @@

AggregatedListStatus

- +
+
+
-allocatedCount
+metadata
-int64 + +Kubernetes meta/v1.ObjectMeta +
+Refer to the Kubernetes API documentation for the fields of the +metadata field.
-allocatedCapacity
+spec
-int64 + +GameServerSpec +
-
- -
-count
+container
-int64 +string
+

Container specifies which Pod container is the game server. Only required if there is more than one +container defined

-capacity
+ports
-int64 + +[]GameServerPort +
+

Ports are the array of ports that can be exposed via the game server

-

AggregatedPlayerStatus -

-

-(Appears on: -FleetStatus, -GameServerSetStatus) -

-

-

AggregatedPlayerStatus stores total player tracking values

-

- - - - + + - - - -
FieldDescription +health
+ + +Health + + +
+

Health configures health checking

+
-count
+scheduling
-int64 +agones.dev/agones/pkg/apis.SchedulingStrategy
+

Scheduling strategy. Defaults to “Packed”

-capacity
+sdkServer
-int64 + +SdkServer +
+

SdkServer specifies parameters for the Agones SDK Server sidecar container

-

AllocationOverflow -

-

-(Appears on: -FleetSpec, -GameServerSetSpec) -

-

-

AllocationOverflow specifies what labels and/or annotations to apply on Allocated GameServers -if the desired number of the underlying GameServerSet drops below the number of Allocated GameServers -attached to it.

-

- - - - + + - - - -
FieldDescription +template
+ + +Kubernetes core/v1.PodTemplateSpec + + +
+

Template describes the Pod that will be created for the GameServer

+
-labels
+players
-map[string]string + +PlayersSpec +
(Optional) -

Labels to be applied to the GameServer

+

(Alpha, PlayerTracking feature flag) Players provides the configuration for player tracking features.

-annotations
+counters
-map[string]string + +map[string]agones.dev/agones/pkg/apis/agones/v1.CounterStatus +
(Optional) -

Annotations to be applied to the GameServer

+

(Alpha, CountsAndLists feature flag) Counters and Lists provides the configuration for generic tracking features.

-

CounterStatus -

-

-(Appears on: -GameServerSpec, -GameServerStatus) -

-

-

CounterStatus stores the current counter values

-

- - - - - - - - + +
FieldDescription
-count
+lists
-int64 + +map[string]agones.dev/agones/pkg/apis/agones/v1.ListStatus +
@@ -6124,25 +6012,31 @@

CounterStatus

-capacity
+eviction
-int64 + +Eviction +
+(Optional) +

Eviction specifies the eviction tolerance of the GameServer. Defaults to “Never”.

+
-

Eviction +

Health

(Appears on: -GameServerSpec, -GameServerStatus) +GameServerSpec)

-

Eviction specifies the eviction tolerance of the GameServer

+

Health configures health checking on the GameServer

@@ -6154,141 +6048,98 @@

Eviction

- -
-safe
+disabled
- -EvictionSafe - +bool
-

Game server supports termination via SIGTERM: -- Always: Allow eviction for both Cluster Autoscaler and node drain for upgrades -- OnUpgrade: Allow eviction for upgrades alone -- Never (default): Pod should run to completion

+

Disabled is whether health checking is disabled or not

-

EvictionSafe -(string alias)

-

-(Appears on: -Eviction) -

-

-

EvictionSafe specified whether the game server supports termination via SIGTERM

-

-

FleetSpec -

-

-(Appears on: -Fleet) -

-

-

FleetSpec is the spec for a Fleet

-

- - - - - - - - + +
FieldDescription
-replicas
+periodSeconds
int32
-

Replicas are the number of GameServers that should be in this set. Defaults to 0.

+

PeriodSeconds is the number of seconds each health ping has to occur in

-allocationOverflow
+failureThreshold
- -AllocationOverflow - +int32
-(Optional) -

[Stage: Alpha] -[FeatureFlag:FleetAllocationOverflow] -Labels and/or Annotations to apply to overflowing GameServers when the number of Allocated GameServers is more -than the desired replicas on the underlying GameServerSet

+

FailureThreshold how many failures in a row constitutes unhealthy

-strategy
+initialDelaySeconds
- -Kubernetes apps/v1.DeploymentStrategy - +int32
-

Deployment strategy

+

InitialDelaySeconds initial delay before checking health

+

ListStatus +

+

+(Appears on: +GameServerSpec, +GameServerStatus) +

+

+

ListStatus stores the current list values

+

+ + - - + + + +
-scheduling
- -agones.dev/agones/pkg/apis.SchedulingStrategy - -
-

Scheduling strategy. Defaults to “Packed”.

-
FieldDescription
-priorities
+capacity
- -[]Priority - +int64
-(Optional) -

(Alpha, CountsAndLists feature flag) The first Priority on the array of Priorities is the most -important for sorting. The Fleetautoscaler will use the first priority for sorting GameServers -by total Capacity in the Fleet and acts as a tie-breaker after sorting the game servers by -State and Strategy. Impacts scale down logic.

-template
+values
- -GameServerTemplateSpec - +[]string
-

Template the GameServer template to apply for this Fleet

-

FleetStatus +

PlayerStatus

(Appears on: -Fleet, -FleetAutoscaleRequest) +GameServerStatus)

-

FleetStatus is the status of a Fleet

+

PlayerStatus stores the current player capacity values

@@ -6300,106 +6151,137 @@

FleetStatus

+ +
-replicas
+count
-int32 +int64
-

Replicas the total number of current GameServer replicas

-readyReplicas
+capacity
-int32 +int64
-

ReadyReplicas are the number of Ready GameServer replicas

-reservedReplicas
+ids
-int32 +[]string
-

ReservedReplicas are the total number of Reserved GameServer replicas in this fleet. -Reserved instances won’t be deleted on scale down, but won’t cause an autoscaler to scale up.

+

PlayersSpec +

+

+(Appears on: +GameServerSpec) +

+

+

PlayersSpec tracks the initial player capacity

+

+ + + + + + + + + +
FieldDescription
-allocatedReplicas
+initialCapacity
-int32 +int64
-

AllocatedReplicas are the number of Allocated GameServer replicas

+

PortPolicy +(string alias)

+

+(Appears on: +GameServerPort) +

+

+

PortPolicy is the port policy for the GameServer

+

+

Priority +

+

+(Appears on: +FleetSpec, +GameServerAllocationSpec, +GameServerSetSpec) +

+

+

Priority is a sorting option for GameServers with Counters or Lists based on the Capacity. +Type: Sort by a “Counter” or a “List”. +Key: The name of the Counter or List. If not found on the GameServer, has no impact. +Order: Sort by “Ascending” or “Descending”. “Descending” a bigger Capacity is preferred. +“Ascending” would be smaller Capacity is preferred.

+

+ + + + + + + +
FieldDescription
-players
+type
- -AggregatedPlayerStatus - +string
-(Optional) -

[Stage:Alpha] -[FeatureFlag:PlayerTracking] -Players are the current total player capacity and count for this Fleet

-counters
+key
- -map[string]agones.dev/agones/pkg/apis/agones/v1.AggregatedCounterStatus - +string
-(Optional) -

(Alpha, CountsAndLists feature flag) Counters provides aggregated Counter capacity and Counter -count for this Fleet.

-lists
+order
- -map[string]agones.dev/agones/pkg/apis/agones/v1.AggregatedListStatus - +string
-(Optional) -

(Alpha, CountsAndLists feature flag) Lists provides aggregated List capacityv and List values -for this Fleet.

-

GameServerPort +

SdkServer

(Appears on: GameServerSpec)

-

GameServerPort defines a set of Ports that -are to be exposed via the GameServer

+

SdkServer specifies parameters for the Agones SDK Server sidecar container

@@ -6411,89 +6293,64 @@

GameServerPort

- - - - - - - - - - - -
-name
- -string - -
-

Name is the descriptive name of the port

-
-portPolicy
+logLevel
- -PortPolicy + +SdkServerLogLevel
-

PortPolicy defines the policy for how the HostPort is populated. -Dynamic port will allocate a HostPort within the selected MIN_PORT and MAX_PORT range passed to the controller -at installation time. -When Static portPolicy is specified, HostPort is required, to specify the port that game clients will -connect to

+

LogLevel for SDK server (sidecar) logs. Defaults to “Info”

-container
+grpcPort
-string +int32
-(Optional) -

Container is the name of the container on which to open the port. Defaults to the game server container.

+

GRPCPort is the port on which the SDK Server binds the gRPC server to accept incoming connections

-containerPort
+httpPort
int32
-

ContainerPort is the port that is being opened on the specified container’s process

-
-hostPort
- -int32 - -
-

HostPort the port exposed on the host for clients to connect to

-
-protocol
- - -Kubernetes core/v1.Protocol - - -
-

Protocol is the network protocol being used. Defaults to UDP. TCP and TCPUDP are other options.

+

HTTPPort is the port on which the SDK Server binds the HTTP gRPC gateway server to accept incoming connections

-

GameServerSetSpec -

+

SdkServerLogLevel +(string alias)

(Appears on: -GameServerSet) +SdkServer)

-

GameServerSetSpec the specification for GameServerSet

+

SdkServerLogLevel is the log level for SDK server (sidecar) logs

+

+
+

allocation.agones.dev/v1

+

+

Package v1 is the v1 version of the API.

+

+Resource Types: + +

GameServerAllocation +

+

+

GameServerAllocation is the data structure for allocating against a set of +GameServers, defined selectors selectors

@@ -6505,204 +6362,208 @@

GameServerSetSpec

+ + + + - +
+
+
-replicas
- -int32 - +apiVersion
+string
+ +allocation.agones.dev/v1 +
-

Replicas are the number of GameServers that should be in this set

+kind
+string
GameServerAllocation
-allocationOverflow
+metadata
- -AllocationOverflow + +Kubernetes meta/v1.ObjectMeta
-(Optional) -

[Stage: Alpha] -[FeatureFlag:FleetAllocationOverflow] -Labels and Annotations to apply to GameServers when the number of Allocated GameServers drops below -the desired replicas on the underlying GameServerSet

+Refer to the Kubernetes API documentation for the fields of the +metadata field.
-scheduling
+spec
-agones.dev/agones/pkg/apis.SchedulingStrategy + +GameServerAllocationSpec +
-

Scheduling strategy. Defaults to “Packed”.

-
- -
-priorities
+multiClusterSetting
- -[]Priority + +MultiClusterSetting
-(Optional) -

(Alpha, CountsAndLists feature flag) The first Priority on the array of Priorities is the most -important for sorting. The Fleetautoscaler will use the first priority for sorting GameServers -by total Capacity in the Fleet and acts as a tie-breaker after sorting the game servers by -State and Strategy. Impacts scale down logic.

+

MultiClusterPolicySelector if specified, multi-cluster policies are applied. +Otherwise, allocation will happen locally.

-template
+required
- -GameServerTemplateSpec + +GameServerSelector
-

Template the GameServer template to apply for this GameServerSet

+

Deprecated: use field Selectors instead. If Selectors is set, this field is ignored. +Required is the GameServer selector from which to choose GameServers from. +Defaults to all GameServers.

-

GameServerSetStatus -

-

-(Appears on: -GameServerSet) -

-

-

GameServerSetStatus is the status of a GameServerSet

-

- - - - - - - - + +
FieldDescription
-replicas
+preferred
-int32 + +[]GameServerSelector +
-

Replicas is the total number of current GameServer replicas

+

Deprecated: use field Selectors instead. If Selectors is set, this field is ignored. +Preferred is an ordered list of preferred GameServer selectors +that are optional to be fulfilled, but will be searched before the required selector. +If the first selector is not matched, the selection attempts the second selector, and so on. +If any of the preferred selectors are matched, the required selector is not considered. +This is useful for things like smoke testing of new game servers.

-readyReplicas
+priorities
-int32 + +[]Priority +
-

ReadyReplicas is the number of Ready GameServer replicas

+(Optional) +

(Alpha, CountsAndLists feature flag) The first Priority on the array of Priorities is the most +important for sorting. The allocator will use the first priority for sorting GameServers by +available Capacity in the Selector set. Acts as a tie-breaker after sorting the game servers +by State and Strategy Packed. Impacts which GameServer is checked first.

-reservedReplicas
+selectors
-int32 + +[]GameServerSelector +
-

ReservedReplicas is the number of Reserved GameServer replicas

+

Ordered list of GameServer label selectors. +If the first selector is not matched, the selection attempts the second selector, and so on. +This is useful for things like smoke testing of new game servers. +Note: This field can only be set if neither Required or Preferred is set.

-allocatedReplicas
+scheduling
-int32 +agones.dev/agones/pkg/apis.SchedulingStrategy
-

AllocatedReplicas is the number of Allocated GameServer replicas

+

Scheduling strategy. Defaults to “Packed”.

-shutdownReplicas
+metadata
-int32 + +MetaPatch +
-

ShutdownReplicas is the number of Shutdown GameServers replicas

+

MetaPatch is optional custom metadata that is added to the game server at allocation +You can use this to tell the server necessary session data

-players
+counters
- -AggregatedPlayerStatus + +map[string]agones.dev/agones/pkg/apis/allocation/v1.CounterAction
(Optional) -

[Stage:Alpha] -[FeatureFlag:PlayerTracking] -Players is the current total player capacity and count for this GameServerSet

+

(Alpha, CountsAndLists feature flag) Counters and Lists provide a set of actions to perform +on Counters and Lists during allocation.

-counters
+lists
- -map[string]agones.dev/agones/pkg/apis/agones/v1.AggregatedCounterStatus + +map[string]agones.dev/agones/pkg/apis/allocation/v1.ListAction
-(Optional) -

(Alpha, CountsAndLists feature flag) Counters provides aggregated Counter capacity and Counter -count for this GameServerSet.

+
-lists
+status
- -map[string]agones.dev/agones/pkg/apis/agones/v1.AggregatedListStatus + +GameServerAllocationStatus -(Optional) -

(Alpha, CountsAndLists feature flag) Lists provides aggregated List capacity and List values -for this GameServerSet.

-

GameServerSpec +

CounterAction

(Appears on: -GameServer, -GameServerTemplateSpec) +GameServerAllocationSpec)

-

GameServerSpec is the spec for a GameServer resource

+

CounterAction is an optional action that can be performed on a Counter at allocation. +Action: “Increment” or “Decrement” the Counter’s Count (optional). Must also define the Amount. +Amount: The amount to increment or decrement the Count (optional). Must be a positive integer. +Capacity: Update the maximum capacity of the Counter to this number (optional). Min 0, Max int64.

@@ -6714,114 +6575,79 @@

GameServerSpec

+ +
-container
+action
string
-

Container specifies which Pod container is the game server. Only required if there is more than one -container defined

-ports
+amount
- -[]GameServerPort - +int64
-

Ports are the array of ports that can be exposed via the game server

-health
+capacity
- -Health - +int64
-

Health configures health checking

+

CounterSelector +

+

+(Appears on: +GameServerSelector) +

+

+

CounterSelector is the filter options for a GameServer based on the count and/or available capacity. +0 for MaxCount or MaxAvailable means unlimited maximum. Default for all fields: 0

+

+ + - - - - - - - - - - + + + +
-scheduling
- -agones.dev/agones/pkg/apis.SchedulingStrategy - -
-

Scheduling strategy. Defaults to “Packed”

-
-sdkServer
- - -SdkServer - - -
-

SdkServer specifies parameters for the Agones SDK Server sidecar container

-
-template
- - -Kubernetes core/v1.PodTemplateSpec - - -
-

Template describes the Pod that will be created for the GameServer

-
FieldDescription
-players
+minCount
- -PlayersSpec - +int64
-(Optional) -

(Alpha, PlayerTracking feature flag) Players provides the configuration for player tracking features.

-counters
+maxCount
- -map[string]agones.dev/agones/pkg/apis/agones/v1.CounterStatus - +int64
-(Optional) -

(Alpha, CountsAndLists feature flag) Counters and Lists provides the configuration for generic tracking features.

-lists
+minAvailable
- -map[string]agones.dev/agones/pkg/apis/agones/v1.ListStatus - +int64
@@ -6829,38 +6655,24 @@

GameServerSpec

-eviction
+maxAvailable
- -Eviction - +int64
-(Optional) -

Eviction specifies the eviction tolerance of the GameServer. Defaults to “Never”.

-

GameServerState -(string alias)

-

-(Appears on: -GameServerSelector, -GameServerStatus) -

-

-

GameServerState is the state for the GameServer

-

-

GameServerStatus +

GameServerAllocationSpec

(Appears on: -GameServer) +GameServerAllocation)

-

GameServerStatus is the status for a GameServer resource

+

GameServerAllocationSpec is the spec for a GameServerAllocation

@@ -6872,129 +6684,155 @@

GameServerStatus

-state
+multiClusterSetting
- -GameServerState + +MultiClusterSetting
-

GameServerState is the current state of a GameServer, e.g. Creating, Starting, Ready, etc

+

MultiClusterPolicySelector if specified, multi-cluster policies are applied. +Otherwise, allocation will happen locally.

-ports
+required
- -[]GameServerStatusPort + +GameServerSelector
+

Deprecated: use field Selectors instead. If Selectors is set, this field is ignored. +Required is the GameServer selector from which to choose GameServers from. +Defaults to all GameServers.

-address
+preferred
-string + +[]GameServerSelector +
+

Deprecated: use field Selectors instead. If Selectors is set, this field is ignored. +Preferred is an ordered list of preferred GameServer selectors +that are optional to be fulfilled, but will be searched before the required selector. +If the first selector is not matched, the selection attempts the second selector, and so on. +If any of the preferred selectors are matched, the required selector is not considered. +This is useful for things like smoke testing of new game servers.

-nodeName
+priorities
-string + +[]Priority +
+(Optional) +

(Alpha, CountsAndLists feature flag) The first Priority on the array of Priorities is the most +important for sorting. The allocator will use the first priority for sorting GameServers by +available Capacity in the Selector set. Acts as a tie-breaker after sorting the game servers +by State and Strategy Packed. Impacts which GameServer is checked first.

-reservedUntil
+selectors
- -Kubernetes meta/v1.Time + +[]GameServerSelector
+

Ordered list of GameServer label selectors. +If the first selector is not matched, the selection attempts the second selector, and so on. +This is useful for things like smoke testing of new game servers. +Note: This field can only be set if neither Required or Preferred is set.

-players
+scheduling
- -PlayerStatus - +agones.dev/agones/pkg/apis.SchedulingStrategy
-(Optional) -

[Stage:Alpha] -[FeatureFlag:PlayerTracking]

+

Scheduling strategy. Defaults to “Packed”.

-counters
+metadata
- -map[string]agones.dev/agones/pkg/apis/agones/v1.CounterStatus + +MetaPatch
-(Optional) -

(Alpha, CountsAndLists feature flag) Counters and Lists provides the configuration for generic tracking features.

+

MetaPatch is optional custom metadata that is added to the game server at allocation +You can use this to tell the server necessary session data

-lists
+counters
- -map[string]agones.dev/agones/pkg/apis/agones/v1.ListStatus + +map[string]agones.dev/agones/pkg/apis/allocation/v1.CounterAction
(Optional) +

(Alpha, CountsAndLists feature flag) Counters and Lists provide a set of actions to perform +on Counters and Lists during allocation.

-eviction
+lists
- -Eviction + +map[string]agones.dev/agones/pkg/apis/allocation/v1.ListAction
-(Optional) -

Eviction specifies the eviction tolerance of the GameServer.

-

GameServerStatusPort +

GameServerAllocationState +(string alias)

+

+(Appears on: +GameServerAllocationStatus) +

+

+

GameServerAllocationState is the Allocation state

+

+

GameServerAllocationStatus

(Appears on: -GameServerAllocationStatus, -GameServerStatus) +GameServerAllocation)

-

GameServerStatusPort shows the port that was allocated to a -GameServer.

+

GameServerAllocationStatus is the status for an GameServerAllocation resource

@@ -7006,213 +6844,237 @@

GameServerStatusPort

- -
-name
+state
-string + +GameServerAllocationState +
+

GameServerState is the current state of an GameServerAllocation, e.g. Allocated, or UnAllocated

-port
+gameServerName
-int32 +string
-

GameServerTemplateSpec -

-

-(Appears on: -FleetSpec, -GameServerSetSpec) -

-

-

GameServerTemplateSpec is a template for GameServers

-

- - - - - - - -
FieldDescription
-metadata
+ports
- -Kubernetes meta/v1.ObjectMeta + +[]GameServerStatusPort
-Refer to the Kubernetes API documentation for the fields of the -metadata field.
-spec
+address
- -GameServerSpec - +string
-
-
- + + - - +
-container
+nodeName
string
-

Container specifies which Pod container is the game server. Only required if there is more than one -container defined

-ports
+source
- -[]GameServerPort - +string
-

Ports are the array of ports that can be exposed via the game server

+

If the allocation is from a remote cluster, Source is the endpoint of the remote agones-allocator. +Otherwise, Source is “local”

-health
+metadata
- -Health + +GameServerMetadata
-

Health configures health checking

-scheduling
+
+

GameServerMetadata +

+

+(Appears on: +GameServerAllocationStatus) +

+

+

GameServerMetadata is the metadata from the allocated game server at allocation time

+

+ + + + + + + + + + + +
FieldDescription
+labels
-agones.dev/agones/pkg/apis.SchedulingStrategy +map[string]string
-

Scheduling strategy. Defaults to “Packed”

-sdkServer
+annotations
- -SdkServer - +map[string]string
-

SdkServer specifies parameters for the Agones SDK Server sidecar container

+

GameServerSelector +

+

+(Appears on: +GameServerAllocationSpec) +

+

+

GameServerSelector contains all the filter options for selecting +a GameServer for allocation.

+

+ + + + + + + + - -
FieldDescription
-template
+LabelSelector
- -Kubernetes core/v1.PodTemplateSpec + +Kubernetes meta/v1.LabelSelector
-

Template describes the Pod that will be created for the GameServer

+

+(Members of LabelSelector are embedded into this type.) +

+

See: https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/

-players
+gameServerState
- -PlayersSpec + +GameServerState
(Optional) -

(Alpha, PlayerTracking feature flag) Players provides the configuration for player tracking features.

+

[Stage:Beta] +[FeatureFlag:StateAllocationFilter] +GameServerState specifies which State is the filter to be used when attempting to retrieve a GameServer +via Allocation. Defaults to “Ready”. The only other option is “Allocated”, which can be used in conjunction with +label/annotation/player selectors to retrieve an already Allocated GameServer.

-counters
+players
- -map[string]agones.dev/agones/pkg/apis/agones/v1.CounterStatus + +PlayerSelector
(Optional) -

(Alpha, CountsAndLists feature flag) Counters and Lists provides the configuration for generic tracking features.

+

[Stage:Alpha] +[FeatureFlag:PlayerAllocationFilter] +Players provides a filter on minimum and maximum values for player capacity when retrieving a GameServer +through Allocation. Defaults to no limits.

-lists
+counters
- -map[string]agones.dev/agones/pkg/apis/agones/v1.ListStatus + +map[string]agones.dev/agones/pkg/apis/allocation/v1.CounterSelector
+(Optional) +

(Alpha, CountsAndLists feature flag) Counters provides filters on minimum and maximum values +for a Counter’s count and available capacity when retrieving a GameServer through Allocation. +Defaults to no limits.

-eviction
+lists
- -Eviction + +map[string]agones.dev/agones/pkg/apis/allocation/v1.ListSelector
(Optional) -

Eviction specifies the eviction tolerance of the GameServer. Defaults to “Never”.

-
+

(Alpha, CountsAndLists feature flag) Lists provides filters on minimum and maximum values +for List capacity, and for the existence of a value in a List, when retrieving a GameServer +through Allocation. Defaults to no limits.

-

Health +

ListAction

(Appears on: -GameServerSpec) +GameServerAllocationSpec)

-

Health configures health checking on the GameServer

+

ListAction is an optional action that can be performed on a List at allocation. +AddValues: Append values to a List’s Values array (optional). Any duplicate values will be ignored. +Capacity: Update the maximum capacity of the Counter to this number (optional). Min 0, Max 1000.

@@ -7224,59 +7086,37 @@

Health

- - - - - - - -
-disabled
- -bool - -
-

Disabled is whether health checking is disabled or not

-
-periodSeconds
- -int32 - -
-

PeriodSeconds is the number of seconds each health ping has to occur in

-
-failureThreshold
+addValues
-int32 +[]string
-

FailureThreshold how many failures in a row constitutes unhealthy

-initialDelaySeconds
+capacity
-int32 +int64
-

InitialDelaySeconds initial delay before checking health

-

ListStatus +

ListSelector

(Appears on: -GameServerSpec, -GameServerStatus) +GameServerSelector)

-

ListStatus stores the current list values

+

ListSelector is the filter options for a GameServer based on List available capacity and/or the +existence of a value in a List. +0 for MaxAvailable means unlimited maximum. Default for integer fields: 0 +“” for ContainsValue means ignore field. Default for string field: “”

@@ -7288,7 +7128,17 @@

ListStatus

+ + + +
-capacity
+containsValue
+ +string + +
+
+minAvailable
int64 @@ -7298,9 +7148,9 @@

ListStatus

-values
+maxAvailable
-[]string +int64
@@ -7308,14 +7158,14 @@

ListStatus

-

PlayerStatus +

MetaPatch

(Appears on: -GameServerStatus) +GameServerAllocationSpec)

-

PlayerStatus stores the current player capacity values

+

MetaPatch is the metadata used to patch the GameServer metadata on allocation

@@ -7327,19 +7177,9 @@

PlayerStatus

- - - -
-count
- -int64 - -
-
-capacity
+labels
-int64 +map[string]string
@@ -7347,9 +7187,9 @@

PlayerStatus

-ids
+annotations
-[]string +map[string]string
@@ -7357,14 +7197,14 @@

PlayerStatus

-

PlayersSpec +

MultiClusterSetting

(Appears on: -GameServerSpec) +GameServerAllocationSpec)

-

PlayersSpec tracks the initial player capacity

+

MultiClusterSetting specifies settings for multi-cluster allocation.

@@ -7376,9 +7216,21 @@

PlayersSpec

+ + + +
-initialCapacity
+enabled
-int64 +bool + +
+
+policySelector
+ + +Kubernetes meta/v1.LabelSelector +
@@ -7386,29 +7238,14 @@

PlayersSpec

-

PortPolicy -(string alias)

-

-(Appears on: -GameServerPort) -

-

-

PortPolicy is the port policy for the GameServer

-

-

Priority +

PlayerSelector

(Appears on: -FleetSpec, -GameServerAllocationSpec, -GameServerSetSpec) +GameServerSelector)

-

Priority is a sorting option for GameServers with Counters or Lists based on the Capacity. -Type: Sort by a “Counter” or a “List”. -Key: The name of the Counter or List. If not found on the GameServer, has no impact. -Order: Sort by “Ascending” or “Descending”. “Descending” a bigger Capacity is preferred. -“Ascending” would be smaller Capacity is preferred.

+

PlayerSelector is the filter options for a GameServer based on player counts

@@ -7420,9 +7257,9 @@

Priority

- - +
-type
+minAvailable
-string +int64
@@ -7430,19 +7267,129 @@

Priority

-key
+maxAvailable
-string +int64
-order
- -string +
+
+

autoscaling.agones.dev/v1

+

+

Package v1 is the v1 version of the API.

+

+Resource Types: + +

FleetAutoscaler +

+

+

FleetAutoscaler is the data structure for a FleetAutoscaler resource

+

+ + + + + + + + + + + + + + + + + + + + + + + + + +
FieldDescription
+apiVersion
+string
+ +autoscaling.agones.dev/v1 + +
+kind
+string +
FleetAutoscaler
+metadata
+ + +Kubernetes meta/v1.ObjectMeta + + +
+Refer to the Kubernetes API documentation for the fields of the +metadata field. +
+spec
+ + +FleetAutoscalerSpec + + +
+
+
+ + + + + + + + + + + + + +
+fleetName
+ +string + +
+
+policy
+ + +FleetAutoscalerPolicy + + +
+

Autoscaling policy

+
+sync
+ + +FleetAutoscalerSync + + +
+(Optional) +

Sync defines when FleetAutoscalers runs autoscaling

+
+
+status
+ + +FleetAutoscalerStatus +
@@ -7450,14 +7397,14 @@

Priority

-

SdkServer +

BufferPolicy

(Appears on: -GameServerSpec) +FleetAutoscalerPolicy)

-

SdkServer specifies parameters for the Agones SDK Server sidecar container

+

BufferPolicy controls the desired behavior of the buffer policy.

@@ -7469,64 +7416,59 @@

SdkServer

-logLevel
+maxReplicas
- -SdkServerLogLevel - +int32
-

LogLevel for SDK server (sidecar) logs. Defaults to “Info”

+

MaxReplicas is the maximum amount of replicas that the fleet may have. +It must be bigger than both MinReplicas and BufferSize

-grpcPort
+minReplicas
int32
-

GRPCPort is the port on which the SDK Server binds the gRPC server to accept incoming connections

+

MinReplicas is the minimum amount of replicas that the fleet must have +If zero, it is ignored. +If non zero, it must be smaller than MaxReplicas and bigger than BufferSize

-httpPort
+bufferSize
-int32 +k8s.io/apimachinery/pkg/util/intstr.IntOrString
-

HTTPPort is the port on which the SDK Server binds the HTTP gRPC gateway server to accept incoming connections

+

BufferSize defines how many replicas the autoscaler tries to have ready all the time +Value can be an absolute number (ex: 5) or a percentage of desired gs instances (ex: 15%) +Absolute number is calculated from percentage by rounding up. +Example: when this is set to 20%, the autoscaler will make sure that 20% +of the fleet’s game server replicas are ready. When this is set to 20, +the autoscaler will make sure that there are 20 available game servers +Must be bigger than 0 +Note: by “ready” we understand in this case “non-allocated”; this is done to ensure robustness +and computation stability in different edge case (fleet just created, not enough +capacity in the cluster etc)

-

SdkServerLogLevel -(string alias)

+

CounterPolicy +

(Appears on: -SdkServer) -

-

-

SdkServerLogLevel is the log level for SDK server (sidecar) logs

-

-
-

allocation.agones.dev/v1

-

-

Package v1 is the v1 version of the API.

+FleetAutoscalerPolicy)

-Resource Types: - -

GameServerAllocation -

-

GameServerAllocation is the data structure for allocating against a set of -GameServers, defined selectors selectors

+

CounterPolicy controls the desired behavior of the Counter autoscaler policy.

@@ -7538,189 +7480,239 @@

GameServerAllocation

+key
+ +string + + + - + + +
-apiVersion
-string
- -allocation.agones.dev/v1 - +

Key is the name of the Counter. Required field.

-kind
-string +maxCapacity
+ +int64 + +
+

MaxCapacity is the maximum aggregate Counter total capacity across the fleet. +MaxCapacity must be bigger than both MinCapacity and BufferSize. Required field.

GameServerAllocation
-metadata
+minCapacity
- -Kubernetes meta/v1.ObjectMeta - +int64
-Refer to the Kubernetes API documentation for the fields of the -metadata field. +

MinCapacity is the minimum aggregate Counter total capacity across the fleet. +If zero, MinCapacity is ignored. +If non zero, MinCapacity must be smaller than MaxCapacity and bigger than BufferSize.

-spec
+bufferSize
- -GameServerAllocationSpec - +k8s.io/apimachinery/pkg/util/intstr.IntOrString
-
-
+

BufferSize is the size of a buffer of counted items that are available in the Fleet (available +capacity). Value can be an absolute number (ex: 5) or a percentage of desired gs instances +(ex: 5%). An absolute number is calculated from percentage by rounding up. +Must be bigger than 0. Required field.

+
+

FixedIntervalSync +

+

+(Appears on: +FleetAutoscalerSync) +

+

+

FixedIntervalSync controls the desired behavior of the fixed interval based sync.

+

+ + + + + + + + +
FieldDescription
-multiClusterSetting
+seconds
- -MultiClusterSetting - +int32
-

MultiClusterPolicySelector if specified, multi-cluster policies are applied. -Otherwise, allocation will happen locally.

+

Seconds defines how often we run fleet autoscaling in seconds

+

FleetAutoscaleRequest +

+

+(Appears on: +FleetAutoscaleReview) +

+

+

FleetAutoscaleRequest defines the request to webhook autoscaler endpoint

+

+ + + + + + + + + +
FieldDescription
-required
+uid
- -GameServerSelector - +k8s.io/apimachinery/pkg/types.UID
-

Deprecated: use field Selectors instead. If Selectors is set, this field is ignored. -Required is the GameServer selector from which to choose GameServers from. -Defaults to all GameServers.

+

UID is an identifier for the individual request/response. It allows us to distinguish instances of requests which are +otherwise identical (parallel requests, requests when earlier requests did not modify etc) +The UID is meant to track the round trip (request/response) between the Autoscaler and the WebHook, not the user request. +It is suitable for correlating log entries between the webhook and apiserver, for either auditing or debugging.

-preferred
+name
- -[]GameServerSelector - +string
-

Deprecated: use field Selectors instead. If Selectors is set, this field is ignored. -Preferred is an ordered list of preferred GameServer selectors -that are optional to be fulfilled, but will be searched before the required selector. -If the first selector is not matched, the selection attempts the second selector, and so on. -If any of the preferred selectors are matched, the required selector is not considered. -This is useful for things like smoke testing of new game servers.

+

Name is the name of the Fleet being scaled

-priorities
+namespace
- -[]Priority - +string
-(Optional) -

(Alpha, CountsAndLists feature flag) The first Priority on the array of Priorities is the most -important for sorting. The allocator will use the first priority for sorting GameServers by -available Capacity in the Selector set and acts as a tie-breaker after sorting the game servers -by State and Strategy. Impacts which GameServer is checked first.

+

Namespace is the namespace associated with the request (if any).

-selectors
+status
- -[]GameServerSelector + +FleetStatus
-

Ordered list of GameServer label selectors. -If the first selector is not matched, the selection attempts the second selector, and so on. -This is useful for things like smoke testing of new game servers. -Note: This field can only be set if neither Required or Preferred is set.

+

The Fleet’s status values

+

FleetAutoscaleResponse +

+

+(Appears on: +FleetAutoscaleReview) +

+

+

FleetAutoscaleResponse defines the response of webhook autoscaler endpoint

+

+ + + + + + + + + +
FieldDescription
-scheduling
+uid
-agones.dev/agones/pkg/apis.SchedulingStrategy +k8s.io/apimachinery/pkg/types.UID
-

Scheduling strategy. Defaults to “Packed”.

+

UID is an identifier for the individual request/response. +This should be copied over from the corresponding FleetAutoscaleRequest.

-metadata
+scale
- -MetaPatch - +bool
-

MetaPatch is optional custom metadata that is added to the game server at allocation -You can use this to tell the server necessary session data

+

Set to false if no scaling should occur to the Fleet

-counters
+replicas
- -map[string]agones.dev/agones/pkg/apis/allocation/v1.CounterAction - +int32
-(Optional) -

(Alpha, CountsAndLists feature flag) Counters and Lists provide a set of actions to perform -on Counters and Lists during allocation.

+

The targeted replica count

+

FleetAutoscaleReview +

+

+

FleetAutoscaleReview is passed to the webhook with a populated Request value, +and then returned with a populated Response.

+

+ + + + + + + + -
FieldDescription
-lists
+request
- -map[string]agones.dev/agones/pkg/apis/allocation/v1.ListAction + +FleetAutoscaleRequest
- - -status
+response
- -GameServerAllocationStatus + +FleetAutoscaleResponse @@ -7729,17 +7721,14 @@

GameServerAllocation -

CounterAction +

FleetAutoscalerPolicy

(Appears on: -GameServerAllocationSpec) +FleetAutoscalerSpec)

-

CounterAction is an optional action that can be performed on a Counter at allocation. -Action: “Increment” or “Decrement” the Counter’s Count (optional). Must also define the Amount. -Amount: The amount to increment or decrement the Count (optional). Must be a positive integer. -Capacity: Update the maximum capacity of the Counter to this number (optional). Min 0, Max int64.

+

FleetAutoscalerPolicy describes how to scale a fleet

@@ -7751,45 +7740,97 @@

CounterAction

+ + + + + + + +
-action
+type
-string + +FleetAutoscalerPolicyType +
+

Type of autoscaling policy.

-amount
+buffer
-int64 + +BufferPolicy +
+(Optional) +

Buffer policy config params. Present only if FleetAutoscalerPolicyType = Buffer.

-capacity
+webhook
-int64 + +WebhookPolicy +
+(Optional) +

Webhook policy config params. Present only if FleetAutoscalerPolicyType = Webhook.

+
+counter
+ + +CounterPolicy + + +
+(Optional) +

[Stage:Alpha] +[FeatureFlag:CountsAndLists] +Counter policy config params. Present only if FleetAutoscalerPolicyType = Counter.

+
+list
+ + +ListPolicy + + +
+(Optional) +

[Stage:Alpha] +[FeatureFlag:CountsAndLists] +List policy config params. Present only if FleetAutoscalerPolicyType = List.

-

CounterSelector +

FleetAutoscalerPolicyType +(string alias)

+

+(Appears on: +FleetAutoscalerPolicy) +

+

+

FleetAutoscalerPolicyType is the policy for autoscaling +for a given Fleet

+

+

FleetAutoscalerSpec

(Appears on: -GameServerSelector) +FleetAutoscaler)

-

CounterSelector is the filter options for a GameServer based on the count and/or available capacity. -0 for MaxCount or MaxAvailable means unlimited maximum. Default for all fields: 0

+

FleetAutoscalerSpec is the spec for a Fleet Scaler

@@ -7801,19 +7842,9 @@

CounterSelector

- - - -
-minCount
- -int64 - -
-
-maxCount
+fleetName
-int64 +string
@@ -7821,34 +7852,41 @@

CounterSelector

-minAvailable
+policy
-int64 + +FleetAutoscalerPolicy +
+

Autoscaling policy

-maxAvailable
+sync
-int64 + +FleetAutoscalerSync +
+(Optional) +

Sync defines when FleetAutoscalers runs autoscaling

-

GameServerAllocationSpec +

FleetAutoscalerStatus

(Appears on: -GameServerAllocation) +FleetAutoscaler)

-

GameServerAllocationSpec is the spec for a GameServerAllocation

+

FleetAutoscalerStatus defines the current status of a FleetAutoscaler

@@ -7860,155 +7898,130 @@

GameServerAllocationS

- - - - + +
-multiClusterSetting
- - -MultiClusterSetting - - -
-

MultiClusterPolicySelector if specified, multi-cluster policies are applied. -Otherwise, allocation will happen locally.

-
-required
+currentReplicas
- -GameServerSelector - +int32
-

Deprecated: use field Selectors instead. If Selectors is set, this field is ignored. -Required is the GameServer selector from which to choose GameServers from. -Defaults to all GameServers.

+

CurrentReplicas is the current number of gameserver replicas +of the fleet managed by this autoscaler, as last seen by the autoscaler

-preferred
+desiredReplicas
- -[]GameServerSelector - +int32
-

Deprecated: use field Selectors instead. If Selectors is set, this field is ignored. -Preferred is an ordered list of preferred GameServer selectors -that are optional to be fulfilled, but will be searched before the required selector. -If the first selector is not matched, the selection attempts the second selector, and so on. -If any of the preferred selectors are matched, the required selector is not considered. -This is useful for things like smoke testing of new game servers.

+

DesiredReplicas is the desired number of gameserver replicas +of the fleet managed by this autoscaler, as last calculated by the autoscaler

-priorities
+lastScaleTime
- -[]Priority + +Kubernetes meta/v1.Time
(Optional) -

(Alpha, CountsAndLists feature flag) The first Priority on the array of Priorities is the most -important for sorting. The allocator will use the first priority for sorting GameServers by -available Capacity in the Selector set and acts as a tie-breaker after sorting the game servers -by State and Strategy. Impacts which GameServer is checked first.

+

lastScaleTime is the last time the FleetAutoscaler scaled the attached fleet,

-selectors
+ableToScale
- -[]GameServerSelector - +bool
-

Ordered list of GameServer label selectors. -If the first selector is not matched, the selection attempts the second selector, and so on. -This is useful for things like smoke testing of new game servers. -Note: This field can only be set if neither Required or Preferred is set.

+

AbleToScale indicates that we can access the target fleet

-scheduling
+scalingLimited
-agones.dev/agones/pkg/apis.SchedulingStrategy +bool
-

Scheduling strategy. Defaults to “Packed”.

+

ScalingLimited indicates that the calculated scale would be above or below the range +defined by MinReplicas and MaxReplicas, and has thus been capped.

+

FleetAutoscalerSync +

+

+(Appears on: +FleetAutoscalerSpec) +

+

+

FleetAutoscalerSync describes when to sync a fleet

+

+ + - - + + + +
-metadata
- - -MetaPatch - - -
-

MetaPatch is optional custom metadata that is added to the game server at allocation -You can use this to tell the server necessary session data

-
FieldDescription
-counters
+type
- -map[string]agones.dev/agones/pkg/apis/allocation/v1.CounterAction + +FleetAutoscalerSyncType
-(Optional) -

(Alpha, CountsAndLists feature flag) Counters and Lists provide a set of actions to perform -on Counters and Lists during allocation.

+

Type of autoscaling sync.

-lists
+fixedInterval
- -map[string]agones.dev/agones/pkg/apis/allocation/v1.ListAction + +FixedIntervalSync
+(Optional) +

FixedInterval config params. Present only if FleetAutoscalerSyncType = FixedInterval.

-

GameServerAllocationState +

FleetAutoscalerSyncType (string alias)

(Appears on: -GameServerAllocationStatus) +FleetAutoscalerSync)

-

GameServerAllocationState is the Allocation state

+

FleetAutoscalerSyncType is the sync strategy for a given Fleet

-

GameServerAllocationStatus +

ListPolicy

(Appears on: -GameServerAllocation) +FleetAutoscalerPolicy)

-

GameServerAllocationStatus is the status for an GameServerAllocation resource

+

ListPolicy controls the desired behavior of the List autoscaler policy.

@@ -8020,93 +8033,150 @@

GameServerAllocatio

+ +
-state
+key
- -GameServerAllocationState - +string
-

GameServerState is the current state of an GameServerAllocation, e.g. Allocated, or UnAllocated

+

Key is the name of the List. Required field.

-gameServerName
+maxCapacity
-string +int64
+

MaxCapacity is the maximum aggregate List total capacity across the fleet. +MaxCapacity must be bigger than both MinCapacity and BufferSize. Required field.

-ports
+minCapacity
- -[]GameServerStatusPort - +int64
+

MinCapacity is the minimum aggregate List total capacity across the fleet. +If zero, it is ignored. +If non zero, it must be smaller than MaxCapacity and bigger than BufferSize.

-address
+bufferSize
-string +k8s.io/apimachinery/pkg/util/intstr.IntOrString
+

BufferSize is the size of a buffer based on the List capacity that is available over the +current aggregate List length in the Fleet (available capacity). It can be specified either +as an absolute value (i.e. 5) or percentage format (i.e. 5%). +Must be bigger than 0. Required field.

+

WebhookPolicy +

+

+(Appears on: +FleetAutoscalerPolicy) +

+

+

WebhookPolicy controls the desired behavior of the webhook policy. +It contains the description of the webhook autoscaler service +used to form url which is accessible inside the cluster

+

+ + + + + + + +
FieldDescription
-nodeName
+url
string
+(Optional) +

url gives the location of the webhook, in standard URL form +(scheme://host:port/path). Exactly one of url or service +must be specified.

+

The host should not refer to a service running in the cluster; use +the service field instead. The host might be resolved via external +DNS in some apiservers (e.g., kube-apiserver cannot resolve +in-cluster DNS as that would be a layering violation). host may +also be an IP address.

+

Please note that using localhost or 127.0.0.1 as a host is +risky unless you take great care to run this webhook on all hosts +which run an apiserver which might need to make calls to this +webhook. Such installs are likely to be non-portable, i.e., not easy +to turn up in a new cluster.

+

The scheme must be “https”; the URL must begin with “https://”.

+

A path is optional, and if present may be any string permissible in +a URL. You may use the path to pass an arbitrary string to the +webhook, for example, a cluster identifier.

+

Attempting to use a user or basic auth e.g. “user:password@” is not +allowed. Fragments (“#…”) and query parameters (“?…”) are not +allowed, either.

-source
+service
-string + +Kubernetes admissionregistration/v1.ServiceReference +
-

If the allocation is from a remote cluster, Source is the endpoint of the remote agones-allocator. -Otherwise, Source is “local”

+(Optional) +

service is a reference to the service for this webhook. Either +service or url must be specified.

+

If the webhook is running within the cluster, then you should use service.

-metadata
+caBundle
- -GameServerMetadata - +[]byte
+(Optional) +

caBundle is a PEM encoded CA bundle which will be used to validate the webhook’s server certificate. +If unspecified, system trust roots on the apiserver are used.

-

GameServerMetadata -

+
+

multicluster.agones.dev/v1

-(Appears on: -GameServerAllocationStatus) +

Package v1 is the v1 version of the API.

+Resource Types: + +

GameServerAllocationPolicy +

-

GameServerMetadata is the metadata from the allocated game server at allocation time

+

GameServerAllocationPolicy is the Schema for the gameserverallocationpolicies API

@@ -8118,139 +8188,93 @@

GameServerMetadata

+apiVersion
+string - + - -
-labels
- -map[string]string - -
+ +multicluster.agones.dev/v1 +
-annotations
- -map[string]string - -
+kind
+string
GameServerAllocationPolicy
-

GameServerSelector -

-

-(Appears on: -GameServerAllocationSpec) -

-

-

GameServerSelector contains all the filter options for selecting -a GameServer for allocation.

-

- - - - - - - - - +
+
+
FieldDescription
-LabelSelector
+metadata
- -Kubernetes meta/v1.LabelSelector + +Kubernetes meta/v1.ObjectMeta
-

-(Members of LabelSelector are embedded into this type.) -

-

See: https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/

+Refer to the Kubernetes API documentation for the fields of the +metadata field.
-gameServerState
+spec
- -GameServerState + +GameServerAllocationPolicySpec
-(Optional) -

[Stage:Beta] -[FeatureFlag:StateAllocationFilter] -GameServerState specifies which State is the filter to be used when attempting to retrieve a GameServer -via Allocation. Defaults to “Ready”. The only other option is “Allocated”, which can be used in conjunction with -label/annotation/player selectors to retrieve an already Allocated GameServer.

-
+ +
-players
+priority
- -PlayerSelector - +int32
-(Optional) -

[Stage:Alpha] -[FeatureFlag:PlayerAllocationFilter] -Players provides a filter on minimum and maximum values for player capacity when retrieving a GameServer -through Allocation. Defaults to no limits.

-counters
+weight
- -map[string]agones.dev/agones/pkg/apis/allocation/v1.CounterSelector - +int
-(Optional) -

(Alpha, CountsAndLists feature flag) Counters provides filters on minimum and maximum values -for a Counter’s count and available capacity when retrieving a GameServer through Allocation. -Defaults to no limits.

-lists
+connectionInfo
- -map[string]agones.dev/agones/pkg/apis/allocation/v1.ListSelector + +ClusterConnectionInfo
-(Optional) -

(Alpha, CountsAndLists feature flag) Lists provides filters on minimum and maximum values -for List capacity, and for the existence of a value in a List, when retrieving a GameServer -through Allocation. Defaults to no limits.

+
-

ListAction +

ClusterConnectionInfo

(Appears on: -GameServerAllocationSpec) +GameServerAllocationPolicySpec)

-

ListAction is an optional action that can be performed on a List at allocation. -AddValues: Append values to a List’s Values array (optional). Any duplicate values will be ignored. -Capacity: Update the maximum capacity of the Counter to this number (optional). Min 0, Max 1000.

+

ClusterConnectionInfo defines the connection information for a cluster

@@ -8262,86 +8286,67 @@

ListAction

- -
-addValues
+clusterName
-[]string +string
+

Optional: the name of the targeted cluster

-capacity
+allocationEndpoints
-int64 +[]string
+

The endpoints for the allocator service in the targeted cluster. +If the AllocationEndpoints is not set, the allocation happens on local cluster. +If there are multiple endpoints any of the endpoints that can handle allocation request should suffice

-

ListSelector -

-

-(Appears on: -GameServerSelector) -

-

-

ListSelector is the filter options for a GameServer based on List available capacity and/or the -existence of a value in a List. -0 for MaxAvailable means unlimited maximum. Default for integer fields: 0 -“” for ContainsValue means ignore field. Default for string field: “”

-

- - - - - - - -
FieldDescription
-containsValue
+secretName
string
+

The name of the secret that contains TLS client certificates to connect the allocator server in the targeted cluster

-minAvailable
+namespace
-int64 +string
+

The cluster namespace from which to allocate gameservers

-maxAvailable
+serverCa
-int64 +[]byte
+

The PEM encoded server CA, used by the allocator client to authenticate the remote server.

-

MetaPatch +

ConnectionInfoIterator

-(Appears on: -GameServerAllocationSpec) -

-

-

MetaPatch is the metadata used to patch the GameServer metadata on allocation

+

ConnectionInfoIterator an iterator on ClusterConnectionInfo

@@ -8353,75 +8358,58 @@

MetaPatch

- -
-labels
+currPriority
-map[string]string +int
+

currPriority Current priority index from the orderedPriorities

-annotations
+orderedPriorities
-map[string]string +[]int32
+

orderedPriorities list of ordered priorities

-

MultiClusterSetting -

-

-(Appears on: -GameServerAllocationSpec) -

-

-

MultiClusterSetting specifies settings for multi-cluster allocation.

-

- - - - - - - -
FieldDescription
-enabled
+priorityToCluster
-bool +map[int32]map[string][]*agones.dev/agones/pkg/apis/multicluster/v1.GameServerAllocationPolicy
+

priorityToCluster Map of priority to cluster-policies map

-policySelector
+clusterBlackList
- -Kubernetes meta/v1.LabelSelector - +map[string]bool
+

clusterBlackList the cluster blacklist for the clusters that has already returned

-

PlayerSelector +

GameServerAllocationPolicySpec

(Appears on: -GameServerSelector) +GameServerAllocationPolicy)

-

PlayerSelector is the filter options for a GameServer based on player counts

+

GameServerAllocationPolicySpec defines the desired state of GameServerAllocationPolicy

@@ -8433,9 +8421,9 @@

PlayerSelector

+ + + +
-minAvailable
+priority
-int64 +int32
@@ -8443,9 +8431,21 @@

PlayerSelector

-maxAvailable
+weight
-int64 +int + +
+
+connectionInfo
+ + +ClusterConnectionInfo +
diff --git a/vendor/github.com/mitchellh/hashstructure/v2/LICENSE b/vendor/github.com/mitchellh/hashstructure/v2/LICENSE new file mode 100644 index 0000000000..a3866a291f --- /dev/null +++ b/vendor/github.com/mitchellh/hashstructure/v2/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2016 Mitchell Hashimoto + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/vendor/github.com/mitchellh/hashstructure/v2/README.md b/vendor/github.com/mitchellh/hashstructure/v2/README.md new file mode 100644 index 0000000000..21f36be193 --- /dev/null +++ b/vendor/github.com/mitchellh/hashstructure/v2/README.md @@ -0,0 +1,76 @@ +# hashstructure [![GoDoc](https://godoc.org/github.com/mitchellh/hashstructure?status.svg)](https://godoc.org/github.com/mitchellh/hashstructure) + +hashstructure is a Go library for creating a unique hash value +for arbitrary values in Go. + +This can be used to key values in a hash (for use in a map, set, etc.) +that are complex. The most common use case is comparing two values without +sending data across the network, caching values locally (de-dup), and so on. + +## Features + + * Hash any arbitrary Go value, including complex types. + + * Tag a struct field to ignore it and not affect the hash value. + + * Tag a slice type struct field to treat it as a set where ordering + doesn't affect the hash code but the field itself is still taken into + account to create the hash value. + + * Optionally, specify a custom hash function to optimize for speed, collision + avoidance for your data set, etc. + + * Optionally, hash the output of `.String()` on structs that implement fmt.Stringer, + allowing effective hashing of time.Time + + * Optionally, override the hashing process by implementing `Hashable`. + +## Installation + +Standard `go get`: + +``` +$ go get github.com/mitchellh/hashstructure/v2 +``` + +**Note on v2:** It is highly recommended you use the "v2" release since this +fixes some significant hash collisions issues from v1. In practice, we used +v1 for many years in real projects at HashiCorp and never had issues, but it +is highly dependent on the shape of the data you're hashing and how you use +those hashes. + +When using v2+, you can still generate weaker v1 hashes by using the +`FormatV1` format when calling `Hash`. + +## Usage & Example + +For usage and examples see the [Godoc](http://godoc.org/github.com/mitchellh/hashstructure). + +A quick code example is shown below: + +```go +type ComplexStruct struct { + Name string + Age uint + Metadata map[string]interface{} +} + +v := ComplexStruct{ + Name: "mitchellh", + Age: 64, + Metadata: map[string]interface{}{ + "car": true, + "location": "California", + "siblings": []string{"Bob", "John"}, + }, +} + +hash, err := hashstructure.Hash(v, hashstructure.FormatV2, nil) +if err != nil { + panic(err) +} + +fmt.Printf("%d", hash) +// Output: +// 2307517237273902113 +``` diff --git a/vendor/github.com/mitchellh/hashstructure/v2/errors.go b/vendor/github.com/mitchellh/hashstructure/v2/errors.go new file mode 100644 index 0000000000..44b8951478 --- /dev/null +++ b/vendor/github.com/mitchellh/hashstructure/v2/errors.go @@ -0,0 +1,22 @@ +package hashstructure + +import ( + "fmt" +) + +// ErrNotStringer is returned when there's an error with hash:"string" +type ErrNotStringer struct { + Field string +} + +// Error implements error for ErrNotStringer +func (ens *ErrNotStringer) Error() string { + return fmt.Sprintf("hashstructure: %s has hash:\"string\" set, but does not implement fmt.Stringer", ens.Field) +} + +// ErrFormat is returned when an invalid format is given to the Hash function. +type ErrFormat struct{} + +func (*ErrFormat) Error() string { + return "format must be one of the defined Format values in the hashstructure library" +} diff --git a/vendor/github.com/mitchellh/hashstructure/v2/hashstructure.go b/vendor/github.com/mitchellh/hashstructure/v2/hashstructure.go new file mode 100644 index 0000000000..3dc0eb74e0 --- /dev/null +++ b/vendor/github.com/mitchellh/hashstructure/v2/hashstructure.go @@ -0,0 +1,482 @@ +package hashstructure + +import ( + "encoding/binary" + "fmt" + "hash" + "hash/fnv" + "reflect" + "time" +) + +// HashOptions are options that are available for hashing. +type HashOptions struct { + // Hasher is the hash function to use. If this isn't set, it will + // default to FNV. + Hasher hash.Hash64 + + // TagName is the struct tag to look at when hashing the structure. + // By default this is "hash". + TagName string + + // ZeroNil is flag determining if nil pointer should be treated equal + // to a zero value of pointed type. By default this is false. + ZeroNil bool + + // IgnoreZeroValue is determining if zero value fields should be + // ignored for hash calculation. + IgnoreZeroValue bool + + // SlicesAsSets assumes that a `set` tag is always present for slices. + // Default is false (in which case the tag is used instead) + SlicesAsSets bool + + // UseStringer will attempt to use fmt.Stringer always. If the struct + // doesn't implement fmt.Stringer, it'll fall back to trying usual tricks. + // If this is true, and the "string" tag is also set, the tag takes + // precedence (meaning that if the type doesn't implement fmt.Stringer, we + // panic) + UseStringer bool +} + +// Format specifies the hashing process used. Different formats typically +// generate different hashes for the same value and have different properties. +type Format uint + +const ( + // To disallow the zero value + formatInvalid Format = iota + + // FormatV1 is the format used in v1.x of this library. This has the + // downsides noted in issue #18 but allows simultaneous v1/v2 usage. + FormatV1 + + // FormatV2 is the current recommended format and fixes the issues + // noted in FormatV1. + FormatV2 + + formatMax // so we can easily find the end +) + +// Hash returns the hash value of an arbitrary value. +// +// If opts is nil, then default options will be used. See HashOptions +// for the default values. The same *HashOptions value cannot be used +// concurrently. None of the values within a *HashOptions struct are +// safe to read/write while hashing is being done. +// +// The "format" is required and must be one of the format values defined +// by this library. You should probably just use "FormatV2". This allows +// generated hashes uses alternate logic to maintain compatibility with +// older versions. +// +// Notes on the value: +// +// * Unexported fields on structs are ignored and do not affect the +// hash value. +// +// * Adding an exported field to a struct with the zero value will change +// the hash value. +// +// For structs, the hashing can be controlled using tags. For example: +// +// struct { +// Name string +// UUID string `hash:"ignore"` +// } +// +// The available tag values are: +// +// * "ignore" or "-" - The field will be ignored and not affect the hash code. +// +// * "set" - The field will be treated as a set, where ordering doesn't +// affect the hash code. This only works for slices. +// +// * "string" - The field will be hashed as a string, only works when the +// field implements fmt.Stringer +// +func Hash(v interface{}, format Format, opts *HashOptions) (uint64, error) { + // Validate our format + if format <= formatInvalid || format >= formatMax { + return 0, &ErrFormat{} + } + + // Create default options + if opts == nil { + opts = &HashOptions{} + } + if opts.Hasher == nil { + opts.Hasher = fnv.New64() + } + if opts.TagName == "" { + opts.TagName = "hash" + } + + // Reset the hash + opts.Hasher.Reset() + + // Create our walker and walk the structure + w := &walker{ + format: format, + h: opts.Hasher, + tag: opts.TagName, + zeronil: opts.ZeroNil, + ignorezerovalue: opts.IgnoreZeroValue, + sets: opts.SlicesAsSets, + stringer: opts.UseStringer, + } + return w.visit(reflect.ValueOf(v), nil) +} + +type walker struct { + format Format + h hash.Hash64 + tag string + zeronil bool + ignorezerovalue bool + sets bool + stringer bool +} + +type visitOpts struct { + // Flags are a bitmask of flags to affect behavior of this visit + Flags visitFlag + + // Information about the struct containing this field + Struct interface{} + StructField string +} + +var timeType = reflect.TypeOf(time.Time{}) + +func (w *walker) visit(v reflect.Value, opts *visitOpts) (uint64, error) { + t := reflect.TypeOf(0) + + // Loop since these can be wrapped in multiple layers of pointers + // and interfaces. + for { + // If we have an interface, dereference it. We have to do this up + // here because it might be a nil in there and the check below must + // catch that. + if v.Kind() == reflect.Interface { + v = v.Elem() + continue + } + + if v.Kind() == reflect.Ptr { + if w.zeronil { + t = v.Type().Elem() + } + v = reflect.Indirect(v) + continue + } + + break + } + + // If it is nil, treat it like a zero. + if !v.IsValid() { + v = reflect.Zero(t) + } + + // Binary writing can use raw ints, we have to convert to + // a sized-int, we'll choose the largest... + switch v.Kind() { + case reflect.Int: + v = reflect.ValueOf(int64(v.Int())) + case reflect.Uint: + v = reflect.ValueOf(uint64(v.Uint())) + case reflect.Bool: + var tmp int8 + if v.Bool() { + tmp = 1 + } + v = reflect.ValueOf(tmp) + } + + k := v.Kind() + + // We can shortcut numeric values by directly binary writing them + if k >= reflect.Int && k <= reflect.Complex64 { + // A direct hash calculation + w.h.Reset() + err := binary.Write(w.h, binary.LittleEndian, v.Interface()) + return w.h.Sum64(), err + } + + switch v.Type() { + case timeType: + w.h.Reset() + b, err := v.Interface().(time.Time).MarshalBinary() + if err != nil { + return 0, err + } + + err = binary.Write(w.h, binary.LittleEndian, b) + return w.h.Sum64(), err + } + + switch k { + case reflect.Array: + var h uint64 + l := v.Len() + for i := 0; i < l; i++ { + current, err := w.visit(v.Index(i), nil) + if err != nil { + return 0, err + } + + h = hashUpdateOrdered(w.h, h, current) + } + + return h, nil + + case reflect.Map: + var includeMap IncludableMap + if opts != nil && opts.Struct != nil { + if v, ok := opts.Struct.(IncludableMap); ok { + includeMap = v + } + } + + // Build the hash for the map. We do this by XOR-ing all the key + // and value hashes. This makes it deterministic despite ordering. + var h uint64 + for _, k := range v.MapKeys() { + v := v.MapIndex(k) + if includeMap != nil { + incl, err := includeMap.HashIncludeMap( + opts.StructField, k.Interface(), v.Interface()) + if err != nil { + return 0, err + } + if !incl { + continue + } + } + + kh, err := w.visit(k, nil) + if err != nil { + return 0, err + } + vh, err := w.visit(v, nil) + if err != nil { + return 0, err + } + + fieldHash := hashUpdateOrdered(w.h, kh, vh) + h = hashUpdateUnordered(h, fieldHash) + } + + if w.format != FormatV1 { + // Important: read the docs for hashFinishUnordered + h = hashFinishUnordered(w.h, h) + } + + return h, nil + + case reflect.Struct: + parent := v.Interface() + var include Includable + if impl, ok := parent.(Includable); ok { + include = impl + } + + if impl, ok := parent.(Hashable); ok { + return impl.Hash() + } + + // If we can address this value, check if the pointer value + // implements our interfaces and use that if so. + if v.CanAddr() { + vptr := v.Addr() + parentptr := vptr.Interface() + if impl, ok := parentptr.(Includable); ok { + include = impl + } + + if impl, ok := parentptr.(Hashable); ok { + return impl.Hash() + } + } + + t := v.Type() + h, err := w.visit(reflect.ValueOf(t.Name()), nil) + if err != nil { + return 0, err + } + + l := v.NumField() + for i := 0; i < l; i++ { + if innerV := v.Field(i); v.CanSet() || t.Field(i).Name != "_" { + var f visitFlag + fieldType := t.Field(i) + if fieldType.PkgPath != "" { + // Unexported + continue + } + + tag := fieldType.Tag.Get(w.tag) + if tag == "ignore" || tag == "-" { + // Ignore this field + continue + } + + if w.ignorezerovalue { + if innerV.IsZero() { + continue + } + } + + // if string is set, use the string value + if tag == "string" || w.stringer { + if impl, ok := innerV.Interface().(fmt.Stringer); ok { + innerV = reflect.ValueOf(impl.String()) + } else if tag == "string" { + // We only show this error if the tag explicitly + // requests a stringer. + return 0, &ErrNotStringer{ + Field: v.Type().Field(i).Name, + } + } + } + + // Check if we implement includable and check it + if include != nil { + incl, err := include.HashInclude(fieldType.Name, innerV) + if err != nil { + return 0, err + } + if !incl { + continue + } + } + + switch tag { + case "set": + f |= visitFlagSet + } + + kh, err := w.visit(reflect.ValueOf(fieldType.Name), nil) + if err != nil { + return 0, err + } + + vh, err := w.visit(innerV, &visitOpts{ + Flags: f, + Struct: parent, + StructField: fieldType.Name, + }) + if err != nil { + return 0, err + } + + fieldHash := hashUpdateOrdered(w.h, kh, vh) + h = hashUpdateUnordered(h, fieldHash) + } + + if w.format != FormatV1 { + // Important: read the docs for hashFinishUnordered + h = hashFinishUnordered(w.h, h) + } + } + + return h, nil + + case reflect.Slice: + // We have two behaviors here. If it isn't a set, then we just + // visit all the elements. If it is a set, then we do a deterministic + // hash code. + var h uint64 + var set bool + if opts != nil { + set = (opts.Flags & visitFlagSet) != 0 + } + l := v.Len() + for i := 0; i < l; i++ { + current, err := w.visit(v.Index(i), nil) + if err != nil { + return 0, err + } + + if set || w.sets { + h = hashUpdateUnordered(h, current) + } else { + h = hashUpdateOrdered(w.h, h, current) + } + } + + if set && w.format != FormatV1 { + // Important: read the docs for hashFinishUnordered + h = hashFinishUnordered(w.h, h) + } + + return h, nil + + case reflect.String: + // Directly hash + w.h.Reset() + _, err := w.h.Write([]byte(v.String())) + return w.h.Sum64(), err + + default: + return 0, fmt.Errorf("unknown kind to hash: %s", k) + } + +} + +func hashUpdateOrdered(h hash.Hash64, a, b uint64) uint64 { + // For ordered updates, use a real hash function + h.Reset() + + // We just panic if the binary writes fail because we are writing + // an int64 which should never be fail-able. + e1 := binary.Write(h, binary.LittleEndian, a) + e2 := binary.Write(h, binary.LittleEndian, b) + if e1 != nil { + panic(e1) + } + if e2 != nil { + panic(e2) + } + + return h.Sum64() +} + +func hashUpdateUnordered(a, b uint64) uint64 { + return a ^ b +} + +// After mixing a group of unique hashes with hashUpdateUnordered, it's always +// necessary to call hashFinishUnordered. Why? Because hashUpdateUnordered +// is a simple XOR, and calling hashUpdateUnordered on hashes produced by +// hashUpdateUnordered can effectively cancel out a previous change to the hash +// result if the same hash value appears later on. For example, consider: +// +// hashUpdateUnordered(hashUpdateUnordered("A", "B"), hashUpdateUnordered("A", "C")) = +// H("A") ^ H("B")) ^ (H("A") ^ H("C")) = +// (H("A") ^ H("A")) ^ (H("B") ^ H(C)) = +// H(B) ^ H(C) = +// hashUpdateUnordered(hashUpdateUnordered("Z", "B"), hashUpdateUnordered("Z", "C")) +// +// hashFinishUnordered "hardens" the result, so that encountering partially +// overlapping input data later on in a different context won't cancel out. +func hashFinishUnordered(h hash.Hash64, a uint64) uint64 { + h.Reset() + + // We just panic if the writes fail + e1 := binary.Write(h, binary.LittleEndian, a) + if e1 != nil { + panic(e1) + } + + return h.Sum64() +} + +// visitFlag is used as a bitmask for affecting visit behavior +type visitFlag uint + +const ( + visitFlagInvalid visitFlag = iota + visitFlagSet = iota << 1 +) diff --git a/vendor/github.com/mitchellh/hashstructure/v2/include.go b/vendor/github.com/mitchellh/hashstructure/v2/include.go new file mode 100644 index 0000000000..702d35415d --- /dev/null +++ b/vendor/github.com/mitchellh/hashstructure/v2/include.go @@ -0,0 +1,22 @@ +package hashstructure + +// Includable is an interface that can optionally be implemented by +// a struct. It will be called for each field in the struct to check whether +// it should be included in the hash. +type Includable interface { + HashInclude(field string, v interface{}) (bool, error) +} + +// IncludableMap is an interface that can optionally be implemented by +// a struct. It will be called when a map-type field is found to ask the +// struct if the map item should be included in the hash. +type IncludableMap interface { + HashIncludeMap(field string, k, v interface{}) (bool, error) +} + +// Hashable is an interface that can optionally be implemented by a struct +// to override the hash value. This value will override the hash value for +// the entire struct. Entries in the struct will not be hashed. +type Hashable interface { + Hash() (uint64, error) +} diff --git a/vendor/modules.txt b/vendor/modules.txt index 7328e592ef..7896189027 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -243,6 +243,9 @@ github.com/matttproud/golang_protobuf_extensions/pbutil # github.com/mennanov/fmutils v0.2.0 ## explicit; go 1.15 github.com/mennanov/fmutils +# github.com/mitchellh/hashstructure/v2 v2.0.2 +## explicit; go 1.14 +github.com/mitchellh/hashstructure/v2 # github.com/mitchellh/mapstructure v1.4.1 ## explicit; go 1.14 github.com/mitchellh/mapstructure