Compare commits
1 commit
main
...
issue-175-
Author | SHA1 | Date | |
---|---|---|---|
|
9334c8ec11 |
44 changed files with 1574 additions and 494 deletions
.gitignoreCHANGELOG.mdarion-compose.cabalbors.toml
docs
examples
flake.lockflake.nixnixos-module.nixrun-arion-via-nixsrc
haskell
test
testdata/Arion/NixSpec
nix
tests
update-options
2
.gitignore
vendored
2
.gitignore
vendored
|
@ -5,5 +5,3 @@ dist/
|
|||
dist-newstyle/
|
||||
cabal.project.local
|
||||
|
||||
*.swp
|
||||
|
||||
|
|
13
CHANGELOG.md
13
CHANGELOG.md
|
@ -1,18 +1,5 @@
|
|||
# Revision history for Arion
|
||||
|
||||
## 0.2.1.0 -- 2023-07-26
|
||||
|
||||
### Added
|
||||
|
||||
* `service.networks` now supports attribute set values with various options, thanks to @pedorich-n.
|
||||
* `docker-compose.volumes` can now be specified in multiple modules, thanks to @qaifshaikh.
|
||||
* `image.fakeRootCommands` for making modifications to the image that aren't "add a link farm".
|
||||
|
||||
### Fixed
|
||||
|
||||
* Regular maintenance fixes, including one by olebedev
|
||||
|
||||
|
||||
## 0.2.0.0 -- 2022-12-02
|
||||
|
||||
### BREAKING
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
cabal-version: 2.4
|
||||
|
||||
name: arion-compose
|
||||
version: 0.2.1.0
|
||||
version: 0.2.0.0
|
||||
synopsis: Run docker-compose with help from Nix/NixOS
|
||||
description: Arion is a tool for building and running applications that consist of multiple docker containers using NixOS modules. It has special support for docker images that are built with Nix, for a smooth development experience and improved performance.
|
||||
homepage: https://github.com/hercules-ci/arion#readme
|
||||
|
@ -30,7 +30,7 @@ source-repository head
|
|||
location: https://github.com/hercules-ci/arion
|
||||
|
||||
common common
|
||||
build-depends: base >=4.12.0.0 && <4.99
|
||||
build-depends: base >=4.12.0.0 && <4.17
|
||||
, aeson >=2
|
||||
, aeson-pretty
|
||||
, async
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
status = [
|
||||
"ci/hercules/onPush/default",
|
||||
"ci/hercules/derivations",
|
||||
"ci/hercules/evaluation",
|
||||
]
|
||||
delete_merged_branches = true
|
||||
|
|
|
@ -4,4 +4,3 @@ version: 'master'
|
|||
nav:
|
||||
- modules/ROOT/nav.adoc
|
||||
- modules/reference/nav.adoc
|
||||
nix: true
|
||||
|
|
|
@ -1,31 +1,20 @@
|
|||
{
|
||||
perSystem = { config, pkgs, lib, ... }: {
|
||||
packages.generated-option-doc-arion =
|
||||
# TODO: use the render pipeline in flake-parts,
|
||||
# which has support for things like {options}`foo`.
|
||||
let
|
||||
eval = lib.evalModules {
|
||||
modules = import ../src/nix/modules.nix;
|
||||
};
|
||||
in
|
||||
(pkgs.nixosOptionsDoc
|
||||
{
|
||||
options = eval.options;
|
||||
}).optionsCommonMark;
|
||||
perSystem = { config, pkgs, ... }:
|
||||
let
|
||||
doc-options = import ./options.nix { };
|
||||
|
||||
packages.generated-antora-files =
|
||||
pkgs.runCommand "generated-antora-files"
|
||||
{
|
||||
nativeBuildInputs = [ pkgs.pandoc ];
|
||||
doc_arion = config.packages.generated-option-doc-arion;
|
||||
}
|
||||
# TODO: use the render pipeline in flake-parts,
|
||||
# which has support for things like {options}`foo`.
|
||||
''
|
||||
mkdir -p $out/modules/ROOT/partials
|
||||
pandoc --from=markdown --to=asciidoc \
|
||||
< $doc_arion \
|
||||
> $out/modules/ROOT/partials/arion-options.adoc
|
||||
'';
|
||||
};
|
||||
in
|
||||
{
|
||||
packages.doc-options = pkgs.callPackage ./options.nix { };
|
||||
|
||||
checks.doc-options = pkgs.runCommand "doc-options-check" { } ''
|
||||
if diff --color -u ${./modules/ROOT/partials/NixOSOptions.adoc} ${config.packages.doc-options}; then
|
||||
touch $out
|
||||
else
|
||||
echo 1>&2 "The doc options have changed and need to be added."
|
||||
echo 1>&2 "Please run ./update-options in the root of your arion clone."
|
||||
exit 1
|
||||
fi
|
||||
'';
|
||||
};
|
||||
}
|
||||
|
|
|
@ -1 +0,0 @@
|
|||
../../../../../examples/full-nixos/arion-compose.nix
|
|
@ -1 +0,0 @@
|
|||
../../../../../examples/minimal/arion-compose.nix
|
|
@ -1 +0,0 @@
|
|||
../../../../../examples/nixos-unit/arion-compose.nix
|
|
@ -45,21 +45,18 @@ NOTE: This deployment method does NOT use an `arion-pkgs.nix` file, but reuses
|
|||
# Pick one of:
|
||||
# - niv
|
||||
((import ./nix/sources.nix).arion + "/nixos-module.nix")
|
||||
# - or flakes (where arion is a flake input)
|
||||
# - flakes (where arion is a flake input)
|
||||
arion.nixosModules.arion
|
||||
# - or other: copy commit hash of arion and replace HASH in:
|
||||
(builtins.fetchTarball "https://github.com/hercules-ci/arion/archive/HASH.tar.gz") + "/nixos-module.nix")
|
||||
# - other
|
||||
arionPath + "/nixos-module.nix")
|
||||
];
|
||||
|
||||
virtualisation.arion = {
|
||||
backend = "podman-socket"; # or "docker"
|
||||
projects.example = {
|
||||
serviceName = "example"; # optional systemd service name, defaults to arion-example in this case
|
||||
settings = {
|
||||
# Specify you project here, or import it from a file.
|
||||
# NOTE: This does NOT use ./arion-pkgs.nix, but defaults to NixOS' pkgs.
|
||||
imports = [ ./arion-compose.nix ];
|
||||
};
|
||||
projects.example.settings = {
|
||||
# Specify you project here, or import it from a file.
|
||||
# NOTE: This does NOT use ./arion-pkgs.nix, but defaults to NixOS' pkgs.
|
||||
imports = [ ./arion-compose.nix ];
|
||||
};
|
||||
};
|
||||
}
|
||||
|
|
|
@ -113,16 +113,14 @@ Describe containers using NixOS-style modules. There are a few options:
|
|||
|
||||
==== Minimal: Plain command using nixpkgs
|
||||
|
||||
`examples/minimal/arion-compose.nix`
|
||||
[,nix]
|
||||
----
|
||||
`examples/minimal/arion-compose.nix`:
|
||||
|
||||
```nix
|
||||
{ pkgs, ... }:
|
||||
{
|
||||
project.name = "webapp";
|
||||
services = {
|
||||
config.services = {
|
||||
|
||||
webserver = {
|
||||
image.enableRecommendedContents = true;
|
||||
service.useHostStore = true;
|
||||
service.command = [ "sh" "-c" ''
|
||||
cd "$$WEB_ROOT"
|
||||
|
@ -132,36 +130,58 @@ Describe containers using NixOS-style modules. There are a few options:
|
|||
"8000:8000" # host:container
|
||||
];
|
||||
service.environment.WEB_ROOT = "${pkgs.nix.doc}/share/doc/nix/manual";
|
||||
service.stop_signal = "SIGINT";
|
||||
};
|
||||
};
|
||||
}
|
||||
----
|
||||
```
|
||||
|
||||
==== NixOS: run full OS
|
||||
==== NixOS: run only one systemd service
|
||||
|
||||
`examples/full-nixos/arion-compose.nix`:
|
||||
`examples/nixos-unit/arion-compose.nix`:
|
||||
|
||||
[,nix]
|
||||
----
|
||||
```nix
|
||||
{
|
||||
project.name = "full-nixos";
|
||||
services.webserver = { pkgs, lib, ... }: {
|
||||
nixos.useSystemd = true;
|
||||
nixos.configuration.boot.tmp.useTmpfs = true;
|
||||
nixos.configuration.services.nginx.enable = true;
|
||||
nixos.configuration.services.nginx.virtualHosts.localhost.root = "${pkgs.nix.doc}/share/doc/nix/manual";
|
||||
nixos.configuration.services.nscd.enable = false;
|
||||
nixos.configuration.system.nssModules = lib.mkForce [];
|
||||
nixos.configuration.systemd.services.nginx.serviceConfig.AmbientCapabilities =
|
||||
lib.mkForce [ "CAP_NET_BIND_SERVICE" ];
|
||||
services.webserver = { config, pkgs, ... }: {
|
||||
|
||||
nixos.configuration = {config, pkgs, ...}: {
|
||||
boot.isContainer = true;
|
||||
services.nginx.enable = true;
|
||||
services.nginx.virtualHosts.localhost.root = "${pkgs.nix.doc}/share/doc/nix/manual";
|
||||
system.build.run-nginx = pkgs.writeScript "run-nginx" ''
|
||||
#!${pkgs.bash}/bin/bash
|
||||
PATH='${config.systemd.services.nginx.environment.PATH}'
|
||||
echo nginx:x:${toString config.users.users.nginx.uid}:${toString config.users.groups.nginx.gid}:nginx web server user:/var/empty:/bin/sh >>/etc/passwd
|
||||
echo nginx:x:${toString config.users.groups.nginx.gid}:nginx >>/etc/group
|
||||
${config.systemd.services.nginx.runner}
|
||||
'';
|
||||
};
|
||||
service.command = [ config.nixos.build.run-nginx ];
|
||||
service.useHostStore = true;
|
||||
service.ports = [
|
||||
"8000:80" # host:container
|
||||
];
|
||||
};
|
||||
}
|
||||
----
|
||||
```
|
||||
|
||||
==== NixOS: run full OS
|
||||
|
||||
`examples/full-nixos/arion-compose.nix`:
|
||||
|
||||
```nix
|
||||
{
|
||||
services.webserver = { pkgs, ... }: {
|
||||
nixos.useSystemd = true;
|
||||
nixos.configuration.boot.tmpOnTmpfs = true;
|
||||
nixos.configuration.services.nginx.enable = true;
|
||||
nixos.configuration.services.nginx.virtualHosts.localhost.root = "${pkgs.nix.doc}/share/doc/nix/manual";
|
||||
service.useHostStore = true;
|
||||
service.ports = [
|
||||
"8000:80" # host:container
|
||||
];
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
==== Docker image from DockerHub
|
||||
|
||||
|
@ -175,11 +195,6 @@ Describe containers using NixOS-style modules. There are a few options:
|
|||
}
|
||||
```
|
||||
|
||||
==== NixOS: run only one systemd service
|
||||
|
||||
Running individual units from NixOS is possible using an experimental script.
|
||||
See `examples/nixos-unit/arion-compose.nix`.
|
||||
|
||||
=== Run
|
||||
|
||||
Start containers and watch their logs:
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
# Arion Options
|
||||
// To update option descriptions
|
||||
// - use git grep or github search
|
||||
// - or browse through src/nix/modules
|
||||
|
||||
include::partial$arion-options.adoc[]
|
||||
include::partial$NixOSOptions.adoc[]
|
||||
|
|
1320
docs/modules/ROOT/partials/NixOSOptions.adoc
Normal file
1320
docs/modules/ROOT/partials/NixOSOptions.adoc
Normal file
File diff suppressed because it is too large
Load diff
|
@ -2,8 +2,7 @@
|
|||
project.name = "full-nixos";
|
||||
services.webserver = { pkgs, lib, ... }: {
|
||||
nixos.useSystemd = true;
|
||||
nixos.configuration.boot.tmp.useTmpfs = true;
|
||||
nixos.configuration.networking.useDHCP = false;
|
||||
nixos.configuration.boot.tmpOnTmpfs = true;
|
||||
nixos.configuration.services.nginx.enable = true;
|
||||
nixos.configuration.services.nginx.virtualHosts.localhost.root = "${pkgs.nix.doc}/share/doc/nix/manual";
|
||||
nixos.configuration.services.nscd.enable = false;
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
{ pkgs, ... }:
|
||||
{
|
||||
project.name = "webapp";
|
||||
services = {
|
||||
config.project.name = "webapp";
|
||||
config.services = {
|
||||
|
||||
webserver = {
|
||||
image.enableRecommendedContents = true;
|
||||
|
|
|
@ -10,17 +10,6 @@
|
|||
*/
|
||||
{ lib, pkgs, ... }: {
|
||||
config.project.name = "traefik";
|
||||
config.networks = {
|
||||
traefik-custom = {
|
||||
name = "traefik-custom";
|
||||
ipam = {
|
||||
config = [{
|
||||
subnet = "172.32.0.0/16";
|
||||
gateway = "172.32.0.1";
|
||||
}];
|
||||
};
|
||||
};
|
||||
};
|
||||
config.services = {
|
||||
traefik = {
|
||||
image.command = [
|
||||
|
@ -35,7 +24,6 @@
|
|||
stop_signal = "SIGINT";
|
||||
ports = [ "80:80" "8080:8080" ];
|
||||
volumes = [ "/var/run/docker.sock:/var/run/docker.sock:ro" ];
|
||||
networks = [ "traefik-custom" ];
|
||||
};
|
||||
};
|
||||
|
||||
|
@ -46,17 +34,14 @@
|
|||
${pkgs.python3}/bin/python -m http.server
|
||||
''}"];
|
||||
service.container_name = "simple-service";
|
||||
service.ports = [
|
||||
"8000:8000" # host:container
|
||||
];
|
||||
service.stop_signal = "SIGINT";
|
||||
service.labels = {
|
||||
"traefik.enable" = "true";
|
||||
"traefik.http.routers.nix-docs.rule" = "Host(`nix-docs.localhost`)";
|
||||
"traefik.http.routers.nix-docs.entrypoints" = "web";
|
||||
"traefik.http.services.nix-docs.loadBalancer.server.port" = "8000";
|
||||
};
|
||||
service.networks = {
|
||||
traefik-custom = {
|
||||
ipv4_address = "172.32.0.5";
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
|
64
flake.lock
generated
64
flake.lock
generated
|
@ -7,88 +7,47 @@
|
|||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1722555600,
|
||||
"narHash": "sha256-XOQkdLafnb/p9ij77byFQjDf5m5QYl9b2REiVClC+x4=",
|
||||
"lastModified": 1669931201,
|
||||
"narHash": "sha256-UnYFeaLPLj7e4eEt4GJooeJZhaZXyloQZYinwO/CeUw=",
|
||||
"owner": "hercules-ci",
|
||||
"repo": "flake-parts",
|
||||
"rev": "8471fe90ad337a8074e957b69ca4d0089218391d",
|
||||
"rev": "995d6bc162c0539998ef6375c2c6b612972dc016",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "hercules-ci",
|
||||
"ref": "easyOverlay",
|
||||
"repo": "flake-parts",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"flake-parts_2": {
|
||||
"inputs": {
|
||||
"nixpkgs-lib": [
|
||||
"hercules-ci-effects",
|
||||
"nixpkgs"
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1712014858,
|
||||
"narHash": "sha256-sB4SWl2lX95bExY2gMFG5HIzvva5AVMJd4Igm+GpZNw=",
|
||||
"owner": "hercules-ci",
|
||||
"repo": "flake-parts",
|
||||
"rev": "9126214d0a59633752a136528f5f3b9aa8565b7d",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"id": "flake-parts",
|
||||
"type": "indirect"
|
||||
}
|
||||
},
|
||||
"haskell-flake": {
|
||||
"locked": {
|
||||
"lastModified": 1675296942,
|
||||
"narHash": "sha256-u1X1sblozi5qYEcLp1hxcyo8FfDHnRUVX3dJ/tW19jY=",
|
||||
"lastModified": 1668167720,
|
||||
"narHash": "sha256-5wDTR6xt9BB3BjgKR+YOjOkZgMyDXKaX79g42sStzDU=",
|
||||
"owner": "srid",
|
||||
"repo": "haskell-flake",
|
||||
"rev": "c2cafce9d57bfca41794dc3b99c593155006c71e",
|
||||
"rev": "4fc511d93a55fedf815c1647ad146c26d7a2054e",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "srid",
|
||||
"ref": "0.1.0",
|
||||
"repo": "haskell-flake",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"hercules-ci-effects": {
|
||||
"inputs": {
|
||||
"flake-parts": "flake-parts_2",
|
||||
"nixpkgs": [
|
||||
"nixpkgs"
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1719226092,
|
||||
"narHash": "sha256-YNkUMcCUCpnULp40g+svYsaH1RbSEj6s4WdZY/SHe38=",
|
||||
"owner": "hercules-ci",
|
||||
"repo": "hercules-ci-effects",
|
||||
"rev": "11e4b8dc112e2f485d7c97e1cee77f9958f498f5",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "hercules-ci",
|
||||
"repo": "hercules-ci-effects",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nixpkgs": {
|
||||
"locked": {
|
||||
"lastModified": 1722630782,
|
||||
"narHash": "sha256-hMyG9/WlUi0Ho9VkRrrez7SeNlDzLxalm9FwY7n/Noo=",
|
||||
"lastModified": 1669980218,
|
||||
"narHash": "sha256-HBK1tIqarj7ZsSwQEKGlyvbAIFnglytG7FxuS4K3nY8=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "d04953086551086b44b6f3c6b7eeb26294f207da",
|
||||
"rev": "da7988fe440ef5b8779d4f76340ad7dc79ff3b33",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "NixOS",
|
||||
"ref": "nixos-unstable",
|
||||
"ref": "haskell-updates",
|
||||
"repo": "nixpkgs",
|
||||
"type": "github"
|
||||
}
|
||||
|
@ -97,7 +56,6 @@
|
|||
"inputs": {
|
||||
"flake-parts": "flake-parts",
|
||||
"haskell-flake": "haskell-flake",
|
||||
"hercules-ci-effects": "hercules-ci-effects",
|
||||
"nixpkgs": "nixpkgs"
|
||||
}
|
||||
}
|
||||
|
|
40
flake.nix
40
flake.nix
|
@ -2,19 +2,16 @@
|
|||
description = "Arion - use Docker Compose via Nix";
|
||||
|
||||
inputs = {
|
||||
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
|
||||
haskell-flake.url = "github:srid/haskell-flake/0.1.0";
|
||||
flake-parts.url = "github:hercules-ci/flake-parts";
|
||||
nixpkgs.url = "github:NixOS/nixpkgs/haskell-updates";
|
||||
haskell-flake.url = "github:srid/haskell-flake";
|
||||
flake-parts.url = "github:hercules-ci/flake-parts/easyOverlay"; # TODO merge
|
||||
flake-parts.inputs.nixpkgs-lib.follows = "nixpkgs";
|
||||
hercules-ci-effects.url = "github:hercules-ci/hercules-ci-effects";
|
||||
hercules-ci-effects.inputs.nixpkgs.follows = "nixpkgs";
|
||||
};
|
||||
|
||||
outputs = inputs@{ self, flake-parts, ... }:
|
||||
flake-parts.lib.mkFlake { inherit inputs; } ({ config, lib, extendModules, ... }: {
|
||||
flake-parts.lib.mkFlake { inherit self; } ({ config, lib, extendModules, ... }: {
|
||||
imports = [
|
||||
inputs.haskell-flake.flakeModule
|
||||
inputs.hercules-ci-effects.flakeModule
|
||||
inputs.flake-parts.flakeModules.easyOverlay
|
||||
./docs/flake-module.nix
|
||||
./tests/flake-module.nix
|
||||
|
@ -66,26 +63,15 @@
|
|||
];
|
||||
});
|
||||
};
|
||||
|
||||
hercules-ci.flake-update = {
|
||||
enable = true;
|
||||
autoMergeMethod = "merge";
|
||||
when = {
|
||||
hour = [ 2 ];
|
||||
dayOfMonth = [ 5 ];
|
||||
};
|
||||
};
|
||||
|
||||
herculesCI.ciSystems = [
|
||||
# "aarch64-darwin"
|
||||
# "aarch64-linux"
|
||||
"x86_64-darwin"
|
||||
"x86_64-linux"
|
||||
];
|
||||
|
||||
flake = {
|
||||
debug = { inherit inputs config lib; };
|
||||
|
||||
defaultPackage =
|
||||
lib.mapAttrs
|
||||
(ps: lib.warn "arion.defaultPackage has been removed in favor of arion.packages.\${system}.default"
|
||||
ps.default)
|
||||
config.flake.packages;
|
||||
|
||||
lib = {
|
||||
eval = import ./src/nix/eval-composition.nix;
|
||||
build = args@{ ... }:
|
||||
|
@ -93,6 +79,12 @@
|
|||
in composition.config.out.dockerComposeYaml;
|
||||
};
|
||||
nixosModules.arion = ./nixos-module.nix;
|
||||
herculesCI.ciSystems = [
|
||||
# "aarch64-darwin"
|
||||
# "aarch64-linux"
|
||||
"x86_64-darwin"
|
||||
"x86_64-linux"
|
||||
];
|
||||
};
|
||||
});
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
{ config, lib, options, pkgs, ... }:
|
||||
{ config, lib, pkgs, ... }:
|
||||
let
|
||||
inherit (lib)
|
||||
attrValues
|
||||
|
@ -26,14 +26,9 @@ let
|
|||
visible = "shallow";
|
||||
};
|
||||
_systemd = mkOption { internal = true; };
|
||||
serviceName = mkOption {
|
||||
description = "The name of the Arion project's systemd service";
|
||||
type = types.str;
|
||||
default = "arion-${name}";
|
||||
};
|
||||
};
|
||||
config = {
|
||||
_systemd.services.${config.serviceName} = {
|
||||
_systemd.services."arion-${name}" = {
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
after = [ "sockets.target" ];
|
||||
|
||||
|
@ -51,7 +46,7 @@ let
|
|||
};
|
||||
|
||||
arionSettingsType = name:
|
||||
(cfg.package.eval { modules = [{ project.name = lib.mkDefault name; }]; }).type or (
|
||||
(cfg.package.eval { modules = [ { project.name = lib.mkDefault name; } ]; }).type or (
|
||||
throw "lib.evalModules did not produce a type. Please upgrade Nixpkgs to nixos-unstable or >=nixos-21.11"
|
||||
);
|
||||
|
||||
|
@ -69,7 +64,7 @@ in
|
|||
};
|
||||
package = mkOption {
|
||||
type = types.package;
|
||||
|
||||
|
||||
default = (import ./. { inherit pkgs; }).arion;
|
||||
description = ''
|
||||
Arion package to use. This will provide <literal>arion</literal>
|
||||
|
@ -102,10 +97,7 @@ in
|
|||
virtualisation.docker.enable = false;
|
||||
virtualisation.podman.enable = true;
|
||||
virtualisation.podman.dockerSocket.enable = true;
|
||||
virtualisation.podman.defaultNetwork =
|
||||
if options?virtualisation.podman.defaultNetwork.settings
|
||||
then { settings.dns_enabled = true; } # since 2023-01 https://github.com/NixOS/nixpkgs/pull/199965
|
||||
else { dnsname.enable = true; }; # compat <2023
|
||||
virtualisation.podman.defaultNetwork.dnsname.enable = true;
|
||||
|
||||
virtualisation.arion.docker.client.package = pkgs.docker-client;
|
||||
})
|
||||
|
|
|
@ -3,4 +3,4 @@
|
|||
# For manual testing of a hacked arion built via Nix.
|
||||
# Works when called from outside the project directory.
|
||||
|
||||
exec nix run -f "$(dirname ${BASH_SOURCE[0]})" arion "$@"
|
||||
exec nix run -f "$(dirname ${BASH_SOURCE[0]})" arion -c arion "$@"
|
||||
|
|
|
@ -13,34 +13,19 @@ import qualified Data.Text as T
|
|||
import qualified Data.Text.IO as T
|
||||
|
||||
spec :: Spec
|
||||
spec = describe "evaluateComposition" $ do
|
||||
it "matches an example" $ do
|
||||
x <- Arion.Nix.evaluateComposition EvaluationArgs
|
||||
{ evalUid = 123
|
||||
, evalModules = NEL.fromList
|
||||
["src/haskell/testdata/Arion/NixSpec/arion-compose.nix"]
|
||||
, evalPkgs = "import <nixpkgs> { system = \"x86_64-linux\"; }"
|
||||
, evalWorkDir = Nothing
|
||||
, evalMode = ReadOnly
|
||||
, evalUserArgs = ["--show-trace"]
|
||||
}
|
||||
let actual = pretty x
|
||||
expected <- T.readFile "src/haskell/testdata/Arion/NixSpec/arion-compose.json"
|
||||
censorPaths actual `shouldBe` censorPaths expected
|
||||
|
||||
it "matches an build.context example" $ do
|
||||
x <- Arion.Nix.evaluateComposition EvaluationArgs
|
||||
{ evalUid = 1234
|
||||
, evalModules = NEL.fromList
|
||||
["src/haskell/testdata/Arion/NixSpec/arion-context-compose.nix"]
|
||||
, evalPkgs = "import <nixpkgs> { system = \"x86_64-linux\"; }"
|
||||
, evalWorkDir = Nothing
|
||||
, evalMode = ReadOnly
|
||||
, evalUserArgs = ["--show-trace"]
|
||||
}
|
||||
let actual = pretty x
|
||||
expected <- T.readFile "src/haskell/testdata/Arion/NixSpec/arion-context-compose.json"
|
||||
censorPaths actual `shouldBe` censorPaths expected
|
||||
spec = describe "evaluateComposition" $ it "matches an example" $ do
|
||||
x <- Arion.Nix.evaluateComposition EvaluationArgs
|
||||
{ evalUid = 123
|
||||
, evalModules = NEL.fromList
|
||||
["src/haskell/testdata/Arion/NixSpec/arion-compose.nix"]
|
||||
, evalPkgs = "import <nixpkgs> { system = \"x86_64-linux\"; }"
|
||||
, evalWorkDir = Nothing
|
||||
, evalMode = ReadOnly
|
||||
, evalUserArgs = ["--show-trace"]
|
||||
}
|
||||
let actual = pretty x
|
||||
expected <- T.readFile "src/haskell/testdata/Arion/NixSpec/arion-compose.json"
|
||||
censorPaths actual `shouldBe` censorPaths expected
|
||||
|
||||
censorPaths :: Text -> Text
|
||||
censorPaths = censorImages . censorStorePaths
|
||||
|
|
|
@ -9,4 +9,3 @@ import qualified Arion.NixSpec
|
|||
spec :: Spec
|
||||
spec = do
|
||||
describe "Arion.Nix" Arion.NixSpec.spec
|
||||
|
||||
|
|
|
@ -33,7 +33,6 @@
|
|||
}
|
||||
},
|
||||
"version": "3.4",
|
||||
"volumes": {},
|
||||
"x-arion": {
|
||||
"images": [
|
||||
{
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
project.name = "unit-test-data";
|
||||
services.webserver = { pkgs, ... }: {
|
||||
nixos.useSystemd = true;
|
||||
nixos.configuration.boot.tmp.useTmpfs = true;
|
||||
nixos.configuration.boot.tmpOnTmpfs = true;
|
||||
nixos.configuration.services.nginx.enable = true;
|
||||
nixos.configuration.services.nginx.virtualHosts.localhost.root = "${pkgs.nix.doc}/share/doc/nix/manual";
|
||||
service.useHostStore = true;
|
||||
|
|
|
@ -1,41 +0,0 @@
|
|||
{
|
||||
"networks": {
|
||||
"default": {
|
||||
"name": "unit-test-data"
|
||||
}
|
||||
},
|
||||
"services": {
|
||||
"webserver": {
|
||||
"build": {
|
||||
"context": "<STOREPATH>"
|
||||
},
|
||||
"environment": {},
|
||||
"ports": [
|
||||
"8080:80"
|
||||
],
|
||||
"sysctls": {},
|
||||
"volumes": []
|
||||
}
|
||||
},
|
||||
"version": "3.4",
|
||||
"volumes": {},
|
||||
"x-arion": {
|
||||
"images": [
|
||||
{
|
||||
"imageExe": "<STOREPATH>",
|
||||
"imageName": "localhost/webserver",
|
||||
"imageTag": "<HASH>"
|
||||
}
|
||||
],
|
||||
"project": {
|
||||
"name": "unit-test-data"
|
||||
},
|
||||
"serviceInfo": {
|
||||
"webserver": {
|
||||
"defaultExec": [
|
||||
"/bin/sh"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,9 +0,0 @@
|
|||
{
|
||||
project.name = "unit-test-data";
|
||||
services.webserver.service = {
|
||||
build.context = "${./build-context}";
|
||||
ports = [
|
||||
"8080:80"
|
||||
];
|
||||
};
|
||||
}
|
|
@ -1,4 +0,0 @@
|
|||
FROM nginx
|
||||
|
||||
RUN echo this is a dockerfile to be built
|
||||
|
|
@ -1,21 +1,16 @@
|
|||
{ lib }:
|
||||
let
|
||||
|
||||
link = url: text: ''[${text}](${url})'';
|
||||
link = url: text:
|
||||
''link:${url}[${text}]'';
|
||||
|
||||
composeSpecRev = "55b450aee50799a2f33cc99e1d714518babe305e";
|
||||
|
||||
serviceRef = fragment:
|
||||
''See ${link "https://github.com/compose-spec/compose-spec/blob/${composeSpecRev}/05-services.md#${fragment}" "Compose Spec Services #${fragment}"}'';
|
||||
|
||||
networkRef = fragment:
|
||||
''See ${link "https://github.com/compose-spec/compose-spec/blob/${composeSpecRev}/06-networks.md#${fragment}" "Compose Spec Networks #${fragment}"}'';
|
||||
dockerComposeRef = fragment:
|
||||
''See ${link "https://docs.docker.com/compose/compose-file/#${fragment}" "Docker Compose#${fragment}"}'';
|
||||
|
||||
in
|
||||
{
|
||||
inherit
|
||||
dockerComposeRef
|
||||
link
|
||||
networkRef
|
||||
serviceRef
|
||||
;
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@ let
|
|||
inherit (lib) types mkOption;
|
||||
|
||||
link = url: text:
|
||||
''[${text}](${url})'';
|
||||
''link:${url}[${text}]'';
|
||||
|
||||
in
|
||||
{
|
||||
|
|
|
@ -63,11 +63,6 @@ in
|
|||
type = lib.types.attrsOf (lib.types.submodule service);
|
||||
description = "An attribute set of service configurations. A service specifies how to run an image as a container.";
|
||||
};
|
||||
docker-compose.volumes = lib.mkOption {
|
||||
type = lib.types.attrsOf lib.types.unspecified;
|
||||
description = "A attribute set of volume configurations.";
|
||||
default = {};
|
||||
};
|
||||
};
|
||||
config = {
|
||||
out.dockerComposeYaml = pkgs.writeText "docker-compose.yaml" config.out.dockerComposeYamlText;
|
||||
|
@ -78,7 +73,6 @@ in
|
|||
version = "3.4";
|
||||
services = lib.mapAttrs (k: c: c.out.service) config.services;
|
||||
x-arion = config.docker-compose.extended;
|
||||
volumes = config.docker-compose.volumes;
|
||||
};
|
||||
};
|
||||
}
|
||||
|
|
|
@ -23,9 +23,9 @@
|
|||
stored at an alternate location without altering the format of
|
||||
store paths.
|
||||
|
||||
For example: instead of mounting the host's `/nix/store` as the
|
||||
container's `/nix/store`, this will mount `/mnt/foo/nix/store`
|
||||
as the container's `/nix/store`.
|
||||
For example: instead of mounting the host's /nix/store as the
|
||||
container's /nix/store, this will mount /mnt/foo/nix/store
|
||||
as the container's /nix/store.
|
||||
'';
|
||||
};
|
||||
|
||||
|
|
|
@ -36,7 +36,7 @@ in
|
|||
build.imagesToLoad = lib.mkOption {
|
||||
type = listOf unspecified;
|
||||
internal = true;
|
||||
description = "List of `dockerTools` image derivations.";
|
||||
description = "List of dockerTools image derivations.";
|
||||
};
|
||||
};
|
||||
config = {
|
||||
|
|
|
@ -7,7 +7,7 @@ let
|
|||
types
|
||||
;
|
||||
inherit (import ../../lib.nix { inherit lib; })
|
||||
link
|
||||
dockerComposeRef
|
||||
;
|
||||
in
|
||||
{
|
||||
|
@ -19,7 +19,7 @@ in
|
|||
];
|
||||
});
|
||||
description = ''
|
||||
See ${link "https://docs.docker.com/compose/compose-file/06-networks/" "Docker Compose Networks"}
|
||||
${dockerComposeRef "networks-top-level-element"}
|
||||
'';
|
||||
};
|
||||
enableDefaultNetwork = mkOption {
|
||||
|
|
|
@ -7,7 +7,7 @@ let
|
|||
types
|
||||
;
|
||||
inherit (import ../../lib.nix { inherit lib; })
|
||||
networkRef
|
||||
dockerComposeRef
|
||||
;
|
||||
in
|
||||
{
|
||||
|
@ -15,21 +15,21 @@ in
|
|||
driver = mkOption {
|
||||
description = ''
|
||||
`"none"`, `"host"`, or a platform-specific value.
|
||||
${networkRef "driver"}
|
||||
${dockerComposeRef "driver"}
|
||||
'';
|
||||
type = types.str;
|
||||
};
|
||||
|
||||
driver_opts = mkOption {
|
||||
description = ''
|
||||
${networkRef "driver_opts"}
|
||||
${dockerComposeRef "driver_opts"}
|
||||
'';
|
||||
type = types.lazyAttrsOf types.raw or types.unspecified;
|
||||
};
|
||||
|
||||
attachable = mkOption {
|
||||
description = ''
|
||||
${networkRef "attachable"}
|
||||
${dockerComposeRef "attachable"}
|
||||
'';
|
||||
type = types.bool;
|
||||
example = true;
|
||||
|
@ -39,7 +39,7 @@ in
|
|||
description = ''
|
||||
Whether we've entered the 21st century yet.
|
||||
|
||||
${networkRef "enable_ipv6"}
|
||||
${dockerComposeRef "enable_ipv6"}
|
||||
'';
|
||||
type = types.bool;
|
||||
};
|
||||
|
@ -49,7 +49,7 @@ in
|
|||
description = ''
|
||||
Manage IP addresses.
|
||||
|
||||
${networkRef "ipam"}
|
||||
${dockerComposeRef "ipam"}
|
||||
'';
|
||||
type = types.raw or types.unspecified;
|
||||
};
|
||||
|
@ -58,7 +58,7 @@ in
|
|||
description = ''
|
||||
Achieves "external isolation".
|
||||
|
||||
${networkRef "internal"}
|
||||
${dockerComposeRef "internal"}
|
||||
'';
|
||||
defaultText = false;
|
||||
type = types.bool;
|
||||
|
@ -68,7 +68,7 @@ in
|
|||
description = ''
|
||||
Metadata.
|
||||
|
||||
${networkRef "labels"}
|
||||
${dockerComposeRef "labels"}
|
||||
'';
|
||||
# no list support, because less expressive wrt overriding
|
||||
type = types.attrsOf types.str;
|
||||
|
@ -79,7 +79,7 @@ in
|
|||
When `true`, don't create or destroy the network, but assume that it
|
||||
exists.
|
||||
|
||||
${networkRef "external"}
|
||||
${dockerComposeRef "external"}
|
||||
'';
|
||||
type = types.bool;
|
||||
};
|
||||
|
@ -92,7 +92,7 @@ in
|
|||
|
||||
Note the `default` network's default `name` is set to `project.name` by Arion.
|
||||
|
||||
${networkRef "name"}
|
||||
${dockerComposeRef "name"}
|
||||
'';
|
||||
type = types.str;
|
||||
};
|
||||
|
|
|
@ -12,9 +12,15 @@ let
|
|||
|
||||
inherit (import ../../lib.nix { inherit lib; })
|
||||
link
|
||||
serviceRef
|
||||
dockerComposeRef
|
||||
;
|
||||
|
||||
dockerComposeKitchenSink = ''
|
||||
Analogous to the `docker run` counterpart.
|
||||
|
||||
${dockerComposeRef "domainname-hostname-ipc-mac_address-privileged-read_only-shm_size-stdin_open-tty-user-working_dir"}
|
||||
'';
|
||||
|
||||
cap_add = lib.attrNames (lib.filterAttrs (name: value: value == true) config.service.capabilities);
|
||||
cap_drop = lib.attrNames (lib.filterAttrs (name: value: value == false) config.service.capabilities);
|
||||
|
||||
|
@ -50,12 +56,12 @@ in
|
|||
service.volumes = mkOption {
|
||||
type = listOf types.unspecified;
|
||||
default = [];
|
||||
description = serviceRef "volumes";
|
||||
description = dockerComposeRef "volumes";
|
||||
};
|
||||
service.tmpfs = mkOption {
|
||||
type = listOf types.str;
|
||||
default = [];
|
||||
description = serviceRef "tmpfs";
|
||||
description = dockerComposeRef "tmpfs";
|
||||
};
|
||||
service.build.context = mkOption {
|
||||
type = nullOr str;
|
||||
|
@ -63,65 +69,44 @@ in
|
|||
description = ''
|
||||
Locates a Dockerfile to use for creating an image to use in this service.
|
||||
|
||||
https://docs.docker.com/compose/compose-file/build/#context
|
||||
'';
|
||||
};
|
||||
service.build.dockerfile = mkOption {
|
||||
type = nullOr str;
|
||||
default = null;
|
||||
description = ''
|
||||
Sets an alternate Dockerfile. A relative path is resolved from the build context.
|
||||
https://docs.docker.com/compose/compose-file/build/#dockerfile
|
||||
'';
|
||||
};
|
||||
service.build.target = mkOption {
|
||||
type = nullOr str;
|
||||
default = null;
|
||||
description = ''
|
||||
Defines the stage to build as defined inside a multi-stage Dockerfile.
|
||||
https://docs.docker.com/compose/compose-file/build/#target
|
||||
${dockerComposeRef "context"}
|
||||
'';
|
||||
};
|
||||
service.hostname = mkOption {
|
||||
type = nullOr str;
|
||||
default = null;
|
||||
description = ''
|
||||
${serviceRef "hostname"}
|
||||
'';
|
||||
description = dockerComposeKitchenSink;
|
||||
};
|
||||
service.tty = mkOption {
|
||||
type = nullOr bool;
|
||||
default = null;
|
||||
description = ''
|
||||
${serviceRef "tty"}
|
||||
'';
|
||||
description = dockerComposeKitchenSink;
|
||||
};
|
||||
service.environment = mkOption {
|
||||
type = attrsOf (either str int);
|
||||
default = {};
|
||||
description = serviceRef "environment";
|
||||
description = dockerComposeRef "environment";
|
||||
};
|
||||
service.image = mkOption {
|
||||
type = nullOr str;
|
||||
default = null;
|
||||
description = serviceRef "image";
|
||||
type = str;
|
||||
description = dockerComposeRef "image";
|
||||
};
|
||||
service.command = mkOption {
|
||||
type = nullOr types.unspecified;
|
||||
default = null;
|
||||
description = serviceRef "command";
|
||||
description = dockerComposeRef "command";
|
||||
};
|
||||
service.container_name = mkOption {
|
||||
type = nullOr types.str;
|
||||
default = null;
|
||||
description = serviceRef "container_name";
|
||||
description = dockerComposeRef "container_name";
|
||||
};
|
||||
service.depends_on =
|
||||
let conditionsModule = {
|
||||
options = {
|
||||
condition = mkOption {
|
||||
type = enum ["service_started" "service_healthy" "service_completed_successfully"];
|
||||
description = serviceRef "depends_on";
|
||||
description = dockerComposeRef "depends_on";
|
||||
default = "service_started";
|
||||
};
|
||||
};
|
||||
|
@ -129,10 +114,10 @@ in
|
|||
in mkOption {
|
||||
type = either (listOf str) (attrsOf (submodule conditionsModule));
|
||||
default = [];
|
||||
description = serviceRef "depends_on";
|
||||
description = dockerComposeRef "depends_on";
|
||||
};
|
||||
service.healthcheck = mkOption {
|
||||
description = serviceRef "healthcheck";
|
||||
description = dockerComposeRef "healthcheck";
|
||||
type = submodule ({ config, options, ...}: {
|
||||
options = {
|
||||
_out = mkOption {
|
||||
|
@ -145,30 +130,30 @@ in
|
|||
type = nullOr (listOf str);
|
||||
default = null;
|
||||
example = [ "CMD" "pg_isready" ];
|
||||
description = serviceRef "healthcheck";
|
||||
description = dockerComposeRef "healthcheck";
|
||||
};
|
||||
interval = mkOption {
|
||||
type = str;
|
||||
default = "30s";
|
||||
example = "1m";
|
||||
description = serviceRef "healthcheck";
|
||||
description = dockerComposeRef "healthcheck";
|
||||
};
|
||||
timeout = mkOption {
|
||||
type = str;
|
||||
default = "30s";
|
||||
example = "10s";
|
||||
description = serviceRef "healthcheck";
|
||||
description = dockerComposeRef "healthcheck";
|
||||
};
|
||||
start_period = mkOption {
|
||||
type = str;
|
||||
default = "0s";
|
||||
example = "30s";
|
||||
description = serviceRef "healthcheck";
|
||||
description = dockerComposeRef "healthcheck";
|
||||
};
|
||||
retries = mkOption {
|
||||
type = int;
|
||||
default = 3;
|
||||
description = serviceRef "healthcheck";
|
||||
description = dockerComposeRef "healthcheck";
|
||||
};
|
||||
};
|
||||
});
|
||||
|
@ -180,14 +165,14 @@ in
|
|||
See ${link "https://docs.docker.com/engine/reference/run/#runtime-privilege-and-linux-capabilities"
|
||||
"`docker run --device` documentation"}
|
||||
|
||||
${serviceRef "devices"}
|
||||
${dockerComposeRef "devices"}
|
||||
'';
|
||||
};
|
||||
service.dns = mkOption {
|
||||
type = listOf str;
|
||||
default = [];
|
||||
example = [ "8.8.8.8" "8.8.4.4" ];
|
||||
description = serviceRef "dns";
|
||||
description = dockerComposeRef "dns";
|
||||
};
|
||||
service.labels = mkOption {
|
||||
type = attrsOf str;
|
||||
|
@ -198,58 +183,47 @@ in
|
|||
"traefik.http.routers.my-service.rule" = "Host(`my-service.localhost`)";
|
||||
"traefik.http.routers.my-service.entrypoints" = "web";
|
||||
};
|
||||
description = serviceRef "labels";
|
||||
description = dockerComposeRef "labels";
|
||||
};
|
||||
service.links = mkOption {
|
||||
type = listOf str;
|
||||
default = [];
|
||||
description = serviceRef "links";
|
||||
description = dockerComposeRef "links";
|
||||
};
|
||||
service.external_links = mkOption {
|
||||
type = listOf str;
|
||||
default = [];
|
||||
description = serviceRef "external_links";
|
||||
};
|
||||
service.profiles = mkOption {
|
||||
type = listOf str;
|
||||
default = [];
|
||||
description = serviceRef "profiles";
|
||||
description = dockerComposeRef "external_links";
|
||||
};
|
||||
service.extra_hosts = mkOption {
|
||||
type = listOf str;
|
||||
default = [];
|
||||
description = serviceRef "extra_hosts";
|
||||
description = dockerComposeRef "extra_hosts";
|
||||
};
|
||||
service.working_dir = mkOption {
|
||||
type = nullOr str;
|
||||
default = null;
|
||||
description = ''
|
||||
${serviceRef "working_dir"}
|
||||
'';
|
||||
description = dockerComposeKitchenSink;
|
||||
};
|
||||
service.privileged = mkOption {
|
||||
type = nullOr bool;
|
||||
default = null;
|
||||
description = ''
|
||||
${serviceRef "privileged"}
|
||||
'';
|
||||
description = dockerComposeKitchenSink;
|
||||
};
|
||||
service.entrypoint = mkOption {
|
||||
type = nullOr str;
|
||||
default = null;
|
||||
description = serviceRef "entrypoint";
|
||||
description = dockerComposeRef "entrypoint";
|
||||
};
|
||||
service.restart = mkOption {
|
||||
type = nullOr str;
|
||||
default = null;
|
||||
description = serviceRef "restart";
|
||||
description = dockerComposeRef "restart";
|
||||
};
|
||||
service.user = mkOption {
|
||||
type = nullOr str;
|
||||
default = null;
|
||||
description = ''
|
||||
${serviceRef "user"}
|
||||
'';
|
||||
description = dockerComposeKitchenSink;
|
||||
};
|
||||
service.ports = mkOption {
|
||||
type = listOf types.unspecified;
|
||||
|
@ -257,76 +231,38 @@ in
|
|||
description = ''
|
||||
Expose ports on host. "host:container" or structured.
|
||||
|
||||
${serviceRef "ports"}
|
||||
${dockerComposeRef "ports"}
|
||||
'';
|
||||
};
|
||||
service.expose = mkOption {
|
||||
type = listOf str;
|
||||
default = [];
|
||||
description = serviceRef "expose";
|
||||
description = dockerComposeRef "expose";
|
||||
};
|
||||
service.env_file = mkOption {
|
||||
type = listOf str;
|
||||
default = [];
|
||||
description = serviceRef "env_file";
|
||||
description = dockerComposeRef "env_file";
|
||||
};
|
||||
service.network_mode = mkOption {
|
||||
type = nullOr str;
|
||||
default = null;
|
||||
description = serviceRef "network_mode";
|
||||
description = dockerComposeRef "network_mode";
|
||||
};
|
||||
service.networks = mkOption {
|
||||
type = nullOr (listOf types.str);
|
||||
default = null;
|
||||
description = dockerComposeRef "networks";
|
||||
};
|
||||
service.networks =
|
||||
let
|
||||
networksModule = submodule ({ config, options, ...}: {
|
||||
options = {
|
||||
_out = mkOption {
|
||||
internal = true;
|
||||
readOnly = true;
|
||||
default = lib.mapAttrs (k: opt: opt.value) (lib.filterAttrs (_: opt: opt.isDefined) { inherit (options) aliases ipv4_address ipv6_address link_local_ips priority; });
|
||||
};
|
||||
aliases = mkOption {
|
||||
type = listOf str;
|
||||
description = serviceRef "aliases";
|
||||
default = [ ];
|
||||
};
|
||||
ipv4_address = mkOption {
|
||||
type = str;
|
||||
description = serviceRef "ipv4_address-ipv6_address";
|
||||
};
|
||||
ipv6_address = mkOption {
|
||||
type = str;
|
||||
description = serviceRef "ipv4_address-ipv6_address";
|
||||
};
|
||||
link_local_ips = mkOption {
|
||||
type = listOf str;
|
||||
description = serviceRef "link_local_ips";
|
||||
};
|
||||
priority = mkOption {
|
||||
type = int;
|
||||
description = serviceRef "priority";
|
||||
};
|
||||
};
|
||||
});
|
||||
in
|
||||
mkOption {
|
||||
type = either (listOf str) (attrsOf networksModule);
|
||||
default = [];
|
||||
description = serviceRef "networks";
|
||||
};
|
||||
service.stop_signal = mkOption {
|
||||
type = nullOr str;
|
||||
default = null;
|
||||
description = serviceRef "stop_signal";
|
||||
};
|
||||
service.stop_grace_period = mkOption {
|
||||
type = nullOr str;
|
||||
default = null;
|
||||
description = serviceRef "stop_grace_period";
|
||||
description = dockerComposeRef "stop_signal";
|
||||
};
|
||||
service.sysctls = mkOption {
|
||||
type = attrsOf (either str int);
|
||||
default = {};
|
||||
description = serviceRef "sysctls";
|
||||
description = dockerComposeRef "sysctls";
|
||||
};
|
||||
service.capabilities = mkOption {
|
||||
type = attrsOf (nullOr bool);
|
||||
|
@ -337,15 +273,13 @@ in
|
|||
|
||||
Setting a capability to `true` means that it will be
|
||||
"added". Setting it to `false` means that it will be "dropped".
|
||||
${dockerComposeRef "cap_add-cap_drop"}
|
||||
|
||||
Omitted and `null` capabilities will therefore be set
|
||||
according to Docker's ${
|
||||
link "https://docs.docker.com/engine/reference/run/#runtime-privilege-and-linux-capabilities"
|
||||
"default list of capabilities."
|
||||
}
|
||||
|
||||
${serviceRef "cap_add"}
|
||||
${serviceRef "cap_drop"}
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
@ -355,11 +289,10 @@ in
|
|||
volumes
|
||||
environment
|
||||
sysctls
|
||||
image
|
||||
;
|
||||
} // lib.optionalAttrs (config.service.image != null) {
|
||||
inherit (config.service) image;
|
||||
} // lib.optionalAttrs (config.service.build.context != null ) {
|
||||
build = lib.filterAttrs (n: v: v != null) config.service.build;
|
||||
} // lib.optionalAttrs (config.service.build.context != null) {
|
||||
inherit (config.service) build;
|
||||
} // lib.optionalAttrs (cap_add != []) {
|
||||
inherit cap_add;
|
||||
} // lib.optionalAttrs (cap_drop != []) {
|
||||
|
@ -398,16 +331,12 @@ in
|
|||
inherit (config.service) privileged;
|
||||
} // lib.optionalAttrs (config.service.network_mode != null) {
|
||||
inherit (config.service) network_mode;
|
||||
} // lib.optionalAttrs (config.service.networks != [] && config.service.networks != {}) {
|
||||
networks =
|
||||
if (builtins.isAttrs config.service.networks) then builtins.mapAttrs (_: v: v._out) config.service.networks
|
||||
else config.service.networks;
|
||||
} // lib.optionalAttrs (config.service.networks != null) {
|
||||
inherit (config.service) networks;
|
||||
} // lib.optionalAttrs (config.service.restart != null) {
|
||||
inherit (config.service) restart;
|
||||
} // lib.optionalAttrs (config.service.stop_signal != null) {
|
||||
inherit (config.service) stop_signal;
|
||||
} // lib.optionalAttrs (config.service.stop_grace_period != null) {
|
||||
inherit (config.service) stop_grace_period;
|
||||
} // lib.optionalAttrs (config.service.tmpfs != []) {
|
||||
inherit (config.service) tmpfs;
|
||||
} // lib.optionalAttrs (config.service.tty != null) {
|
||||
|
@ -416,7 +345,5 @@ in
|
|||
inherit (config.service) working_dir;
|
||||
} // lib.optionalAttrs (config.service.user != null) {
|
||||
inherit (config.service) user;
|
||||
} // lib.optionalAttrs (config.service.profiles != []) {
|
||||
inherit (config.service) profiles;
|
||||
};
|
||||
}
|
||||
|
|
|
@ -12,7 +12,7 @@ in
|
|||
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
|
||||
but that will not be used by the `docker-compose`> command
|
||||
itself.
|
||||
|
||||
It will be inserted in `x-arion.serviceInfo.<service.name>`.
|
||||
|
|
|
@ -20,7 +20,7 @@ in
|
|||
service.hostStoreAsReadOnly = mkOption {
|
||||
type = types.bool;
|
||||
default = true;
|
||||
description = "Adds a `:ro` (read-only) access mode to the host nix store bind mount.";
|
||||
description = "Adds a ':ro' (read-only) access mode to the host nix store bind mount.";
|
||||
};
|
||||
service.useHostNixDaemon = mkOption {
|
||||
type = types.bool;
|
||||
|
|
|
@ -28,9 +28,12 @@ in
|
|||
};
|
||||
};
|
||||
|
||||
config = {
|
||||
image.contents = mkIf config.image.enableRecommendedContents [
|
||||
config = mkIf config.image.enableRecommendedContents {
|
||||
image.contents = [
|
||||
(pkgs.callPackage recommendedContents {})
|
||||
];
|
||||
image.rawConfig.Env = {
|
||||
"PATH" = lib.mkDefault "/run/current-system/sw/bin:/bin:/usr/bin:/usr/local/bin";
|
||||
};
|
||||
};
|
||||
}
|
||||
|
|
|
@ -30,7 +30,6 @@ let
|
|||
{
|
||||
name = null; tag = null; contents = null; config = null;
|
||||
created = null; extraCommands = null; maxLayers = null;
|
||||
fakeRootCommands = null;
|
||||
}
|
||||
args;
|
||||
acceptedArgs = functionArgs dockerTools.streamLayeredImage;
|
||||
|
@ -68,8 +67,6 @@ let
|
|||
ln -s $i nix/var/nix/gcroots/docker/$(basename $i)
|
||||
done;
|
||||
'';
|
||||
|
||||
fakeRootCommands = config.image.fakeRootCommands;
|
||||
};
|
||||
|
||||
priorityIsDefault = option: option.highestPrio >= (lib.mkDefault true).priority;
|
||||
|
@ -79,18 +76,18 @@ in
|
|||
build.image = mkOption {
|
||||
type = nullOr package;
|
||||
description = ''
|
||||
Docker image derivation to be `docker load`-ed.
|
||||
Docker image derivation to be `docker load`ed.
|
||||
'';
|
||||
internal = true;
|
||||
};
|
||||
build.imageName = mkOption {
|
||||
type = str;
|
||||
description = "Derived from `build.image`";
|
||||
description = "Derived from build.image";
|
||||
internal = true;
|
||||
};
|
||||
build.imageTag = mkOption {
|
||||
type = str;
|
||||
description = "Derived from `build.image`";
|
||||
description = "Derived from build.image";
|
||||
internal = true;
|
||||
};
|
||||
image.nixBuild = mkOption {
|
||||
|
@ -123,22 +120,13 @@ in
|
|||
Top level paths in the container.
|
||||
'';
|
||||
};
|
||||
image.fakeRootCommands = mkOption {
|
||||
type = types.lines;
|
||||
default = "";
|
||||
description = ''
|
||||
Commands that build the root of the container in the current working directory.
|
||||
|
||||
See [`dockerTools.buildLayeredImage`](https://nixos.org/manual/nixpkgs/stable/#ssec-pkgs-dockerTools-buildLayeredImage).
|
||||
'';
|
||||
};
|
||||
image.includeStorePaths = mkOption {
|
||||
type = bool;
|
||||
default = true;
|
||||
internal = true;
|
||||
description = ''
|
||||
Include all referenced store paths. You generally want this in your
|
||||
image, unless you load store paths via some other means, like `useHostStore = true`;
|
||||
image, unless you load store paths via some other means, like useHostStore = true;
|
||||
'';
|
||||
};
|
||||
image.rawConfig = mkOption {
|
||||
|
@ -152,8 +140,8 @@ in
|
|||
Please use the specific `image` options instead.
|
||||
|
||||
Run-time configuration of the container. A full list of the
|
||||
options is available in the [Docker Image Specification
|
||||
v1.2.0](https://github.com/moby/moby/blob/master/image/spec/v1.2.md#image-json-field-descriptions).
|
||||
options is available in the https://github.com/moby/moby/blob/master/image/spec/v1.2.md#image-json-field-descriptions[Docker Image Specification
|
||||
v1.2.0].
|
||||
'';
|
||||
};
|
||||
image.command = mkOption {
|
||||
|
@ -163,19 +151,17 @@ in
|
|||
'';
|
||||
};
|
||||
};
|
||||
config = lib.mkMerge [{
|
||||
build.image = builtImage;
|
||||
build.imageName = config.build.image.imageName;
|
||||
build.imageTag =
|
||||
if config.build.image.imageTag != ""
|
||||
then config.build.image.imageTag
|
||||
else lib.head (lib.strings.splitString "-" (baseNameOf config.build.image.outPath));
|
||||
image.rawConfig.Cmd = config.image.command;
|
||||
image.nixBuild = lib.mkDefault (priorityIsDefault options.service.image);
|
||||
}
|
||||
( lib.mkIf (config.service.build.context == null)
|
||||
{
|
||||
service.image = lib.mkDefault "${config.build.imageName}:${config.build.imageTag}";
|
||||
})
|
||||
];
|
||||
config = {
|
||||
build.image = builtImage;
|
||||
build.imageName = config.build.image.imageName;
|
||||
build.imageTag =
|
||||
if config.build.image.imageTag != ""
|
||||
then config.build.image.imageTag
|
||||
else lib.head (lib.strings.splitString "-" (baseNameOf config.build.image.outPath));
|
||||
|
||||
service.image = lib.mkDefault "${config.build.imageName}:${config.build.imageTag}";
|
||||
image.rawConfig.Cmd = config.image.command;
|
||||
|
||||
image.nixBuild = lib.mkDefault (priorityIsDefault options.service.image);
|
||||
};
|
||||
}
|
||||
|
|
|
@ -39,7 +39,7 @@ in
|
|||
service.tmpfs = [
|
||||
"/run" # noexec is fine because exes should be symlinked from elsewhere anyway
|
||||
"/run/wrappers" # noexec breaks this intentionally
|
||||
] ++ lib.optional (config.nixos.evaluatedConfig.boot.tmp.useTmpfs) "/tmp:exec,mode=777";
|
||||
] ++ lib.optional (config.nixos.evaluatedConfig.boot.tmpOnTmpfs) "/tmp:exec,mode=777";
|
||||
|
||||
service.stop_signal = "SIGRTMIN+3";
|
||||
service.tty = true;
|
||||
|
|
|
@ -29,9 +29,17 @@ in
|
|||
enable = true;
|
||||
dockerSocket.enable = true;
|
||||
};
|
||||
|
||||
|
||||
# no caches, because no internet
|
||||
nix.settings.substituters = lib.mkForce [];
|
||||
nix.binaryCaches = lib.mkForce [];
|
||||
|
||||
# FIXME: Sandbox seems broken with current version of NixOS test
|
||||
# w/ writable store. Error:
|
||||
# machine# error: linking '/nix/store/7r8z2zvhwda85pgpdn5hzzz6hs1njklc-stdenv-linux.drv.chroot/nix/store/6v3y7s4q4wd16hsw393gjpxvcf9159bv-patch-shebangs.sh' to '/nix/store/6v3y7s4q4wd16hsw393gjpxvcf9159bv-patch-shebangs.sh': Operation not permitted
|
||||
#
|
||||
# There should be no reason why arion can't run without
|
||||
# sandboxing, so please re-enable.
|
||||
nix.useSandbox = false;
|
||||
|
||||
virtualisation.writableStore = true;
|
||||
# Switch to virtualisation.additionalPaths when dropping all NixOS <= 21.05.
|
||||
|
@ -45,7 +53,7 @@ in
|
|||
pkgs.stdenv
|
||||
];
|
||||
|
||||
virtualisation.memorySize = 2048;
|
||||
virtualisation.memorySize = 1024;
|
||||
virtualisation.diskSize = 8000;
|
||||
};
|
||||
testScript = ''
|
||||
|
|
|
@ -12,11 +12,10 @@
|
|||
virtualisation.arion.backend = "docker";
|
||||
};
|
||||
|
||||
# Currently broken; kafka can't reach zookeeper
|
||||
# nixosModuleWithPodman =
|
||||
# import ./nixos-virtualization-arion-test/test.nix final {
|
||||
# virtualisation.arion.backend = "podman-socket";
|
||||
# };
|
||||
nixosModuleWithPodman =
|
||||
import ./nixos-virtualization-arion-test/test.nix final {
|
||||
virtualisation.arion.backend = "podman-socket";
|
||||
};
|
||||
|
||||
testWithPodman =
|
||||
nixosTest (import ./arion-test { usePodman = true; pkgs = final; });
|
||||
|
|
|
@ -4,7 +4,7 @@ pkgs.nixosTest {
|
|||
name = "test-basic-arion-kafka";
|
||||
nodes = {
|
||||
machine = { ... }: {
|
||||
virtualisation.memorySize = 4096;
|
||||
virtualisation.memorySize = 3000;
|
||||
virtualisation.diskSize = 10000;
|
||||
imports = [
|
||||
../../nixos-module.nix
|
||||
|
|
9
update-options
Executable file
9
update-options
Executable file
|
@ -0,0 +1,9 @@
|
|||
#!/usr/bin/env nix-shell
|
||||
#!nix-shell -i bash -p jq
|
||||
|
||||
set -eu -o pipefail
|
||||
|
||||
cd "$(dirname ${BASH_SOURCE[0]})"
|
||||
|
||||
doc_options="$(nix build .#doc-options --json | jq -r .[].outputs.out)"
|
||||
cat "$doc_options" >docs/modules/ROOT/partials/NixOSOptions.adoc
|
Loading…
Add table
Reference in a new issue