Compare commits

...

6 Commits

View File

@@ -93,6 +93,9 @@ def docker_commit (container, image_name):
def docker_rm (container):
call(["docker", "rm", "-f", container])
def docker_restart (container):
call(["docker", "restart", container])
def docker_rmi (container):
call(["docker", "rmi", "-f", container])
@@ -132,6 +135,67 @@ def expand_user_volumes (volumes):
return mappings
def parse_command_line (command, config=None):
if config is None:
config = {
"actions": [],
"user_volumes": [],
"command_env": {}
}
while len(command) > 0:
arg = command[0]
if arg == "--quiet":
command = command[1:]
config['quiet'] = True
elif arg == "--notty":
command = command[1:]
config['tty'] = False
elif arg == "--rm":
config['actions'].append("rm")
command = command[1:]
elif arg == "--restart":
config['actions'].append("restart")
command = command[1:]
elif arg == "--rmi":
config['actions'].append("rmi")
command = command[1:]
elif arg == "--commit":
config['actions'].append("commit")
command = command[1:]
elif arg == "--sudo":
config['command_user'] = "root"
command = command[1:]
elif arg.startswith("--container="):
config['container_name'] = arg[len("--container="):]
command = command[1:]
elif arg.startswith("--image="):
config['image_name'] = arg[len("--image="):]
command = command[1:]
elif arg.startswith("--build="):
config['build_path'] = arg[len("--build="):]
command = command[1:]
elif arg.startswith("--volume="):
config['user_volumes'].append(arg[len("--volume="):])
command = command[1:]
elif arg.startswith("--env="):
env_pair = arg[len("--env="):]
(key, value) = env_pair.split("=", 1)
config['command_env'][key] = value
command = command[1:]
elif arg == "--cd":
config['command_workdir'] = os.getcwd()
command = command[1:]
elif arg.startswith("--cd="):
config['command_workdir'] = arg[len("--cd="):]
command = command[1:]
elif arg == "--pull":
command = command[1:]
config['pull'] = True
else:
break
return (config, command)
def find_config_files (config_names):
config_files = []
directory = os.path.abspath(os.getcwd())
@@ -159,91 +223,69 @@ def load_config_files (namespace, config_files):
exec(config_code.read(), {}, namespace)
return dict([item for item in namespace.items() if item[0] in config_keys])
user = os.environ["USER"]
uid = int(check_output(["id", "-u"]).strip())
image_name = os.environ.get("OW_IMAGE", None)
container_name = os.environ.get("OW_CONTAINER", f"{CONTAINER_NAME}_{user}")
build_path = None
def init_command_as_list (command):
if isinstance(command, str):
command = ["sh", "-c", command]
return command
command = sys.argv[1:]
command_user = user
user_volumes = USER_VOLUMES
pull = False
# parse options and command from command line
(command_line_options, command) = parse_command_line(sys.argv[1:])
actions = command_line_options['actions']
actions = []
quiet = command_line_options.get("quiet", False)
def log (message, *args, **kwargs):
if quiet:
return
print(">> {}".format(message.format(*args, **kwargs)))
command_env = {}
command_workdir = None
quiet = False
tty = sys.stdout.isatty()
# load config from files
config = load_config_files({
# default config
user = os.environ["USER"]
config = {
"command": command,
"user": user,
"uid": uid,
"command_user": command_user,
"image_name": image_name,
"container_name": container_name,
"build_path": build_path,
"command_workdir": command_workdir,
"user_volumes": user_volumes,
"pull": pull,
"command_env": command_env,
"uid": int(check_output(["id", "-u"]).strip()),
"command_user": user,
"image_name": os.environ.get("OW_IMAGE", None),
"container_name": command_line_options.get("container_name", os.environ.get("OW_CONTAINER", f"{CONTAINER_NAME}_{user}")),
"build_path": None,
"command_workdir": None,
"user_volumes": USER_VOLUMES,
"pull": False,
"command_env": {},
"cwd": os.getcwd(),
"tty": tty
}, find_config_files([OTHERWORLD_CONFIG, "{}{}".format(container_name, OTHERWORLD_CONFIG)]))
locals().update(config)
"tty": sys.stdout.isatty(),
"log": log,
"root_init_command": [],
"root_init_commmands": [],
"user_init_command": [],
"user_init_commands": [],
"docker_create_options": []
}
while len(command) > 0:
arg = command[0]
if arg == "--quiet":
command = command[1:]
quiet = True
elif arg == "--notty":
command = command[1:]
tty = False
elif arg == "--rm":
actions.append("rm")
command = command[1:]
elif arg == "--rmi":
actions.append("rmi")
command = command[1:]
elif arg == "--commit":
actions.append("commit")
command = command[1:]
elif arg == "--sudo":
command_user = "root"
command = command[1:]
elif arg.startswith("--container="):
container_name = arg[len("--container="):]
command = command[1:]
elif arg.startswith("--image="):
image_name = arg[len("--image="):]
command = command[1:]
elif arg.startswith("--build="):
build_path = arg[len("--build="):]
command = command[1:]
elif arg.startswith("--volume="):
user_volumes.append(arg[len("--volume="):])
command = command[1:]
elif arg.startswith("--env="):
env_pair = arg[len("--env="):]
(key, value) = env_pair.split("=", 1)
command_env[key] = value
command = command[1:]
elif arg == "--cd":
command_workdir = os.getcwd()
command = command[1:]
elif arg.startswith("--cd="):
command_workdir = arg[len("--cd="):]
command = command[1:]
elif arg == "--pull":
command = command[1:]
pull = True
# load config from files
config_files = find_config_files([
OTHERWORLD_CONFIG,
"{}{}".format(config['container_name'], OTHERWORLD_CONFIG)
])
for config_file in config_files:
log("Loading config file {}", config_file)
config = load_config_files(config, config_files)
# apply config from command line
for key, value in command_line_options.items():
if key == "user_volumes":
config['user_volumes'] = config['user_volumes'] + value
elif key == "command_env":
config['command_env'].update(value)
else:
break
config[key] = value
# update local variables (FIXME: rewrite to avoid doing this)
locals().update(config)
if command_workdir:
user_volumes.append(command_workdir)
@@ -252,19 +294,20 @@ if command_workdir:
if actions:
if "commit" in actions:
target_image_name = get_generated_image_name(container_name)
if not quiet:
print(f">> Committing container: {container_name} to image: {target_image_name}")
log("Committing container: {} to image: {}", container_name, target_image_name)
docker_commit(container_name, target_image_name)
if "restart" in actions:
log("Restarting container: {}", container_name)
docker_restart(container_name)
if "rm" in actions:
if not quiet:
print(f">> Removing container: {container_name}")
log("Removing container: {}", container_name)
docker_rm(container_name)
if "rmi" in actions:
target_image_name = get_generated_image_name(container_name)
if not quiet:
print(f">> Removing image: {target_image_name}")
log("Removing image: {}", target_image_name)
docker_rmi(target_image_name)
if not command:
@@ -285,39 +328,45 @@ except Exception:
image_name = get_generated_image_name(container_name)
try:
docker_inspect(image_name)
if not quiet:
print(f">> Using default otherworld image {image_name}")
log("Using default otherworld image {}", image_name)
except Exception:
if not quiet:
print(f">> Default otherworld image {image_name} not found, falling back to {DEFAULT_IMAGE_NAME}")
log("Default otherworld image {} not found, falling back to {}", image_name, DEFAULT_IMAGE_NAME)
image_name = DEFAULT_IMAGE_NAME
if pull:
docker_pull(image_name)
if not quiet:
print(f">> Creating container: {container_name} (using image: {image_name})")
log("Creating container: {} (using image: {})", container_name, image_name)
docker_create(
image_name,
container_name,
DOCKER_CREATE_OPTIONS + create_x11_mapping() + expand_user_volumes(user_volumes),
DOCKER_CREATE_OPTIONS + config.get("docker_create_options", []) + create_x11_mapping() + expand_user_volumes(user_volumes),
BACKGROUND_COMMAND, { OTHERWORLD_LABEL: user }
)
container = docker_inspect(container_name)[0]
if not container["State"]["Running"]:
if not quiet:
print(f">> Starting container: {container_name}")
log("Starting container: {}", container_name)
docker_start(container_name)
container = docker_inspect(container_name)[0]
try:
docker_get_user(container_name, user)
except Exception:
if not quiet:
print(f">> Creating container user: {user}")
log("Creating container user: {}", user)
docker_create_user(container_name, user, uid)
if not quiet:
print(f">> Welcome to {container_name} (IP {container['NetworkSettings']['IPAddress']})")
if config['root_init_command']:
config['root_init_commands'].append(config['root_init_command'])
for command in config['root_init_commands']:
docker_exec(container_name, init_command_as_list(command), "root", command_env, tty, "/home/{}".format(command_user))
if config['user_init_command']:
config['user_init_commands'].append(config['user_init_command'])
for command in config['user_init_commands']:
docker_exec(container_name, init_command_as_list(command), command_user, command_env, tty, "/home/{}".format(command_user))
log("Welcome to {} (IP {})", container_name, container['NetworkSettings']['IPAddress'])
docker_exec(container_name, command, command_user, command_env, tty, command_workdir)