diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000000..8ea23cf2cc --- /dev/null +++ b/.dockerignore @@ -0,0 +1,38 @@ +# Copyright 2018 Google Inc. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# project specific +.* +.idea +*.zip +/release +bin +/docs +*.md +*.amd64 + +# Created by .ignore support plugin (hsz.mobi) +### Go template +# Binaries for programs and plugins +*.exe +*.exe~ +*.dll +*.so +*.dylib + +# Test binary, build with `go test -c` +*.test + +# Output of the go coverage tool, specifically when used with LiteIDE +*.out diff --git a/.gitignore b/.gitignore index eb7a84d1bd..052df9ee5b 100644 --- a/.gitignore +++ b/.gitignore @@ -16,6 +16,7 @@ !.gitignore !.helmignore !.gitattributes +!.dockerignore *.iml bin *.o diff --git a/build/Makefile b/build/Makefile index 7eb74036fc..4f8926e37c 100644 --- a/build/Makefile +++ b/build/Makefile @@ -47,7 +47,7 @@ GCP_CLUSTER_ZONE ?= us-west1-c MINIKUBE_PROFILE ?= agones # Game Server image to use while doing end-to-end tests -GS_TEST_IMAGE ?= gcr.io/agones-images/udp-server:0.1 +GS_TEST_IMAGE ?= gcr.io/agones-images/udp-server:0.3 # Directory that this Makefile is in. mkfile_path := $(abspath $(lastword $(MAKEFILE_LIST))) @@ -119,7 +119,7 @@ test-go: # Runs end-to-end tests on the current configured cluster # For minikube user the minikube-test-e2e targets test-e2e: - $(DOCKER_RUN) go test -v $(agones_package)/test/e2e/... \ + $(DOCKER_RUN) go test -v -race $(agones_package)/test/e2e/... \ --kubeconfig /root/.kube/config \ --gameserver-image=$(GS_TEST_IMAGE) diff --git a/docs/sdk_rest_api.md b/docs/sdk_rest_api.md index 09a2d73ca2..d21ecf11d5 100644 --- a/docs/sdk_rest_api.md +++ b/docs/sdk_rest_api.md @@ -62,6 +62,28 @@ Call when the GameServer session is over and it's time to shut down $ curl -d "{}" -H "Content-Type: application/json" -X POST http://localhost:59358/shutdown ``` +### Set Label + +Apply a Label with the prefix "stable.agones.dev/sdk-" to the backing `GameServer` metadata. + +See the SDK [SetLabel](../sdks/README.md#setlabelkey-value) documentation for restrictions. + +#### Example + +```bash +$ curl -d '{"key": "foo", "value": "bar"}' -H "Content-Type: application/json" -X PUT http://localhost:59358/metadata/label +``` + +### Set Annotation + +Apply a Annotation with the prefix "stable.agones.dev/sdk-" to the backing `GameServer` metadata + +#### Example + +```bash +$ curl -d '{"key": "foo", "value": "bar"}' -H "Content-Type: application/json" -X PUT http://localhost:59358/metadata/annotation +``` + ### GameServer Call when you want to retrieve the backing `GameServer` configuration details diff --git a/examples/cpp-simple/server.cc b/examples/cpp-simple/server.cc index 38c9e8a7b4..fbcbe2a9ac 100644 --- a/examples/cpp-simple/server.cc +++ b/examples/cpp-simple/server.cc @@ -59,8 +59,22 @@ int main() { std::thread health (doHealth, sdk); std::thread watch (watchUpdates, sdk); + std::cout << "Setting a label" << std::endl; + grpc::Status status = sdk->SetLabel("test-label", "test-value"); + if (!status.ok()) { + std::cout << "Could not run SetLabel(): "+ status.error_message() + ". Exiting!" << std::endl; + return -1; + } + + std::cout << "Setting an annotation" << std::endl; + status = sdk->SetAnnotation("test-annotation", "test value"); + if (!status.ok()) { + std::cout << "Could not run SetAnnotation(): "+ status.error_message() + ". Exiting!" << std::endl; + return -1; + } + std::cout << "Marking server as ready..." << std::endl; - grpc::Status status = sdk->Ready(); + status = sdk->Ready(); if (!status.ok()) { std::cout << "Could not run Ready(): "+ status.error_message() + ". Exiting!" << std::endl; return -1; diff --git a/examples/simple-udp/main.go b/examples/simple-udp/main.go index 23632a7785..9f6e43cd4e 100644 --- a/examples/simple-udp/main.go +++ b/examples/simple-udp/main.go @@ -16,6 +16,7 @@ package main import ( + "encoding/json" "flag" "log" "net" @@ -23,9 +24,9 @@ import ( "strings" "time" - "agones.dev/agones/sdks/go" - "encoding/json" coresdk "agones.dev/agones/pkg/sdk" + "agones.dev/agones/sdks/go" + "strconv" ) // main starts a UDP server that received 1024 byte sized packets at at time @@ -67,23 +68,12 @@ func main() { func readWriteLoop(conn net.PacketConn, stop chan struct{}, s *sdk.SDK) { b := make([]byte, 1024) for { - n, sender, err := conn.ReadFrom(b) - if err != nil { - log.Fatalf("Could not read from udp stream: %v", err) - } - - txt := strings.TrimSpace(string(b[:n])) - log.Printf("Received packet from %v: %v", sender.String(), txt) + sender, txt := readPacket(conn, b) switch txt { + // shuts down the gameserver case "EXIT": - log.Printf("Received EXIT command. Exiting.") - // This tells Agones to shutdown this Game Server - shutdownErr := s.Shutdown() - if shutdownErr != nil { - log.Printf("Could not shutdown") - } - os.Exit(0) + exit(s) // turns off the health pings case "UNHEALTHY": @@ -94,14 +84,46 @@ func readWriteLoop(conn net.PacketConn, stop chan struct{}, s *sdk.SDK) { case "WATCH": watchGameServerEvents(s) - } - // echo it back - ack := "ACK: " + txt + "\n" - if _, err = conn.WriteTo([]byte(ack), sender); err != nil { - log.Fatalf("Could not write to udp stream: %v", err) + case "LABEL": + setLabel(s) + + case "ANNOTATION": + setAnnotation(s) } + + ack(conn, sender, txt) + } +} + +// readPacket reads a string from the connection +func readPacket(conn net.PacketConn, b []byte) (net.Addr, string) { + n, sender, err := conn.ReadFrom(b) + if err != nil { + log.Fatalf("Could not read from udp stream: %v", err) } + txt := strings.TrimSpace(string(b[:n])) + log.Printf("Received packet from %v: %v", sender.String(), txt) + return sender, txt +} + +// ack echoes it back, with an ACK +func ack(conn net.PacketConn, sender net.Addr, txt string) { + ack := "ACK: " + txt + "\n" + if _, err := conn.WriteTo([]byte(ack), sender); err != nil { + log.Fatalf("Could not write to udp stream: %v", err) + } +} + +// exit shutdowns the server +func exit(s *sdk.SDK) { + log.Printf("Received EXIT command. Exiting.") + // This tells Agones to shutdown this Game Server + shutdownErr := s.Shutdown() + if shutdownErr != nil { + log.Printf("Could not shutdown") + } + os.Exit(0) } // writes the GameServer name to the connection UDP stream @@ -138,6 +160,25 @@ func watchGameServerEvents(s *sdk.SDK) { } } +// setAnnotation sets a given annotation +func setAnnotation(s *sdk.SDK) { + log.Print("Setting annotation") + err := s.SetAnnotation("timestamp", time.Now().UTC().String()) + if err != nil { + log.Fatalf("could not set annotation: %v", err) + } +} + +// setLabel sets a given label +func setLabel(s *sdk.SDK) { + log.Print("Setting label") + // label values can only be alpha, - and . + err := s.SetLabel("timestamp", strconv.FormatInt(time.Now().Unix(), 10)) + if err != nil { + log.Fatalf("could not set label: %v", err) + } +} + // doHealth sends the regular Health Pings func doHealth(sdk *sdk.SDK, stop <-chan struct{}) { tick := time.Tick(2 * time.Second) diff --git a/pkg/gameservers/localsdk.go b/pkg/gameservers/localsdk.go index c76f29cae2..024241bd63 100644 --- a/pkg/gameservers/localsdk.go +++ b/pkg/gameservers/localsdk.go @@ -17,6 +17,7 @@ package gameservers import ( "io" "time" + "sync" "agones.dev/agones/pkg/sdk" "github.com/pkg/errors" @@ -50,14 +51,30 @@ var ( // is being run for local development, and doesn't connect to the // Kubernetes cluster type LocalSDKServer struct { - watchPeriod time.Duration + watchPeriod time.Duration + update chan struct{} + updateObservers sync.Map } // NewLocalSDKServer returns the default LocalSDKServer func NewLocalSDKServer() *LocalSDKServer { - return &LocalSDKServer{ - watchPeriod: 5 * time.Second, + l := &LocalSDKServer{ + watchPeriod: 5 * time.Second, + update: make(chan struct{}), + updateObservers: sync.Map{}, } + + go func() { + for value := range l.update { + logrus.Info("gameserver update received") + l.updateObservers.Range(func(observer, _ interface{}) bool { + observer.(chan struct{}) <- value + return true + }) + } + }() + + return l } // Ready logs that the Ready request has been received @@ -87,6 +104,22 @@ func (l *LocalSDKServer) Health(stream sdk.SDK_HealthServer) error { } } +// SetLabel applies a Label to the backing GameServer metadata +func (l *LocalSDKServer) SetLabel(_ context.Context, kv *sdk.KeyValue) (*sdk.Empty, error) { + logrus.WithField("values", kv).Info("Setting label") + fixture.ObjectMeta.Labels[metadataPrefix+kv.Key] = kv.Value + l.update <- struct{}{} + return &sdk.Empty{}, nil +} + +// SetAnnotation applies a Annotation to the backing GameServer metadata +func (l *LocalSDKServer) SetAnnotation(_ context.Context, kv *sdk.KeyValue) (*sdk.Empty, error) { + logrus.WithField("values", kv).Info("Setting annotation") + fixture.ObjectMeta.Annotations[metadataPrefix+kv.Key] = kv.Value + l.update <- struct{}{} + return &sdk.Empty{}, nil +} + // GetGameServer returns a dummy game server. func (l *LocalSDKServer) GetGameServer(context.Context, *sdk.Empty) (*sdk.GameServer, error) { logrus.Info("getting GameServer details") @@ -96,17 +129,32 @@ func (l *LocalSDKServer) GetGameServer(context.Context, *sdk.Empty) (*sdk.GameSe // WatchGameServer will return a dummy GameServer (with no changes), 3 times, every 5 seconds func (l *LocalSDKServer) WatchGameServer(_ *sdk.Empty, stream sdk.SDK_WatchGameServerServer) error { logrus.Info("connected to watch GameServer...") - times := 3 + observer := make(chan struct{}) + + defer func() { + l.updateObservers.Delete(observer) + close(observer) + }() + + l.updateObservers.Store(observer, true) + + // on connect, send 3 events, as advertised + go func() { + times := 3 - for i := 0; i < times; i++ { - logrus.Info("Sending watched GameServer!") + for i := 0; i < times; i++ { + logrus.Info("Sending watched GameServer!") + l.update <- struct{}{} + time.Sleep(l.watchPeriod) + } + }() + + for range observer { err := stream.Send(fixture) if err != nil { logrus.WithError(err).Error("error sending gameserver") return err } - - time.Sleep(l.watchPeriod) } return nil diff --git a/pkg/gameservers/localsdk_test.go b/pkg/gameservers/localsdk_test.go index e355f7677f..3e3307e1c0 100644 --- a/pkg/gameservers/localsdk_test.go +++ b/pkg/gameservers/localsdk_test.go @@ -56,6 +56,60 @@ func TestLocal(t *testing.T) { assert.Equal(t, fixture, gs) } +func TestLocalSDKServerSetLabel(t *testing.T) { + ctx := context.Background() + e := &sdk.Empty{} + l := NewLocalSDKServer() + kv := &sdk.KeyValue{Key: "foo", Value: "bar"} + + stream := newGameServerMockStream() + go func() { + err := l.WatchGameServer(e, stream) + assert.Nil(t, err) + }() + + _, err := l.SetLabel(ctx, kv) + assert.Nil(t, err) + + gs, err := l.GetGameServer(ctx, e) + assert.Nil(t, err) + assert.Equal(t, gs.ObjectMeta.Labels[metadataPrefix+"foo"], "bar") + + select { + case msg := <-stream.msgs: + assert.Equal(t, msg.ObjectMeta.Labels[metadataPrefix+"foo"], "bar") + case <-time.After(2 * l.watchPeriod): + assert.FailNow(t, "timeout on receiving messages") + } +} + +func TestLocalSDKServerSetAnnotation(t *testing.T) { + ctx := context.Background() + e := &sdk.Empty{} + l := NewLocalSDKServer() + kv := &sdk.KeyValue{Key: "bar", Value: "foo"} + + stream := newGameServerMockStream() + go func() { + err := l.WatchGameServer(e, stream) + assert.Nil(t, err) + }() + + _, err := l.SetAnnotation(ctx, kv) + assert.Nil(t, err) + + gs, err := l.GetGameServer(ctx, e) + assert.Nil(t, err) + assert.Equal(t, gs.ObjectMeta.Annotations[metadataPrefix+"bar"], "foo") + + select { + case msg := <-stream.msgs: + assert.Equal(t, msg.ObjectMeta.Annotations[metadataPrefix+"bar"], "foo") + case <-time.After(2 * l.watchPeriod): + assert.FailNow(t, "timeout on receiving messages") + } +} + func TestLocalSDKServerWatchGameServer(t *testing.T) { t.Parallel() @@ -64,15 +118,17 @@ func TestLocalSDKServerWatchGameServer(t *testing.T) { l.watchPeriod = time.Second stream := newGameServerMockStream() - err := l.WatchGameServer(e, stream) - assert.Nil(t, err) + go func() { + err := l.WatchGameServer(e, stream) + assert.Nil(t, err) + }() for i := 0; i < 3; i++ { select { case msg := <-stream.msgs: assert.Equal(t, fixture, msg) case <-time.After(2 * l.watchPeriod): - assert.FailNow(t, "timeout on receiving messagess") + assert.FailNow(t, "timeout on receiving messages") } } } diff --git a/pkg/gameservers/sdk.go b/pkg/gameservers/sdk.go new file mode 100644 index 0000000000..6b3132fbb7 --- /dev/null +++ b/pkg/gameservers/sdk.go @@ -0,0 +1,20 @@ +// Copyright 2018 Google Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package gameservers + +const ( + // metadataPrefix prefix for labels and annotations + metadataPrefix = "stable.agones.dev/sdk-" +) diff --git a/pkg/gameservers/sdkserver.go b/pkg/gameservers/sdkserver.go index a482ad338a..23ea094bbf 100644 --- a/pkg/gameservers/sdkserver.go +++ b/pkg/gameservers/sdkserver.go @@ -26,7 +26,7 @@ import ( "agones.dev/agones/pkg/client/clientset/versioned" typedv1alpha1 "agones.dev/agones/pkg/client/clientset/versioned/typed/stable/v1alpha1" "agones.dev/agones/pkg/client/informers/externalversions" - "agones.dev/agones/pkg/client/listers/stable/v1alpha1" + listersv1alpha1 "agones.dev/agones/pkg/client/listers/stable/v1alpha1" "agones.dev/agones/pkg/sdk" "agones.dev/agones/pkg/util/runtime" "agones.dev/agones/pkg/util/workerqueue" @@ -40,11 +40,20 @@ import ( "k8s.io/apimachinery/pkg/util/wait" "k8s.io/client-go/kubernetes" "k8s.io/client-go/kubernetes/scheme" - typedcorev1 "k8s.io/client-go/kubernetes/typed/core/v1" + k8sv1 "k8s.io/client-go/kubernetes/typed/core/v1" "k8s.io/client-go/tools/cache" "k8s.io/client-go/tools/record" ) +// Operation is a synchronisation action +type Operation string + +const ( + updateState Operation = "updateState" + updateLabel Operation = "updateLabel" + updateAnnotation Operation = "updateAnnotation" +) + var _ sdk.SDKServer = &SDKServer{} // SDKServer is a gRPC server, that is meant to be a sidecar @@ -55,7 +64,7 @@ type SDKServer struct { namespace string informerFactory externalversions.SharedInformerFactory gameServerGetter typedv1alpha1.GameServersGetter - gameServerLister v1alpha1.GameServerLister + gameServerLister listersv1alpha1.GameServerLister gameServerSynced cache.InformerSynced server *http.Server clock clock.Clock @@ -112,7 +121,7 @@ func NewSDKServer(gameServerName, namespace string, kubeClient kubernetes.Interf eventBroadcaster := record.NewBroadcaster() eventBroadcaster.StartLogging(s.logger.Infof) - eventBroadcaster.StartRecordingToSink(&typedcorev1.EventSinkImpl{Interface: kubeClient.CoreV1().Events("")}) + eventBroadcaster.StartRecordingToSink(&k8sv1.EventSinkImpl{Interface: kubeClient.CoreV1().Events("")}) s.recorder = eventBroadcaster.NewRecorder(scheme.Scheme, corev1.EventSource{Component: "gameserver-sidecar"}) mux.HandleFunc("/healthz", func(w http.ResponseWriter, r *http.Request) { @@ -135,9 +144,7 @@ func NewSDKServer(gameServerName, namespace string, kubeClient kubernetes.Interf }) s.workerqueue = workerqueue.NewWorkerQueue( - func(key string) error { - return s.updateState(stablev1alpha1.State(key)) - }, + s.syncGameServer, s.logger, strings.Join([]string{stable.GroupName, s.namespace, s.gameServerName}, ".")) @@ -165,7 +172,7 @@ func (s *SDKServer) Run(stop <-chan struct{}) error { // grab configuration details s.health = gs.Spec.Health - s.logger.WithField("health", s.health).Info("setting health configuration") + s.logger.WithField("health", s.health).Info("setting health configuration") s.healthTimeout = time.Duration(gs.Spec.Health.PeriodSeconds) * time.Second s.initHealthLastUpdated(time.Duration(gs.Spec.Health.InitialDelaySeconds) * time.Second) @@ -195,14 +202,42 @@ func (s *SDKServer) Run(stop <-chan struct{}) error { return nil } +// syncGameServer synchronises the GameServer with the +// requested operations +// takes a key in the format of {operation}/{data} +func (s *SDKServer) syncGameServer(key string) error { + op := strings.Split(key, "/") + rest := op[1:] + + switch Operation(op[0]) { + case updateState: + return s.syncState(rest) + case updateLabel: + return s.syncLabel(rest) + case updateAnnotation: + return s.syncAnnotation(rest) + } + + return errors.Errorf("could not sync game server key: %s", key) +} + +// syncState converts the string array into values for updateState +func (s *SDKServer) syncState(rest []string) error { + if len(rest) == 0 { + return errors.New("could not sync state, as not state provided") + } + + return s.updateState(stablev1alpha1.State(rest[0])) +} + // updateState sets the GameServer Status's state to the state // that has been passed through func (s *SDKServer) updateState(state stablev1alpha1.State) error { s.logger.WithField("state", state).Info("Updating state") gameServers := s.gameServerGetter.GameServers(s.namespace) - gs, err := s.gameServerLister.GameServers(s.namespace).Get(s.gameServerName) + gs, err := s.gameServer() if err != nil { - return errors.Wrapf(err, "could not retrieve GameServer %s/%s", s.namespace, s.gameServerName) + return err } // if the state is currently unhealthy, you can't go back to Ready @@ -222,11 +257,80 @@ func (s *SDKServer) updateState(state stablev1alpha1.State) error { return errors.Wrapf(err, "could not update GameServer %s/%s to state %s", s.namespace, s.gameServerName, state) } +func (s *SDKServer) gameServer() (*stablev1alpha1.GameServer, error) { + gs, err := s.gameServerLister.GameServers(s.namespace).Get(s.gameServerName) + return gs, errors.Wrapf(err, "could not retrieve GameServer %s/%s", s.namespace, s.gameServerName) +} + +// syncLabel converts the string array values into values for +// updateLabel +func (s *SDKServer) syncLabel(rest []string) error { + if len(rest) < 2 { + return errors.Errorf("could not sync label: %#v", rest) + } + + return s.updateLabel(rest[0], rest[1]) +} + +// updateLabel updates the label on this GameServer, with the prefix of +// "stable.agones.dev/sdk-" +func (s *SDKServer) updateLabel(key, value string) error { + s.logger.WithField("key", key).WithField("value", value).Info("updating label") + gs, err := s.gameServer() + if err != nil { + return err + } + + gsCopy := gs.DeepCopy() + if gsCopy.ObjectMeta.Labels == nil { + gsCopy.ObjectMeta.Labels = map[string]string{} + } + gsCopy.ObjectMeta.Labels[metadataPrefix+key] = value + + _, err = s.gameServerGetter.GameServers(s.namespace).Update(gsCopy) + return err +} + +// syncAnnotation converts the string array values into values for +// updateAnnotation +func (s *SDKServer) syncAnnotation(rest []string) error { + if len(rest) < 2 { + return errors.Errorf("could not sync annotation: %#v", rest) + } + + return s.updateAnnotation(rest[0], rest[1]) +} + +// updateAnnotation updates the Annotation on this GameServer, with the prefix of +// "stable.agones.dev/sdk-" +func (s *SDKServer) updateAnnotation(key, value string) error { + gs, err := s.gameServer() + if err != nil { + return err + } + + gsCopy := gs.DeepCopy() + if gsCopy.ObjectMeta.Annotations == nil { + gsCopy.ObjectMeta.Annotations = map[string]string{} + } + gsCopy.ObjectMeta.Annotations[metadataPrefix+key] = value + + _, err = s.gameServerGetter.GameServers(s.namespace).Update(gsCopy) + return err +} + +// enqueueState enqueue a State change request into the +// workerqueue +func (s *SDKServer) enqueueState(state stablev1alpha1.State) { + key := string(updateState) + "/" + string(state) + s.workerqueue.Enqueue(cache.ExplicitKey(key)) +} + // Ready enters the RequestReady state change for this GameServer into // the workqueue so it can be updated func (s *SDKServer) Ready(ctx context.Context, e *sdk.Empty) (*sdk.Empty, error) { s.logger.Info("Received Ready request, adding to queue") - s.workerqueue.Enqueue(cache.ExplicitKey(stablev1alpha1.RequestReady)) + s.enqueueState(stablev1alpha1.RequestReady) return e, nil } @@ -234,7 +338,7 @@ func (s *SDKServer) Ready(ctx context.Context, e *sdk.Empty) (*sdk.Empty, error) // the workqueue so it can be updated func (s *SDKServer) Shutdown(ctx context.Context, e *sdk.Empty) (*sdk.Empty, error) { s.logger.Info("Received Shutdown request, adding to queue") - s.workerqueue.Enqueue(cache.ExplicitKey(stablev1alpha1.Shutdown)) + s.enqueueState(stablev1alpha1.Shutdown) return e, nil } @@ -255,12 +359,30 @@ func (s *SDKServer) Health(stream sdk.SDK_HealthServer) error { } } +// SetLabel adds the Key/Value to be used to set the label with the metadataPrefix to the `GameServer` +// metdata +func (s *SDKServer) SetLabel(_ context.Context, kv *sdk.KeyValue) (*sdk.Empty, error) { + s.logger.WithField("values", kv).Info("Adding SetLabel to queue") + key := string(updateLabel) + "/" + kv.Key + "/" + kv.Value + s.workerqueue.Enqueue(cache.ExplicitKey(key)) + return &sdk.Empty{}, nil +} + +// SetAnnotation adds the Key/Value to be used to set the annotations with the metadataPrefix to the `GameServer` +// metdata +func (s *SDKServer) SetAnnotation(_ context.Context, kv *sdk.KeyValue) (*sdk.Empty, error) { + s.logger.WithField("values", kv).Info("Adding SetLabel to queue") + key := string(updateAnnotation) + "/" + kv.Key + "/" + kv.Value + s.workerqueue.Enqueue(cache.ExplicitKey(key)) + return &sdk.Empty{}, nil +} + // GetGameServer returns the current GameServer configuration and state from the backing GameServer CRD func (s *SDKServer) GetGameServer(context.Context, *sdk.Empty) (*sdk.GameServer, error) { s.logger.Info("Received GetGameServer request") - gs, err := s.gameServerLister.GameServers(s.namespace).Get(s.gameServerName) + gs, err := s.gameServer() if err != nil { - return nil, errors.Wrapf(err, "error retrieving gameserver %s/%s", s.namespace, s.gameServerName) + return nil, err } return s.convert(gs), nil @@ -349,7 +471,7 @@ func (s *SDKServer) runHealth() { s.checkHealth() if !s.healthy() { s.logger.WithField("gameServerName", s.gameServerName).Info("being marked as not healthy") - s.workerqueue.Enqueue(cache.ExplicitKey(stablev1alpha1.Unhealthy)) + s.enqueueState(stablev1alpha1.Unhealthy) } } diff --git a/pkg/gameservers/sdkserver_test.go b/pkg/gameservers/sdkserver_test.go index 98782d5a1d..83b44627e8 100644 --- a/pkg/gameservers/sdkserver_test.go +++ b/pkg/gameservers/sdkserver_test.go @@ -15,7 +15,7 @@ package gameservers import ( - "net/http" + "net/http" "sync" "testing" "time" @@ -33,35 +33,65 @@ import ( "k8s.io/apimachinery/pkg/watch" k8stesting "k8s.io/client-go/testing" "k8s.io/client-go/tools/cache" - ) +) func TestSidecarRun(t *testing.T) { t.Parallel() + type expected struct { + state v1alpha1.State + labels map[string]string + annotations map[string]string + recordings []string + } + fixtures := map[string]struct { - state v1alpha1.State - f func(*SDKServer, context.Context) - recordings []string + f func(*SDKServer, context.Context) + expected expected }{ "ready": { - state: v1alpha1.RequestReady, f: func(sc *SDKServer, ctx context.Context) { sc.Ready(ctx, &sdk.Empty{}) // nolint: errcheck }, + expected: expected{ + state: v1alpha1.RequestReady, + }, }, "shutdown": { - state: v1alpha1.Shutdown, f: func(sc *SDKServer, ctx context.Context) { sc.Shutdown(ctx, &sdk.Empty{}) // nolint: errcheck }, + expected: expected{ + state: v1alpha1.Shutdown, + }, }, "unhealthy": { - state: v1alpha1.Unhealthy, f: func(sc *SDKServer, ctx context.Context) { // we have a 1 second timeout time.Sleep(2 * time.Second) }, - recordings: []string{string(v1alpha1.Unhealthy)}, + expected: expected{ + state: v1alpha1.Unhealthy, + recordings: []string{string(v1alpha1.Unhealthy)}, + }, + }, + "label": { + f: func(sc *SDKServer, ctx context.Context) { + _, err := sc.SetLabel(ctx, &sdk.KeyValue{Key: "foo", Value: "bar"}) + assert.Nil(t, err) + }, + expected: expected{ + labels: map[string]string{metadataPrefix + "foo": "bar"}, + }, + }, + "annotation": { + f: func(sc *SDKServer, ctx context.Context) { + _, err := sc.SetAnnotation(ctx, &sdk.KeyValue{Key: "test", Value: "annotation"}) + assert.Nil(t, err) + }, + expected: expected{ + annotations: map[string]string{metadataPrefix + "test": "annotation"}, + }, }, } @@ -72,7 +102,9 @@ func TestSidecarRun(t *testing.T) { m.AgonesClient.AddReactor("list", "gameservers", func(action k8stesting.Action) (bool, runtime.Object, error) { gs := v1alpha1.GameServer{ - ObjectMeta: metav1.ObjectMeta{Name: "test", Namespace: "default"}, + ObjectMeta: metav1.ObjectMeta{ + Name: "test", Namespace: "default", + }, Spec: v1alpha1.GameServerSpec{ Health: v1alpha1.Health{Disabled: false, FailureThreshold: 1, PeriodSeconds: 1, InitialDelaySeconds: 0}, }, @@ -88,7 +120,16 @@ func TestSidecarRun(t *testing.T) { ua := action.(k8stesting.UpdateAction) gs := ua.GetObject().(*v1alpha1.GameServer) - assert.Equal(t, v.state, gs.Status.State) + if v.expected.state != "" { + assert.Equal(t, v.expected.state, gs.Status.State) + } + + for label, value := range v.expected.labels { + assert.Equal(t, value, gs.ObjectMeta.Labels[label]) + } + for ann, value := range v.expected.annotations { + assert.Equal(t, value, gs.ObjectMeta.Annotations[ann]) + } return true, gs, nil }) @@ -116,7 +157,7 @@ func TestSidecarRun(t *testing.T) { } logrus.Info("attempting to find event recording") - for _, str := range v.recordings { + for _, str := range v.expected.recordings { agtesting.AssertEventContains(t, m.FakeRecorder.Events, str) } @@ -126,6 +167,85 @@ func TestSidecarRun(t *testing.T) { } } +func TestSDKServerSyncGameServer(t *testing.T) { + t.Parallel() + + type expected struct { + state v1alpha1.State + labels map[string]string + annotations map[string]string + } + + fixtures := map[string]struct { + expected expected + key string + }{ + "ready": { + key: string(updateState) + "/" + string(v1alpha1.Ready), + expected: expected{ + state: v1alpha1.Ready, + }, + }, + "label": { + key: string(updateLabel) + "/foo/bar", + expected: expected{ + labels: map[string]string{metadataPrefix + "foo": "bar"}, + }, + }, + "annotation": { + key: string(updateAnnotation) + "/test/annotation", + expected: expected{ + annotations: map[string]string{metadataPrefix + "test": "annotation"}, + }, + }, + } + + for k, v := range fixtures { + t.Run(k, func(t *testing.T) { + m := agtesting.NewMocks() + sc, err := defaultSidecar(m) + assert.Nil(t, err) + updated := false + + m.AgonesClient.AddReactor("list", "gameservers", func(action k8stesting.Action) (bool, runtime.Object, error) { + gs := v1alpha1.GameServer{ObjectMeta: metav1.ObjectMeta{ + UID: "1234", + Name: sc.gameServerName, Namespace: sc.namespace, + Labels: map[string]string{}, Annotations: map[string]string{}}, + } + return true, &v1alpha1.GameServerList{Items: []v1alpha1.GameServer{gs}}, nil + }) + m.AgonesClient.AddReactor("update", "gameservers", func(action k8stesting.Action) (bool, runtime.Object, error) { + updated = true + ua := action.(k8stesting.UpdateAction) + gs := ua.GetObject().(*v1alpha1.GameServer) + + if v.expected.state != "" { + assert.Equal(t, v.expected.state, gs.Status.State) + } + for label, value := range v.expected.labels { + assert.Equal(t, value, gs.ObjectMeta.Labels[label]) + } + for ann, value := range v.expected.annotations { + assert.Equal(t, value, gs.ObjectMeta.Annotations[ann]) + } + + return true, gs, nil + }) + + stop := make(chan struct{}) + defer close(stop) + sc.informerFactory.Start(stop) + assert.True(t, cache.WaitForCacheSync(stop, sc.gameServerSynced)) + + err = sc.syncGameServer(v.key) + assert.Nil(t, err) + assert.True(t, updated, "should have updated") + + }) + } +} + func TestSidecarUpdateState(t *testing.T) { t.Parallel() diff --git a/pkg/sdk/sdk.pb.go b/pkg/sdk/sdk.pb.go index 13a8d5d52d..d31a188a0e 100644 --- a/pkg/sdk/sdk.pb.go +++ b/pkg/sdk/sdk.pb.go @@ -39,6 +39,7 @@ var _ = math.Inf // proto package needs to be updated. const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package +// I am Empty type Empty struct { XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_unrecognized []byte `json:"-"` @@ -49,7 +50,7 @@ func (m *Empty) Reset() { *m = Empty{} } func (m *Empty) String() string { return proto.CompactTextString(m) } func (*Empty) ProtoMessage() {} func (*Empty) Descriptor() ([]byte, []int) { - return fileDescriptor_sdk_33bebf5c55a081c3, []int{0} + return fileDescriptor_sdk_1ced06a751c91178, []int{0} } func (m *Empty) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_Empty.Unmarshal(m, b) @@ -69,6 +70,53 @@ func (m *Empty) XXX_DiscardUnknown() { var xxx_messageInfo_Empty proto.InternalMessageInfo +// Key, Value entry +type KeyValue struct { + Key string `protobuf:"bytes,1,opt,name=key" json:"key,omitempty"` + Value string `protobuf:"bytes,2,opt,name=value" json:"value,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *KeyValue) Reset() { *m = KeyValue{} } +func (m *KeyValue) String() string { return proto.CompactTextString(m) } +func (*KeyValue) ProtoMessage() {} +func (*KeyValue) Descriptor() ([]byte, []int) { + return fileDescriptor_sdk_1ced06a751c91178, []int{1} +} +func (m *KeyValue) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_KeyValue.Unmarshal(m, b) +} +func (m *KeyValue) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_KeyValue.Marshal(b, m, deterministic) +} +func (dst *KeyValue) XXX_Merge(src proto.Message) { + xxx_messageInfo_KeyValue.Merge(dst, src) +} +func (m *KeyValue) XXX_Size() int { + return xxx_messageInfo_KeyValue.Size(m) +} +func (m *KeyValue) XXX_DiscardUnknown() { + xxx_messageInfo_KeyValue.DiscardUnknown(m) +} + +var xxx_messageInfo_KeyValue proto.InternalMessageInfo + +func (m *KeyValue) GetKey() string { + if m != nil { + return m.Key + } + return "" +} + +func (m *KeyValue) GetValue() string { + if m != nil { + return m.Value + } + return "" +} + // A GameServer Custom Resource Definition object // We will only export those resources that make the most // sense. Can always expand to more as needed. @@ -85,7 +133,7 @@ func (m *GameServer) Reset() { *m = GameServer{} } func (m *GameServer) String() string { return proto.CompactTextString(m) } func (*GameServer) ProtoMessage() {} func (*GameServer) Descriptor() ([]byte, []int) { - return fileDescriptor_sdk_33bebf5c55a081c3, []int{1} + return fileDescriptor_sdk_1ced06a751c91178, []int{2} } func (m *GameServer) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_GameServer.Unmarshal(m, b) @@ -148,7 +196,7 @@ func (m *GameServer_ObjectMeta) Reset() { *m = GameServer_ObjectMeta{} } func (m *GameServer_ObjectMeta) String() string { return proto.CompactTextString(m) } func (*GameServer_ObjectMeta) ProtoMessage() {} func (*GameServer_ObjectMeta) Descriptor() ([]byte, []int) { - return fileDescriptor_sdk_33bebf5c55a081c3, []int{1, 0} + return fileDescriptor_sdk_1ced06a751c91178, []int{2, 0} } func (m *GameServer_ObjectMeta) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_GameServer_ObjectMeta.Unmarshal(m, b) @@ -242,7 +290,7 @@ func (m *GameServer_Spec) Reset() { *m = GameServer_Spec{} } func (m *GameServer_Spec) String() string { return proto.CompactTextString(m) } func (*GameServer_Spec) ProtoMessage() {} func (*GameServer_Spec) Descriptor() ([]byte, []int) { - return fileDescriptor_sdk_33bebf5c55a081c3, []int{1, 1} + return fileDescriptor_sdk_1ced06a751c91178, []int{2, 1} } func (m *GameServer_Spec) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_GameServer_Spec.Unmarshal(m, b) @@ -283,7 +331,7 @@ func (m *GameServer_Spec_Health) Reset() { *m = GameServer_Spec_Health{} func (m *GameServer_Spec_Health) String() string { return proto.CompactTextString(m) } func (*GameServer_Spec_Health) ProtoMessage() {} func (*GameServer_Spec_Health) Descriptor() ([]byte, []int) { - return fileDescriptor_sdk_33bebf5c55a081c3, []int{1, 1, 0} + return fileDescriptor_sdk_1ced06a751c91178, []int{2, 1, 0} } func (m *GameServer_Spec_Health) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_GameServer_Spec_Health.Unmarshal(m, b) @@ -344,7 +392,7 @@ func (m *GameServer_Status) Reset() { *m = GameServer_Status{} } func (m *GameServer_Status) String() string { return proto.CompactTextString(m) } func (*GameServer_Status) ProtoMessage() {} func (*GameServer_Status) Descriptor() ([]byte, []int) { - return fileDescriptor_sdk_33bebf5c55a081c3, []int{1, 2} + return fileDescriptor_sdk_1ced06a751c91178, []int{2, 2} } func (m *GameServer_Status) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_GameServer_Status.Unmarshal(m, b) @@ -397,7 +445,7 @@ func (m *GameServer_Status_Port) Reset() { *m = GameServer_Status_Port{} func (m *GameServer_Status_Port) String() string { return proto.CompactTextString(m) } func (*GameServer_Status_Port) ProtoMessage() {} func (*GameServer_Status_Port) Descriptor() ([]byte, []int) { - return fileDescriptor_sdk_33bebf5c55a081c3, []int{1, 2, 0} + return fileDescriptor_sdk_1ced06a751c91178, []int{2, 2, 0} } func (m *GameServer_Status_Port) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_GameServer_Status_Port.Unmarshal(m, b) @@ -433,6 +481,7 @@ func (m *GameServer_Status_Port) GetPort() int32 { func init() { proto.RegisterType((*Empty)(nil), "stable.agones.dev.sdk.Empty") + proto.RegisterType((*KeyValue)(nil), "stable.agones.dev.sdk.KeyValue") proto.RegisterType((*GameServer)(nil), "stable.agones.dev.sdk.GameServer") proto.RegisterType((*GameServer_ObjectMeta)(nil), "stable.agones.dev.sdk.GameServer.ObjectMeta") proto.RegisterMapType((map[string]string)(nil), "stable.agones.dev.sdk.GameServer.ObjectMeta.AnnotationsEntry") @@ -464,6 +513,10 @@ type SDKClient interface { GetGameServer(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*GameServer, error) // Send GameServer details whenever the GameServer is updated WatchGameServer(ctx context.Context, in *Empty, opts ...grpc.CallOption) (SDK_WatchGameServerClient, error) + // Apply a Label to the backing GameServer metadata + SetLabel(ctx context.Context, in *KeyValue, opts ...grpc.CallOption) (*Empty, error) + // Apply a Annotation to the backing GameServer metadata + SetAnnotation(ctx context.Context, in *KeyValue, opts ...grpc.CallOption) (*Empty, error) } type sDKClient struct { @@ -567,6 +620,24 @@ func (x *sDKWatchGameServerClient) Recv() (*GameServer, error) { return m, nil } +func (c *sDKClient) SetLabel(ctx context.Context, in *KeyValue, opts ...grpc.CallOption) (*Empty, error) { + out := new(Empty) + err := grpc.Invoke(ctx, "/stable.agones.dev.sdk.SDK/SetLabel", in, out, c.cc, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *sDKClient) SetAnnotation(ctx context.Context, in *KeyValue, opts ...grpc.CallOption) (*Empty, error) { + out := new(Empty) + err := grpc.Invoke(ctx, "/stable.agones.dev.sdk.SDK/SetAnnotation", in, out, c.cc, opts...) + if err != nil { + return nil, err + } + return out, nil +} + // Server API for SDK service type SDKServer interface { @@ -580,6 +651,10 @@ type SDKServer interface { GetGameServer(context.Context, *Empty) (*GameServer, error) // Send GameServer details whenever the GameServer is updated WatchGameServer(*Empty, SDK_WatchGameServerServer) error + // Apply a Label to the backing GameServer metadata + SetLabel(context.Context, *KeyValue) (*Empty, error) + // Apply a Annotation to the backing GameServer metadata + SetAnnotation(context.Context, *KeyValue) (*Empty, error) } func RegisterSDKServer(s *grpc.Server, srv SDKServer) { @@ -687,6 +762,42 @@ func (x *sDKWatchGameServerServer) Send(m *GameServer) error { return x.ServerStream.SendMsg(m) } +func _SDK_SetLabel_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(KeyValue) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(SDKServer).SetLabel(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/stable.agones.dev.sdk.SDK/SetLabel", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(SDKServer).SetLabel(ctx, req.(*KeyValue)) + } + return interceptor(ctx, in, info, handler) +} + +func _SDK_SetAnnotation_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(KeyValue) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(SDKServer).SetAnnotation(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/stable.agones.dev.sdk.SDK/SetAnnotation", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(SDKServer).SetAnnotation(ctx, req.(*KeyValue)) + } + return interceptor(ctx, in, info, handler) +} + var _SDK_serviceDesc = grpc.ServiceDesc{ ServiceName: "stable.agones.dev.sdk.SDK", HandlerType: (*SDKServer)(nil), @@ -703,6 +814,14 @@ var _SDK_serviceDesc = grpc.ServiceDesc{ MethodName: "GetGameServer", Handler: _SDK_GetGameServer_Handler, }, + { + MethodName: "SetLabel", + Handler: _SDK_SetLabel_Handler, + }, + { + MethodName: "SetAnnotation", + Handler: _SDK_SetAnnotation_Handler, + }, }, Streams: []grpc.StreamDesc{ { @@ -719,54 +838,58 @@ var _SDK_serviceDesc = grpc.ServiceDesc{ Metadata: "sdk.proto", } -func init() { proto.RegisterFile("sdk.proto", fileDescriptor_sdk_33bebf5c55a081c3) } - -var fileDescriptor_sdk_33bebf5c55a081c3 = []byte{ - // 725 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x95, 0xcd, 0x6e, 0xdb, 0x46, - 0x10, 0xc7, 0x41, 0xf3, 0x43, 0xe2, 0xa8, 0xae, 0xe5, 0xb5, 0x0b, 0xb0, 0x84, 0x51, 0xb8, 0x42, - 0x51, 0xa8, 0x46, 0x4d, 0x19, 0xee, 0xc5, 0x15, 0xd0, 0xa2, 0x1f, 0x76, 0xdd, 0xa2, 0x35, 0x6a, - 0x50, 0x86, 0x0b, 0x18, 0x05, 0x84, 0x15, 0x39, 0x90, 0x58, 0x51, 0x5c, 0x62, 0x77, 0x25, 0x43, - 0xd7, 0xbe, 0x42, 0x1e, 0x22, 0xb9, 0x24, 0x2f, 0x93, 0x57, 0xc8, 0x3d, 0xd7, 0x1c, 0x83, 0x5d, - 0x92, 0x96, 0xe2, 0x38, 0xfe, 0x80, 0x73, 0xd2, 0xec, 0xcc, 0xfc, 0x7f, 0xb3, 0xda, 0x99, 0x5d, - 0x82, 0x2b, 0xe2, 0x71, 0x90, 0x73, 0x26, 0x19, 0xf9, 0x4c, 0x48, 0x3a, 0x48, 0x31, 0xa0, 0x43, - 0x96, 0xa1, 0x08, 0x62, 0x9c, 0x05, 0x22, 0x1e, 0xfb, 0x5b, 0x43, 0xc6, 0x86, 0x29, 0x76, 0x68, - 0x9e, 0x74, 0x68, 0x96, 0x31, 0x49, 0x65, 0xc2, 0x32, 0x51, 0x88, 0x5a, 0x35, 0xb0, 0x8f, 0x26, - 0xb9, 0x9c, 0xb7, 0x5e, 0xb8, 0x00, 0xc7, 0x74, 0x82, 0x3d, 0xe4, 0x33, 0xe4, 0xe4, 0x04, 0x1a, - 0x6c, 0xf0, 0x1f, 0x46, 0xb2, 0x3f, 0x41, 0x49, 0x3d, 0x63, 0xdb, 0x68, 0x37, 0xf6, 0xbf, 0x0d, - 0x6e, 0x2c, 0x11, 0x2c, 0x74, 0xc1, 0xdf, 0x5a, 0x74, 0x82, 0x92, 0x86, 0xc0, 0xae, 0x6c, 0xd2, - 0x05, 0x4b, 0xe4, 0x18, 0x79, 0x2b, 0x9a, 0xf3, 0xf5, 0xdd, 0x9c, 0x5e, 0x8e, 0x51, 0xa8, 0x35, - 0xe4, 0x27, 0x70, 0x84, 0xa4, 0x72, 0x2a, 0x3c, 0x53, 0xab, 0xdb, 0xf7, 0x50, 0xeb, 0xfc, 0xb0, - 0xd4, 0xf9, 0x4f, 0x2d, 0x80, 0xc5, 0xc6, 0x08, 0x01, 0x2b, 0xa3, 0x13, 0xd4, 0x7f, 0xca, 0x0d, - 0xb5, 0x4d, 0xb6, 0xc0, 0x55, 0xbf, 0x22, 0xa7, 0x11, 0xea, 0x5d, 0xba, 0xe1, 0xc2, 0x41, 0x9a, - 0x60, 0x4e, 0x93, 0x58, 0xd7, 0x77, 0x43, 0x65, 0x92, 0x6f, 0xa0, 0xc9, 0x51, 0xb0, 0x29, 0x8f, - 0xb0, 0x3f, 0x43, 0x2e, 0x12, 0x96, 0x79, 0x96, 0x0e, 0xaf, 0x55, 0xfe, 0xf3, 0xc2, 0x4d, 0xbe, - 0x00, 0x18, 0x62, 0x86, 0x5c, 0x9f, 0xbb, 0x67, 0x6f, 0x1b, 0x6d, 0x33, 0x5c, 0xf2, 0x90, 0x5d, - 0x20, 0x11, 0x47, 0x6d, 0xf7, 0x65, 0x32, 0x41, 0x21, 0xe9, 0x24, 0xf7, 0x1c, 0x9d, 0xb7, 0x5e, - 0x45, 0xce, 0xaa, 0x80, 0x4a, 0x8f, 0x31, 0xc5, 0x6b, 0xe9, 0xb5, 0x22, 0xbd, 0x8a, 0x2c, 0xd2, - 0xfb, 0xd0, 0x58, 0xea, 0xba, 0x57, 0xdf, 0x36, 0xdb, 0x8d, 0xfd, 0x1f, 0x1e, 0xd2, 0xc8, 0xe0, - 0xe7, 0x85, 0xfe, 0x28, 0x93, 0x7c, 0x1e, 0x2e, 0x13, 0xc9, 0x29, 0x38, 0x29, 0x1d, 0x60, 0x2a, - 0x3c, 0x57, 0xb3, 0x0f, 0x1e, 0xc4, 0xfe, 0x4b, 0x4b, 0x0b, 0x6c, 0xc9, 0xf1, 0x7f, 0x84, 0xe6, - 0xf5, 0x92, 0xaa, 0x03, 0x63, 0x9c, 0x97, 0x2d, 0x53, 0x26, 0xd9, 0x04, 0x7b, 0x46, 0xd3, 0x69, - 0xd5, 0xad, 0x62, 0xd1, 0x5d, 0x39, 0x30, 0xfc, 0xef, 0xa1, 0xb1, 0x84, 0x7d, 0x90, 0xf4, 0x8d, - 0x01, 0x96, 0x1a, 0x3d, 0x72, 0x04, 0xce, 0x08, 0x69, 0x2a, 0x47, 0xe5, 0xe8, 0xef, 0xde, 0x6f, - 0x64, 0x83, 0xdf, 0xb5, 0x28, 0x2c, 0xc5, 0xfe, 0x33, 0x03, 0x9c, 0xc2, 0x45, 0x7c, 0xa8, 0x1f, - 0x26, 0x42, 0x31, 0x62, 0xcd, 0xac, 0x87, 0x57, 0x6b, 0xf2, 0x15, 0xac, 0x9e, 0x22, 0x4f, 0x58, - 0xdc, 0xc3, 0x88, 0x65, 0xb1, 0xd0, 0x1b, 0xb3, 0xc3, 0x77, 0x9d, 0x64, 0x07, 0x9a, 0xbf, 0xd1, - 0x24, 0x9d, 0x72, 0x3c, 0x1b, 0x71, 0x14, 0x23, 0x96, 0x16, 0x23, 0x69, 0x87, 0xef, 0xf9, 0xc9, - 0x1e, 0x6c, 0xfc, 0x91, 0x25, 0x32, 0xa1, 0xe9, 0x21, 0xa6, 0x74, 0x5e, 0x71, 0x2d, 0x9d, 0x7e, - 0x53, 0xc8, 0x7f, 0x6e, 0x80, 0x53, 0xdc, 0x1b, 0x75, 0x3e, 0xea, 0xe6, 0x54, 0x37, 0xa4, 0x58, - 0x10, 0x0f, 0x6a, 0x34, 0x8e, 0x39, 0x0a, 0x51, 0x9e, 0x5b, 0xb5, 0x24, 0xbf, 0x82, 0x9d, 0x33, - 0x2e, 0xd5, 0x05, 0x35, 0xef, 0x79, 0x56, 0xba, 0x50, 0x70, 0xca, 0xb8, 0x0c, 0x0b, 0xad, 0x1f, - 0x80, 0xa5, 0x96, 0x37, 0xde, 0x4e, 0x02, 0x96, 0x4a, 0x2a, 0x8f, 0x45, 0xdb, 0xfb, 0xaf, 0x4d, - 0x30, 0x7b, 0x87, 0x7f, 0x92, 0x73, 0xb0, 0x43, 0xa4, 0xf1, 0x9c, 0x6c, 0x7d, 0xa0, 0xac, 0x7e, - 0xdf, 0xfc, 0x5b, 0xa3, 0xad, 0xf5, 0xff, 0x5f, 0xbe, 0x7a, 0xb2, 0xd2, 0x68, 0x39, 0x1d, 0xae, - 0x58, 0x5d, 0x63, 0x87, 0xfc, 0x0b, 0xf5, 0xde, 0x68, 0x2a, 0x63, 0x76, 0x99, 0x3d, 0x0a, 0xbd, - 0xa9, 0xd1, 0x9f, 0xb6, 0xdc, 0x8e, 0x28, 0x71, 0x8a, 0x7e, 0x71, 0x35, 0x17, 0x8f, 0x61, 0x13, - 0xcd, 0xfe, 0xa4, 0x55, 0xeb, 0x14, 0xf3, 0xd6, 0x35, 0x76, 0xda, 0x06, 0x41, 0x58, 0x3d, 0x46, - 0xb9, 0xf4, 0x98, 0xdf, 0x5e, 0xe2, 0xcb, 0x3b, 0xdb, 0xd5, 0xda, 0xd0, 0x75, 0x56, 0x49, 0xa3, - 0x33, 0x54, 0x6f, 0x62, 0x41, 0x65, 0xb0, 0xf6, 0x0f, 0x95, 0xd1, 0xe8, 0x63, 0x16, 0xfa, 0x5c, - 0x17, 0xda, 0x20, 0xeb, 0x9d, 0x4b, 0x85, 0x5e, 0x2a, 0xb7, 0x67, 0xfc, 0x62, 0x5f, 0x98, 0x22, - 0x1e, 0x0f, 0x1c, 0xfd, 0xe5, 0xfa, 0xee, 0x6d, 0x00, 0x00, 0x00, 0xff, 0xff, 0x59, 0x57, 0x6a, - 0x19, 0xfb, 0x06, 0x00, 0x00, +func init() { proto.RegisterFile("sdk.proto", fileDescriptor_sdk_1ced06a751c91178) } + +var fileDescriptor_sdk_1ced06a751c91178 = []byte{ + // 789 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x55, 0xef, 0x6e, 0xe3, 0x44, + 0x10, 0x97, 0x1b, 0xdb, 0x4d, 0xc6, 0x94, 0xa6, 0xdb, 0x20, 0xf9, 0xac, 0x8a, 0x2b, 0x16, 0x42, + 0x21, 0xe2, 0xec, 0x53, 0xf8, 0x72, 0x44, 0x02, 0xf1, 0xa7, 0xe5, 0x40, 0xc7, 0x89, 0xca, 0x39, + 0x15, 0xe9, 0x84, 0x14, 0x6d, 0xec, 0x51, 0x62, 0xe2, 0x78, 0xad, 0xdd, 0x4d, 0x4e, 0xf9, 0xca, + 0x2b, 0xf0, 0x10, 0xf0, 0x05, 0x5e, 0x83, 0x07, 0xe0, 0x15, 0x78, 0x08, 0x3e, 0xa2, 0x5d, 0xdb, + 0x75, 0x38, 0x7a, 0xd7, 0x54, 0xbd, 0x4f, 0x99, 0x9d, 0x99, 0xdf, 0xef, 0xe7, 0xcc, 0xce, 0xcc, + 0x42, 0x47, 0x24, 0x8b, 0xa0, 0xe0, 0x4c, 0x32, 0xf2, 0x8e, 0x90, 0x74, 0x9a, 0x61, 0x40, 0x67, + 0x2c, 0x47, 0x11, 0x24, 0xb8, 0x0e, 0x44, 0xb2, 0xf0, 0x4e, 0x66, 0x8c, 0xcd, 0x32, 0x0c, 0x69, + 0x91, 0x86, 0x34, 0xcf, 0x99, 0xa4, 0x32, 0x65, 0xb9, 0x28, 0x41, 0xfe, 0x3e, 0x58, 0xe7, 0xcb, + 0x42, 0x6e, 0xfc, 0x21, 0xb4, 0x9f, 0xe0, 0xe6, 0x92, 0x66, 0x2b, 0x24, 0x5d, 0x68, 0x2d, 0x70, + 0xe3, 0x1a, 0xa7, 0x46, 0xbf, 0x13, 0x29, 0x93, 0xf4, 0xc0, 0x5a, 0xab, 0x90, 0xbb, 0xa7, 0x7d, + 0xe5, 0xc1, 0xff, 0xa3, 0x03, 0xf0, 0x98, 0x2e, 0x71, 0x8c, 0x7c, 0x8d, 0x9c, 0x3c, 0x05, 0x87, + 0x4d, 0x7f, 0xc2, 0x58, 0x4e, 0x96, 0x28, 0xa9, 0x86, 0x3b, 0xc3, 0x8f, 0x82, 0x6b, 0x3f, 0x2b, + 0x68, 0x70, 0xc1, 0xf7, 0x1a, 0xf4, 0x14, 0x25, 0x8d, 0x80, 0x5d, 0xd9, 0x64, 0x04, 0xa6, 0x28, + 0x30, 0xd6, 0x92, 0xce, 0xf0, 0x83, 0x9b, 0x79, 0xc6, 0x05, 0xc6, 0x91, 0xc6, 0x90, 0xcf, 0xc1, + 0x16, 0x92, 0xca, 0x95, 0x70, 0x5b, 0x1a, 0xdd, 0xdf, 0x01, 0xad, 0xf3, 0xa3, 0x0a, 0xe7, 0xfd, + 0x6a, 0x02, 0x34, 0x1f, 0x46, 0x08, 0x98, 0x39, 0x5d, 0x62, 0x55, 0x13, 0x6d, 0x93, 0x13, 0xe8, + 0xa8, 0x5f, 0x51, 0xd0, 0xb8, 0x2e, 0x4c, 0xe3, 0x50, 0x45, 0x5c, 0xa5, 0x89, 0xd6, 0xef, 0x44, + 0xca, 0x24, 0x1f, 0x42, 0x97, 0xa3, 0x60, 0x2b, 0x1e, 0xe3, 0x64, 0x8d, 0x5c, 0xa4, 0x2c, 0x77, + 0x4d, 0x1d, 0x3e, 0xac, 0xfd, 0x97, 0xa5, 0x9b, 0xbc, 0x0b, 0x30, 0xc3, 0x1c, 0xb9, 0xbe, 0x2b, + 0xd7, 0x3a, 0x35, 0xfa, 0xad, 0x68, 0xcb, 0x43, 0x1e, 0x00, 0x89, 0x39, 0x6a, 0x7b, 0x22, 0xd3, + 0x25, 0x0a, 0x49, 0x97, 0x85, 0x6b, 0xeb, 0xbc, 0xa3, 0x3a, 0xf2, 0xac, 0x0e, 0xa8, 0xf4, 0x04, + 0x33, 0x7c, 0x29, 0x7d, 0xbf, 0x4c, 0xaf, 0x23, 0x4d, 0xfa, 0x04, 0x9c, 0xad, 0x4e, 0x71, 0xdb, + 0xa7, 0xad, 0xbe, 0x33, 0xfc, 0xf4, 0x36, 0x17, 0x19, 0x7c, 0xd1, 0xe0, 0xcf, 0x73, 0xc9, 0x37, + 0xd1, 0x36, 0x23, 0xb9, 0x00, 0x3b, 0xa3, 0x53, 0xcc, 0x84, 0xdb, 0xd1, 0xdc, 0x8f, 0x6e, 0xc5, + 0xfd, 0x9d, 0x86, 0x96, 0xb4, 0x15, 0x8f, 0xf7, 0x19, 0x74, 0x5f, 0x96, 0xdc, 0xb5, 0x8d, 0x47, + 0x7b, 0x8f, 0x0c, 0xef, 0x13, 0x70, 0xb6, 0x68, 0x6f, 0x05, 0xfd, 0xc7, 0x00, 0x53, 0xb5, 0x1e, + 0x39, 0x07, 0x7b, 0x8e, 0x34, 0x93, 0xf3, 0xaa, 0xf5, 0x1f, 0xec, 0xd6, 0xb2, 0xc1, 0x37, 0x1a, + 0x14, 0x55, 0x60, 0xef, 0x37, 0x03, 0xec, 0xd2, 0x45, 0x3c, 0x68, 0x9f, 0xa5, 0x42, 0x71, 0x24, + 0x9a, 0xb3, 0x1d, 0x5d, 0x9d, 0xc9, 0xfb, 0x70, 0x70, 0x81, 0x3c, 0x65, 0xc9, 0x18, 0x63, 0x96, + 0x27, 0x42, 0x7f, 0x98, 0x15, 0xfd, 0xd7, 0x49, 0x06, 0xd0, 0xfd, 0x9a, 0xa6, 0xd9, 0x8a, 0xe3, + 0xb3, 0x39, 0x47, 0x31, 0x67, 0x59, 0xd9, 0x92, 0x56, 0xf4, 0x3f, 0x3f, 0x79, 0x08, 0xc7, 0xdf, + 0xe6, 0xa9, 0x4c, 0x69, 0x76, 0x86, 0x19, 0xdd, 0xd4, 0xbc, 0xa6, 0x4e, 0xbf, 0x2e, 0xe4, 0xfd, + 0x6e, 0x80, 0x5d, 0xce, 0x8d, 0xaa, 0x8f, 0x9a, 0x9c, 0x7a, 0x42, 0xca, 0x03, 0x71, 0x61, 0x9f, + 0x26, 0x09, 0x47, 0x21, 0xaa, 0xba, 0xd5, 0x47, 0xf2, 0x15, 0x58, 0x05, 0xe3, 0x52, 0x0d, 0x68, + 0x6b, 0xc7, 0x5a, 0x69, 0xa1, 0xe0, 0x82, 0x71, 0x19, 0x95, 0x58, 0x2f, 0x00, 0x53, 0x1d, 0xaf, + 0x9d, 0x4e, 0x02, 0xa6, 0x4a, 0xaa, 0xca, 0xa2, 0xed, 0xe1, 0x9f, 0x16, 0xb4, 0xc6, 0x67, 0x4f, + 0xc8, 0x25, 0x58, 0x11, 0xd2, 0x64, 0x43, 0x4e, 0x5e, 0x21, 0xab, 0x77, 0xa2, 0xf7, 0xda, 0xa8, + 0x7f, 0xf4, 0xf3, 0x5f, 0x7f, 0xff, 0xb2, 0xe7, 0xf8, 0x76, 0xc8, 0x15, 0xd7, 0xc8, 0x18, 0x90, + 0x1f, 0xa1, 0x3d, 0x9e, 0xaf, 0x64, 0xc2, 0x5e, 0xe4, 0x77, 0xa2, 0xee, 0x69, 0xea, 0xb7, 0xfd, + 0x4e, 0x28, 0x2a, 0x3a, 0xc5, 0xfe, 0xfc, 0xaa, 0x2f, 0xee, 0xc2, 0x4d, 0x34, 0xf7, 0x5b, 0xfe, + 0x7e, 0x58, 0xf6, 0xdb, 0xc8, 0x18, 0xf4, 0x0d, 0x82, 0x70, 0xf0, 0x18, 0xe5, 0xd6, 0x32, 0x7f, + 0xbd, 0xc4, 0x7b, 0x37, 0x5e, 0x97, 0x7f, 0xac, 0x75, 0x0e, 0x88, 0x13, 0xce, 0xd4, 0x4e, 0x2c, + 0x59, 0x19, 0x1c, 0xfe, 0x40, 0x65, 0x3c, 0x7f, 0x93, 0x42, 0xf7, 0xb4, 0xd0, 0x31, 0x39, 0x0a, + 0x5f, 0x28, 0xea, 0x2d, 0xb9, 0x87, 0xea, 0x7f, 0xb5, 0xc7, 0x28, 0xf5, 0x68, 0x93, 0xfb, 0xaf, + 0xe0, 0xaa, 0xdf, 0xbd, 0x1b, 0x0a, 0xe7, 0x69, 0x9d, 0x9e, 0x77, 0x18, 0xaa, 0xe7, 0x2d, 0xa1, + 0x92, 0x86, 0x7a, 0xf9, 0xa8, 0xab, 0x61, 0x70, 0x30, 0x46, 0xd9, 0x6c, 0xa0, 0xbb, 0x6a, 0xdd, + 0xd7, 0x5a, 0xf7, 0xbc, 0x5e, 0xa3, 0xd5, 0xec, 0xcf, 0x91, 0x31, 0xf8, 0xd2, 0x7a, 0xde, 0x12, + 0xc9, 0x62, 0x6a, 0xeb, 0x57, 0xfc, 0xe3, 0x7f, 0x03, 0x00, 0x00, 0xff, 0xff, 0x96, 0xf4, 0x2d, + 0x3f, 0x07, 0x08, 0x00, 0x00, } diff --git a/pkg/sdk/sdk.pb.gw.go b/pkg/sdk/sdk.pb.gw.go index f20d3e8c25..465bbbf4af 100644 --- a/pkg/sdk/sdk.pb.gw.go +++ b/pkg/sdk/sdk.pb.gw.go @@ -136,6 +136,32 @@ func request_SDK_WatchGameServer_0(ctx context.Context, marshaler runtime.Marsha } +func request_SDK_SetLabel_0(ctx context.Context, marshaler runtime.Marshaler, client SDKClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq KeyValue + var metadata runtime.ServerMetadata + + if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && err != io.EOF { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + + msg, err := client.SetLabel(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err + +} + +func request_SDK_SetAnnotation_0(ctx context.Context, marshaler runtime.Marshaler, client SDKClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq KeyValue + var metadata runtime.ServerMetadata + + if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && err != io.EOF { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + + msg, err := client.SetAnnotation(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err + +} + // RegisterSDKHandlerFromEndpoint is same as RegisterSDKHandler but // automatically dials to "endpoint" and closes the connection when "ctx" gets done. func RegisterSDKHandlerFromEndpoint(ctx context.Context, mux *runtime.ServeMux, endpoint string, opts []grpc.DialOption) (err error) { @@ -319,6 +345,64 @@ func RegisterSDKHandlerClient(ctx context.Context, mux *runtime.ServeMux, client }) + mux.Handle("PUT", pattern_SDK_SetLabel_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + if cn, ok := w.(http.CloseNotifier); ok { + go func(done <-chan struct{}, closed <-chan bool) { + select { + case <-done: + case <-closed: + cancel() + } + }(ctx.Done(), cn.CloseNotify()) + } + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + rctx, err := runtime.AnnotateContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := request_SDK_SetLabel_0(rctx, inboundMarshaler, client, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_SDK_SetLabel_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("PUT", pattern_SDK_SetAnnotation_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + if cn, ok := w.(http.CloseNotifier); ok { + go func(done <-chan struct{}, closed <-chan bool) { + select { + case <-done: + case <-closed: + cancel() + } + }(ctx.Done(), cn.CloseNotify()) + } + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + rctx, err := runtime.AnnotateContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := request_SDK_SetAnnotation_0(rctx, inboundMarshaler, client, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_SDK_SetAnnotation_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + return nil } @@ -332,6 +416,10 @@ var ( pattern_SDK_GetGameServer_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0}, []string{"gameserver"}, "")) pattern_SDK_WatchGameServer_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1}, []string{"watch", "gameserver"}, "")) + + pattern_SDK_SetLabel_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1}, []string{"metadata", "label"}, "")) + + pattern_SDK_SetAnnotation_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1}, []string{"metadata", "annotation"}, "")) ) var ( @@ -344,4 +432,8 @@ var ( forward_SDK_GetGameServer_0 = runtime.ForwardResponseMessage forward_SDK_WatchGameServer_0 = runtime.ForwardResponseStream + + forward_SDK_SetLabel_0 = runtime.ForwardResponseMessage + + forward_SDK_SetAnnotation_0 = runtime.ForwardResponseMessage ) diff --git a/sdk.proto b/sdk.proto index ee08a47723..f4a803c5be 100644 --- a/sdk.proto +++ b/sdk.proto @@ -54,11 +54,34 @@ service SDK { get: "/watch/gameserver" }; } + + // Apply a Label to the backing GameServer metadata + rpc SetLabel(KeyValue) returns (Empty) { + option (google.api.http) = { + put: "/metadata/label" + body: "*" + }; + } + + // Apply a Annotation to the backing GameServer metadata + rpc SetAnnotation(KeyValue) returns (Empty) { + option (google.api.http) = { + put: "/metadata/annotation" + body: "*" + }; + } } +// I am Empty message Empty { } +// Key, Value entry +message KeyValue { + string key = 1; + string value = 2; +} + // A GameServer Custom Resource Definition object // We will only export those resources that make the most // sense. Can always expand to more as needed. diff --git a/sdk.swagger.json b/sdk.swagger.json index db50c77acd..ca89218b44 100644 --- a/sdk.swagger.json +++ b/sdk.swagger.json @@ -59,6 +59,60 @@ ] } }, + "/metadata/annotation": { + "put": { + "summary": "Apply a Annotation to the backing GameServer metadata", + "operationId": "SetAnnotation", + "responses": { + "200": { + "description": "", + "schema": { + "$ref": "#/definitions/sdkEmpty" + } + } + }, + "parameters": [ + { + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/sdkKeyValue" + } + } + ], + "tags": [ + "SDK" + ] + } + }, + "/metadata/label": { + "put": { + "summary": "Apply a Label to the backing GameServer metadata", + "operationId": "SetLabel", + "responses": { + "200": { + "description": "", + "schema": { + "$ref": "#/definitions/sdkEmpty" + } + } + }, + "parameters": [ + { + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/sdkKeyValue" + } + } + ], + "tags": [ + "SDK" + ] + } + }, "/ready": { "post": { "summary": "Call when the GameServer is ready", @@ -235,7 +289,8 @@ } }, "sdkEmpty": { - "type": "object" + "type": "object", + "title": "I am Empty" }, "sdkGameServer": { "type": "object", @@ -251,6 +306,18 @@ } }, "description": "A GameServer Custom Resource Definition object\nWe will only export those resources that make the most\nsense. Can always expand to more as needed." + }, + "sdkKeyValue": { + "type": "object", + "properties": { + "key": { + "type": "string" + }, + "value": { + "type": "string" + } + }, + "title": "Key, Value entry" } } } diff --git a/sdks/README.md b/sdks/README.md index 1dd10f1497..94f9db4821 100644 --- a/sdks/README.md +++ b/sdks/README.md @@ -46,6 +46,24 @@ This tells Agones to shut down the currently running game server. The GameServer state will be set `Shutdown` and the backing Pod will be deleted, if they have not shut themselves down already. +### SetLabel(key, value) +⚠️⚠️⚠️ **`SetLabel` is currently a development feature and has not been released** ⚠️⚠️⚠️ + +This will set a [Label](https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/) value on the backing `GameServer` +record that is stored in Kubernetes. To maintain isolation, the `key` value is automatically prefixed with "stable.agones.dev/sdk-" + +> Note: There are limits on the characters that be used for label keys and values. Details are [here](https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/#syntax-and-character-set). + +This can be useful if you want to information from your running game server process to be observable or searchable through the Kubernetes API. + +### SetAnnotation(key, value) +⚠️⚠️⚠️ **`SetAnnotation` is currently a development feature and has not been released** ⚠️⚠️⚠️ + +This will set a [Annotation](https://kubernetes.io/docs/concepts/overview/working-with-objects/annotations/) value on the backing +`Gameserver` record that is stored in Kubernetes. To maintain isolation, the `key` value is automatically prefixed with "stable.agones.dev/sdk-" + +This can be useful if you want to information from your running game server process to be observable through the Kubernetes API. + ### GameServer() This returns most of the backing GameServer configuration and Status. This can be useful for instances where you may want to know Health check configuration, or the IP and Port @@ -63,7 +81,7 @@ and the [examples](../examples). ### WatchGameServer(function(gameserver){...}) -⚠️⚠️⚠️ **`WatchGameServer` is currently a development feature and has not been released** ⚠️⚠️⚠ +⚠️⚠️⚠️ **`WatchGameServer` is currently a development feature and has not been released** ⚠️⚠️⚠️ This executes the passed in callback with the current `GameServer` details whenever the underlying `GameServer` configuration is updated. This can be useful to track `GameServer > Status > State` changes, `metadata` changes, such as labels and annotations, and more. diff --git a/sdks/cpp/README.md b/sdks/cpp/README.md index 369dd7d299..1897545f18 100644 --- a/sdks/cpp/README.md +++ b/sdks/cpp/README.md @@ -50,14 +50,41 @@ if the function completed successfully. For more information you can also look at the [gRPC Status reference](https://grpc.io/grpc/cpp/classgrpc_1_1_status.html) - ```cpp grpc::Status status = sdk->Shutdown(); if (!status.ok()) { ... } ``` -For more information, you can also read the [SDK Overview](../), check out [sdk.h](sdk.h) and also look at the -[C++ example](../../examples/cpp-simple). +To [set a Label](../README.md#setlabelkey-value) on the backing `GameServer` call +`sdk->SetLabel(key, value)`. + +⚠️⚠️⚠️ **`SetLabel` is currently a development feature and has not been released** ⚠️⚠️⚠️ + +This will return a grpc::Status object, from which we can call `status.ok()` to determine +if the function completed successfully. + +For more information you can also look at the [gRPC Status reference](https://grpc.io/grpc/cpp/classgrpc_1_1_status.html) + +```cpp +grpc::Status status = sdk->SetLabel("test-label", "test-value"); +if (!status.ok()) { ... } +``` + +To [set an Annotation](../README.md#setannotationkey-value) on the backing `GameServer` call +`sdk->SetAnnotation(key, value)`. + +⚠️⚠️⚠️ **`SetAnnotation` is currently a development feature and has not been released** ⚠️⚠️⚠️ + +This will return a grpc::Status object, from which we can call `status.ok()` to determine +if the function completed successfully. + +For more information you can also look at the [gRPC Status reference](https://grpc.io/grpc/cpp/classgrpc_1_1_status.html) + +```cpp +status = sdk->SetAnnotation("test-annotation", "test value"); +if (!status.ok()) { ... } +``` + To get the details on the [backing `GameServer`](../README.md#gameserver) call `sdk->GameServer(&gameserver)`, passing in a `stable::agones::dev::sdk::GameServer*` to push the results of the `GameServer` configuration into. @@ -71,10 +98,7 @@ grpc::Status status = sdk->GameServer(&gameserver); if (!status.ok()) {...} ``` -For more information, you can also read the [SDK Overview](../), check out [sdk.h](sdk.h) and also look at the -[C++ example](../../examples/cpp-simple). - -To get updates on the [backing `GameServer`](../README.md#gameserver) as they happen, +To get [updates on the backing `GameServer`](../README.md#watchgameserverfunctiongameserver) as they happen, call `sdk->WatchGameServer([](stable::agones::dev::sdk::GameServer gameserver){...})`. ⚠️⚠️⚠️ **`WatchGameServer` is currently a development feature and has not been released** ⚠️⚠️️⚠️ diff --git a/sdks/cpp/sdk.cc b/sdks/cpp/sdk.cc index 216c9cf6cd..bda1748ff0 100644 --- a/sdks/cpp/sdk.cc +++ b/sdks/cpp/sdk.cc @@ -79,4 +79,30 @@ namespace agones { return stub->Shutdown(context, request, &response); } + + grpc::Status SDK::SetLabel(std::string key, std::string value) { + grpc::ClientContext *context = new grpc::ClientContext(); + context->set_deadline(gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), gpr_time_from_seconds(30, GPR_TIMESPAN))); + + stable::agones::dev::sdk::KeyValue request; + request.set_key(key); + request.set_value(value); + + stable::agones::dev::sdk::Empty response; + + return stub->SetLabel(context, request, &response); + } + + grpc::Status SDK::SetAnnotation(std::string key, std::string value) { + grpc::ClientContext *context = new grpc::ClientContext(); + context->set_deadline(gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), gpr_time_from_seconds(30, GPR_TIMESPAN))); + + stable::agones::dev::sdk::KeyValue request; + request.set_key(key); + request.set_value(value); + + stable::agones::dev::sdk::Empty response; + + return stub->SetAnnotation(context, request, &response); + } } \ No newline at end of file diff --git a/sdks/cpp/sdk.grpc.pb.cc b/sdks/cpp/sdk.grpc.pb.cc index 29970cbf9b..0f0fc9f701 100644 --- a/sdks/cpp/sdk.grpc.pb.cc +++ b/sdks/cpp/sdk.grpc.pb.cc @@ -39,6 +39,8 @@ static const char* SDK_method_names[] = { "/stable.agones.dev.sdk.SDK/Health", "/stable.agones.dev.sdk.SDK/GetGameServer", "/stable.agones.dev.sdk.SDK/WatchGameServer", + "/stable.agones.dev.sdk.SDK/SetLabel", + "/stable.agones.dev.sdk.SDK/SetAnnotation", }; std::unique_ptr< SDK::Stub> SDK::NewStub(const std::shared_ptr< ::grpc::ChannelInterface>& channel, const ::grpc::StubOptions& options) { @@ -53,6 +55,8 @@ SDK::Stub::Stub(const std::shared_ptr< ::grpc::ChannelInterface>& channel) , rpcmethod_Health_(SDK_method_names[2], ::grpc::internal::RpcMethod::CLIENT_STREAMING, channel) , rpcmethod_GetGameServer_(SDK_method_names[3], ::grpc::internal::RpcMethod::NORMAL_RPC, channel) , rpcmethod_WatchGameServer_(SDK_method_names[4], ::grpc::internal::RpcMethod::SERVER_STREAMING, channel) + , rpcmethod_SetLabel_(SDK_method_names[5], ::grpc::internal::RpcMethod::NORMAL_RPC, channel) + , rpcmethod_SetAnnotation_(SDK_method_names[6], ::grpc::internal::RpcMethod::NORMAL_RPC, channel) {} ::grpc::Status SDK::Stub::Ready(::grpc::ClientContext* context, const ::stable::agones::dev::sdk::Empty& request, ::stable::agones::dev::sdk::Empty* response) { @@ -115,6 +119,30 @@ ::grpc::ClientAsyncReader< ::stable::agones::dev::sdk::GameServer>* SDK::Stub::P return ::grpc::internal::ClientAsyncReaderFactory< ::stable::agones::dev::sdk::GameServer>::Create(channel_.get(), cq, rpcmethod_WatchGameServer_, context, request, false, nullptr); } +::grpc::Status SDK::Stub::SetLabel(::grpc::ClientContext* context, const ::stable::agones::dev::sdk::KeyValue& request, ::stable::agones::dev::sdk::Empty* response) { + return ::grpc::internal::BlockingUnaryCall(channel_.get(), rpcmethod_SetLabel_, context, request, response); +} + +::grpc::ClientAsyncResponseReader< ::stable::agones::dev::sdk::Empty>* SDK::Stub::AsyncSetLabelRaw(::grpc::ClientContext* context, const ::stable::agones::dev::sdk::KeyValue& request, ::grpc::CompletionQueue* cq) { + return ::grpc::internal::ClientAsyncResponseReaderFactory< ::stable::agones::dev::sdk::Empty>::Create(channel_.get(), cq, rpcmethod_SetLabel_, context, request, true); +} + +::grpc::ClientAsyncResponseReader< ::stable::agones::dev::sdk::Empty>* SDK::Stub::PrepareAsyncSetLabelRaw(::grpc::ClientContext* context, const ::stable::agones::dev::sdk::KeyValue& request, ::grpc::CompletionQueue* cq) { + return ::grpc::internal::ClientAsyncResponseReaderFactory< ::stable::agones::dev::sdk::Empty>::Create(channel_.get(), cq, rpcmethod_SetLabel_, context, request, false); +} + +::grpc::Status SDK::Stub::SetAnnotation(::grpc::ClientContext* context, const ::stable::agones::dev::sdk::KeyValue& request, ::stable::agones::dev::sdk::Empty* response) { + return ::grpc::internal::BlockingUnaryCall(channel_.get(), rpcmethod_SetAnnotation_, context, request, response); +} + +::grpc::ClientAsyncResponseReader< ::stable::agones::dev::sdk::Empty>* SDK::Stub::AsyncSetAnnotationRaw(::grpc::ClientContext* context, const ::stable::agones::dev::sdk::KeyValue& request, ::grpc::CompletionQueue* cq) { + return ::grpc::internal::ClientAsyncResponseReaderFactory< ::stable::agones::dev::sdk::Empty>::Create(channel_.get(), cq, rpcmethod_SetAnnotation_, context, request, true); +} + +::grpc::ClientAsyncResponseReader< ::stable::agones::dev::sdk::Empty>* SDK::Stub::PrepareAsyncSetAnnotationRaw(::grpc::ClientContext* context, const ::stable::agones::dev::sdk::KeyValue& request, ::grpc::CompletionQueue* cq) { + return ::grpc::internal::ClientAsyncResponseReaderFactory< ::stable::agones::dev::sdk::Empty>::Create(channel_.get(), cq, rpcmethod_SetAnnotation_, context, request, false); +} + SDK::Service::Service() { AddMethod(new ::grpc::internal::RpcServiceMethod( SDK_method_names[0], @@ -141,6 +169,16 @@ SDK::Service::Service() { ::grpc::internal::RpcMethod::SERVER_STREAMING, new ::grpc::internal::ServerStreamingHandler< SDK::Service, ::stable::agones::dev::sdk::Empty, ::stable::agones::dev::sdk::GameServer>( std::mem_fn(&SDK::Service::WatchGameServer), this))); + AddMethod(new ::grpc::internal::RpcServiceMethod( + SDK_method_names[5], + ::grpc::internal::RpcMethod::NORMAL_RPC, + new ::grpc::internal::RpcMethodHandler< SDK::Service, ::stable::agones::dev::sdk::KeyValue, ::stable::agones::dev::sdk::Empty>( + std::mem_fn(&SDK::Service::SetLabel), this))); + AddMethod(new ::grpc::internal::RpcServiceMethod( + SDK_method_names[6], + ::grpc::internal::RpcMethod::NORMAL_RPC, + new ::grpc::internal::RpcMethodHandler< SDK::Service, ::stable::agones::dev::sdk::KeyValue, ::stable::agones::dev::sdk::Empty>( + std::mem_fn(&SDK::Service::SetAnnotation), this))); } SDK::Service::~Service() { @@ -181,6 +219,20 @@ ::grpc::Status SDK::Service::WatchGameServer(::grpc::ServerContext* context, con return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); } +::grpc::Status SDK::Service::SetLabel(::grpc::ServerContext* context, const ::stable::agones::dev::sdk::KeyValue* request, ::stable::agones::dev::sdk::Empty* response) { + (void) context; + (void) request; + (void) response; + return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); +} + +::grpc::Status SDK::Service::SetAnnotation(::grpc::ServerContext* context, const ::stable::agones::dev::sdk::KeyValue* request, ::stable::agones::dev::sdk::Empty* response) { + (void) context; + (void) request; + (void) response; + return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); +} + } // namespace stable } // namespace agones diff --git a/sdks/cpp/sdk.grpc.pb.h b/sdks/cpp/sdk.grpc.pb.h index b128ca4b5e..37aea54b64 100644 --- a/sdks/cpp/sdk.grpc.pb.h +++ b/sdks/cpp/sdk.grpc.pb.h @@ -96,6 +96,22 @@ class SDK final { std::unique_ptr< ::grpc::ClientAsyncReaderInterface< ::stable::agones::dev::sdk::GameServer>> PrepareAsyncWatchGameServer(::grpc::ClientContext* context, const ::stable::agones::dev::sdk::Empty& request, ::grpc::CompletionQueue* cq) { return std::unique_ptr< ::grpc::ClientAsyncReaderInterface< ::stable::agones::dev::sdk::GameServer>>(PrepareAsyncWatchGameServerRaw(context, request, cq)); } + // Apply a Label to the backing GameServer metadata + virtual ::grpc::Status SetLabel(::grpc::ClientContext* context, const ::stable::agones::dev::sdk::KeyValue& request, ::stable::agones::dev::sdk::Empty* response) = 0; + std::unique_ptr< ::grpc::ClientAsyncResponseReaderInterface< ::stable::agones::dev::sdk::Empty>> AsyncSetLabel(::grpc::ClientContext* context, const ::stable::agones::dev::sdk::KeyValue& request, ::grpc::CompletionQueue* cq) { + return std::unique_ptr< ::grpc::ClientAsyncResponseReaderInterface< ::stable::agones::dev::sdk::Empty>>(AsyncSetLabelRaw(context, request, cq)); + } + std::unique_ptr< ::grpc::ClientAsyncResponseReaderInterface< ::stable::agones::dev::sdk::Empty>> PrepareAsyncSetLabel(::grpc::ClientContext* context, const ::stable::agones::dev::sdk::KeyValue& request, ::grpc::CompletionQueue* cq) { + return std::unique_ptr< ::grpc::ClientAsyncResponseReaderInterface< ::stable::agones::dev::sdk::Empty>>(PrepareAsyncSetLabelRaw(context, request, cq)); + } + // Apply a Annotation to the backing GameServer metadata + virtual ::grpc::Status SetAnnotation(::grpc::ClientContext* context, const ::stable::agones::dev::sdk::KeyValue& request, ::stable::agones::dev::sdk::Empty* response) = 0; + std::unique_ptr< ::grpc::ClientAsyncResponseReaderInterface< ::stable::agones::dev::sdk::Empty>> AsyncSetAnnotation(::grpc::ClientContext* context, const ::stable::agones::dev::sdk::KeyValue& request, ::grpc::CompletionQueue* cq) { + return std::unique_ptr< ::grpc::ClientAsyncResponseReaderInterface< ::stable::agones::dev::sdk::Empty>>(AsyncSetAnnotationRaw(context, request, cq)); + } + std::unique_ptr< ::grpc::ClientAsyncResponseReaderInterface< ::stable::agones::dev::sdk::Empty>> PrepareAsyncSetAnnotation(::grpc::ClientContext* context, const ::stable::agones::dev::sdk::KeyValue& request, ::grpc::CompletionQueue* cq) { + return std::unique_ptr< ::grpc::ClientAsyncResponseReaderInterface< ::stable::agones::dev::sdk::Empty>>(PrepareAsyncSetAnnotationRaw(context, request, cq)); + } private: virtual ::grpc::ClientAsyncResponseReaderInterface< ::stable::agones::dev::sdk::Empty>* AsyncReadyRaw(::grpc::ClientContext* context, const ::stable::agones::dev::sdk::Empty& request, ::grpc::CompletionQueue* cq) = 0; virtual ::grpc::ClientAsyncResponseReaderInterface< ::stable::agones::dev::sdk::Empty>* PrepareAsyncReadyRaw(::grpc::ClientContext* context, const ::stable::agones::dev::sdk::Empty& request, ::grpc::CompletionQueue* cq) = 0; @@ -109,6 +125,10 @@ class SDK final { virtual ::grpc::ClientReaderInterface< ::stable::agones::dev::sdk::GameServer>* WatchGameServerRaw(::grpc::ClientContext* context, const ::stable::agones::dev::sdk::Empty& request) = 0; virtual ::grpc::ClientAsyncReaderInterface< ::stable::agones::dev::sdk::GameServer>* AsyncWatchGameServerRaw(::grpc::ClientContext* context, const ::stable::agones::dev::sdk::Empty& request, ::grpc::CompletionQueue* cq, void* tag) = 0; virtual ::grpc::ClientAsyncReaderInterface< ::stable::agones::dev::sdk::GameServer>* PrepareAsyncWatchGameServerRaw(::grpc::ClientContext* context, const ::stable::agones::dev::sdk::Empty& request, ::grpc::CompletionQueue* cq) = 0; + virtual ::grpc::ClientAsyncResponseReaderInterface< ::stable::agones::dev::sdk::Empty>* AsyncSetLabelRaw(::grpc::ClientContext* context, const ::stable::agones::dev::sdk::KeyValue& request, ::grpc::CompletionQueue* cq) = 0; + virtual ::grpc::ClientAsyncResponseReaderInterface< ::stable::agones::dev::sdk::Empty>* PrepareAsyncSetLabelRaw(::grpc::ClientContext* context, const ::stable::agones::dev::sdk::KeyValue& request, ::grpc::CompletionQueue* cq) = 0; + virtual ::grpc::ClientAsyncResponseReaderInterface< ::stable::agones::dev::sdk::Empty>* AsyncSetAnnotationRaw(::grpc::ClientContext* context, const ::stable::agones::dev::sdk::KeyValue& request, ::grpc::CompletionQueue* cq) = 0; + virtual ::grpc::ClientAsyncResponseReaderInterface< ::stable::agones::dev::sdk::Empty>* PrepareAsyncSetAnnotationRaw(::grpc::ClientContext* context, const ::stable::agones::dev::sdk::KeyValue& request, ::grpc::CompletionQueue* cq) = 0; }; class Stub final : public StubInterface { public: @@ -152,6 +172,20 @@ class SDK final { std::unique_ptr< ::grpc::ClientAsyncReader< ::stable::agones::dev::sdk::GameServer>> PrepareAsyncWatchGameServer(::grpc::ClientContext* context, const ::stable::agones::dev::sdk::Empty& request, ::grpc::CompletionQueue* cq) { return std::unique_ptr< ::grpc::ClientAsyncReader< ::stable::agones::dev::sdk::GameServer>>(PrepareAsyncWatchGameServerRaw(context, request, cq)); } + ::grpc::Status SetLabel(::grpc::ClientContext* context, const ::stable::agones::dev::sdk::KeyValue& request, ::stable::agones::dev::sdk::Empty* response) override; + std::unique_ptr< ::grpc::ClientAsyncResponseReader< ::stable::agones::dev::sdk::Empty>> AsyncSetLabel(::grpc::ClientContext* context, const ::stable::agones::dev::sdk::KeyValue& request, ::grpc::CompletionQueue* cq) { + return std::unique_ptr< ::grpc::ClientAsyncResponseReader< ::stable::agones::dev::sdk::Empty>>(AsyncSetLabelRaw(context, request, cq)); + } + std::unique_ptr< ::grpc::ClientAsyncResponseReader< ::stable::agones::dev::sdk::Empty>> PrepareAsyncSetLabel(::grpc::ClientContext* context, const ::stable::agones::dev::sdk::KeyValue& request, ::grpc::CompletionQueue* cq) { + return std::unique_ptr< ::grpc::ClientAsyncResponseReader< ::stable::agones::dev::sdk::Empty>>(PrepareAsyncSetLabelRaw(context, request, cq)); + } + ::grpc::Status SetAnnotation(::grpc::ClientContext* context, const ::stable::agones::dev::sdk::KeyValue& request, ::stable::agones::dev::sdk::Empty* response) override; + std::unique_ptr< ::grpc::ClientAsyncResponseReader< ::stable::agones::dev::sdk::Empty>> AsyncSetAnnotation(::grpc::ClientContext* context, const ::stable::agones::dev::sdk::KeyValue& request, ::grpc::CompletionQueue* cq) { + return std::unique_ptr< ::grpc::ClientAsyncResponseReader< ::stable::agones::dev::sdk::Empty>>(AsyncSetAnnotationRaw(context, request, cq)); + } + std::unique_ptr< ::grpc::ClientAsyncResponseReader< ::stable::agones::dev::sdk::Empty>> PrepareAsyncSetAnnotation(::grpc::ClientContext* context, const ::stable::agones::dev::sdk::KeyValue& request, ::grpc::CompletionQueue* cq) { + return std::unique_ptr< ::grpc::ClientAsyncResponseReader< ::stable::agones::dev::sdk::Empty>>(PrepareAsyncSetAnnotationRaw(context, request, cq)); + } private: std::shared_ptr< ::grpc::ChannelInterface> channel_; @@ -167,11 +201,17 @@ class SDK final { ::grpc::ClientReader< ::stable::agones::dev::sdk::GameServer>* WatchGameServerRaw(::grpc::ClientContext* context, const ::stable::agones::dev::sdk::Empty& request) override; ::grpc::ClientAsyncReader< ::stable::agones::dev::sdk::GameServer>* AsyncWatchGameServerRaw(::grpc::ClientContext* context, const ::stable::agones::dev::sdk::Empty& request, ::grpc::CompletionQueue* cq, void* tag) override; ::grpc::ClientAsyncReader< ::stable::agones::dev::sdk::GameServer>* PrepareAsyncWatchGameServerRaw(::grpc::ClientContext* context, const ::stable::agones::dev::sdk::Empty& request, ::grpc::CompletionQueue* cq) override; + ::grpc::ClientAsyncResponseReader< ::stable::agones::dev::sdk::Empty>* AsyncSetLabelRaw(::grpc::ClientContext* context, const ::stable::agones::dev::sdk::KeyValue& request, ::grpc::CompletionQueue* cq) override; + ::grpc::ClientAsyncResponseReader< ::stable::agones::dev::sdk::Empty>* PrepareAsyncSetLabelRaw(::grpc::ClientContext* context, const ::stable::agones::dev::sdk::KeyValue& request, ::grpc::CompletionQueue* cq) override; + ::grpc::ClientAsyncResponseReader< ::stable::agones::dev::sdk::Empty>* AsyncSetAnnotationRaw(::grpc::ClientContext* context, const ::stable::agones::dev::sdk::KeyValue& request, ::grpc::CompletionQueue* cq) override; + ::grpc::ClientAsyncResponseReader< ::stable::agones::dev::sdk::Empty>* PrepareAsyncSetAnnotationRaw(::grpc::ClientContext* context, const ::stable::agones::dev::sdk::KeyValue& request, ::grpc::CompletionQueue* cq) override; const ::grpc::internal::RpcMethod rpcmethod_Ready_; const ::grpc::internal::RpcMethod rpcmethod_Shutdown_; const ::grpc::internal::RpcMethod rpcmethod_Health_; const ::grpc::internal::RpcMethod rpcmethod_GetGameServer_; const ::grpc::internal::RpcMethod rpcmethod_WatchGameServer_; + const ::grpc::internal::RpcMethod rpcmethod_SetLabel_; + const ::grpc::internal::RpcMethod rpcmethod_SetAnnotation_; }; static std::unique_ptr NewStub(const std::shared_ptr< ::grpc::ChannelInterface>& channel, const ::grpc::StubOptions& options = ::grpc::StubOptions()); @@ -189,6 +229,10 @@ class SDK final { virtual ::grpc::Status GetGameServer(::grpc::ServerContext* context, const ::stable::agones::dev::sdk::Empty* request, ::stable::agones::dev::sdk::GameServer* response); // Send GameServer details whenever the GameServer is updated virtual ::grpc::Status WatchGameServer(::grpc::ServerContext* context, const ::stable::agones::dev::sdk::Empty* request, ::grpc::ServerWriter< ::stable::agones::dev::sdk::GameServer>* writer); + // Apply a Label to the backing GameServer metadata + virtual ::grpc::Status SetLabel(::grpc::ServerContext* context, const ::stable::agones::dev::sdk::KeyValue* request, ::stable::agones::dev::sdk::Empty* response); + // Apply a Annotation to the backing GameServer metadata + virtual ::grpc::Status SetAnnotation(::grpc::ServerContext* context, const ::stable::agones::dev::sdk::KeyValue* request, ::stable::agones::dev::sdk::Empty* response); }; template class WithAsyncMethod_Ready : public BaseClass { @@ -290,7 +334,47 @@ class SDK final { ::grpc::Service::RequestAsyncServerStreaming(4, context, request, writer, new_call_cq, notification_cq, tag); } }; - typedef WithAsyncMethod_Ready > > > > AsyncService; + template + class WithAsyncMethod_SetLabel : public BaseClass { + private: + void BaseClassMustBeDerivedFromService(const Service *service) {} + public: + WithAsyncMethod_SetLabel() { + ::grpc::Service::MarkMethodAsync(5); + } + ~WithAsyncMethod_SetLabel() override { + BaseClassMustBeDerivedFromService(this); + } + // disable synchronous version of this method + ::grpc::Status SetLabel(::grpc::ServerContext* context, const ::stable::agones::dev::sdk::KeyValue* request, ::stable::agones::dev::sdk::Empty* response) final override { + abort(); + return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); + } + void RequestSetLabel(::grpc::ServerContext* context, ::stable::agones::dev::sdk::KeyValue* request, ::grpc::ServerAsyncResponseWriter< ::stable::agones::dev::sdk::Empty>* response, ::grpc::CompletionQueue* new_call_cq, ::grpc::ServerCompletionQueue* notification_cq, void *tag) { + ::grpc::Service::RequestAsyncUnary(5, context, request, response, new_call_cq, notification_cq, tag); + } + }; + template + class WithAsyncMethod_SetAnnotation : public BaseClass { + private: + void BaseClassMustBeDerivedFromService(const Service *service) {} + public: + WithAsyncMethod_SetAnnotation() { + ::grpc::Service::MarkMethodAsync(6); + } + ~WithAsyncMethod_SetAnnotation() override { + BaseClassMustBeDerivedFromService(this); + } + // disable synchronous version of this method + ::grpc::Status SetAnnotation(::grpc::ServerContext* context, const ::stable::agones::dev::sdk::KeyValue* request, ::stable::agones::dev::sdk::Empty* response) final override { + abort(); + return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); + } + void RequestSetAnnotation(::grpc::ServerContext* context, ::stable::agones::dev::sdk::KeyValue* request, ::grpc::ServerAsyncResponseWriter< ::stable::agones::dev::sdk::Empty>* response, ::grpc::CompletionQueue* new_call_cq, ::grpc::ServerCompletionQueue* notification_cq, void *tag) { + ::grpc::Service::RequestAsyncUnary(6, context, request, response, new_call_cq, notification_cq, tag); + } + }; + typedef WithAsyncMethod_Ready > > > > > > AsyncService; template class WithGenericMethod_Ready : public BaseClass { private: @@ -377,6 +461,40 @@ class SDK final { } }; template + class WithGenericMethod_SetLabel : public BaseClass { + private: + void BaseClassMustBeDerivedFromService(const Service *service) {} + public: + WithGenericMethod_SetLabel() { + ::grpc::Service::MarkMethodGeneric(5); + } + ~WithGenericMethod_SetLabel() override { + BaseClassMustBeDerivedFromService(this); + } + // disable synchronous version of this method + ::grpc::Status SetLabel(::grpc::ServerContext* context, const ::stable::agones::dev::sdk::KeyValue* request, ::stable::agones::dev::sdk::Empty* response) final override { + abort(); + return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); + } + }; + template + class WithGenericMethod_SetAnnotation : public BaseClass { + private: + void BaseClassMustBeDerivedFromService(const Service *service) {} + public: + WithGenericMethod_SetAnnotation() { + ::grpc::Service::MarkMethodGeneric(6); + } + ~WithGenericMethod_SetAnnotation() override { + BaseClassMustBeDerivedFromService(this); + } + // disable synchronous version of this method + ::grpc::Status SetAnnotation(::grpc::ServerContext* context, const ::stable::agones::dev::sdk::KeyValue* request, ::stable::agones::dev::sdk::Empty* response) final override { + abort(); + return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); + } + }; + template class WithStreamedUnaryMethod_Ready : public BaseClass { private: void BaseClassMustBeDerivedFromService(const Service *service) {} @@ -436,7 +554,47 @@ class SDK final { // replace default version of method with streamed unary virtual ::grpc::Status StreamedGetGameServer(::grpc::ServerContext* context, ::grpc::ServerUnaryStreamer< ::stable::agones::dev::sdk::Empty,::stable::agones::dev::sdk::GameServer>* server_unary_streamer) = 0; }; - typedef WithStreamedUnaryMethod_Ready > > StreamedUnaryService; + template + class WithStreamedUnaryMethod_SetLabel : public BaseClass { + private: + void BaseClassMustBeDerivedFromService(const Service *service) {} + public: + WithStreamedUnaryMethod_SetLabel() { + ::grpc::Service::MarkMethodStreamed(5, + new ::grpc::internal::StreamedUnaryHandler< ::stable::agones::dev::sdk::KeyValue, ::stable::agones::dev::sdk::Empty>(std::bind(&WithStreamedUnaryMethod_SetLabel::StreamedSetLabel, this, std::placeholders::_1, std::placeholders::_2))); + } + ~WithStreamedUnaryMethod_SetLabel() override { + BaseClassMustBeDerivedFromService(this); + } + // disable regular version of this method + ::grpc::Status SetLabel(::grpc::ServerContext* context, const ::stable::agones::dev::sdk::KeyValue* request, ::stable::agones::dev::sdk::Empty* response) final override { + abort(); + return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); + } + // replace default version of method with streamed unary + virtual ::grpc::Status StreamedSetLabel(::grpc::ServerContext* context, ::grpc::ServerUnaryStreamer< ::stable::agones::dev::sdk::KeyValue,::stable::agones::dev::sdk::Empty>* server_unary_streamer) = 0; + }; + template + class WithStreamedUnaryMethod_SetAnnotation : public BaseClass { + private: + void BaseClassMustBeDerivedFromService(const Service *service) {} + public: + WithStreamedUnaryMethod_SetAnnotation() { + ::grpc::Service::MarkMethodStreamed(6, + new ::grpc::internal::StreamedUnaryHandler< ::stable::agones::dev::sdk::KeyValue, ::stable::agones::dev::sdk::Empty>(std::bind(&WithStreamedUnaryMethod_SetAnnotation::StreamedSetAnnotation, this, std::placeholders::_1, std::placeholders::_2))); + } + ~WithStreamedUnaryMethod_SetAnnotation() override { + BaseClassMustBeDerivedFromService(this); + } + // disable regular version of this method + ::grpc::Status SetAnnotation(::grpc::ServerContext* context, const ::stable::agones::dev::sdk::KeyValue* request, ::stable::agones::dev::sdk::Empty* response) final override { + abort(); + return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); + } + // replace default version of method with streamed unary + virtual ::grpc::Status StreamedSetAnnotation(::grpc::ServerContext* context, ::grpc::ServerUnaryStreamer< ::stable::agones::dev::sdk::KeyValue,::stable::agones::dev::sdk::Empty>* server_unary_streamer) = 0; + }; + typedef WithStreamedUnaryMethod_Ready > > > > StreamedUnaryService; template class WithSplitStreamingMethod_WatchGameServer : public BaseClass { private: @@ -458,7 +616,7 @@ class SDK final { virtual ::grpc::Status StreamedWatchGameServer(::grpc::ServerContext* context, ::grpc::ServerSplitStreamer< ::stable::agones::dev::sdk::Empty,::stable::agones::dev::sdk::GameServer>* server_split_streamer) = 0; }; typedef WithSplitStreamingMethod_WatchGameServer SplitStreamedService; - typedef WithStreamedUnaryMethod_Ready > > > StreamedService; + typedef WithStreamedUnaryMethod_Ready > > > > > StreamedService; }; } // namespace sdk diff --git a/sdks/cpp/sdk.h b/sdks/cpp/sdk.h index 7a5b522c40..dcfdf24175 100644 --- a/sdks/cpp/sdk.h +++ b/sdks/cpp/sdk.h @@ -42,6 +42,14 @@ namespace agones { // Marks the Game Server as ready to shutdown grpc::Status Shutdown(); + // SetLabel sets a metadata label on the `GameServer` with the prefix + // stable.agones.dev/sdk- + grpc::Status SetLabel(std::string key, std::string value); + + // SetAnnotation sets a metadata annotation on the `GameServer` with the prefix + // stable.agones.dev/sdk- + grpc::Status SetAnnotation(std::string key, std::string value); + // Watch the GameServer configuration, and fire the callback // when an update occurs. // This is a blocking function, and as such you will likely want to run it inside a thread. diff --git a/sdks/cpp/sdk.pb.cc b/sdks/cpp/sdk.pb.cc index 76295107d2..01689b54c9 100644 --- a/sdks/cpp/sdk.pb.cc +++ b/sdks/cpp/sdk.pb.cc @@ -43,6 +43,11 @@ class EmptyDefaultTypeInternal { ::google::protobuf::internal::ExplicitlyConstructed _instance; } _Empty_default_instance_; +class KeyValueDefaultTypeInternal { + public: + ::google::protobuf::internal::ExplicitlyConstructed + _instance; +} _KeyValue_default_instance_; class GameServer_ObjectMeta_AnnotationsEntry_DoNotUseDefaultTypeInternal { public: ::google::protobuf::internal::ExplicitlyConstructed @@ -109,6 +114,27 @@ void InitDefaultsEmpty() { ::google::protobuf::GoogleOnceInit(&once, &InitDefaultsEmptyImpl); } +void InitDefaultsKeyValueImpl() { + GOOGLE_PROTOBUF_VERIFY_VERSION; + +#ifdef GOOGLE_PROTOBUF_ENFORCE_UNIQUENESS + ::google::protobuf::internal::InitProtobufDefaultsForceUnique(); +#else + ::google::protobuf::internal::InitProtobufDefaults(); +#endif // GOOGLE_PROTOBUF_ENFORCE_UNIQUENESS + { + void* ptr = &::stable::agones::dev::sdk::_KeyValue_default_instance_; + new (ptr) ::stable::agones::dev::sdk::KeyValue(); + ::google::protobuf::internal::OnShutdownDestroyMessage(ptr); + } + ::stable::agones::dev::sdk::KeyValue::InitAsDefaultInstance(); +} + +void InitDefaultsKeyValue() { + static GOOGLE_PROTOBUF_DECLARE_ONCE(once); + ::google::protobuf::GoogleOnceInit(&once, &InitDefaultsKeyValueImpl); +} + void InitDefaultsGameServer_ObjectMeta_AnnotationsEntry_DoNotUseImpl() { GOOGLE_PROTOBUF_VERIFY_VERSION; @@ -282,7 +308,7 @@ void InitDefaultsGameServer() { ::google::protobuf::GoogleOnceInit(&once, &InitDefaultsGameServerImpl); } -::google::protobuf::Metadata file_level_metadata[9]; +::google::protobuf::Metadata file_level_metadata[10]; const ::google::protobuf::uint32 TableStruct::offsets[] GOOGLE_PROTOBUF_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = { ~0u, // no _has_bits_ @@ -290,6 +316,13 @@ const ::google::protobuf::uint32 TableStruct::offsets[] GOOGLE_PROTOBUF_ATTRIBUT ~0u, // no _extensions_ ~0u, // no _oneof_case_ ~0u, // no _weak_field_map_ + ~0u, // no _has_bits_ + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(::stable::agones::dev::sdk::KeyValue, _internal_metadata_), + ~0u, // no _extensions_ + ~0u, // no _oneof_case_ + ~0u, // no _weak_field_map_ + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(::stable::agones::dev::sdk::KeyValue, key_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(::stable::agones::dev::sdk::KeyValue, value_), GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(::stable::agones::dev::sdk::GameServer_ObjectMeta_AnnotationsEntry_DoNotUse, _has_bits_), GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(::stable::agones::dev::sdk::GameServer_ObjectMeta_AnnotationsEntry_DoNotUse, _internal_metadata_), ~0u, // no _extensions_ @@ -363,18 +396,20 @@ const ::google::protobuf::uint32 TableStruct::offsets[] GOOGLE_PROTOBUF_ATTRIBUT }; static const ::google::protobuf::internal::MigrationSchema schemas[] GOOGLE_PROTOBUF_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = { { 0, -1, sizeof(::stable::agones::dev::sdk::Empty)}, - { 5, 12, sizeof(::stable::agones::dev::sdk::GameServer_ObjectMeta_AnnotationsEntry_DoNotUse)}, - { 14, 21, sizeof(::stable::agones::dev::sdk::GameServer_ObjectMeta_LabelsEntry_DoNotUse)}, - { 23, -1, sizeof(::stable::agones::dev::sdk::GameServer_ObjectMeta)}, - { 37, -1, sizeof(::stable::agones::dev::sdk::GameServer_Spec_Health)}, - { 46, -1, sizeof(::stable::agones::dev::sdk::GameServer_Spec)}, - { 52, -1, sizeof(::stable::agones::dev::sdk::GameServer_Status_Port)}, - { 59, -1, sizeof(::stable::agones::dev::sdk::GameServer_Status)}, - { 67, -1, sizeof(::stable::agones::dev::sdk::GameServer)}, + { 5, -1, sizeof(::stable::agones::dev::sdk::KeyValue)}, + { 12, 19, sizeof(::stable::agones::dev::sdk::GameServer_ObjectMeta_AnnotationsEntry_DoNotUse)}, + { 21, 28, sizeof(::stable::agones::dev::sdk::GameServer_ObjectMeta_LabelsEntry_DoNotUse)}, + { 30, -1, sizeof(::stable::agones::dev::sdk::GameServer_ObjectMeta)}, + { 44, -1, sizeof(::stable::agones::dev::sdk::GameServer_Spec_Health)}, + { 53, -1, sizeof(::stable::agones::dev::sdk::GameServer_Spec)}, + { 59, -1, sizeof(::stable::agones::dev::sdk::GameServer_Status_Port)}, + { 66, -1, sizeof(::stable::agones::dev::sdk::GameServer_Status)}, + { 74, -1, sizeof(::stable::agones::dev::sdk::GameServer)}, }; static ::google::protobuf::Message const * const file_default_instances[] = { reinterpret_cast(&::stable::agones::dev::sdk::_Empty_default_instance_), + reinterpret_cast(&::stable::agones::dev::sdk::_KeyValue_default_instance_), reinterpret_cast(&::stable::agones::dev::sdk::_GameServer_ObjectMeta_AnnotationsEntry_DoNotUse_default_instance_), reinterpret_cast(&::stable::agones::dev::sdk::_GameServer_ObjectMeta_LabelsEntry_DoNotUse_default_instance_), reinterpret_cast(&::stable::agones::dev::sdk::_GameServer_ObjectMeta_default_instance_), @@ -401,14 +436,15 @@ void protobuf_AssignDescriptorsOnce() { void protobuf_RegisterTypes(const ::std::string&) GOOGLE_PROTOBUF_ATTRIBUTE_COLD; void protobuf_RegisterTypes(const ::std::string&) { protobuf_AssignDescriptorsOnce(); - ::google::protobuf::internal::RegisterAllTypes(file_level_metadata, 9); + ::google::protobuf::internal::RegisterAllTypes(file_level_metadata, 10); } void AddDescriptorsImpl() { InitDefaults(); static const char descriptor[] GOOGLE_PROTOBUF_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = { "\n\tsdk.proto\022\025stable.agones.dev.sdk\032\034goog" - "le/api/annotations.proto\"\007\n\005Empty\"\242\007\n\nGa" + "le/api/annotations.proto\"\007\n\005Empty\"&\n\010Key" + "Value\022\013\n\003key\030\001 \001(\t\022\r\n\005value\030\002 \001(\t\"\242\007\n\nGa" "meServer\022A\n\013object_meta\030\001 \001(\0132,.stable.a" "gones.dev.sdk.GameServer.ObjectMeta\0224\n\004s" "pec\030\002 \001(\0132&.stable.agones.dev.sdk.GameSe" @@ -432,7 +468,7 @@ void AddDescriptorsImpl() { "state\030\001 \001(\t\022\017\n\007address\030\002 \001(\t\022<\n\005ports\030\003 " "\003(\0132-.stable.agones.dev.sdk.GameServer.S" "tatus.Port\032\"\n\004Port\022\014\n\004name\030\001 \001(\t\022\014\n\004port" - "\030\002 \001(\0052\357\003\n\003SDK\022V\n\005Ready\022\034.stable.agones." + "\030\002 \001(\0052\307\005\n\003SDK\022V\n\005Ready\022\034.stable.agones." "dev.sdk.Empty\032\034.stable.agones.dev.sdk.Em" "pty\"\021\202\323\344\223\002\013\"\006/ready:\001*\022\\\n\010Shutdown\022\034.sta" "ble.agones.dev.sdk.Empty\032\034.stable.agones" @@ -444,10 +480,16 @@ void AddDescriptorsImpl() { "GameServer\"\023\202\323\344\223\002\r\022\013/gameserver\022o\n\017Watch" "GameServer\022\034.stable.agones.dev.sdk.Empty" "\032!.stable.agones.dev.sdk.GameServer\"\031\202\323\344" - "\223\002\023\022\021/watch/gameserver0\001B\005Z\003sdkb\006proto3" + "\223\002\023\022\021/watch/gameserver0\001\022e\n\010SetLabel\022\037.s" + "table.agones.dev.sdk.KeyValue\032\034.stable.a" + "gones.dev.sdk.Empty\"\032\202\323\344\223\002\024\032\017/metadata/l" + "abel:\001*\022o\n\rSetAnnotation\022\037.stable.agones" + ".dev.sdk.KeyValue\032\034.stable.agones.dev.sd" + "k.Empty\"\037\202\323\344\223\002\031\032\024/metadata/annotation:\001*" + "B\005Z\003sdkb\006proto3" }; ::google::protobuf::DescriptorPool::InternalAddGeneratedFile( - descriptor, 1519); + descriptor, 1775); ::google::protobuf::MessageFactory::InternalRegisterGeneratedFile( "sdk.proto", &protobuf_RegisterTypes); ::protobuf_google_2fapi_2fannotations_2eproto::AddDescriptors(); @@ -663,6 +705,319 @@ ::google::protobuf::Metadata Empty::GetMetadata() const { } +// =================================================================== + +void KeyValue::InitAsDefaultInstance() { +} +#if !defined(_MSC_VER) || _MSC_VER >= 1900 +const int KeyValue::kKeyFieldNumber; +const int KeyValue::kValueFieldNumber; +#endif // !defined(_MSC_VER) || _MSC_VER >= 1900 + +KeyValue::KeyValue() + : ::google::protobuf::Message(), _internal_metadata_(NULL) { + if (GOOGLE_PREDICT_TRUE(this != internal_default_instance())) { + ::protobuf_sdk_2eproto::InitDefaultsKeyValue(); + } + SharedCtor(); + // @@protoc_insertion_point(constructor:stable.agones.dev.sdk.KeyValue) +} +KeyValue::KeyValue(const KeyValue& from) + : ::google::protobuf::Message(), + _internal_metadata_(NULL), + _cached_size_(0) { + _internal_metadata_.MergeFrom(from._internal_metadata_); + key_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + if (from.key().size() > 0) { + key_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.key_); + } + value_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + if (from.value().size() > 0) { + value_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.value_); + } + // @@protoc_insertion_point(copy_constructor:stable.agones.dev.sdk.KeyValue) +} + +void KeyValue::SharedCtor() { + key_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + value_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + _cached_size_ = 0; +} + +KeyValue::~KeyValue() { + // @@protoc_insertion_point(destructor:stable.agones.dev.sdk.KeyValue) + SharedDtor(); +} + +void KeyValue::SharedDtor() { + key_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + value_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +} + +void KeyValue::SetCachedSize(int size) const { + GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); + _cached_size_ = size; + GOOGLE_SAFE_CONCURRENT_WRITES_END(); +} +const ::google::protobuf::Descriptor* KeyValue::descriptor() { + ::protobuf_sdk_2eproto::protobuf_AssignDescriptorsOnce(); + return ::protobuf_sdk_2eproto::file_level_metadata[kIndexInFileMessages].descriptor; +} + +const KeyValue& KeyValue::default_instance() { + ::protobuf_sdk_2eproto::InitDefaultsKeyValue(); + return *internal_default_instance(); +} + +KeyValue* KeyValue::New(::google::protobuf::Arena* arena) const { + KeyValue* n = new KeyValue; + if (arena != NULL) { + arena->Own(n); + } + return n; +} + +void KeyValue::Clear() { +// @@protoc_insertion_point(message_clear_start:stable.agones.dev.sdk.KeyValue) + ::google::protobuf::uint32 cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + key_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + value_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + _internal_metadata_.Clear(); +} + +bool KeyValue::MergePartialFromCodedStream( + ::google::protobuf::io::CodedInputStream* input) { +#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure + ::google::protobuf::uint32 tag; + // @@protoc_insertion_point(parse_start:stable.agones.dev.sdk.KeyValue) + for (;;) { + ::std::pair< ::google::protobuf::uint32, bool> p = input->ReadTagWithCutoffNoLastTag(127u); + tag = p.first; + if (!p.second) goto handle_unusual; + switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) { + // string key = 1; + case 1: { + if (static_cast< ::google::protobuf::uint8>(tag) == + static_cast< ::google::protobuf::uint8>(10u /* 10 & 0xFF */)) { + DO_(::google::protobuf::internal::WireFormatLite::ReadString( + input, this->mutable_key())); + DO_(::google::protobuf::internal::WireFormatLite::VerifyUtf8String( + this->key().data(), static_cast(this->key().length()), + ::google::protobuf::internal::WireFormatLite::PARSE, + "stable.agones.dev.sdk.KeyValue.key")); + } else { + goto handle_unusual; + } + break; + } + + // string value = 2; + case 2: { + if (static_cast< ::google::protobuf::uint8>(tag) == + static_cast< ::google::protobuf::uint8>(18u /* 18 & 0xFF */)) { + DO_(::google::protobuf::internal::WireFormatLite::ReadString( + input, this->mutable_value())); + DO_(::google::protobuf::internal::WireFormatLite::VerifyUtf8String( + this->value().data(), static_cast(this->value().length()), + ::google::protobuf::internal::WireFormatLite::PARSE, + "stable.agones.dev.sdk.KeyValue.value")); + } else { + goto handle_unusual; + } + break; + } + + default: { + handle_unusual: + if (tag == 0) { + goto success; + } + DO_(::google::protobuf::internal::WireFormat::SkipField( + input, tag, _internal_metadata_.mutable_unknown_fields())); + break; + } + } + } +success: + // @@protoc_insertion_point(parse_success:stable.agones.dev.sdk.KeyValue) + return true; +failure: + // @@protoc_insertion_point(parse_failure:stable.agones.dev.sdk.KeyValue) + return false; +#undef DO_ +} + +void KeyValue::SerializeWithCachedSizes( + ::google::protobuf::io::CodedOutputStream* output) const { + // @@protoc_insertion_point(serialize_start:stable.agones.dev.sdk.KeyValue) + ::google::protobuf::uint32 cached_has_bits = 0; + (void) cached_has_bits; + + // string key = 1; + if (this->key().size() > 0) { + ::google::protobuf::internal::WireFormatLite::VerifyUtf8String( + this->key().data(), static_cast(this->key().length()), + ::google::protobuf::internal::WireFormatLite::SERIALIZE, + "stable.agones.dev.sdk.KeyValue.key"); + ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased( + 1, this->key(), output); + } + + // string value = 2; + if (this->value().size() > 0) { + ::google::protobuf::internal::WireFormatLite::VerifyUtf8String( + this->value().data(), static_cast(this->value().length()), + ::google::protobuf::internal::WireFormatLite::SERIALIZE, + "stable.agones.dev.sdk.KeyValue.value"); + ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased( + 2, this->value(), output); + } + + if ((_internal_metadata_.have_unknown_fields() && ::google::protobuf::internal::GetProto3PreserveUnknownsDefault())) { + ::google::protobuf::internal::WireFormat::SerializeUnknownFields( + (::google::protobuf::internal::GetProto3PreserveUnknownsDefault() ? _internal_metadata_.unknown_fields() : _internal_metadata_.default_instance()), output); + } + // @@protoc_insertion_point(serialize_end:stable.agones.dev.sdk.KeyValue) +} + +::google::protobuf::uint8* KeyValue::InternalSerializeWithCachedSizesToArray( + bool deterministic, ::google::protobuf::uint8* target) const { + (void)deterministic; // Unused + // @@protoc_insertion_point(serialize_to_array_start:stable.agones.dev.sdk.KeyValue) + ::google::protobuf::uint32 cached_has_bits = 0; + (void) cached_has_bits; + + // string key = 1; + if (this->key().size() > 0) { + ::google::protobuf::internal::WireFormatLite::VerifyUtf8String( + this->key().data(), static_cast(this->key().length()), + ::google::protobuf::internal::WireFormatLite::SERIALIZE, + "stable.agones.dev.sdk.KeyValue.key"); + target = + ::google::protobuf::internal::WireFormatLite::WriteStringToArray( + 1, this->key(), target); + } + + // string value = 2; + if (this->value().size() > 0) { + ::google::protobuf::internal::WireFormatLite::VerifyUtf8String( + this->value().data(), static_cast(this->value().length()), + ::google::protobuf::internal::WireFormatLite::SERIALIZE, + "stable.agones.dev.sdk.KeyValue.value"); + target = + ::google::protobuf::internal::WireFormatLite::WriteStringToArray( + 2, this->value(), target); + } + + if ((_internal_metadata_.have_unknown_fields() && ::google::protobuf::internal::GetProto3PreserveUnknownsDefault())) { + target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray( + (::google::protobuf::internal::GetProto3PreserveUnknownsDefault() ? _internal_metadata_.unknown_fields() : _internal_metadata_.default_instance()), target); + } + // @@protoc_insertion_point(serialize_to_array_end:stable.agones.dev.sdk.KeyValue) + return target; +} + +size_t KeyValue::ByteSizeLong() const { +// @@protoc_insertion_point(message_byte_size_start:stable.agones.dev.sdk.KeyValue) + size_t total_size = 0; + + if ((_internal_metadata_.have_unknown_fields() && ::google::protobuf::internal::GetProto3PreserveUnknownsDefault())) { + total_size += + ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize( + (::google::protobuf::internal::GetProto3PreserveUnknownsDefault() ? _internal_metadata_.unknown_fields() : _internal_metadata_.default_instance())); + } + // string key = 1; + if (this->key().size() > 0) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::StringSize( + this->key()); + } + + // string value = 2; + if (this->value().size() > 0) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::StringSize( + this->value()); + } + + int cached_size = ::google::protobuf::internal::ToCachedSize(total_size); + GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); + _cached_size_ = cached_size; + GOOGLE_SAFE_CONCURRENT_WRITES_END(); + return total_size; +} + +void KeyValue::MergeFrom(const ::google::protobuf::Message& from) { +// @@protoc_insertion_point(generalized_merge_from_start:stable.agones.dev.sdk.KeyValue) + GOOGLE_DCHECK_NE(&from, this); + const KeyValue* source = + ::google::protobuf::internal::DynamicCastToGenerated( + &from); + if (source == NULL) { + // @@protoc_insertion_point(generalized_merge_from_cast_fail:stable.agones.dev.sdk.KeyValue) + ::google::protobuf::internal::ReflectionOps::Merge(from, this); + } else { + // @@protoc_insertion_point(generalized_merge_from_cast_success:stable.agones.dev.sdk.KeyValue) + MergeFrom(*source); + } +} + +void KeyValue::MergeFrom(const KeyValue& from) { +// @@protoc_insertion_point(class_specific_merge_from_start:stable.agones.dev.sdk.KeyValue) + GOOGLE_DCHECK_NE(&from, this); + _internal_metadata_.MergeFrom(from._internal_metadata_); + ::google::protobuf::uint32 cached_has_bits = 0; + (void) cached_has_bits; + + if (from.key().size() > 0) { + + key_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.key_); + } + if (from.value().size() > 0) { + + value_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.value_); + } +} + +void KeyValue::CopyFrom(const ::google::protobuf::Message& from) { +// @@protoc_insertion_point(generalized_copy_from_start:stable.agones.dev.sdk.KeyValue) + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +void KeyValue::CopyFrom(const KeyValue& from) { +// @@protoc_insertion_point(class_specific_copy_from_start:stable.agones.dev.sdk.KeyValue) + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +bool KeyValue::IsInitialized() const { + return true; +} + +void KeyValue::Swap(KeyValue* other) { + if (other == this) return; + InternalSwap(other); +} +void KeyValue::InternalSwap(KeyValue* other) { + using std::swap; + key_.Swap(&other->key_); + value_.Swap(&other->value_); + _internal_metadata_.Swap(&other->_internal_metadata_); + swap(_cached_size_, other->_cached_size_); +} + +::google::protobuf::Metadata KeyValue::GetMetadata() const { + protobuf_sdk_2eproto::protobuf_AssignDescriptorsOnce(); + return ::protobuf_sdk_2eproto::file_level_metadata[kIndexInFileMessages]; +} + + // =================================================================== GameServer_ObjectMeta_AnnotationsEntry_DoNotUse::GameServer_ObjectMeta_AnnotationsEntry_DoNotUse() {} @@ -672,7 +1027,7 @@ void GameServer_ObjectMeta_AnnotationsEntry_DoNotUse::MergeFrom(const GameServer } ::google::protobuf::Metadata GameServer_ObjectMeta_AnnotationsEntry_DoNotUse::GetMetadata() const { ::protobuf_sdk_2eproto::protobuf_AssignDescriptorsOnce(); - return ::protobuf_sdk_2eproto::file_level_metadata[1]; + return ::protobuf_sdk_2eproto::file_level_metadata[2]; } void GameServer_ObjectMeta_AnnotationsEntry_DoNotUse::MergeFrom( const ::google::protobuf::Message& other) { @@ -689,7 +1044,7 @@ void GameServer_ObjectMeta_LabelsEntry_DoNotUse::MergeFrom(const GameServer_Obje } ::google::protobuf::Metadata GameServer_ObjectMeta_LabelsEntry_DoNotUse::GetMetadata() const { ::protobuf_sdk_2eproto::protobuf_AssignDescriptorsOnce(); - return ::protobuf_sdk_2eproto::file_level_metadata[2]; + return ::protobuf_sdk_2eproto::file_level_metadata[3]; } void GameServer_ObjectMeta_LabelsEntry_DoNotUse::MergeFrom( const ::google::protobuf::Message& other) { diff --git a/sdks/cpp/sdk.pb.h b/sdks/cpp/sdk.pb.h index 2083843b9f..7b893fe55c 100644 --- a/sdks/cpp/sdk.pb.h +++ b/sdks/cpp/sdk.pb.h @@ -55,7 +55,7 @@ namespace protobuf_sdk_2eproto { struct TableStruct { static const ::google::protobuf::internal::ParseTableField entries[]; static const ::google::protobuf::internal::AuxillaryParseTableField aux[]; - static const ::google::protobuf::internal::ParseTable schema[9]; + static const ::google::protobuf::internal::ParseTable schema[10]; static const ::google::protobuf::internal::FieldMetadata field_metadata[]; static const ::google::protobuf::internal::SerializationTable serialization_table[]; static const ::google::protobuf::uint32 offsets[]; @@ -63,6 +63,8 @@ struct TableStruct { void AddDescriptors(); void InitDefaultsEmptyImpl(); void InitDefaultsEmpty(); +void InitDefaultsKeyValueImpl(); +void InitDefaultsKeyValue(); void InitDefaultsGameServer_ObjectMeta_AnnotationsEntry_DoNotUseImpl(); void InitDefaultsGameServer_ObjectMeta_AnnotationsEntry_DoNotUse(); void InitDefaultsGameServer_ObjectMeta_LabelsEntry_DoNotUseImpl(); @@ -81,6 +83,7 @@ void InitDefaultsGameServerImpl(); void InitDefaultsGameServer(); inline void InitDefaults() { InitDefaultsEmpty(); + InitDefaultsKeyValue(); InitDefaultsGameServer_ObjectMeta_AnnotationsEntry_DoNotUse(); InitDefaultsGameServer_ObjectMeta_LabelsEntry_DoNotUse(); InitDefaultsGameServer_ObjectMeta(); @@ -122,6 +125,9 @@ extern GameServer_StatusDefaultTypeInternal _GameServer_Status_default_instance_ class GameServer_Status_Port; class GameServer_Status_PortDefaultTypeInternal; extern GameServer_Status_PortDefaultTypeInternal _GameServer_Status_Port_default_instance_; +class KeyValue; +class KeyValueDefaultTypeInternal; +extern KeyValueDefaultTypeInternal _KeyValue_default_instance_; } // namespace sdk } // namespace dev } // namespace agones @@ -225,6 +231,128 @@ class Empty : public ::google::protobuf::Message /* @@protoc_insertion_point(cla }; // ------------------------------------------------------------------- +class KeyValue : public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:stable.agones.dev.sdk.KeyValue) */ { + public: + KeyValue(); + virtual ~KeyValue(); + + KeyValue(const KeyValue& from); + + inline KeyValue& operator=(const KeyValue& from) { + CopyFrom(from); + return *this; + } + #if LANG_CXX11 + KeyValue(KeyValue&& from) noexcept + : KeyValue() { + *this = ::std::move(from); + } + + inline KeyValue& operator=(KeyValue&& from) noexcept { + if (GetArenaNoVirtual() == from.GetArenaNoVirtual()) { + if (this != &from) InternalSwap(&from); + } else { + CopyFrom(from); + } + return *this; + } + #endif + static const ::google::protobuf::Descriptor* descriptor(); + static const KeyValue& default_instance(); + + static void InitAsDefaultInstance(); // FOR INTERNAL USE ONLY + static inline const KeyValue* internal_default_instance() { + return reinterpret_cast( + &_KeyValue_default_instance_); + } + static PROTOBUF_CONSTEXPR int const kIndexInFileMessages = + 1; + + void Swap(KeyValue* other); + friend void swap(KeyValue& a, KeyValue& b) { + a.Swap(&b); + } + + // implements Message ---------------------------------------------- + + inline KeyValue* New() const PROTOBUF_FINAL { return New(NULL); } + + KeyValue* New(::google::protobuf::Arena* arena) const PROTOBUF_FINAL; + void CopyFrom(const ::google::protobuf::Message& from) PROTOBUF_FINAL; + void MergeFrom(const ::google::protobuf::Message& from) PROTOBUF_FINAL; + void CopyFrom(const KeyValue& from); + void MergeFrom(const KeyValue& from); + void Clear() PROTOBUF_FINAL; + bool IsInitialized() const PROTOBUF_FINAL; + + size_t ByteSizeLong() const PROTOBUF_FINAL; + bool MergePartialFromCodedStream( + ::google::protobuf::io::CodedInputStream* input) PROTOBUF_FINAL; + void SerializeWithCachedSizes( + ::google::protobuf::io::CodedOutputStream* output) const PROTOBUF_FINAL; + ::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray( + bool deterministic, ::google::protobuf::uint8* target) const PROTOBUF_FINAL; + int GetCachedSize() const PROTOBUF_FINAL { return _cached_size_; } + private: + void SharedCtor(); + void SharedDtor(); + void SetCachedSize(int size) const PROTOBUF_FINAL; + void InternalSwap(KeyValue* other); + private: + inline ::google::protobuf::Arena* GetArenaNoVirtual() const { + return NULL; + } + inline void* MaybeArenaPtr() const { + return NULL; + } + public: + + ::google::protobuf::Metadata GetMetadata() const PROTOBUF_FINAL; + + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + + // string key = 1; + void clear_key(); + static const int kKeyFieldNumber = 1; + const ::std::string& key() const; + void set_key(const ::std::string& value); + #if LANG_CXX11 + void set_key(::std::string&& value); + #endif + void set_key(const char* value); + void set_key(const char* value, size_t size); + ::std::string* mutable_key(); + ::std::string* release_key(); + void set_allocated_key(::std::string* key); + + // string value = 2; + void clear_value(); + static const int kValueFieldNumber = 2; + const ::std::string& value() const; + void set_value(const ::std::string& value); + #if LANG_CXX11 + void set_value(::std::string&& value); + #endif + void set_value(const char* value); + void set_value(const char* value, size_t size); + ::std::string* mutable_value(); + ::std::string* release_value(); + void set_allocated_value(::std::string* value); + + // @@protoc_insertion_point(class_scope:stable.agones.dev.sdk.KeyValue) + private: + + ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_; + ::google::protobuf::internal::ArenaStringPtr key_; + ::google::protobuf::internal::ArenaStringPtr value_; + mutable int _cached_size_; + friend struct ::protobuf_sdk_2eproto::TableStruct; + friend void ::protobuf_sdk_2eproto::InitDefaultsKeyValueImpl(); +}; +// ------------------------------------------------------------------- + class GameServer_ObjectMeta_AnnotationsEntry_DoNotUse : public ::google::protobuf::internal::MapEntry(value), size)); + // @@protoc_insertion_point(field_set_pointer:stable.agones.dev.sdk.KeyValue.key) +} +inline ::std::string* KeyValue::mutable_key() { + + // @@protoc_insertion_point(field_mutable:stable.agones.dev.sdk.KeyValue.key) + return key_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +} +inline ::std::string* KeyValue::release_key() { + // @@protoc_insertion_point(field_release:stable.agones.dev.sdk.KeyValue.key) + + return key_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +} +inline void KeyValue::set_allocated_key(::std::string* key) { + if (key != NULL) { + + } else { + + } + key_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), key); + // @@protoc_insertion_point(field_set_allocated:stable.agones.dev.sdk.KeyValue.key) +} + +// string value = 2; +inline void KeyValue::clear_value() { + value_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +} +inline const ::std::string& KeyValue::value() const { + // @@protoc_insertion_point(field_get:stable.agones.dev.sdk.KeyValue.value) + return value_.GetNoArena(); +} +inline void KeyValue::set_value(const ::std::string& value) { + + value_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value); + // @@protoc_insertion_point(field_set:stable.agones.dev.sdk.KeyValue.value) +} +#if LANG_CXX11 +inline void KeyValue::set_value(::std::string&& value) { + + value_.SetNoArena( + &::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::move(value)); + // @@protoc_insertion_point(field_set_rvalue:stable.agones.dev.sdk.KeyValue.value) +} +#endif +inline void KeyValue::set_value(const char* value) { + GOOGLE_DCHECK(value != NULL); + + value_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value)); + // @@protoc_insertion_point(field_set_char:stable.agones.dev.sdk.KeyValue.value) +} +inline void KeyValue::set_value(const char* value, size_t size) { + + value_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), + ::std::string(reinterpret_cast(value), size)); + // @@protoc_insertion_point(field_set_pointer:stable.agones.dev.sdk.KeyValue.value) +} +inline ::std::string* KeyValue::mutable_value() { + + // @@protoc_insertion_point(field_mutable:stable.agones.dev.sdk.KeyValue.value) + return value_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +} +inline ::std::string* KeyValue::release_value() { + // @@protoc_insertion_point(field_release:stable.agones.dev.sdk.KeyValue.value) + + return value_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +} +inline void KeyValue::set_allocated_value(::std::string* value) { + if (value != NULL) { + + } else { + + } + value_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value); + // @@protoc_insertion_point(field_set_allocated:stable.agones.dev.sdk.KeyValue.value) +} + +// ------------------------------------------------------------------- + // ------------------------------------------------------------------- // ------------------------------------------------------------------- @@ -1877,6 +2115,8 @@ inline void GameServer::set_allocated_status(::stable::agones::dev::sdk::GameSer // ------------------------------------------------------------------- +// ------------------------------------------------------------------- + // @@protoc_insertion_point(namespace_scope) diff --git a/sdks/go/sdk.go b/sdks/go/sdk.go index 76855feff0..cc56d0bbf5 100644 --- a/sdks/go/sdk.go +++ b/sdks/go/sdk.go @@ -79,9 +79,26 @@ func (s *SDK) Health() error { return errors.Wrap(s.health.Send(&sdk.Empty{}), "could not send Health ping") } +// SetLabel sets a metadata label on the `GameServer` with the prefix +// stable.agones.dev/sdk- +func (s *SDK) SetLabel(key, value string) error { + kv := &sdk.KeyValue{Key: key, Value: value} + _, err := s.client.SetLabel(s.ctx, kv) + return errors.Wrap(err, "could not set label") +} + +// SetAnnotation sets a metadata annotation on the `GameServer` with the prefix +// stable.agones.dev/sdk- +func (s *SDK) SetAnnotation(key, value string) error { + kv := &sdk.KeyValue{Key: key, Value: value} + _, err := s.client.SetAnnotation(s.ctx, kv) + return errors.Wrap(err, "could not set annotation") +} + // GameServer retrieve the GameServer details func (s *SDK) GameServer() (*sdk.GameServer, error) { - return s.client.GetGameServer(s.ctx, &sdk.Empty{}) + gs, err := s.client.GetGameServer(s.ctx, &sdk.Empty{}) + return gs, errors.Wrap(err, "could not retrieve gameserver") } // WatchGameServer asynchronously calls the given GameServerCallback with the current GameServer @@ -98,12 +115,11 @@ func (s *SDK) WatchGameServer(f GameServerCallback) error { var gs *sdk.GameServer gs, err = stream.Recv() if err != nil { - if err != io.EOF { - fmt.Printf("error watching GameServer: %s\n", err.Error()) - } else { + if err == io.EOF { fmt.Println("gameserver event stream EOF received") return } + fmt.Printf("error watching GameServer: %s\n", err.Error()) // This is to wait for the reconnection, and not peg the CPU at 100% time.Sleep(time.Second) continue diff --git a/sdks/go/sdk_test.go b/sdks/go/sdk_test.go index b09c158c98..9ec8404920 100644 --- a/sdks/go/sdk_test.go +++ b/sdks/go/sdk_test.go @@ -68,7 +68,7 @@ func TestSDKWatchGameServer(t *testing.T) { client: sm, } - fixture := &sdk.GameServer{ObjectMeta: &sdk.GameServer_ObjectMeta{Name:"test-server"}} + fixture := &sdk.GameServer{ObjectMeta: &sdk.GameServer_ObjectMeta{Name: "test-server"}} updated := make(chan struct{}, 5) @@ -83,19 +83,63 @@ func TestSDKWatchGameServer(t *testing.T) { select { case <-updated: case <-time.After(5 * time.Second): - assert.FailNow(t,"update handler should have fired") + assert.FailNow(t, "update handler should have fired") } } +func TestSDKSetLabel(t *testing.T) { + t.Parallel() + sm := &sdkMock{ + labels: map[string]string{}, + } + s := SDK{ + ctx: context.Background(), + client: sm, + } + + expected := "bar" + err := s.SetLabel("foo", expected) + assert.Nil(t, err) + assert.Equal(t, expected, sm.labels["foo"]) +} + +func TestSDKSetAnnotation(t *testing.T) { + t.Parallel() + sm := &sdkMock{ + annotations: map[string]string{}, + } + s := SDK{ + ctx: context.Background(), + client: sm, + } + + expected := "bar" + err := s.SetAnnotation("foo", expected) + assert.Nil(t, err) + assert.Equal(t, expected, sm.annotations["foo"]) +} + var _ sdk.SDKClient = &sdkMock{} var _ sdk.SDK_HealthClient = &healthMock{} var _ sdk.SDK_WatchGameServerClient = &watchMock{} type sdkMock struct { - ready bool - shutdown bool - hm *healthMock - wm *watchMock + ready bool + shutdown bool + hm *healthMock + wm *watchMock + labels map[string]string + annotations map[string]string +} + +func (m *sdkMock) SetLabel(ctx context.Context, in *sdk.KeyValue, opts ...grpc.CallOption) (*sdk.Empty, error) { + m.labels[in.Key] = in.Value + return &sdk.Empty{}, nil +} + +func (m *sdkMock) SetAnnotation(ctx context.Context, in *sdk.KeyValue, opts ...grpc.CallOption) (*sdk.Empty, error) { + m.annotations[in.Key] = in.Value + return &sdk.Empty{}, nil } func (m *sdkMock) WatchGameServer(ctx context.Context, in *sdk.Empty, opts ...grpc.CallOption) (sdk.SDK_WatchGameServerClient, error) { @@ -162,7 +206,7 @@ type watchMock struct { } func (wm *watchMock) Recv() (*sdk.GameServer, error) { - return <- wm.msgs, nil + return <-wm.msgs, nil } func (*watchMock) Header() (metadata.MD, error) { diff --git a/sdks/rust/src/grpc/sdk.rs b/sdks/rust/src/grpc/sdk.rs index 3a9a4af01f..e26b798556 100644 --- a/sdks/rust/src/grpc/sdk.rs +++ b/sdks/rust/src/grpc/sdk.rs @@ -156,6 +156,211 @@ impl ::protobuf::reflect::ProtobufValue for Empty { } } +#[derive(PartialEq,Clone,Default)] +pub struct KeyValue { + // message fields + pub key: ::std::string::String, + pub value: ::std::string::String, + // special fields + unknown_fields: ::protobuf::UnknownFields, + cached_size: ::protobuf::CachedSize, +} + +impl KeyValue { + pub fn new() -> KeyValue { + ::std::default::Default::default() + } + + // string key = 1; + + pub fn clear_key(&mut self) { + self.key.clear(); + } + + // Param is passed by value, moved + pub fn set_key(&mut self, v: ::std::string::String) { + self.key = v; + } + + // Mutable pointer to the field. + // If field is not initialized, it is initialized with default value first. + pub fn mut_key(&mut self) -> &mut ::std::string::String { + &mut self.key + } + + // Take field + pub fn take_key(&mut self) -> ::std::string::String { + ::std::mem::replace(&mut self.key, ::std::string::String::new()) + } + + pub fn get_key(&self) -> &str { + &self.key + } + + // string value = 2; + + pub fn clear_value(&mut self) { + self.value.clear(); + } + + // Param is passed by value, moved + pub fn set_value(&mut self, v: ::std::string::String) { + self.value = v; + } + + // Mutable pointer to the field. + // If field is not initialized, it is initialized with default value first. + pub fn mut_value(&mut self) -> &mut ::std::string::String { + &mut self.value + } + + // Take field + pub fn take_value(&mut self) -> ::std::string::String { + ::std::mem::replace(&mut self.value, ::std::string::String::new()) + } + + pub fn get_value(&self) -> &str { + &self.value + } +} + +impl ::protobuf::Message for KeyValue { + fn is_initialized(&self) -> bool { + true + } + + fn merge_from(&mut self, is: &mut ::protobuf::CodedInputStream) -> ::protobuf::ProtobufResult<()> { + while !is.eof()? { + let (field_number, wire_type) = is.read_tag_unpack()?; + match field_number { + 1 => { + ::protobuf::rt::read_singular_proto3_string_into(wire_type, is, &mut self.key)?; + }, + 2 => { + ::protobuf::rt::read_singular_proto3_string_into(wire_type, is, &mut self.value)?; + }, + _ => { + ::protobuf::rt::read_unknown_or_skip_group(field_number, wire_type, is, self.mut_unknown_fields())?; + }, + }; + } + ::std::result::Result::Ok(()) + } + + // Compute sizes of nested messages + #[allow(unused_variables)] + fn compute_size(&self) -> u32 { + let mut my_size = 0; + if !self.key.is_empty() { + my_size += ::protobuf::rt::string_size(1, &self.key); + } + if !self.value.is_empty() { + my_size += ::protobuf::rt::string_size(2, &self.value); + } + my_size += ::protobuf::rt::unknown_fields_size(self.get_unknown_fields()); + self.cached_size.set(my_size); + my_size + } + + fn write_to_with_cached_sizes(&self, os: &mut ::protobuf::CodedOutputStream) -> ::protobuf::ProtobufResult<()> { + if !self.key.is_empty() { + os.write_string(1, &self.key)?; + } + if !self.value.is_empty() { + os.write_string(2, &self.value)?; + } + os.write_unknown_fields(self.get_unknown_fields())?; + ::std::result::Result::Ok(()) + } + + fn get_cached_size(&self) -> u32 { + self.cached_size.get() + } + + fn get_unknown_fields(&self) -> &::protobuf::UnknownFields { + &self.unknown_fields + } + + fn mut_unknown_fields(&mut self) -> &mut ::protobuf::UnknownFields { + &mut self.unknown_fields + } + + fn as_any(&self) -> &::std::any::Any { + self as &::std::any::Any + } + fn as_any_mut(&mut self) -> &mut ::std::any::Any { + self as &mut ::std::any::Any + } + fn into_any(self: Box) -> ::std::boxed::Box<::std::any::Any> { + self + } + + fn descriptor(&self) -> &'static ::protobuf::reflect::MessageDescriptor { + Self::descriptor_static() + } + + fn new() -> KeyValue { + KeyValue::new() + } + + fn descriptor_static() -> &'static ::protobuf::reflect::MessageDescriptor { + static mut descriptor: ::protobuf::lazy::Lazy<::protobuf::reflect::MessageDescriptor> = ::protobuf::lazy::Lazy { + lock: ::protobuf::lazy::ONCE_INIT, + ptr: 0 as *const ::protobuf::reflect::MessageDescriptor, + }; + unsafe { + descriptor.get(|| { + let mut fields = ::std::vec::Vec::new(); + fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeString>( + "key", + |m: &KeyValue| { &m.key }, + |m: &mut KeyValue| { &mut m.key }, + )); + fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeString>( + "value", + |m: &KeyValue| { &m.value }, + |m: &mut KeyValue| { &mut m.value }, + )); + ::protobuf::reflect::MessageDescriptor::new::( + "KeyValue", + fields, + file_descriptor_proto() + ) + }) + } + } + + fn default_instance() -> &'static KeyValue { + static mut instance: ::protobuf::lazy::Lazy = ::protobuf::lazy::Lazy { + lock: ::protobuf::lazy::ONCE_INIT, + ptr: 0 as *const KeyValue, + }; + unsafe { + instance.get(KeyValue::new) + } + } +} + +impl ::protobuf::Clear for KeyValue { + fn clear(&mut self) { + self.clear_key(); + self.clear_value(); + self.unknown_fields.clear(); + } +} + +impl ::std::fmt::Debug for KeyValue { + fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { + ::protobuf::text_format::fmt(self, f) + } +} + +impl ::protobuf::reflect::ProtobufValue for KeyValue { + fn as_ref(&self) -> ::protobuf::reflect::ProtobufValueRef { + ::protobuf::reflect::ProtobufValueRef::Message(self) + } +} + #[derive(PartialEq,Clone,Default)] pub struct GameServer { // message fields @@ -1809,209 +2014,241 @@ impl ::protobuf::reflect::ProtobufValue for GameServer_Status_Port { static file_descriptor_proto_data: &'static [u8] = b"\ \n\tsdk.proto\x12\x15stable.agones.dev.sdk\x1a\x1cgoogle/api/annotations\ - .proto\"\x07\n\x05Empty\"\xae\t\n\nGameServer\x12M\n\x0bobject_meta\x18\ - \x01\x20\x01(\x0b2,.stable.agones.dev.sdk.GameServer.ObjectMetaR\nobject\ - Meta\x12:\n\x04spec\x18\x02\x20\x01(\x0b2&.stable.agones.dev.sdk.GameSer\ - ver.SpecR\x04spec\x12@\n\x06status\x18\x03\x20\x01(\x0b2(.stable.agones.\ - dev.sdk.GameServer.StatusR\x06status\x1a\xa7\x04\n\nObjectMeta\x12\x12\n\ - \x04name\x18\x01\x20\x01(\tR\x04name\x12\x1c\n\tnamespace\x18\x02\x20\ - \x01(\tR\tnamespace\x12\x10\n\x03uid\x18\x03\x20\x01(\tR\x03uid\x12)\n\ - \x10resource_version\x18\x04\x20\x01(\tR\x0fresourceVersion\x12\x1e\n\ng\ - eneration\x18\x05\x20\x01(\x03R\ngeneration\x12-\n\x12creation_timestamp\ - \x18\x06\x20\x01(\x03R\x11creationTimestamp\x12-\n\x12deletion_timestamp\ - \x18\x07\x20\x01(\x03R\x11deletionTimestamp\x12_\n\x0bannotations\x18\ - \x08\x20\x03(\x0b2=.stable.agones.dev.sdk.GameServer.ObjectMeta.Annotati\ - onsEntryR\x0bannotations\x12P\n\x06labels\x18\t\x20\x03(\x0b28.stable.ag\ - ones.dev.sdk.GameServer.ObjectMeta.LabelsEntryR\x06labels\x1a>\n\x10Anno\ - tationsEntry\x12\x10\n\x03key\x18\x01\x20\x01(\tR\x03key\x12\x14\n\x05va\ - lue\x18\x02\x20\x01(\tR\x05value:\x028\x01\x1a9\n\x0bLabelsEntry\x12\x10\ - \n\x03key\x18\x01\x20\x01(\tR\x03key\x12\x14\n\x05value\x18\x02\x20\x01(\ - \tR\x05value:\x028\x01\x1a\xf8\x01\n\x04Spec\x12E\n\x06health\x18\x01\ - \x20\x01(\x0b2-.stable.agones.dev.sdk.GameServer.Spec.HealthR\x06health\ - \x1a\xa8\x01\n\x06Health\x12\x1a\n\x08Disabled\x18\x01\x20\x01(\x08R\x08\ - Disabled\x12$\n\rPeriodSeconds\x18\x02\x20\x01(\x05R\rPeriodSeconds\x12*\ - \n\x10FailureThreshold\x18\x03\x20\x01(\x05R\x10FailureThreshold\x120\n\ - \x13InitialDelaySeconds\x18\x04\x20\x01(\x05R\x13InitialDelaySeconds\x1a\ - \xad\x01\n\x06Status\x12\x14\n\x05state\x18\x01\x20\x01(\tR\x05state\x12\ - \x18\n\x07address\x18\x02\x20\x01(\tR\x07address\x12C\n\x05ports\x18\x03\ - \x20\x03(\x0b2-.stable.agones.dev.sdk.GameServer.Status.PortR\x05ports\ - \x1a.\n\x04Port\x12\x12\n\x04name\x18\x01\x20\x01(\tR\x04name\x12\x12\n\ - \x04port\x18\x02\x20\x01(\x05R\x04port2\xef\x03\n\x03SDK\x12V\n\x05Ready\ - \x12\x1c.stable.agones.dev.sdk.Empty\x1a\x1c.stable.agones.dev.sdk.Empty\ - \"\x11\x82\xd3\xe4\x93\x02\x0b\"\x06/ready:\x01*\x12\\\n\x08Shutdown\x12\ - \x1c.stable.agones.dev.sdk.Empty\x1a\x1c.stable.agones.dev.sdk.Empty\"\ - \x14\x82\xd3\xe4\x93\x02\x0e\"\t/shutdown:\x01*\x12Z\n\x06Health\x12\x1c\ - .stable.agones.dev.sdk.Empty\x1a\x1c.stable.agones.dev.sdk.Empty\"\x12\ - \x82\xd3\xe4\x93\x02\x0c\"\x07/health:\x01*(\x01\x12e\n\rGetGameServer\ - \x12\x1c.stable.agones.dev.sdk.Empty\x1a!.stable.agones.dev.sdk.GameServ\ - er\"\x13\x82\xd3\xe4\x93\x02\r\x12\x0b/gameserver\x12o\n\x0fWatchGameSer\ - ver\x12\x1c.stable.agones.dev.sdk.Empty\x1a!.stable.agones.dev.sdk.GameS\ - erver\"\x19\x82\xd3\xe4\x93\x02\x13\x12\x11/watch/gameserver0\x01B\x05Z\ - \x03sdkJ\xef\x20\n\x06\x12\x04\x0e\0i\x01\n\xd2\x04\n\x01\x0c\x12\x03\ - \x0e\0\x122\xc7\x04\x20Copyright\x202017\x20Google\x20Inc.\x20All\x20Rig\ - hts\x20Reserved.\n\n\x20Licensed\x20under\x20the\x20Apache\x20License,\ - \x20Version\x202.0\x20(the\x20\"License\");\n\x20you\x20may\x20not\x20us\ - e\x20this\x20file\x20except\x20in\x20compliance\x20with\x20the\x20Licens\ - e.\n\x20You\x20may\x20obtain\x20a\x20copy\x20of\x20the\x20License\x20at\ - \n\n\x20\x20\x20\x20\x20http://www.apache.org/licenses/LICENSE-2.0\n\n\ - \x20Unless\x20required\x20by\x20applicable\x20law\x20or\x20agreed\x20to\ - \x20in\x20writing,\x20software\n\x20distributed\x20under\x20the\x20Licen\ - se\x20is\x20distributed\x20on\x20an\x20\"AS\x20IS\"\x20BASIS,\n\x20WITHO\ - UT\x20WARRANTIES\x20OR\x20CONDITIONS\x20OF\x20ANY\x20KIND,\x20either\x20\ - express\x20or\x20implied.\n\x20See\x20the\x20License\x20for\x20the\x20sp\ - ecific\x20language\x20governing\x20permissions\x20and\n\x20limitations\ - \x20under\x20the\x20License.\n\n\x08\n\x01\x02\x12\x03\x10\x08\x1d\n\x08\ - \n\x01\x08\x12\x03\x11\0\x1a\n\x0b\n\x04\x08\xe7\x07\0\x12\x03\x11\0\x1a\ - \n\x0c\n\x05\x08\xe7\x07\0\x02\x12\x03\x11\x07\x11\n\r\n\x06\x08\xe7\x07\ - \0\x02\0\x12\x03\x11\x07\x11\n\x0e\n\x07\x08\xe7\x07\0\x02\0\x01\x12\x03\ - \x11\x07\x11\n\x0c\n\x05\x08\xe7\x07\0\x07\x12\x03\x11\x14\x19\n\t\n\x02\ - \x03\0\x12\x03\x13\x07%\nM\n\x02\x06\0\x12\x04\x16\08\x01\x1aA\x20SDK\ - \x20service\x20to\x20be\x20used\x20in\x20the\x20GameServer\x20SDK\x20to\ - \x20the\x20Pod\x20Sidecar\n\n\n\n\x03\x06\0\x01\x12\x03\x16\x08\x0b\n1\n\ - \x04\x06\0\x02\0\x12\x04\x18\x04\x1d\x05\x1a#\x20Call\x20when\x20the\x20\ - GameServer\x20is\x20ready\n\n\x0c\n\x05\x06\0\x02\0\x01\x12\x03\x18\x08\ - \r\n\x0c\n\x05\x06\0\x02\0\x02\x12\x03\x18\x0f\x14\n\x0c\n\x05\x06\0\x02\ - \0\x03\x12\x03\x18\x1f$\n\r\n\x05\x06\0\x02\0\x04\x12\x04\x19\x08\x1c\n\ - \n\x10\n\x08\x06\0\x02\0\x04\xe7\x07\0\x12\x04\x19\x08\x1c\n\n\x10\n\t\ - \x06\0\x02\0\x04\xe7\x07\0\x02\x12\x03\x19\x0f\x20\n\x11\n\n\x06\0\x02\0\ - \x04\xe7\x07\0\x02\0\x12\x03\x19\x0f\x20\n\x12\n\x0b\x06\0\x02\0\x04\xe7\ - \x07\0\x02\0\x01\x12\x03\x19\x10\x1f\n\x11\n\t\x06\0\x02\0\x04\xe7\x07\0\ - \x08\x12\x04\x19#\x1c\t\n9\n\x04\x06\0\x02\x01\x12\x04\x1f\x04$\x05\x1a+\ - \x20Call\x20when\x20the\x20GameServer\x20is\x20shutting\x20down\n\n\x0c\ - \n\x05\x06\0\x02\x01\x01\x12\x03\x1f\x08\x10\n\x0c\n\x05\x06\0\x02\x01\ - \x02\x12\x03\x1f\x12\x17\n\x0c\n\x05\x06\0\x02\x01\x03\x12\x03\x1f\"'\n\ - \r\n\x05\x06\0\x02\x01\x04\x12\x04\x20\x08#\n\n\x10\n\x08\x06\0\x02\x01\ - \x04\xe7\x07\0\x12\x04\x20\x08#\n\n\x10\n\t\x06\0\x02\x01\x04\xe7\x07\0\ - \x02\x12\x03\x20\x0f\x20\n\x11\n\n\x06\0\x02\x01\x04\xe7\x07\0\x02\0\x12\ - \x03\x20\x0f\x20\n\x12\n\x0b\x06\0\x02\x01\x04\xe7\x07\0\x02\0\x01\x12\ - \x03\x20\x10\x1f\n\x11\n\t\x06\0\x02\x01\x04\xe7\x07\0\x08\x12\x04\x20##\ - \t\nW\n\x04\x06\0\x02\x02\x12\x04&\x04+\x05\x1aI\x20Send\x20a\x20Empty\ - \x20every\x20d\x20Duration\x20to\x20declare\x20that\x20this\x20GameSever\ - \x20is\x20healthy\n\n\x0c\n\x05\x06\0\x02\x02\x01\x12\x03&\x08\x0e\n\x0c\ - \n\x05\x06\0\x02\x02\x05\x12\x03&\x10\x16\n\x0c\n\x05\x06\0\x02\x02\x02\ - \x12\x03&\x17\x1c\n\x0c\n\x05\x06\0\x02\x02\x03\x12\x03&',\n\r\n\x05\x06\ - \0\x02\x02\x04\x12\x04'\x08*\x12\n\x10\n\x08\x06\0\x02\x02\x04\xe7\x07\0\ - \x12\x04'\x08*\x12\n\x10\n\t\x06\0\x02\x02\x04\xe7\x07\0\x02\x12\x03'\ - \x0f\x20\n\x11\n\n\x06\0\x02\x02\x04\xe7\x07\0\x02\0\x12\x03'\x0f\x20\n\ - \x12\n\x0b\x06\0\x02\x02\x04\xe7\x07\0\x02\0\x01\x12\x03'\x10\x1f\n\x11\ - \n\t\x06\0\x02\x02\x04\xe7\x07\0\x08\x12\x04'#*\x11\n4\n\x04\x06\0\x02\ - \x03\x12\x04-\x041\x05\x1a&\x20Retrieve\x20the\x20current\x20GameServer\ - \x20data\n\n\x0c\n\x05\x06\0\x02\x03\x01\x12\x03-\x08\x15\n\x0c\n\x05\ - \x06\0\x02\x03\x02\x12\x03-\x17\x1c\n\x0c\n\x05\x06\0\x02\x03\x03\x12\ - \x03-'1\n\r\n\x05\x06\0\x02\x03\x04\x12\x04.\x080\n\n\x10\n\x08\x06\0\ - \x02\x03\x04\xe7\x07\0\x12\x04.\x080\n\n\x10\n\t\x06\0\x02\x03\x04\xe7\ - \x07\0\x02\x12\x03.\x0f\x20\n\x11\n\n\x06\0\x02\x03\x04\xe7\x07\0\x02\0\ - \x12\x03.\x0f\x20\n\x12\n\x0b\x06\0\x02\x03\x04\xe7\x07\0\x02\0\x01\x12\ - \x03.\x10\x1f\n\x11\n\t\x06\0\x02\x03\x04\xe7\x07\0\x08\x12\x04.#0\t\nJ\ - \n\x04\x06\0\x02\x04\x12\x043\x047\x05\x1a<\x20Send\x20GameServer\x20det\ - ails\x20whenever\x20the\x20GameServer\x20is\x20updated\n\n\x0c\n\x05\x06\ - \0\x02\x04\x01\x12\x033\x08\x17\n\x0c\n\x05\x06\0\x02\x04\x02\x12\x033\ - \x19\x1e\n\x0c\n\x05\x06\0\x02\x04\x06\x12\x033)/\n\x0c\n\x05\x06\0\x02\ - \x04\x03\x12\x0330:\n\r\n\x05\x06\0\x02\x04\x04\x12\x044\x086\n\n\x10\n\ - \x08\x06\0\x02\x04\x04\xe7\x07\0\x12\x044\x086\n\n\x10\n\t\x06\0\x02\x04\ - \x04\xe7\x07\0\x02\x12\x034\x0f\x20\n\x11\n\n\x06\0\x02\x04\x04\xe7\x07\ - \0\x02\0\x12\x034\x0f\x20\n\x12\n\x0b\x06\0\x02\x04\x04\xe7\x07\0\x02\0\ - \x01\x12\x034\x10\x1f\n\x11\n\t\x06\0\x02\x04\x04\xe7\x07\0\x08\x12\x044\ - #6\t\n\n\n\x02\x04\0\x12\x04:\0;\x01\n\n\n\x03\x04\0\x01\x12\x03:\x08\r\ - \n\xa2\x01\n\x02\x04\x01\x12\x04@\0i\x01\x1a\x95\x01\x20A\x20GameServer\ + .proto\"\x07\n\x05Empty\"2\n\x08KeyValue\x12\x10\n\x03key\x18\x01\x20\ + \x01(\tR\x03key\x12\x14\n\x05value\x18\x02\x20\x01(\tR\x05value\"\xae\t\ + \n\nGameServer\x12M\n\x0bobject_meta\x18\x01\x20\x01(\x0b2,.stable.agone\ + s.dev.sdk.GameServer.ObjectMetaR\nobjectMeta\x12:\n\x04spec\x18\x02\x20\ + \x01(\x0b2&.stable.agones.dev.sdk.GameServer.SpecR\x04spec\x12@\n\x06sta\ + tus\x18\x03\x20\x01(\x0b2(.stable.agones.dev.sdk.GameServer.StatusR\x06s\ + tatus\x1a\xa7\x04\n\nObjectMeta\x12\x12\n\x04name\x18\x01\x20\x01(\tR\ + \x04name\x12\x1c\n\tnamespace\x18\x02\x20\x01(\tR\tnamespace\x12\x10\n\ + \x03uid\x18\x03\x20\x01(\tR\x03uid\x12)\n\x10resource_version\x18\x04\ + \x20\x01(\tR\x0fresourceVersion\x12\x1e\n\ngeneration\x18\x05\x20\x01(\ + \x03R\ngeneration\x12-\n\x12creation_timestamp\x18\x06\x20\x01(\x03R\x11\ + creationTimestamp\x12-\n\x12deletion_timestamp\x18\x07\x20\x01(\x03R\x11\ + deletionTimestamp\x12_\n\x0bannotations\x18\x08\x20\x03(\x0b2=.stable.ag\ + ones.dev.sdk.GameServer.ObjectMeta.AnnotationsEntryR\x0bannotations\x12P\ + \n\x06labels\x18\t\x20\x03(\x0b28.stable.agones.dev.sdk.GameServer.Objec\ + tMeta.LabelsEntryR\x06labels\x1a>\n\x10AnnotationsEntry\x12\x10\n\x03key\ + \x18\x01\x20\x01(\tR\x03key\x12\x14\n\x05value\x18\x02\x20\x01(\tR\x05va\ + lue:\x028\x01\x1a9\n\x0bLabelsEntry\x12\x10\n\x03key\x18\x01\x20\x01(\tR\ + \x03key\x12\x14\n\x05value\x18\x02\x20\x01(\tR\x05value:\x028\x01\x1a\ + \xf8\x01\n\x04Spec\x12E\n\x06health\x18\x01\x20\x01(\x0b2-.stable.agones\ + .dev.sdk.GameServer.Spec.HealthR\x06health\x1a\xa8\x01\n\x06Health\x12\ + \x1a\n\x08Disabled\x18\x01\x20\x01(\x08R\x08Disabled\x12$\n\rPeriodSecon\ + ds\x18\x02\x20\x01(\x05R\rPeriodSeconds\x12*\n\x10FailureThreshold\x18\ + \x03\x20\x01(\x05R\x10FailureThreshold\x120\n\x13InitialDelaySeconds\x18\ + \x04\x20\x01(\x05R\x13InitialDelaySeconds\x1a\xad\x01\n\x06Status\x12\ + \x14\n\x05state\x18\x01\x20\x01(\tR\x05state\x12\x18\n\x07address\x18\ + \x02\x20\x01(\tR\x07address\x12C\n\x05ports\x18\x03\x20\x03(\x0b2-.stabl\ + e.agones.dev.sdk.GameServer.Status.PortR\x05ports\x1a.\n\x04Port\x12\x12\ + \n\x04name\x18\x01\x20\x01(\tR\x04name\x12\x12\n\x04port\x18\x02\x20\x01\ + (\x05R\x04port2\xc7\x05\n\x03SDK\x12V\n\x05Ready\x12\x1c.stable.agones.d\ + ev.sdk.Empty\x1a\x1c.stable.agones.dev.sdk.Empty\"\x11\x82\xd3\xe4\x93\ + \x02\x0b\"\x06/ready:\x01*\x12\\\n\x08Shutdown\x12\x1c.stable.agones.dev\ + .sdk.Empty\x1a\x1c.stable.agones.dev.sdk.Empty\"\x14\x82\xd3\xe4\x93\x02\ + \x0e\"\t/shutdown:\x01*\x12Z\n\x06Health\x12\x1c.stable.agones.dev.sdk.E\ + mpty\x1a\x1c.stable.agones.dev.sdk.Empty\"\x12\x82\xd3\xe4\x93\x02\x0c\"\ + \x07/health:\x01*(\x01\x12e\n\rGetGameServer\x12\x1c.stable.agones.dev.s\ + dk.Empty\x1a!.stable.agones.dev.sdk.GameServer\"\x13\x82\xd3\xe4\x93\x02\ + \r\x12\x0b/gameserver\x12o\n\x0fWatchGameServer\x12\x1c.stable.agones.de\ + v.sdk.Empty\x1a!.stable.agones.dev.sdk.GameServer\"\x19\x82\xd3\xe4\x93\ + \x02\x13\x12\x11/watch/gameserver0\x01\x12e\n\x08SetLabel\x12\x1f.stable\ + .agones.dev.sdk.KeyValue\x1a\x1c.stable.agones.dev.sdk.Empty\"\x1a\x82\ + \xd3\xe4\x93\x02\x14\x1a\x0f/metadata/label:\x01*\x12o\n\rSetAnnotation\ + \x12\x1f.stable.agones.dev.sdk.KeyValue\x1a\x1c.stable.agones.dev.sdk.Em\ + pty\"\x1f\x82\xd3\xe4\x93\x02\x19\x1a\x14/metadata/annotation:\x01*B\x05\ + Z\x03sdkJ\xee%\n\x07\x12\x05\x0e\0\x80\x01\x01\n\xd2\x04\n\x01\x0c\x12\ + \x03\x0e\0\x122\xc7\x04\x20Copyright\x202017\x20Google\x20Inc.\x20All\ + \x20Rights\x20Reserved.\n\n\x20Licensed\x20under\x20the\x20Apache\x20Lic\ + ense,\x20Version\x202.0\x20(the\x20\"License\");\n\x20you\x20may\x20not\ + \x20use\x20this\x20file\x20except\x20in\x20compliance\x20with\x20the\x20\ + License.\n\x20You\x20may\x20obtain\x20a\x20copy\x20of\x20the\x20License\ + \x20at\n\n\x20\x20\x20\x20\x20http://www.apache.org/licenses/LICENSE-2.0\ + \n\n\x20Unless\x20required\x20by\x20applicable\x20law\x20or\x20agreed\ + \x20to\x20in\x20writing,\x20software\n\x20distributed\x20under\x20the\ + \x20License\x20is\x20distributed\x20on\x20an\x20\"AS\x20IS\"\x20BASIS,\n\ + \x20WITHOUT\x20WARRANTIES\x20OR\x20CONDITIONS\x20OF\x20ANY\x20KIND,\x20e\ + ither\x20express\x20or\x20implied.\n\x20See\x20the\x20License\x20for\x20\ + the\x20specific\x20language\x20governing\x20permissions\x20and\n\x20limi\ + tations\x20under\x20the\x20License.\n\n\x08\n\x01\x02\x12\x03\x10\x08\ + \x1d\n\x08\n\x01\x08\x12\x03\x11\0\x1a\n\x0b\n\x04\x08\xe7\x07\0\x12\x03\ + \x11\0\x1a\n\x0c\n\x05\x08\xe7\x07\0\x02\x12\x03\x11\x07\x11\n\r\n\x06\ + \x08\xe7\x07\0\x02\0\x12\x03\x11\x07\x11\n\x0e\n\x07\x08\xe7\x07\0\x02\0\ + \x01\x12\x03\x11\x07\x11\n\x0c\n\x05\x08\xe7\x07\0\x07\x12\x03\x11\x14\ + \x19\n\t\n\x02\x03\0\x12\x03\x13\x07%\nM\n\x02\x06\0\x12\x04\x16\0H\x01\ + \x1aA\x20SDK\x20service\x20to\x20be\x20used\x20in\x20the\x20GameServer\ + \x20SDK\x20to\x20the\x20Pod\x20Sidecar\n\n\n\n\x03\x06\0\x01\x12\x03\x16\ + \x08\x0b\n1\n\x04\x06\0\x02\0\x12\x04\x18\x04\x1d\x05\x1a#\x20Call\x20wh\ + en\x20the\x20GameServer\x20is\x20ready\n\n\x0c\n\x05\x06\0\x02\0\x01\x12\ + \x03\x18\x08\r\n\x0c\n\x05\x06\0\x02\0\x02\x12\x03\x18\x0f\x14\n\x0c\n\ + \x05\x06\0\x02\0\x03\x12\x03\x18\x1f$\n\r\n\x05\x06\0\x02\0\x04\x12\x04\ + \x19\x08\x1c\n\n\x10\n\x08\x06\0\x02\0\x04\xe7\x07\0\x12\x04\x19\x08\x1c\ + \n\n\x10\n\t\x06\0\x02\0\x04\xe7\x07\0\x02\x12\x03\x19\x0f\x20\n\x11\n\n\ + \x06\0\x02\0\x04\xe7\x07\0\x02\0\x12\x03\x19\x0f\x20\n\x12\n\x0b\x06\0\ + \x02\0\x04\xe7\x07\0\x02\0\x01\x12\x03\x19\x10\x1f\n\x11\n\t\x06\0\x02\0\ + \x04\xe7\x07\0\x08\x12\x04\x19#\x1c\t\n9\n\x04\x06\0\x02\x01\x12\x04\x1f\ + \x04$\x05\x1a+\x20Call\x20when\x20the\x20GameServer\x20is\x20shutting\ + \x20down\n\n\x0c\n\x05\x06\0\x02\x01\x01\x12\x03\x1f\x08\x10\n\x0c\n\x05\ + \x06\0\x02\x01\x02\x12\x03\x1f\x12\x17\n\x0c\n\x05\x06\0\x02\x01\x03\x12\ + \x03\x1f\"'\n\r\n\x05\x06\0\x02\x01\x04\x12\x04\x20\x08#\n\n\x10\n\x08\ + \x06\0\x02\x01\x04\xe7\x07\0\x12\x04\x20\x08#\n\n\x10\n\t\x06\0\x02\x01\ + \x04\xe7\x07\0\x02\x12\x03\x20\x0f\x20\n\x11\n\n\x06\0\x02\x01\x04\xe7\ + \x07\0\x02\0\x12\x03\x20\x0f\x20\n\x12\n\x0b\x06\0\x02\x01\x04\xe7\x07\0\ + \x02\0\x01\x12\x03\x20\x10\x1f\n\x11\n\t\x06\0\x02\x01\x04\xe7\x07\0\x08\ + \x12\x04\x20##\t\nW\n\x04\x06\0\x02\x02\x12\x04&\x04+\x05\x1aI\x20Send\ + \x20a\x20Empty\x20every\x20d\x20Duration\x20to\x20declare\x20that\x20thi\ + s\x20GameSever\x20is\x20healthy\n\n\x0c\n\x05\x06\0\x02\x02\x01\x12\x03&\ + \x08\x0e\n\x0c\n\x05\x06\0\x02\x02\x05\x12\x03&\x10\x16\n\x0c\n\x05\x06\ + \0\x02\x02\x02\x12\x03&\x17\x1c\n\x0c\n\x05\x06\0\x02\x02\x03\x12\x03&',\ + \n\r\n\x05\x06\0\x02\x02\x04\x12\x04'\x08*\x12\n\x10\n\x08\x06\0\x02\x02\ + \x04\xe7\x07\0\x12\x04'\x08*\x12\n\x10\n\t\x06\0\x02\x02\x04\xe7\x07\0\ + \x02\x12\x03'\x0f\x20\n\x11\n\n\x06\0\x02\x02\x04\xe7\x07\0\x02\0\x12\ + \x03'\x0f\x20\n\x12\n\x0b\x06\0\x02\x02\x04\xe7\x07\0\x02\0\x01\x12\x03'\ + \x10\x1f\n\x11\n\t\x06\0\x02\x02\x04\xe7\x07\0\x08\x12\x04'#*\x11\n4\n\ + \x04\x06\0\x02\x03\x12\x04-\x041\x05\x1a&\x20Retrieve\x20the\x20current\ + \x20GameServer\x20data\n\n\x0c\n\x05\x06\0\x02\x03\x01\x12\x03-\x08\x15\ + \n\x0c\n\x05\x06\0\x02\x03\x02\x12\x03-\x17\x1c\n\x0c\n\x05\x06\0\x02\ + \x03\x03\x12\x03-'1\n\r\n\x05\x06\0\x02\x03\x04\x12\x04.\x080\n\n\x10\n\ + \x08\x06\0\x02\x03\x04\xe7\x07\0\x12\x04.\x080\n\n\x10\n\t\x06\0\x02\x03\ + \x04\xe7\x07\0\x02\x12\x03.\x0f\x20\n\x11\n\n\x06\0\x02\x03\x04\xe7\x07\ + \0\x02\0\x12\x03.\x0f\x20\n\x12\n\x0b\x06\0\x02\x03\x04\xe7\x07\0\x02\0\ + \x01\x12\x03.\x10\x1f\n\x11\n\t\x06\0\x02\x03\x04\xe7\x07\0\x08\x12\x04.\ + #0\t\nJ\n\x04\x06\0\x02\x04\x12\x043\x047\x05\x1a<\x20Send\x20GameServer\ + \x20details\x20whenever\x20the\x20GameServer\x20is\x20updated\n\n\x0c\n\ + \x05\x06\0\x02\x04\x01\x12\x033\x08\x17\n\x0c\n\x05\x06\0\x02\x04\x02\ + \x12\x033\x19\x1e\n\x0c\n\x05\x06\0\x02\x04\x06\x12\x033)/\n\x0c\n\x05\ + \x06\0\x02\x04\x03\x12\x0330:\n\r\n\x05\x06\0\x02\x04\x04\x12\x044\x086\ + \n\n\x10\n\x08\x06\0\x02\x04\x04\xe7\x07\0\x12\x044\x086\n\n\x10\n\t\x06\ + \0\x02\x04\x04\xe7\x07\0\x02\x12\x034\x0f\x20\n\x11\n\n\x06\0\x02\x04\ + \x04\xe7\x07\0\x02\0\x12\x034\x0f\x20\n\x12\n\x0b\x06\0\x02\x04\x04\xe7\ + \x07\0\x02\0\x01\x12\x034\x10\x1f\n\x11\n\t\x06\0\x02\x04\x04\xe7\x07\0\ + \x08\x12\x044#6\t\n@\n\x04\x06\0\x02\x05\x12\x04:\x04?\x05\x1a2\x20Apply\ + \x20a\x20Label\x20to\x20the\x20backing\x20GameServer\x20metadata\n\n\x0c\ + \n\x05\x06\0\x02\x05\x01\x12\x03:\x08\x10\n\x0c\n\x05\x06\0\x02\x05\x02\ + \x12\x03:\x11\x19\n\x0c\n\x05\x06\0\x02\x05\x03\x12\x03:$)\n\r\n\x05\x06\ + \0\x02\x05\x04\x12\x04;\x08>\x12\n\x10\n\x08\x06\0\x02\x05\x04\xe7\x07\0\ + \x12\x04;\x08>\x12\n\x10\n\t\x06\0\x02\x05\x04\xe7\x07\0\x02\x12\x03;\ + \x0f\x20\n\x11\n\n\x06\0\x02\x05\x04\xe7\x07\0\x02\0\x12\x03;\x0f\x20\n\ + \x12\n\x0b\x06\0\x02\x05\x04\xe7\x07\0\x02\0\x01\x12\x03;\x10\x1f\n\x11\ + \n\t\x06\0\x02\x05\x04\xe7\x07\0\x08\x12\x04;#>\x11\nE\n\x04\x06\0\x02\ + \x06\x12\x04B\x04G\x05\x1a7\x20Apply\x20a\x20Annotation\x20to\x20the\x20\ + backing\x20GameServer\x20metadata\n\n\x0c\n\x05\x06\0\x02\x06\x01\x12\ + \x03B\x08\x15\n\x0c\n\x05\x06\0\x02\x06\x02\x12\x03B\x16\x1e\n\x0c\n\x05\ + \x06\0\x02\x06\x03\x12\x03B).\n\r\n\x05\x06\0\x02\x06\x04\x12\x04C\x08F\ + \x12\n\x10\n\x08\x06\0\x02\x06\x04\xe7\x07\0\x12\x04C\x08F\x12\n\x10\n\t\ + \x06\0\x02\x06\x04\xe7\x07\0\x02\x12\x03C\x0f\x20\n\x11\n\n\x06\0\x02\ + \x06\x04\xe7\x07\0\x02\0\x12\x03C\x0f\x20\n\x12\n\x0b\x06\0\x02\x06\x04\ + \xe7\x07\0\x02\0\x01\x12\x03C\x10\x1f\n\x11\n\t\x06\0\x02\x06\x04\xe7\ + \x07\0\x08\x12\x04C#F\x11\n\x18\n\x02\x04\0\x12\x04K\0L\x01\x1a\x0c\x20I\ + \x20am\x20Empty\n\n\n\n\x03\x04\0\x01\x12\x03K\x08\r\n\x1e\n\x02\x04\x01\ + \x12\x04O\0R\x01\x1a\x12\x20Key,\x20Value\x20entry\n\n\n\n\x03\x04\x01\ + \x01\x12\x03O\x08\x10\n\x0b\n\x04\x04\x01\x02\0\x12\x03P\x04\x13\n\r\n\ + \x05\x04\x01\x02\0\x04\x12\x04P\x04O\x12\n\x0c\n\x05\x04\x01\x02\0\x05\ + \x12\x03P\x04\n\n\x0c\n\x05\x04\x01\x02\0\x01\x12\x03P\x0b\x0e\n\x0c\n\ + \x05\x04\x01\x02\0\x03\x12\x03P\x11\x12\n\x0b\n\x04\x04\x01\x02\x01\x12\ + \x03Q\x04\x15\n\r\n\x05\x04\x01\x02\x01\x04\x12\x04Q\x04P\x13\n\x0c\n\ + \x05\x04\x01\x02\x01\x05\x12\x03Q\x04\n\n\x0c\n\x05\x04\x01\x02\x01\x01\ + \x12\x03Q\x0b\x10\n\x0c\n\x05\x04\x01\x02\x01\x03\x12\x03Q\x13\x14\n\xa3\ + \x01\n\x02\x04\x02\x12\x05W\0\x80\x01\x01\x1a\x95\x01\x20A\x20GameServer\ \x20Custom\x20Resource\x20Definition\x20object\n\x20We\x20will\x20only\ \x20export\x20those\x20resources\x20that\x20make\x20the\x20most\n\x20sen\ se.\x20Can\x20always\x20expand\x20to\x20more\x20as\x20needed.\n\n\n\n\ - \x03\x04\x01\x01\x12\x03@\x08\x12\n\x0b\n\x04\x04\x01\x02\0\x12\x03A\x04\ - \x1f\n\r\n\x05\x04\x01\x02\0\x04\x12\x04A\x04@\x14\n\x0c\n\x05\x04\x01\ - \x02\0\x06\x12\x03A\x04\x0e\n\x0c\n\x05\x04\x01\x02\0\x01\x12\x03A\x0f\ - \x1a\n\x0c\n\x05\x04\x01\x02\0\x03\x12\x03A\x1d\x1e\n\x0b\n\x04\x04\x01\ - \x02\x01\x12\x03B\x04\x12\n\r\n\x05\x04\x01\x02\x01\x04\x12\x04B\x04A\ - \x1f\n\x0c\n\x05\x04\x01\x02\x01\x06\x12\x03B\x04\x08\n\x0c\n\x05\x04\ - \x01\x02\x01\x01\x12\x03B\t\r\n\x0c\n\x05\x04\x01\x02\x01\x03\x12\x03B\ - \x10\x11\n\x0b\n\x04\x04\x01\x02\x02\x12\x03C\x04\x16\n\r\n\x05\x04\x01\ - \x02\x02\x04\x12\x04C\x04B\x12\n\x0c\n\x05\x04\x01\x02\x02\x06\x12\x03C\ - \x04\n\n\x0c\n\x05\x04\x01\x02\x02\x01\x12\x03C\x0b\x11\n\x0c\n\x05\x04\ - \x01\x02\x02\x03\x12\x03C\x14\x15\n=\n\x04\x04\x01\x03\0\x12\x04F\x04R\ + \x03\x04\x02\x01\x12\x03W\x08\x12\n\x0b\n\x04\x04\x02\x02\0\x12\x03X\x04\ + \x1f\n\r\n\x05\x04\x02\x02\0\x04\x12\x04X\x04W\x14\n\x0c\n\x05\x04\x02\ + \x02\0\x06\x12\x03X\x04\x0e\n\x0c\n\x05\x04\x02\x02\0\x01\x12\x03X\x0f\ + \x1a\n\x0c\n\x05\x04\x02\x02\0\x03\x12\x03X\x1d\x1e\n\x0b\n\x04\x04\x02\ + \x02\x01\x12\x03Y\x04\x12\n\r\n\x05\x04\x02\x02\x01\x04\x12\x04Y\x04X\ + \x1f\n\x0c\n\x05\x04\x02\x02\x01\x06\x12\x03Y\x04\x08\n\x0c\n\x05\x04\ + \x02\x02\x01\x01\x12\x03Y\t\r\n\x0c\n\x05\x04\x02\x02\x01\x03\x12\x03Y\ + \x10\x11\n\x0b\n\x04\x04\x02\x02\x02\x12\x03Z\x04\x16\n\r\n\x05\x04\x02\ + \x02\x02\x04\x12\x04Z\x04Y\x12\n\x0c\n\x05\x04\x02\x02\x02\x06\x12\x03Z\ + \x04\n\n\x0c\n\x05\x04\x02\x02\x02\x01\x12\x03Z\x0b\x11\n\x0c\n\x05\x04\ + \x02\x02\x02\x03\x12\x03Z\x14\x15\n=\n\x04\x04\x02\x03\0\x12\x04]\x04i\ \x05\x1a/\x20representation\x20of\x20the\x20K8s\x20ObjectMeta\x20resourc\ - e\n\n\x0c\n\x05\x04\x01\x03\0\x01\x12\x03F\x0c\x16\n\r\n\x06\x04\x01\x03\ - \0\x02\0\x12\x03G\x08\x18\n\x0f\n\x07\x04\x01\x03\0\x02\0\x04\x12\x04G\ - \x08F\x18\n\x0e\n\x07\x04\x01\x03\0\x02\0\x05\x12\x03G\x08\x0e\n\x0e\n\ - \x07\x04\x01\x03\0\x02\0\x01\x12\x03G\x0f\x13\n\x0e\n\x07\x04\x01\x03\0\ - \x02\0\x03\x12\x03G\x16\x17\n\r\n\x06\x04\x01\x03\0\x02\x01\x12\x03H\x08\ - \x1d\n\x0f\n\x07\x04\x01\x03\0\x02\x01\x04\x12\x04H\x08G\x18\n\x0e\n\x07\ - \x04\x01\x03\0\x02\x01\x05\x12\x03H\x08\x0e\n\x0e\n\x07\x04\x01\x03\0\ - \x02\x01\x01\x12\x03H\x0f\x18\n\x0e\n\x07\x04\x01\x03\0\x02\x01\x03\x12\ - \x03H\x1b\x1c\n\r\n\x06\x04\x01\x03\0\x02\x02\x12\x03I\x08\x17\n\x0f\n\ - \x07\x04\x01\x03\0\x02\x02\x04\x12\x04I\x08H\x1d\n\x0e\n\x07\x04\x01\x03\ - \0\x02\x02\x05\x12\x03I\x08\x0e\n\x0e\n\x07\x04\x01\x03\0\x02\x02\x01\ - \x12\x03I\x0f\x12\n\x0e\n\x07\x04\x01\x03\0\x02\x02\x03\x12\x03I\x15\x16\ - \n\r\n\x06\x04\x01\x03\0\x02\x03\x12\x03J\x08$\n\x0f\n\x07\x04\x01\x03\0\ - \x02\x03\x04\x12\x04J\x08I\x17\n\x0e\n\x07\x04\x01\x03\0\x02\x03\x05\x12\ - \x03J\x08\x0e\n\x0e\n\x07\x04\x01\x03\0\x02\x03\x01\x12\x03J\x0f\x1f\n\ - \x0e\n\x07\x04\x01\x03\0\x02\x03\x03\x12\x03J\"#\n\r\n\x06\x04\x01\x03\0\ - \x02\x04\x12\x03K\x08\x1d\n\x0f\n\x07\x04\x01\x03\0\x02\x04\x04\x12\x04K\ - \x08J$\n\x0e\n\x07\x04\x01\x03\0\x02\x04\x05\x12\x03K\x08\r\n\x0e\n\x07\ - \x04\x01\x03\0\x02\x04\x01\x12\x03K\x0e\x18\n\x0e\n\x07\x04\x01\x03\0\ - \x02\x04\x03\x12\x03K\x1b\x1c\n<\n\x06\x04\x01\x03\0\x02\x05\x12\x03M\ + e\n\n\x0c\n\x05\x04\x02\x03\0\x01\x12\x03]\x0c\x16\n\r\n\x06\x04\x02\x03\ + \0\x02\0\x12\x03^\x08\x18\n\x0f\n\x07\x04\x02\x03\0\x02\0\x04\x12\x04^\ + \x08]\x18\n\x0e\n\x07\x04\x02\x03\0\x02\0\x05\x12\x03^\x08\x0e\n\x0e\n\ + \x07\x04\x02\x03\0\x02\0\x01\x12\x03^\x0f\x13\n\x0e\n\x07\x04\x02\x03\0\ + \x02\0\x03\x12\x03^\x16\x17\n\r\n\x06\x04\x02\x03\0\x02\x01\x12\x03_\x08\ + \x1d\n\x0f\n\x07\x04\x02\x03\0\x02\x01\x04\x12\x04_\x08^\x18\n\x0e\n\x07\ + \x04\x02\x03\0\x02\x01\x05\x12\x03_\x08\x0e\n\x0e\n\x07\x04\x02\x03\0\ + \x02\x01\x01\x12\x03_\x0f\x18\n\x0e\n\x07\x04\x02\x03\0\x02\x01\x03\x12\ + \x03_\x1b\x1c\n\r\n\x06\x04\x02\x03\0\x02\x02\x12\x03`\x08\x17\n\x0f\n\ + \x07\x04\x02\x03\0\x02\x02\x04\x12\x04`\x08_\x1d\n\x0e\n\x07\x04\x02\x03\ + \0\x02\x02\x05\x12\x03`\x08\x0e\n\x0e\n\x07\x04\x02\x03\0\x02\x02\x01\ + \x12\x03`\x0f\x12\n\x0e\n\x07\x04\x02\x03\0\x02\x02\x03\x12\x03`\x15\x16\ + \n\r\n\x06\x04\x02\x03\0\x02\x03\x12\x03a\x08$\n\x0f\n\x07\x04\x02\x03\0\ + \x02\x03\x04\x12\x04a\x08`\x17\n\x0e\n\x07\x04\x02\x03\0\x02\x03\x05\x12\ + \x03a\x08\x0e\n\x0e\n\x07\x04\x02\x03\0\x02\x03\x01\x12\x03a\x0f\x1f\n\ + \x0e\n\x07\x04\x02\x03\0\x02\x03\x03\x12\x03a\"#\n\r\n\x06\x04\x02\x03\0\ + \x02\x04\x12\x03b\x08\x1d\n\x0f\n\x07\x04\x02\x03\0\x02\x04\x04\x12\x04b\ + \x08a$\n\x0e\n\x07\x04\x02\x03\0\x02\x04\x05\x12\x03b\x08\r\n\x0e\n\x07\ + \x04\x02\x03\0\x02\x04\x01\x12\x03b\x0e\x18\n\x0e\n\x07\x04\x02\x03\0\ + \x02\x04\x03\x12\x03b\x1b\x1c\n<\n\x06\x04\x02\x03\0\x02\x05\x12\x03d\ \x08%\x1a-\x20timestamp\x20is\x20in\x20Epoch\x20format,\x20unit:\x20seco\ - nds\n\n\x0f\n\x07\x04\x01\x03\0\x02\x05\x04\x12\x04M\x08K\x1d\n\x0e\n\ - \x07\x04\x01\x03\0\x02\x05\x05\x12\x03M\x08\r\n\x0e\n\x07\x04\x01\x03\0\ - \x02\x05\x01\x12\x03M\x0e\x20\n\x0e\n\x07\x04\x01\x03\0\x02\x05\x03\x12\ - \x03M#$\nK\n\x06\x04\x01\x03\0\x02\x06\x12\x03O\x08%\x1a<\x20optional\ + nds\n\n\x0f\n\x07\x04\x02\x03\0\x02\x05\x04\x12\x04d\x08b\x1d\n\x0e\n\ + \x07\x04\x02\x03\0\x02\x05\x05\x12\x03d\x08\r\n\x0e\n\x07\x04\x02\x03\0\ + \x02\x05\x01\x12\x03d\x0e\x20\n\x0e\n\x07\x04\x02\x03\0\x02\x05\x03\x12\ + \x03d#$\nK\n\x06\x04\x02\x03\0\x02\x06\x12\x03f\x08%\x1a<\x20optional\ \x20deletion\x20timestamp\x20in\x20Epoch\x20format,\x20unit:\x20seconds\ - \n\n\x0f\n\x07\x04\x01\x03\0\x02\x06\x04\x12\x04O\x08M%\n\x0e\n\x07\x04\ - \x01\x03\0\x02\x06\x05\x12\x03O\x08\r\n\x0e\n\x07\x04\x01\x03\0\x02\x06\ - \x01\x12\x03O\x0e\x20\n\x0e\n\x07\x04\x01\x03\0\x02\x06\x03\x12\x03O#$\n\ - \r\n\x06\x04\x01\x03\0\x02\x07\x12\x03P\x08,\n\x0f\n\x07\x04\x01\x03\0\ - \x02\x07\x04\x12\x04P\x08O%\n\x0e\n\x07\x04\x01\x03\0\x02\x07\x06\x12\ - \x03P\x08\x1b\n\x0e\n\x07\x04\x01\x03\0\x02\x07\x01\x12\x03P\x1c'\n\x0e\ - \n\x07\x04\x01\x03\0\x02\x07\x03\x12\x03P*+\n\r\n\x06\x04\x01\x03\0\x02\ - \x08\x12\x03Q\x08'\n\x0f\n\x07\x04\x01\x03\0\x02\x08\x04\x12\x04Q\x08P,\ - \n\x0e\n\x07\x04\x01\x03\0\x02\x08\x06\x12\x03Q\x08\x1b\n\x0e\n\x07\x04\ - \x01\x03\0\x02\x08\x01\x12\x03Q\x1c\"\n\x0e\n\x07\x04\x01\x03\0\x02\x08\ - \x03\x12\x03Q%&\n\x0c\n\x04\x04\x01\x03\x01\x12\x04T\x04]\x05\n\x0c\n\ - \x05\x04\x01\x03\x01\x01\x12\x03T\x0c\x10\n\r\n\x06\x04\x01\x03\x01\x02\ - \0\x12\x03U\x08\x1a\n\x0f\n\x07\x04\x01\x03\x01\x02\0\x04\x12\x04U\x08T\ - \x12\n\x0e\n\x07\x04\x01\x03\x01\x02\0\x06\x12\x03U\x08\x0e\n\x0e\n\x07\ - \x04\x01\x03\x01\x02\0\x01\x12\x03U\x0f\x15\n\x0e\n\x07\x04\x01\x03\x01\ - \x02\0\x03\x12\x03U\x18\x19\n\x0e\n\x06\x04\x01\x03\x01\x03\0\x12\x04W\ - \x08\\\t\n\x0e\n\x07\x04\x01\x03\x01\x03\0\x01\x12\x03W\x10\x16\n\x0f\n\ - \x08\x04\x01\x03\x01\x03\0\x02\0\x12\x03X\x0c\x1e\n\x11\n\t\x04\x01\x03\ - \x01\x03\0\x02\0\x04\x12\x04X\x0cW\x18\n\x10\n\t\x04\x01\x03\x01\x03\0\ - \x02\0\x05\x12\x03X\x0c\x10\n\x10\n\t\x04\x01\x03\x01\x03\0\x02\0\x01\ - \x12\x03X\x11\x19\n\x10\n\t\x04\x01\x03\x01\x03\0\x02\0\x03\x12\x03X\x1c\ - \x1d\n\x0f\n\x08\x04\x01\x03\x01\x03\0\x02\x01\x12\x03Y\x0c$\n\x11\n\t\ - \x04\x01\x03\x01\x03\0\x02\x01\x04\x12\x04Y\x0cX\x1e\n\x10\n\t\x04\x01\ - \x03\x01\x03\0\x02\x01\x05\x12\x03Y\x0c\x11\n\x10\n\t\x04\x01\x03\x01\ - \x03\0\x02\x01\x01\x12\x03Y\x12\x1f\n\x10\n\t\x04\x01\x03\x01\x03\0\x02\ - \x01\x03\x12\x03Y\"#\n\x0f\n\x08\x04\x01\x03\x01\x03\0\x02\x02\x12\x03Z\ - \x0c'\n\x11\n\t\x04\x01\x03\x01\x03\0\x02\x02\x04\x12\x04Z\x0cY$\n\x10\n\ - \t\x04\x01\x03\x01\x03\0\x02\x02\x05\x12\x03Z\x0c\x11\n\x10\n\t\x04\x01\ - \x03\x01\x03\0\x02\x02\x01\x12\x03Z\x12\"\n\x10\n\t\x04\x01\x03\x01\x03\ - \0\x02\x02\x03\x12\x03Z%&\n\x0f\n\x08\x04\x01\x03\x01\x03\0\x02\x03\x12\ - \x03[\x0c*\n\x11\n\t\x04\x01\x03\x01\x03\0\x02\x03\x04\x12\x04[\x0cZ'\n\ - \x10\n\t\x04\x01\x03\x01\x03\0\x02\x03\x05\x12\x03[\x0c\x11\n\x10\n\t\ - \x04\x01\x03\x01\x03\0\x02\x03\x01\x12\x03[\x12%\n\x10\n\t\x04\x01\x03\ - \x01\x03\0\x02\x03\x03\x12\x03[()\n\x0c\n\x04\x04\x01\x03\x02\x12\x04_\ - \x04h\x05\n\x0c\n\x05\x04\x01\x03\x02\x01\x12\x03_\x0c\x12\n\x0e\n\x06\ - \x04\x01\x03\x02\x03\0\x12\x04`\x08c\t\n\x0e\n\x07\x04\x01\x03\x02\x03\0\ - \x01\x12\x03`\x10\x14\n\x0f\n\x08\x04\x01\x03\x02\x03\0\x02\0\x12\x03a\ - \x0c\x1c\n\x11\n\t\x04\x01\x03\x02\x03\0\x02\0\x04\x12\x04a\x0c`\x16\n\ - \x10\n\t\x04\x01\x03\x02\x03\0\x02\0\x05\x12\x03a\x0c\x12\n\x10\n\t\x04\ - \x01\x03\x02\x03\0\x02\0\x01\x12\x03a\x13\x17\n\x10\n\t\x04\x01\x03\x02\ - \x03\0\x02\0\x03\x12\x03a\x1a\x1b\n\x0f\n\x08\x04\x01\x03\x02\x03\0\x02\ - \x01\x12\x03b\x0c\x1b\n\x11\n\t\x04\x01\x03\x02\x03\0\x02\x01\x04\x12\ - \x04b\x0ca\x1c\n\x10\n\t\x04\x01\x03\x02\x03\0\x02\x01\x05\x12\x03b\x0c\ - \x11\n\x10\n\t\x04\x01\x03\x02\x03\0\x02\x01\x01\x12\x03b\x12\x16\n\x10\ - \n\t\x04\x01\x03\x02\x03\0\x02\x01\x03\x12\x03b\x19\x1a\n\r\n\x06\x04\ - \x01\x03\x02\x02\0\x12\x03e\x08\x19\n\x0f\n\x07\x04\x01\x03\x02\x02\0\ - \x04\x12\x04e\x08c\t\n\x0e\n\x07\x04\x01\x03\x02\x02\0\x05\x12\x03e\x08\ - \x0e\n\x0e\n\x07\x04\x01\x03\x02\x02\0\x01\x12\x03e\x0f\x14\n\x0e\n\x07\ - \x04\x01\x03\x02\x02\0\x03\x12\x03e\x17\x18\n\r\n\x06\x04\x01\x03\x02\ - \x02\x01\x12\x03f\x08\x1b\n\x0f\n\x07\x04\x01\x03\x02\x02\x01\x04\x12\ - \x04f\x08e\x19\n\x0e\n\x07\x04\x01\x03\x02\x02\x01\x05\x12\x03f\x08\x0e\ - \n\x0e\n\x07\x04\x01\x03\x02\x02\x01\x01\x12\x03f\x0f\x16\n\x0e\n\x07\ - \x04\x01\x03\x02\x02\x01\x03\x12\x03f\x19\x1a\n\r\n\x06\x04\x01\x03\x02\ - \x02\x02\x12\x03g\x08\x20\n\x0e\n\x07\x04\x01\x03\x02\x02\x02\x04\x12\ - \x03g\x08\x10\n\x0e\n\x07\x04\x01\x03\x02\x02\x02\x06\x12\x03g\x11\x15\n\ - \x0e\n\x07\x04\x01\x03\x02\x02\x02\x01\x12\x03g\x16\x1b\n\x0e\n\x07\x04\ - \x01\x03\x02\x02\x02\x03\x12\x03g\x1e\x1fb\x06proto3\ + \n\n\x0f\n\x07\x04\x02\x03\0\x02\x06\x04\x12\x04f\x08d%\n\x0e\n\x07\x04\ + \x02\x03\0\x02\x06\x05\x12\x03f\x08\r\n\x0e\n\x07\x04\x02\x03\0\x02\x06\ + \x01\x12\x03f\x0e\x20\n\x0e\n\x07\x04\x02\x03\0\x02\x06\x03\x12\x03f#$\n\ + \r\n\x06\x04\x02\x03\0\x02\x07\x12\x03g\x08,\n\x0f\n\x07\x04\x02\x03\0\ + \x02\x07\x04\x12\x04g\x08f%\n\x0e\n\x07\x04\x02\x03\0\x02\x07\x06\x12\ + \x03g\x08\x1b\n\x0e\n\x07\x04\x02\x03\0\x02\x07\x01\x12\x03g\x1c'\n\x0e\ + \n\x07\x04\x02\x03\0\x02\x07\x03\x12\x03g*+\n\r\n\x06\x04\x02\x03\0\x02\ + \x08\x12\x03h\x08'\n\x0f\n\x07\x04\x02\x03\0\x02\x08\x04\x12\x04h\x08g,\ + \n\x0e\n\x07\x04\x02\x03\0\x02\x08\x06\x12\x03h\x08\x1b\n\x0e\n\x07\x04\ + \x02\x03\0\x02\x08\x01\x12\x03h\x1c\"\n\x0e\n\x07\x04\x02\x03\0\x02\x08\ + \x03\x12\x03h%&\n\x0c\n\x04\x04\x02\x03\x01\x12\x04k\x04t\x05\n\x0c\n\ + \x05\x04\x02\x03\x01\x01\x12\x03k\x0c\x10\n\r\n\x06\x04\x02\x03\x01\x02\ + \0\x12\x03l\x08\x1a\n\x0f\n\x07\x04\x02\x03\x01\x02\0\x04\x12\x04l\x08k\ + \x12\n\x0e\n\x07\x04\x02\x03\x01\x02\0\x06\x12\x03l\x08\x0e\n\x0e\n\x07\ + \x04\x02\x03\x01\x02\0\x01\x12\x03l\x0f\x15\n\x0e\n\x07\x04\x02\x03\x01\ + \x02\0\x03\x12\x03l\x18\x19\n\x0e\n\x06\x04\x02\x03\x01\x03\0\x12\x04n\ + \x08s\t\n\x0e\n\x07\x04\x02\x03\x01\x03\0\x01\x12\x03n\x10\x16\n\x0f\n\ + \x08\x04\x02\x03\x01\x03\0\x02\0\x12\x03o\x0c\x1e\n\x11\n\t\x04\x02\x03\ + \x01\x03\0\x02\0\x04\x12\x04o\x0cn\x18\n\x10\n\t\x04\x02\x03\x01\x03\0\ + \x02\0\x05\x12\x03o\x0c\x10\n\x10\n\t\x04\x02\x03\x01\x03\0\x02\0\x01\ + \x12\x03o\x11\x19\n\x10\n\t\x04\x02\x03\x01\x03\0\x02\0\x03\x12\x03o\x1c\ + \x1d\n\x0f\n\x08\x04\x02\x03\x01\x03\0\x02\x01\x12\x03p\x0c$\n\x11\n\t\ + \x04\x02\x03\x01\x03\0\x02\x01\x04\x12\x04p\x0co\x1e\n\x10\n\t\x04\x02\ + \x03\x01\x03\0\x02\x01\x05\x12\x03p\x0c\x11\n\x10\n\t\x04\x02\x03\x01\ + \x03\0\x02\x01\x01\x12\x03p\x12\x1f\n\x10\n\t\x04\x02\x03\x01\x03\0\x02\ + \x01\x03\x12\x03p\"#\n\x0f\n\x08\x04\x02\x03\x01\x03\0\x02\x02\x12\x03q\ + \x0c'\n\x11\n\t\x04\x02\x03\x01\x03\0\x02\x02\x04\x12\x04q\x0cp$\n\x10\n\ + \t\x04\x02\x03\x01\x03\0\x02\x02\x05\x12\x03q\x0c\x11\n\x10\n\t\x04\x02\ + \x03\x01\x03\0\x02\x02\x01\x12\x03q\x12\"\n\x10\n\t\x04\x02\x03\x01\x03\ + \0\x02\x02\x03\x12\x03q%&\n\x0f\n\x08\x04\x02\x03\x01\x03\0\x02\x03\x12\ + \x03r\x0c*\n\x11\n\t\x04\x02\x03\x01\x03\0\x02\x03\x04\x12\x04r\x0cq'\n\ + \x10\n\t\x04\x02\x03\x01\x03\0\x02\x03\x05\x12\x03r\x0c\x11\n\x10\n\t\ + \x04\x02\x03\x01\x03\0\x02\x03\x01\x12\x03r\x12%\n\x10\n\t\x04\x02\x03\ + \x01\x03\0\x02\x03\x03\x12\x03r()\n\x0c\n\x04\x04\x02\x03\x02\x12\x04v\ + \x04\x7f\x05\n\x0c\n\x05\x04\x02\x03\x02\x01\x12\x03v\x0c\x12\n\x0e\n\ + \x06\x04\x02\x03\x02\x03\0\x12\x04w\x08z\t\n\x0e\n\x07\x04\x02\x03\x02\ + \x03\0\x01\x12\x03w\x10\x14\n\x0f\n\x08\x04\x02\x03\x02\x03\0\x02\0\x12\ + \x03x\x0c\x1c\n\x11\n\t\x04\x02\x03\x02\x03\0\x02\0\x04\x12\x04x\x0cw\ + \x16\n\x10\n\t\x04\x02\x03\x02\x03\0\x02\0\x05\x12\x03x\x0c\x12\n\x10\n\ + \t\x04\x02\x03\x02\x03\0\x02\0\x01\x12\x03x\x13\x17\n\x10\n\t\x04\x02\ + \x03\x02\x03\0\x02\0\x03\x12\x03x\x1a\x1b\n\x0f\n\x08\x04\x02\x03\x02\ + \x03\0\x02\x01\x12\x03y\x0c\x1b\n\x11\n\t\x04\x02\x03\x02\x03\0\x02\x01\ + \x04\x12\x04y\x0cx\x1c\n\x10\n\t\x04\x02\x03\x02\x03\0\x02\x01\x05\x12\ + \x03y\x0c\x11\n\x10\n\t\x04\x02\x03\x02\x03\0\x02\x01\x01\x12\x03y\x12\ + \x16\n\x10\n\t\x04\x02\x03\x02\x03\0\x02\x01\x03\x12\x03y\x19\x1a\n\r\n\ + \x06\x04\x02\x03\x02\x02\0\x12\x03|\x08\x19\n\x0f\n\x07\x04\x02\x03\x02\ + \x02\0\x04\x12\x04|\x08z\t\n\x0e\n\x07\x04\x02\x03\x02\x02\0\x05\x12\x03\ + |\x08\x0e\n\x0e\n\x07\x04\x02\x03\x02\x02\0\x01\x12\x03|\x0f\x14\n\x0e\n\ + \x07\x04\x02\x03\x02\x02\0\x03\x12\x03|\x17\x18\n\r\n\x06\x04\x02\x03\ + \x02\x02\x01\x12\x03}\x08\x1b\n\x0f\n\x07\x04\x02\x03\x02\x02\x01\x04\ + \x12\x04}\x08|\x19\n\x0e\n\x07\x04\x02\x03\x02\x02\x01\x05\x12\x03}\x08\ + \x0e\n\x0e\n\x07\x04\x02\x03\x02\x02\x01\x01\x12\x03}\x0f\x16\n\x0e\n\ + \x07\x04\x02\x03\x02\x02\x01\x03\x12\x03}\x19\x1a\n\r\n\x06\x04\x02\x03\ + \x02\x02\x02\x12\x03~\x08\x20\n\x0e\n\x07\x04\x02\x03\x02\x02\x02\x04\ + \x12\x03~\x08\x10\n\x0e\n\x07\x04\x02\x03\x02\x02\x02\x06\x12\x03~\x11\ + \x15\n\x0e\n\x07\x04\x02\x03\x02\x02\x02\x01\x12\x03~\x16\x1b\n\x0e\n\ + \x07\x04\x02\x03\x02\x02\x02\x03\x12\x03~\x1e\x1fb\x06proto3\ "; static mut file_descriptor_proto_lazy: ::protobuf::lazy::Lazy<::protobuf::descriptor::FileDescriptorProto> = ::protobuf::lazy::Lazy { diff --git a/sdks/rust/src/grpc/sdk_grpc.rs b/sdks/rust/src/grpc/sdk_grpc.rs index c349f091ab..ebd63f7e3c 100644 --- a/sdks/rust/src/grpc/sdk_grpc.rs +++ b/sdks/rust/src/grpc/sdk_grpc.rs @@ -68,6 +68,20 @@ const METHOD_SDK_WATCH_GAME_SERVER: ::grpcio::Method = ::grpcio::Method { + ty: ::grpcio::MethodType::Unary, + name: "/stable.agones.dev.sdk.SDK/SetLabel", + req_mar: ::grpcio::Marshaller { ser: ::grpcio::pb_ser, de: ::grpcio::pb_de }, + resp_mar: ::grpcio::Marshaller { ser: ::grpcio::pb_ser, de: ::grpcio::pb_de }, +}; + +const METHOD_SDK_SET_ANNOTATION: ::grpcio::Method = ::grpcio::Method { + ty: ::grpcio::MethodType::Unary, + name: "/stable.agones.dev.sdk.SDK/SetAnnotation", + req_mar: ::grpcio::Marshaller { ser: ::grpcio::pb_ser, de: ::grpcio::pb_de }, + resp_mar: ::grpcio::Marshaller { ser: ::grpcio::pb_ser, de: ::grpcio::pb_de }, +}; + pub struct SdkClient { client: ::grpcio::Client, } @@ -142,6 +156,38 @@ impl SdkClient { pub fn watch_game_server(&self, req: &super::sdk::Empty) -> ::grpcio::Result<::grpcio::ClientSStreamReceiver> { self.watch_game_server_opt(req, ::grpcio::CallOption::default()) } + + pub fn set_label_opt(&self, req: &super::sdk::KeyValue, opt: ::grpcio::CallOption) -> ::grpcio::Result { + self.client.unary_call(&METHOD_SDK_SET_LABEL, req, opt) + } + + pub fn set_label(&self, req: &super::sdk::KeyValue) -> ::grpcio::Result { + self.set_label_opt(req, ::grpcio::CallOption::default()) + } + + pub fn set_label_async_opt(&self, req: &super::sdk::KeyValue, opt: ::grpcio::CallOption) -> ::grpcio::Result<::grpcio::ClientUnaryReceiver> { + self.client.unary_call_async(&METHOD_SDK_SET_LABEL, req, opt) + } + + pub fn set_label_async(&self, req: &super::sdk::KeyValue) -> ::grpcio::Result<::grpcio::ClientUnaryReceiver> { + self.set_label_async_opt(req, ::grpcio::CallOption::default()) + } + + pub fn set_annotation_opt(&self, req: &super::sdk::KeyValue, opt: ::grpcio::CallOption) -> ::grpcio::Result { + self.client.unary_call(&METHOD_SDK_SET_ANNOTATION, req, opt) + } + + pub fn set_annotation(&self, req: &super::sdk::KeyValue) -> ::grpcio::Result { + self.set_annotation_opt(req, ::grpcio::CallOption::default()) + } + + pub fn set_annotation_async_opt(&self, req: &super::sdk::KeyValue, opt: ::grpcio::CallOption) -> ::grpcio::Result<::grpcio::ClientUnaryReceiver> { + self.client.unary_call_async(&METHOD_SDK_SET_ANNOTATION, req, opt) + } + + pub fn set_annotation_async(&self, req: &super::sdk::KeyValue) -> ::grpcio::Result<::grpcio::ClientUnaryReceiver> { + self.set_annotation_async_opt(req, ::grpcio::CallOption::default()) + } pub fn spawn(&self, f: F) where F: ::futures::Future + Send + 'static { self.client.spawn(f) } @@ -153,6 +199,8 @@ pub trait Sdk { fn health(&self, ctx: ::grpcio::RpcContext, stream: ::grpcio::RequestStream, sink: ::grpcio::ClientStreamingSink); fn get_game_server(&self, ctx: ::grpcio::RpcContext, req: super::sdk::Empty, sink: ::grpcio::UnarySink); fn watch_game_server(&self, ctx: ::grpcio::RpcContext, req: super::sdk::Empty, sink: ::grpcio::ServerStreamingSink); + fn set_label(&self, ctx: ::grpcio::RpcContext, req: super::sdk::KeyValue, sink: ::grpcio::UnarySink); + fn set_annotation(&self, ctx: ::grpcio::RpcContext, req: super::sdk::KeyValue, sink: ::grpcio::UnarySink); } pub fn create_sdk(s: S) -> ::grpcio::Service { @@ -177,5 +225,13 @@ pub fn create_sdk(s: S) -> ::grpcio::Service { builder = builder.add_server_streaming_handler(&METHOD_SDK_WATCH_GAME_SERVER, move |ctx, req, resp| { instance.watch_game_server(ctx, req, resp) }); + let instance = s.clone(); + builder = builder.add_unary_handler(&METHOD_SDK_SET_LABEL, move |ctx, req, resp| { + instance.set_label(ctx, req, resp) + }); + let instance = s.clone(); + builder = builder.add_unary_handler(&METHOD_SDK_SET_ANNOTATION, move |ctx, req, resp| { + instance.set_annotation(ctx, req, resp) + }); builder.build() } diff --git a/test/e2e/framework/framework.go b/test/e2e/framework/framework.go index 1f78929e33..0c4706464e 100644 --- a/test/e2e/framework/framework.go +++ b/test/e2e/framework/framework.go @@ -30,6 +30,7 @@ import ( // required to use gcloud login see: https://github.com/kubernetes/client-go/issues/242 _ "k8s.io/client-go/plugin/pkg/client/auth/gcp" "k8s.io/client-go/tools/clientcmd" + "github.com/sirupsen/logrus" ) // Framework is a testing framework @@ -70,6 +71,8 @@ func (f *Framework) CreateGameServerAndWaitUntilReady(ns string, gs *v1alpha1.Ga return nil, fmt.Errorf("creating %v GameServer instances failed (%v): %v", gs.Spec, gs.Name, err) } + logrus.WithField("name", newGs.ObjectMeta.Name).Info("GameServer created, waiting for Ready") + readyGs, err := f.WaitForGameServerState(newGs, v1alpha1.Ready, 5*time.Minute) if err != nil { diff --git a/test/e2e/gameserver_test.go b/test/e2e/gameserver_test.go index 12d5171193..9c2b4e3bfa 100644 --- a/test/e2e/gameserver_test.go +++ b/test/e2e/gameserver_test.go @@ -17,36 +17,21 @@ package e2e import ( "fmt" "testing" + "time" "agones.dev/agones/pkg/apis/stable/v1alpha1" e2eframework "agones.dev/agones/test/e2e/framework" "github.com/stretchr/testify/assert" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/util/wait" ) const defaultNs = "default" func TestCreateConnect(t *testing.T) { t.Parallel() - gs := &v1alpha1.GameServer{ObjectMeta: metav1.ObjectMeta{GenerateName: "udp-server", Namespace: defaultNs}, - Spec: v1alpha1.GameServerSpec{ - Container: "udp-server", - Ports: []v1alpha1.GameServerPort{v1alpha1.GameServerPort{ - ContainerPort: 7654, - Name: "gameport", - PortPolicy: v1alpha1.Dynamic, - Protocol: corev1.ProtocolUDP, - }}, - Template: corev1.PodTemplateSpec{ - Spec: corev1.PodSpec{ - Containers: []corev1.Container{{ - Name: "udp-server", - Image: framework.GameServerImage}}, - }, - }, - }, - } + gs := defaultGameServer() readyGs, err := framework.CreateGameServerAndWaitUntilReady(defaultNs, gs) if err != nil { @@ -67,3 +52,87 @@ func TestCreateConnect(t *testing.T) { assert.Equal(t, reply, "ACK: Hello World !\n") } + +func TestSDKSetLabel(t *testing.T) { + t.Parallel() + gs := defaultGameServer() + readyGs, err := framework.CreateGameServerAndWaitUntilReady(defaultNs, gs) + if err != nil { + t.Fatalf("Could not get a GameServer ready: %v", err) + } + + assert.Equal(t, readyGs.Status.State, v1alpha1.Ready) + reply, err := e2eframework.PingGameServer("LABEL", fmt.Sprintf("%s:%d", readyGs.Status.Address, + readyGs.Status.Ports[0].Port)) + + if err != nil { + t.Fatalf("Could ping GameServer: %v", err) + } + + assert.Equal(t, "ACK: LABEL\n", reply) + + // the label is set in a queue, so it may take a moment + err = wait.PollImmediate(time.Second, 10*time.Second, func() (bool, error) { + gs, err = framework.AgonesClient.StableV1alpha1().GameServers(defaultNs).Get(readyGs.ObjectMeta.Name, metav1.GetOptions{}) + if err != nil { + return true, err + } + return gs.ObjectMeta.Labels != nil, nil + }) + + assert.Nil(t, err) + assert.NotEmpty(t, gs.ObjectMeta.Labels["stable.agones.dev/sdk-timestamp"]) +} + +func TestSDKSetAnnotation(t *testing.T) { + t.Parallel() + gs := defaultGameServer() + readyGs, err := framework.CreateGameServerAndWaitUntilReady(defaultNs, gs) + if err != nil { + t.Fatalf("Could not get a GameServer ready: %v", err) + } + + assert.Equal(t, readyGs.Status.State, v1alpha1.Ready) + reply, err := e2eframework.PingGameServer("ANNOTATION", fmt.Sprintf("%s:%d", readyGs.Status.Address, + readyGs.Status.Ports[0].Port)) + + if err != nil { + t.Fatalf("Could ping GameServer: %v", err) + } + + assert.Equal(t, "ACK: ANNOTATION\n", reply) + + // the label is set in a queue, so it may take a moment + err = wait.PollImmediate(time.Second, 10*time.Second, func() (bool, error) { + gs, err = framework.AgonesClient.StableV1alpha1().GameServers(defaultNs).Get(readyGs.ObjectMeta.Name, metav1.GetOptions{}) + if err != nil { + return true, err + } + return gs.ObjectMeta.Annotations != nil, nil + }) + + assert.Nil(t, err) + assert.NotEmpty(t, gs.ObjectMeta.Annotations["stable.agones.dev/sdk-timestamp"]) +} + +func defaultGameServer() *v1alpha1.GameServer { + return &v1alpha1.GameServer{ObjectMeta: metav1.ObjectMeta{GenerateName: "udp-server", Namespace: defaultNs}, + Spec: v1alpha1.GameServerSpec{ + Container: "udp-server", + Ports: []v1alpha1.GameServerPort{{ + ContainerPort: 7654, + Name: "gameport", + PortPolicy: v1alpha1.Dynamic, + Protocol: corev1.ProtocolUDP, + }}, + Template: corev1.PodTemplateSpec{ + Spec: corev1.PodSpec{ + Containers: []corev1.Container{{ + Name: "udp-server", + Image: framework.GameServerImage, + ImagePullPolicy: corev1.PullAlways}}, + }, + }, + }, + } +} diff --git a/test/e2e/main_test.go b/test/e2e/main_test.go index df04334bd1..c06d085bfd 100644 --- a/test/e2e/main_test.go +++ b/test/e2e/main_test.go @@ -31,8 +31,8 @@ func TestMain(m *testing.M) { usr, _ := user.Current() kubeconfig := flag.String("kubeconfig", filepath.Join(usr.HomeDir, "/.kube/config"), "kube config path, e.g. $HOME/.kube/config") - gsimage := flag.String("gameserver-image", "gcr.io/agones-images/cpp-simple-server:0.2", - "gameserver image to use for those tests, gcr.io/agones-images/cpp-simple-server:0.2") + gsimage := flag.String("gameserver-image", "gcr.io/agones-images/udp-server:0.3", + "gameserver image to use for those tests, gcr.io/agones-images/udp-server:0.3") flag.Parse()