Parse command line config on startup and apply later, so we can load config files based on container name (and also just because it looks cleaner). Also wrap logging logic into function and expose to config files.

This commit is contained in:
Adrian Kuschelyagi Malacoda 2021-02-28 16:21:07 -06:00
parent 556b9d6b75
commit 9340dbe720

View File

@ -132,6 +132,64 @@ def expand_user_volumes (volumes):
return mappings 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 == "--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): def find_config_files (config_names):
config_files = [] config_files = []
directory = os.path.abspath(os.getcwd()) directory = os.path.abspath(os.getcwd())
@ -159,91 +217,59 @@ def load_config_files (namespace, config_files):
exec(config_code.read(), {}, namespace) exec(config_code.read(), {}, namespace)
return dict([item for item in namespace.items() if item[0] in config_keys]) return dict([item for item in namespace.items() if item[0] in config_keys])
user = os.environ["USER"] # parse options and command from command line
uid = int(check_output(["id", "-u"]).strip()) (command_line_options, command) = parse_command_line(sys.argv[1:])
image_name = os.environ.get("OW_IMAGE", None) actions = command_line_options['actions']
container_name = os.environ.get("OW_CONTAINER", f"{CONTAINER_NAME}_{user}")
build_path = None
command = sys.argv[1:] quiet = command_line_options.get("quiet", False)
command_user = user def log (message, *args, **kwargs):
user_volumes = USER_VOLUMES if quiet:
pull = False return
print(">> {}".format(message.format(*args, **kwargs)))
actions = []
command_env = {}
command_workdir = None
quiet = False
tty = sys.stdout.isatty() tty = sys.stdout.isatty()
# load config from files # default config
config = load_config_files({ user = os.environ["USER"]
config = {
"command": command, "command": command,
"user": user, "user": user,
"uid": uid, "uid": int(check_output(["id", "-u"]).strip()),
"command_user": command_user, "command_user": user,
"image_name": image_name, "image_name": os.environ.get("OW_IMAGE", None),
"container_name": container_name, "container_name": command_line_options.get("container_name", os.environ.get("OW_CONTAINER", f"{CONTAINER_NAME}_{user}")),
"build_path": build_path, "build_path": None,
"command_workdir": command_workdir, "command_workdir": None,
"user_volumes": user_volumes, "user_volumes": USER_VOLUMES,
"pull": pull, "pull": False,
"command_env": command_env, "command_env": {},
"cwd": os.getcwd(), "cwd": os.getcwd(),
"tty": tty "tty": sys.stdout.isatty(),
}, find_config_files([OTHERWORLD_CONFIG, "{}{}".format(container_name, OTHERWORLD_CONFIG)])) "log": log
locals().update(config) }
while len(command) > 0: # load config from files
arg = command[0] config_files = find_config_files([
if arg == "--quiet": OTHERWORLD_CONFIG,
command = command[1:] "{}{}".format(config['container_name'], OTHERWORLD_CONFIG)
quiet = True ])
elif arg == "--notty":
command = command[1:] for config_file in config_files:
tty = False log("Loading config file {}", config_file)
elif arg == "--rm":
actions.append("rm") config = load_config_files(config, config_files)
command = command[1:]
elif arg == "--rmi": # apply config from command line
actions.append("rmi") for key, value in command_line_options.items():
command = command[1:] if key == "user_volumes":
elif arg == "--commit": config['user_volumes'] = config['user_volumes'] + value
actions.append("commit") elif key == "command_env":
command = command[1:] config['command_env'].update(value)
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
else: else:
break config[key] = value
# update local variables (FIXME: rewrite to avoid doing this)
locals().update(config)
if command_workdir: if command_workdir:
user_volumes.append(command_workdir) user_volumes.append(command_workdir)
@ -252,19 +278,16 @@ if command_workdir:
if actions: if actions:
if "commit" in actions: if "commit" in actions:
target_image_name = get_generated_image_name(container_name) target_image_name = get_generated_image_name(container_name)
if not quiet: log("Committing container: {} to image: {}", container_name, target_image_name)
print(f">> Committing container: {container_name} to image: {target_image_name}")
docker_commit(container_name, target_image_name) docker_commit(container_name, target_image_name)
if "rm" in actions: if "rm" in actions:
if not quiet: log("Removing container: {}", container_name)
print(f">> Removing container: {container_name}")
docker_rm(container_name) docker_rm(container_name)
if "rmi" in actions: if "rmi" in actions:
target_image_name = get_generated_image_name(container_name) target_image_name = get_generated_image_name(container_name)
if not quiet: log("Removing image: {}", target_image_name)
print(f">> Removing image: {target_image_name}")
docker_rmi(target_image_name) docker_rmi(target_image_name)
if not command: if not command:
@ -285,18 +308,15 @@ except Exception:
image_name = get_generated_image_name(container_name) image_name = get_generated_image_name(container_name)
try: try:
docker_inspect(image_name) docker_inspect(image_name)
if not quiet: log("Using default otherworld image {}", image_name)
print(f">> Using default otherworld image {image_name}")
except Exception: except Exception:
if not quiet: log("Default otherworld image {} not found, falling back to {}", image_name, DEFAULT_IMAGE_NAME)
print(f">> Default otherworld image {image_name} not found, falling back to {DEFAULT_IMAGE_NAME}")
image_name = DEFAULT_IMAGE_NAME image_name = DEFAULT_IMAGE_NAME
if pull: if pull:
docker_pull(image_name) docker_pull(image_name)
if not quiet: log("Creating container: {} (using image: {})", container_name, image_name)
print(f">> Creating container: {container_name} (using image: {image_name})")
docker_create( docker_create(
image_name, image_name,
container_name, container_name,
@ -306,18 +326,15 @@ except Exception:
container = docker_inspect(container_name)[0] container = docker_inspect(container_name)[0]
if not container["State"]["Running"]: if not container["State"]["Running"]:
if not quiet: log("Starting container: {}", container_name)
print(f">> Starting container: {container_name}")
docker_start(container_name) docker_start(container_name)
container = docker_inspect(container_name)[0] container = docker_inspect(container_name)[0]
try: try:
docker_get_user(container_name, user) docker_get_user(container_name, user)
except Exception: except Exception:
if not quiet: log("Creating container user: {}", user)
print(f">> Creating container user: {user}")
docker_create_user(container_name, user, uid) docker_create_user(container_name, user, uid)
if not quiet: log("Welcome to {} (IP {})", container_name, container['NetworkSettings']['IPAddress'])
print(f">> Welcome to {container_name} (IP {container['NetworkSettings']['IPAddress']})")
docker_exec(container_name, command, command_user, command_env, tty, command_workdir) docker_exec(container_name, command, command_user, command_env, tty, command_workdir)