NAS-121620 / 23.10 / Add Terraria to community train (#1152)

* Add terraria to community train

* correct pod/container names

* fix probes

* add mail

* add metadata

* let update_strategy handle a single image for now
This commit is contained in:
Stavros Kois
2023-05-05 22:20:09 +03:00
committed by GitHub
parent 21a80ead62
commit cecc3414f7
18 changed files with 694 additions and 0 deletions

View File

@@ -0,0 +1,6 @@
dependencies:
- name: common
repository: file://../../../common
version: 1.0.6
digest: sha256:2f1f31c15fb7f92db141a66adbb8d23a8598727730050a3883a211763a4e5472
generated: "2023-04-21T18:31:42.509470102+03:00"

View File

@@ -0,0 +1,26 @@
name: terraria
description: Terraria is a land of adventure! A land of mystery! A land that's yours to shape, defend, and enjoy.
annotations:
title: Terraria
type: application
version: 1.0.0
apiVersion: v2
appVersion: '1.4.4.9'
kubeVersion: '>=1.16.0-0'
maintainers:
- name: truenas
url: https://www.truenas.com/
email: dev@ixsystems.com
dependencies:
- name: common
repository: file://../../../common
version: 1.0.6
home: https://terraria.org/
icon: https://static.wikia.nocookie.net/terraria_gamepedia/images/a/a4/NewPromoLogo.png/revision/latest
sources:
- https://terraria.org/
- https://github.com/truenas/charts/tree/master/community/terraria
- https://github.com/ryansheehan/terraria
keywords:
- game
- terraria

View File

@@ -0,0 +1,17 @@
# Terraria
[Terraria](https://terraria.org/) is a land of adventure! A land of mystery! A land that's yours to shape, defend, and enjoy.
This applies only for the `TShock` image.
On the first run, you have to check the logs to get the server token. You will find something like this:
```text
Login before join enabled. Users may be prompted for an account specific password instead of a server password on connect.
Login using UUID enabled. Users automatically login via UUID.
A malicious server can easily steal a user's UUID. You may consider turning this option off if you run a public server.
TShock Notice: setup-code.txt is still present, and the code located in that file will be used.
To setup the server, join the game and type /setup 424041
This token will display until disabled by verification. (/setup)
```
Join the server and run `/setup <token>`

View File

@@ -0,0 +1,17 @@
# Terraria
[Terraria](https://terraria.org/) is a land of adventure! A land of mystery! A land that's yours to shape, defend, and enjoy.
This applies only for the `TShock` image.
On the first run, you have to check the logs to get the server token. You will find something like this:
```text
Login before join enabled. Users may be prompted for an account specific password instead of a server password on connect.
Login using UUID enabled. Users automatically login via UUID.
A malicious server can easily steal a user's UUID. You may consider turning this option off if you run a public server.
TShock Notice: setup-code.txt is still present, and the code located in that file will be used.
To setup the server, join the game and type /setup 424041
This token will display until disabled by verification. (/setup)
```
Join the server and run `/setup <token>`

View File

@@ -0,0 +1,19 @@
terrariaStorage:
world:
type: hostPath
hostPath: /mnt/{{ .Release.Name }}/world
plugins:
type: hostPath
hostPath: /mnt/{{ .Release.Name }}/plugins
terrariaConfig:
worldEvil: crimson
worldSize: small
worldName: myworld
worldDifficulty: normal
maxPlayers: 8
password: ''
# Enable probes on CI runs only,
# so we can check if the container is ready
ci: true

View File

@@ -0,0 +1,19 @@
terrariaStorage:
world:
type: hostPath
hostPath: /mnt/{{ .Release.Name }}/world
plugins:
type: hostPath
hostPath: /mnt/{{ .Release.Name }}/plugins
terrariaConfig:
worldEvil: crimson
worldSize: small
worldName: myworld
worldDifficulty: normal
maxPlayers: 8
password: 'test'
# Enable probes on CI runs only,
# so we can check if the container is ready
ci: true

View File

@@ -0,0 +1,20 @@
terrariaStorage:
world:
type: hostPath
hostPath: /mnt/{{ .Release.Name }}/world
plugins:
type: hostPath
hostPath: /mnt/{{ .Release.Name }}/plugins
terrariaConfig:
imageSelector: vanillaImage
worldEvil: crimson
worldSize: small
worldName: myworld
worldDifficulty: normal
maxPlayers: 8
password: ''
# Enable probes on CI runs only,
# so we can check if the container is ready
ci: true

View File

@@ -0,0 +1,4 @@
icon_url: https://static.wikia.nocookie.net/terraria_gamepedia/images/a/a4/NewPromoLogo.png/revision/latest
categories:
- game
- terraria

View File

@@ -0,0 +1,8 @@
runAsContext:
- userName: root
groupName: root
gid: 0
uid: 0
description: Terraria runs as root user.
capabilities: []
hostMounts: []

View File

@@ -0,0 +1,316 @@
groups:
- name: Terraria Configuration
description: Configure Terraria
- name: Network Configuration
description: Configure Network for Terraria
- name: Storage Configuration
description: Configure Storage for Terraria
- name: Resources Configuration
description: Configure Resources for Terraria
questions:
- variable: terrariaConfig
label: ""
group: Terraria Configuration
schema:
type: dict
attrs:
- variable: imageSelector
label: Image Selector
description: |
Selects the image to use for the Terraria server.</br>
TShock is a fork of the Terraria server that adds a number of features.</br>
Vanilla is the original Terraria server. </br>
Only applies to newly generated worlds.
schema:
type: string
default: image
required: true
immutable: true
enum:
- value: image
description: TShock
- value: vanillaImage
description: Vanilla
- variable: worldName
label: World Name
description: |
Sets the world's name.</br>
Only applies to newly generated worlds.
schema:
type: string
default: My-World
required: true
immutable: true
- variable: worldSeed
label: World Seed
description: |
Sets the world's seed.</br>
Only applies to newly generated worlds.
schema:
type: string
default: ''
immutable: true
- variable: worldEvil
label: World's Evil
description: |
Sets the world's evil state.</br>
Only applies to newly generated worlds.
schema:
type: string
default: random
required: true
immutable: true
enum:
- value: random
description: Random
- value: corrupt
description: Corrupt
- value: crimson
description: Crimson
- variable: worldSize
label: World Size
description: |
Sets the world's size.</br>
Only applies to newly generated worlds.
schema:
type: string
default: small
required: true
immutable: true
enum:
- value: small
description: Small (1)
- value: medium
description: Medium (2)
- value: large
description: Large (3)
- variable: worldDifficulty
label: World Difficulty
description: |
Sets the world's difficulty.</br>
Only applies to newly generated worlds.
schema:
type: string
default: normal
required: true
immutable: true
enum:
- value: normal
description: Normal (0)
- value: expert
description: Expert (1)
- value: master
description: Master (2)
- value: journey
description: Journey (3)
- variable: maxPlayers
label: Maximum Players
description: Starts the server with the given player count as the maximum.
schema:
type: int
default: 8
min: 1
max: 255
required: true
- variable: password
label: Server Password
description: Sets the server password.
schema:
type: string
private: true
default: ''
- variable: secure
label: Secure Server
description: Turns on the base game's "anti-spam" feature.
schema:
type: boolean
default: false
- variable: forceUpdate
label: Force Update
description: |
Forces the server to continue running, and not hibernating when no players are on. </br>
This results in time passing, grass growing, and cpu running.
schema:
type: boolean
default: false
- variable: additionalEnvs
label: Additional Environment Variables
description: Configure additional environment variables for Terraria.
schema:
type: list
default: []
items:
- variable: env
label: Environment Variable
schema:
type: dict
attrs:
- variable: name
label: Name
schema:
type: string
required: true
- variable: value
label: Value
schema:
type: string
required: true
- variable: additionalArgs
label: Additional Arguments
description: |
Configure additional arguments for Terraria. </br>
Value is optional for flags like -heaptile </br>
For example: </br>
Key: -lang </br>
Value: en-US
schema:
type: list
default: []
items:
- variable: arg
label: Argument
schema:
type: dict
attrs:
- variable: key
label: Key
schema:
type: string
required: true
- variable: value
label: Value
schema:
type: string
- variable: terrariaNetwork
label: ""
group: Network Configuration
schema:
type: dict
attrs:
- variable: serverPort
label: Server Port
description: The port for the Terraria Server.
schema:
type: int
default: 30000
min: 9000
max: 65535
required: true
- variable: hostNetwork
label: Host Network
description: |
Bind to the host network. It's recommended to keep this disabled.</br>
schema:
type: boolean
default: false
- variable: terrariaStorage
label: ""
group: Storage Configuration
schema:
type: dict
attrs:
- variable: world
label: Terraria World Storage
description: The path to store Terraria World.
schema:
type: dict
attrs:
- variable: type
label: Type
description: |
ixVolume: Is dataset created automatically by the system.</br>
Host Path: Is a path that already exists on the system.
schema:
type: string
required: true
default: "ixVolume"
enum:
- value: "hostPath"
description: Host Path (Path that already exists on the system)
- value: "ixVolume"
description: ixVolume (Dataset created automatically by the system)
- variable: datasetName
label: Dataset Name
schema:
type: string
show_if: [["type", "=", "ixVolume"]]
required: true
hidden: true
immutable: true
default: "world"
$ref:
- "normalize/ixVolume"
- variable: hostPath
label: Host Path
schema:
type: hostpath
show_if: [["type", "=", "hostPath"]]
immutable: true
required: true
- variable: plugins
label: Terraria Plugins Storage
description: The path to store Terraria Plugins.
schema:
type: dict
attrs:
- variable: type
label: Type
description: |
ixVolume: Is dataset created automatically by the system.</br>
Host Path: Is a path that already exists on the system.
schema:
type: string
required: true
default: "ixVolume"
enum:
- value: "hostPath"
description: Host Path (Path that already exists on the system)
- value: "ixVolume"
description: ixVolume (Dataset created automatically by the system)
- variable: datasetName
label: Dataset Name
schema:
type: string
show_if: [["type", "=", "ixVolume"]]
required: true
hidden: true
immutable: true
default: "plugins"
$ref:
- "normalize/ixVolume"
- variable: hostPath
label: Host Path
schema:
type: hostpath
show_if: [["type", "=", "hostPath"]]
immutable: true
required: true
- variable: resources
group: Resources Configuration
label: ""
schema:
type: dict
attrs:
- variable: limits
label: Limits
schema:
type: dict
attrs:
- variable: cpu
label: CPU
description: CPU limit for Terraria.
schema:
type: string
default: "4000m"
required: true
- variable: memory
label: Memory
description: Memory limit for Terraria.
schema:
type: string
default: "8Gi"
required: true

View File

@@ -0,0 +1 @@
{{ include "ix.v1.common.lib.chart.notes" $ }}

View File

@@ -0,0 +1,78 @@
{{- define "terraria.configuration" -}}
{{ include "terraria.validation" $ }}
{{ $sizes := (dict "small" 1 "medium" 2 "large" 3) }}
{{ $difficutlies := (dict "normal" 0 "expert" 1 "master" 2 "journey" 3) }}
{{ $flags := (list "-port" "-world" "-maxplayers" "-password" "-secure" "-forceupdate" "-worldevil" "-difficulty" "-autocreate" "-seed") }}
{{/* worldevil, dificulty and autocreate flags are only used
when a world is generated. According to docs server will
ingore them if a world exists, so we can safely pass
them all the time and let server handle it.
Also -autocreate must come before other flags.
*/}}
- -autocreate
- {{ get $sizes .Values.terrariaConfig.worldSize | quote }}
- -worldevil
- {{ .Values.terrariaConfig.worldEvil | quote }}
- -difficulty
- {{ get $difficutlies .Values.terrariaConfig.worldDifficulty | quote }}
{{ with .Values.terrariaConfig.worldSeed }}
- -seed
- {{ . | quote }}
{{ end }}
- -port
- {{ .Values.terrariaNetwork.serverPort | quote }}
- -world
- {{ printf "/root/.local/share/Terraria/Worlds/%s.wld" .Values.terrariaConfig.worldName | quote }}
- -maxplayers
- {{ .Values.terrariaConfig.maxPlayers | quote }}
{{ with .Values.terrariaConfig.password }}
- -password
- {{ . | quote }}
{{ end }}
{{ if .Values.terrariaConfig.secure }}
- -secure
{{ end }}
{{ if .Values.terrariaConfig.forceUpdate }}
- -forceupdate
{{ end }}
{{ range $arg := .Values.terrariaConfig.additionalArgs }}
{{ if (mustHas $arg.key $flags) }}
{{ fail (printf "Terraria - Argument [%s] is already handled by the app, please use the corresponding field instead" $arg.key) }}
{{ end }}
- {{ $arg.key | quote }}
{{ with $arg.value }}
- {{ . | quote }}
{{ end }}
{{ end }}
{{- end -}}
{{- define "terraria.validation" -}}
{{- if not (mustRegexMatch "^[a-zA-Z0-9-]+$" .Values.terrariaConfig.worldName) -}}
{{- fail "Terraria - Expected World Name to only have [letters, numbers, dashes]" -}}
{{- end -}}
{{- if not .Values.terrariaConfig.maxPlayers -}}
{{- fail "Terraria - Expected non-empty Max Players" -}}
{{- end -}}
{{- if gt (int .Values.terrariaConfig.maxPlayers) 255 -}}
{{- fail "Terraria - Expected Max Players to be at most 255" -}}
{{- end -}}
{{- $evils := (list "crimson" "corrupt" "random") -}}
{{- if not (mustHas .Values.terrariaConfig.worldEvil $evils) -}}
{{- fail (printf "Terraria - Expected World Evil to be one of [%s], but got [%s]" (join ", " $evils) .Values.terrariaConfig.worldEvil) -}}
{{- end -}}
{{- $sizes := (list "small" "medium" "large") -}}
{{- if not (mustHas .Values.terrariaConfig.worldSize $sizes) -}}
{{- fail (printf "Terraria - Expected World Size to be one of [%s], but got [%s]" (join ", " $sizes) .Values.terrariaConfig.worldSize) -}}
{{- end -}}
{{- $difficutlies := (list "normal" "expert" "master" "journey") -}}
{{- if not (mustHas .Values.terrariaConfig.worldDifficulty $difficutlies) -}}
{{- fail (printf "Terraria - Expected World Difficulty to be one of [%s], but got [%s]" (join ", " $difficutlies) .Values.terrariaConfig.worldDifficulty) -}}
{{- end -}}
{{- end -}}

View File

@@ -0,0 +1,81 @@
{{- define "terraria.workload" -}}
workload:
terraria:
enabled: true
primary: true
type: Deployment
podSpec:
hostNetwork: {{ .Values.terrariaNetwork.hostNetwork }}
containers:
terraria:
enabled: true
primary: true
imageSelector: {{ .Values.terrariaConfig.imageSelector }}
tty: true
stdin: true
args:
{{- include "terraria.configuration" $ | nindent 12 }}
securityContext:
runAsUser: 0
runAsGroup: 0
runAsNonRoot: false
readOnlyRootFilesystem: false
envList:
{{ with .Values.terrariaConfig.additionalEnvs }}
{{ range $env := . }}
- name: {{ $env.name }}
value: {{ $env.value }}
{{ end }}
{{ end }}
probes:
# Probes are disabled because it fills the logs with
# "login attemps"
liveness:
enabled: {{ .Values.ci }}
type: tcp
port: "{{ .Values.terrariaNetwork.serverPort }}"
readiness:
enabled: {{ .Values.ci }}
type: tcp
port: "{{ .Values.terrariaNetwork.serverPort }}"
startup:
enabled: {{ .Values.ci }}
type: tcp
port: "{{ .Values.terrariaNetwork.serverPort }}"
{{/* Service */}}
service:
terraria:
enabled: true
primary: true
type: NodePort
targetSelector: terraria
ports:
server:
enabled: true
primary: true
port: {{ .Values.terrariaNetwork.serverPort }}
nodePort: {{ .Values.terrariaNetwork.serverPort }}
targetSelector: terraria
{{/* Persistence */}}
persistence:
world:
enabled: true
type: {{ .Values.terrariaStorage.world.type }}
datasetName: {{ .Values.terrariaStorage.world.datasetName | default "" }}
hostPath: {{ .Values.terrariaStorage.world.hostPath | default "" }}
targetSelector:
terraria:
terraria:
mountPath: /root/.local/share/Terraria/Worlds
plugins:
enabled: true
type: {{ .Values.terrariaStorage.plugins.type }}
datasetName: {{ .Values.terrariaStorage.plugins.datasetName | default "" }}
hostPath: {{ .Values.terrariaStorage.plugins.hostPath | default "" }}
targetSelector:
terraria:
terraria:
mountPath: /plugins
{{- end -}}

View File

@@ -0,0 +1,6 @@
{{- include "ix.v1.common.loader.init" . -}}
{{/* Merge the templates with Values */}}
{{- $_ := mustMergeOverwrite .Values (include "terraria.workload" $ | fromYaml) -}}
{{- include "ix.v1.common.loader.apply" . -}}

View File

@@ -0,0 +1 @@
{"filename": "values.yaml", "keys": ["image"]}

View File

@@ -0,0 +1,31 @@
#!/usr/bin/python3
import json
import re
import sys
from catalog_update.upgrade_strategy import semantic_versioning
RE_STABLE_VERSION = re.compile(r'tshock-[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+-[0-9]+\.[0-9]+\.[0-9]+(-[0-9]+)?')
def newer_mapping(image_tags):
key = list(image_tags.keys())[0]
tags = {t: t for t in image_tags[key] if RE_STABLE_VERSION.fullmatch(t)}
version = semantic_versioning(list(tags))
if not version:
return {}
return {
'tags': {key: tags[version]},
'app_version': version,
}
if __name__ == '__main__':
try:
versions_json = json.loads(sys.stdin.read())
except ValueError:
raise ValueError('Invalid json specified')
print(json.dumps(newer_mapping(versions_json)))

View File

@@ -0,0 +1,44 @@
image:
repository: ryshe/terraria
pullPolicy: IfNotPresent
tag: tshock-1.4.4.9-1.5.3-2
vanillaImage:
repository: ryshe/terraria
pullPolicy: IfNotPresent
tag: vanilla-1.4.4.9
ci: false
resources:
limits:
cpu: 4000m
memory: 8Gi
terrariaConfig:
imageSelector: image
worldSeed: ''
worldName: world
worldEvil: random
worldSize: small
worldDifficulty: normal
maxPlayers: 8
password: ''
secure: false
forceUpdate: false
additionalEnvs: []
additionalArgs: []
terrariaNetwork:
serverPort: 30000
hostNetwork: false
terrariaStorage:
world:
type: ixVolume
hostPath: ''
datasetName: world
plugins:
type: ixVolume
hostPath: ''
datasetName: plugins