Skip to content

Commit

Permalink
C++ SDK implementation, example and doc
Browse files Browse the repository at this point in the history
This includes a very basic "server" that
integrates with the SDK to show how it works
as well as expansion of the SDK docs to explain
how they work.

This also includes working the SDK code gen
and compilation (on linux at least) into the
main build process as well.

Closes #7
  • Loading branch information
markmandel committed Dec 22, 2017
1 parent dd27d28 commit 506eebf
Show file tree
Hide file tree
Showing 21 changed files with 1,430 additions and 47 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,4 @@
!.gitignore
*.iml
bin
*.o
19 changes: 10 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,12 @@
Agon is a library for running dedicated game servers on [Kubernetes](https://kubernetes.io).

## Disclaimer
This software is currenty alpha, and subject to change. Not to be used in production systems.
This software is currently alpha, and subject to change. Not to be used in production systems.

## Roadmap for 0.1 release
- Develop a [Custom Resource Defintion](https://kubernetes.io/docs/concepts/api-extension/custom-resources/#customresourcedefinitions) for dedicated game server
- Sidecar for managing the DGS lifecycle and recorded status, e.g. registering the port the server has started on
- A Kubernetes operator that registers the CRD, and creates a Pod with the DGS in it, with the accompanying sidecar for system registration.
- A basic client library for integration with a DGS
- Simple example code
- Documentation of the above
## Major Features
- Be able to define a `GameServer` within Kubernetes - either through yaml or the via API
- Manage GameServer lifecycles - including health checking and connection information.
- Client SDKs for integration with dedicated game servers to work with Agon.

## Requirements
- Requires a Kubernetes cluster of version 1.8+
Expand All @@ -26,10 +23,14 @@ and edit to match your settings.
_Note:_ There has yet to be a release of Agon, so you will need to edit the `install.yaml` to specify a
development release or [build from source](build/README.md)

## Game Server SDKs
Game Servers are required to have the [Agon SDK](sdks) integrated, to help manage Game Server state, health checking
and more.

## Usage
See the [examples](./examples) directory

## Development
## Development and Contribution
See the tools in the [build](build/README.md) directory for testing and building Agon from source.

## Licence
Expand Down
31 changes: 20 additions & 11 deletions build/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,13 @@ go_version_flags = -ldflags "-X github.com/agonio/agon/pkg.Version=$(VERSION)"
# |___/

# build all
build: build-gameservers-controller-image build-gameservers-sidecar-image
build: build-images build-sdks

# build the docker images
build-images: build-gameservers-controller-image build-gameservers-sidecar-image

#build all the sdks
build-sdks: build-sdk-cpp

# Run all tests
test: ensure-image
Expand Down Expand Up @@ -105,13 +111,18 @@ build-gameservers-sidecar-binary: ensure-image
build-gameservers-sidecar-image: ensure-image build-gameservers-sidecar-binary
docker build $(agon_path)/gameservers/sidecar/ --tag=$(sidecar_tag)

# Build the cpp sdk linux archive
build-sdk-cpp: ensure-image
docker run --rm $(common_mounts) -w $(mount_path)/sdks/cpp --entrypoint make $(build_tag) build install archive

# push the gameservers sidecar image
push-gameservers-sidecar-image: ensure-image
docker push $(sidecar_tag)

# Generate the sidecar gRPC code
gen-gameservers-sidecar-grpc: ensure-image
# Generate the SDK gRPC server and client code
gen-gameservers-sdk-grpc: ensure-image
docker run --rm $(common_mounts) --entrypoint="/root/gen-grpc-go.sh" $(build_tag)
docker run --rm $(common_mounts) --entrypoint="/root/gen-grpc-cpp.sh" $(build_tag)

# Generate the client for our CustomResourceDefinition
gen-crd-client: ensure-image
Expand All @@ -137,14 +148,12 @@ godoc:
docker run -p 8888:8888 --rm $(common_mounts) -v $(build_path)/.index:/root/.index \
--entrypoint=godoc $(build_tag) -http=":8888" -index=true -index_files=/root/.index

.PHONY: build-image

# Creates the build docker image
build-image:
build-build-image:
docker build --tag=$(build_tag) $(build_path)/build-image

# Deletes the local build docker image
clean-image:
clean-build-image:
docker rmi $(build_tag)

ensure-config:
Expand All @@ -154,7 +163,7 @@ ensure-config:
ensure-image: ensure-config
@if [ -z $$(docker images -q $(build_tag)) ]; then\
echo "Could not find $(build_tag) image. Building...";\
$(MAKE) build-image;\
$(MAKE) build-build-image;\
fi

# Initialise the gcloud login and project configuration, if you are working with GCP
Expand All @@ -164,23 +173,23 @@ gcloud-init: ensure-config
--entrypoint="gcloud" $(build_tag) init

# Creates and authenticates a small, 3 node GKE cluster to work against
gcloud-test-cluster:
gcloud-test-cluster: ensure-image
docker run --rm -it $(common_mounts) \
--entrypoint="gcloud" $(build_tag) \
deployment-manager deployments create test-cluster --config=$(mount_path)/build/gke-test-cluster/deployment.yml
$(MAKE) gcloud-auth-cluster

# Pulls down authentication information for kubectl against a cluster, name can be specified through CLUSTER_NAME
# (defaults to 'test-cluster')
gcloud-auth-cluster:
gcloud-auth-cluster: ensure-image
docker run --rm $(common_mounts) --entrypoint="gcloud" $(build_tag) config set container/cluster $(CLUSTER_NAME)
docker run --rm $(common_mounts) --entrypoint="gcloud" $(build_tag) config set compute/zone \
`grep zone: $(build_path)/gke-test-cluster/deployment.yml | sed 's/zone: //'`
docker run --rm $(common_mounts) --entrypoint="gcloud" $(build_tag) container clusters get-credentials $(CLUSTER_NAME)

# authenticate our docker configuration so that you can do a docker push directly
# to the gcr.io repository
gcloud-auth-docker:
gcloud-auth-docker: ensure-image
-sudo rm -rf /tmp/gcloud-auth-docker
mkdir -p /tmp/gcloud-auth-docker
-cp ~/.dockercfg /tmp/gcloud-auth-docker
Expand Down
23 changes: 18 additions & 5 deletions build/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,18 @@ This is not required if you are simply building using the `make` targets
Make sure you are in the `build` directory to start.

First, let's test all the code. To do this, run `make test`, which will execute all the unit tests for the codebase.

If you haven't run any of the `build` make targets before then this will also create the build image, and then run the tests.
Building the `build-image` may take a few minutes to download all the dependencies, so feel
free to make cup of tea or coffee at this point. ☕️

The build image is only created the first time one of the make targets is executed, and will only rebuild if the build
Dockerfile has changed.

Assuming that the tests all pass, let's go ahead an compile the code and build the Docker images that Agon consists of.

To compile the code and create the Docker images run `make build`. This will compile the code and create the docker image.
To compile the code, create the Docker images, and compile and archive the sdks,
run `make build`. This will compile the code and create the docker image.
You may note that the docker image is tagged with a concatenation of the upcoming release number and short git hash
for the current commit. This has also been set in the code itself, so that it can be seen in log statements.

Expand Down Expand Up @@ -108,8 +112,17 @@ All targets will create the build image if it is not present.
Targets for developing with the build image

#### `make build`
Build all the images required for Agon, as well as the SDKs

#### `make build-images`
Build all the images required for Agon

#### `make build-sdks`
Build all the sdks required for Agon

#### `make build-sdk-cpp`
Build the cpp sdk static and dynamic libraries (linux libraries only)

#### `make test`
Run all tests

Expand All @@ -131,8 +144,8 @@ Compile the gameserver sidecar and then build the docker image
#### `make gen-crd-client`
Generate the Custom Resource Definition client(s)

#### `make gen-gameservers-sidecar-grpc`
Generate the gRPC sidecar Server and Client
#### `make gen-gameservers-sdk-grpc`
Generate the SDK gRPC server and client code

### Build Image Targets

Expand All @@ -141,10 +154,10 @@ Targets for building the build image
### `make clean-config`
Cleans the kubernetes and gcloud configurations

### `make clean-image`
### `make clean-build-image`
Deletes the local build docker image

### `make build-image`
### `make build-build-image`
Creates the build docker image

## Google Cloud Platform
Expand Down
45 changes: 23 additions & 22 deletions build/build-image/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -12,41 +12,42 @@
# See the License for the specific language governing permissions and
# limitations under the License.

FROM golang:1.9.2
# compiling proto + grpc takes an exceptionally long time
# so we'll use that as the base.
FROM grpc/cxx:1.8

RUN apt-get update && apt-get install -y wget unzip bash-completion rsync
RUN apt-get update && \
apt-get install -y wget rsync make python bash-completion && \
apt-get clean

WORKDIR /
# install go
WORKDIR /usr/local
ENV GO_VERSION=1.9.2
ENV GOPATH /go
RUN wget -q https://redirector.gvt1.com/edgedl/go/go${GO_VERSION}.linux-amd64.tar.gz && \
tar -xzf go${GO_VERSION}.linux-amd64.tar.gz && rm go${GO_VERSION}.linux-amd64.tar.gz && mkdir ${GOPATH}

# install gcloud + kubectl, because it's an easy way to test/dev against kubernetes.
RUN wget -q https://dl.google.com/dl/cloudsdk/release/google-cloud-sdk.zip && unzip -q google-cloud-sdk.zip && rm google-cloud-sdk.zip
RUN /google-cloud-sdk/install.sh --usage-reporting=true --path-update=true --bash-completion=true --rc-path=/root/.bashrc
ENV PATH /google-cloud-sdk/bin:$PATH
WORKDIR /opt
RUN wget -q https://dl.google.com/dl/cloudsdk/release/google-cloud-sdk.zip && unzip -q google-cloud-sdk.zip && \
rm google-cloud-sdk.zip && \
/opt/google-cloud-sdk/install.sh --usage-reporting=true --path-update=true --bash-completion=true --rc-path=/root/.bashrc

# update the path for both go and gcloud
ENV PATH /usr/local/go/bin:/opt/google-cloud-sdk/bin:$PATH

# RUN gcloud components update
RUN gcloud components update && gcloud components install kubectl
RUN echo "source <(kubectl completion bash)" >> /root/.bashrc

# install protoc for grpc
ENV PB_VER 3.5.0
ENV PB_URL https://github.com/google/protobuf/releases/download/v${PB_VER}/protoc-${PB_VER}-linux-x86_64.zip
RUN mkdir -p /tmp/protoc && \
curl -L ${PB_URL} > /tmp/protoc/protoc.zip && \
cd /tmp/protoc && \
unzip protoc.zip && \
cp /tmp/protoc/bin/protoc /usr/local/bin && \
cp -R /tmp/protoc/include/* /usr/local/include && \
chmod go+rx /usr/local/bin/protoc && \
cd /tmp && \
rm -r /tmp/protoc

# install go tooling for building and testing
# install go tooling for development, building and testing
RUN go get -u github.com/golang/dep/cmd/dep && \
go get -u github.com/alecthomas/gometalinter && \
go get -u github.com/golang/protobuf/protoc-gen-go && \
/go/bin/gometalinter --install

# install the release branch of the code generator tools
RUN cd /go/src && mkdir -p k8s.io && cd k8s.io && \
RUN mkdir -p /go/src && cd /go/src && mkdir -p k8s.io && cd k8s.io && \
git clone -b release-1.8 --depth=3 https://github.com/kubernetes/code-generator.git

# make sure we keep the path to go
Expand All @@ -56,4 +57,4 @@ RUN echo "export PATH=/usr/local/go/bin:/go/bin/:\$PATH" >> /root/.bashrc
COPY *.sh /root/
RUN chmod +x /root/*.sh

ENTRYPOINT kubectl
WORKDIR /go
25 changes: 25 additions & 0 deletions build/build-image/gen-grpc-cpp.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
#!/usr/bin/env bash

# Copyright 2017 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.

cd /go/src/github.com/agonio/agon
protoc -I . --grpc_out=./sdks/cpp --plugin=protoc-gen-grpc=`which grpc_cpp_plugin` sdk.proto
protoc -I . --cpp_out=./sdks/cpp sdk.proto
mkdir /tmp/cpp
ls ./sdks/cpp | xargs -I@ bash -c "cat ./build/boilerplate.go.txt ./sdks/cpp/@ >> /tmp/cpp/@"
# already has a header, so we'll remove it
rm /tmp/cpp/sdk.grpc.pb.h
mv /tmp/cpp/* ./sdks/cpp/

23 changes: 23 additions & 0 deletions examples/cpp-simple/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# Copyright 2017 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.

FROM debian:stretch
RUN useradd -m server

COPY ./bin/server-static /home/server/server-static
RUN chown -R server /home/server && \
chmod o+x /home/server/server-static

USER server
ENTRYPOINT /home/server/server-static
65 changes: 65 additions & 0 deletions examples/cpp-simple/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
# Copyright 2017 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.

#
# Makefile for building the world's simplest C++ game server
#

# __ __ _ _ _
# \ \ / /_ _ _ __(_) __ _| |__ | | ___ ___
# \ \ / / _` | '__| |/ _` | '_ \| |/ _ \ __|
# \ V / (_| | | | | (_| | |_) | | __\__ \
# \_/ \__,_|_| |_|\__,_|_.__/|_|\___|___/
#

CXX = g++
CPPFLAGS += -I/usr/local/include -pthread
CXXFLAGS += -std=c++11
LDFLAGS += -L/usr/local/lib -lagonsdk -lgrpc++_unsecure -lgrpc -lprotobuf -lpthread -ldl
REPOSITORY = gcr.io/agon-images

# Directory that this Makefile is in.
mkfile_path := $(abspath $(lastword $(MAKEFILE_LIST)))
project_path := $(dir $(mkfile_path))
server_tag = $(REPOSITORY)/cpp-simple-server:0.1

# _____ _
# |_ _|_ _ _ __ __ _ ___| |_ ___
# | |/ _` | '__/ _` |/ _ \ __/ __|
# | | (_| | | | (_| | __/ |_\__ \
# |_|\__,_|_| \__, |\___|\__|___/
# |___/

# build the library
build: ensure-bin server-dynamic server-static

# Build a docker image for the server, and tag it
build-image:
docker build $(project_path) --tag=$(server_tag)

# make the server executable
server-dynamic: server.o
$(CXX) $^ $(LDFLAGS) -o $(project_path)bin/$@

# make the server executable
server-static: server.o
$(CXX) $^ $(LDFLAGS) -o $(project_path)bin/$@ -static

# make sure the bin directory exists
ensure-bin:
-mkdir $(project_path)/bin

clean:
-rm -r $(project_path)/bin
-rm *.o
12 changes: 12 additions & 0 deletions examples/cpp-simple/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# Simple C++ Example

This is a very simple "server" that doesn't do much other than show how the SDK works in C++.

It will
- Setup the Agon SDK
- Call `SDK::Ready()` to register that it is ready with Agon.
- Every 10 seconds, write a log saying "Hi! I'm a Game Server"
- After 60 seconds, call `SDK::Shutdown()` to shut the server down.

## Building
Depends on the [`sdks/cpp`](../../sdks/cpp) SDK and its dependencies have been compiled and installed.
Loading

0 comments on commit 506eebf

Please sign in to comment.