Skip to content

Commit 036cc27

Browse files
committed
jacks xonotic image
1 parent fcb90c9 commit 036cc27

16 files changed

+223
-66
lines changed

.editorconfig

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
root = true
2+
3+
[*]
4+
end_of_line = lf
5+
insert_final_newline = true

.github/workflows/publish-xonotic.yml

+41
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
name: Create and publish the Xonotic Docker image
2+
3+
on:
4+
push:
5+
branches: ["release-xonotic"]
6+
7+
env:
8+
REGISTRY: ghcr.io
9+
IMAGE_NAME: ${{ github.repository }}
10+
11+
jobs:
12+
build-and-push-image:
13+
runs-on: ubuntu-latest
14+
permissions:
15+
contents: read
16+
packages: write
17+
18+
steps:
19+
- name: Checkout repository
20+
uses: actions/checkout@v2
21+
22+
- name: Log in to the Container registry
23+
uses: docker/[email protected]
24+
with:
25+
registry: ${{ env.REGISTRY }}
26+
username: ${{ github.actor }}
27+
password: ${{ secrets.GITHUB_TOKEN }}
28+
29+
- name: Extract metadata (tags, labels) for Docker
30+
id: meta
31+
uses: docker/[email protected]
32+
with:
33+
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
34+
35+
- name: Build and push Docker image
36+
uses: docker/[email protected]
37+
with:
38+
context: ./docker-containers/xonotic/
39+
push: true
40+
tags: ${{ steps.meta.outputs.tags }}
41+
labels: ${{ steps.meta.outputs.labels }}

.gitignore

+3
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
docker-containers/xonotic/xonotic.zip
2+
docker-containers/xonotic/Xonotic*
3+
14
# Local .terraform directories
25
**/.terraform/*
36

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
Xonotic
2+
xonotic.zip
3+
./sidecar-service/venv

docker-containers/xonotic/Dockerfile

+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
FROM debian:buster-slim
2+
3+
WORKDIR /opt
4+
5+
RUN apt-get update
6+
RUN apt-get -y install python3 python3-pip
7+
8+
COPY Xonotic-clean .
9+
10+
RUN mkdir -p /opt/server && touch /opt/server/server.cfg
11+
12+
COPY sidecar-service/requirements.txt .
13+
COPY sidecar-service/sidecar-service.py .
14+
RUN pip3 install -r requirements.txt
15+
16+
EXPOSE 26000/udp
17+
EXPOSE 5001/tcp
18+
19+
ENTRYPOINT ["python3"]
20+
CMD ["-u", "sidecar-service.py"]

docker-containers/xonotic/Makefile

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
all: download clean build
2+
3+
download:
4+
./download.sh
5+
6+
clean:
7+
./clean.sh
8+
9+
build:
10+
./build.sh
11+
12+
run:
13+
./run.sh

docker-containers/xonotic/build.sh

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
#!/usr/bin/env sh
2+
3+
docker-compose build xonotic

docker-containers/xonotic/clean.sh

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
#!/usr/bin/env sh
2+
3+
echo "Copying required data..."
4+
5+
rm -rf ./Xonotic-clean
6+
mkdir -p ./Xonotic-clean/data
7+
8+
cp ./Xonotic/xonotic-linux64-dedicated ./Xonotic-clean
9+
cp ./Xonotic/data/xonotic-20170401-data.pk3 ./Xonotic-clean/data
10+
cp ./Xonotic/data/xonotic-20170401-maps.pk3 ./Xonotic-clean/data
11+
cp ./Xonotic/data/xonotic-20170401-nexcompat.pk3 ./Xonotic-clean/data
12+
13+
echo "Copied data!"
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
version: '3'
2+
3+
services:
4+
xonotic:
5+
image: xonotic:latest
6+
build: ./.
7+
ports:
8+
- "127.0.0.1:26000:26000/udp"
9+
- "127.0.0.1:5001:5001/tcp"

docker-containers/xonotic/download.sh

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
#!/usr/bin/env sh
2+
3+
FILE=xonotic.zip
4+
SHA_256_SUM=a22f7230f486c5825b55cfdadd73399c9b0fae98c9e081dd8ac76eca08359ad5
5+
6+
validate() {
7+
echo "$SHA_256_SUM $FILE" | sha256sum -c
8+
}
9+
10+
exists() {
11+
echo "$FILE exists, validating checksum"
12+
validate
13+
}
14+
15+
if [ -f "$FILE" ]; then
16+
exists
17+
else
18+
echo "$FILE does not exist, downloading..."
19+
curl https://dl.xonotic.org/xonotic-0.8.2.zip -L -o xonotic.zip
20+
exists
21+
fi

docker-containers/xonotic/run.sh

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
#!/usr/bin/env sh
2+
3+
docker-compose run xonotic
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Flask==2.*
2+
requests==2.*
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
from enum import Enum
2+
import os
3+
import subprocess
4+
from subprocess import PIPE
5+
from datetime import datetime
6+
from typing import Optional
7+
8+
import requests
9+
from flask import Flask
10+
11+
DEBUG = bool(os.environ.get("DEBUG", False))
12+
CONFIG_URL = os.environ.get(
13+
"CONFIG_URL",
14+
"https://raw.githubusercontent.com/xonotic/xonotic/master/server/server.cfg",
15+
)
16+
17+
HOST = os.environ.get("HOST", "0.0.0.0")
18+
19+
DEFAULT_PORT = 5001
20+
PORT = int(os.environ.get("PORT", DEFAULT_PORT))
21+
22+
app = Flask(__name__)
23+
process = None
24+
25+
26+
def log(message):
27+
print(f"SIDECAR: {message}")
28+
29+
30+
def get_game_pid() -> Optional[int]:
31+
try:
32+
int(subprocess.check_output(["pidof", "./xonotic-linux64-dedicated"]))
33+
except:
34+
log("Failed to get game pid, assuming not currently running")
35+
return None
36+
37+
38+
def write_config():
39+
with open("/opt/server/server.cfg", "wb") as f:
40+
f.write(requests.get(CONFIG_URL).content)
41+
42+
43+
class Response(Enum):
44+
STARTED = "started"
45+
RESTARTED = "restarted"
46+
47+
48+
def start_or_restart_game() -> Response:
49+
global process
50+
51+
def fresh():
52+
return subprocess.Popen(["./xonotic-linux64-dedicated"], stdin=PIPE)
53+
54+
if process is None:
55+
log("No process, starting initial process")
56+
process = fresh()
57+
return Response.STARTED
58+
else:
59+
log("Process already running, shutting down")
60+
process.stdin.write(str.encode("exit\n"))
61+
process.stdin.flush()
62+
process.wait(15)
63+
log("Process shutdown, starting fresh process")
64+
process = fresh()
65+
log("Fresh process started")
66+
return Response.RESTARTED
67+
68+
69+
@app.route("/")
70+
def home():
71+
global process
72+
return {"pid": process.pid, "timestamp": datetime.now().isoformat()}
73+
74+
75+
@app.route("/restart")
76+
def restart():
77+
global process
78+
response = start_or_restart_game()
79+
return {"pid": process.pid, "status": response.value}
80+
81+
82+
if __name__ == "__main__":
83+
write_config()
84+
start_or_restart_game()
85+
86+
log(f"Starting sidecar-service on {HOST}:{PORT}")
87+
app.run(debug=DEBUG, host=HOST, port=PORT)

game_container/Dockerfile

-14
This file was deleted.

game_container/requirements.txt

-6
This file was deleted.

game_container/service.py

-46
This file was deleted.

0 commit comments

Comments
 (0)