Quibbble K8s Controller
The project allows Quibbble games to be run in a K8s cluster. Games are spun up as individual pods with their entire lifecycle handled by the Quibbble controller. This allows Quibbble to take advantage of the power of K8s, primarily the ability to scale as well as to seperate and self heal in the event of any single game failure.
Quick Start
Install NGINX
This controller currently requires the usage of NGINX to allow for dynamic routing of games. Meaning that if a game with key tictactoe
and id example
is created, then NGINX will handle the routing to that game over path /game/tictactoe/example
.
helm upgrade --install ingress-nginx ingress-nginx \
--repo https://kubernetes.github.io/ingress-nginx \
--namespace ingress-nginx --create-namespace
Install Quibbble Controller
helm upgrade --install quibbble-controller quibbble-controller \
--repo https://quibbble.github.io/quibbble-controller \
--namespace quibbble --create-namespace
Contributing
All contributions are welcome. To get started take a look at additional docs on setting up a local environment.
Supported Games
Architecture
There are three main processes in this system.
controller
- Processes game create and delete requests.
watcher
- Periodically searches for and cleans up stale games.
server
- Runs a game instance.
Flows
Game Creation
- Send
POST https://<host>/game
with some qqn
such as [key "tictactoe"][id "example"][teams "red, blue"]
.
controller
processes the request and, if valid, creates K8s ConfigMap, Pod, Service, and Ingress resources.
- Game can now be accessed at
https://<host>/game/tictactoe/example
.
Game Connection
- Join a game by connection to
wss://<host>/game/tictactoe/example?name=<name>
with websockets.
- Connection should be open to a
server
instance and relevant game messages should be recieved.
Game Cleanup
watcher
will kick off every X
timeperiod.
- Job requests data from all live games by calling
GET https://<host>/game/<key>/<id>/activity
for each game.
- If there are no connected players and no recent updates then all K8s related resources are deleted.
REST API
POST
/game
(create a game)
Parameters
name | type | data type | description |
---|
None | required | QGN | QGN descibing the game to create |
Responses
http code | content-type | response |
---|
201 | text/plain;charset=UTF-8 | Created |
400 | text/plain;charset=UTF-8 | Bad Request |
409 | text/plain;charset=UTF-8 | Conflict |
500 | text/plain;charset=UTF-8 | Internal Server Error |
503 | text/plain;charset=UTF-8 | Service Unavailable |
Example cURL
curl -X POST -H "Content-Type: application/qgn" --data @post.qgn https://api.quibbble.com/game
PUT
/game
(load a game from storage)
Parameters
name | type | data type | description |
---|
key | required | string | The name of the game i.e. tictactoe or connect4 |
id | required | string | The unique id of the game instance to join |
Responses
http code | content-type | response |
---|
200 | text/plain;charset=UTF-8 | OK |
400 | text/plain;charset=UTF-8 | Bad Request |
404 | text/plain;charset=UTF-8 | Not Found |
500 | text/plain;charset=UTF-8 | Internal Server Error |
503 | text/plain;charset=UTF-8 | Service Unavailable |
Example cURL
curl -X PUT https://api.quibbble.com/game?key={key}&id={id}
DELETE
/game?key={key}&id={id}
(delete a game)
Parameters
name | type | data type | description |
---|
key | required | string | The name of the game i.e. tictactoe or connect4 |
id | required | string | The unique id of the game instance to join |
Responses
http code | content-type | response |
---|
200 | text/plain;charset=UTF-8 | OK |
400 | text/plain;charset=UTF-8 | Bad Request |
404 | text/plain;charset=UTF-8 | Not Found |
500 | text/plain;charset=UTF-8 | Internal Server Error |
Example cURL
curl -X DELETE https://api.quibbble.com/game?key={key}&id={id}
WEBSOCKET
/game/{key}/{id}?name={name}
(connect to a game)
Parameters
name | type | data type | description |
---|
key | required | string | The name of the game i.e. tictactoe or connect4 |
id | required | string | The unique id of the game instance to join |
name | required | string | The name of the player connecting |
Responses
None
Example wscat
wscat -c wss://api.quibbble.com/game/{key}/{id}
GET
/game/{key}/{id}/snapshot?format={format}
(get game snapshot)
Parameters
name | type | data type | description |
---|
key | required | string | The name of the game i.e. tictactoe or connect4 |
id | required | string | The unique id of the game instance to join |
format | required | one of json or qgn | The type of data to return |
Responses
http code | content-type | response |
---|
200 | application/json or application/qgn | JSON or QGN |
400 | text/plain;charset=UTF-8 | Bad Request |
404 | text/plain;charset=UTF-8 | Not Found |
500 | text/plain;charset=UTF-8 | Internal Server Error |
Example cURL
curl -X GET https://api.quibbble.com/game/{key}/{id}/snapshot?format=json
GET
/game/activity
(get all games activity)
Parameters
None
Responses
http code | content-type | response |
---|
200 | application/json | Activity for all games |
500 | text/plain;charset=UTF-8 | Internal Server Error |
Example cURL
curl -X GET https://api.quibbble.com/game/activity
GET
/game/{key}/{id}/activity
(get game activity)
Parameters
name | type | data type | description |
---|
key | required | string | The name of the game i.e. tictactoe or connect4 |
id | required | string | The unique id of the game instance to join |
Responses
http code | content-type | response |
---|
200 | application/json | JSON data describing player count and last update time |
404 | text/plain;charset=UTF-8 | Not Found |
Example cURL
curl -X GET https://api.quibbble.com/game/{key}/{id}/activity
Websocket Messaging
Sendable Messages
join
(join a team)
Join
{
"type": "join",
"details": "$TEAM"
}
action
(perform a game action)
Message
{
"type": "$ACTION",
"details": {...}
}
ai
(ai plays for the current team)
Message
{
"type": "ai",
}
chat
(send a chat message)
Message
{
"type": "chat",
"details": "$MESSAGE"
}
Recievable Messages
snapshot
(retrieve a snapshot of the game)
Details
Message sent to all players on every game state change.
Message
{
"type": "snapshot",
"details": {...}
}
connection
(retrieve player connection information)
Details
Message sent to all players on every player connection, drop, or team change.
Message
{
"type": "connection",
"details": {
"$NAME1": "$TEAM1",
"$NAME2": "$TEAM2",
"$NAME3": null
}
}
chat
(retrieve chat message)
Details
Message sent to all players on every sent chat message.
Message
{
"type": "chat",
"details": {
"name": "$NAME",
"team": "$TEAM",
"message": "$MESSAGE",
}
}
error
(retrieve error message)
Details
Message sent to origin player on failed action message.
Message
{
"type": "error",
"details": "$MESSAGE"
}