Skip to content

Commit 8e2d159

Browse files
author
zone-zero
committed
updated save importer
1 parent 7e74308 commit 8e2d159

File tree

4 files changed

+198
-40
lines changed

4 files changed

+198
-40
lines changed

charts/factorio-server-charts/README.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -235,7 +235,10 @@ If you do run into any issues with mods, I will try to work with you on finding
235235
| `factorioServer.generate_new_save` | Generate a new save if `save_name` is not found | `true` |
236236
| `factorioServer.update_mods_on_start` | Update mods on server start | `false` |
237237
| `factorioServer.load_latest_save` | Lets the game know if you want to load the latest save | `true` |
238-
| `factorioServer.import_save` | Import an existing save file from '/factorio/save_to_import'. **:warning: Overwrites existing save** | `true` |
238+
| `import_save.enabled` | Enable save importer. Importer runs at every pod initialization. **:warning: Overwrites existing save if successful** | `true` |
239+
| `import_save.source_url` | Full URL (including http(s)://). If left blank, saves can still be imported by placing in '/factorio/save-importer/import' | `""` |
240+
| `import_save.reimport_on_change` | Reimport save file from source_url when checksum changes. File will be downloaded at every pod initialization. | `false` |
241+
| `import_save.reimport_every_time` | Reimport save file from source_url at every pod intialization. Useful for resetting demos or testing. | `false` |
239242
| `account.accountSecret` | Existing secret containing a valid factorio.com username and either a password or a token (or both) | `""` |
240243
| `account.username` | Factorio.com username, ignored if `account.accountSecret` is set | `""` |
241244
| `account.password` | Factorio.com password, ignored if `account.accountSecret` is set | `""` |

charts/factorio-server-charts/templates/deployment.yaml

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -103,16 +103,14 @@ spec:
103103
mountPath: /account
104104
{{- end }}
105105
{{- end }}
106-
{{- if .Values.factorioServer.import_save }}
106+
{{- if .Values.import_save.enabled }}
107107
- name: import-factorio-save
108108
image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
109109
imagePullPolicy: {{ .Values.image.pullPolicy }}
110110
command:
111111
- /bin/bash
112112
- -ec
113113
- |
114-
mkdir -p /factorio/save_to_import
115-
mkdir -p /factorio/saves
116114
bash /scripts/save-importer.sh
117115
{{- with .Values.securityContext }}
118116
securityContext:

charts/factorio-server-charts/templates/save-importer-configmap.yaml

Lines changed: 181 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -9,51 +9,199 @@ metadata:
99
heritage: "{{ .Release.Service }}"
1010
data:
1111
save-importer.sh: |
12-
message_prefix="save-importer: "
13-
source_dir="/factorio/save_to_import"
12+
#directory where file at $source_url will be downloaded to
13+
download_dir="/factorio/save-importer/download"
14+
15+
#directory where files from $source_url that meet staging criteria will be downloaded to
16+
#OR where files can be manually placed for import regardless of criteria.
17+
staging_dir="/factorio/save-importer/import"
18+
19+
#file used to record checksums and urls of previously downloaded files
20+
import_data="/factorio/save-importer/import_data.txt"
21+
1422
target_dir="/factorio/saves"
15-
target_filename="{{ .Values.factorioServer.save_name }}.zip"
23+
app_name="factorio"
24+
file_extension=".zip" #note, this is used both for searching the staging_dir and displaying messages to the user
25+
file_type="save"
26+
27+
#config read from values.yaml
28+
target_filename="{{ .Values.factorioServer.save_name }}.zip" #name for the downloaded file
29+
source_url="{{ .Values.import_save.source_url }}"
30+
reimport_on_file_change={{ .Values.import_save.reimport_on_change | int }}
31+
reimport_every_time={{ .Values.import_save.reimport_every_time | int }}
1632
1733
18-
# Check if the source dir exists
19-
if [ ! -d "$source_dir" ]; then
20-
mkdir -p "$source_dir"
34+
main() {
35+
echo "starting $file_type import process"
36+
37+
build_import_structure
38+
39+
if [ "${#source_url}" -gt 0 ]; then
40+
echo "source_url $source_url provided. checking..."
41+
download_file
42+
stage_downloaded_file
43+
else
44+
echo "no download url specified. checking $staging_dir for manually staged files..."
2145
fi
2246
23-
# Count the number of save files in the source dir
24-
# luckily the factorio docker image incldues find
25-
count=$(find "$source_dir" -maxdepth 1 -type f -name "*.zip" | wc -l)
47+
import_file
48+
}
2649
27-
if [ "$count" -eq 1 ]; then
28-
save_file=$(find "$source_dir" -maxdepth 1 -type f -name "*.zip")
29-
echo "$message_prefix Found save file to import - '$save_file'."
30-
echo "$message_prefix Starting save import process."
31-
# Copy and rename the file
32-
cp -f "$save_file" "$target_dir/$target_filename"
33-
if [ $? -eq 0 ]; then
34-
# Copy was successful
35-
echo "$message_prefix File copied to '$target_dir/$target_filename'."
36-
37-
# Touch the new copy to be _certain_ it's the latest file
38-
touch "$target_dir/$target_filename"
39-
40-
# Delete the original file, so we don't reimport it again
41-
rm "$save_file"
42-
echo "$message_prefix Original file '$save_file' deleted."
50+
get_sha256sum() {
51+
sha256sum "$1" | awk '{ print $1 }'
52+
}
53+
54+
get_previous_sha256sum() {
55+
echo $(grep "^${source_url}::" "$import_data" | awk -F '::' '{print $NF}')
56+
}
57+
58+
build_import_structure() {
59+
# staging_dir
60+
if [ ! -d "$staging_dir" ]; then
61+
mkdir -p "$staging_dir"
62+
fi
63+
64+
# download_dir
65+
if [ ! -d "$download_dir" ]; then
66+
mkdir -p "$download_dir"
67+
fi
68+
69+
# target_dir
70+
if [ ! -d "$target_dir" ]; then
71+
mkdir -p "$target_dir"
72+
fi
73+
74+
# data file
75+
if [ ! -f "$import_data" ]; then
76+
touch "$import_data"
77+
fi
78+
}
79+
80+
download_file() {
81+
do_download=0
82+
if [ "$reimport_every_time" -eq 1 ]; then
83+
do_download=1
84+
echo "reimport_every_time is set to true."
85+
else
86+
echo "reimport_every_time is set to false."
87+
fi
88+
89+
if [ "$reimport_on_file_change" -eq 1 ]; then
90+
do_download=1
91+
echo "reimport_on_file_change is set to true."
92+
else
93+
echo "reimport_on_file_change is set to false."
94+
fi
95+
96+
if ! grep -q "$source_url" "$import_data"; then
97+
do_download=1
98+
echo "source '$source_url' not previously downloaded."
99+
else
100+
echo "source '$source_url' previously downloaded."
101+
fi
102+
103+
if [ "$do_download" -eq 1 ]; then
104+
echo "downloading '$source_url'..."
105+
if curl -L -o "$download_dir/$target_filename" "$source_url"; then
106+
echo "$file_type file downloaded from '$source_url' and renamed '$target_filename'"
43107
else
44-
echo "$message_prefix Error copying the file."
45-
exit 1
108+
echo "unable to download $file_type file from '$source_url'. skipping import process."
109+
exit 0
46110
fi
47-
elif [ "$count" -eq 0 ]; then
48-
echo "$message_prefix No save file found in '$source_dir'"
49-
echo "$message_prefix Skipping save import process."
111+
else
112+
echo "conditions not met to download file."
113+
fi
114+
}
115+
116+
117+
118+
write_sha256sum () {
119+
echo "writing checksum of '$source_url' download to '$import_data' file for future runs of the import script."
120+
if grep -q "^${source_url}::" "$import_data"; then
121+
# Update the checksum if the file entry already exists (escape any ampersands!)
122+
sed -i "s~^${source_url}::.*~${source_url//&/\\&}::${checksum}~" "$import_data"
50123
else
51-
echo "$message_prefix Multiple save files found in '$source_dir'"
52-
echo "$message_prefix Put only one factorio save zip file in '$source_dir' to enable the import process."
53-
echo "$message_prefix Skipping save import process."
124+
# Append the new entry to the checksum file if it doesn't exist
125+
echo "${source_url}::${checksum}" >> "$import_data"
54126
fi
127+
}
128+
129+
130+
stage_downloaded_file(){
131+
stage_file=0
132+
if [ -e "$download_dir/$target_filename" ]; then
133+
#get checksum of file, and any previous checksums that might exist for this source url
134+
checksum=$(get_sha256sum "$download_dir/$target_filename")
135+
previous_checksum=$(get_previous_sha256sum "$source_url")
136+
echo "previous checksum: $previous_checksum"
55137
138+
if [ "$reimport_every_time" -eq 1 ]; then
139+
stage_file=1
140+
echo "reimport_every_time flag is set. file will be staged for import"
141+
fi
56142
143+
if [ -z "$previous_checksum" ]; then
144+
stage_file=1
145+
echo "no record found of a previous download for this file. file will be staged for import."
146+
fi
57147
148+
if [ "$checksum" != "$previous_checksum" -a "$reimport_on_file_change" ]; then
149+
echo "file from '$source_url' has changed since we last downloaded it..."
150+
if [ "$reimport_on_file_change" -eq 1 ]; then
151+
stage_file=1
152+
echo "...and 'reimport_on_file_change' is enabled. file will be staged for import"
153+
else
154+
echo "...but 'reimport_on_file_change' is disabled. file will NOT be staged for import"
155+
fi
156+
else
157+
echo "file from '$source_url' has NOT changed since we last downloaded it..."
158+
fi
58159
160+
if [ "$stage_file" -eq 1 ]; then
161+
echo "file downloaded from $source_url meets conditions for import. Moving to $staging_dir to prepare for $file_type import."
162+
write_sha256sum
163+
mv -f "$download_dir/$target_filename" "$staging_dir"
164+
else
165+
echo "file downloaded from $source_url does not meet conditions for import. Deleting the downloaded file."
166+
rm -f "$download_dir/$target_filename"
167+
fi
168+
else
169+
echo "target file not found in download directory. checking $staging_dir for manually staged files."
170+
fi
171+
}
172+
173+
import_file() {
174+
# Count the number of files with the $file_extension in the source dir
175+
count=$(find "$staging_dir" -maxdepth 1 -type f -name "*$file_extension" | wc -l)
176+
177+
if [ "$count" -eq 1 ]; then
178+
file_to_import=$(find "$staging_dir" -maxdepth 1 -type f -name "*$file_extension")
179+
echo "Found $file_type file to import - '$file_to_import'."
180+
echo "Copying '$file_to_import' to '$target_dir/$target_filename'. This will replace any previously existing file at this destination."
181+
# Copy and rename the file
182+
cp -f "$file_to_import" "$target_dir/$target_filename"
183+
if [ $? -eq 0 ]; then
184+
# Copy was successful
185+
echo "File copied to '$target_dir/$target_filename'."
186+
187+
# Touch the new copy to be _certain_ it's the latest file
188+
touch "$target_dir/$target_filename"
189+
190+
# Delete the original file, so we don't reimport it again
191+
rm "$file_to_import"
192+
echo "staging file '$file_to_import' deleted."
193+
else
194+
echo "Error copying the file."
195+
exit 1
196+
fi
197+
elif [ "$count" -eq 0 ]; then
198+
echo "No $file_type file found in '$staging_dir'"
199+
echo "Skipping $file_type import process."
200+
else
201+
echo "Multiple $file_type files found in '$staging_dir'"
202+
echo "Put only one $app_name $file_type $file_extension file in '$staging_dir' to enable the import process."
203+
echo "Skipping $file_type import process."
204+
fi
205+
}
59206
207+
main

charts/factorio-server-charts/values.yaml

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -153,9 +153,18 @@ factorioServer:
153153
update_mods_on_start: false
154154
# lets the game know if you want to load the latest save
155155
load_latest_save: true
156-
# import a save file if it exists in /factorio/save_to_import
157-
# WARNING: this will overwrite your existing save game with the name specified in factorioServer.save_name.
158-
import_save: true
156+
157+
158+
import_save:
159+
#enable save importer
160+
enabled: true
161+
#url to download save from (http or https only).
162+
#if no url is specified, saves can still be manually imported by placing the file in "/factorio/save-importer/import"
163+
source_url: ""
164+
#reimport from the source_url if the checksum of the file changes
165+
reimport_on_change: false
166+
#reimport from the source_url AND OVERWRITE PREVIOUS SAVE every time pod is initialized. good for demos or testing
167+
reimport_every_time: false
159168

160169
## @param account.accountSecret Existing secret containing a valid factorio.com username and either a password or a token (or both)
161170
## @param account.username Factorio.com username, ignored if `account.accountSecret` is set

0 commit comments

Comments
 (0)