Skip to content

Commit

Permalink
flakes CLI: add container commands
Browse files Browse the repository at this point in the history
  • Loading branch information
nazarewk committed Mar 28, 2023
1 parent 75257de commit aa6ab74
Show file tree
Hide file tree
Showing 7 changed files with 187 additions and 90 deletions.
52 changes: 39 additions & 13 deletions flake-module.nix
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,6 @@ devenvFlake: { flake-parts-lib, lib, inputs, ... }: {
};
}];
}).type;

shellPrefix = shellName: if shellName == "default" then "" else "${shellName}-";
in

{
Expand Down Expand Up @@ -44,7 +42,7 @@ devenvFlake: { flake-parts-lib, lib, inputs, ... }: {
(shellName: devenv:
lib.concatMapAttrs
(containerName: container: {
"${shellPrefix shellName}container-${containerName}-spec" = container.derivation;
"${shellName}-container-${containerName}-spec" = container.derivation;
})
devenv.containers
)
Expand All @@ -54,16 +52,44 @@ devenvFlake: { flake-parts-lib, lib, inputs, ... }: {
lib.concatMapAttrs
(shellName: devenv:
lib.concatMapAttrs
(containerName: container: {
"${shellPrefix shellName}container-${containerName}" = {
type = "app";
program = "${container.run}";
};
"${shellPrefix shellName}container-${containerName}-copy-to" = {
type = "app";
program = "${container.copyTo}";
};
})
(containerName: config:
let prefix = "devenv-${shellName}-container-${containerName}"; in {
"${prefix}-copy-to" = {
type = "app";
program = pkgs.writeShellApplication {
name = "${shellName}-container-${containerName}-copy-to";
text = ''
${config.copyScript} ${config.derivation} "$@"
'';
};
};
"${prefix}-docker-run" = {
type = "app";
program = "${config.dockerRun}";
};
"${prefix}-docker-load" = {
type = "app";
program = pkgs.writeShellApplication {
name = "${shellName}-container-${containerName}-docker-load";
text = ''
${config.copyScript} ${config.derivation} local-docker
'';
};
};
"${prefix}-podman-run" = {
type = "app";
program = "${config.podmanRun}";
};
"${prefix}-podman-load" = {
type = "app";
program = pkgs.writeShellApplication {
name = "${shellName}-container-${containerName}-podman-load";
text = ''
${config.copyScript} ${config.derivation} local
'';
};
};
})
devenv.containers
)
config.devenv.shells;
Expand Down
53 changes: 12 additions & 41 deletions src/devenv-devShell.nix
Original file line number Diff line number Diff line change
@@ -1,46 +1,17 @@
{ config, pkgs }:
let
lib = pkgs.lib;
version = lib.fileContents ./modules/latest-version;
in
pkgs.writeScriptBin "devenv" ''
#!/usr/bin/env bash
# we want subshells to fail the program
set -e

NIX_FLAGS="--show-trace --extra-experimental-features nix-command --extra-experimental-features flakes"
app = pkgs.writeShellApplication {
name = "devenv-flake-cli";
runtimeInputs = with pkgs; [ docopts ];
text = builtins.readFile ./devenv-devShell.sh;
};

command=$1
if [[ ! -z $command ]]; then
shift
fi
case $command in
up)
procfilescript=${config.procfileScript}
if [ "$(cat $procfilescript|tail -n +2)" = "" ]; then
echo "No 'processes' option defined: https://devenv.sh/processes/"
exit 1
else
$procfilescript
fi
;;
version)
echo "devenv: ${version}"
;;
*)
echo "https://devenv.sh (version ${version}): Fast, Declarative, Reproducible, and Composable Developer Environments"
echo
echo "This is a flake integration wrapper that comes with a subset of functionality from the flakeless devenv CLI."
echo
echo "Usage: devenv command"
echo
echo "Commands:"
echo
echo "up Starts processes in foreground. See http://devenv.sh/processes"
echo "version Display devenv version"
echo
exit 1
esac
''
envs = lib.concatStringsSep " " (lib.mapAttrsToList lib.toShellVar {
PROCFILESCRIPT = config.procfileScript;
VERSION = lib.fileContents ./modules/latest-version;
CUSTOM_NIX = "${pkgs.nix}/bin/nix";
});
in
pkgs.writeScriptBin "devenv" ''${envs} "${app}/bin/devenv-flake-cli" "$@"''
94 changes: 94 additions & 0 deletions src/devenv-devShell.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
#!/usr/bin/env bash
set -eEuo pipefail

if [ "${DEBUG:-}" == 1 ]; then
set -x
fi
PROCFILESCRIPT="${PROCFILESCRIPT:-"placeholder"}"
VERSION="${VERSION:-"placeholder"}"
CUSTOM_NIX="${CUSTOM_NIX:-"nix"}"

NIX_FLAGS=(--show-trace --extra-experimental-features 'nix-command flakes')

function nix {
"$CUSTOM_NIX" "${NIX_FLAGS[@]}" "${@}"
}

function container {
declare -A args
set -x
# shellcheck disable=SC2016
eval "$(docopts -A args -h '
Usage: container [options] <container-name> [--] [<run-args>...]
Options:
-s <shell>, --shell <shell> `devenv.shells.<shell>` to use. [default: default]
-r <name>, --registry <name> Registry to copy the container to.
Available shortcuts: config, local-docker, local [default: config]
--copy Copy the container to the registry.
--copy-args <args> Arguments passed to `skopeo copy`.
--docker-run Execute `docker run`.
--podman-run Execute `podman run`.
' : "$@")"

local registry="${args['--registry']}"

local app_prefix="${DEVENV_ROOT}#devenv-${args['--shell']}-container-${args['<container-name>']}"

if [[ "${args['--copy']}" != false || "${args['--docker-run']}" != false || "${args['--podman-run']}" != false ]]; then
if [[ ${args['--docker-run']} == true ]]; then
registry=local-docker
elif [[ ${args['--podman-run']} == true ]]; then
registry=local
fi
# shellcheck disable=SC2086
nix run "${app_prefix}-copy-to" "${registry}" ${args['--copy-args']}
fi

# shellcheck disable=SC1090
source "$(command -v docopts.sh)"

if [[ "${args['--docker-run']}" != false ]]; then
# shellcheck disable=SC2046
nix run "${app_prefix}-docker-run" -- $(docopt_get_values args '<run-args>')
elif [[ "${args['--podman-run']}" != false ]]; then
# shellcheck disable=SC2046
nix run "${app_prefix}-podman-run" -- $(docopt_get_values args '<run-args>')
fi
}

command="${1:-}"
if [[ -n "$command" ]]; then
shift
fi

case "$command" in
up)
if [ "$(tail -n +2 <<<"$PROCFILESCRIPT")" = "" ]; then
echo "No 'processes' option defined: https://devenv.sh/processes/"
exit 1
else
"$PROCFILESCRIPT"
fi
;;
container)
container "$@"
;;
version)
echo "devenv: ${VERSION}"
;;
*)
echo "https://devenv.sh (version ${VERSION}): Fast, Declarative, Reproducible, and Composable Developer Environments"
echo
echo "This is a flake integration wrapper that comes with a subset of functionality from the flakeless devenv CLI."
echo
echo "Usage: devenv command"
echo
echo "Commands:"
echo
echo "up Starts processes in foreground. See http://devenv.sh/processes"
echo "version Display devenv version"
echo
exit 1
;;
esac
10 changes: 7 additions & 3 deletions src/devenv.nix
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,7 @@ pkgs.writeScriptBin "devenv" ''
--copy Copy the container to the registry.
--copy-args=<args> Arguments passed to `skopeo copy`.
--docker-run Execute `docker run`.
--podman-run Execute `podman run`.
EOF
)
Expand All @@ -124,20 +125,23 @@ pkgs.writeScriptBin "devenv" ''
echo $spec
# copy container
if [[ ''${subcommand[--copy]} != false || ''${subcommand[--docker-run]} != false ]]; then
if [[ ''${subcommand[--copy]} != false || ''${subcommand[--docker-run]} != false || ''${subcommand[--podman-run]} != false ]]; then
copyScript=$($CUSTOM_NIX/bin/nix $NIX_FLAGS build --print-out-paths --no-link --impure ".#devenv.containers.\"$container\".copyScript")
if [[ ''${subcommand[--docker-run]} == true ]]; then
registry=docker-daemon:
registry=local-docker
elif [[ ''${subcommand[--podman-run]} == true ]]; then
registry=local
else
registry="''${subcommand[--registry]}"
fi
$copyScript $spec $registry ''${subcommand[--copy-args]}
fi
# docker run
if [[ ''${subcommand[--docker-run]} != false ]]; then
$($CUSTOM_NIX/bin/nix $NIX_FLAGS build --print-out-paths --no-link --impure ".#devenv.containers.\"$container\".dockerRun")
if [[ ''${subcommand[--podman-run]} != false ]]; then
$($CUSTOM_NIX/bin/nix $NIX_FLAGS build --print-out-paths --no-link --impure ".#devenv.containers.\"$container\".podmanRun")
fi
;;
search)
Expand Down
57 changes: 27 additions & 30 deletions src/modules/containers.nix
Original file line number Diff line number Diff line change
Expand Up @@ -56,14 +56,17 @@ let

# <registry> <args>
mkCopyScript = cfg: pkgs.writeScript "copy-container" ''
container=$1
spec=$1
shift
if [[ "$1" == false ]]; then
registry=${cfg.registry}
else
registry="$1"
fi
case "$1" in
false|config) registry="${cfg.registry}" ;;
local-docker) registry="docker-daemon:" ;;
local|local-podman|local-containers|local-buildah)
registry="containers-storage:"
;;
*) registry="$1" ;;
esac
shift
dest="''${registry}${cfg.name}:${cfg.version}"
Expand All @@ -75,10 +78,10 @@ let
fi
echo
echo "Copying container $container to $dest"
echo "Copying container $spec to $dest"
echo
${nix2container.skopeo-nix2container}/bin/skopeo --insecure-policy copy "nix:$container" "$dest" "''${args[@]}"
${nix2container.skopeo-nix2container}/bin/skopeo --insecure-policy copy "nix:$spec" "$dest" "''${args[@]}"
'';
containerOptions = types.submodule ({ name, config, ... }: {
options = {
Expand Down Expand Up @@ -154,28 +157,31 @@ let
internal = true;
default = pkgs.writeScript "docker-run" ''
#!${pkgs.bash}/bin/bash
set -eEuo pipefail
docker run -it ${config.name}:${config.version} "$@"
'';
};
container_args=()
runtime_args=()
copyTo = lib.mkOption {
type = types.package;
internal = true;
default = pkgs.writeScript "devenv-container-copy-to" ''
${config.copyScript} ${config.derivation} "''${1:-"containers-storage:localhost/"}" "''${@:2}"
for arg in "$@" ; do
if [ "$arg" == "--" ] ; then
runtime_args=("''${container_args[@]}")
container_args=()
else
container_args+=("$arg")
fi
done
docker run -it "''${runtime_args[@]}" '${config.name}:${config.version}' "''${container_args[@]}"
'';
};

run = lib.mkOption {
podmanRun = lib.mkOption {
type = types.package;
internal = true;
default = pkgs.writeScript "devenv-container-run" ''
default = pkgs.writeScript "podman-run" ''
#!${pkgs.bash}/bin/bash
set -eEuo pipefail
${config.copyScript} ${config.derivation} "containers-storage:localhost/"
container_args=()
runtime_args=()
Expand All @@ -188,16 +194,7 @@ let
fi
done
args=( run -it "''${runtime_args[@]}" '${config.name}:${config.version}' "''${container_args[@]}" )
if command -v docker >/dev/null ; then
docker "''${args[@]}"
elif command -v podman >/dev/null ; then
podman "''${args[@]}"
else
echo "Found neither docker nor podman." >&2
exit 1
fi
podman run -it "''${runtime_args[@]}" '${config.name}:${config.version}' "''${container_args[@]}"
'';
};
};
Expand Down
8 changes: 8 additions & 0 deletions templates/flake-parts/.envrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
if ! has nix_direnv_version || ! nix_direnv_version 2.2.1; then
source_url "https://raw.githubusercontent.com/nix-community/nix-direnv/2.2.1/direnvrc" "sha256-zelF0vLbEl5uaqrfIzbgNzJWGmLzCmYAkInj/LNxvKs="
fi

if ! use flake . --impure
then
echo "devenv could not be build. The devenv environment was not loaded. Make the necessary changes to devenv.nix and hit enter to try again." >&2
fi
3 changes: 0 additions & 3 deletions templates/simple/.envrc
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,6 @@ if ! has nix_direnv_version || ! nix_direnv_version 2.2.1; then
source_url "https://raw.githubusercontent.com/nix-community/nix-direnv/2.2.1/direnvrc" "sha256-zelF0vLbEl5uaqrfIzbgNzJWGmLzCmYAkInj/LNxvKs="
fi

nix_direnv_watch_file devenv.nix
nix_direnv_watch_file devenv.lock
nix_direnv_watch_file devenv.yaml
if ! use flake . --impure
then
echo "devenv could not be build. The devenv environment was not loaded. Make the necessary changes to devenv.nix and hit enter to try again." >&2
Expand Down

0 comments on commit aa6ab74

Please sign in to comment.