Assertions, warnings, renames
This commit is contained in:
parent
6abcc26a76
commit
c3a5f8c13f
14 changed files with 106 additions and 27 deletions
|
@ -19,6 +19,7 @@ data-files: nix/*.nix
|
||||||
, nix/modules/composition/*.nix
|
, nix/modules/composition/*.nix
|
||||||
, nix/modules/nixos/*.nix
|
, nix/modules/nixos/*.nix
|
||||||
, nix/modules/service/*.nix
|
, nix/modules/service/*.nix
|
||||||
|
, nix/modules/lib/*.nix
|
||||||
|
|
||||||
-- all data is verbatim from some sources
|
-- all data is verbatim from some sources
|
||||||
data-dir: src
|
data-dir: src
|
||||||
|
|
|
@ -11,7 +11,7 @@ let
|
||||||
eval = import (srcDir + "/nix/eval-composition.nix");
|
eval = import (srcDir + "/nix/eval-composition.nix");
|
||||||
build = args@{...}:
|
build = args@{...}:
|
||||||
let composition = eval args;
|
let composition = eval args;
|
||||||
in composition.config.build.dockerComposeYaml;
|
in composition.config.out.dockerComposeYaml;
|
||||||
|
|
||||||
in
|
in
|
||||||
justStaticExecutables (overrideCabal arion-compose (o: {
|
justStaticExecutables (overrideCabal arion-compose (o: {
|
||||||
|
|
|
@ -51,7 +51,7 @@ evaluateComposition ea = do
|
||||||
, "--strict"
|
, "--strict"
|
||||||
, "--json"
|
, "--json"
|
||||||
, "--attr"
|
, "--attr"
|
||||||
, "config.build.dockerComposeYamlAttrs"
|
, "config.out.dockerComposeYamlAttrs"
|
||||||
]
|
]
|
||||||
args =
|
args =
|
||||||
[ evalComposition ]
|
[ evalComposition ]
|
||||||
|
@ -99,7 +99,7 @@ buildComposition outLink ea = do
|
||||||
evalComposition <- getEvalCompositionFile
|
evalComposition <- getEvalCompositionFile
|
||||||
let commandArgs =
|
let commandArgs =
|
||||||
[ "--attr"
|
[ "--attr"
|
||||||
, "config.build.dockerComposeYaml"
|
, "config.out.dockerComposeYaml"
|
||||||
, "--out-link"
|
, "--out-link"
|
||||||
, outLink
|
, outLink
|
||||||
]
|
]
|
||||||
|
|
|
@ -34,7 +34,7 @@ let
|
||||||
};
|
};
|
||||||
|
|
||||||
in
|
in
|
||||||
# Typically you need composition.config.build.dockerComposeYaml
|
# Typically you need composition.config.out.dockerComposeYaml
|
||||||
composition // {
|
composition // {
|
||||||
# throw in lib and pkgs for repl convenience
|
# throw in lib and pkgs for repl convenience
|
||||||
inherit lib;
|
inherit lib;
|
||||||
|
|
|
@ -34,7 +34,7 @@ in
|
||||||
|
|
||||||
config = {
|
config = {
|
||||||
arionBaseImage = "${name}:${tag}";
|
arionBaseImage = "${name}:${tag}";
|
||||||
build.imagesToLoad = lib.mkIf (lib.any (s: s.service.useHostStore) (lib.attrValues config.docker-compose.services)) [
|
build.imagesToLoad = lib.mkIf (lib.any (s: s.service.useHostStore) (lib.attrValues config.services)) [
|
||||||
{ image = builtImage; imageName = name; imageTag = tag; }
|
{ image = builtImage; imageName = name; imageTag = tag; }
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
|
|
|
@ -3,10 +3,10 @@
|
||||||
This is a composition-level module.
|
This is a composition-level module.
|
||||||
|
|
||||||
It defines the low-level options that are read by arion, like
|
It defines the low-level options that are read by arion, like
|
||||||
- build.dockerComposeYaml
|
- out.dockerComposeYaml
|
||||||
|
|
||||||
It declares options like
|
It declares options like
|
||||||
- docker-compose.services
|
- services
|
||||||
|
|
||||||
*/
|
*/
|
||||||
compositionArgs@{ lib, config, options, pkgs, ... }:
|
compositionArgs@{ lib, config, options, pkgs, ... }:
|
||||||
|
@ -31,20 +31,24 @@ let
|
||||||
|
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
|
imports = [
|
||||||
|
../lib/assert.nix
|
||||||
|
(lib.mkRenamedOptionModule ["docker-compose" "services"] ["services"])
|
||||||
|
];
|
||||||
options = {
|
options = {
|
||||||
build.dockerComposeYaml = lib.mkOption {
|
out.dockerComposeYaml = lib.mkOption {
|
||||||
type = lib.types.package;
|
type = lib.types.package;
|
||||||
description = "A derivation that produces a docker-compose.yaml file for this composition.";
|
description = "A derivation that produces a docker-compose.yaml file for this composition.";
|
||||||
readOnly = true;
|
readOnly = true;
|
||||||
};
|
};
|
||||||
build.dockerComposeYamlText = lib.mkOption {
|
out.dockerComposeYamlText = lib.mkOption {
|
||||||
type = lib.types.str;
|
type = lib.types.str;
|
||||||
description = "The text of build.dockerComposeYaml.";
|
description = "The text of out.dockerComposeYaml.";
|
||||||
readOnly = true;
|
readOnly = true;
|
||||||
};
|
};
|
||||||
build.dockerComposeYamlAttrs = lib.mkOption {
|
out.dockerComposeYamlAttrs = lib.mkOption {
|
||||||
type = lib.types.attrsOf lib.types.unspecified;
|
type = lib.types.attrsOf lib.types.unspecified;
|
||||||
description = "The text of build.dockerComposeYaml.";
|
description = "The text of out.dockerComposeYaml.";
|
||||||
readOnly = true;
|
readOnly = true;
|
||||||
};
|
};
|
||||||
docker-compose.raw = lib.mkOption {
|
docker-compose.raw = lib.mkOption {
|
||||||
|
@ -55,19 +59,19 @@ in
|
||||||
type = lib.types.attrs;
|
type = lib.types.attrs;
|
||||||
description = "Attribute set that will be turned into the x-arion section of the docker-compose.yaml file.";
|
description = "Attribute set that will be turned into the x-arion section of the docker-compose.yaml file.";
|
||||||
};
|
};
|
||||||
docker-compose.services = lib.mkOption {
|
services = lib.mkOption {
|
||||||
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.";
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
config = {
|
config = {
|
||||||
build.dockerComposeYaml = pkgs.writeText "docker-compose.yaml" config.build.dockerComposeYamlText;
|
out.dockerComposeYaml = pkgs.writeText "docker-compose.yaml" config.out.dockerComposeYamlText;
|
||||||
build.dockerComposeYamlText = builtins.toJSON (config.build.dockerComposeYamlAttrs);
|
out.dockerComposeYamlText = builtins.toJSON (config.out.dockerComposeYamlAttrs);
|
||||||
build.dockerComposeYamlAttrs = config.docker-compose.raw;
|
out.dockerComposeYamlAttrs = config.assertWarn config.docker-compose.raw;
|
||||||
|
|
||||||
docker-compose.raw = {
|
docker-compose.raw = {
|
||||||
version = "3.4";
|
version = "3.4";
|
||||||
services = lib.mapAttrs (k: c: c.build.service) config.docker-compose.services;
|
services = lib.mapAttrs (k: c: c.out.service) config.services;
|
||||||
x-arion = config.docker-compose.extended;
|
x-arion = config.docker-compose.extended;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
|
@ -4,7 +4,7 @@ let
|
||||||
|
|
||||||
serviceImages =
|
serviceImages =
|
||||||
lib.mapAttrs addDetails (
|
lib.mapAttrs addDetails (
|
||||||
lib.filterAttrs filterFunction config.docker-compose.services
|
lib.filterAttrs filterFunction config.services
|
||||||
);
|
);
|
||||||
|
|
||||||
filterFunction = serviceName: service:
|
filterFunction = serviceName: service:
|
||||||
|
@ -14,7 +14,7 @@ let
|
||||||
addDetails = serviceName: service:
|
addDetails = serviceName: service:
|
||||||
builtins.addErrorContext "while evaluating the image for service ${serviceName}"
|
builtins.addErrorContext "while evaluating the image for service ${serviceName}"
|
||||||
(let
|
(let
|
||||||
inherit (service.config) build;
|
inherit (service) build;
|
||||||
in {
|
in {
|
||||||
image = build.image.outPath;
|
image = build.image.outPath;
|
||||||
imageName = build.imageName or service.image.name;
|
imageName = build.imageName or service.image.name;
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
let
|
let
|
||||||
serviceInfo =
|
serviceInfo =
|
||||||
lib.mapAttrs getInfo (
|
lib.mapAttrs getInfo (
|
||||||
lib.filterAttrs filterFunction config.docker-compose.services
|
lib.filterAttrs filterFunction config.services
|
||||||
);
|
);
|
||||||
|
|
||||||
filterFunction = _serviceName: service:
|
filterFunction = _serviceName: service:
|
||||||
|
|
2
src/nix/modules/lib/README.md
Normal file
2
src/nix/modules/lib/README.md
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
`assertions.nix`: Nixpkgs
|
||||||
|
`assert.nix`: extracted from Nixpkgs, adapted
|
32
src/nix/modules/lib/assert.nix
Normal file
32
src/nix/modules/lib/assert.nix
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
{ config, lib, pkgs, ... }:
|
||||||
|
|
||||||
|
# based on nixpkgs/nixos/modules/system/activation/top-level.nix
|
||||||
|
|
||||||
|
let
|
||||||
|
inherit (lib) filter concatStringsSep types mkOption;
|
||||||
|
|
||||||
|
# lib.showWarnings since 19.09
|
||||||
|
showWarnings = warnings: res: lib.fold (w: x: lib.warn w x) res warnings;
|
||||||
|
warn = msg: builtins.trace "[1;31mwarning: ${msg}[0m";
|
||||||
|
|
||||||
|
# Handle assertions and warnings
|
||||||
|
|
||||||
|
failedAssertions = map (x: x.message) (filter (x: !x.assertion) config.assertions);
|
||||||
|
|
||||||
|
assertWarn = if failedAssertions != []
|
||||||
|
then throw "\nFailed assertions:\n${concatStringsSep "\n" (map (x: "- ${x}") failedAssertions)}"
|
||||||
|
else showWarnings config.warnings;
|
||||||
|
|
||||||
|
in
|
||||||
|
|
||||||
|
{
|
||||||
|
imports = [ ./assertions.nix ];
|
||||||
|
options.assertWarn = mkOption {
|
||||||
|
type = types.unspecified; # a function
|
||||||
|
# It's for the wrapping program to know about this. User need not care.
|
||||||
|
internal = true;
|
||||||
|
readOnly = true;
|
||||||
|
};
|
||||||
|
config = { inherit assertWarn; };
|
||||||
|
}
|
||||||
|
|
34
src/nix/modules/lib/assertions.nix
Normal file
34
src/nix/modules/lib/assertions.nix
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
{ lib, ... }:
|
||||||
|
|
||||||
|
with lib;
|
||||||
|
|
||||||
|
{
|
||||||
|
|
||||||
|
options = {
|
||||||
|
|
||||||
|
assertions = mkOption {
|
||||||
|
type = types.listOf types.unspecified;
|
||||||
|
internal = true;
|
||||||
|
default = [];
|
||||||
|
example = [ { assertion = false; message = "you can't enable this for that reason"; } ];
|
||||||
|
description = ''
|
||||||
|
This option allows modules to express conditions that must
|
||||||
|
hold for the evaluation of the system configuration to
|
||||||
|
succeed, along with associated error messages for the user.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
warnings = mkOption {
|
||||||
|
internal = true;
|
||||||
|
default = [];
|
||||||
|
type = types.listOf types.str;
|
||||||
|
example = [ "The `foo' service is deprecated and will go away soon!" ];
|
||||||
|
description = ''
|
||||||
|
This option allows modules to show warnings to users during
|
||||||
|
the evaluation of the system configuration.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
};
|
||||||
|
# impl of assertions is in <nixpkgs/nixos/modules/system/activation/top-level.nix>
|
||||||
|
}
|
|
@ -7,4 +7,5 @@
|
||||||
./image.nix
|
./image.nix
|
||||||
./nixos.nix
|
./nixos.nix
|
||||||
./nixos-init.nix
|
./nixos-init.nix
|
||||||
|
../lib/assert.nix
|
||||||
]
|
]
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
|
|
||||||
This service-level module defines the build.service option, using
|
This service-level module defines the out.service option, using
|
||||||
the user-facing options service.image, service.volumes, etc.
|
the user-facing options service.image, service.volumes, etc.
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
@ -25,8 +25,12 @@ let
|
||||||
|
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
|
imports = [
|
||||||
|
(lib.mkRenamedOptionModule ["build" "service"] ["out" "service"])
|
||||||
|
];
|
||||||
|
|
||||||
options = {
|
options = {
|
||||||
build.service = mkOption {
|
out.service = mkOption {
|
||||||
type = attrsOf types.unspecified;
|
type = attrsOf types.unspecified;
|
||||||
description = ''
|
description = ''
|
||||||
Raw input for the service in <code>docker-compose.yaml</code>.
|
Raw input for the service in <code>docker-compose.yaml</code>.
|
||||||
|
@ -37,12 +41,13 @@ in
|
||||||
This option is user accessible because it may serve as an
|
This option is user accessible because it may serve as an
|
||||||
escape hatch for some.
|
escape hatch for some.
|
||||||
'';
|
'';
|
||||||
|
apply = config.assertWarn;
|
||||||
};
|
};
|
||||||
|
|
||||||
service.name = mkOption {
|
service.name = mkOption {
|
||||||
type = str;
|
type = str;
|
||||||
description = ''
|
description = ''
|
||||||
The name of the service - <code><name></code> in the composition-level <code>docker-compose.services.<name></code>
|
The name of the service - <code><name></code> in the composition-level <code>services.<name></code>
|
||||||
'';
|
'';
|
||||||
readOnly = true;
|
readOnly = true;
|
||||||
};
|
};
|
||||||
|
@ -209,7 +214,7 @@ in
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
config.build.service = {
|
config.out.service = {
|
||||||
inherit (config.service)
|
inherit (config.service)
|
||||||
volumes
|
volumes
|
||||||
environment
|
environment
|
||||||
|
|
|
@ -30,9 +30,9 @@ in
|
||||||
virtualisation.pathsInNixDB = [
|
virtualisation.pathsInNixDB = [
|
||||||
# Pre-build the image because we don't want to build the world
|
# Pre-build the image because we don't want to build the world
|
||||||
# in the vm.
|
# in the vm.
|
||||||
(preEval [ ../../examples/minimal/arion-compose.nix ]).config.build.dockerComposeYaml
|
(preEval [ ../../examples/minimal/arion-compose.nix ]).config.out.dockerComposeYaml
|
||||||
(preEval [ ../../examples/full-nixos/arion-compose.nix ]).config.build.dockerComposeYaml
|
(preEval [ ../../examples/full-nixos/arion-compose.nix ]).config.out.dockerComposeYaml
|
||||||
(preEval [ ../../examples/nixos-unit/arion-compose.nix ]).config.build.dockerComposeYaml
|
(preEval [ ../../examples/nixos-unit/arion-compose.nix ]).config.out.dockerComposeYaml
|
||||||
pkgs.stdenv
|
pkgs.stdenv
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in a new issue