Skip to content

Commit

Permalink
Support Rust SDK by gRPC-rs
Browse files Browse the repository at this point in the history
  • Loading branch information
thara authored and cyriltovena committed Jun 8, 2018
1 parent 081c186 commit 9e024d8
Show file tree
Hide file tree
Showing 19 changed files with 755 additions and 0 deletions.
1 change: 1 addition & 0 deletions build/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,7 @@ gen-install: ensure-build-image
gen-gameservers-sdk-grpc: ensure-build-image
docker run --rm $(common_mounts) -w $(mount_path) $(build_tag) /root/gen-grpc-go.sh
docker run --rm $(common_mounts) -w $(mount_path) $(build_tag) /root/gen-grpc-cpp.sh
docker run --rm $(common_mounts) -w $(mount_path) $(build_tag) /root/gen-grpc-rust.sh

# Generate the client for our CustomResourceDefinition
gen-crd-client: ensure-build-image
Expand Down
20 changes: 20 additions & 0 deletions build/build-image/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,26 @@ RUN go get -u github.com/golang/dep/cmd/dep && \
RUN mkdir -p /go/src && cd /go/src && mkdir -p k8s.io && cd k8s.io && \
git clone -b kubernetes-1.9.2 --depth=3 https://github.com/kubernetes/code-generator.git

# install rust
ENV RUSTUP_HOME=/usr/local/rustup \
CARGO_HOME=/usr/local/cargo \
PATH=/usr/local/cargo/bin:$PATH \
RUST_VERSION=1.26.1
ENV RUST_ARCH=x86_64-unknown-linux-gnu \
RUSTUP_SHA256=c9837990bce0faab4f6f52604311a19bb8d2cde989bea6a7b605c8e526db6f02
RUN wget -q https://static.rust-lang.org/rustup/archive/1.11.0/${RUST_ARCH}/rustup-init && \
echo "${RUSTUP_SHA256} *rustup-init" | sha256sum -c - && \
chmod +x rustup-init && \
./rustup-init -y --no-modify-path --default-toolchain $RUST_VERSION && \
rm rustup-init && \
rustup --version; \
cargo --version; \
rustc --version;

# install rust tooling for SDK generation
RUN cargo install protobuf-codegen --vers 2.0.2
RUN cargo install grpcio-compiler --vers 0.3.0

# make sure we keep the path to go
RUN echo "export PATH=/usr/local/go/bin:/go/bin/:\$PATH" >> /root/.bashrc
# make nano the editor
Expand Down
4 changes: 4 additions & 0 deletions build/build-image/gen-grpc-rust.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
#!/usr/bin/env bash

cd /go/src/agones.dev/agones
protoc --rust_out sdks/rust/src/grpc --grpc_out=sdks/rust/src/grpc --plugin=protoc-gen-grpc=`which grpc_rust_plugin` sdk.proto
19 changes: 19 additions & 0 deletions examples/rust-simple/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@

# Created by https://www.gitignore.io/api/rust

### Rust ###
# Generated by Cargo
# will have compiled files and executables
/target/

# Remove Cargo.lock from gitignore if creating an executable, leave it for libraries
# More information here http://doc.crates.io/guide.html#cargotoml-vs-cargolock
Cargo.lock

# These are backup files generated by rustfmt
**/*.rs.bk


# End of https://www.gitignore.io/api/rust

sdk
6 changes: 6 additions & 0 deletions examples/rust-simple/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
[package]
name = "rust-simple"
version = "0.1.0"

[dependencies]
agones = { path = "../../sdks/rust" }
50 changes: 50 additions & 0 deletions examples/rust-simple/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
FROM rust:1.25.0 as builder
RUN useradd -m build

# Rust SDK depends on https://github.com/pingcap/grpc-rs and it requires CMake and Go

## Cmake
ENV CMAKE_MINOR_VERSION=v3.10 \
CMAKE_FULL_VERSION=3.10.3
RUN mkdir -p /usr/src/cmake \
&& curl -fSLO https://cmake.org/files/${CMAKE_MINOR_VERSION}/cmake-${CMAKE_FULL_VERSION}.tar.gz \
&& curl -fSLO https://cmake.org/files/${CMAKE_MINOR_VERSION}/cmake-${CMAKE_FULL_VERSION}-SHA-256.txt \
&& sha256sum -c cmake-${CMAKE_FULL_VERSION}-SHA-256.txt 2>&1 | grep OK \
&& tar xf cmake-${CMAKE_FULL_VERSION}.tar.gz -C /usr/src/cmake --strip-components=1 \
&& rm -f cmake-${CMAKE_FULL_VERSION}.* \
&& cd /usr/src/cmake \
&& ./configure && make -j$(nproc) && make install

## Go
ENV GO_VERSION=1.10.2 \
GO_CHECKSUM=4b677d698c65370afa33757b6954ade60347aaca310ea92a63ed717d7cb0c2ff
RUN mkdir -p /usr/local/go \
&& curl -fSO https://dl.google.com/go/go${GO_VERSION}.linux-amd64.tar.gz \
&& shasum -a 256 go${GO_VERSION}.linux-amd64.tar.gz | grep ${GO_CHECKSUM} \
&& tar xf go${GO_VERSION}.linux-amd64.tar.gz -C /usr/local/go --strip-components=1 \
&& rm -f go${GO_VERSION}.linux-amd64.tar.gz
ENV PATH $PATH:/usr/local/go/bin

# SDK
COPY sdk/src /home/builder/agones/sdks/rust/src
COPY sdk/Cargo.toml /home/builder/agones/sdks/rust/
COPY sdk/Cargo.lock /home/builder/agones/sdks/rust/

# Example
COPY src /home/builder/agones/examples/rust-simple/src
COPY Cargo.toml /home/builder/agones/examples/rust-simple/
COPY Cargo.lock /home/builder/agones/examples/rust-simple/
COPY Makefile /home/builder/agones/examples/rust-simple/

WORKDIR /home/builder/agones/examples/rust-simple
RUN make build

FROM debian:stretch
RUN useradd -m server

COPY --from=builder /home/builder/agones/examples/rust-simple/target/release/rust-simple /home/server/rust-simple
RUN chown -R server /home/server && \
chmod o+x /home/server/rust-simple

USER server
ENTRYPOINT /home/server/rust-simple
40 changes: 40 additions & 0 deletions examples/rust-simple/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
#
# Makefile for building the world's simplest Rust game server
#

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

mkfile_path := $(abspath $(lastword $(MAKEFILE_LIST)))
project_path := $(dir $(mkfile_path))
server_tag = rust-simple-server:0.1

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

# build the library
build: build-server

# Build the server
build-server:
cargo build --release

# Build a docker image for the server, and tag it
build-image:
# Docker does not allow to copy outside files,
mkdir -p $(project_path)sdk
cp -rf $(project_path)../../sdks/rust/src $(project_path)sdk/src
cp -rf $(project_path)../../sdks/rust/Cargo.* $(project_path)sdk
docker build $(project_path) --tag=$(server_tag)

clean:
cargo clean
rm -rf $(project_path)sdk
34 changes: 34 additions & 0 deletions examples/rust-simple/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# Simple Rust Example

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

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

## Running by minikube

First of all, you have to configure Agones on minikude. Check out [these instructions](https://github.com/GoogleCloudPlatform/agones/blob/3b856a4b90862a3ea183643869f81801d4468220/install/README.md).

```
$ eval $(minikube docker-env)
$ make build-image
$ kubectl create -f gameserver.yaml
```

You can see output of the example by the following.

```
$ POD_NAME=`kubectl get pods -o go-template --template '{{range .items}}{{.metadata.name}}{{"\n"}}{{end}}'`
$ kubectl logs $POD_NAME -c rust-simple
Rust Game Server has started!
Creating SDK instance
Marking server as ready...
Running for 0 seconds
Health ping sent
Health ping sent
Health ping sent
Health ping sent
```
14 changes: 14 additions & 0 deletions examples/rust-simple/gameserver.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
apiVersion: "stable.agones.dev/v1alpha1"
kind: GameServer
metadata:
# generate a unique name
# will need to be created with `kubectl create`
generateName: rust-simple-
spec:
containerPort: 7654
template:
spec:
containers:
- name: rust-simple
image: gcr.io/agones-images/rust-simple-server:0.1
imagePullPolicy: IfNotPresent
68 changes: 68 additions & 0 deletions examples/rust-simple/src/main.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
extern crate agones;

use std::result::Result;
use std::thread;
use std::time::Duration;

macro_rules! enclose {
( ($( $x:ident ),*) $y:expr ) => {
{
$(let mut $x = $x.clone();)*
$y
}
};
}

fn main() {
println!("Rust Game Server has started!");

::std::process::exit(match run() {
Ok(_) => {
println!("Rust Game Server finished.");
0
},
Err(msg) => {
println!("{}", msg);
1
}
});
}

fn run() -> Result<(), String>{

println!("Creating SDK instance");
let sdk = agones::Sdk::new().map_err(|_| "Could not connect to the sidecar. Exiting!")?;

let _t = thread::spawn(enclose!{(sdk) move || {
loop {
match sdk.health() {
(s, Ok(_)) => {
println!("Health ping sent");
sdk = s;
},
(s, Err(e)) => {
println!("Health ping failed : {:?}", e);
sdk = s;
}
}
thread::sleep(Duration::from_secs(2));
}
}});

println!("Marking server as ready...");

for i in 0..10 {
let time = i * 10;
println!("Running for {} seconds", time);

thread::sleep(Duration::from_secs(10));

if i == 5 {
println!("Shutting down after 60 seconds...");
sdk.shutdown().map_err(|e| format!("Could not run Shutdown: {}. Exiting!", e))?;
println!("...marked for Shutdown");
}
}

Ok(())
}
17 changes: 17 additions & 0 deletions sdks/rust/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@

# Created by https://www.gitignore.io/api/rust

### Rust ###
# Generated by Cargo
# will have compiled files and executables
/target/

# Remove Cargo.lock from gitignore if creating an executable, leave it for libraries
# More information here http://doc.crates.io/guide.html#cargotoml-vs-cargolock
Cargo.lock

# These are backup files generated by rustfmt
**/*.rs.bk


# End of https://www.gitignore.io/api/rust
10 changes: 10 additions & 0 deletions sdks/rust/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
[package]
name = "agones"
version = "0.1.0"

[dependencies]
grpcio = "0.3.0"
grpcio-proto = "0.3.0"
protobuf = "2.0.2"
futures = "^0.1.15"
error-chain = "0.11.0"
46 changes: 46 additions & 0 deletions sdks/rust/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
# Rust Game Server Client SDK

This is the Rust version of the Agones Game Server Client SDK.
Check the [Client SDK Documentation](../) for more details on each of the SDK functions and how to run the SDK locally.

## Prerequisites

- CMake >= 3.8.0
- Rust >= 1.19.0
- Go (>=1.7)

The SDK needs the above for building to [gRPC-rs](https://github.com/pingcap/grpc-rs).

## Usage

Add this crate to `dependencies` section in your Cargo.toml.
Specify a directory where this README.md is located to the `path`.

```toml
[dependencies]
agones = { path = "../agones/sdks/rust" }
```

Add `extern crate agones` to your crate root.

To begin working with the SDK, create an instance of it. This function blocks until connection and handshake are made.

```rust
let sdk = agones::Sdk::new()?;
```

To send a [health check](../README.md#health) ping call `sdk.health()`.

```rust
if sdk.health().is_ok() {
println!("Health ping sent");
}
```

To mark that the [game session is completed](../README.md#shutdown) and the game server should be shut down call `sdk.shutdown()`.

```rust
if sdk.shutdown().is_err() {
println!("Could not run Shutdown");
}
```
13 changes: 13 additions & 0 deletions sdks/rust/src/errors.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
// Wrap in a new error
error_chain!{
foreign_links {
Grpc(::grpcio::Error);
}

errors {
HealthPingConnectionFailure(t: String) {
description("health ping connection failure"),
display("health ping connection failure: '{}'", t),
}
}
}
2 changes: 2 additions & 0 deletions sdks/rust/src/grpc/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
pub mod sdk;
pub mod sdk_grpc;
Loading

0 comments on commit 9e024d8

Please sign in to comment.