Skip to content

Commit

Permalink
Local implementation of Set/GetPlayerCapacity
Browse files Browse the repository at this point in the history
Local SDK implementations of SetPlayerCapacity and GetPlayerCapacity,
including conformance tests for the Go SDK.

Work on #1033
  • Loading branch information
markmandel committed Apr 2, 2020
1 parent 5ef8c77 commit 92de6a7
Show file tree
Hide file tree
Showing 4 changed files with 125 additions and 9 deletions.
15 changes: 11 additions & 4 deletions build/includes/sdk.mk
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,9 @@ examples_folder = ../examples/
SDK_FOLDER ?= go
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


.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 @@ -133,13 +136,14 @@ run-sdk-conformance-local: ensure-agones-sdk-image
run-sdk-conformance-no-build: TIMEOUT ?= 30
run-sdk-conformance-no-build: RANDOM := $(shell bash -c 'echo $$RANDOM')
run-sdk-conformance-no-build: DELAY ?= $(shell bash -c "echo $$[ ($(RANDOM) % 5 ) + 1 ]")
run-sdk-conformance-no-build: TESTS ?= ready,allocate,setlabel,setannotation,gameserver,health,shutdown,watch,reserve
run-sdk-conformance-no-build: TESTS ?= $(DEFAULT_CONFORMANCE_TESTS)
run-sdk-conformance-no-build: GRPC_PORT ?= 9357
run-sdk-conformance-no-build: HTTP_PORT ?= 9358
run-sdk-conformance-no-build: FEATURE_GATES ?=
run-sdk-conformance-no-build: ensure-agones-sdk-image
run-sdk-conformance-no-build: ensure-build-sdk-image
DOCKER_RUN_ARGS="--net host -e AGONES_SDK_GRPC_PORT=$(GRPC_PORT) -e AGONES_SDK_HTTP_PORT=$(HTTP_PORT) $(DOCKER_RUN_ARGS)" COMMAND=sdktest $(MAKE) run-sdk-command & \
docker run -p $(GRPC_PORT):$(GRPC_PORT) -p $(HTTP_PORT):$(HTTP_PORT) -e "ADDRESS=" -e "TEST=$(TESTS)" -e "TIMEOUT=$(TIMEOUT)" -e "DELAY=$(DELAY)" \
DOCKER_RUN_ARGS="--net host -e AGONES_SDK_GRPC_PORT=$(GRPC_PORT) -e AGONES_SDK_HTTP_PORT=$(HTTP_PORT) -e FEATURE_GATES=$(FEATURE_GATES) $(DOCKER_RUN_ARGS)" COMMAND=sdktest $(MAKE) run-sdk-command & \
docker run -p $(GRPC_PORT):$(GRPC_PORT) -p $(HTTP_PORT):$(HTTP_PORT) -e "FEATURE_GATES=$(FEATURE_GATES)" -e "ADDRESS=" -e "TEST=$(TESTS)" -e "TIMEOUT=$(TIMEOUT)" -e "DELAY=$(DELAY)" \
--net=host $(sidecar_tag) --grpc-port $(GRPC_PORT) --http-port $(HTTP_PORT)

# Run SDK conformance test for a specific SDK_FOLDER
Expand All @@ -155,7 +159,10 @@ run-sdk-conformance-test-node:
$(MAKE) run-sdk-conformance-test SDK_FOLDER=node GRPC_PORT=9002 HTTP_PORT=9102

run-sdk-conformance-test-go:
$(MAKE) run-sdk-conformance-test SDK_FOLDER=go GRPC_PORT=9001 HTTP_PORT=9101
# run without feature flags
$(MAKE) run-sdk-conformance-test SDK_FOLDER=go GRPC_PORT=9001 HTTP_PORT=9101
# run with feature flags enabled
$(MAKE) run-sdk-conformance-no-build SDK_FOLDER=go GRPC_PORT=9001 HTTP_PORT=9101 FEATURE_GATES=PlayerTracking=true TESTS=$(DEFAULT_CONFORMANCE_TESTS),$(ALPHA_CONFORMANCE_TESTS)

run-sdk-conformance-test-rust:
$(MAKE) run-sdk-conformance-test SDK_FOLDER=rust
Expand Down
43 changes: 39 additions & 4 deletions pkg/sdkserver/localsdk.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import (
"agones.dev/agones/pkg/sdk"
"agones.dev/agones/pkg/sdk/alpha"
"agones.dev/agones/pkg/sdk/beta"
"agones.dev/agones/pkg/util/runtime"
"github.com/fsnotify/fsnotify"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
Expand Down Expand Up @@ -177,6 +178,8 @@ func (l *LocalSDKServer) recordRequestWithValue(request string, value string, ob
fieldVal = strconv.FormatInt(l.gs.ObjectMeta.CreationTimestamp, 10)
case "UID":
fieldVal = l.gs.ObjectMeta.Uid
case "PlayerCapacity":
fieldVal = strconv.FormatInt(l.gs.Status.Players.Capacity, 10)
default:
fmt.Printf("Error: Unexpected Field to compare")
}
Expand Down Expand Up @@ -375,15 +378,47 @@ func (l *LocalSDKServer) PlayerDisconnect(ctx context.Context, id *alpha.PlayerI
// SetPlayerCapacity to change the game server's player capacity.
// [Stage:Alpha]
// [FeatureFlag:PlayerTesting]
func (l *LocalSDKServer) SetPlayerCapacity(ctx context.Context, count *alpha.Count) (*alpha.Empty, error) {
panic("implement me")
func (l *LocalSDKServer) SetPlayerCapacity(_ context.Context, count *alpha.Count) (*alpha.Empty, error) {
if !runtime.FeatureEnabled(runtime.FeaturePlayerTracking) {
return nil, errors.New(string(runtime.FeaturePlayerTracking) + " not enabled")
}

logrus.WithField("capacity", count.Count).Info("Setting Player Capacity")
l.gsMutex.Lock()
defer l.gsMutex.Unlock()

if l.gs.Status.Players == nil {
l.gs.Status.Players = &sdk.GameServer_Status_PlayerStatus{}
}

l.gs.Status.Players.Capacity = count.Count

l.update <- struct{}{}
l.recordRequestWithValue("setplayercapacity", strconv.FormatInt(count.Count, 10), "PlayerCapacity")
return &alpha.Empty{}, nil
}

// GetPlayerCapacity returns the current player capacity.
// [Stage:Alpha]
// [FeatureFlag:PlayerTesting]
func (l *LocalSDKServer) GetPlayerCapacity(ctx context.Context, _ *alpha.Empty) (*alpha.Count, error) {
panic("implement me")
func (l *LocalSDKServer) GetPlayerCapacity(_ context.Context, _ *alpha.Empty) (*alpha.Count, error) {
if !runtime.FeatureEnabled(runtime.FeaturePlayerTracking) {
return nil, errors.New(string(runtime.FeaturePlayerTracking) + " not enabled")
}
logrus.Info("Getting Player Capacity")
l.recordRequest("getplayercapacity")
l.gsMutex.RLock()
defer l.gsMutex.RUnlock()

// SDK.GetPlayerCapacity() has a contract of always return a number,
// so if we're nil, then let's always return a value, and
// remove lots of special cases upstream.
result := &alpha.Count{}
if l.gs.Status.Players != nil {
result.Count = l.gs.Status.Players.Capacity
}

return result, nil
}

// GetPlayerCount returns the current player count.
Expand Down
48 changes: 47 additions & 1 deletion pkg/sdkserver/localsdk_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
package sdkserver

import (
"context"
"encoding/json"
"io/ioutil"
"os"
Expand All @@ -24,8 +25,9 @@ import (

agonesv1 "agones.dev/agones/pkg/apis/agones/v1"
"agones.dev/agones/pkg/sdk"
"agones.dev/agones/pkg/sdk/alpha"
"agones.dev/agones/pkg/util/runtime"
"github.com/stretchr/testify/assert"
"golang.org/x/net/context"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/util/wait"
)
Expand Down Expand Up @@ -275,6 +277,50 @@ func TestLocalSDKServerWatchGameServer(t *testing.T) {
}
}

func TestLocalSDKServerPlayerCapacity(t *testing.T) {
t.Parallel()

runtime.FeatureTestMutex.Lock()
defer runtime.FeatureTestMutex.Unlock()
assert.NoError(t, runtime.ParseFeatures(string(runtime.FeaturePlayerTracking)+"=true"))

fixture := &agonesv1.GameServer{ObjectMeta: metav1.ObjectMeta{Name: "stuff"}}

e := &alpha.Empty{}
path, err := gsToTmpFile(fixture)
assert.NoError(t, err)
l, err := NewLocalSDKServer(path)
assert.Nil(t, err)

stream := newGameServerMockStream()
go func() {
err := l.WatchGameServer(&sdk.Empty{}, stream)
assert.Nil(t, err)
}()

c, err := l.GetPlayerCapacity(context.Background(), e)
assert.NoError(t, err)
assert.Equal(t, int64(0), c.Count)

_, err = l.SetPlayerCapacity(context.Background(), &alpha.Count{Count: 10})
assert.NoError(t, err)

select {
case msg := <-stream.msgs:
assert.Equal(t, int64(10), msg.Status.Players.Capacity)
case <-time.After(10 * time.Second):
assert.Fail(t, "timeout getting watch")
}

c, err = l.GetPlayerCapacity(context.Background(), e)
assert.NoError(t, err)
assert.Equal(t, int64(10), c.Count)

gs, err := l.GetGameServer(context.Background(), &sdk.Empty{})
assert.NoError(t, err)
assert.Equal(t, int64(10), gs.Status.Players.Capacity)
}

func gsToTmpFile(gs *agonesv1.GameServer) (string, error) {
file, err := ioutil.TempFile(os.TempDir(), "gameserver-")
if err != nil {
Expand Down
28 changes: 28 additions & 0 deletions test/sdk/go/sdk-client-test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,27 @@ package main
import (
"log"
"strconv"
"strings"
"time"

pkgSdk "agones.dev/agones/pkg/sdk"
"agones.dev/agones/pkg/util/runtime"
goSdk "agones.dev/agones/sdks/go"
"github.com/spf13/pflag"
"github.com/spf13/viper"
)

func main() {
viper.AllowEmptyEnv(true)
runtime.FeaturesBindFlags()
pflag.Parse()
viper.SetEnvKeyReplacer(strings.NewReplacer("-", "_"))
runtime.Must(runtime.FeaturesBindEnv())
runtime.Must(runtime.ParseFeaturesFromEnv())

log.SetFlags(log.Lshortfile)
log.Println("Client is starting")
log.Printf("Feature Flags: %s\n", runtime.EncodeFeatures())
time.Sleep(100 * time.Millisecond)
sdk, err := goSdk.NewSDK()
if err != nil {
Expand Down Expand Up @@ -80,6 +92,22 @@ func main() {
if err != nil {
log.Fatalf("Could not set annotation: %s", err)
}

if runtime.FeatureEnabled(runtime.FeaturePlayerTracking) {
capacity := int64(10)
if err = sdk.Alpha().SetPlayerCapacity(capacity); err != nil {
log.Fatalf("Error setting player capacity: %s", err)
}

c, err := sdk.Alpha().GetPlayerCapacity()
if err != nil {
log.Fatalf("Error getting player capacity: %s", err)
}
if c != capacity {
log.Fatalf("Player Capacity should be %d, but is %d", capacity, c)
}
}

err = sdk.Shutdown()
if err != nil {
log.Fatalf("Could not shutdown GameServer: %s", err)
Expand Down

0 comments on commit 92de6a7

Please sign in to comment.