From 7cf74389adfbafb341e6b3ea57cc2ba567ae5415 Mon Sep 17 00:00:00 2001 From: Robert Hensing Date: Thu, 21 Mar 2019 15:06:44 +0100 Subject: [PATCH 1/2] Add build.extendedInfo to service To let services write to the x-arion section. --- src/nix/eval-composition.nix | 1 + src/nix/eval-service.nix | 1 + .../modules/composition/docker-compose.nix | 7 +++++- src/nix/modules/composition/images.nix | 2 +- src/nix/modules/composition/service-info.nix | 24 +++++++++++++++++++ src/nix/modules/service/extended-info.nix | 20 ++++++++++++++++ 6 files changed, 53 insertions(+), 2 deletions(-) create mode 100644 src/nix/modules/composition/service-info.nix create mode 100644 src/nix/modules/service/extended-info.nix diff --git a/src/nix/eval-composition.nix b/src/nix/eval-composition.nix index 7d10e99..b3fc78a 100644 --- a/src/nix/eval-composition.nix +++ b/src/nix/eval-composition.nix @@ -21,6 +21,7 @@ let ./modules/composition/docker-compose.nix ./modules/composition/host-environment.nix ./modules/composition/images.nix + ./modules/composition/service-info.nix ]; argsModule = { diff --git a/src/nix/eval-service.nix b/src/nix/eval-service.nix index 887b419..09fe579 100644 --- a/src/nix/eval-service.nix +++ b/src/nix/eval-service.nix @@ -10,6 +10,7 @@ let builtinModules = [ argsModule ./modules/service/docker-compose-service.nix + ./modules/service/extended-info.nix ./modules/service/host-store.nix ./modules/service/host.nix ./modules/service/image.nix diff --git a/src/nix/modules/composition/docker-compose.nix b/src/nix/modules/composition/docker-compose.nix index 552c2e4..95855ff 100644 --- a/src/nix/modules/composition/docker-compose.nix +++ b/src/nix/modules/composition/docker-compose.nix @@ -26,7 +26,11 @@ in }; docker-compose.raw = lib.mkOption { type = lib.types.attrs; - description = "Nested attribute set that will be turned into the docker-compose.yaml file, using Nix's toJSON builtin."; + description = "Attribute set that will be turned into the docker-compose.yaml file, using Nix's toJSON builtin."; + }; + docker-compose.extended = lib.mkOption { + type = lib.types.attrs; + description = "Attribute set that will be turned into the x-arion section of the docker-compose.yaml file."; }; docker-compose.services = lib.mkOption { default = {}; @@ -47,6 +51,7 @@ in docker-compose.raw = { version = "3.4"; services = lib.mapAttrs (k: c: c.config.build.service) config.docker-compose.evaluatedServices; + x-arion = config.docker-compose.extended; }; }; } diff --git a/src/nix/modules/composition/images.nix b/src/nix/modules/composition/images.nix index 19035e8..9a9b04c 100644 --- a/src/nix/modules/composition/images.nix +++ b/src/nix/modules/composition/images.nix @@ -31,6 +31,6 @@ in }; config = { build.imagesToLoad = lib.attrValues serviceImages; - docker-compose.raw.x-arion.images = config.build.imagesToLoad; + docker-compose.extended.images = config.build.imagesToLoad; }; } diff --git a/src/nix/modules/composition/service-info.nix b/src/nix/modules/composition/service-info.nix new file mode 100644 index 0000000..1ed2989 --- /dev/null +++ b/src/nix/modules/composition/service-info.nix @@ -0,0 +1,24 @@ +/* + Adds extendedInfo from services to the Docker Compose file. + + This contains fields that are not in Docker Compose schema. + */ +{ config, lib, ... }: +let + serviceInfo = + lib.mapAttrs getInfo ( + lib.filterAttrs filterFunction config.docker-compose.evaluatedServices + ); + + filterFunction = _serviceName: service: + # shallow equality suffices for emptiness test + builtins.attrNames service.config.build.extendedInfo != []; + + getInfo = _serviceName: service: service.config.build.extendedInfo; + +in +{ + config = { + docker-compose.extended.serviceInfo = serviceInfo; + }; +} diff --git a/src/nix/modules/service/extended-info.nix b/src/nix/modules/service/extended-info.nix new file mode 100644 index 0000000..bb876c7 --- /dev/null +++ b/src/nix/modules/service/extended-info.nix @@ -0,0 +1,20 @@ +{ config, lib, ... }: +let + inherit (lib) mkOption; + inherit (lib.types) attrsOf unspecified; +in +{ + options = { + build.extendedInfo = mkOption { + type = attrsOf unspecified; + description = '' + Information about a service to include in the Docker Compose file, + but that will not be used by the docker-compose command + itself. + + It will be inserted in x-arion.serviceInfo.<service.name>. + ''; + default = {}; + }; + }; +} \ No newline at end of file From 2232038631689daab9fcd36cb82f35b98b0f0e03 Mon Sep 17 00:00:00 2001 From: Robert Hensing Date: Thu, 21 Mar 2019 15:10:21 +0100 Subject: [PATCH 2/2] Execute a shell on arion exec ; --- src/arion | 47 ++++++++++++++++++++++++ src/nix/eval-service.nix | 1 + src/nix/modules/nixos/default-shell.nix | 4 ++ src/nix/modules/service/default-exec.nix | 19 ++++++++++ src/nix/modules/service/nixos-init.nix | 2 + tests/arion-test/default.nix | 2 + 6 files changed, 75 insertions(+) create mode 100644 src/nix/modules/nixos/default-shell.nix create mode 100644 src/nix/modules/service/default-exec.nix diff --git a/src/arion b/src/arion index 32ec65d..41a1dea 100755 --- a/src/arion +++ b/src/arion @@ -46,6 +46,11 @@ while test $# != 0; do shift break ;; + exec) + command="$1" + shift + break + ;; docker-compose) command="docker-compose" shift @@ -231,6 +236,45 @@ do_repl_cleanup() { rm -f $REPL_TMP } +run_exec() { + case "${#docker_compose_args[@]}" in + 0) + echo "As an argument to exec, please specify a service" + exit 1 + ;; + 1) + case "${docker_compose_args[0]}" in + -*|--*) + echo "As an argument to exec, please specify a service" + echo "Note that executing the default command currently does not support" + echo "docker-compose options." + # This requires parsing the options, in order to figure out + # which service to invoke. + exit 1 + ;; + *) + serviceName="${docker_compose_args[0]}" + do_eval + default_args=() + while read arg; do + default_args+=("$arg") + done < <( + jq < "$docker_compose_yaml" \ + --arg serviceName "$serviceName" \ + -r \ + '.["x-arion"].serviceInfo.webserver.defaultExec | tostream | .[1] | select(.)' + ) + docker-compose -f $docker_compose_yaml exec "$serviceName" "${default_args[@]}" + ;; + esac + ;; + *) + do_eval + docker-compose -f $docker_compose_yaml exec "${docker_compose_args[@]}" + ;; + esac +} + case "$command" in cat) do_eval @@ -239,6 +283,9 @@ case "$command" in repl) do_repl ;; + exec) + run_exec "$@" + ;; docker-compose) if [[ ${#docker_compose_args[@]} != 0 && ${docker_compose_args[0]} != "help" diff --git a/src/nix/eval-service.nix b/src/nix/eval-service.nix index 09fe579..26a498c 100644 --- a/src/nix/eval-service.nix +++ b/src/nix/eval-service.nix @@ -9,6 +9,7 @@ let builtinModules = [ argsModule + ./modules/service/default-exec.nix ./modules/service/docker-compose-service.nix ./modules/service/extended-info.nix ./modules/service/host-store.nix diff --git a/src/nix/modules/nixos/default-shell.nix b/src/nix/modules/nixos/default-shell.nix new file mode 100644 index 0000000..2eb4173 --- /dev/null +++ b/src/nix/modules/nixos/default-shell.nix @@ -0,0 +1,4 @@ +{ config, utils, ... }: +{ + config.system.build.x-arion-defaultShell = utils.toShellPath config.users.defaultUserShell; +} diff --git a/src/nix/modules/service/default-exec.nix b/src/nix/modules/service/default-exec.nix new file mode 100644 index 0000000..299e083 --- /dev/null +++ b/src/nix/modules/service/default-exec.nix @@ -0,0 +1,19 @@ +{ config, lib, ... }: +let + inherit (lib) types mkOption; +in +{ + options = { + service.defaultExec = mkOption { + type = types.listOf types.str; + default = ["/bin/sh"]; + description = '' + Container program and arguments to invoke when calling + arion exec <service.name> without further arguments. + ''; + }; + }; + config = { + build.extendedInfo.defaultExec = config.service.defaultExec; + }; +} \ No newline at end of file diff --git a/src/nix/modules/service/nixos-init.nix b/src/nix/modules/service/nixos-init.nix index 0dab936..9fe52c3 100644 --- a/src/nix/modules/service/nixos-init.nix +++ b/src/nix/modules/service/nixos-init.nix @@ -21,6 +21,7 @@ in config = lib.mkIf (config.nixos.useSystemd) { nixos.configuration.imports = [ ../nixos/container-systemd.nix + ../nixos/default-shell.nix (pkgs.path + "/nixos/modules/profiles/minimal.nix") ]; image.command = [ "${config.nixos.build.toplevel}/init" ]; @@ -35,5 +36,6 @@ in ]; service.stop_signal = "SIGRTMIN+3"; service.tty = true; + service.defaultExec = [config.nixos.build.x-arion-defaultShell "-l"]; }; } diff --git a/tests/arion-test/default.nix b/tests/arion-test/default.nix index 4ad5aca..1020a1b 100644 --- a/tests/arion-test/default.nix +++ b/tests/arion-test/default.nix @@ -51,6 +51,8 @@ in subtest "full-nixos", sub { $machine->succeed("cp -r ${../../examples/full-nixos} work && cd work && NIX_PATH=nixpkgs='${pkgs.path}' arion up -d"); $machine->waitUntilSucceeds("curl localhost:8000"); + # Also test exec with defaultExec + $machine->succeed("cd work && export NIX_PATH=nixpkgs='${pkgs.path}' && (echo 'nix run -f ~/h/arion arion -c arion exec webserver'; echo 'target=world; echo Hello \$target'; echo exit) | script /dev/null | grep 'Hello world'"); $machine->succeed("cd work && NIX_PATH=nixpkgs='${pkgs.path}' arion down && rm -rf work"); $machine->waitUntilFails("curl localhost:8000"); };