Files
factorio/tests/smoke.py
T
feedc0de d1978abb05
Test and deploy Factorio / validate (push) Failing after 12s
Test and deploy Factorio / deploy (push) Skipped
Deploy achievement-safe Factorio 2.0.77 with strict placement, monitoring and limited CD
2026-10-17 13:50:19 +02:00

44 lines
2.7 KiB
Python

"""Boot the actual server image with the actual rendered configuration, then probe/save/restart it."""
import json,os,secrets,subprocess,sys,tempfile,time
from pathlib import Path
import yaml
docs=list(yaml.safe_load_all(Path(sys.argv[1]).read_text()))
d=next(d for d in docs if d['kind']=='Deployment')
c=next(c for c in d['spec']['template']['spec']['containers'] if c['name']=='factorio')
cms={d['metadata']['name']:d['data'] for d in docs if d['kind']=='ConfigMap'}
run=lambda *a,**kw: subprocess.run(a,check=True,**kw)
with tempfile.TemporaryDirectory() as directory:
root=Path(directory)
for name in ['scripts','settings','credentials','data']:(root/name).mkdir()
for folder,name in [('scripts','factorio-scripts'),('settings','factorio-settings')]:
for key,value in cms[name].items():
file=root/folder/key; file.write_text(value); file.chmod(0o755 if key.endswith('.sh') else 0o644)
(root/'credentials/rcon-password').write_text(secrets.token_urlsafe(32))
args=['docker','run','--detach','--name','factorio-smoke-'+secrets.token_hex(5)]
for env in c['env']:args+=['--env',env['name']+'='+env['value']]
for mount in c['volumeMounts']:
folder={'data':'data','scripts':'scripts','settings':'settings','credentials':'credentials'}[mount['name']]
args+=['--volume',f'{root/folder}:{mount["mountPath"]}'+(':ro' if mount.get('readOnly') else '')]
args+=['--entrypoint',c['command'][0],c['image'],*c['command'][1:]]
container=subprocess.check_output(args,text=True).strip()
def ready():
command=c['readinessProbe']['exec']['command']
for _ in range(90):
if subprocess.run(['docker','exec',container,*command],stdout=subprocess.DEVNULL,stderr=subprocess.DEVNULL,timeout=15).returncode==0:return
time.sleep(2)
raise RuntimeError('Server did not pass the production readiness probe')
try:
ready()
run('docker','exec',container,'rcon','/server-save')
run('docker','stop','--time','180',container,stdout=subprocess.DEVNULL)
assert list((root/'data/saves').glob('*.zip')), 'No persistent save'
run('docker','start',container,stdout=subprocess.DEVNULL)
ready()
assert list((root/'data/upgrade-backups').glob('*/*.zip')), 'No pre-upgrade backup'
print('Actual image passed RCON readiness, persistent save, restart, and upgrade-backup checks')
finally:
run('docker','rm','--force',container,stdout=subprocess.DEVNULL)
# The upstream image owns its world files; cleanup through the same image.
run('docker','run','--rm','--volume',f'{root}/data:/cleanup','--entrypoint','sh',c['image'],'-c','rm -rf /cleanup/*',stdout=subprocess.DEVNULL)