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
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):
config_files = []
directory = os.path.abspath(os.getcwd())
@ -159,91 +217,59 @@ 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
# parse options and command from command line
(command_line_options, command) = parse_command_line(sys.argv[1:])
actions = command_line_options['actions']
command = sys.argv[1:]
command_user = user
user_volumes = USER_VOLUMES
pull = False
quiet = command_line_options.get("quiet", False)
def log (message, *args, **kwargs):
if quiet:
return
print(">> {}".format(message.format(*args, **kwargs)))
actions = []
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
}
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 +278,16 @@ 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 "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,18 +308,15 @@ 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,
@ -306,18 +326,15 @@ except Exception:
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']})")
log("Welcome to {} (IP {})", container_name, container['NetworkSettings']['IPAddress'])
docker_exec(container_name, command, command_user, command_env, tty, command_workdir)