Skip to content

Commit

Permalink
Merge branch 'main' into i_3715
Browse files Browse the repository at this point in the history
  • Loading branch information
Kalaiselvi84 committed May 1, 2024
2 parents ec72f7f + ef2d0b5 commit f98e459
Show file tree
Hide file tree
Showing 32 changed files with 558 additions and 52 deletions.
5 changes: 4 additions & 1 deletion build/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -63,8 +63,11 @@ KIND_CONTAINER_NAME=$(KIND_PROFILE)-control-plane
# Game Server image to use while doing end-to-end tests
GS_TEST_IMAGE ?= us-docker.pkg.dev/agones-images/examples/simple-game-server:0.31

# Enable all beta feature gates. Keep in sync with `true` (beta) entries in pkg/util/runtime/features.go:featureDefaults
BETA_FEATURE_GATES ?= "CountsAndLists=true&DisableResyncOnSDKServer=true"

# Enable all alpha feature gates. Keep in sync with `false` (alpha) entries in pkg/util/runtime/features.go:featureDefaults
ALPHA_FEATURE_GATES ?= "PlayerAllocationFilter=true&PlayerTracking=true&CountsAndLists=true&Example=true"
ALPHA_FEATURE_GATES ?= "PlayerAllocationFilter=true&PlayerTracking=true&Example=true"

# Build with Windows support
WITH_WINDOWS=1
Expand Down
24 changes: 12 additions & 12 deletions build/includes/sdk.mk
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ COMMAND ?= gen
SDK_IMAGE_TAG=$(build_sdk_prefix)$(SDK_FOLDER):$(build_sdk_version)
DEFAULT_CONFORMANCE_TESTS = ready,allocate,setlabel,setannotation,gameserver,health,shutdown,watch,reserve
ALPHA_CONFORMANCE_TESTS = getplayercapacity,setplayercapacity,playerconnect,playerdisconnect,getplayercount,isplayerconnected,getconnectedplayers
# TODO: Move Counter and List tests into ALPHA_CONFORMANCE_TESTS once the they are written for all SDKs
# TODO: Move Counter and List tests into DEFAULT_CONFORMANCE_TESTS once the they are written for all SDKs
COUNTS_AND_LISTS_TESTS = getcounter,updatecounter,setcountcounter,setcapacitycounter,getlist,updatelist,addlistvalue,removelistvalue

.PHONY: test-sdks test-sdk build-sdks build-sdk gen-all-sdk-grpc gen-sdk-grpc run-all-sdk-command run-sdk-command build-example
Expand Down Expand Up @@ -168,9 +168,9 @@ run-sdk-conformance-test-node:
$(MAKE) run-sdk-conformance-test SDK_FOLDER=node GRPC_PORT=9002 HTTP_PORT=9102

run-sdk-conformance-test-go:
# run without feature flags
$(MAKE) run-sdk-conformance-test SDK_FOLDER=go GRPC_PORT=9001 HTTP_PORT=9101
# run with feature flags enabled
# run with on-by-default (Beta) feature flags enabled
$(MAKE) run-sdk-conformance-test SDK_FOLDER=go GRPC_PORT=9001 HTTP_PORT=9101 TESTS=$(DEFAULT_CONFORMANCE_TESTS),$(COUNTS_AND_LISTS_TESTS)
# run with Alpha and Beta feature flags enabled
$(MAKE) run-sdk-conformance-test SDK_FOLDER=go GRPC_PORT=9001 HTTP_PORT=9101 FEATURE_GATES=$(ALPHA_FEATURE_GATES) TESTS=$(DEFAULT_CONFORMANCE_TESTS),$(ALPHA_CONFORMANCE_TESTS),$(COUNTS_AND_LISTS_TESTS)

run-sdk-conformance-test-rust:
Expand All @@ -184,17 +184,17 @@ run-sdk-conformance-test-rust:
DOCKER_RUN_ARGS="$(DOCKER_RUN_ARGS) -e RUN_ASYNC=true" $(MAKE) run-sdk-conformance-test SDK_FOLDER=rust GRPC_PORT=9004 HTTP_PORT=9104 FEATURE_GATES=PlayerTracking=true TESTS=$(DEFAULT_CONFORMANCE_TESTS),$(ALPHA_CONFORMANCE_TESTS)

run-sdk-conformance-test-csharp:
# run without feature flags
$(MAKE) run-sdk-conformance-test SDK_FOLDER=csharp GRPC_PORT=9005 HTTP_PORT=9105
# run with feature flags enabled
$(MAKE) run-sdk-conformance-test SDK_FOLDER=csharp GRPC_PORT=9005 HTTP_PORT=9105 FEATURE_GATES=$(ALPHA_FEATURE_GATES) TESTS=$(DEFAULT_CONFORMANCE_TESTS),$(ALPHA_CONFORMANCE_TESTS),$(COUNTS_AND_LISTS_TESTS)
# run with Beta feature flags enabled
$(MAKE) run-sdk-conformance-test SDK_FOLDER=csharp GRPC_PORT=9005 HTTP_PORT=9105 FEATURE_GATES=$(BETA_FEATURE_GATES) TESTS=$(DEFAULT_CONFORMANCE_TESTS),$(COUNTS_AND_LISTS_TESTS)
# run with Alpha feature flags enabled
$(MAKE) run-sdk-conformance-test SDK_FOLDER=csharp GRPC_PORT=9005 HTTP_PORT=9105 FEATURE_GATES=$(ALPHA_FEATURE_GATES) TESTS=$(DEFAULT_CONFORMANCE_TESTS),$(ALPHA_CONFORMANCE_TESTS)

run-sdk-conformance-test-rest:
# (note: the restapi folder doesn't use GRPC_PORT but run-sdk-conformance-no-build defaults it, so we supply a unique value here)
# run without feature flags
$(MAKE) run-sdk-conformance-test SDK_FOLDER=restapi GRPC_PORT=9050 HTTP_PORT=9150
# run with feature flags enabled
$(MAKE) run-sdk-conformance-test SDK_FOLDER=restapi GRPC_PORT=9050 HTTP_PORT=9150 FEATURE_GATES=$(ALPHA_FEATURE_GATES) TESTS=$(DEFAULT_CONFORMANCE_TESTS),$(ALPHA_CONFORMANCE_TESTS),$(COUNTS_AND_LISTS_TESTS)
# run with Beta feature flags enabled
$(MAKE) run-sdk-conformance-test SDK_FOLDER=restapi GRPC_PORT=9050 HTTP_PORT=9150 FEATURE_GATES=$(BETA_FEATURE_GATES) TESTS=$(DEFAULT_CONFORMANCE_TESTS),$(COUNTS_AND_LISTS_TESTS)
# run with Alpha feature flags enabled
$(MAKE) run-sdk-conformance-test SDK_FOLDER=restapi GRPC_PORT=9050 HTTP_PORT=9150 FEATURE_GATES=$(ALPHA_FEATURE_GATES) TESTS=$(DEFAULT_CONFORMANCE_TESTS),$(ALPHA_CONFORMANCE_TESTS)

$(MAKE) run-sdk-command COMMAND=clean SDK_FOLDER=restapi

Expand Down
1 change: 1 addition & 0 deletions build/includes/website.mk
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ site-test:
# generate site images, if they don't exist
site-images: $(site_path)/static/diagrams/gameserver-states.dot.png
site-images: $(site_path)/static/diagrams/eviction-decision.dot.png
site-images: ${site_path}/static/diagrams/system-diagram.dot.png
site-images: $(site_path)/static/diagrams/gameserver-lifecycle.puml.png
site-images: $(site_path)/static/diagrams/gameserver-reserved.puml.png
site-images: $(site_path)/static/diagrams/canary-testing.puml.png
Expand Down
2 changes: 1 addition & 1 deletion cloudbuild.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -276,7 +276,7 @@ steps:
declare -A versionsAndRegions=( [1.27]=us-east1 [1.28]=us-west1 [1.29]=europe-west1 )
# Keep in sync with (the inverse of) pkg/util/runtime/features.go:featureDefaults
featureWithGate="PlayerAllocationFilter=true&PlayerTracking=true&CountsAndLists=true&DisableResyncOnSDKServer=false&Example=true"
featureWithGate="PlayerAllocationFilter=true&PlayerTracking=true&CountsAndLists=false&DisableResyncOnSDKServer=false&Example=true"
featureWithoutGate=""
# Use this if specific feature gates can only be supported on specific Kubernetes versions.
Expand Down
3 changes: 2 additions & 1 deletion install/helm/agones/defaultfeaturegates.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,16 @@
# Default values for feature gates. Keep in sync with pkg/util/runtime/features.go:featureDefaults

# Beta features
CountsAndLists: true
DisableResyncOnSDKServer: true

# Alpha features
CountsAndLists: false
GKEAutopilotExtendedDurationPods: false
PlayerAllocationFilter: false
PlayerTracking: false

# Dev features
FeatureAutopilotPassthroughPort: true

# Example feature
Example: false
3 changes: 3 additions & 0 deletions pkg/apis/agones/v1/gameserver.go
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,9 @@ const (
// GameServerPodLabel is the label that the name of the GameServer
// is set on the Pod the GameServer controls
GameServerPodLabel = agones.GroupName + "/gameserver"
// GameServerPortPolicyPodLabel is the label to identify the port policy
// of the pod
GameServerPortPolicyPodLabel = agones.GroupName + "/port"
// GameServerContainerAnnotation is the annotation that stores
// which container is the container that runs the dedicated game server
GameServerContainerAnnotation = agones.GroupName + "/container"
Expand Down
19 changes: 19 additions & 0 deletions pkg/cloudproduct/gke/gke.go
Original file line number Diff line number Diff line change
Expand Up @@ -155,11 +155,21 @@ func (*gkeAutopilot) ValidateScheduling(ss apis.SchedulingStrategy, fldPath *fie
}

func (*gkeAutopilot) MutateGameServerPod(gss *agonesv1.GameServerSpec, pod *corev1.Pod) error {
setPassthroughLabel(gss, pod)
setPrimaryContainer(pod, gss.Container)
podSpecSeccompUnconfined(&pod.Spec)
return nil
}

// setPassthroughLabel sets the agones.dev/port: "autopilot-passthrough" label to the game server container.
// This will help to back the container port from the allocated port using an objectSelector of this label
// in GameServers that are using Passthrough Port Policy
func setPassthroughLabel(gs *agonesv1.GameServerSpec, pod *corev1.Pod) {
if runtime.FeatureEnabled(runtime.FeatureAutopilotPassthroughPort) && hasPortPolicy(gs, agonesv1.Passthrough) {
pod.ObjectMeta.Labels[agonesv1.GameServerPortPolicyPodLabel] = "autopilot-passthrough"
}
}

// setPrimaryContainer sets the autopilot.gke.io/primary-container annotation to the game server container.
// This acts as a hint to Autopilot for which container to add resources to during resource adjustment.
// See https://cloud.google.com/kubernetes-engine/docs/concepts/autopilot-resource-requests#autopilot-resource-management
Expand Down Expand Up @@ -223,6 +233,15 @@ func setEvictionNoExtended(ev *agonesv1.Eviction, pod *corev1.Pod) error {
return nil
}

func hasPortPolicy(gs *agonesv1.GameServerSpec, portPolicy agonesv1.PortPolicy) bool {
for _, p := range gs.Ports {
if p.PortPolicy == portPolicy {
return true
}
}
return false
}

type autopilotPortAllocator struct {
minPort int32
maxPort int32
Expand Down
96 changes: 96 additions & 0 deletions pkg/cloudproduct/gke/gke_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,12 @@
package gke

import (
"fmt"
"testing"

"agones.dev/agones/pkg/apis"
agonesv1 "agones.dev/agones/pkg/apis/agones/v1"
"agones.dev/agones/pkg/util/runtime"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
corev1 "k8s.io/api/core/v1"
Expand Down Expand Up @@ -222,6 +224,100 @@ func TestPodSeccompUnconfined(t *testing.T) {
}
}

func TestSetPassthroughLabel(t *testing.T) {
for name, tc := range map[string]struct {
pod *corev1.Pod
wantPod *corev1.Pod
ports []agonesv1.GameServerPort
features string
}{
"gameserver with with Passthrough port policy adds label to pod": {
features: fmt.Sprintf("%s=true", runtime.FeatureAutopilotPassthroughPort),

pod: &corev1.Pod{
ObjectMeta: metav1.ObjectMeta{
Annotations: map[string]string{},
Labels: map[string]string{},
},
},
ports: []agonesv1.GameServerPort{
{
Name: "awesome-udp",
PortPolicy: agonesv1.Passthrough,
ContainerPort: 1234,
Protocol: corev1.ProtocolUDP,
},
},
wantPod: &corev1.Pod{
ObjectMeta: metav1.ObjectMeta{
Annotations: map[string]string{},
Labels: map[string]string{
agonesv1.GameServerPortPolicyPodLabel: "autopilot-passthrough",
},
},
},
},
"gameserver with Static port policy does not add label to pod": {
features: fmt.Sprintf("%s=true", runtime.FeatureAutopilotPassthroughPort),

pod: &corev1.Pod{
ObjectMeta: metav1.ObjectMeta{
Annotations: map[string]string{},
Labels: map[string]string{},
},
},
ports: []agonesv1.GameServerPort{
{
Name: "awesome-udp",
PortPolicy: agonesv1.Static,
ContainerPort: 1234,
Protocol: corev1.ProtocolUDP,
},
},
wantPod: &corev1.Pod{
ObjectMeta: metav1.ObjectMeta{
Annotations: map[string]string{},
Labels: map[string]string{},
},
},
},
"gameserver, no feature gate, with Passthrough port policy does not add label to pod": {
features: fmt.Sprintf("%s=false", runtime.FeatureAutopilotPassthroughPort),

pod: &corev1.Pod{
ObjectMeta: metav1.ObjectMeta{
Annotations: map[string]string{},
Labels: map[string]string{},
},
},
ports: []agonesv1.GameServerPort{
{
Name: "awesome-udp",
PortPolicy: agonesv1.Passthrough,
ContainerPort: 1234,
Protocol: corev1.ProtocolUDP,
},
},
wantPod: &corev1.Pod{
ObjectMeta: metav1.ObjectMeta{
Annotations: map[string]string{},
Labels: map[string]string{},
},
},
},
} {
t.Run(name, func(t *testing.T) {
runtime.FeatureTestMutex.Lock()
defer runtime.FeatureTestMutex.Unlock()
require.NoError(t, runtime.ParseFeatures(tc.features))
gs := (&autopilotPortAllocator{minPort: 7000, maxPort: 8000}).Allocate(&agonesv1.GameServer{Spec: agonesv1.GameServerSpec{Ports: tc.ports}})
pod := tc.pod.DeepCopy()
setPassthroughLabel(&gs.Spec, pod)
assert.Equal(t, tc.wantPod, pod)
})
}
}

func TestSetEvictionNoExtended(t *testing.T) {
emptyPodAnd := func(f func(*corev1.Pod)) *corev1.Pod {
pod := &corev1.Pod{
Expand Down
2 changes: 2 additions & 0 deletions pkg/gameserversets/controller_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -340,6 +340,8 @@ func TestComputeStatus(t *testing.T) {
Count: 30,
Capacity: 55,
},
Counters: map[string]agonesv1.AggregatedCounterStatus{},
Lists: map[string]agonesv1.AggregatedListStatus{},
}

assert.Equal(t, expected, computeStatus(list))
Expand Down
21 changes: 15 additions & 6 deletions pkg/util/runtime/features.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,16 +31,19 @@ const (
////////////////
// Beta features

////////////////
// Alpha features

// FeatureCountsAndLists is a feature flag that enables/disables counts and lists feature
// FeatureCountsAndLists is a feature flag that enables counts and lists feature
// (a generic implenetation of the player tracking feature).
FeatureCountsAndLists Feature = "CountsAndLists"

////////////////
// Alpha features

// FeatureDisableResyncOnSDKServer is a feature flag to enable/disable resync on SDK server.
FeatureDisableResyncOnSDKServer Feature = "DisableResyncOnSDKServer"

////////////////
// Alpha features

// FeatureGKEAutopilotExtendedDurationPods enables the use of Extended Duration pods
// when Agones is running on Autopilot. Available on 1.28+ only.
FeatureGKEAutopilotExtendedDurationPods = "GKEAutopilotExtendedDurationPods"
Expand All @@ -55,6 +58,9 @@ const (
////////////////
// Dev features

// FeatureAutopilotPassthroughPort is a feature flag that enables/disables Passthrough Port Policy.
FeatureAutopilotPassthroughPort Feature = "PassthroughPortPolicy"

////////////////
// Example feature

Expand Down Expand Up @@ -83,27 +89,30 @@ var (
// * move from `false` to `true` in `featureDefaults`.
// * move from `false` to `true` in install/helm/agones/defaultfeaturegates.yaml
// * remove from `ALPHA_FEATURE_GATES` in build/Makefile
// * add to `BETA_FEATURE_GATES` in build/Makefile
// * invert in the e2e-runner config in cloudbuild.yaml
// * change the value in site/content/en/docs/Guides/feature-stages.md.
// * Ensure that the features in each file are organized categorically and alphabetically.
//
// To promote a feature from beta->GA:
// * remove all places consuming the feature gate and fold logic to true
// * consider cleanup - often folding a gate to true allows refactoring
// * consider cleanup - often folding a gate to true allows refactoring
// * invert the "new alpha feature" steps above
// * remove from `BETA_FEATURE_GATES` in build/Makefile
//
// In each of these, keep the feature sorted by descending maturity then alphabetical
featureDefaults = map[Feature]bool{
// Beta features
FeatureCountsAndLists: true,
FeatureDisableResyncOnSDKServer: true,

// Alpha features
FeatureCountsAndLists: false,
FeatureGKEAutopilotExtendedDurationPods: false,
FeaturePlayerAllocationFilter: false,
FeaturePlayerTracking: false,

// Dev features
FeatureAutopilotPassthroughPort: true,

// Example feature
FeatureExample: false,
Expand Down
49 changes: 49 additions & 0 deletions site/content/en/docs/Advanced/system-diagram.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
---
title: "System Diagram"
date: 2024-04-18
weight: -100
description: >
A pictoral overview of the Agones component relationships.
---

![System Diagram](../../../diagrams/system-diagram.dot.png)

# Agones Control Plane

The Agones Control Plane consists of 4 `Deployments`:
```
NAME READY UP-TO-DATE AVAILABLE AGE
agones-allocator 3/3 3 3 40d
agones-controller 2/2 2 2 40d
agones-extensions 2/2 2 2 40d
agones-ping 2/2 2 2 40d
```

## `agones-allocator`

`agones-allocator` provides a gRPC/REST service that translates allocation requests into `GameServerAllocations`. See [Allocator Service]({{< relref "allocator-service.md">}}) for more information.

## `agones-controller`

`agones-controller` maintains various control loops for all Agones CRDs (`GameServer`, `Fleet`, etc.). A single leader-elected `Pod` of the `Deployment`
is active at any given time (see [High Availability]({{< relref "high-availability-agones.md">}})).

## `agones-extensions`

`agones-extensions` is the endpoint for:
* Agones-installed Kubernetes webhooks, which handle defaulting and validation for Agones CRs,
* and the `GameServerAllocation` `APIService`, which handles `GameServer` allocations (either from the Allocator Service or the Kubernetes API).

## `agones-ping` (not pictured)

`agones-ping` is a simple ping service for latency testing from your game client - see [Latency Testing]({{< relref "ping-service.md">}}).

# Agones CRDs

See [Create a Game Server]({{< relref "create-gameserver.md">}}), [Create a Game Server]({{< relref "create-fleet.md">}}) for examples of Agones CRDs in action, or the [API Reference]({{< ref "/docs/Reference" >}}) for more detail.

All of the Agones CRDs are controlled and updated by `agones-controller`. `GameServer` is additionally updated by the SDK Sidecar and `agones-extensions` (moving a `GameServer` from [`Ready` to `Allocated`]({{< ref "/docs/Reference/gameserver.md#gameserver-state-diagram" >}})

# Game Server Pod

Also pictured is an example `Pod` owned by a `GameServer`. Game clients typically connect to the Dedicated Game Server directly, or via a proxy like [Quilkin](https://googleforgames.github.io/quilkin/main/book/introduction.html). The game server server interfaces with Agones using the [Client SDK]({{< relref "Client SDKs">}}), which is a thin wrapper around the [SDK gRPC protocol](https://github.com/googleforgames/agones/blob/main/proto/sdk/sdk.proto). The SDK connects to the SDK Sidecar (`sdk-server`) in the same Pod, which handles the SDK business logic for e.g. [health checks]({{< relref "health-checking.md">}}), [Counters and Lists]({{< relref "counters-and-lists.md">}}), etc.
Loading

0 comments on commit f98e459

Please sign in to comment.