Compare commits
No commits in common. "main" and "remove-traces" have entirely different histories.
main
...
remove-tra
55 changed files with 1997 additions and 678 deletions
.gitignoreCHANGELOG.mdarion-compose.cabalbors.tomldefault.nixflake.lockflake.nix
docs
examples
full-nixos
minimal
nixos-unit
traefik
nix
nixos-module.nixrun-arion-via-nixshell.nixsrc
haskell
lib/Arion
test
testdata/Arion/NixSpec
nix
tests
update-options
2
.gitignore
vendored
2
.gitignore
vendored
|
@ -5,5 +5,3 @@ dist/
|
||||||
dist-newstyle/
|
dist-newstyle/
|
||||||
cabal.project.local
|
cabal.project.local
|
||||||
|
|
||||||
*.swp
|
|
||||||
|
|
||||||
|
|
28
CHANGELOG.md
28
CHANGELOG.md
|
@ -1,40 +1,16 @@
|
||||||
# Revision history for Arion
|
# Revision history for Arion
|
||||||
|
|
||||||
## 0.2.1.0 -- 2023-07-26
|
## Next
|
||||||
|
|
||||||
### 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
|
|
||||||
|
|
||||||
* The `project.name` option is now mandatory for projects that aren't deployed with the NixOS module.
|
|
||||||
|
|
||||||
* The NixOS module now sets the default network name to the project name (commonly referred to as `<name>` in the option path).
|
|
||||||
If this is not desired, for instance if you need the projects to be on the same network, set `networks.default.name` in each of them.
|
|
||||||
|
|
||||||
* The NixOS module now sets the default project name. You can still set your own value with the `project.name` option.
|
|
||||||
If you did not set one, docker compose heuristically determined the name to be `store`, so you may want to set `project.name = "store"` or prepare to rename the network manually.
|
|
||||||
|
|
||||||
### Removed
|
### Removed
|
||||||
|
|
||||||
- NixOS 20.09 support. Its docker-compose does not support the
|
- NixOS 20.09 support. Its docker-compose does not support the
|
||||||
`networks.<name>.name` option, which is important in later versions.
|
`networks.<name>.name` option, which is important in later versions.
|
||||||
A newer, bundled docker compose may work there, but for now the decision
|
|
||||||
is to drop this legacy version.
|
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
|
||||||
* Healthcheck-based dependencies in `service.depends_on`.
|
* Healthcheck-based dependencies in `service.depends_on`.
|
||||||
|
* The `project.name` option is now mandatory.
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
cabal-version: 2.4
|
cabal-version: 2.4
|
||||||
|
|
||||||
name: arion-compose
|
name: arion-compose
|
||||||
version: 0.2.1.0
|
version: 0.1.3.0
|
||||||
synopsis: Run docker-compose with help from Nix/NixOS
|
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.
|
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
|
homepage: https://github.com/hercules-ci/arion#readme
|
||||||
|
@ -30,8 +30,8 @@ source-repository head
|
||||||
location: https://github.com/hercules-ci/arion
|
location: https://github.com/hercules-ci/arion
|
||||||
|
|
||||||
common common
|
common common
|
||||||
build-depends: base >=4.12.0.0 && <4.99
|
build-depends: base >=4.12.0.0 && <4.17
|
||||||
, aeson >=2
|
, aeson
|
||||||
, aeson-pretty
|
, aeson-pretty
|
||||||
, async
|
, async
|
||||||
, bytestring
|
, bytestring
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
status = [
|
status = [
|
||||||
"ci/hercules/onPush/default",
|
"ci/hercules/derivations",
|
||||||
"ci/hercules/evaluation",
|
"ci/hercules/evaluation",
|
||||||
]
|
]
|
||||||
delete_merged_branches = true
|
delete_merged_branches = true
|
||||||
|
|
|
@ -1,11 +1,6 @@
|
||||||
let flake = import ./nix/compat.nix;
|
{ pkgs ? import ./nix {}
|
||||||
in
|
|
||||||
{ pkgs ? import flake.inputs.nixpkgs { }
|
|
||||||
, haskellPackages ? pkgs.haskellPackages
|
, haskellPackages ? pkgs.haskellPackages
|
||||||
}:
|
}:
|
||||||
let
|
|
||||||
pkgsWithArion = pkgs.extend flake.overlays.default;
|
|
||||||
in
|
|
||||||
{
|
{
|
||||||
inherit (pkgsWithArion) arion;
|
arion = import ./nix/arion.nix { inherit pkgs haskellPackages; };
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,4 +4,3 @@ version: 'master'
|
||||||
nav:
|
nav:
|
||||||
- modules/ROOT/nav.adoc
|
- modules/ROOT/nav.adoc
|
||||||
- modules/reference/nav.adoc
|
- modules/reference/nav.adoc
|
||||||
nix: true
|
|
||||||
|
|
|
@ -1,31 +0,0 @@
|
||||||
{
|
|
||||||
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;
|
|
||||||
|
|
||||||
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
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
}
|
|
|
@ -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,23 +45,20 @@ NOTE: This deployment method does NOT use an `arion-pkgs.nix` file, but reuses
|
||||||
# Pick one of:
|
# Pick one of:
|
||||||
# - niv
|
# - niv
|
||||||
((import ./nix/sources.nix).arion + "/nixos-module.nix")
|
((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
|
arion.nixosModules.arion
|
||||||
# - or other: copy commit hash of arion and replace HASH in:
|
# - other
|
||||||
(builtins.fetchTarball "https://github.com/hercules-ci/arion/archive/HASH.tar.gz") + "/nixos-module.nix")
|
arionPath + "/nixos-module.nix")
|
||||||
];
|
];
|
||||||
|
|
||||||
virtualisation.arion = {
|
virtualisation.arion = {
|
||||||
backend = "podman-socket"; # or "docker"
|
backend = "podman-socket"; # or "docker"
|
||||||
projects.example = {
|
projects.example.settings = {
|
||||||
serviceName = "example"; # optional systemd service name, defaults to arion-example in this case
|
|
||||||
settings = {
|
|
||||||
# Specify you project here, or import it from a file.
|
# Specify you project here, or import it from a file.
|
||||||
# NOTE: This does NOT use ./arion-pkgs.nix, but defaults to NixOS' pkgs.
|
# NOTE: This does NOT use ./arion-pkgs.nix, but defaults to NixOS' pkgs.
|
||||||
imports = [ ./arion-compose.nix ];
|
imports = [ ./arion-compose.nix ];
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
|
@ -40,7 +40,6 @@ Arion allows to compose containers with different granularity:
|
||||||
* <<Docker image from DockerHub>>
|
* <<Docker image from DockerHub>>
|
||||||
|
|
||||||
Full NixOS is supported on
|
Full NixOS is supported on
|
||||||
|
|
||||||
* docker-compose + podman with docker socket (NixOS >= 21.05)
|
* docker-compose + podman with docker socket (NixOS >= 21.05)
|
||||||
* docker-compose + docker, before cgroupsv2 (NixOS < 21.05)
|
* docker-compose + docker, before cgroupsv2 (NixOS < 21.05)
|
||||||
|
|
||||||
|
@ -113,16 +112,14 @@ Describe containers using NixOS-style modules. There are a few options:
|
||||||
|
|
||||||
==== Minimal: Plain command using nixpkgs
|
==== Minimal: Plain command using nixpkgs
|
||||||
|
|
||||||
`examples/minimal/arion-compose.nix`
|
`examples/minimal/arion-compose.nix`:
|
||||||
[,nix]
|
|
||||||
----
|
```nix
|
||||||
{ pkgs, ... }:
|
{ pkgs, ... }:
|
||||||
{
|
{
|
||||||
project.name = "webapp";
|
config.services = {
|
||||||
services = {
|
|
||||||
|
|
||||||
webserver = {
|
webserver = {
|
||||||
image.enableRecommendedContents = true;
|
|
||||||
service.useHostStore = true;
|
service.useHostStore = true;
|
||||||
service.command = [ "sh" "-c" ''
|
service.command = [ "sh" "-c" ''
|
||||||
cd "$$WEB_ROOT"
|
cd "$$WEB_ROOT"
|
||||||
|
@ -132,36 +129,58 @@ Describe containers using NixOS-style modules. There are a few options:
|
||||||
"8000:8000" # host:container
|
"8000:8000" # host:container
|
||||||
];
|
];
|
||||||
service.environment.WEB_ROOT = "${pkgs.nix.doc}/share/doc/nix/manual";
|
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 = { config, pkgs, ... }: {
|
||||||
services.webserver = { pkgs, lib, ... }: {
|
|
||||||
nixos.useSystemd = true;
|
nixos.configuration = {config, pkgs, ...}: {
|
||||||
nixos.configuration.boot.tmp.useTmpfs = true;
|
boot.isContainer = true;
|
||||||
nixos.configuration.services.nginx.enable = true;
|
services.nginx.enable = true;
|
||||||
nixos.configuration.services.nginx.virtualHosts.localhost.root = "${pkgs.nix.doc}/share/doc/nix/manual";
|
services.nginx.virtualHosts.localhost.root = "${pkgs.nix.doc}/share/doc/nix/manual";
|
||||||
nixos.configuration.services.nscd.enable = false;
|
system.build.run-nginx = pkgs.writeScript "run-nginx" ''
|
||||||
nixos.configuration.system.nssModules = lib.mkForce [];
|
#!${pkgs.bash}/bin/bash
|
||||||
nixos.configuration.systemd.services.nginx.serviceConfig.AmbientCapabilities =
|
PATH='${config.systemd.services.nginx.environment.PATH}'
|
||||||
lib.mkForce [ "CAP_NET_BIND_SERVICE" ];
|
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.useHostStore = true;
|
||||||
service.ports = [
|
service.ports = [
|
||||||
"8000:80" # host:container
|
"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
|
==== Docker image from DockerHub
|
||||||
|
|
||||||
|
@ -175,11 +194,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
|
=== Run
|
||||||
|
|
||||||
Start containers and watch their logs:
|
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";
|
project.name = "full-nixos";
|
||||||
services.webserver = { pkgs, lib, ... }: {
|
services.webserver = { pkgs, lib, ... }: {
|
||||||
nixos.useSystemd = true;
|
nixos.useSystemd = true;
|
||||||
nixos.configuration.boot.tmp.useTmpfs = true;
|
nixos.configuration.boot.tmpOnTmpfs = true;
|
||||||
nixos.configuration.networking.useDHCP = false;
|
|
||||||
nixos.configuration.services.nginx.enable = true;
|
nixos.configuration.services.nginx.enable = true;
|
||||||
nixos.configuration.services.nginx.virtualHosts.localhost.root = "${pkgs.nix.doc}/share/doc/nix/manual";
|
nixos.configuration.services.nginx.virtualHosts.localhost.root = "${pkgs.nix.doc}/share/doc/nix/manual";
|
||||||
nixos.configuration.services.nscd.enable = false;
|
nixos.configuration.services.nscd.enable = false;
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
{ pkgs, ... }:
|
{ pkgs, ... }:
|
||||||
{
|
{
|
||||||
project.name = "webapp";
|
config.project.name = "webapp";
|
||||||
services = {
|
config.services = {
|
||||||
|
|
||||||
webserver = {
|
webserver = {
|
||||||
image.enableRecommendedContents = true;
|
image.enableRecommendedContents = true;
|
||||||
|
|
|
@ -36,8 +36,8 @@
|
||||||
echo nginx:x:${toString config.users.groups.nginx.gid}:nginx >>/etc/group
|
echo nginx:x:${toString config.users.groups.nginx.gid}:nginx >>/etc/group
|
||||||
echo 'nobody:x:65534:65534:Unprivileged account do not use:/var/empty:/run/current-system/sw/bin/nologin' >>/etc/passwd
|
echo 'nobody:x:65534:65534:Unprivileged account do not use:/var/empty:/run/current-system/sw/bin/nologin' >>/etc/passwd
|
||||||
echo 'nogroup:x:65534:' >>/etc/group
|
echo 'nogroup:x:65534:' >>/etc/group
|
||||||
mkdir -p /var/log/nginx /run/nginx/ /var/cache/nginx /var/lib/nginx/{,logs,proxy_temp,client_body_temp,fastcgi_temp,scgi_temp,uwsgi_temp} /tmp/nginx_client_body
|
mkdir -p /var/log/nginx /run/nginx/ /var/cache/nginx /var/lib/nginx/{,logs,proxy_temp,client_body_temp,fastcgi_temp,scgi_temp,uwsgi_temp}
|
||||||
chown nginx /var/log/nginx /run/nginx/ /var/cache/nginx /var/lib/nginx/{,logs,proxy_temp,client_body_temp,fastcgi_temp,scgi_temp,uwsgi_temp} /tmp/nginx_client_body
|
chown nginx /var/log/nginx /run/nginx/ /var/cache/nginx /var/lib/nginx/{,logs,proxy_temp,client_body_temp,fastcgi_temp,scgi_temp,uwsgi_temp}
|
||||||
${config.systemd.services.nginx.runner}
|
${config.systemd.services.nginx.runner}
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
|
|
|
@ -10,17 +10,6 @@
|
||||||
*/
|
*/
|
||||||
{ lib, pkgs, ... }: {
|
{ lib, pkgs, ... }: {
|
||||||
config.project.name = "traefik";
|
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 = {
|
config.services = {
|
||||||
traefik = {
|
traefik = {
|
||||||
image.command = [
|
image.command = [
|
||||||
|
@ -35,7 +24,6 @@
|
||||||
stop_signal = "SIGINT";
|
stop_signal = "SIGINT";
|
||||||
ports = [ "80:80" "8080:8080" ];
|
ports = [ "80:80" "8080:8080" ];
|
||||||
volumes = [ "/var/run/docker.sock:/var/run/docker.sock:ro" ];
|
volumes = [ "/var/run/docker.sock:/var/run/docker.sock:ro" ];
|
||||||
networks = [ "traefik-custom" ];
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -46,17 +34,14 @@
|
||||||
${pkgs.python3}/bin/python -m http.server
|
${pkgs.python3}/bin/python -m http.server
|
||||||
''}"];
|
''}"];
|
||||||
service.container_name = "simple-service";
|
service.container_name = "simple-service";
|
||||||
|
service.ports = [
|
||||||
|
"8000:8000" # host:container
|
||||||
|
];
|
||||||
service.stop_signal = "SIGINT";
|
service.stop_signal = "SIGINT";
|
||||||
service.labels = {
|
service.labels = {
|
||||||
"traefik.enable" = "true";
|
"traefik.enable" = "true";
|
||||||
"traefik.http.routers.nix-docs.rule" = "Host(`nix-docs.localhost`)";
|
"traefik.http.routers.nix-docs.rule" = "Host(`nix-docs.localhost`)";
|
||||||
"traefik.http.routers.nix-docs.entrypoints" = "web";
|
"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";
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
92
flake.lock
generated
92
flake.lock
generated
|
@ -1,103 +1,21 @@
|
||||||
{
|
{
|
||||||
"nodes": {
|
"nodes": {
|
||||||
"flake-parts": {
|
|
||||||
"inputs": {
|
|
||||||
"nixpkgs-lib": [
|
|
||||||
"nixpkgs"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"locked": {
|
|
||||||
"lastModified": 1722555600,
|
|
||||||
"narHash": "sha256-XOQkdLafnb/p9ij77byFQjDf5m5QYl9b2REiVClC+x4=",
|
|
||||||
"owner": "hercules-ci",
|
|
||||||
"repo": "flake-parts",
|
|
||||||
"rev": "8471fe90ad337a8074e957b69ca4d0089218391d",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"owner": "hercules-ci",
|
|
||||||
"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=",
|
|
||||||
"owner": "srid",
|
|
||||||
"repo": "haskell-flake",
|
|
||||||
"rev": "c2cafce9d57bfca41794dc3b99c593155006c71e",
|
|
||||||
"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": {
|
"nixpkgs": {
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1722630782,
|
"lastModified": 1601906239,
|
||||||
"narHash": "sha256-hMyG9/WlUi0Ho9VkRrrez7SeNlDzLxalm9FwY7n/Noo=",
|
"narHash": "sha256-P1jBYbYeFswig/0FKbgh+BpVhh9iurD3m0T2ae4gdx8=",
|
||||||
"owner": "NixOS",
|
"owner": "NixOS",
|
||||||
"repo": "nixpkgs",
|
"repo": "nixpkgs",
|
||||||
"rev": "d04953086551086b44b6f3c6b7eeb26294f207da",
|
"rev": "c2bb4af48d26ed091e5674394bacbf8d488c7939",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
"owner": "NixOS",
|
"id": "nixpkgs",
|
||||||
"ref": "nixos-unstable",
|
"type": "indirect"
|
||||||
"repo": "nixpkgs",
|
|
||||||
"type": "github"
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"root": {
|
"root": {
|
||||||
"inputs": {
|
"inputs": {
|
||||||
"flake-parts": "flake-parts",
|
|
||||||
"haskell-flake": "haskell-flake",
|
|
||||||
"hercules-ci-effects": "hercules-ci-effects",
|
|
||||||
"nixpkgs": "nixpkgs"
|
"nixpkgs": "nixpkgs"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
108
flake.nix
108
flake.nix
|
@ -1,90 +1,35 @@
|
||||||
{
|
{
|
||||||
description = "Arion - use Docker Compose via Nix";
|
description = "Arion - use Docker Compose via Nix";
|
||||||
|
|
||||||
inputs = {
|
outputs = { self, nixpkgs }:
|
||||||
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
|
let
|
||||||
haskell-flake.url = "github:srid/haskell-flake/0.1.0";
|
lib = import (nixpkgs + "/lib");
|
||||||
flake-parts.url = "github:hercules-ci/flake-parts";
|
systems = [
|
||||||
flake-parts.inputs.nixpkgs-lib.follows = "nixpkgs";
|
"aarch64-linux"
|
||||||
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, ... }: {
|
|
||||||
imports = [
|
|
||||||
inputs.haskell-flake.flakeModule
|
|
||||||
inputs.hercules-ci-effects.flakeModule
|
|
||||||
inputs.flake-parts.flakeModules.easyOverlay
|
|
||||||
./docs/flake-module.nix
|
|
||||||
./tests/flake-module.nix
|
|
||||||
];
|
|
||||||
systems = inputs.nixpkgs.lib.systems.flakeExposed;
|
|
||||||
perSystem = { config, self', inputs', pkgs, system, final, ... }:
|
|
||||||
let h = pkgs.haskell.lib.compose; in
|
|
||||||
{
|
|
||||||
overlayAttrs = {
|
|
||||||
inherit (config.packages) arion;
|
|
||||||
arionTestingFlags = {
|
|
||||||
dockerSupportsSystemd = false;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
packages.default = config.packages.arion;
|
|
||||||
packages.overlay-test = final.arion;
|
|
||||||
packages.arion = import ./nix/arion.nix { inherit pkgs; };
|
|
||||||
haskellProjects.haskell-package = {
|
|
||||||
# not autodetected: https://github.com/srid/haskell-flake/issues/49
|
|
||||||
packages.arion-compose.root = ./.;
|
|
||||||
|
|
||||||
overrides =
|
|
||||||
self: super: {
|
|
||||||
arion-compose =
|
|
||||||
lib.pipe super.arion-compose [
|
|
||||||
(h.addBuildTools [ pkgs.nix ])
|
|
||||||
(h.overrideCabal (o: {
|
|
||||||
src = pkgs.lib.sourceByRegex ./. [
|
|
||||||
".*[.]cabal"
|
|
||||||
"LICENSE"
|
|
||||||
"src/?.*"
|
|
||||||
"README.asciidoc"
|
|
||||||
"CHANGELOG.md"
|
|
||||||
];
|
|
||||||
preCheck = ''
|
|
||||||
export NIX_LOG_DIR=$TMPDIR
|
|
||||||
export NIX_STATE_DIR=$TMPDIR
|
|
||||||
export NIX_PATH=nixpkgs=${pkgs.path}
|
|
||||||
'';
|
|
||||||
}))
|
|
||||||
];
|
|
||||||
};
|
|
||||||
};
|
|
||||||
devShells.default = config.devShells.haskell-package.overrideAttrs (o: {
|
|
||||||
nativeBuildInputs = o.nativeBuildInputs or [ ] ++ [
|
|
||||||
pkgs.docker-compose
|
|
||||||
pkgs.nixpkgs-fmt
|
|
||||||
config.haskellProjects.haskell-package.haskellPackages.releaser
|
|
||||||
];
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
hercules-ci.flake-update = {
|
|
||||||
enable = true;
|
|
||||||
autoMergeMethod = "merge";
|
|
||||||
when = {
|
|
||||||
hour = [ 2 ];
|
|
||||||
dayOfMonth = [ 5 ];
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
herculesCI.ciSystems = [
|
|
||||||
# "aarch64-darwin"
|
|
||||||
# "aarch64-linux"
|
|
||||||
"x86_64-darwin"
|
"x86_64-darwin"
|
||||||
"x86_64-linux"
|
"x86_64-linux"
|
||||||
];
|
];
|
||||||
|
arionFromPkgs = pkgs: import ./nix/arion.nix { inherit pkgs; };
|
||||||
|
in {
|
||||||
|
|
||||||
flake = {
|
# The overlay is currently the recommended way to integrate arion,
|
||||||
debug = { inherit inputs config lib; };
|
# because its arion attribute behaves just like Nixpkgs.
|
||||||
|
overlay = final: prev: {
|
||||||
|
arion = arionFromPkgs final;
|
||||||
|
};
|
||||||
|
|
||||||
|
packages = lib.genAttrs systems (system:
|
||||||
|
let
|
||||||
|
pkgs = nixpkgs.legacyPackages.${system};
|
||||||
|
in
|
||||||
|
{
|
||||||
|
arion = arionFromPkgs pkgs;
|
||||||
|
});
|
||||||
|
|
||||||
|
# Does not include the eval and build functions like you may expect from Nixpkgs.
|
||||||
|
defaultPackage = lib.genAttrs systems (system:
|
||||||
|
self.packages.${system}.arion
|
||||||
|
);
|
||||||
|
|
||||||
lib = {
|
lib = {
|
||||||
eval = import ./src/nix/eval-composition.nix;
|
eval = import ./src/nix/eval-composition.nix;
|
||||||
|
@ -92,7 +37,8 @@
|
||||||
let composition = self.lib.eval args;
|
let composition = self.lib.eval args;
|
||||||
in composition.config.out.dockerComposeYaml;
|
in composition.config.out.dockerComposeYaml;
|
||||||
};
|
};
|
||||||
|
|
||||||
nixosModules.arion = ./nixos-module.nix;
|
nixosModules.arion = ./nixos-module.nix;
|
||||||
|
|
||||||
};
|
};
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
46
nix/ci.nix
Normal file
46
nix/ci.nix
Normal file
|
@ -0,0 +1,46 @@
|
||||||
|
let
|
||||||
|
sources = import ./sources.nix;
|
||||||
|
lib = import (sources."nixos-unstable" + "/lib");
|
||||||
|
inherit (import (sources."project.nix" + "/lib/dimension.nix") { inherit lib; }) dimension;
|
||||||
|
in
|
||||||
|
|
||||||
|
dimension "Nixpkgs version" {
|
||||||
|
"nixos-22_05" = {
|
||||||
|
nixpkgsSource = "nixos-22.05";
|
||||||
|
enableDoc = true;
|
||||||
|
};
|
||||||
|
"nixos-unstable" = {
|
||||||
|
nixpkgsSource = "nixos-unstable";
|
||||||
|
isReferenceNixpkgs = true; # match ./default.nix
|
||||||
|
enableDoc = true;
|
||||||
|
};
|
||||||
|
} (
|
||||||
|
_name: { nixpkgsSource, isReferenceNixpkgs ? false, enableDoc ? true,
|
||||||
|
dockerSupportsSystemd ? false, nixosHasPodmanDockerSocket ? true }:
|
||||||
|
|
||||||
|
|
||||||
|
dimension "System" {
|
||||||
|
"x86_64-linux" = { isReferenceTarget = isReferenceNixpkgs; };
|
||||||
|
"x86_64-darwin" = { enableNixOSTests = false; };
|
||||||
|
} (
|
||||||
|
system: { isReferenceTarget ? false, enableNixOSTests ? true }:
|
||||||
|
let
|
||||||
|
pkgs = import ./. {
|
||||||
|
inherit system dockerSupportsSystemd nixosHasPodmanDockerSocket;
|
||||||
|
nixpkgsSrc = sources.${nixpkgsSource};
|
||||||
|
};
|
||||||
|
in
|
||||||
|
{
|
||||||
|
inherit (pkgs) arion;
|
||||||
|
} // lib.optionalAttrs enableNixOSTests {
|
||||||
|
inherit (pkgs) tests;
|
||||||
|
} // lib.optionalAttrs enableDoc {
|
||||||
|
inherit (pkgs)
|
||||||
|
# FIXME: nixpkgs antora packaging is broken
|
||||||
|
# doc
|
||||||
|
doc-options doc-options-check;
|
||||||
|
} // lib.optionalAttrs isReferenceTarget {
|
||||||
|
inherit (pkgs.arion-project.haskellPkgs) arion-compose-checked;
|
||||||
|
}
|
||||||
|
)
|
||||||
|
)
|
|
@ -1,10 +0,0 @@
|
||||||
(import
|
|
||||||
(
|
|
||||||
let lock = builtins.fromJSON (builtins.readFile ./flake.lock); in
|
|
||||||
fetchTarball {
|
|
||||||
url = "https://github.com/edolstra/flake-compat/archive/009399224d5e398d03b22badca40a37ac85412a1.tar.gz";
|
|
||||||
sha256 = "sha256:0xcr9fibnapa12ywzcnlf54wrmbqqb96fmmv8043zhsycws7bpqy";
|
|
||||||
}
|
|
||||||
)
|
|
||||||
{ src = ../.; }
|
|
||||||
).defaultNix
|
|
23
nix/default.nix
Normal file
23
nix/default.nix
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
{ sources ? import ./sources.nix
|
||||||
|
, nixpkgsName ? "nixos-unstable" # match ./ci.nix isReferenceNixpkgs
|
||||||
|
, nixpkgsSrc ? sources.${nixpkgsName}
|
||||||
|
, system ? builtins.currentSystem
|
||||||
|
, dockerSupportsSystemd ? false
|
||||||
|
, nixosHasPodmanDockerSocket ? true
|
||||||
|
, ...
|
||||||
|
}:
|
||||||
|
|
||||||
|
import nixpkgsSrc ({
|
||||||
|
# Makes the config pure as well. See <nixpkgs>/top-level/impure.nix:
|
||||||
|
config = {
|
||||||
|
};
|
||||||
|
overlays = [
|
||||||
|
(_: _: {
|
||||||
|
arionTestingFlags = {
|
||||||
|
inherit dockerSupportsSystemd nixosHasPodmanDockerSocket;
|
||||||
|
};
|
||||||
|
})
|
||||||
|
(import ./overlay.nix)
|
||||||
|
];
|
||||||
|
inherit system;
|
||||||
|
})
|
16
nix/haskell-overlay.nix
Normal file
16
nix/haskell-overlay.nix
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
self: super: hself: hsuper:
|
||||||
|
{
|
||||||
|
arion-compose = import ./haskell-arion-compose.nix { pkgs = self; haskellPackages = hself; };
|
||||||
|
arion-compose-checked =
|
||||||
|
let pkg = /* super.haskell.lib.buildStrictly currently broken in nixos-unstable */ hself.arion-compose;
|
||||||
|
checked = super.haskell.lib.overrideCabal pkg (o: {
|
||||||
|
postConfigure = ''${o.postConfigure or ""}
|
||||||
|
if ! ${hsuper.cabal-install}/bin/cabal check;
|
||||||
|
then
|
||||||
|
echo 1>&2 ERROR: cabal file is invalid. Above warnings were errors.
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
'';
|
||||||
|
});
|
||||||
|
in checked;
|
||||||
|
}
|
60
nix/overlay.nix
Normal file
60
nix/overlay.nix
Normal file
|
@ -0,0 +1,60 @@
|
||||||
|
self: super:
|
||||||
|
let
|
||||||
|
inherit (self.arion-project) haskellPkgs;
|
||||||
|
inherit (super) lib;
|
||||||
|
|
||||||
|
sources = import ./sources.nix;
|
||||||
|
|
||||||
|
fakeRepo = src: super.runCommand "source" { inherit src; nativeBuildInputs = [super.git]; } ''
|
||||||
|
cp -r --no-preserve=mode $src $out
|
||||||
|
git init
|
||||||
|
cp -r .git $out
|
||||||
|
'';
|
||||||
|
|
||||||
|
in
|
||||||
|
{
|
||||||
|
|
||||||
|
inherit (import ./.. { pkgs = self; }) arion;
|
||||||
|
tests = super.callPackage ../tests {};
|
||||||
|
|
||||||
|
doc-options = import ../docs/options.nix {};
|
||||||
|
doc-options-check = self.runCommand "doc-options-check" {} ''
|
||||||
|
if diff --color -u ${../docs/modules/ROOT/partials/NixOSOptions.adoc} ${self.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
|
||||||
|
'';
|
||||||
|
doc = self.stdenv.mkDerivation {
|
||||||
|
name = "arion-documentation";
|
||||||
|
nativeBuildInputs = [super.antora];
|
||||||
|
src = fakeRepo ../.;
|
||||||
|
HOME = ".";
|
||||||
|
buildPhase = "antora antora-playbook";
|
||||||
|
installPhase = ''
|
||||||
|
mkdir $out
|
||||||
|
mv public/* $out/
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
arion-project = super.recurseIntoAttrs {
|
||||||
|
haskellPkgs = super.haskellPackages.extend (import ./haskell-overlay.nix self super);
|
||||||
|
shell = haskellPkgs.shellFor {
|
||||||
|
packages = p: [p.arion-compose];
|
||||||
|
nativeBuildInputs = [
|
||||||
|
haskellPkgs.cabal-install
|
||||||
|
haskellPkgs.ghcid
|
||||||
|
haskellPkgs.haskell-language-server
|
||||||
|
super.docker-compose
|
||||||
|
self.niv
|
||||||
|
self.nixpkgs-fmt
|
||||||
|
self.releaser
|
||||||
|
];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
inherit (import (sources.niv) {}) niv;
|
||||||
|
releaser = self.haskellPackages.callCabal2nix "releaser" sources.releaser {};
|
||||||
|
}
|
63
nix/sources.json
Normal file
63
nix/sources.json
Normal file
|
@ -0,0 +1,63 @@
|
||||||
|
{
|
||||||
|
"niv": {
|
||||||
|
"branch": "master",
|
||||||
|
"description": "Easy dependency management for Nix projects",
|
||||||
|
"homepage": "https://github.com/nmattia/niv",
|
||||||
|
"owner": "nmattia",
|
||||||
|
"repo": "niv",
|
||||||
|
"rev": "fad2a6cbfb2e7cdebb7cb0ad2f5cc91e2c9bc06b",
|
||||||
|
"sha256": "0mghc1j0rd15spdjx81bayjqr0khc062cs25y5dcfzlxk4ynyc6m",
|
||||||
|
"type": "tarball",
|
||||||
|
"url": "https://github.com/nmattia/niv/archive/fad2a6cbfb2e7cdebb7cb0ad2f5cc91e2c9bc06b.tar.gz",
|
||||||
|
"url_template": "https://github.com/<owner>/<repo>/archive/<rev>.tar.gz"
|
||||||
|
},
|
||||||
|
"nixos-22.05": {
|
||||||
|
"branch": "nixos-22.05",
|
||||||
|
"description": "Nix Packages collection",
|
||||||
|
"homepage": null,
|
||||||
|
"owner": "NixOS",
|
||||||
|
"repo": "nixpkgs",
|
||||||
|
"rev": "a634c8f6c1fbf9b9730e01764999666f3436f10a",
|
||||||
|
"sha256": "1d40v43x972li5fg7jadxkj341li41mf2cl6vv7xi6j80rkq45q4",
|
||||||
|
"type": "tarball",
|
||||||
|
"url": "https://github.com/NixOS/nixpkgs/archive/a634c8f6c1fbf9b9730e01764999666f3436f10a.tar.gz",
|
||||||
|
"url_template": "https://github.com/<owner>/<repo>/archive/<rev>.tar.gz"
|
||||||
|
},
|
||||||
|
"nixos-unstable": {
|
||||||
|
"branch": "lib-modules-allow-disable-_modules.args-docs-internal",
|
||||||
|
"description": "A read-only mirror of NixOS/nixpkgs tracking the released channels. Send issues and PRs to",
|
||||||
|
"homepage": "https://github.com/NixOS/nixpkgs",
|
||||||
|
"owner": "hercules-ci",
|
||||||
|
"repo": "nixpkgs",
|
||||||
|
"rev": "14aa201b658f43546b00153bb2ada7206ba8dd26",
|
||||||
|
"sha256": "0xn43gdn3rfys1d8ni3y6x7vxyc263qsbhfsjwc5x7pcd3dfrcjw",
|
||||||
|
"type": "tarball",
|
||||||
|
"url": "https://github.com/hercules-ci/nixpkgs/archive/14aa201b658f43546b00153bb2ada7206ba8dd26.tar.gz",
|
||||||
|
"url_template": "https://github.com/<owner>/<repo>/archive/<rev>.tar.gz",
|
||||||
|
"version": ""
|
||||||
|
},
|
||||||
|
"project.nix": {
|
||||||
|
"branch": "master",
|
||||||
|
"description": "A configuration manager for your projects",
|
||||||
|
"homepage": null,
|
||||||
|
"owner": "hercules-ci",
|
||||||
|
"repo": "project.nix",
|
||||||
|
"rev": "2e598501e7fda6993d2a1a281aa296b26d01e10c",
|
||||||
|
"sha256": "1rkzpzxpg69px6qwchdlg4xf5irv0snrzk2l6vrs9rsx48gqax9j",
|
||||||
|
"type": "tarball",
|
||||||
|
"url": "https://github.com/hercules-ci/project.nix/archive/2e598501e7fda6993d2a1a281aa296b26d01e10c.tar.gz",
|
||||||
|
"url_template": "https://github.com/<owner>/<repo>/archive/<rev>.tar.gz"
|
||||||
|
},
|
||||||
|
"releaser": {
|
||||||
|
"branch": "master",
|
||||||
|
"description": "Automation of Haskell package release process.",
|
||||||
|
"homepage": null,
|
||||||
|
"owner": "domenkozar",
|
||||||
|
"repo": "releaser",
|
||||||
|
"rev": "52a2bb0b2ce0bc15d4e7b11d8761a28d82c0c083",
|
||||||
|
"sha256": "178lv0a0qxd8six0rm83j7wjwlsad1hysdrk4mb38fagbb8csagb",
|
||||||
|
"type": "tarball",
|
||||||
|
"url": "https://github.com/domenkozar/releaser/archive/52a2bb0b2ce0bc15d4e7b11d8761a28d82c0c083.tar.gz",
|
||||||
|
"url_template": "https://github.com/<owner>/<repo>/archive/<rev>.tar.gz"
|
||||||
|
}
|
||||||
|
}
|
171
nix/sources.nix
Normal file
171
nix/sources.nix
Normal file
|
@ -0,0 +1,171 @@
|
||||||
|
# This file has been generated by Niv.
|
||||||
|
|
||||||
|
let
|
||||||
|
|
||||||
|
#
|
||||||
|
# The fetchers. fetch_<type> fetches specs of type <type>.
|
||||||
|
#
|
||||||
|
|
||||||
|
fetch_file = pkgs: name: spec:
|
||||||
|
let
|
||||||
|
name' = sanitizeName name + "-src";
|
||||||
|
in
|
||||||
|
if spec.builtin or true then
|
||||||
|
builtins_fetchurl { inherit (spec) url sha256; name = name'; }
|
||||||
|
else
|
||||||
|
pkgs.fetchurl { inherit (spec) url sha256; name = name'; };
|
||||||
|
|
||||||
|
fetch_tarball = pkgs: name: spec:
|
||||||
|
let
|
||||||
|
name' = sanitizeName name + "-src";
|
||||||
|
in
|
||||||
|
if spec.builtin or true then
|
||||||
|
builtins_fetchTarball { name = name'; inherit (spec) url sha256; }
|
||||||
|
else
|
||||||
|
pkgs.fetchzip { name = name'; inherit (spec) url sha256; };
|
||||||
|
|
||||||
|
fetch_git = name: spec:
|
||||||
|
let
|
||||||
|
ref =
|
||||||
|
if spec ? ref then spec.ref else
|
||||||
|
if spec ? branch then "refs/heads/${spec.branch}" else
|
||||||
|
if spec ? tag then "refs/tags/${spec.tag}" else
|
||||||
|
abort "In git source '${name}': Please specify `ref`, `tag` or `branch`!";
|
||||||
|
in
|
||||||
|
builtins.fetchGit { url = spec.repo; inherit (spec) rev; inherit ref; };
|
||||||
|
|
||||||
|
fetch_local = spec: spec.path;
|
||||||
|
|
||||||
|
fetch_builtin-tarball = name: throw
|
||||||
|
''[${name}] The niv type "builtin-tarball" is deprecated. You should instead use `builtin = true`.
|
||||||
|
$ niv modify ${name} -a type=tarball -a builtin=true'';
|
||||||
|
|
||||||
|
fetch_builtin-url = name: throw
|
||||||
|
''[${name}] The niv type "builtin-url" will soon be deprecated. You should instead use `builtin = true`.
|
||||||
|
$ niv modify ${name} -a type=file -a builtin=true'';
|
||||||
|
|
||||||
|
#
|
||||||
|
# Various helpers
|
||||||
|
#
|
||||||
|
|
||||||
|
# https://github.com/NixOS/nixpkgs/pull/83241/files#diff-c6f540a4f3bfa4b0e8b6bafd4cd54e8bR695
|
||||||
|
sanitizeName = name:
|
||||||
|
(
|
||||||
|
concatMapStrings (s: if builtins.isList s then "-" else s)
|
||||||
|
(
|
||||||
|
builtins.split "[^[:alnum:]+._?=-]+"
|
||||||
|
((x: builtins.elemAt (builtins.match "\\.*(.*)" x) 0) name)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
# The set of packages used when specs are fetched using non-builtins.
|
||||||
|
mkPkgs = sources: system:
|
||||||
|
let
|
||||||
|
sourcesNixpkgs =
|
||||||
|
import (builtins_fetchTarball { inherit (sources.nixpkgs) url sha256; }) { inherit system; };
|
||||||
|
hasNixpkgsPath = builtins.any (x: x.prefix == "nixpkgs") builtins.nixPath;
|
||||||
|
hasThisAsNixpkgsPath = <nixpkgs> == ./.;
|
||||||
|
in
|
||||||
|
if builtins.hasAttr "nixpkgs" sources
|
||||||
|
then sourcesNixpkgs
|
||||||
|
else if hasNixpkgsPath && ! hasThisAsNixpkgsPath then
|
||||||
|
import <nixpkgs> {}
|
||||||
|
else
|
||||||
|
abort
|
||||||
|
''
|
||||||
|
Please specify either <nixpkgs> (through -I or NIX_PATH=nixpkgs=...) or
|
||||||
|
add a package called "nixpkgs" to your sources.json.
|
||||||
|
'';
|
||||||
|
|
||||||
|
# The actual fetching function.
|
||||||
|
fetch = pkgs: name: spec:
|
||||||
|
|
||||||
|
if ! builtins.hasAttr "type" spec then
|
||||||
|
abort "ERROR: niv spec ${name} does not have a 'type' attribute"
|
||||||
|
else if spec.type == "file" then fetch_file pkgs name spec
|
||||||
|
else if spec.type == "tarball" then fetch_tarball pkgs name spec
|
||||||
|
else if spec.type == "git" then fetch_git name spec
|
||||||
|
else if spec.type == "local" then fetch_local spec
|
||||||
|
else if spec.type == "builtin-tarball" then fetch_builtin-tarball name
|
||||||
|
else if spec.type == "builtin-url" then fetch_builtin-url name
|
||||||
|
else
|
||||||
|
abort "ERROR: niv spec ${name} has unknown type ${builtins.toJSON spec.type}";
|
||||||
|
|
||||||
|
# If the environment variable NIV_OVERRIDE_${name} is set, then use
|
||||||
|
# the path directly as opposed to the fetched source.
|
||||||
|
replace = name: drv:
|
||||||
|
let
|
||||||
|
saneName = stringAsChars (c: if isNull (builtins.match "[a-zA-Z0-9]" c) then "_" else c) name;
|
||||||
|
ersatz = builtins.getEnv "NIV_OVERRIDE_${saneName}";
|
||||||
|
in
|
||||||
|
if ersatz == "" then drv else ersatz;
|
||||||
|
|
||||||
|
# Ports of functions for older nix versions
|
||||||
|
|
||||||
|
# a Nix version of mapAttrs if the built-in doesn't exist
|
||||||
|
mapAttrs = builtins.mapAttrs or (
|
||||||
|
f: set: with builtins;
|
||||||
|
listToAttrs (map (attr: { name = attr; value = f attr set.${attr}; }) (attrNames set))
|
||||||
|
);
|
||||||
|
|
||||||
|
# https://github.com/NixOS/nixpkgs/blob/0258808f5744ca980b9a1f24fe0b1e6f0fecee9c/lib/lists.nix#L295
|
||||||
|
range = first: last: if first > last then [] else builtins.genList (n: first + n) (last - first + 1);
|
||||||
|
|
||||||
|
# https://github.com/NixOS/nixpkgs/blob/0258808f5744ca980b9a1f24fe0b1e6f0fecee9c/lib/strings.nix#L257
|
||||||
|
stringToCharacters = s: map (p: builtins.substring p 1 s) (range 0 (builtins.stringLength s - 1));
|
||||||
|
|
||||||
|
# https://github.com/NixOS/nixpkgs/blob/0258808f5744ca980b9a1f24fe0b1e6f0fecee9c/lib/strings.nix#L269
|
||||||
|
stringAsChars = f: s: concatStrings (map f (stringToCharacters s));
|
||||||
|
concatMapStrings = f: list: concatStrings (map f list);
|
||||||
|
concatStrings = builtins.concatStringsSep "";
|
||||||
|
|
||||||
|
# https://github.com/NixOS/nixpkgs/blob/8a9f58a375c401b96da862d969f66429def1d118/lib/attrsets.nix#L331
|
||||||
|
optionalAttrs = cond: as: if cond then as else {};
|
||||||
|
|
||||||
|
# fetchTarball version that is compatible between all the versions of Nix
|
||||||
|
builtins_fetchTarball = { url, name ? null, sha256 }@attrs:
|
||||||
|
let
|
||||||
|
inherit (builtins) lessThan nixVersion fetchTarball;
|
||||||
|
in
|
||||||
|
if lessThan nixVersion "1.12" then
|
||||||
|
fetchTarball ({ inherit url; } // (optionalAttrs (!isNull name) { inherit name; }))
|
||||||
|
else
|
||||||
|
fetchTarball attrs;
|
||||||
|
|
||||||
|
# fetchurl version that is compatible between all the versions of Nix
|
||||||
|
builtins_fetchurl = { url, name ? null, sha256 }@attrs:
|
||||||
|
let
|
||||||
|
inherit (builtins) lessThan nixVersion fetchurl;
|
||||||
|
in
|
||||||
|
if lessThan nixVersion "1.12" then
|
||||||
|
fetchurl ({ inherit url; } // (optionalAttrs (!isNull name) { inherit name; }))
|
||||||
|
else
|
||||||
|
fetchurl attrs;
|
||||||
|
|
||||||
|
# Create the final "sources" from the config
|
||||||
|
mkSources = config:
|
||||||
|
mapAttrs (
|
||||||
|
name: spec:
|
||||||
|
if builtins.hasAttr "outPath" spec
|
||||||
|
then abort
|
||||||
|
"The values in sources.json should not have an 'outPath' attribute"
|
||||||
|
else
|
||||||
|
spec // { outPath = replace name (fetch config.pkgs name spec); }
|
||||||
|
) config.sources;
|
||||||
|
|
||||||
|
# The "config" used by the fetchers
|
||||||
|
mkConfig =
|
||||||
|
{ sourcesFile ? if builtins.pathExists ./sources.json then ./sources.json else null
|
||||||
|
, sources ? if isNull sourcesFile then {} else builtins.fromJSON (builtins.readFile sourcesFile)
|
||||||
|
, system ? builtins.currentSystem
|
||||||
|
, pkgs ? mkPkgs sources system
|
||||||
|
}: rec {
|
||||||
|
# The sources, i.e. the attribute set of spec name to spec
|
||||||
|
inherit sources;
|
||||||
|
|
||||||
|
# The "pkgs" (evaluated nixpkgs) to use for e.g. non-builtin fetchers
|
||||||
|
inherit pkgs;
|
||||||
|
};
|
||||||
|
|
||||||
|
in
|
||||||
|
mkSources (mkConfig {}) // { __functor = _: settings: mkSources (mkConfig settings); }
|
|
@ -1,4 +1,4 @@
|
||||||
{ config, lib, options, pkgs, ... }:
|
{ config, lib, pkgs, ... }:
|
||||||
let
|
let
|
||||||
inherit (lib)
|
inherit (lib)
|
||||||
attrValues
|
attrValues
|
||||||
|
@ -26,14 +26,9 @@ let
|
||||||
visible = "shallow";
|
visible = "shallow";
|
||||||
};
|
};
|
||||||
_systemd = mkOption { internal = true; };
|
_systemd = mkOption { internal = true; };
|
||||||
serviceName = mkOption {
|
|
||||||
description = "The name of the Arion project's systemd service";
|
|
||||||
type = types.str;
|
|
||||||
default = "arion-${name}";
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
config = {
|
config = {
|
||||||
_systemd.services.${config.serviceName} = {
|
_systemd.services."arion-${name}" = {
|
||||||
wantedBy = [ "multi-user.target" ];
|
wantedBy = [ "multi-user.target" ];
|
||||||
after = [ "sockets.target" ];
|
after = [ "sockets.target" ];
|
||||||
|
|
||||||
|
@ -102,10 +97,7 @@ in
|
||||||
virtualisation.docker.enable = false;
|
virtualisation.docker.enable = false;
|
||||||
virtualisation.podman.enable = true;
|
virtualisation.podman.enable = true;
|
||||||
virtualisation.podman.dockerSocket.enable = true;
|
virtualisation.podman.dockerSocket.enable = true;
|
||||||
virtualisation.podman.defaultNetwork =
|
virtualisation.podman.defaultNetwork.dnsname.enable = true;
|
||||||
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.arion.docker.client.package = pkgs.docker-client;
|
virtualisation.arion.docker.client.package = pkgs.docker-client;
|
||||||
})
|
})
|
||||||
|
|
|
@ -3,4 +3,4 @@
|
||||||
# For manual testing of a hacked arion built via Nix.
|
# For manual testing of a hacked arion built via Nix.
|
||||||
# Works when called from outside the project directory.
|
# 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 "$@"
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
(builtins.getFlake ("git+file://" + toString ./.)).devShells.${builtins.currentSystem}.default
|
args@{...}: (import ./nix args).arion-project.shell
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
{-# LANGUAGE DeriveGeneric #-}
|
{-# LANGUAGE DeriveGeneric #-}
|
||||||
{-# LANGUAGE DeriveAnyClass #-}
|
{-# LANGUAGE DeriveAnyClass #-}
|
||||||
{-# LANGUAGE OverloadedStrings #-}
|
{-# LANGUAGE OverloadedStrings #-}
|
||||||
{-# LANGUAGE CPP #-}
|
|
||||||
module Arion.Services
|
module Arion.Services
|
||||||
( getDefaultExec
|
( getDefaultExec
|
||||||
) where
|
) where
|
||||||
|
@ -10,28 +9,15 @@ import Prelude()
|
||||||
import Protolude hiding (to)
|
import Protolude hiding (to)
|
||||||
|
|
||||||
import qualified Data.Aeson as Aeson
|
import qualified Data.Aeson as Aeson
|
||||||
#if MIN_VERSION_lens_aeson(1,2,0)
|
|
||||||
import qualified Data.Aeson.Key as AK
|
|
||||||
#endif
|
|
||||||
import Arion.Aeson (decodeFile)
|
import Arion.Aeson (decodeFile)
|
||||||
|
|
||||||
import Control.Lens
|
import Control.Lens
|
||||||
import Data.Aeson.Lens
|
import Data.Aeson.Lens
|
||||||
|
|
||||||
#if MIN_VERSION_lens_aeson(1,2,0)
|
|
||||||
type Key = AK.Key
|
|
||||||
mkKey :: Text -> Key
|
|
||||||
mkKey = AK.fromText
|
|
||||||
#else
|
|
||||||
type Key = Text
|
|
||||||
mkKey :: Text -> Key
|
|
||||||
mkKey = identity
|
|
||||||
#endif
|
|
||||||
|
|
||||||
-- | Subject to change
|
-- | Subject to change
|
||||||
getDefaultExec :: FilePath -> Text -> IO [Text]
|
getDefaultExec :: FilePath -> Text -> IO [Text]
|
||||||
getDefaultExec fp service = do
|
getDefaultExec fp service = do
|
||||||
|
|
||||||
v <- decodeFile fp
|
v <- decodeFile fp
|
||||||
|
|
||||||
pure ((v :: Aeson.Value) ^.. key "x-arion" . key "serviceInfo" . key (mkKey service) . key "defaultExec" . _Array . traverse . _String)
|
pure ((v :: Aeson.Value) ^.. key "x-arion" . key "serviceInfo" . key service . key "defaultExec" . _Array . traverse . _String)
|
||||||
|
|
|
@ -13,8 +13,7 @@ import qualified Data.Text as T
|
||||||
import qualified Data.Text.IO as T
|
import qualified Data.Text.IO as T
|
||||||
|
|
||||||
spec :: Spec
|
spec :: Spec
|
||||||
spec = describe "evaluateComposition" $ do
|
spec = describe "evaluateComposition" $ it "matches an example" $ do
|
||||||
it "matches an example" $ do
|
|
||||||
x <- Arion.Nix.evaluateComposition EvaluationArgs
|
x <- Arion.Nix.evaluateComposition EvaluationArgs
|
||||||
{ evalUid = 123
|
{ evalUid = 123
|
||||||
, evalModules = NEL.fromList
|
, evalModules = NEL.fromList
|
||||||
|
@ -28,20 +27,6 @@ spec = describe "evaluateComposition" $ do
|
||||||
expected <- T.readFile "src/haskell/testdata/Arion/NixSpec/arion-compose.json"
|
expected <- T.readFile "src/haskell/testdata/Arion/NixSpec/arion-compose.json"
|
||||||
censorPaths actual `shouldBe` censorPaths expected
|
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
|
|
||||||
|
|
||||||
censorPaths :: Text -> Text
|
censorPaths :: Text -> Text
|
||||||
censorPaths = censorImages . censorStorePaths
|
censorPaths = censorImages . censorStorePaths
|
||||||
|
|
||||||
|
|
|
@ -9,4 +9,3 @@ import qualified Arion.NixSpec
|
||||||
spec :: Spec
|
spec :: Spec
|
||||||
spec = do
|
spec = do
|
||||||
describe "Arion.Nix" Arion.NixSpec.spec
|
describe "Arion.Nix" Arion.NixSpec.spec
|
||||||
|
|
||||||
|
|
|
@ -33,7 +33,6 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"version": "3.4",
|
"version": "3.4",
|
||||||
"volumes": {},
|
|
||||||
"x-arion": {
|
"x-arion": {
|
||||||
"images": [
|
"images": [
|
||||||
{
|
{
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
project.name = "unit-test-data";
|
project.name = "unit-test-data";
|
||||||
services.webserver = { pkgs, ... }: {
|
services.webserver = { pkgs, ... }: {
|
||||||
nixos.useSystemd = true;
|
nixos.useSystemd = true;
|
||||||
nixos.configuration.boot.tmp.useTmpfs = true;
|
nixos.configuration.boot.tmpOnTmpfs = true;
|
||||||
nixos.configuration.services.nginx.enable = true;
|
nixos.configuration.services.nginx.enable = true;
|
||||||
nixos.configuration.services.nginx.virtualHosts.localhost.root = "${pkgs.nix.doc}/share/doc/nix/manual";
|
nixos.configuration.services.nginx.virtualHosts.localhost.root = "${pkgs.nix.doc}/share/doc/nix/manual";
|
||||||
service.useHostStore = true;
|
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 }:
|
{ lib }:
|
||||||
let
|
let
|
||||||
|
|
||||||
link = url: text: ''[${text}](${url})'';
|
link = url: text:
|
||||||
|
''link:${url}[${text}]'';
|
||||||
|
|
||||||
composeSpecRev = "55b450aee50799a2f33cc99e1d714518babe305e";
|
dockerComposeRef = fragment:
|
||||||
|
''See ${link "https://docs.docker.com/compose/compose-file/#${fragment}" "Docker Compose#${fragment}"}'';
|
||||||
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}"}'';
|
|
||||||
|
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
inherit
|
inherit
|
||||||
|
dockerComposeRef
|
||||||
link
|
link
|
||||||
networkRef
|
|
||||||
serviceRef
|
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,7 +3,7 @@ let
|
||||||
inherit (lib) types mkOption;
|
inherit (lib) types mkOption;
|
||||||
|
|
||||||
link = url: text:
|
link = url: text:
|
||||||
''[${text}](${url})'';
|
''link:${url}[${text}]'';
|
||||||
|
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
|
|
|
@ -63,11 +63,6 @@ in
|
||||||
type = lib.types.attrsOf (lib.types.submodule service);
|
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.";
|
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 = {
|
config = {
|
||||||
out.dockerComposeYaml = pkgs.writeText "docker-compose.yaml" config.out.dockerComposeYamlText;
|
out.dockerComposeYaml = pkgs.writeText "docker-compose.yaml" config.out.dockerComposeYamlText;
|
||||||
|
@ -78,7 +73,6 @@ in
|
||||||
version = "3.4";
|
version = "3.4";
|
||||||
services = lib.mapAttrs (k: c: c.out.service) config.services;
|
services = lib.mapAttrs (k: c: c.out.service) config.services;
|
||||||
x-arion = config.docker-compose.extended;
|
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
|
stored at an alternate location without altering the format of
|
||||||
store paths.
|
store paths.
|
||||||
|
|
||||||
For example: instead of mounting the host's `/nix/store` as the
|
For example: instead of mounting the host's /nix/store as the
|
||||||
container's `/nix/store`, this will mount `/mnt/foo/nix/store`
|
container's /nix/store, this will mount /mnt/foo/nix/store
|
||||||
as the container's `/nix/store`.
|
as the container's /nix/store.
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -36,7 +36,7 @@ in
|
||||||
build.imagesToLoad = lib.mkOption {
|
build.imagesToLoad = lib.mkOption {
|
||||||
type = listOf unspecified;
|
type = listOf unspecified;
|
||||||
internal = true;
|
internal = true;
|
||||||
description = "List of `dockerTools` image derivations.";
|
description = "List of dockerTools image derivations.";
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
config = {
|
config = {
|
||||||
|
|
|
@ -7,7 +7,7 @@ let
|
||||||
types
|
types
|
||||||
;
|
;
|
||||||
inherit (import ../../lib.nix { inherit lib; })
|
inherit (import ../../lib.nix { inherit lib; })
|
||||||
link
|
dockerComposeRef
|
||||||
;
|
;
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
|
@ -19,7 +19,7 @@ in
|
||||||
];
|
];
|
||||||
});
|
});
|
||||||
description = ''
|
description = ''
|
||||||
See ${link "https://docs.docker.com/compose/compose-file/06-networks/" "Docker Compose Networks"}
|
${dockerComposeRef "networks-top-level-element"}
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
enableDefaultNetwork = mkOption {
|
enableDefaultNetwork = mkOption {
|
||||||
|
|
|
@ -7,7 +7,7 @@ let
|
||||||
types
|
types
|
||||||
;
|
;
|
||||||
inherit (import ../../lib.nix { inherit lib; })
|
inherit (import ../../lib.nix { inherit lib; })
|
||||||
networkRef
|
dockerComposeRef
|
||||||
;
|
;
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
|
@ -15,21 +15,21 @@ in
|
||||||
driver = mkOption {
|
driver = mkOption {
|
||||||
description = ''
|
description = ''
|
||||||
`"none"`, `"host"`, or a platform-specific value.
|
`"none"`, `"host"`, or a platform-specific value.
|
||||||
${networkRef "driver"}
|
${dockerComposeRef "driver"}
|
||||||
'';
|
'';
|
||||||
type = types.str;
|
type = types.str;
|
||||||
};
|
};
|
||||||
|
|
||||||
driver_opts = mkOption {
|
driver_opts = mkOption {
|
||||||
description = ''
|
description = ''
|
||||||
${networkRef "driver_opts"}
|
${dockerComposeRef "driver_opts"}
|
||||||
'';
|
'';
|
||||||
type = types.lazyAttrsOf types.raw or types.unspecified;
|
type = types.lazyAttrsOf types.raw or types.unspecified;
|
||||||
};
|
};
|
||||||
|
|
||||||
attachable = mkOption {
|
attachable = mkOption {
|
||||||
description = ''
|
description = ''
|
||||||
${networkRef "attachable"}
|
${dockerComposeRef "attachable"}
|
||||||
'';
|
'';
|
||||||
type = types.bool;
|
type = types.bool;
|
||||||
example = true;
|
example = true;
|
||||||
|
@ -39,7 +39,7 @@ in
|
||||||
description = ''
|
description = ''
|
||||||
Whether we've entered the 21st century yet.
|
Whether we've entered the 21st century yet.
|
||||||
|
|
||||||
${networkRef "enable_ipv6"}
|
${dockerComposeRef "enable_ipv6"}
|
||||||
'';
|
'';
|
||||||
type = types.bool;
|
type = types.bool;
|
||||||
};
|
};
|
||||||
|
@ -49,7 +49,7 @@ in
|
||||||
description = ''
|
description = ''
|
||||||
Manage IP addresses.
|
Manage IP addresses.
|
||||||
|
|
||||||
${networkRef "ipam"}
|
${dockerComposeRef "ipam"}
|
||||||
'';
|
'';
|
||||||
type = types.raw or types.unspecified;
|
type = types.raw or types.unspecified;
|
||||||
};
|
};
|
||||||
|
@ -58,7 +58,7 @@ in
|
||||||
description = ''
|
description = ''
|
||||||
Achieves "external isolation".
|
Achieves "external isolation".
|
||||||
|
|
||||||
${networkRef "internal"}
|
${dockerComposeRef "internal"}
|
||||||
'';
|
'';
|
||||||
defaultText = false;
|
defaultText = false;
|
||||||
type = types.bool;
|
type = types.bool;
|
||||||
|
@ -68,7 +68,7 @@ in
|
||||||
description = ''
|
description = ''
|
||||||
Metadata.
|
Metadata.
|
||||||
|
|
||||||
${networkRef "labels"}
|
${dockerComposeRef "labels"}
|
||||||
'';
|
'';
|
||||||
# no list support, because less expressive wrt overriding
|
# no list support, because less expressive wrt overriding
|
||||||
type = types.attrsOf types.str;
|
type = types.attrsOf types.str;
|
||||||
|
@ -79,7 +79,7 @@ in
|
||||||
When `true`, don't create or destroy the network, but assume that it
|
When `true`, don't create or destroy the network, but assume that it
|
||||||
exists.
|
exists.
|
||||||
|
|
||||||
${networkRef "external"}
|
${dockerComposeRef "external"}
|
||||||
'';
|
'';
|
||||||
type = types.bool;
|
type = types.bool;
|
||||||
};
|
};
|
||||||
|
@ -92,7 +92,7 @@ in
|
||||||
|
|
||||||
Note the `default` network's default `name` is set to `project.name` by Arion.
|
Note the `default` network's default `name` is set to `project.name` by Arion.
|
||||||
|
|
||||||
${networkRef "name"}
|
${dockerComposeRef "name"}
|
||||||
'';
|
'';
|
||||||
type = types.str;
|
type = types.str;
|
||||||
};
|
};
|
||||||
|
|
|
@ -12,9 +12,15 @@ let
|
||||||
|
|
||||||
inherit (import ../../lib.nix { inherit lib; })
|
inherit (import ../../lib.nix { inherit lib; })
|
||||||
link
|
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_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);
|
cap_drop = lib.attrNames (lib.filterAttrs (name: value: value == false) config.service.capabilities);
|
||||||
|
|
||||||
|
@ -50,12 +56,12 @@ in
|
||||||
service.volumes = mkOption {
|
service.volumes = mkOption {
|
||||||
type = listOf types.unspecified;
|
type = listOf types.unspecified;
|
||||||
default = [];
|
default = [];
|
||||||
description = serviceRef "volumes";
|
description = dockerComposeRef "volumes";
|
||||||
};
|
};
|
||||||
service.tmpfs = mkOption {
|
service.tmpfs = mkOption {
|
||||||
type = listOf types.str;
|
type = listOf types.str;
|
||||||
default = [];
|
default = [];
|
||||||
description = serviceRef "tmpfs";
|
description = dockerComposeRef "tmpfs";
|
||||||
};
|
};
|
||||||
service.build.context = mkOption {
|
service.build.context = mkOption {
|
||||||
type = nullOr str;
|
type = nullOr str;
|
||||||
|
@ -63,65 +69,44 @@ in
|
||||||
description = ''
|
description = ''
|
||||||
Locates a Dockerfile to use for creating an image to use in this service.
|
Locates a Dockerfile to use for creating an image to use in this service.
|
||||||
|
|
||||||
https://docs.docker.com/compose/compose-file/build/#context
|
${dockerComposeRef "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
|
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
service.hostname = mkOption {
|
service.hostname = mkOption {
|
||||||
type = nullOr str;
|
type = nullOr str;
|
||||||
default = null;
|
default = null;
|
||||||
description = ''
|
description = dockerComposeKitchenSink;
|
||||||
${serviceRef "hostname"}
|
|
||||||
'';
|
|
||||||
};
|
};
|
||||||
service.tty = mkOption {
|
service.tty = mkOption {
|
||||||
type = nullOr bool;
|
type = nullOr bool;
|
||||||
default = null;
|
default = null;
|
||||||
description = ''
|
description = dockerComposeKitchenSink;
|
||||||
${serviceRef "tty"}
|
|
||||||
'';
|
|
||||||
};
|
};
|
||||||
service.environment = mkOption {
|
service.environment = mkOption {
|
||||||
type = attrsOf (either str int);
|
type = attrsOf (either str int);
|
||||||
default = {};
|
default = {};
|
||||||
description = serviceRef "environment";
|
description = dockerComposeRef "environment";
|
||||||
};
|
};
|
||||||
service.image = mkOption {
|
service.image = mkOption {
|
||||||
type = nullOr str;
|
type = str;
|
||||||
default = null;
|
description = dockerComposeRef "image";
|
||||||
description = serviceRef "image";
|
|
||||||
};
|
};
|
||||||
service.command = mkOption {
|
service.command = mkOption {
|
||||||
type = nullOr types.unspecified;
|
type = nullOr types.unspecified;
|
||||||
default = null;
|
default = null;
|
||||||
description = serviceRef "command";
|
description = dockerComposeRef "command";
|
||||||
};
|
};
|
||||||
service.container_name = mkOption {
|
service.container_name = mkOption {
|
||||||
type = nullOr types.str;
|
type = nullOr types.str;
|
||||||
default = null;
|
default = null;
|
||||||
description = serviceRef "container_name";
|
description = dockerComposeRef "container_name";
|
||||||
};
|
};
|
||||||
service.depends_on =
|
service.depends_on =
|
||||||
let conditionsModule = {
|
let conditionsModule = {
|
||||||
options = {
|
options = {
|
||||||
condition = mkOption {
|
condition = mkOption {
|
||||||
type = enum ["service_started" "service_healthy" "service_completed_successfully"];
|
type = enum ["service_started" "service_healthy" "service_completed_successfully"];
|
||||||
description = serviceRef "depends_on";
|
description = dockerComposeRef "depends_on";
|
||||||
default = "service_started";
|
default = "service_started";
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
@ -129,10 +114,9 @@ in
|
||||||
in mkOption {
|
in mkOption {
|
||||||
type = either (listOf str) (attrsOf (submodule conditionsModule));
|
type = either (listOf str) (attrsOf (submodule conditionsModule));
|
||||||
default = [];
|
default = [];
|
||||||
description = serviceRef "depends_on";
|
description = dockerComposeRef "depends_on";
|
||||||
};
|
};
|
||||||
service.healthcheck = mkOption {
|
service.healthcheck = mkOption {
|
||||||
description = serviceRef "healthcheck";
|
|
||||||
type = submodule ({ config, options, ...}: {
|
type = submodule ({ config, options, ...}: {
|
||||||
options = {
|
options = {
|
||||||
_out = mkOption {
|
_out = mkOption {
|
||||||
|
@ -145,30 +129,30 @@ in
|
||||||
type = nullOr (listOf str);
|
type = nullOr (listOf str);
|
||||||
default = null;
|
default = null;
|
||||||
example = [ "CMD" "pg_isready" ];
|
example = [ "CMD" "pg_isready" ];
|
||||||
description = serviceRef "healthcheck";
|
description = dockerComposeRef "healthcheck";
|
||||||
};
|
};
|
||||||
interval = mkOption {
|
interval = mkOption {
|
||||||
type = str;
|
type = str;
|
||||||
default = "30s";
|
default = "30s";
|
||||||
example = "1m";
|
example = "1m";
|
||||||
description = serviceRef "healthcheck";
|
description = dockerComposeRef "healthcheck";
|
||||||
};
|
};
|
||||||
timeout = mkOption {
|
timeout = mkOption {
|
||||||
type = str;
|
type = str;
|
||||||
default = "30s";
|
default = "30s";
|
||||||
example = "10s";
|
example = "10s";
|
||||||
description = serviceRef "healthcheck";
|
description = dockerComposeRef "healthcheck";
|
||||||
};
|
};
|
||||||
start_period = mkOption {
|
start_period = mkOption {
|
||||||
type = str;
|
type = str;
|
||||||
default = "0s";
|
default = "0s";
|
||||||
example = "30s";
|
example = "30s";
|
||||||
description = serviceRef "healthcheck";
|
description = dockerComposeRef "healthcheck";
|
||||||
};
|
};
|
||||||
retries = mkOption {
|
retries = mkOption {
|
||||||
type = int;
|
type = int;
|
||||||
default = 3;
|
default = 3;
|
||||||
description = serviceRef "healthcheck";
|
description = dockerComposeRef "healthcheck";
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
@ -180,14 +164,14 @@ in
|
||||||
See ${link "https://docs.docker.com/engine/reference/run/#runtime-privilege-and-linux-capabilities"
|
See ${link "https://docs.docker.com/engine/reference/run/#runtime-privilege-and-linux-capabilities"
|
||||||
"`docker run --device` documentation"}
|
"`docker run --device` documentation"}
|
||||||
|
|
||||||
${serviceRef "devices"}
|
${dockerComposeRef "devices"}
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
service.dns = mkOption {
|
service.dns = mkOption {
|
||||||
type = listOf str;
|
type = listOf str;
|
||||||
default = [];
|
default = [];
|
||||||
example = [ "8.8.8.8" "8.8.4.4" ];
|
example = [ "8.8.8.8" "8.8.4.4" ];
|
||||||
description = serviceRef "dns";
|
description = dockerComposeRef "dns";
|
||||||
};
|
};
|
||||||
service.labels = mkOption {
|
service.labels = mkOption {
|
||||||
type = attrsOf str;
|
type = attrsOf str;
|
||||||
|
@ -198,58 +182,47 @@ in
|
||||||
"traefik.http.routers.my-service.rule" = "Host(`my-service.localhost`)";
|
"traefik.http.routers.my-service.rule" = "Host(`my-service.localhost`)";
|
||||||
"traefik.http.routers.my-service.entrypoints" = "web";
|
"traefik.http.routers.my-service.entrypoints" = "web";
|
||||||
};
|
};
|
||||||
description = serviceRef "labels";
|
description = dockerComposeRef "labels";
|
||||||
};
|
};
|
||||||
service.links = mkOption {
|
service.links = mkOption {
|
||||||
type = listOf str;
|
type = listOf str;
|
||||||
default = [];
|
default = [];
|
||||||
description = serviceRef "links";
|
description = dockerComposeRef "links";
|
||||||
};
|
};
|
||||||
service.external_links = mkOption {
|
service.external_links = mkOption {
|
||||||
type = listOf str;
|
type = listOf str;
|
||||||
default = [];
|
default = [];
|
||||||
description = serviceRef "external_links";
|
description = dockerComposeRef "external_links";
|
||||||
};
|
|
||||||
service.profiles = mkOption {
|
|
||||||
type = listOf str;
|
|
||||||
default = [];
|
|
||||||
description = serviceRef "profiles";
|
|
||||||
};
|
};
|
||||||
service.extra_hosts = mkOption {
|
service.extra_hosts = mkOption {
|
||||||
type = listOf str;
|
type = listOf str;
|
||||||
default = [];
|
default = [];
|
||||||
description = serviceRef "extra_hosts";
|
description = dockerComposeRef "extra_hosts";
|
||||||
};
|
};
|
||||||
service.working_dir = mkOption {
|
service.working_dir = mkOption {
|
||||||
type = nullOr str;
|
type = nullOr str;
|
||||||
default = null;
|
default = null;
|
||||||
description = ''
|
description = dockerComposeKitchenSink;
|
||||||
${serviceRef "working_dir"}
|
|
||||||
'';
|
|
||||||
};
|
};
|
||||||
service.privileged = mkOption {
|
service.privileged = mkOption {
|
||||||
type = nullOr bool;
|
type = nullOr bool;
|
||||||
default = null;
|
default = null;
|
||||||
description = ''
|
description = dockerComposeKitchenSink;
|
||||||
${serviceRef "privileged"}
|
|
||||||
'';
|
|
||||||
};
|
};
|
||||||
service.entrypoint = mkOption {
|
service.entrypoint = mkOption {
|
||||||
type = nullOr str;
|
type = nullOr str;
|
||||||
default = null;
|
default = null;
|
||||||
description = serviceRef "entrypoint";
|
description = dockerComposeRef "entrypoint";
|
||||||
};
|
};
|
||||||
service.restart = mkOption {
|
service.restart = mkOption {
|
||||||
type = nullOr str;
|
type = nullOr str;
|
||||||
default = null;
|
default = null;
|
||||||
description = serviceRef "restart";
|
description = dockerComposeRef "restart";
|
||||||
};
|
};
|
||||||
service.user = mkOption {
|
service.user = mkOption {
|
||||||
type = nullOr str;
|
type = nullOr str;
|
||||||
default = null;
|
default = null;
|
||||||
description = ''
|
description = dockerComposeKitchenSink;
|
||||||
${serviceRef "user"}
|
|
||||||
'';
|
|
||||||
};
|
};
|
||||||
service.ports = mkOption {
|
service.ports = mkOption {
|
||||||
type = listOf types.unspecified;
|
type = listOf types.unspecified;
|
||||||
|
@ -257,76 +230,38 @@ in
|
||||||
description = ''
|
description = ''
|
||||||
Expose ports on host. "host:container" or structured.
|
Expose ports on host. "host:container" or structured.
|
||||||
|
|
||||||
${serviceRef "ports"}
|
${dockerComposeRef "ports"}
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
service.expose = mkOption {
|
service.expose = mkOption {
|
||||||
type = listOf str;
|
type = listOf str;
|
||||||
default = [];
|
default = [];
|
||||||
description = serviceRef "expose";
|
description = dockerComposeRef "expose";
|
||||||
};
|
};
|
||||||
service.env_file = mkOption {
|
service.env_file = mkOption {
|
||||||
type = listOf str;
|
type = listOf str;
|
||||||
default = [];
|
default = [];
|
||||||
description = serviceRef "env_file";
|
description = dockerComposeRef "env_file";
|
||||||
};
|
};
|
||||||
service.network_mode = mkOption {
|
service.network_mode = mkOption {
|
||||||
type = nullOr str;
|
type = nullOr str;
|
||||||
default = null;
|
default = null;
|
||||||
description = serviceRef "network_mode";
|
description = dockerComposeRef "network_mode";
|
||||||
};
|
};
|
||||||
service.networks =
|
service.networks = mkOption {
|
||||||
let
|
type = nullOr (listOf types.str);
|
||||||
networksModule = submodule ({ config, options, ...}: {
|
default = null;
|
||||||
options = {
|
description = dockerComposeRef "networks";
|
||||||
_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 {
|
service.stop_signal = mkOption {
|
||||||
type = nullOr str;
|
type = nullOr str;
|
||||||
default = null;
|
default = null;
|
||||||
description = serviceRef "stop_signal";
|
description = dockerComposeRef "stop_signal";
|
||||||
};
|
|
||||||
service.stop_grace_period = mkOption {
|
|
||||||
type = nullOr str;
|
|
||||||
default = null;
|
|
||||||
description = serviceRef "stop_grace_period";
|
|
||||||
};
|
};
|
||||||
service.sysctls = mkOption {
|
service.sysctls = mkOption {
|
||||||
type = attrsOf (either str int);
|
type = attrsOf (either str int);
|
||||||
default = {};
|
default = {};
|
||||||
description = serviceRef "sysctls";
|
description = dockerComposeRef "sysctls";
|
||||||
};
|
};
|
||||||
service.capabilities = mkOption {
|
service.capabilities = mkOption {
|
||||||
type = attrsOf (nullOr bool);
|
type = attrsOf (nullOr bool);
|
||||||
|
@ -337,15 +272,13 @@ in
|
||||||
|
|
||||||
Setting a capability to `true` means that it will be
|
Setting a capability to `true` means that it will be
|
||||||
"added". Setting it to `false` means that it will be "dropped".
|
"added". Setting it to `false` means that it will be "dropped".
|
||||||
|
${dockerComposeRef "cap_add-cap_drop"}
|
||||||
|
|
||||||
Omitted and `null` capabilities will therefore be set
|
Omitted and `null` capabilities will therefore be set
|
||||||
according to Docker's ${
|
according to Docker's ${
|
||||||
link "https://docs.docker.com/engine/reference/run/#runtime-privilege-and-linux-capabilities"
|
link "https://docs.docker.com/engine/reference/run/#runtime-privilege-and-linux-capabilities"
|
||||||
"default list of capabilities."
|
"default list of capabilities."
|
||||||
}
|
}
|
||||||
|
|
||||||
${serviceRef "cap_add"}
|
|
||||||
${serviceRef "cap_drop"}
|
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
@ -355,11 +288,10 @@ in
|
||||||
volumes
|
volumes
|
||||||
environment
|
environment
|
||||||
sysctls
|
sysctls
|
||||||
|
image
|
||||||
;
|
;
|
||||||
} // lib.optionalAttrs (config.service.image != null) {
|
|
||||||
inherit (config.service) image;
|
|
||||||
} // lib.optionalAttrs (config.service.build.context != null) {
|
} // lib.optionalAttrs (config.service.build.context != null) {
|
||||||
build = lib.filterAttrs (n: v: v != null) config.service.build;
|
inherit (config.service) build;
|
||||||
} // lib.optionalAttrs (cap_add != []) {
|
} // lib.optionalAttrs (cap_add != []) {
|
||||||
inherit cap_add;
|
inherit cap_add;
|
||||||
} // lib.optionalAttrs (cap_drop != []) {
|
} // lib.optionalAttrs (cap_drop != []) {
|
||||||
|
@ -398,16 +330,12 @@ in
|
||||||
inherit (config.service) privileged;
|
inherit (config.service) privileged;
|
||||||
} // lib.optionalAttrs (config.service.network_mode != null) {
|
} // lib.optionalAttrs (config.service.network_mode != null) {
|
||||||
inherit (config.service) network_mode;
|
inherit (config.service) network_mode;
|
||||||
} // lib.optionalAttrs (config.service.networks != [] && config.service.networks != {}) {
|
} // lib.optionalAttrs (config.service.networks != null) {
|
||||||
networks =
|
inherit (config.service) networks;
|
||||||
if (builtins.isAttrs config.service.networks) then builtins.mapAttrs (_: v: v._out) config.service.networks
|
|
||||||
else config.service.networks;
|
|
||||||
} // lib.optionalAttrs (config.service.restart != null) {
|
} // lib.optionalAttrs (config.service.restart != null) {
|
||||||
inherit (config.service) restart;
|
inherit (config.service) restart;
|
||||||
} // lib.optionalAttrs (config.service.stop_signal != null) {
|
} // lib.optionalAttrs (config.service.stop_signal != null) {
|
||||||
inherit (config.service) stop_signal;
|
inherit (config.service) stop_signal;
|
||||||
} // lib.optionalAttrs (config.service.stop_grace_period != null) {
|
|
||||||
inherit (config.service) stop_grace_period;
|
|
||||||
} // lib.optionalAttrs (config.service.tmpfs != []) {
|
} // lib.optionalAttrs (config.service.tmpfs != []) {
|
||||||
inherit (config.service) tmpfs;
|
inherit (config.service) tmpfs;
|
||||||
} // lib.optionalAttrs (config.service.tty != null) {
|
} // lib.optionalAttrs (config.service.tty != null) {
|
||||||
|
@ -416,7 +344,5 @@ in
|
||||||
inherit (config.service) working_dir;
|
inherit (config.service) working_dir;
|
||||||
} // lib.optionalAttrs (config.service.user != null) {
|
} // lib.optionalAttrs (config.service.user != null) {
|
||||||
inherit (config.service) user;
|
inherit (config.service) user;
|
||||||
} // lib.optionalAttrs (config.service.profiles != []) {
|
|
||||||
inherit (config.service) profiles;
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,7 +12,7 @@ in
|
||||||
type = attrsOf unspecified;
|
type = attrsOf unspecified;
|
||||||
description = ''
|
description = ''
|
||||||
Information about a service to include in the Docker Compose file,
|
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.
|
itself.
|
||||||
|
|
||||||
It will be inserted in `x-arion.serviceInfo.<service.name>`.
|
It will be inserted in `x-arion.serviceInfo.<service.name>`.
|
||||||
|
|
|
@ -20,7 +20,7 @@ in
|
||||||
service.hostStoreAsReadOnly = mkOption {
|
service.hostStoreAsReadOnly = mkOption {
|
||||||
type = types.bool;
|
type = types.bool;
|
||||||
default = true;
|
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 {
|
service.useHostNixDaemon = mkOption {
|
||||||
type = types.bool;
|
type = types.bool;
|
||||||
|
|
|
@ -30,7 +30,6 @@ let
|
||||||
{
|
{
|
||||||
name = null; tag = null; contents = null; config = null;
|
name = null; tag = null; contents = null; config = null;
|
||||||
created = null; extraCommands = null; maxLayers = null;
|
created = null; extraCommands = null; maxLayers = null;
|
||||||
fakeRootCommands = null;
|
|
||||||
}
|
}
|
||||||
args;
|
args;
|
||||||
acceptedArgs = functionArgs dockerTools.streamLayeredImage;
|
acceptedArgs = functionArgs dockerTools.streamLayeredImage;
|
||||||
|
@ -68,8 +67,6 @@ let
|
||||||
ln -s $i nix/var/nix/gcroots/docker/$(basename $i)
|
ln -s $i nix/var/nix/gcroots/docker/$(basename $i)
|
||||||
done;
|
done;
|
||||||
'';
|
'';
|
||||||
|
|
||||||
fakeRootCommands = config.image.fakeRootCommands;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
priorityIsDefault = option: option.highestPrio >= (lib.mkDefault true).priority;
|
priorityIsDefault = option: option.highestPrio >= (lib.mkDefault true).priority;
|
||||||
|
@ -79,18 +76,18 @@ in
|
||||||
build.image = mkOption {
|
build.image = mkOption {
|
||||||
type = nullOr package;
|
type = nullOr package;
|
||||||
description = ''
|
description = ''
|
||||||
Docker image derivation to be `docker load`-ed.
|
Docker image derivation to be `docker load`ed.
|
||||||
'';
|
'';
|
||||||
internal = true;
|
internal = true;
|
||||||
};
|
};
|
||||||
build.imageName = mkOption {
|
build.imageName = mkOption {
|
||||||
type = str;
|
type = str;
|
||||||
description = "Derived from `build.image`";
|
description = "Derived from build.image";
|
||||||
internal = true;
|
internal = true;
|
||||||
};
|
};
|
||||||
build.imageTag = mkOption {
|
build.imageTag = mkOption {
|
||||||
type = str;
|
type = str;
|
||||||
description = "Derived from `build.image`";
|
description = "Derived from build.image";
|
||||||
internal = true;
|
internal = true;
|
||||||
};
|
};
|
||||||
image.nixBuild = mkOption {
|
image.nixBuild = mkOption {
|
||||||
|
@ -123,22 +120,13 @@ in
|
||||||
Top level paths in the container.
|
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 {
|
image.includeStorePaths = mkOption {
|
||||||
type = bool;
|
type = bool;
|
||||||
default = true;
|
default = true;
|
||||||
internal = true;
|
internal = true;
|
||||||
description = ''
|
description = ''
|
||||||
Include all referenced store paths. You generally want this in your
|
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 {
|
image.rawConfig = mkOption {
|
||||||
|
@ -152,8 +140,8 @@ in
|
||||||
Please use the specific `image` options instead.
|
Please use the specific `image` options instead.
|
||||||
|
|
||||||
Run-time configuration of the container. A full list of the
|
Run-time configuration of the container. A full list of the
|
||||||
options is available in the [Docker Image Specification
|
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](https://github.com/moby/moby/blob/master/image/spec/v1.2.md#image-json-field-descriptions).
|
v1.2.0].
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
image.command = mkOption {
|
image.command = mkOption {
|
||||||
|
@ -163,19 +151,17 @@ in
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
config = lib.mkMerge [{
|
config = {
|
||||||
build.image = builtImage;
|
build.image = builtImage;
|
||||||
build.imageName = config.build.image.imageName;
|
build.imageName = config.build.image.imageName;
|
||||||
build.imageTag =
|
build.imageTag =
|
||||||
if config.build.image.imageTag != ""
|
if config.build.image.imageTag != ""
|
||||||
then config.build.image.imageTag
|
then config.build.image.imageTag
|
||||||
else lib.head (lib.strings.splitString "-" (baseNameOf config.build.image.outPath));
|
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}";
|
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 = [
|
service.tmpfs = [
|
||||||
"/run" # noexec is fine because exes should be symlinked from elsewhere anyway
|
"/run" # noexec is fine because exes should be symlinked from elsewhere anyway
|
||||||
"/run/wrappers" # noexec breaks this intentionally
|
"/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.stop_signal = "SIGRTMIN+3";
|
||||||
service.tty = true;
|
service.tty = true;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
{ usePodman ? false, pkgs, lib ? pkgs.lib, ... }:
|
{ usePodman ? false, pkgs, lib, ... }:
|
||||||
|
|
||||||
let
|
let
|
||||||
# To make some prebuilt derivations available in the vm
|
# To make some prebuilt derivations available in the vm
|
||||||
|
@ -31,7 +31,15 @@ in
|
||||||
};
|
};
|
||||||
|
|
||||||
# no caches, because no internet
|
# 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;
|
virtualisation.writableStore = true;
|
||||||
# Switch to virtualisation.additionalPaths when dropping all NixOS <= 21.05.
|
# Switch to virtualisation.additionalPaths when dropping all NixOS <= 21.05.
|
||||||
|
@ -45,7 +53,7 @@ in
|
||||||
pkgs.stdenv
|
pkgs.stdenv
|
||||||
];
|
];
|
||||||
|
|
||||||
virtualisation.memorySize = 2048;
|
virtualisation.memorySize = 1024;
|
||||||
virtualisation.diskSize = 8000;
|
virtualisation.diskSize = 8000;
|
||||||
};
|
};
|
||||||
testScript = ''
|
testScript = ''
|
||||||
|
|
46
tests/default.nix
Normal file
46
tests/default.nix
Normal file
|
@ -0,0 +1,46 @@
|
||||||
|
{ pkgs ? import ../pkgs.nix, arionTestingFlags ? {} }:
|
||||||
|
let
|
||||||
|
inherit (pkgs) nixosTest recurseIntoAttrs arion lib;
|
||||||
|
|
||||||
|
hasEvalModulesType = (lib.evalModules { modules = [ {} ]; })?type;
|
||||||
|
|
||||||
|
in
|
||||||
|
|
||||||
|
recurseIntoAttrs {
|
||||||
|
|
||||||
|
test = nixosTest ./arion-test;
|
||||||
|
|
||||||
|
nixosModuleWithDocker =
|
||||||
|
lib.optionalAttrs
|
||||||
|
hasEvalModulesType
|
||||||
|
(
|
||||||
|
import ./nixos-virtualization-arion-test/test.nix pkgs {
|
||||||
|
virtualisation.arion.backend = "docker";
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
nixosModuleWithPodman =
|
||||||
|
lib.optionalAttrs
|
||||||
|
(hasEvalModulesType && arionTestingFlags.nixosHasPodmanDockerSocket)
|
||||||
|
(
|
||||||
|
import ./nixos-virtualization-arion-test/test.nix pkgs {
|
||||||
|
virtualisation.arion.backend = "podman-socket";
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
testWithPodman =
|
||||||
|
if arionTestingFlags.nixosHasPodmanDockerSocket
|
||||||
|
then nixosTest (import ./arion-test { usePodman = true; inherit pkgs lib; })
|
||||||
|
else {};
|
||||||
|
|
||||||
|
testBuild = arion.build {
|
||||||
|
|
||||||
|
# To be more accurately, you can do
|
||||||
|
# pkgs = import ../examples/minimal/arion-pkgs.nix;
|
||||||
|
# but this is quite efficient:
|
||||||
|
inherit pkgs;
|
||||||
|
|
||||||
|
modules = [ ../examples/minimal/arion-compose.nix ];
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
|
@ -1,36 +0,0 @@
|
||||||
{
|
|
||||||
perSystem = { pkgs, final, ... }:
|
|
||||||
let
|
|
||||||
inherit (final) nixosTest arion lib;
|
|
||||||
in
|
|
||||||
{
|
|
||||||
checks = lib.optionalAttrs pkgs.stdenv.isLinux {
|
|
||||||
test = nixosTest ./arion-test;
|
|
||||||
|
|
||||||
nixosModuleWithDocker =
|
|
||||||
import ./nixos-virtualization-arion-test/test.nix final {
|
|
||||||
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";
|
|
||||||
# };
|
|
||||||
|
|
||||||
testWithPodman =
|
|
||||||
nixosTest (import ./arion-test { usePodman = true; pkgs = final; });
|
|
||||||
|
|
||||||
testBuild = arion.build {
|
|
||||||
|
|
||||||
# To be more accurate, we could do
|
|
||||||
# pkgs = import ../examples/minimal/arion-pkgs.nix;
|
|
||||||
# But let's avoid re-evaluating Nixpkgs
|
|
||||||
pkgs = final;
|
|
||||||
|
|
||||||
modules = [ ../examples/minimal/arion-compose.nix ];
|
|
||||||
};
|
|
||||||
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
|
@ -4,7 +4,7 @@ pkgs.nixosTest {
|
||||||
name = "test-basic-arion-kafka";
|
name = "test-basic-arion-kafka";
|
||||||
nodes = {
|
nodes = {
|
||||||
machine = { ... }: {
|
machine = { ... }: {
|
||||||
virtualisation.memorySize = 4096;
|
virtualisation.memorySize = 3000;
|
||||||
virtualisation.diskSize = 10000;
|
virtualisation.diskSize = 10000;
|
||||||
imports = [
|
imports = [
|
||||||
../../nixos-module.nix
|
../../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
|
||||||
|
|
||||||
|
set -eu -o pipefail
|
||||||
|
|
||||||
|
cd "$(dirname ${BASH_SOURCE[0]})"
|
||||||
|
|
||||||
|
doc_options="$(nix-build nix -A doc-options)"
|
||||||
|
cat "$doc_options" >docs/modules/ROOT/partials/NixOSOptions.adoc
|
Loading…
Add table
Add a link
Reference in a new issue