diff --git a/pkg/apis/agones/v1/gameserver.go b/pkg/apis/agones/v1/gameserver.go index e24c0820f8..f6236e989b 100644 --- a/pkg/apis/agones/v1/gameserver.go +++ b/pkg/apis/agones/v1/gameserver.go @@ -151,13 +151,9 @@ type GameServerSpec struct { SdkServer SdkServer `json:"sdkServer,omitempty"` // Template describes the Pod that will be created for the GameServer Template corev1.PodTemplateSpec `json:"template"` - // Alpha describes the alpha properties for the GameServer. - Alpha AlphaSpec `json:"alpha,omitempty"` -} - -// AlphaSpec contains the alpha properties of the GameServer. -type AlphaSpec struct { - Players PlayersSpec `json:"players"` + // (Alpha, PlayerTracking feature flag) Players provides the configuration for player tracking features. + // +optional + Players *PlayersSpec `json:"players,omitempty"` } // PlayersSpec tracks the initial player capacity, and what webhooks to send events to when there are @@ -225,7 +221,9 @@ type GameServerStatus struct { Address string `json:"address"` NodeName string `json:"nodeName"` ReservedUntil *metav1.Time `json:"reservedUntil"` - Alpha AlphaStatus `json:"alpha"` + // (Alpha, PlayerTracking feature flag) + // +optional + Players *PlayerStatus `json:"players"` } // GameServerStatusPort shows the port that was allocated to a @@ -235,11 +233,6 @@ type GameServerStatusPort struct { Port int32 `json:"port"` } -// AlphaStatus is the alpha status values for a GameServer -type AlphaStatus struct { - Players PlayerStatus `json:"players"` -} - // PlayerStatus stores the current player capacity values type PlayerStatus struct { Count int64 `json:"count"` @@ -315,7 +308,12 @@ func (gs *GameServer) applyStatusDefaults() { } if runtime.FeatureEnabled(runtime.FeaturePlayerTracking) { - gs.Status.Alpha.Players.Capacity = gs.Spec.Alpha.Players.InitialCapacity + if gs.Spec.Players != nil { + if gs.Status.Players == nil { + gs.Status.Players = &PlayerStatus{} + } + gs.Status.Players.Capacity = gs.Spec.Players.InitialCapacity + } } } @@ -345,6 +343,17 @@ func (gss *GameServerSpec) applySchedulingDefaults() { // the returned array func (gss *GameServerSpec) Validate(devAddress string) ([]metav1.StatusCause, bool) { var causes []metav1.StatusCause + + if !runtime.FeatureEnabled(runtime.FeaturePlayerTracking) { + if gss.Players != nil { + causes = append(causes, metav1.StatusCause{ + Type: metav1.CauseTypeFieldValueNotSupported, + Field: "players", + Message: fmt.Sprintf("Value cannot be set unless feature flag %s is enabled,", runtime.FeaturePlayerTracking), + }) + } + } + if devAddress != "" { // verify that the value is a valid IP address. if net.ParseIP(devAddress) == nil { diff --git a/pkg/apis/agones/v1/gameserver_test.go b/pkg/apis/agones/v1/gameserver_test.go index b99e0965f1..3ab0d8d164 100644 --- a/pkg/apis/agones/v1/gameserver_test.go +++ b/pkg/apis/agones/v1/gameserver_test.go @@ -62,6 +62,8 @@ func TestGameServerFindGameServerContainer(t *testing.T) { func TestGameServerApplyDefaults(t *testing.T) { t.Parallel() + ten := int64(10) + type expected struct { protocol corev1.Protocol state GameServerState @@ -69,7 +71,7 @@ func TestGameServerApplyDefaults(t *testing.T) { health Health scheduling apis.SchedulingStrategy sdkServer SdkServer - alphaPlayerCapacity int64 + alphaPlayerCapacity *int64 } data := map[string]struct { gameServer GameServer @@ -78,11 +80,11 @@ func TestGameServerApplyDefaults(t *testing.T) { expected expected }{ "set basic defaults on a very simple gameserver": { - featureFlags: runtime.FeaturePlayerTracking + "=true", + featureFlags: string(runtime.FeaturePlayerTracking) + "=true", gameServer: GameServer{ Spec: GameServerSpec{ - Alpha: AlphaSpec{Players: PlayersSpec{InitialCapacity: 10}}, - Ports: []GameServerPort{{ContainerPort: 999}}, + Players: &PlayersSpec{InitialCapacity: 10}, + Ports: []GameServerPort{{ContainerPort: 999}}, Template: corev1.PodTemplateSpec{ Spec: corev1.PodSpec{Containers: []corev1.Container{ {Name: "testing", Image: "testing/image"}, @@ -105,7 +107,7 @@ func TestGameServerApplyDefaults(t *testing.T) { GRPCPort: 9357, HTTPPort: 9358, }, - alphaPlayerCapacity: 10, + alphaPlayerCapacity: &ten, }, }, "defaults on passthrough": { @@ -186,7 +188,6 @@ func TestGameServerApplyDefaults(t *testing.T) { gameServer: GameServer{ Spec: GameServerSpec{ Ports: []GameServerPort{{PortPolicy: Static}}, - Alpha: AlphaSpec{Players: PlayersSpec{InitialCapacity: 10}}, Template: corev1.PodTemplateSpec{ Spec: corev1.PodSpec{Containers: []corev1.Container{{Name: "testing", Image: "testing/image"}}}}}, }, @@ -346,7 +347,12 @@ func TestGameServerApplyDefaults(t *testing.T) { assert.Equal(t, test.expected.scheduling, test.gameServer.Spec.Scheduling) assert.Equal(t, test.expected.health, test.gameServer.Spec.Health) assert.Equal(t, test.expected.sdkServer, test.gameServer.Spec.SdkServer) - assert.Equal(t, test.expected.alphaPlayerCapacity, test.gameServer.Status.Alpha.Players.Capacity) + if test.expected.alphaPlayerCapacity != nil { + assert.Equal(t, *test.expected.alphaPlayerCapacity, test.gameServer.Status.Players.Capacity) + } else { + assert.Nil(t, test.gameServer.Spec.Players) + assert.Nil(t, test.gameServer.Status.Players) + } }) } } @@ -491,6 +497,36 @@ func TestGameServerValidate(t *testing.T) { assert.Len(t, causes, 2) assert.Contains(t, fields, "one.containerPort") assert.Contains(t, fields, "two.hostPort") + + t.Run("validation of "+string(runtime.FeaturePlayerTracking), func(t *testing.T) { + gs := GameServer{ + Spec: GameServerSpec{ + Players: &PlayersSpec{InitialCapacity: 10}, + Template: corev1.PodTemplateSpec{ + Spec: corev1.PodSpec{Containers: []corev1.Container{{Name: "testing", Image: "testing/image"}}}}}, + } + gs.ApplyDefaults() + causes, ok := gs.Validate() + for _, f := range causes { + fields = append(fields, f.Field) + } + assert.False(t, ok) + assert.Len(t, causes, 1) + assert.Contains(t, fields, "players") + + err := runtime.ParseFeatures(string(runtime.FeaturePlayerTracking) + "=true") + assert.NoError(t, err) + gs = GameServer{ + Spec: GameServerSpec{ + Players: &PlayersSpec{InitialCapacity: 10}, + Template: corev1.PodTemplateSpec{ + Spec: corev1.PodSpec{Containers: []corev1.Container{{Name: "testing", Image: "testing/image"}}}}}, + } + gs.ApplyDefaults() + causes, ok = gs.Validate() + assert.True(t, ok) + assert.Empty(t, causes) + }) } func TestGameServerPod(t *testing.T) { diff --git a/pkg/apis/agones/v1/zz_generated.deepcopy.go b/pkg/apis/agones/v1/zz_generated.deepcopy.go index bb4f9ebeea..cd571dc17f 100644 --- a/pkg/apis/agones/v1/zz_generated.deepcopy.go +++ b/pkg/apis/agones/v1/zz_generated.deepcopy.go @@ -25,40 +25,6 @@ import ( runtime "k8s.io/apimachinery/pkg/runtime" ) -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *AlphaSpec) DeepCopyInto(out *AlphaSpec) { - *out = *in - in.Players.DeepCopyInto(&out.Players) - return -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AlphaSpec. -func (in *AlphaSpec) DeepCopy() *AlphaSpec { - if in == nil { - return nil - } - out := new(AlphaSpec) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *AlphaStatus) DeepCopyInto(out *AlphaStatus) { - *out = *in - out.Players = in.Players - return -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AlphaStatus. -func (in *AlphaStatus) DeepCopy() *AlphaStatus { - if in == nil { - return nil - } - out := new(AlphaStatus) - in.DeepCopyInto(out) - return out -} - // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *Fleet) DeepCopyInto(out *Fleet) { *out = *in @@ -336,7 +302,11 @@ func (in *GameServerSpec) DeepCopyInto(out *GameServerSpec) { out.Health = in.Health out.SdkServer = in.SdkServer in.Template.DeepCopyInto(&out.Template) - in.Alpha.DeepCopyInto(&out.Alpha) + if in.Players != nil { + in, out := &in.Players, &out.Players + *out = new(PlayersSpec) + (*in).DeepCopyInto(*out) + } return } @@ -362,7 +332,11 @@ func (in *GameServerStatus) DeepCopyInto(out *GameServerStatus) { in, out := &in.ReservedUntil, &out.ReservedUntil *out = (*in).DeepCopy() } - out.Alpha = in.Alpha + if in.Players != nil { + in, out := &in.Players, &out.Players + *out = new(PlayerStatus) + **out = **in + } return } diff --git a/pkg/client/clientset/versioned/clientset.go b/pkg/client/clientset/versioned/clientset.go index c6044097b0..62fb9716bd 100644 --- a/pkg/client/clientset/versioned/clientset.go +++ b/pkg/client/clientset/versioned/clientset.go @@ -31,17 +31,9 @@ import ( type Interface interface { Discovery() discovery.DiscoveryInterface AgonesV1() agonesv1.AgonesV1Interface - // Deprecated: please explicitly pick a version if possible. - Agones() agonesv1.AgonesV1Interface AllocationV1() allocationv1.AllocationV1Interface - // Deprecated: please explicitly pick a version if possible. - Allocation() allocationv1.AllocationV1Interface AutoscalingV1() autoscalingv1.AutoscalingV1Interface - // Deprecated: please explicitly pick a version if possible. - Autoscaling() autoscalingv1.AutoscalingV1Interface MulticlusterV1() multiclusterv1.MulticlusterV1Interface - // Deprecated: please explicitly pick a version if possible. - Multicluster() multiclusterv1.MulticlusterV1Interface } // Clientset contains the clients for groups. Each group has exactly one @@ -59,45 +51,21 @@ func (c *Clientset) AgonesV1() agonesv1.AgonesV1Interface { return c.agonesV1 } -// Deprecated: Agones retrieves the default version of AgonesClient. -// Please explicitly pick a version. -func (c *Clientset) Agones() agonesv1.AgonesV1Interface { - return c.agonesV1 -} - // AllocationV1 retrieves the AllocationV1Client func (c *Clientset) AllocationV1() allocationv1.AllocationV1Interface { return c.allocationV1 } -// Deprecated: Allocation retrieves the default version of AllocationClient. -// Please explicitly pick a version. -func (c *Clientset) Allocation() allocationv1.AllocationV1Interface { - return c.allocationV1 -} - // AutoscalingV1 retrieves the AutoscalingV1Client func (c *Clientset) AutoscalingV1() autoscalingv1.AutoscalingV1Interface { return c.autoscalingV1 } -// Deprecated: Autoscaling retrieves the default version of AutoscalingClient. -// Please explicitly pick a version. -func (c *Clientset) Autoscaling() autoscalingv1.AutoscalingV1Interface { - return c.autoscalingV1 -} - // MulticlusterV1 retrieves the MulticlusterV1Client func (c *Clientset) MulticlusterV1() multiclusterv1.MulticlusterV1Interface { return c.multiclusterV1 } -// Deprecated: Multicluster retrieves the default version of MulticlusterClient. -// Please explicitly pick a version. -func (c *Clientset) Multicluster() multiclusterv1.MulticlusterV1Interface { - return c.multiclusterV1 -} - // Discovery retrieves the DiscoveryClient func (c *Clientset) Discovery() discovery.DiscoveryInterface { if c == nil { diff --git a/pkg/client/clientset/versioned/fake/clientset_generated.go b/pkg/client/clientset/versioned/fake/clientset_generated.go index bb3558c3ad..a9da11b774 100644 --- a/pkg/client/clientset/versioned/fake/clientset_generated.go +++ b/pkg/client/clientset/versioned/fake/clientset_generated.go @@ -82,37 +82,17 @@ func (c *Clientset) AgonesV1() agonesv1.AgonesV1Interface { return &fakeagonesv1.FakeAgonesV1{Fake: &c.Fake} } -// Agones retrieves the AgonesV1Client -func (c *Clientset) Agones() agonesv1.AgonesV1Interface { - return &fakeagonesv1.FakeAgonesV1{Fake: &c.Fake} -} - // AllocationV1 retrieves the AllocationV1Client func (c *Clientset) AllocationV1() allocationv1.AllocationV1Interface { return &fakeallocationv1.FakeAllocationV1{Fake: &c.Fake} } -// Allocation retrieves the AllocationV1Client -func (c *Clientset) Allocation() allocationv1.AllocationV1Interface { - return &fakeallocationv1.FakeAllocationV1{Fake: &c.Fake} -} - // AutoscalingV1 retrieves the AutoscalingV1Client func (c *Clientset) AutoscalingV1() autoscalingv1.AutoscalingV1Interface { return &fakeautoscalingv1.FakeAutoscalingV1{Fake: &c.Fake} } -// Autoscaling retrieves the AutoscalingV1Client -func (c *Clientset) Autoscaling() autoscalingv1.AutoscalingV1Interface { - return &fakeautoscalingv1.FakeAutoscalingV1{Fake: &c.Fake} -} - // MulticlusterV1 retrieves the MulticlusterV1Client func (c *Clientset) MulticlusterV1() multiclusterv1.MulticlusterV1Interface { return &fakemulticlusterv1.FakeMulticlusterV1{Fake: &c.Fake} } - -// Multicluster retrieves the MulticlusterV1Client -func (c *Clientset) Multicluster() multiclusterv1.MulticlusterV1Interface { - return &fakemulticlusterv1.FakeMulticlusterV1{Fake: &c.Fake} -} diff --git a/pkg/util/runtime/features.go b/pkg/util/runtime/features.go index ed227515b1..d015c5e83d 100644 --- a/pkg/util/runtime/features.go +++ b/pkg/util/runtime/features.go @@ -31,7 +31,7 @@ const ( FeatureExample Feature = "Example" // FeaturePlayerTracking is a feature flag to enable/disable player tracking features. - FeaturePlayerTracking = "PlayerTracking" + FeaturePlayerTracking Feature = "PlayerTracking" ) var ( 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 c8fd1861cd..b9cea4d275 100644 --- a/site/content/en/docs/Reference/agones_crd_api_reference.html +++ b/site/content/en/docs/Reference/agones_crd_api_reference.html @@ -2536,15 +2536,16 @@
alpha
+players
-
-AlphaSpec
+
+PlayersSpec
Alpha describes the alpha properties for the GameServer.
+(Optional) +(Alpha, PlayerTracking feature flag) Players provides the configuration for player tracking features.
-(Appears on: -GameServerSpec) -
--
AlphaSpec contains the alpha properties of the GameServer.
- -Field | -Description | -
---|---|
-players
-
-
-PlayersSpec
-
-
- |
-- | -
-(Appears on: -GameServerStatus) -
--
AlphaStatus is the alpha status values for a GameServer
- -Field | -Description | -
---|---|
-players
-
-
-PlayerStatus
-
-
- |
-- | -
@@ -3175,15 +3114,16 @@
alpha
+players
-
-AlphaSpec
+
+PlayersSpec
Alpha describes the alpha properties for the GameServer.
+(Optional) +(Alpha, PlayerTracking feature flag) Players provides the configuration for player tracking features.
alpha
+players
-
-AlphaStatus
+
+PlayerStatus
(Alpha, PlayerTracking feature flag)
alpha
+players
-
-AlphaSpec
+
+PlayersSpec
Alpha describes the alpha properties for the GameServer.
+(Optional) +(Alpha, PlayerTracking feature flag) Players provides the configuration for player tracking features.
(Appears on: -AlphaStatus) +GameServerStatus)
PlayerStatus stores the current player capacity values
@@ -3570,7 +3513,7 @@(Appears on: -AlphaSpec) +GameServerSpec)
PlayersSpec tracks the initial player capacity, and what webhooks to send events to when there are