Skip to content
Snippets Groups Projects
create_dockerimage.py 6.12 KiB
Newer Older
#!/usr/bin/env python3
import os
import sys
import string
import shutil
import argparse
import subprocess
from util.moduleinfo import getModuleFile
from util.moduleinfo import extractModuleInfos

# require python 3
if sys.version_info[0] < 3:
    sys.exit("\nERROR: Python3 required")

if __name__ == "__main__":

    # input argument parser
    parser = argparse.ArgumentParser(
        description="Create a docker image for a given module and install script."
    )

    parser.add_argument('-m', '--modulepath',
                        required=True,
                        help='the path to the your module')
    parser.add_argument('-i', '--installScript',
                        required=True,
                        help="Specify the installation script")
    parser.add_argument('-t', '--templateFolder',
                        required=False,
                        help="Specify the folder with the template files")

    args = vars(parser.parse_args())

    # get information on the module
    modulePath = os.path.abspath(args['modulepath'])
    modInfo = extractModuleInfos(getModuleFile(modulePath),
                                ['Module', 'Maintainer'])
    moduleName = modInfo['Module']
    moduleMaintainer = modInfo['Maintainer']
    dockerTag = moduleName.lower()  # docker only supports lower case

    # get folder with the template files
    templateFolder = args['templateFolder']
    if not templateFolder:
        templateFolder = os.path.join(modulePath, '../dumux/docker')
    if not os.path.exists(templateFolder):
        sys.exit("Template folder {} could not be found".format(templateFolder))

    print("*"*54)
    print("\n-- Creating a Docker image for module " + moduleName + " --\n")
    print("*"*54)

    if os.path.exists("docker"):
        print("\nA docker folder already exists. "
            "Continue anyway? - will be overwritten - [y/N]\n")
        delete = input()
        if delete == "y" or delete == "Y":
            shutil.rmtree("docker")
            print("--> Deleted old docker folder.")
        else:
            sys.exit("Abort.")

    os.mkdir("docker")
    print("--> Created the folder 'docker'.")

    # copy install script into docker folder and make it executable
    installScriptPath = args['installScript']
    installScriptName = os.path.split(installScriptPath)[1]
    installScript = os.path.join(os.path.join(os.getcwd(), 'docker'),
                                installScriptName)
    shutil.copy(installScriptPath, installScript)
    os.system("chmod +x {}".format(installScript))
    print("--> Using install script: {} to install dependencies for module {}."
        .format(installScript, moduleName))


    # substitute content from template and write to target
    def substituteAndWrite(template, target, mapping):
        if not os.path.exists(template):
            sys.exit("Template file '" + template + "' could not be found")
        with open(target, 'w') as targetFile:
            raw = string.Template(open(template).read())
            targetFile.write(raw.substitute(**mapping))


    # write setpermissions helper script
    template = os.path.join(templateFolder, 'setpermissions.sh.template')
    target = os.path.join(os.getcwd(), 'docker/setpermissions.sh')
    substituteAndWrite(template, target, {})
    print("--> Created permission helper script for easier container setup.")

    # write welcome message file
    template = os.path.join(templateFolder, 'WELCOME.template')
    target = os.path.join(os.getcwd(), 'docker/WELCOME')
    substituteAndWrite(template, target,
                    {'modName': moduleName, 'modFolder': moduleName})
    print("--> Created welcome message displayed on Docker container startup.")

    # write readme file
    template = os.path.join(templateFolder, 'README.md.template')
    target = os.path.join(os.getcwd(), 'docker/README.md')
    substituteAndWrite(template, target,
                    {'modName': moduleName, 'dockerTag': dockerTag})
    print("--> Created README.md on how to use the docker image.")

    # write helper file for container spin-up (make it executable after creation)
    template = os.path.join(templateFolder, 'docker.sh.template')
    target = os.path.join(os.getcwd(), 'docker/docker_{}.sh'.format(dockerTag))
    substituteAndWrite(template, target, {'dockerTag': dockerTag})
    os.system("chmod +x " + target)
    print("--> Created helper script to spin up the docker container.")

    # write the docker file
    template = os.path.join(templateFolder, 'Dockerfile.template')
    target = os.path.join(os.getcwd(), 'docker/Dockerfile')
    substituteAndWrite(template, target,
                    {
                        'modName': moduleName,
                        'modMaintainer': moduleMaintainer,
                        'dockerTag': dockerTag,
                        'instScript': installScriptName
                    })
    print("--> Created Dockerfile. You can adapt it to your needs.")
    print()
    print("Do you want to directly build the Docker image? [y/N]")

    build = input()
    if build == "y" or build == "Y":
        print("Building Docker image... this may take several minutes.")
        try:
            os.chdir('docker')
            subprocess.run(['docker', 'build',
                            '-f', 'Dockerfile',
                            '-t', dockerTag, '.'], check=True)
            os.chdir('../')
        except Exception:
            os.chdir('../')
            sys.exit("ERROR: docker image build failed")

        print()
        print("Successfully built image: {}. "
            "Have a look at docker/README.md.".format(dockerTag))
        print("Check the container by running "
            "'docker run -it {} /bin/bash' in the same".format(dockerTag))
        print("directory as the Dockerfile, and try using the convenience script "
            "docker_{}.sh".format(dockerTag))
        print("See docker/README.md for more information.")
    else:
        print("You can build your Docker image later by running "
            "'docker build -f Dockerfile -t {}'".format(dockerTag))
        print("from within the folder 'docker' that was created by this script, "
            "and in which you should find the 'Dockerfile'.")