Skip to content

Commit

Permalink
Implementation of SDK.Allocate()
Browse files Browse the repository at this point in the history
Now GameServers can self Allocate!

This is just the implementation of the GO SDK at this stage (although
the gRPC libraries have been regenerated). Other languages can come in
later PRs.

This is the first part of 1st Party MatchMaking support (#660)
  • Loading branch information
markmandel committed Apr 26, 2019
1 parent fd86d86 commit 2f8d3ae
Show file tree
Hide file tree
Showing 42 changed files with 955 additions and 313 deletions.
2 changes: 1 addition & 1 deletion build/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ KIND_PROFILE ?= agones
KIND_CONTAINER_NAME=kind-$(KIND_PROFILE)-control-plane

# Game Server image to use while doing end-to-end tests
GS_TEST_IMAGE ?= gcr.io/agones-images/udp-server:0.7
GS_TEST_IMAGE ?= gcr.io/agones-images/udp-server:0.8

# Directory that this Makefile is in.
mkfile_path := $(abspath $(lastword $(MAKEFILE_LIST)))
Expand Down
2 changes: 1 addition & 1 deletion examples/fleet.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -67,4 +67,4 @@ spec:
spec:
containers:
- name: simple-udp
image: gcr.io/agones-images/udp-server:0.7
image: gcr.io/agones-images/udp-server:0.8
2 changes: 1 addition & 1 deletion examples/simple-udp/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ REPOSITORY = gcr.io/agones-images

mkfile_path := $(abspath $(lastword $(MAKEFILE_LIST)))
project_path := $(dir $(mkfile_path))
server_tag = $(REPOSITORY)/udp-server:0.7
server_tag = $(REPOSITORY)/udp-server:0.8
root_path = $(realpath $(project_path)/../..)

# _____ _
Expand Down
2 changes: 1 addition & 1 deletion examples/simple-udp/fleet-distributed.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ spec:
spec:
containers:
- name: simple-udp
image: gcr.io/agones-images/udp-server:0.7
image: gcr.io/agones-images/udp-server:0.8
resources:
requests:
memory: "32Mi"
Expand Down
2 changes: 1 addition & 1 deletion examples/simple-udp/fleet.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ spec:
spec:
containers:
- name: simple-udp
image: gcr.io/agones-images/udp-server:0.7
image: gcr.io/agones-images/udp-server:0.8
resources:
requests:
memory: "64Mi"
Expand Down
2 changes: 1 addition & 1 deletion examples/simple-udp/gameserver.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ spec:
spec:
containers:
- name: simple-udp
image: gcr.io/agones-images/udp-server:0.7
image: gcr.io/agones-images/udp-server:0.8
resources:
requests:
memory: "32Mi"
Expand Down
2 changes: 1 addition & 1 deletion examples/simple-udp/gameserverset.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -31,4 +31,4 @@ spec:
spec:
containers:
- name: simple-udp
image: gcr.io/agones-images/udp-server:0.7
image: gcr.io/agones-images/udp-server:0.8
11 changes: 11 additions & 0 deletions examples/simple-udp/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,9 @@ func readWriteLoop(conn net.PacketConn, stop chan struct{}, s *sdk.SDK) {
case "GAMESERVER":
writeGameServerName(s, conn, sender)

case "ALLOCATE":
allocate(s)

case "WATCH":
watchGameServerEvents(s)

Expand Down Expand Up @@ -126,6 +129,14 @@ func readWriteLoop(conn net.PacketConn, stop chan struct{}, s *sdk.SDK) {
}
}

// allocate attemps to allocate this gameserver
func allocate(s *sdk.SDK) {
err := s.Allocate()
if err != nil {
log.Fatalf("could not allocate gameserver: %v", err)
}
}

// readPacket reads a string from the connection
func readPacket(conn net.PacketConn, b []byte) (net.Addr, string) {
n, sender, err := conn.ReadFrom(b)
Expand Down
2 changes: 1 addition & 1 deletion install/helm/agones/templates/NOTES.txt
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ spec:
spec:
containers:
- name: simple-udp
image: gcr.io/agones-images/udp-server:0.7
image: gcr.io/agones-images/udp-server:0.8

Finally don't forget to explore our documentation and usage guides on how to develop and host dedicated game servers on top of Agones. :

Expand Down
162 changes: 99 additions & 63 deletions pkg/sdk/sdk.pb.go

Large diffs are not rendered by default.

48 changes: 47 additions & 1 deletion pkg/sdk/sdk.pb.gw.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions pkg/sdkserver/localsdk.go
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,12 @@ func (l *LocalSDKServer) Ready(context.Context, *sdk.Empty) (*sdk.Empty, error)
return &sdk.Empty{}, nil
}

// Allocate logs that an allocate request has been received
func (l *LocalSDKServer) Allocate(context.Context, *sdk.Empty) (*sdk.Empty, error) {
logrus.Info("Allocate request has been received!")
return &sdk.Empty{}, nil
}

// Shutdown logs that the shutdown request has been received
func (l *LocalSDKServer) Shutdown(context.Context, *sdk.Empty) (*sdk.Empty, error) {
logrus.Info("Shutdown request has been received!")
Expand Down
58 changes: 57 additions & 1 deletion pkg/sdkserver/sdkserver.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ import (
"github.com/sirupsen/logrus"
"golang.org/x/net/context"
corev1 "k8s.io/api/core/v1"
k8serrors "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/fields"
"k8s.io/apimachinery/pkg/util/clock"
Expand All @@ -55,7 +56,17 @@ const (
updateAnnotation Operation = "updateAnnotation"
)

var _ sdk.SDKServer = &SDKServer{}
var (
_ sdk.SDKServer = &SDKServer{}

defaultTimeout = 30 * time.Second
defaultBackoff = wait.Backoff{
Duration: 100 * time.Millisecond,
Factor: 1,
Jitter: 0.1,
Steps: 5,
}
)

// SDKServer is a gRPC server, that is meant to be a sidecar
// for a GameServer that will update the game server status on SDK requests
Expand Down Expand Up @@ -330,6 +341,51 @@ func (s *SDKServer) Ready(ctx context.Context, e *sdk.Empty) (*sdk.Empty, error)
return e, nil
}

// Allocate set the GameServer to Allocate, as longs as it's not in UnHealthy,
// Shutdown or has a DeletionTimeStamp(). Times out after 30 seconds if it cannot
// complete the operation due to contention issues.
func (s *SDKServer) Allocate(context.Context, *sdk.Empty) (*sdk.Empty, error) {
s.logger.Info("Received self Allocate request")

now := s.clock.Now()
err := wait.ExponentialBackoff(defaultBackoff, func() (done bool, err error) {
gs, err := s.gameServer()
if err != nil {
return true, err
}

if !gs.ObjectMeta.DeletionTimestamp.IsZero() {
return true, nil
}

switch gs.Status.State {
case stablev1alpha1.GameServerStateUnhealthy:
return true, errors.New("cannot Allocate an Unhealthy GameServer")

case stablev1alpha1.GameServerStateShutdown:
return true, errors.New("cannot Allocate a Shutdown GameServer")
}

gsCopy := gs.DeepCopy()
gsCopy.Status.State = stablev1alpha1.GameServerStateAllocated
_, err = s.gameServerGetter.GameServers(s.namespace).Update(gsCopy)

// if a contention, and we are under the timeout period.
if k8serrors.IsConflict(err) {
// TODO: write a test for this
if s.clock.Since(now) > defaultTimeout {
return true, errors.New("Allocation request timed out")
}

return false, nil
}

return true, errors.Wrap(err, "could not update gameserver to Allocated")
})

return &sdk.Empty{}, errors.WithStack(err)
}

// Shutdown enters the Shutdown state change for this GameServer into
// the workqueue so it can be updated
func (s *SDKServer) Shutdown(ctx context.Context, e *sdk.Empty) (*sdk.Empty, error) {
Expand Down
Loading

0 comments on commit 2f8d3ae

Please sign in to comment.