|
| 1 | + |
| 2 | + |
| 3 | +import json |
| 4 | +import jsonschema |
| 5 | +import base64 |
| 6 | +import os |
| 7 | + |
| 8 | +# Validate JSON file against OpenRecon schema and write Dockerfile |
| 9 | +toolName = os.getenv('toolName') |
| 10 | + |
| 11 | +jsonFilePath = toolName + '/OpenReconLabel.json' |
| 12 | +schemaFilePath = 'OpenReconSchema_1.1.0.json' |
| 13 | +dockerfilePath = toolName + '/OpenRecon.dockerfile' |
| 14 | +baseDockerImage = os.getenv('baseDockerImage') |
| 15 | + |
| 16 | +def validateJson(jsonFilePath, schemaFilePath): |
| 17 | + try: |
| 18 | + # Load the JSON data from the file |
| 19 | + with open(jsonFilePath, 'r') as jsonFile: |
| 20 | + jsonData = json.load(jsonFile) |
| 21 | + |
| 22 | + # Load the JSON schema from the file |
| 23 | + with open(schemaFilePath, 'r') as schemaFile: |
| 24 | + schemaData = json.load(schemaFile) |
| 25 | + |
| 26 | + # Create a JSON Schema validator |
| 27 | + validator = jsonschema.Draft7Validator(schemaData) |
| 28 | + |
| 29 | + # Validate the JSON data against the schema |
| 30 | + errors = list(validator.iter_errors(jsonData)) |
| 31 | + |
| 32 | + if not errors: |
| 33 | + print("JSON is valid against the schema.") |
| 34 | + return True |
| 35 | + else: |
| 36 | + print("JSON is not valid against the schema. Errors:") |
| 37 | + for error in errors: |
| 38 | + print(error) |
| 39 | + return False |
| 40 | + |
| 41 | + except Exception as e: |
| 42 | + print(f"An error occurred: {e}") |
| 43 | + |
| 44 | +# Write Dockerfile |
| 45 | +if validateJson(jsonFilePath, schemaFilePath): |
| 46 | + with open(jsonFilePath, 'r') as jsonFile: |
| 47 | + jsonData = json.load(jsonFile) |
| 48 | + jsonString = json.dumps(jsonData, indent=2) |
| 49 | + encodedJson = base64.b64encode(jsonString.encode('utf-8')).decode('utf-8') |
| 50 | + |
| 51 | + with open(dockerfilePath, 'w') as file: |
| 52 | + labelName = 'com.siemens-healthineers.magneticresonance.openrecon.metadata:1.1.0' |
| 53 | + labelStr = 'LABEL "' + labelName + '"="' + encodedJson + '"' |
| 54 | + |
| 55 | + file.writelines('FROM ' + baseDockerImage) |
| 56 | + file.writelines('\n' + labelStr) |
| 57 | + print('Wrote Dockerfile:', os.path.abspath(dockerfilePath)) |
| 58 | +else: |
| 59 | + raise Exception('Not writing Dockerfile because JSON is not valid') |
| 60 | + |
| 61 | +# Build Docker image, save to a .tar file, and package into a .zip file for OpenRecon |
| 62 | +# The documentation must be a valid PDF! |
| 63 | +# README.pdf is autogenerated from README.md, but if it should be overwritten with a dedicated docs.pdf thats's possible |
| 64 | +if os.path.isfile('docs.pdf'): |
| 65 | + docsFile = 'docs.pdf' |
| 66 | +else: |
| 67 | + docsFile = 'README.pdf' |
| 68 | + |
| 69 | +# Filename must match information contained in the JSON |
| 70 | +version = jsonData['general']['version'] |
| 71 | +vendor = jsonData['general']['vendor'] |
| 72 | +name = jsonData['general']['name']['en'] |
| 73 | + |
| 74 | +# Check documentation file exists |
| 75 | +if not os.path.isfile(docsFile): |
| 76 | + raise Exception('Could not find documentation file: ' + docsFile) |
| 77 | + |
| 78 | +# Check 7-zip exists |
| 79 | +zipExe = '/usr/bin/7z' |
| 80 | + |
| 81 | +if not os.path.isfile(zipExe): |
| 82 | + raise Exception('Could not find 7-Zip executable: ' + zipExe + '\nPlease download and install 7-Zip') |
| 83 | + |
| 84 | +dockerImagename = ('OpenRecon_' + vendor + '_' + name + ':' + 'V' + version).lower() |
| 85 | +baseFilename = 'OpenRecon_' + vendor + '_' + name + '_V' + version |
| 86 | + |
| 87 | +import subprocess |
| 88 | +import shutil |
| 89 | + |
| 90 | +try: |
| 91 | + # Build Docker image docker buildx build --platform linux/amd64 |
| 92 | + print('Attempting to create Docker image with tag:', dockerImagename, '...') |
| 93 | + output = subprocess.check_output(['docker', 'buildx', 'build', '--platform', 'linux/amd64', '--no-cache', '--progress=plain', '-t', dockerImagename, '-f', dockerfilePath, './'], stderr=subprocess.STDOUT) |
| 94 | + print('Docker build output:\n' + output.decode('utf-8')) |
| 95 | + |
| 96 | + # Save Docker image to a .tar file |
| 97 | + print('Saving Docker image file with name:', baseFilename + '.tar', '...') |
| 98 | + output = subprocess.check_output(['docker', 'save', '-o', baseFilename + '.tar', dockerImagename], stderr=subprocess.STDOUT) |
| 99 | + print('Docker save output:\n' + output.decode('utf-8')) |
| 100 | + |
| 101 | + # Copy documentation file with appropriate filename |
| 102 | + print('Copying documentation to file with name:', baseFilename + '.pdf', '...') |
| 103 | + try: |
| 104 | + shutil.copy(docsFile, baseFilename + '.pdf') |
| 105 | + print(f'File copied from {docsFile} to {baseFilename}.pdf') |
| 106 | + except IOError as e: |
| 107 | + print(f'An error occurred: {e}') |
| 108 | + |
| 109 | + # Zip into a package |
| 110 | + print('Packaging files into zip with name:', baseFilename + '.zip', '...') |
| 111 | + output = subprocess.check_output([zipExe, 'a', '-tzip', '-mm=Deflate', baseFilename + '.zip', baseFilename + '.tar', baseFilename + '.pdf'], stderr=subprocess.STDOUT) |
| 112 | + print('Zip packaging output:\n' + output.decode('utf-8')) |
| 113 | + |
| 114 | +except subprocess.CalledProcessError as e: |
| 115 | + # If the command returns a non-zero exit status, it will raise a CalledProcessError |
| 116 | + print('Command failed with return code:', e.returncode) |
| 117 | + print('Error output:\n' + e.output.decode('utf-8')) |
| 118 | + |
0 commit comments