58 lines
2.9 KiB
Python
58 lines
2.9 KiB
Python
#!/usr/bin/env python3
|
|
"""Cross-shell safeguards for real Compose volume names and existing bind paths."""
|
|
import json
|
|
import os
|
|
from pathlib import Path
|
|
import shutil
|
|
import subprocess
|
|
import tempfile
|
|
|
|
source = Path(__file__).resolve().parent.parent
|
|
with tempfile.TemporaryDirectory(prefix='easyai-storage-check-') as temporary:
|
|
root = Path(temporary)
|
|
(root / 'upload').mkdir()
|
|
(root / 'compose.yml').write_text('''name: fixture-project
|
|
services:
|
|
mongo:
|
|
container_name: fixture-mongo
|
|
image: mongo:7
|
|
volumes: [database:/data/db]
|
|
easyai-server:
|
|
container_name: fixture-server
|
|
image: alpine:3
|
|
volumes: [./upload:/app/upload]
|
|
volumes:
|
|
database:
|
|
name: existing-database
|
|
''')
|
|
configuration = subprocess.check_output(['docker','compose','config','--format','json'], cwd=root, text=True)
|
|
(root / 'config.json').write_text(configuration)
|
|
binaries = root / 'bin'
|
|
binaries.mkdir()
|
|
docker = binaries / 'docker'
|
|
docker.write_text('''#!/usr/bin/env python3
|
|
import json,os,sys
|
|
from pathlib import Path
|
|
args=sys.argv[1:]
|
|
if args[:2]==['compose','config']: print(Path('config.json').read_text());sys.exit(0)
|
|
if args[:1]==['info']:sys.exit(0)
|
|
if args[:2]==['container','inspect']:
|
|
project='another-project' if os.environ['STORAGE_CASE']=='wrong-project' else 'fixture-project'
|
|
mount={'Type':'volume','Name':'old-database' if os.environ['STORAGE_CASE']=='changed-volume' else 'existing-database','Destination':'/data/db'}
|
|
if args[-1]=='fixture-server':mount={'Type':'bind','Source':str(Path('upload').resolve()),'Destination':'/app/upload'}
|
|
print(json.dumps([{'Config':{'Labels':{'com.docker.compose.project':project}},'Mounts':[mount]}]));sys.exit(0)
|
|
sys.exit(1)
|
|
''')
|
|
docker.chmod(0o755)
|
|
script = root / 'check.ps1'
|
|
script.write_text('param($Runtime)\n$ErrorActionPreference="Stop"\n. $Runtime\n$selection = @($env:STORAGE_SELECTED -split " " | Where-Object { $_ })\nTest-DeploymentStorage -ComposeCommand @("docker","compose") -Services $selection\n')
|
|
for case, selected, success in [('same-storage','',True),('wrong-project','',False),('changed-volume','',False),('changed-volume','easyai-server',True),('missing-bind','',False)]:
|
|
if case == 'missing-bind': (root / 'upload').rmdir()
|
|
env = {**os.environ, 'PATH':str(binaries)+os.pathsep+os.environ['PATH'], 'STORAGE_CASE':case, 'STORAGE_SELECTED':selected}
|
|
commands = [(['python3',str(source/'scripts/check-deployment-storage.py'),'--services',*selected.split()], configuration),
|
|
(['pwsh','-NoProfile','-NonInteractive','-File',str(script),str(source/'scripts/DeploymentRuntime.ps1')], None)]
|
|
for command, stdin in commands:
|
|
result = subprocess.run(command, input=stdin, cwd=root, env=env, capture_output=True, text=True, timeout=90)
|
|
assert (result.returncode == 0) == success, (case, selected, result.stdout, result.stderr)
|
|
print(case + '/' + (selected or 'all') + ': passed in Python/Bash and PowerShell')
|