diff --git a/.editorconfig b/.editorconfig deleted file mode 100644 index 64d3d6a..0000000 --- a/.editorconfig +++ /dev/null @@ -1,12 +0,0 @@ -# EditorConfig is awesome: https://EditorConfig.org - -# top-most EditorConfig file -root = true - -[*] -indent_style = space -indent_size = 2 -end_of_line = lf -charset = utf-8 -trim_trailing_whitespace = true -insert_final_newline = true \ No newline at end of file diff --git a/.github/workflows/chart_workflow.yaml b/.github/workflows/chart_workflow.yaml index 19f6c17..6158ab7 100644 --- a/.github/workflows/chart_workflow.yaml +++ b/.github/workflows/chart_workflow.yaml @@ -1,7 +1,6 @@ name: Lint, Test and Deploy Charts on: push: - pull_request: jobs: lint-test: diff --git a/.github/workflows/verify_readme.yaml b/.github/workflows/verify_readme.yaml new file mode 100644 index 0000000..e2c2030 --- /dev/null +++ b/.github/workflows/verify_readme.yaml @@ -0,0 +1,28 @@ +name: Verify Chart Documentation +on: + push: + +jobs: + verify-docs: + runs-on: ubuntu-latest + + steps: + - name: Checkout repository + uses: actions/checkout@v3 + - name: Install Golang + uses: actions/setup-go@v5 + with: + go-version: 'stable' + - name: install chart-doc-gen + run: go install kubepack.dev/chart-doc-gen@latest + - name: Set up dependencies + run: | + sudo apt-get update + sudo apt-get install -y make + # Install chart-doc-gen or add additional commands as needed + + - name: Generate Documentation + run: make gen + + - name: Verify Documentation + run: make verify \ No newline at end of file diff --git a/.github/workflows/verify_values_schema.yaml b/.github/workflows/verify_values_schema.yaml new file mode 100644 index 0000000..8b86331 --- /dev/null +++ b/.github/workflows/verify_values_schema.yaml @@ -0,0 +1,32 @@ +name: Verify Chart Schema +on: + push: + +jobs: + verify-schema: + name: "Verify Chart Schema" + runs-on: ubuntu-22.04 + steps: + - name: "Checkout" + uses: actions/checkout@v2.4.2 + with: + fetch-depth: 0 + + - name: "Set Up Helm" + uses: azure/setup-helm@v3.3 + if: github.ref != 'refs/heads/main' + with: + version: v3.4.1 + - name: install helm-schema-gen + run: helm plugin install https://github.com/karuppiah7890/helm-schema-gen.git + - name: Set up dependencies + run: | + sudo apt-get update + sudo apt-get install -y make + # Install chart-doc-gen or add additional commands as needed + + - name: Generate Documentation + run: make gen-schema + + - name: Verify Documentation + run: make verify \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index 48cbae9..c7b1a1e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,15 @@ ## Changelog +### V2.5.1 + +#### Non-Breaking Changes +- Updating values.schema.json +- Updating Readme documentation +- Adding new github workflow to verify readme documentation is up to date going forward +- Removed unneeded files from the repository +- Removed changelog entries from the main readme +- Added values.schema.json workflow to make sure schema json is up to date going forward + ### V2.5.0 #### Breaking Changes diff --git a/README.md b/README.md index b92a67a..5a83eb7 100644 --- a/README.md +++ b/README.md @@ -36,23 +36,4 @@ chart's [README.md](https://github.com/SQLJames/factorio-server-charts/blob/main ## Examples Of Large mods Values.yaml configuration of large [mods](./examples/): -* [Space-Exploration](https://mods.factorio.com/mod/space-exploration) - -## Changelog - -### V1.1.0 - -#### Breaking Changes - -- Moved account data from `server_settings.` to `account.` in values.yaml -- Moved server password from `server_settings.` to `serverPassword.` in values.yaml - -#### Non-Breaking Changes - -- Added `account.accountSecret` field to values.yaml -- Added `rcon.passwordSecret` field to values.yaml -- Added `serverPassword.passwordSecret` field to values.yaml -- Changed default `rcon.password` to `CHANGEMECHANGEME`, which should be changed anyway -- Changed default `map_gen_settings.autoplace_controls` from the standard values to `{}`, since by default map - generation follows standard parameters if not overriden -- Changed default `admin_list`, `white_list` and `ban_list` to `[]` instead of `nil` +* [Space-Exploration](https://mods.factorio.com/mod/space-exploration) \ No newline at end of file diff --git a/charts/factorio-server-charts/Chart.yaml b/charts/factorio-server-charts/Chart.yaml index ad4a7e5..a4bdfec 100644 --- a/charts/factorio-server-charts/Chart.yaml +++ b/charts/factorio-server-charts/Chart.yaml @@ -20,7 +20,7 @@ sources: # This is the chart version. This version number should be incremented each time you make changes # to the chart and its templates, including the app version. # Versions are expected to follow Semantic Versioning (https://semver.org/) -version: 2.5.0 +version: 2.5.1 # This is the version number of the application being deployed. This version number should be # incremented each time you make changes to the application. Versions are not expected to diff --git a/charts/factorio-server-charts/README.md b/charts/factorio-server-charts/README.md index a1d246e..86d380e 100644 --- a/charts/factorio-server-charts/README.md +++ b/charts/factorio-server-charts/README.md @@ -5,107 +5,46 @@ # factorio-server-charts -[factorio-server-charts](https://github.com/SQLJames/factorio-server-charts) - A Helm chart for running factorio in -kubernetes +[factorio-server-charts](https://github.com/SQLJames/factorio-server-charts) - A Helm chart for running factorio in kubernetes + +## TL;DR; + +```bash +$ helm repo add factorio https://sqljames.github.io/factorio-server-charts +$ helm repo update +$ helm search repo factorio/factorio-server-charts +$ helm upgrade -i factorio factorio/factorio-server-charts -n factorio --create-namespace +``` ## Introduction -This chart deploys Factorio on a [Kubernetes](http://kubernetes.io) cluster using the [Helm](https://helm.sh) package -manager. +This chart deploys Factorio on a [Kubernetes](http://kubernetes.io) cluster using the [Helm](https://helm.sh) package manager. ## Prerequisites -- An open NodePort or a UDP capable LoadBalancer if playing publicly. -- Networking knowledge to route the traffic to the appropriate port. -## Background +## Installing the Chart -This is something of a passion project for both learning kubernetes and because kubernetes is awesome. -Because of this, I have only confirm this working on version 1.1.0 of Factorio, but I am sure it will work just fine on -old versions as long as the schema doesn't change to much on the Secrets settings. +To install/upgrade the chart with the release name `factorio`: -However, with the way this is implemented if you want to make it backwards compatible, you can update the appropriate -sections in the values.yaml file to have the items added or removed to the json files that are required by factorio. -Server-settings, map-gen-settings, etc. +```bash +$ helm upgrade -i factorio factorio/factorio-server-charts -n factorio --create-namespace +``` -I did run into one issue on my setup, and I feel like it will likely come up again if people follow along. The Factorio -server is defaulting to run on port 30000 instead of 34197 because the default nginx port range for ingress does not -have 34197 within the normal port range. This shows the line of code that specifically is causing the issue inside -kubernetes :) -https://github.com/kubernetes/kubernetes/blob/59876df736c41093363f4c198aeec05e29c9c902/cmd/kube-apiserver/app/server.go#L197 +The command deploys Factorio on the Kubernetes cluster in the default configuration. The [configuration](#configuration) section lists the parameters that can be configured during installation. -## Releases +> **Tip**: List all releases using `helm list` -Releases are published using the official helm release action in github. -https://github.com/helm/chart-releaser-action - -## Quick Start +## Uninstalling the Chart -- Create a values.yaml file -- Set the following options +To uninstall the `factorio`: -```yaml -rcon: - external: false - -nodeSelector: - kubernetes.io/hostname: "" # this makes it easier for firewall rules and makes sure things dont change - -# making sure the game doesnt auto update on redeploy -# https://hub.docker.com/r/factoriotools/factorio/ -image: - tag: "" - - -persistence: - enabled: true - -factorioServer: - save_name: "" - -#needed if playing online -admin_list: [ ] # put your admins based on factorio names -# - "john_doe" -# - "jane_doe" - -white_list: [ ] # put the people you want to play with you based on factorio names -# - "john_doe" -# - "jane_doe" - -server_settings: - name: Factorio-2022-01-kubernetes - tags: - - modded - visibility: - public: true - require_user_verification: true - -account: - # Existing secret containing a valid factorio.com username and either a password or a token - # Example: - # - # apiVersion: v1 - # kind: Secret - # metadata: - # name: account-secret - # data: - # username: - # password: - # - # accountSecret: account-secret - accountSecret: '' - # Your factorio.com login credentials. Required for games with visibility public - username: '' - password: '' - # Authentication token. May be used instead of password above. - token: '' - -serverPassword: - # password required to log into the factorio server - game_password: '' - # Existing Secret containing a `game_password` data entry - passwordSecret: '' +```bash +$ helm uninstall factorio -n factorio ``` + +The command removes all the Kubernetes components associated with the chart and deletes the release. + ## Importing a save file > :warning: Importing a save file will **OVERWRITE THE SERVER SAVEFILE** with the name specified in `factorioServer.save_name`. Import with caution! @@ -138,32 +77,39 @@ Restart the pod again to import your save file. To Install mods, change `mods.enabled` to `true`, add any offical mods by their URL name under the `mods.portal` section, and any unofficial mods in the `mods.unofficial`section. + ```yaml mods: - enabled: true - # in order to use the mods portal you will need to specify the username and token in the server_settings. - # name is determined by the url, it will be the last part of the url, not the title of the mod. - portal: - - Krastorio2 - - StorageTank2_Updated - - early-robots - # unofficial section is meant to just allow you to download and place folders into the mods folder. - # we will not check version compatibility automatically with these downloads. - # you can encounter an error if the file names dont match what the mod is expecting for example - #Error Util.cpp:83: Failed to load mod "Squeak-Through": Filename of mod - # /factorio/mods/Squeak-Through.zip doesn't match the expected Squeak Through_1.8.2.zip (case sensitive!) - unofficial: - - url: "https://github.com/Suprcheese/Squeak-Through/archive/refs/tags/1.8.2.zip" - name: "Squeak Through_1.8.2.zip" + image: + repository: "ghcr.io/sqljames/factorio-mod-downloader" + ## Container image pull policy + pullPolicy: Always + ## Overrides the image tag whose default is the chart appVersion. + tag: "1.0.1" + ## You should set an fix version, i.e.: + # tag: "1.1.37" + enabled: false +# in order to use the mods portal you will need to specify the username and token in the server_settings. + portal: [] +# - name: factorissimo-2-notnotmelon +# version: 3.5.11 +# unofficial section is meant to just allow you to download and place folders into the mods folder. +# we will not check version compatibility automatically with these downloads. +# you can encounter an error if the file names dont match what the mod is expecting for example +# Error Util.cpp:83: Failed to load mod "Squeak-Through": Filename of mod +# /factorio/mods/Squeak-Through.zip doesn't match the expected Squeak Through_1.8.2.zip (case sensitive!) + unofficial: [] +# - url: "https://github.com/Suprcheese/Squeak-Through/archive/refs/tags/1.8.2.zip" +# name: "Squeak Through_1.8.2.zip" ``` If the Factorio server doesn't start, check that the logs don't have an error with the mods. They are pretty verbose. -### Space Exploration and other overhaul mods +### Overhaul mods It is possible that your mod may extend the default settings. As a result, your server might not start properly and instead throw an error. While we expose all the default settings, we would not be able to determine what is needed if it is absent. To add new settings you would need to convert the desired json file into a yaml struct as we are mounting all configurations as a config map into the container. -the issue with Space Exploration, as an example, was that the `autoplace_controls` by default is an empty array, and thus we were not able to start the instance as there were no settings for them to evaluate. Additionally, they are also modifying some of the other settings. These changes implement the default recommended settings, available in the UI and were stored in a file at `...Factorio\mods\space-exploration\shared.lua`. In the lua file, it has 2 sections, basic_settings and advanced_settings which correspond to settings in `map-gen-settings.json` and `map-settings.json` respecively. +For example prior to the official release of 2.0, there was an issue with Space Exploration. The `autoplace_controls` by default is an empty array, and thus we were not able to start the instance as there were no settings for them to evaluate. Additionally, they are also modifying some of the other settings. These changes implement the default recommended settings, available in the UI and were stored in a file at `...Factorio\mods\space-exploration\shared.lua`. In the lua file, it has 2 sections, basic_settings and advanced_settings which correspond to settings in `map-gen-settings.json` and `map-settings.json` respecively. At the time of writing, to make these changes you would need to add this to your values.yaml file to override their default values in the chart. @@ -193,131 +139,215 @@ More information about the debugging process for the space exploration mod can b If you do run into any issues with mods, I will try to work with you on finding the right settings and document them as well. -## Parameters - -### Kubernetes Parameters - -| Name | Description | Value | -|-----------------------------|----------------------------------------------------|------------| -| `replicaCount` | Number of replicas to create (only 1 is supported) | `1` | -| `nodeSelector` | Node labels for pod assignment | `{}` | -| `resources.requests.cpu` | The requested cpu for the Factorio containers | `500m` | -| `resources.requests.memory` | The requested memory for the Factorio containers | `512Mi` | -| `resources.limits` | If you like to limit Factorio resources | `{}` | -| `strategy.type` | Strategy used to replace old pods | `Recreate` | -| `tolerations` | Tolerations for pod assignment | `[]` | -| `affinity` | Affinity rules for pod assignment | `{}` | - -### Image Parameters - -| Name | Description | Value | -|--------------------|-----------------------------------------------------|--------------------------| -| `image.repository` | Factorio image repository | `factoriotools/factorio` | -| `image.tag` | Factorio image tag (immutable tags are recommended) | `latest` | -| `image.pullPolicy` | Factorio image pull policy | `Always` | - -### Service Parameters - -| Name | Description | Value | -|---------------------------------|----------------------------------------------------------------------------------------------------------------------------|------------| -| `service.type` | Factorio service type | `NodePort` | -| `service.port` | Factorio service port | `31497` | -| `service.externalIPs` | If you are able to map an external IP, set it here | | -| `service.nodePort` | If you use "type: NodePort" set the port to a value you like in the range of 30000-32767. Leave it blank for a random port | | -| `service.annotations` | Additional custom annotations for Factorio service | `{}` | -| `service.externalTrafficPolicy` | Traffic policy, "Cluster" or "Local", used for the service | `Cluster` | - -### Persistence Configuration - -| Name | Description | Value | -|-------------------------------------|----------------------------------------------------|--------| -| `persistence.enabled` | Enable persistence using Persistent Volume Claims | `true` | -| `persistence.dataDir.Size` | Persistent Volume size | `1Gi` | -| `persistence.dataDir.existingClaim` | The name of an existing PVC to use for persistence | | -| `persistence.storageClassName` | Persistent Volume storage class | `""` | -| `persistence.annotations` | Persistent Volume Claim annotations | `{}` | -| `persistence.lables` | Persistent Volume Claim labels | `{}` | - -### Factorio Parameters - -| Name | Description | Value | -|----------------------------------------------------------------|------------------------------------------------------------------------------------------------------------------------------------------|----------------------------------| -| `mods.enabled` | Enable mods | `false` | -| `mods.portal` | List of official mods to be downloaded from Factorio Mod Portal | `[]` | -| `mods.unofficial` | List of unofficial mods name and url to download into the mods folder | `[]` | -| `factorioServer.save_name` | Factorio save name | `replaceMe` | -| `factorioServer.generate_new_save` | Generate a new save if `save_name` is not found | `true` | -| `factorioServer.update_mods_on_start` | Update mods on server start | `false` | -| `factorioServer.load_latest_save` | Lets the game know if you want to load the latest save | `true` | -| `import_save.enabled` | Enable save importer. Importer runs at every pod initialization. **:warning: Overwrites existing save if successful** | `true` | -| `import_save.source_url` | Full URL (including http(s)://). If left blank, saves can still be imported by placing in '/factorio/save-importer/import' | `""` | -| `import_save.reimport_on_change` | Reimport save file from source_url when checksum changes. File will be downloaded at every pod initialization. | `false` | -| `import_save.reimport_every_time` | Reimport save file from source_url at every pod intialization. Useful for resetting demos or testing. | `false` | -| `account.accountSecret` | Existing secret containing a valid factorio.com username and either a password or a token (or both) | `""` | -| `account.username` | Factorio.com username, ignored if `account.accountSecret` is set | `""` | -| `account.password` | Factorio.com password, ignored if `account.accountSecret` is set | `""` | -| `account.token` | Factorio.com token, ignored if `account.accountSecret` is set | `""` | -| `serverPassword.passwordSecret` | Existing Secret containing a `game_password` data entry | `""` | -| `serverPassword.game_password` | Password required to log into the factorio server. Ignored if `serverPassword.passwordSecret` is set | `""` | -| `server_settings.name` | Factorio server name | `Factorio` | -| `server_settings.description` | Factorio server description | `Factorio running on Kubernetes` | -| `server_settings.tags` | Factorio server tags | `["game","tags"]` | -| `server_settings.max_players` | Maximum number of players allowed, admins can join even a full server. 0 means unlimited | `0` | -| `server_settings.visibility.public` | Publish the server on the official Factorio matching server | `false` | -| `server_settings.visibility.lan` | Server will be visible in LAN | `true` | -| `server_settings.require_user_verification` | When set to true, the server will only allow clients that have a valid Factorio.com account | `false` | -| `server_settings.max_upload_in_kilobytes_per_second` | Optional, default value is 0. 0 means unlimited | `0` | -| `server_settings.max_upload_slots` | Optional, default value is 5. 0 means unlimited | `5` | -| `server_settings.minimum_latency_in_ticks` | Optional, one tick is 16ms in default speed, default value is 0. 0 means no minimum | `0` | -| `server_settings.ignore_player_limit_for_returning_players` | Players that played on this map already can join even when the max player limit is reached | `false` | -| `server_settings.allow_commands` | Possible values are true, false and admins-only | `admins-only` | -| `server_settings.autosave_interval` | Autosave interval in minutes | `10` | -| `server_settings.autosave_slots` | Server autosave slots, it is cycled through when the server autosaves | `5` | -| `server_settings.afk_autokick_interval` | How many minutes must pass before someone is kicked when doing nothing, 0 for never | `0` | -| `server_settings.auto_pause` | Whether the server should be paused when no players are present | `true` | -| `server_settings.only_admins_can_pause_the_game` | Specifies if anyone can pause or only admins | `true` | -| `server_settings.autosave_only_on_server` | Whether autosaves should be performed only on the server or also on all connected clients. Default is true | `true` | -| `server_settings.non_blocking_saving` | Highly experimental feature, enable only at your own risk | `false` | -| `server_settings.minimum_segment_size` | Minimum network messages segment size | `25` | -| `server_settings.minimum_segment_size_peer_count` | Minimum network messages segment count | `20` | -| `server_settings.maximum_segment_size` | Maximum network messages segment size | `100` | -| `server_settings.maximum_segment_size_peer_count` | Minimum network messages segment count | `10` | -| `rcon.external` | Enable RCON external access (deploy RCON service) | `true` | -| `rcon.type` | RCON service type | `LoadBalancer` | -| `rcon.serviceAnnotations` | RCON service annotations | `{}` | -| `rcon.passwordSecret` | Existing secret containing a `password` data field | `""` | -| `rcon.password` | Password for RCON, ignored if `rcon.passwordSecret` is set | `CHANGEMECHANGEME` | -| `rcon.port` | RCON service external port | `30100` | -| `map_gen_settings.terrain_segmentation` | The inverse of water scale in the map generator GUI | `1` | -| `map_gen_settings.water` | The equivalent to water coverage in the map generator GUI | `1` | -| `map_gen_settings.width` | Map width in tiles; 0 means infinite | `0` | -| `map_gen_settings.height` | Map height in tiles; 0 means infinite | `0` | -| `map_gen_settings.starting_area` | Multiplier for biter free zone radius | `1` | -| `map_gen_settings.peaceful_mode` | Enable Peaceful mode | `false` | -| `map_gen_settings.autoplace_controls` | Override default ore, trees and enemy bases frequency, size and richness. Leave empty for default values. Supports including modded ores | `{}` | -| `map_gen_settings.cliff_settings.name` | Override default cliff prototype name | `cliff` | -| `map_gen_settings.cliff_settings.cliff_elevation_0` | Override elevation of first row of cliffs | `10` | -| `map_gen_settings.cliff_settings.cliff_elevation_interval` | Override elevation difference between successive rows of cliffs | `40` | -| `map_gen_settings.cliff_settings.richness` | Called cliff continuity in the map generator GUI. 0 will result in no cliffs, 10 will make all cliff rows completely solid | `1` | -| `map_gen_settings.property_expression_names` | Overrides for property value generators (map type) | | -| `map_gen_settings.starting_points` | List of starting points for the map | | -| `map_gen_settings.seed` | Map RNG Seed | `nil` | -| `map_settings.difficulty_settings.recipe_difficulty` | Enable expensive crafting recipe | `0` | -| `map_settings.difficulty_settings.technology_difficulty` | Enable expensive research | `0` | -| `map_settings.difficulty_settings.technology_price_multiplier` | Research cost multiplier | `1` | -| `map_settings.difficulty_settings.research_queue_setting` | Possibile values: `after-victory`, `always`, `never` | `after-victory` | -| `map_settings.pollution.enabled` | Enable pollution. Check values.yaml to know what pollution values you can override | | -| `map_settings.enemy_evolution.enabled` | Enable enemy evolution. Check values.yaml to know what enemy evolution values you can override | | -| `map_settings.enemy_expansion.enabled` | Enable enemy expansion. Check values.yaml to know what enemy expansion values you can override | | -| `map_settings.unit_group` | Override default unit group values. Check values.yaml to know what values you can override | | -| `map_settings.steering` | Override default steering values. Check values.yaml to know what values you can override | | -| `map_settings.path_finder` | Override default pathfinder values. Check values.yaml to know what values you can override | | -| `map_settings.max_failed_behavior_count` | If a behavior fails this many times, the enemy (or enemy group) is destroyed. This solves biters stuck within their own base. | `3` | -| `admin_list` | Admin list | `[]` | -| `white_list` | Whitelist | `[]` | -| `ban_list` | Ban list | `[]` | - -## Readme - -Readme was generated using [chart-doc-gen](https://github.com/kubepack/chart-doc-gen) tool -and [readme-generator-for-helm](https://github.com/bitnami-labs/readme-generator-for-helm). +## Configuration + +The following table lists the configurable parameters of the `factorio-server-charts` chart and their default values. + +| Parameter | Description | Default | +|-------------------------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|---------------------------------------------------------| +| replicaCount | | 1 | +| hostNetworkEnabled | | true | +| securityContext.fsGroup | | 845 | +| podSecurityContext.runAsUser | | 845 | +| podSecurityContext.runAsGroup | | 845 | +| image.repository | | "factoriotools/factorio" | +| image.pullPolicy | # Container image pull policy | Always | +| image.tag | # Overrides the image tag whose default is the chart appVersion. | "latest" | +| service.type | | NodePort | +| service.ipFamilyPolicy | # Represents the dual-stack-ness requested or required by this Service. Possible values are # SingleStack, PreferDualStack or RequireDualStack. # The ipFamilies and clusterIPs fields depend on the value of this field. # Ref: https://kubernetes.io/docs/concepts/services-networking/dual-stack/ | "SingleStack" | +| service.port | | 31497 | +| resources.requests.memory | | 512Mi | +| resources.requests.cpu | | 500m | +| strategy.type | | Recreate | +| persistence.enabled | | true | +| persistence.dataDir.Size | | "1Gi" | +| persistence.storageClassName | # If you like to use a specific storageClassName, set the name. Leave it blank for the default class | "" | +| mods.image.repository | | "ghcr.io/sqljames/factorio-mod-downloader" | +| mods.image.pullPolicy | # Container image pull policy | Always | +| mods.image.tag | # Overrides the image tag whose default is the chart appVersion. | "1.0.1" | +| mods.enabled | | false | +| factorioServer.save_name | name to use for the save file | "replaceMe" | +| factorioServer.generate_new_save | generate a new save if one does not exist before starting the server | true | +| factorioServer.update_mods_on_start | if mods should be updated before starting the server | false | +| factorioServer.load_latest_save | load latest when true. Otherwise load SAVE_NAME | true | +| factorioServer.enable_space_age | enables or disables the mods for DLC Space Age in mod-list.json | true | +| factorioServer.port | factorio game server port the default game port (34197) has been changed to 31497 to resolve issues when using the port-fixer. this port setting is typically for internal Kubernetes configuration only, and in most cases, it does not need to be modified. if it is necessary to change the game server port where you connect to the game, update the "service.port" value accordingly. | 31497 | +| factorioServer.rcon_port | factorio game rcon port this port setting is typically for internal Kubernetes configuration only, and in most cases, it does not need to be modified. if it is necessary to change the rcon server port where you connect to it, update the "rcon.port" value accordingly. | 27015 | +| import_save.enabled | enable save importer | true | +| import_save.source_url | url to download save from (http or https only). if no url is specified, saves can still be manually imported by placing the file in "/factorio/save-importer/import" | "" | +| import_save.reimport_on_change | reimport from the source_url if the checksum of the file changes | false | +| import_save.reimport_every_time | reimport from the source_url AND OVERWRITE PREVIOUS SAVE every time pod is initialized. good for demos or testing | false | +| account.accountSecret | Existing secret containing a valid factorio.com username and either a password or a token
Example:
`apiVersion: v1`
`kind: Secret`
`metadata:`
`name: account-secret`
`data:`
`username: `
`password: `
`accountSecret: account-secret` | '' | +| account.username | Your factorio.com login credentials. Required for games with visibility public | '' | +| account.password | | '' | +| account.token | Authentication token. May be used instead of password above. | '' | +| serverPassword.game_password | password required to log into the factorio server | '' | +| serverPassword.passwordSecret | Existing Secret containing a `game_password` data entry | '' | +| server_settings.name | Your Instance Name | Factorio | +| server_settings.description | Your Instance Description | "Factorio running on Kubernetes" | +| server_settings.max_players | Maximum number of players allowed, admins can join even a full server. 0 means unlimited. | 0 | +| server_settings.visibility.public | Game will be published on the official Factorio matching server | false | +| server_settings.visibility.lan | Game will be broadcast on LAN | true | +| server_settings.require_user_verification | When set to true, the server will only allow clients that have a valid Factorio.com account | false | +| server_settings.max_upload_in_kilobytes_per_second | optional, default value is 0. 0 means unlimited. | 0 | +| server_settings.max_upload_slots | optional, default value is 5. 0 means unlimited. | 5 | +| server_settings.minimum_latency_in_ticks | optional one tick is 16ms in default speed, default value is 0. 0 means no minimum. | 0 | +| server_settings.ignore_player_limit_for_returning_players | Players that played on this map already can join even when the max player limit was reached. | false | +| server_settings.allow_commands | possible values are, true, false and admins-only | admins-only | +| server_settings.autosave_interval | Autosave interval in minutes | 10 | +| server_settings.autosave_slots | server autosave slots, it is cycled through when the server autosaves. | 5 | +| server_settings.afk_autokick_interval | How many minutes until someone is kicked when doing nothing, 0 for never. | 0 | +| server_settings.auto_pause | Whether should the server be paused when no players are present. | true | +| server_settings.auto_pause_when_players_connect | Whether should the server be paused when someone is connecting to the server. | false | +| server_settings.only_admins_can_pause_the_game | specifies if anyone can pause or only admins | true | +| server_settings.autosave_only_on_server | Whether autosaves should be saved only on server or also on all connected clients. Default is true. | true | +| server_settings.non_blocking_saving | Highly experimental feature, enable only at your own risk of losing your saves. On UNIX systems, server will fork itself to create an autosave. Autosaving on connected Windows clients will be disabled regardless of autosave_only_on_server option. | false | +| server_settings.max_heartbeats_per_second | Network tick rate. Maximum rate game updates packets are sent at before bundling them together. Minimum value is 6, maximum value is 240. | 60 | +| server_settings.minimum_segment_size | Long network messages are split into segments that are sent over multiple ticks. Their size depends on the number of peers currently connected. Increasing the segment size will increase upload bandwidth requirement for the server and download bandwidth requirement for clients. This setting only affects server outbound messages. Changing these settings can have a negative impact on connection stability for some clients. | 25 | +| server_settings.minimum_segment_size_peer_count | | 20 | +| server_settings.maximum_segment_size | | 100 | +| server_settings.maximum_segment_size_peer_count | | 10 | +| port_fixer.enabled | Adds an extra container that tries to help with connection issues via the public server browser. This is especially useful when you can’t set up outgoing static port mappings and see log messages like these: > Warning ServerRouter.cpp:541: Received own address message reply with conflicting address (got IP ADDR:({:19296}), expected IP ADDR:({:58037})) > Warning ServerMultiplayerManager.cpp:651: Determining own address has failed. Best guess: IP ADDR:({:58037}) > Warning ServerRouter.cpp:541: Received own address message reply with conflicting address (got IP ADDR:({:19297}), expected IP ADDR:({:58037})) > Warning ServerRouter.cpp:541: Received own address message reply with conflicting address (got IP ADDR:({:24105}), expected IP ADDR:({:58037})) Note: Port forwarding for incoming traffic still needs to be set up properly for this to work. For more info, check out: - https://github.com/SQLJames/factorio-server-charts/issues/15 | false | +| port_fixer.image.repository | | "ghcr.io/zcube/factorio-port-fixer" | +| port_fixer.image.pullPolicy | | Always | +| port_fixer.image.tag | | latest | +| port_fixer.port | | '' | +| rcon.ipFamilyPolicy | # Represents the dual-stack-ness requested or required by this Service. Possible values are # SingleStack, PreferDualStack or RequireDualStack. # The ipFamilies and clusterIPs fields depend on the value of this field. # Ref: https://kubernetes.io/docs/concepts/services-networking/dual-stack/ | "SingleStack" | +| rcon.external | | true | +| rcon.type | | LoadBalancer | +| rcon.passwordSecret | Existing secret containing a `rconpw` data field | "" | +| rcon.password | Password for rcon | "CHANGEMECHANGEME" | +| rcon.port | rcon port | 30100 | +| rconAPI.ipFamilyPolicy | # Represents the dual-stack-ness requested or required by this Service. Possible values are # SingleStack, PreferDualStack or RequireDualStack. # The ipFamilies and clusterIPs fields depend on the value of this field. # Ref: https://kubernetes.io/docs/concepts/services-networking/dual-stack/ | "SingleStack" | +| rconAPI.enabled | | false | +| rconAPI.image.repository | | "ghcr.io/nekomeowww/factorio-rcon-api" | +| rconAPI.image.pullPolicy | | Always | +| rconAPI.image.tag | | latest | +| rconAPI.type | | ClusterIP | +| rconAPI.httpPort | | 30110 | +| rconAPI.grpcPort | | 30111 | +| rconAPI.ingress.enabled | | true | +| rconAPI.ingress.hostname | | "factorio.example.com" | +| rconAPI.ingress.className | | "nginx" | +| rconAPI.ingress.annotations.nginx.ingress.kubernetes.io/ssl-redirect | | "true" | +| rconAPI.ingress.annotations.nginx.ingress.kubernetes.io/backend-protocol | | "GRPC" | +| rconAPI.ingress.tls.enabled | | false | +| rconAPI.ingress.tls.secretName | | "cert-factorio.example.com" | +| map_gen_settings.width | Width and height of map, in tiles; 0 means infinite | 0 | +| map_gen_settings.height | Width and height of map, in tiles; 0 means infinite | 0 | +| map_gen_settings.starting_area | Multiplier for biter free zone radius | 1 | +| map_gen_settings.peaceful_mode | | false | +| map_gen_settings.cliff_settings.name | Name of the cliff prototype | cliff | +| map_gen_settings.cliff_settings.cliff_elevation_0 | Elevation of first row of cliffs | 10 | +| map_gen_settings.cliff_settings.cliff_elevation_interval | Elevation difference between successive rows of cliffs. This is inversely proportional to frequency in the map generation GUI. Specifically, when set from the GUI the value is 40 / frequency. | 40 | +| map_gen_settings.cliff_settings.richness | Called cliff continuity in the map generator GUI. 0 will result in no cliffs, 10 will make all cliff rows completely solid | 1 | +| map_gen_settings.property_expression_names.control:moisture:frequency | | '1' | +| map_gen_settings.property_expression_names.control:moisture:bias | | '0' | +| map_gen_settings.property_expression_names.control:aux:frequency | | '1' | +| map_gen_settings.property_expression_names.control:aux:bias | | '0' | +| map_gen_settings.seed | Use null for a random seed, number for a specific seed. | null | +| map_settings.difficulty_settings.technology_price_multiplier | | 1 | +| map_settings.difficulty_settings.spoil_time_modifier | | 1 | +| map_settings.asteroids.max_ray_portals_expanded_per_tick | | 100 | +| map_settings.asteroids.spawning_rate | | 1 | +| map_settings.pollution.enabled | | true | +| map_settings.pollution.diffusion_ratio | these are values for 60 ticks (1 simulated second) amount that is diffused to neighboring chunk | 0.02 | +| map_settings.pollution.min_to_diffuse | | 15 | +| map_settings.pollution.ageing | | 1 | +| map_settings.pollution.expected_max_per_chunk | | 150 | +| map_settings.pollution.min_to_show_per_chunk | | 50 | +| map_settings.pollution.min_pollution_to_damage_trees | | 60 | +| map_settings.pollution.pollution_with_max_forest_damage | | 150 | +| map_settings.pollution.pollution_per_tree_damage | | 50 | +| map_settings.pollution.pollution_restored_per_tree_damage | | 10 | +| map_settings.pollution.max_pollution_to_restore_trees | | 20 | +| map_settings.pollution.enemy_attack_pollution_consumption_modifier | | 1 | +| map_settings.enemy_evolution.enabled | | true | +| map_settings.enemy_evolution.time_factor | | 0.000004 | +| map_settings.enemy_evolution.destroy_factor | | 0.002 | +| map_settings.enemy_evolution.pollution_factor | | 0.0000009 | +| map_settings.enemy_expansion.enabled | | true | +| map_settings.enemy_expansion.max_expansion_distance | | 7 | +| map_settings.enemy_expansion.friendly_base_influence_radius | | 2 | +| map_settings.enemy_expansion.enemy_building_influence_radius | | 2 | +| map_settings.enemy_expansion.building_coefficient | | 0.1 | +| map_settings.enemy_expansion.other_base_coefficient | | 2 | +| map_settings.enemy_expansion.neighbouring_chunk_coefficient | | 0.5 | +| map_settings.enemy_expansion.neighbouring_base_chunk_coefficient | | 0.4 | +| map_settings.enemy_expansion.max_colliding_tiles_coefficient | | 0.9 | +| map_settings.enemy_expansion.settler_group_min_size | | 5 | +| map_settings.enemy_expansion.settler_group_max_size | | 20 | +| map_settings.enemy_expansion.min_expansion_cooldown | | 14400 | +| map_settings.enemy_expansion.max_expansion_cooldown | | 216000 | +| map_settings.unit_group.min_group_gathering_time | | 3600 | +| map_settings.unit_group.max_group_gathering_time | | 36000 | +| map_settings.unit_group.max_wait_time_for_late_members | | 7200 | +| map_settings.unit_group.max_group_radius | | 30 | +| map_settings.unit_group.min_group_radius | | 5 | +| map_settings.unit_group.max_member_speedup_when_behind | | 1.4 | +| map_settings.unit_group.max_member_slowdown_when_ahead | | 0.6 | +| map_settings.unit_group.max_group_slowdown_factor | | 0.3 | +| map_settings.unit_group.max_group_member_fallback_factor | | 3 | +| map_settings.unit_group.member_disown_distance | | 10 | +| map_settings.unit_group.tick_tolerance_when_member_arrives | | 60 | +| map_settings.unit_group.max_gathering_unit_groups | | 30 | +| map_settings.unit_group.max_unit_group_size | | 200 | +| map_settings.steering.default.radius | | 1.2 | +| map_settings.steering.default.separation_force | | 0.005 | +| map_settings.steering.default.separation_factor | | 1.2 | +| map_settings.steering.default.force_unit_fuzzy_goto_behavior | | false | +| map_settings.steering.moving.radius | | 3 | +| map_settings.steering.moving.separation_force | | 0.01 | +| map_settings.steering.moving.separation_factor | | 3 | +| map_settings.steering.moving.force_unit_fuzzy_goto_behavior | | false | +| map_settings.path_finder.fwd2bwd_ratio | | 5 | +| map_settings.path_finder.goal_pressure_ratio | | 2 | +| map_settings.path_finder.max_steps_worked_per_tick | | 1000 | +| map_settings.path_finder.max_work_done_per_tick | | 8000 | +| map_settings.path_finder.use_path_cache | | true | +| map_settings.path_finder.short_cache_size | | 5 | +| map_settings.path_finder.long_cache_size | | 25 | +| map_settings.path_finder.short_cache_min_cacheable_distance | | 10 | +| map_settings.path_finder.short_cache_min_algo_steps_to_cache | | 50 | +| map_settings.path_finder.long_cache_min_cacheable_distance | | 30 | +| map_settings.path_finder.cache_max_connect_to_cache_steps_multiplier | | 100 | +| map_settings.path_finder.cache_accept_path_start_distance_ratio | | 0.2 | +| map_settings.path_finder.cache_accept_path_end_distance_ratio | | 0.15 | +| map_settings.path_finder.negative_cache_accept_path_start_distance_ratio | | 0.3 | +| map_settings.path_finder.negative_cache_accept_path_end_distance_ratio | | 0.3 | +| map_settings.path_finder.cache_path_start_distance_rating_multiplier | | 10 | +| map_settings.path_finder.cache_path_end_distance_rating_multiplier | | 20 | +| map_settings.path_finder.stale_enemy_with_same_destination_collision_penalty | | 30 | +| map_settings.path_finder.ignore_moving_enemy_collision_distance | | 5 | +| map_settings.path_finder.enemy_with_different_destination_collision_penalty | | 30 | +| map_settings.path_finder.general_entity_collision_penalty | | 10 | +| map_settings.path_finder.general_entity_subsequent_collision_penalty | | 3 | +| map_settings.path_finder.extended_collision_penalty | | 3 | +| map_settings.path_finder.max_clients_to_accept_any_new_request | | 10 | +| map_settings.path_finder.max_clients_to_accept_short_new_request | | 100 | +| map_settings.path_finder.direct_distance_to_consider_short_request | | 100 | +| map_settings.path_finder.short_request_max_steps | | 1000 | +| map_settings.path_finder.short_request_ratio | | 0.5 | +| map_settings.path_finder.min_steps_to_check_path_find_termination | | 2000 | +| map_settings.path_finder.start_to_goal_cost_multiplier_to_terminate_path_find | | 2000.0 | +| map_settings.path_finder.negative_path_cache_delay_interval | | 20 | +| map_settings.max_failed_behavior_count | | 3 | + + +Specify each parameter using the `--set key=value[,key=value]` argument to `helm upgrade -i`. For example: + +```bash +$ helm upgrade -i factorio factorio/factorio-server-charts -n factorio --create-namespace --set replicaCount=1 +``` + +Alternatively, a YAML file that specifies the values for the parameters can be provided while +installing the chart. For example: + +```bash +$ helm upgrade -i factorio factorio/factorio-server-charts -n factorio --create-namespace --values values.yaml +``` + +## Releases + +Releases are published using the official helm release action in github. +https://github.com/helm/chart-releaser-action \ No newline at end of file diff --git a/charts/factorio-server-charts/doc.yaml b/charts/factorio-server-charts/doc.yaml index fad92b9..e41936a 100644 --- a/charts/factorio-server-charts/doc.yaml +++ b/charts/factorio-server-charts/doc.yaml @@ -5,11 +5,10 @@ project: description: A Helm chart for running factorio in kubernetes app: Factorio repository: - url: https://github.com/SQLJames/factorio-server-charts - name: github + url: https://sqljames.github.io/factorio-server-charts + name: factorio chart: name: factorio-server-charts - version: 1.2.4 values: "-- generate from values file --" valuesExample: "-- generate from values file --" release: diff --git a/charts/factorio-server-charts/readme.tpl b/charts/factorio-server-charts/readme.tpl new file mode 100644 index 0000000..f1dc66e --- /dev/null +++ b/charts/factorio-server-charts/readme.tpl @@ -0,0 +1,169 @@ +[![Artifact HUB](https://img.shields.io/endpoint?url=https://artifacthub.io/badge/repository/factorio-server-charts)](https://artifacthub.io/packages/search?repo=factorio-server-charts) +[![Factorio](https://img.shields.io/static/v1?label=Factorio&message=v2.0.10&logo=data:image/png;base64,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&labelColor=4c2c2c&color=8c6c6c)](https://www.factorio.com/) +[![Chart Version](https://img.shields.io/static/v1?logo=Helm&logoColor=0f1689&message=v1.1.0&label=Helm%20Chart&labelColor=eeeeee&color=fefefe)](https://sqljames.github.io/factorio-server-charts/index.yaml) +[![Image Version](https://img.shields.io/static/v1?logo=Docker&message=v1.1.70&label=Docker%20Image&labelColor=eeeeee&color=fefefe)](https://sqljames.github.io/factorio-server-charts/index.yaml) + +# {{ .Project.ShortName }} + +[{{ .Project.Name }}]({{ .Project.URL }}) - {{ .Project.Description }} + +## TL;DR; + +```bash +$ helm repo add {{ .Repository.Name }} {{ .Repository.URL }} +$ helm repo update +$ helm search repo {{ .Repository.Name }}/{{ .Chart.Name }} +$ helm upgrade -i {{ .Release.Name }} {{ .Repository.Name }}/{{ .Chart.Name }} -n {{ .Release.Namespace }} --create-namespace +``` + +## Introduction + +This chart deploys {{ .Project.App }} on a [Kubernetes](http://kubernetes.io) cluster using the [Helm](https://helm.sh) package manager. + +## Prerequisites +{{ range .Prerequisites }} +- {{ . }} +{{- end }} + +## Installing the Chart + +To install/upgrade the chart with the release name `{{ .Release.Name }}`: + +```bash +$ helm upgrade -i {{ .Release.Name }} {{ .Repository.Name }}/{{ .Chart.Name }} -n {{ .Release.Namespace }} --create-namespace +``` + +The command deploys {{ .Project.App }} on the Kubernetes cluster in the default configuration. The [configuration](#configuration) section lists the parameters that can be configured during installation. + +> **Tip**: List all releases using `helm list` + +## Uninstalling the Chart + +To uninstall the `{{ .Release.Name }}`: + +```bash +$ helm uninstall {{ .Release.Name }} -n {{ .Release.Namespace }} +``` + +The command removes all the Kubernetes components associated with the chart and deletes the release. + +## Importing a save file + +> :warning: Importing a save file will **OVERWRITE THE SERVER SAVEFILE** with the name specified in `factorioServer.save_name`. Import with caution! + +### Importing by URL + +To import your save file from a URL, set `import_save.source_url` to a direct-download link for your savegame. By default, the file will be downloaded and imported only once. + +If, on pod intialization, you wish to re-import the file every time the contents of the savegame change, set `import_save.reimport_on_change` to `true`. +:warning: If the savegame at the source url changes, this will overwrite the server save with that file. Use with caution! + +If you wish to reimport the save file every time the pod reinitializes, regardless of changes, set `import_save.reimport_every_time` to `true`. This could be useful for demos or testing. +:warning: This will overwrite the server savegame **every time the pod reinitializes**. Use with caution! + +### Manual Import + +To import an existing save file, start/restart the pod at least once. This will create the import folder structure. + +Now, copy the savegame you wish to import to the `/factorio/save-importer/import/.zip` on the running pod using whatever mechanism you prefer. To do this with kubectl: + +```bash +kubectl cp ./my_existing_savegame.zip /:/factorio/save-importer/import +``` + +Restart the pod again to import your save file. + + +## Installing mods + +To Install mods, change `mods.enabled` to `true`, add any offical mods by their URL name under the `mods.portal` +section, and any unofficial mods in the `mods.unofficial`section. + + +```yaml +mods: + image: + repository: "ghcr.io/sqljames/factorio-mod-downloader" + ## Container image pull policy + pullPolicy: Always + ## Overrides the image tag whose default is the chart appVersion. + tag: "1.0.1" + ## You should set an fix version, i.e.: + # tag: "1.1.37" + enabled: false +# in order to use the mods portal you will need to specify the username and token in the server_settings. + portal: [] +# - name: factorissimo-2-notnotmelon +# version: 3.5.11 +# unofficial section is meant to just allow you to download and place folders into the mods folder. +# we will not check version compatibility automatically with these downloads. +# you can encounter an error if the file names dont match what the mod is expecting for example +# Error Util.cpp:83: Failed to load mod "Squeak-Through": Filename of mod +# /factorio/mods/Squeak-Through.zip doesn't match the expected Squeak Through_1.8.2.zip (case sensitive!) + unofficial: [] +# - url: "https://github.com/Suprcheese/Squeak-Through/archive/refs/tags/1.8.2.zip" +# name: "Squeak Through_1.8.2.zip" +``` +If the Factorio server doesn't start, check that the logs don't have an error with the mods. They are pretty verbose. + +### Overhaul mods +It is possible that your mod may extend the default settings. As a result, your server might not start properly and instead throw an error. + +While we expose all the default settings, we would not be able to determine what is needed if it is absent. To add new settings you would need to convert the desired json file into a yaml struct as we are mounting all configurations as a config map into the container. + +For example prior to the official release of 2.0, there was an issue with Space Exploration. The `autoplace_controls` by default is an empty array, and thus we were not able to start the instance as there were no settings for them to evaluate. Additionally, they are also modifying some of the other settings. These changes implement the default recommended settings, available in the UI and were stored in a file at `...Factorio\mods\space-exploration\shared.lua`. In the lua file, it has 2 sections, basic_settings and advanced_settings which correspond to settings in `map-gen-settings.json` and `map-settings.json` respecively. + +At the time of writing, to make these changes you would need to add this to your values.yaml file to override their default values in the chart. + +> **_NOTE:_** These settings may change and it is important to check with the mod maintainer/community to check the recommended settings. +``` +map_settings: + pollution: + enemy_attack_pollution_consumption_modifier: 0.5 + enemy_evolution: + time_factor: 0.0000005 + destroy_factor: 0.0005 + pollution_factor: 0.00000025 + +map_gen_settings: + water: 1.5 + starting_area: 2 + autoplace_controls: + hot: + size: 0.5 + cold: + size: 0.5 + property_expression_names: + control-setting:moisture:bias: '0.05' + control-setting:aux:bias: '-0.35' +``` +More information about the debugging process for the space exploration mod can be read on [Issue 24](https://github.com/SQLJames/factorio-server-charts/issues/24). + +If you do run into any issues with mods, I will try to work with you on finding the right settings and document them as well. + +{{ if .Chart.Values -}} + +## Configuration + +The following table lists the configurable parameters of the `{{ .Chart.Name }}` chart and their default values. + +{{ .Chart.Values }} + +Specify each parameter using the `--set key=value[,key=value]` argument to `helm upgrade -i`. For example: + +```bash +$ helm upgrade -i {{ .Release.Name }} {{ .Repository.Name }}/{{ .Chart.Name }} -n {{ .Release.Namespace }} --create-namespace --set {{ .Chart.ValuesExample }} +``` + +Alternatively, a YAML file that specifies the values for the parameters can be provided while +installing the chart. For example: + +```bash +$ helm upgrade -i {{ .Release.Name }} {{ .Repository.Name }}/{{ .Chart.Name }} -n {{ .Release.Namespace }} --create-namespace --values values.yaml +``` +{{- end }} + +## Releases + +Releases are published using the official helm release action in github. +https://github.com/helm/chart-releaser-action \ No newline at end of file diff --git a/charts/factorio-server-charts/values.schema.json b/charts/factorio-server-charts/values.schema.json index 8e094df..a326557 100644 --- a/charts/factorio-server-charts/values.schema.json +++ b/charts/factorio-server-charts/values.schema.json @@ -1,42 +1,860 @@ { - "$schema": "http://json-schema.org/draft-07/schema", - "$id": "http://example.com/example.json", - "type": "object", - "title": "The root schema", - "default": {}, - "required": [ - "rcon" - ], - "properties": { - "rcon": { - "$id": "#/properties/rcon", - "type": "object", - "title": "The rcon schema", - "description": "houses the information about the rcon service", - "default": {}, - "examples": [ - { - "password": "1234Test" - } - ], - "required": [ - "password" - ], - "properties": { - "password": { - "$id": "#/properties/rcon/properties/password", - "type": "string", - "minLength": 15, - "title": "The password schema", - "description": "Sets rcon password", - "default": "", - "examples": [ - "1234Test" - ] - } - }, - "additionalProperties": true - } - }, - "additionalProperties": true + "$schema": "http://json-schema.org/schema#", + "type": "object", + "properties": { + "account": { + "type": "object", + "properties": { + "accountSecret": { + "type": "string" + }, + "password": { + "type": "string" + }, + "token": { + "type": "string" + }, + "username": { + "type": "string" + } + } + }, + "admin_list": { + "type": "array" + }, + "affinity": { + "type": "object" + }, + "ban_list": { + "type": "array" + }, + "factorioServer": { + "type": "object", + "properties": { + "enable_space_age": { + "type": "boolean" + }, + "env": { + "type": "object" + }, + "generate_new_save": { + "type": "boolean" + }, + "load_latest_save": { + "type": "boolean" + }, + "port": { + "type": "integer" + }, + "rcon_port": { + "type": "integer" + }, + "save_name": { + "type": "string" + }, + "update_mods_on_start": { + "type": "boolean" + } + } + }, + "hostNetworkEnabled": { + "type": "boolean" + }, + "image": { + "type": "object", + "properties": { + "pullPolicy": { + "type": "string" + }, + "repository": { + "type": "string" + }, + "tag": { + "type": "string" + } + } + }, + "import_save": { + "type": "object", + "properties": { + "enabled": { + "type": "boolean" + }, + "reimport_every_time": { + "type": "boolean" + }, + "reimport_on_change": { + "type": "boolean" + }, + "source_url": { + "type": "string" + } + } + }, + "map_gen_settings": { + "type": "object", + "properties": { + "autoplace_controls": { + "type": "object" + }, + "cliff_settings": { + "type": "object", + "properties": { + "cliff_elevation_0": { + "type": "integer" + }, + "cliff_elevation_interval": { + "type": "integer" + }, + "name": { + "type": "string" + }, + "richness": { + "type": "integer" + } + } + }, + "height": { + "type": "integer" + }, + "peaceful_mode": { + "type": "boolean" + }, + "property_expression_names": { + "type": "object", + "properties": { + "control:aux:bias": { + "type": "string" + }, + "control:aux:frequency": { + "type": "string" + }, + "control:moisture:bias": { + "type": "string" + }, + "control:moisture:frequency": { + "type": "string" + } + } + }, + "seed": { + "type": "null" + }, + "starting_area": { + "type": "integer" + }, + "starting_points": { + "type": "array", + "items": { + "type": "object", + "properties": { + "x": { + "type": "integer" + }, + "y": { + "type": "integer" + } + } + } + }, + "width": { + "type": "integer" + } + } + }, + "map_settings": { + "type": "object", + "properties": { + "asteroids": { + "type": "object", + "properties": { + "max_ray_portals_expanded_per_tick": { + "type": "integer" + }, + "spawning_rate": { + "type": "integer" + } + } + }, + "difficulty_settings": { + "type": "object", + "properties": { + "spoil_time_modifier": { + "type": "integer" + }, + "technology_price_multiplier": { + "type": "integer" + } + } + }, + "enemy_evolution": { + "type": "object", + "properties": { + "destroy_factor": { + "type": "number" + }, + "enabled": { + "type": "boolean" + }, + "pollution_factor": { + "type": "number" + }, + "time_factor": { + "type": "number" + } + } + }, + "enemy_expansion": { + "type": "object", + "properties": { + "building_coefficient": { + "type": "number" + }, + "enabled": { + "type": "boolean" + }, + "enemy_building_influence_radius": { + "type": "integer" + }, + "friendly_base_influence_radius": { + "type": "integer" + }, + "max_colliding_tiles_coefficient": { + "type": "number" + }, + "max_expansion_cooldown": { + "type": "integer" + }, + "max_expansion_distance": { + "type": "integer" + }, + "min_expansion_cooldown": { + "type": "integer" + }, + "neighbouring_base_chunk_coefficient": { + "type": "number" + }, + "neighbouring_chunk_coefficient": { + "type": "number" + }, + "other_base_coefficient": { + "type": "integer" + }, + "settler_group_max_size": { + "type": "integer" + }, + "settler_group_min_size": { + "type": "integer" + } + } + }, + "max_failed_behavior_count": { + "type": "integer" + }, + "path_finder": { + "type": "object", + "properties": { + "cache_accept_path_end_distance_ratio": { + "type": "number" + }, + "cache_accept_path_start_distance_ratio": { + "type": "number" + }, + "cache_max_connect_to_cache_steps_multiplier": { + "type": "integer" + }, + "cache_path_end_distance_rating_multiplier": { + "type": "integer" + }, + "cache_path_start_distance_rating_multiplier": { + "type": "integer" + }, + "direct_distance_to_consider_short_request": { + "type": "integer" + }, + "enemy_with_different_destination_collision_penalty": { + "type": "integer" + }, + "extended_collision_penalty": { + "type": "integer" + }, + "fwd2bwd_ratio": { + "type": "integer" + }, + "general_entity_collision_penalty": { + "type": "integer" + }, + "general_entity_subsequent_collision_penalty": { + "type": "integer" + }, + "goal_pressure_ratio": { + "type": "integer" + }, + "ignore_moving_enemy_collision_distance": { + "type": "integer" + }, + "long_cache_min_cacheable_distance": { + "type": "integer" + }, + "long_cache_size": { + "type": "integer" + }, + "max_clients_to_accept_any_new_request": { + "type": "integer" + }, + "max_clients_to_accept_short_new_request": { + "type": "integer" + }, + "max_steps_worked_per_tick": { + "type": "integer" + }, + "max_work_done_per_tick": { + "type": "integer" + }, + "min_steps_to_check_path_find_termination": { + "type": "integer" + }, + "negative_cache_accept_path_end_distance_ratio": { + "type": "number" + }, + "negative_cache_accept_path_start_distance_ratio": { + "type": "number" + }, + "negative_path_cache_delay_interval": { + "type": "integer" + }, + "overload_levels": { + "type": "array", + "items": { + "type": "integer" + } + }, + "overload_multipliers": { + "type": "array", + "items": { + "type": "integer" + } + }, + "short_cache_min_algo_steps_to_cache": { + "type": "integer" + }, + "short_cache_min_cacheable_distance": { + "type": "integer" + }, + "short_cache_size": { + "type": "integer" + }, + "short_request_max_steps": { + "type": "integer" + }, + "short_request_ratio": { + "type": "number" + }, + "stale_enemy_with_same_destination_collision_penalty": { + "type": "integer" + }, + "start_to_goal_cost_multiplier_to_terminate_path_find": { + "type": "number" + }, + "use_path_cache": { + "type": "boolean" + } + } + }, + "pollution": { + "type": "object", + "properties": { + "ageing": { + "type": "integer" + }, + "diffusion_ratio": { + "type": "number" + }, + "enabled": { + "type": "boolean" + }, + "enemy_attack_pollution_consumption_modifier": { + "type": "integer" + }, + "expected_max_per_chunk": { + "type": "integer" + }, + "max_pollution_to_restore_trees": { + "type": "integer" + }, + "min_pollution_to_damage_trees": { + "type": "integer" + }, + "min_to_diffuse": { + "type": "integer" + }, + "min_to_show_per_chunk": { + "type": "integer" + }, + "pollution_per_tree_damage": { + "type": "integer" + }, + "pollution_restored_per_tree_damage": { + "type": "integer" + }, + "pollution_with_max_forest_damage": { + "type": "integer" + } + } + }, + "steering": { + "type": "object", + "properties": { + "default": { + "type": "object", + "properties": { + "force_unit_fuzzy_goto_behavior": { + "type": "boolean" + }, + "radius": { + "type": "number" + }, + "separation_factor": { + "type": "number" + }, + "separation_force": { + "type": "number" + } + } + }, + "moving": { + "type": "object", + "properties": { + "force_unit_fuzzy_goto_behavior": { + "type": "boolean" + }, + "radius": { + "type": "integer" + }, + "separation_factor": { + "type": "integer" + }, + "separation_force": { + "type": "number" + } + } + } + } + }, + "unit_group": { + "type": "object", + "properties": { + "max_gathering_unit_groups": { + "type": "integer" + }, + "max_group_gathering_time": { + "type": "integer" + }, + "max_group_member_fallback_factor": { + "type": "integer" + }, + "max_group_radius": { + "type": "integer" + }, + "max_group_slowdown_factor": { + "type": "number" + }, + "max_member_slowdown_when_ahead": { + "type": "number" + }, + "max_member_speedup_when_behind": { + "type": "number" + }, + "max_unit_group_size": { + "type": "integer" + }, + "max_wait_time_for_late_members": { + "type": "integer" + }, + "member_disown_distance": { + "type": "integer" + }, + "min_group_gathering_time": { + "type": "integer" + }, + "min_group_radius": { + "type": "integer" + }, + "tick_tolerance_when_member_arrives": { + "type": "integer" + } + } + } + } + }, + "mods": { + "type": "object", + "properties": { + "enabled": { + "type": "boolean" + }, + "image": { + "type": "object", + "properties": { + "pullPolicy": { + "type": "string" + }, + "repository": { + "type": "string" + }, + "tag": { + "type": "string" + } + } + }, + "portal": { + "type": "array" + }, + "unofficial": { + "type": "array" + } + } + }, + "nodeSelector": { + "type": "object" + }, + "persistence": { + "type": "object", + "properties": { + "annotations": { + "type": "object" + }, + "dataDir": { + "type": "object", + "properties": { + "Size": { + "type": "string" + } + } + }, + "enabled": { + "type": "boolean" + }, + "labels": { + "type": "object" + }, + "storageClassName": { + "type": "string" + } + } + }, + "podSecurityContext": { + "type": "object", + "properties": { + "runAsGroup": { + "type": "integer" + }, + "runAsUser": { + "type": "integer" + } + } + }, + "port_fixer": { + "type": "object", + "properties": { + "enabled": { + "type": "boolean" + }, + "image": { + "type": "object", + "properties": { + "pullPolicy": { + "type": "string" + }, + "repository": { + "type": "string" + }, + "tag": { + "type": "string" + } + } + }, + "port": { + "type": "string" + } + } + }, + "rcon": { + "type": "object", + "properties": { + "external": { + "type": "boolean" + }, + "ipFamilies": { + "type": "array", + "items": { + "type": "string" + } + }, + "ipFamilyPolicy": { + "type": "string" + }, + "password": { + "type": "string" + }, + "passwordSecret": { + "type": "string" + }, + "port": { + "type": "integer" + }, + "serviceAnnotations": { + "type": "object" + }, + "type": { + "type": "string" + } + } + }, + "rconAPI": { + "type": "object", + "properties": { + "enabled": { + "type": "boolean" + }, + "grpcPort": { + "type": "integer" + }, + "httpPort": { + "type": "integer" + }, + "image": { + "type": "object", + "properties": { + "pullPolicy": { + "type": "string" + }, + "repository": { + "type": "string" + }, + "tag": { + "type": "string" + } + } + }, + "ingress": { + "type": "object", + "properties": { + "annotations": { + "type": "object", + "properties": { + "nginx.ingress.kubernetes.io/backend-protocol": { + "type": "string" + }, + "nginx.ingress.kubernetes.io/ssl-redirect": { + "type": "string" + } + } + }, + "className": { + "type": "string" + }, + "enabled": { + "type": "boolean" + }, + "hostname": { + "type": "string" + }, + "tls": { + "type": "object", + "properties": { + "enabled": { + "type": "boolean" + }, + "secretName": { + "type": "string" + } + } + } + } + }, + "ipFamilies": { + "type": "array", + "items": { + "type": "string" + } + }, + "ipFamilyPolicy": { + "type": "string" + }, + "serviceAnnotations": { + "type": "object" + }, + "type": { + "type": "string" + } + } + }, + "replicaCount": { + "type": "integer" + }, + "resources": { + "type": "object", + "properties": { + "limits": { + "type": "object" + }, + "requests": { + "type": "object", + "properties": { + "cpu": { + "type": "string" + }, + "memory": { + "type": "string" + } + } + } + } + }, + "securityContext": { + "type": "object", + "properties": { + "fsGroup": { + "type": "integer" + } + } + }, + "serverPassword": { + "type": "object", + "properties": { + "game_password": { + "type": "string" + }, + "passwordSecret": { + "type": "string" + } + } + }, + "server_settings": { + "type": "object", + "properties": { + "afk_autokick_interval": { + "type": "integer" + }, + "allow_commands": { + "type": "string" + }, + "auto_pause": { + "type": "boolean" + }, + "auto_pause_when_players_connect": { + "type": "boolean" + }, + "autosave_interval": { + "type": "integer" + }, + "autosave_only_on_server": { + "type": "boolean" + }, + "autosave_slots": { + "type": "integer" + }, + "description": { + "type": "string" + }, + "ignore_player_limit_for_returning_players": { + "type": "boolean" + }, + "max_heartbeats_per_second": { + "type": "integer" + }, + "max_players": { + "type": "integer" + }, + "max_upload_in_kilobytes_per_second": { + "type": "integer" + }, + "max_upload_slots": { + "type": "integer" + }, + "maximum_segment_size": { + "type": "integer" + }, + "maximum_segment_size_peer_count": { + "type": "integer" + }, + "minimum_latency_in_ticks": { + "type": "integer" + }, + "minimum_segment_size": { + "type": "integer" + }, + "minimum_segment_size_peer_count": { + "type": "integer" + }, + "name": { + "type": "string" + }, + "non_blocking_saving": { + "type": "boolean" + }, + "only_admins_can_pause_the_game": { + "type": "boolean" + }, + "require_user_verification": { + "type": "boolean" + }, + "tags": { + "type": "array", + "items": { + "type": "string" + } + }, + "visibility": { + "type": "object", + "properties": { + "lan": { + "type": "boolean" + }, + "public": { + "type": "boolean" + } + } + } + } + }, + "service": { + "type": "object", + "properties": { + "annotations": { + "type": "object" + }, + "ipFamilies": { + "type": "array", + "items": { + "type": "string" + } + }, + "ipFamilyPolicy": { + "type": "string" + }, + "port": { + "type": "integer" + }, + "type": { + "type": "string" + } + } + }, + "strategy": { + "type": "object", + "properties": { + "type": { + "type": "string" + } + } + }, + "tolerations": { + "type": "array" + }, + "white_list": { + "type": "array" + } + } } diff --git a/helm-output.yaml b/helm-output.yaml deleted file mode 100644 index c0e8bbf..0000000 Binary files a/helm-output.yaml and /dev/null differ diff --git a/makefile b/makefile new file mode 100644 index 0000000..fa8a80d --- /dev/null +++ b/makefile @@ -0,0 +1,21 @@ +.PHONY: gen +gen: gen-chart-doc + +.PHONY: gen-chart-doc +gen-chart-doc: + @echo "Generate chart docs" + @chart-doc-gen -t=./charts/factorio-server-charts/readme.tpl -d=./charts/factorio-server-charts/doc.yaml -v=./charts/factorio-server-charts/values.yaml > ./charts/factorio-server-charts/README.md + +.PHONY: gen-schema +gen-schema: + @echo "Generate helm schema json" + @helm schema-gen ./charts/factorio-server-charts/values.yaml > ./charts/factorio-server-charts/values.schema.json + +.PHONY: verify +verify: verify-gen + +.PHONY: verify-gen +verify-gen: + @if !(git diff --exit-code HEAD); then \ + echo "generated files are out of date, run make gen"; exit 1; \ + fi \ No newline at end of file