Compare commits
2 commits
main
...
compose-sp
Author | SHA1 | Date | |
---|---|---|---|
|
c2e7db488e | ||
|
43b28c9b29 |
21 changed files with 66 additions and 244 deletions
2
.gitignore
vendored
2
.gitignore
vendored
|
@ -5,5 +5,3 @@ dist/
|
|||
dist-newstyle/
|
||||
cabal.project.local
|
||||
|
||||
*.swp
|
||||
|
||||
|
|
13
CHANGELOG.md
13
CHANGELOG.md
|
@ -1,18 +1,5 @@
|
|||
# Revision history for Arion
|
||||
|
||||
## 0.2.1.0 -- 2023-07-26
|
||||
|
||||
### Added
|
||||
|
||||
* `service.networks` now supports attribute set values with various options, thanks to @pedorich-n.
|
||||
* `docker-compose.volumes` can now be specified in multiple modules, thanks to @qaifshaikh.
|
||||
* `image.fakeRootCommands` for making modifications to the image that aren't "add a link farm".
|
||||
|
||||
### Fixed
|
||||
|
||||
* Regular maintenance fixes, including one by olebedev
|
||||
|
||||
|
||||
## 0.2.0.0 -- 2022-12-02
|
||||
|
||||
### BREAKING
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
cabal-version: 2.4
|
||||
|
||||
name: arion-compose
|
||||
version: 0.2.1.0
|
||||
version: 0.2.0.0
|
||||
synopsis: Run docker-compose with help from Nix/NixOS
|
||||
description: Arion is a tool for building and running applications that consist of multiple docker containers using NixOS modules. It has special support for docker images that are built with Nix, for a smooth development experience and improved performance.
|
||||
homepage: https://github.com/hercules-ci/arion#readme
|
||||
|
@ -30,7 +30,7 @@ source-repository head
|
|||
location: https://github.com/hercules-ci/arion
|
||||
|
||||
common common
|
||||
build-depends: base >=4.12.0.0 && <4.99
|
||||
build-depends: base >=4.12.0.0 && <4.17
|
||||
, aeson >=2
|
||||
, aeson-pretty
|
||||
, async
|
||||
|
|
|
@ -45,21 +45,18 @@ NOTE: This deployment method does NOT use an `arion-pkgs.nix` file, but reuses
|
|||
# Pick one of:
|
||||
# - niv
|
||||
((import ./nix/sources.nix).arion + "/nixos-module.nix")
|
||||
# - or flakes (where arion is a flake input)
|
||||
# - flakes (where arion is a flake input)
|
||||
arion.nixosModules.arion
|
||||
# - or other: copy commit hash of arion and replace HASH in:
|
||||
(builtins.fetchTarball "https://github.com/hercules-ci/arion/archive/HASH.tar.gz") + "/nixos-module.nix")
|
||||
# - other
|
||||
arionPath + "/nixos-module.nix")
|
||||
];
|
||||
|
||||
virtualisation.arion = {
|
||||
backend = "podman-socket"; # or "docker"
|
||||
projects.example = {
|
||||
serviceName = "example"; # optional systemd service name, defaults to arion-example in this case
|
||||
settings = {
|
||||
# Specify you project here, or import it from a file.
|
||||
# NOTE: This does NOT use ./arion-pkgs.nix, but defaults to NixOS' pkgs.
|
||||
imports = [ ./arion-compose.nix ];
|
||||
};
|
||||
projects.example.settings = {
|
||||
# Specify you project here, or import it from a file.
|
||||
# NOTE: This does NOT use ./arion-pkgs.nix, but defaults to NixOS' pkgs.
|
||||
imports = [ ./arion-compose.nix ];
|
||||
};
|
||||
};
|
||||
}
|
||||
|
|
|
@ -148,7 +148,7 @@ Describe containers using NixOS-style modules. There are a few options:
|
|||
project.name = "full-nixos";
|
||||
services.webserver = { pkgs, lib, ... }: {
|
||||
nixos.useSystemd = true;
|
||||
nixos.configuration.boot.tmp.useTmpfs = true;
|
||||
nixos.configuration.boot.tmpOnTmpfs = true;
|
||||
nixos.configuration.services.nginx.enable = true;
|
||||
nixos.configuration.services.nginx.virtualHosts.localhost.root = "${pkgs.nix.doc}/share/doc/nix/manual";
|
||||
nixos.configuration.services.nscd.enable = false;
|
||||
|
|
|
@ -2,8 +2,7 @@
|
|||
project.name = "full-nixos";
|
||||
services.webserver = { pkgs, lib, ... }: {
|
||||
nixos.useSystemd = true;
|
||||
nixos.configuration.boot.tmp.useTmpfs = true;
|
||||
nixos.configuration.networking.useDHCP = false;
|
||||
nixos.configuration.boot.tmpOnTmpfs = true;
|
||||
nixos.configuration.services.nginx.enable = true;
|
||||
nixos.configuration.services.nginx.virtualHosts.localhost.root = "${pkgs.nix.doc}/share/doc/nix/manual";
|
||||
nixos.configuration.services.nscd.enable = false;
|
||||
|
|
54
flake.lock
54
flake.lock
|
@ -7,11 +7,11 @@
|
|||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1722555600,
|
||||
"narHash": "sha256-XOQkdLafnb/p9ij77byFQjDf5m5QYl9b2REiVClC+x4=",
|
||||
"lastModified": 1675933616,
|
||||
"narHash": "sha256-/rczJkJHtx16IFxMmAWu5nNYcSXNg1YYXTHoGjLrLUA=",
|
||||
"owner": "hercules-ci",
|
||||
"repo": "flake-parts",
|
||||
"rev": "8471fe90ad337a8074e957b69ca4d0089218391d",
|
||||
"rev": "47478a4a003e745402acf63be7f9a092d51b83d7",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
@ -20,26 +20,6 @@
|
|||
"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,
|
||||
|
@ -56,34 +36,13 @@
|
|||
"type": "github"
|
||||
}
|
||||
},
|
||||
"hercules-ci-effects": {
|
||||
"inputs": {
|
||||
"flake-parts": "flake-parts_2",
|
||||
"nixpkgs": [
|
||||
"nixpkgs"
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1719226092,
|
||||
"narHash": "sha256-YNkUMcCUCpnULp40g+svYsaH1RbSEj6s4WdZY/SHe38=",
|
||||
"owner": "hercules-ci",
|
||||
"repo": "hercules-ci-effects",
|
||||
"rev": "11e4b8dc112e2f485d7c97e1cee77f9958f498f5",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "hercules-ci",
|
||||
"repo": "hercules-ci-effects",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nixpkgs": {
|
||||
"locked": {
|
||||
"lastModified": 1722630782,
|
||||
"narHash": "sha256-hMyG9/WlUi0Ho9VkRrrez7SeNlDzLxalm9FwY7n/Noo=",
|
||||
"lastModified": 1676300157,
|
||||
"narHash": "sha256-1HjRzfp6LOLfcj/HJHdVKWAkX9QRAouoh6AjzJiIerU=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "d04953086551086b44b6f3c6b7eeb26294f207da",
|
||||
"rev": "545c7a31e5dedea4a6d372712a18e00ce097d462",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
@ -97,7 +56,6 @@
|
|||
"inputs": {
|
||||
"flake-parts": "flake-parts",
|
||||
"haskell-flake": "haskell-flake",
|
||||
"hercules-ci-effects": "hercules-ci-effects",
|
||||
"nixpkgs": "nixpkgs"
|
||||
}
|
||||
}
|
||||
|
|
32
flake.nix
32
flake.nix
|
@ -6,15 +6,12 @@
|
|||
haskell-flake.url = "github:srid/haskell-flake/0.1.0";
|
||||
flake-parts.url = "github:hercules-ci/flake-parts";
|
||||
flake-parts.inputs.nixpkgs-lib.follows = "nixpkgs";
|
||||
hercules-ci-effects.url = "github:hercules-ci/hercules-ci-effects";
|
||||
hercules-ci-effects.inputs.nixpkgs.follows = "nixpkgs";
|
||||
};
|
||||
|
||||
outputs = inputs@{ self, flake-parts, ... }:
|
||||
flake-parts.lib.mkFlake { inherit inputs; } ({ config, lib, extendModules, ... }: {
|
||||
imports = [
|
||||
inputs.haskell-flake.flakeModule
|
||||
inputs.hercules-ci-effects.flakeModule
|
||||
inputs.flake-parts.flakeModules.easyOverlay
|
||||
./docs/flake-module.nix
|
||||
./tests/flake-module.nix
|
||||
|
@ -66,26 +63,15 @@
|
|||
];
|
||||
});
|
||||
};
|
||||
|
||||
hercules-ci.flake-update = {
|
||||
enable = true;
|
||||
autoMergeMethod = "merge";
|
||||
when = {
|
||||
hour = [ 2 ];
|
||||
dayOfMonth = [ 5 ];
|
||||
};
|
||||
};
|
||||
|
||||
herculesCI.ciSystems = [
|
||||
# "aarch64-darwin"
|
||||
# "aarch64-linux"
|
||||
"x86_64-darwin"
|
||||
"x86_64-linux"
|
||||
];
|
||||
|
||||
flake = {
|
||||
debug = { inherit inputs config lib; };
|
||||
|
||||
defaultPackage =
|
||||
lib.mapAttrs
|
||||
(ps: lib.warn "arion.defaultPackage has been removed in favor of arion.packages.\${system}.default"
|
||||
ps.default)
|
||||
config.flake.packages;
|
||||
|
||||
lib = {
|
||||
eval = import ./src/nix/eval-composition.nix;
|
||||
build = args@{ ... }:
|
||||
|
@ -93,6 +79,12 @@
|
|||
in composition.config.out.dockerComposeYaml;
|
||||
};
|
||||
nixosModules.arion = ./nixos-module.nix;
|
||||
herculesCI.ciSystems = [
|
||||
# "aarch64-darwin"
|
||||
# "aarch64-linux"
|
||||
"x86_64-darwin"
|
||||
"x86_64-linux"
|
||||
];
|
||||
};
|
||||
});
|
||||
}
|
||||
|
|
|
@ -26,14 +26,9 @@ let
|
|||
visible = "shallow";
|
||||
};
|
||||
_systemd = mkOption { internal = true; };
|
||||
serviceName = mkOption {
|
||||
description = "The name of the Arion project's systemd service";
|
||||
type = types.str;
|
||||
default = "arion-${name}";
|
||||
};
|
||||
};
|
||||
config = {
|
||||
_systemd.services.${config.serviceName} = {
|
||||
_systemd.services."arion-${name}" = {
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
after = [ "sockets.target" ];
|
||||
|
||||
|
|
|
@ -3,4 +3,4 @@
|
|||
# For manual testing of a hacked arion built via Nix.
|
||||
# Works when called from outside the project directory.
|
||||
|
||||
exec nix run -f "$(dirname ${BASH_SOURCE[0]})" arion "$@"
|
||||
exec nix run -f "$(dirname ${BASH_SOURCE[0]})" arion -c arion "$@"
|
||||
|
|
|
@ -13,34 +13,19 @@ import qualified Data.Text as T
|
|||
import qualified Data.Text.IO as T
|
||||
|
||||
spec :: Spec
|
||||
spec = describe "evaluateComposition" $ do
|
||||
it "matches an example" $ do
|
||||
x <- Arion.Nix.evaluateComposition EvaluationArgs
|
||||
{ evalUid = 123
|
||||
, evalModules = NEL.fromList
|
||||
["src/haskell/testdata/Arion/NixSpec/arion-compose.nix"]
|
||||
, evalPkgs = "import <nixpkgs> { system = \"x86_64-linux\"; }"
|
||||
, evalWorkDir = Nothing
|
||||
, evalMode = ReadOnly
|
||||
, evalUserArgs = ["--show-trace"]
|
||||
}
|
||||
let actual = pretty x
|
||||
expected <- T.readFile "src/haskell/testdata/Arion/NixSpec/arion-compose.json"
|
||||
censorPaths actual `shouldBe` censorPaths expected
|
||||
|
||||
it "matches an build.context example" $ do
|
||||
x <- Arion.Nix.evaluateComposition EvaluationArgs
|
||||
{ evalUid = 1234
|
||||
, evalModules = NEL.fromList
|
||||
["src/haskell/testdata/Arion/NixSpec/arion-context-compose.nix"]
|
||||
, evalPkgs = "import <nixpkgs> { system = \"x86_64-linux\"; }"
|
||||
, evalWorkDir = Nothing
|
||||
, evalMode = ReadOnly
|
||||
, evalUserArgs = ["--show-trace"]
|
||||
}
|
||||
let actual = pretty x
|
||||
expected <- T.readFile "src/haskell/testdata/Arion/NixSpec/arion-context-compose.json"
|
||||
censorPaths actual `shouldBe` censorPaths expected
|
||||
spec = describe "evaluateComposition" $ it "matches an example" $ do
|
||||
x <- Arion.Nix.evaluateComposition EvaluationArgs
|
||||
{ evalUid = 123
|
||||
, evalModules = NEL.fromList
|
||||
["src/haskell/testdata/Arion/NixSpec/arion-compose.nix"]
|
||||
, evalPkgs = "import <nixpkgs> { system = \"x86_64-linux\"; }"
|
||||
, evalWorkDir = Nothing
|
||||
, evalMode = ReadOnly
|
||||
, evalUserArgs = ["--show-trace"]
|
||||
}
|
||||
let actual = pretty x
|
||||
expected <- T.readFile "src/haskell/testdata/Arion/NixSpec/arion-compose.json"
|
||||
censorPaths actual `shouldBe` censorPaths expected
|
||||
|
||||
censorPaths :: Text -> Text
|
||||
censorPaths = censorImages . censorStorePaths
|
||||
|
|
|
@ -9,4 +9,3 @@ import qualified Arion.NixSpec
|
|||
spec :: Spec
|
||||
spec = do
|
||||
describe "Arion.Nix" Arion.NixSpec.spec
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
project.name = "unit-test-data";
|
||||
services.webserver = { pkgs, ... }: {
|
||||
nixos.useSystemd = true;
|
||||
nixos.configuration.boot.tmp.useTmpfs = true;
|
||||
nixos.configuration.boot.tmpOnTmpfs = true;
|
||||
nixos.configuration.services.nginx.enable = true;
|
||||
nixos.configuration.services.nginx.virtualHosts.localhost.root = "${pkgs.nix.doc}/share/doc/nix/manual";
|
||||
service.useHostStore = true;
|
||||
|
|
|
@ -1,41 +0,0 @@
|
|||
{
|
||||
"networks": {
|
||||
"default": {
|
||||
"name": "unit-test-data"
|
||||
}
|
||||
},
|
||||
"services": {
|
||||
"webserver": {
|
||||
"build": {
|
||||
"context": "<STOREPATH>"
|
||||
},
|
||||
"environment": {},
|
||||
"ports": [
|
||||
"8080:80"
|
||||
],
|
||||
"sysctls": {},
|
||||
"volumes": []
|
||||
}
|
||||
},
|
||||
"version": "3.4",
|
||||
"volumes": {},
|
||||
"x-arion": {
|
||||
"images": [
|
||||
{
|
||||
"imageExe": "<STOREPATH>",
|
||||
"imageName": "localhost/webserver",
|
||||
"imageTag": "<HASH>"
|
||||
}
|
||||
],
|
||||
"project": {
|
||||
"name": "unit-test-data"
|
||||
},
|
||||
"serviceInfo": {
|
||||
"webserver": {
|
||||
"defaultExec": [
|
||||
"/bin/sh"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,9 +0,0 @@
|
|||
{
|
||||
project.name = "unit-test-data";
|
||||
services.webserver.service = {
|
||||
build.context = "${./build-context}";
|
||||
ports = [
|
||||
"8080:80"
|
||||
];
|
||||
};
|
||||
}
|
|
@ -1,4 +0,0 @@
|
|||
FROM nginx
|
||||
|
||||
RUN echo this is a dockerfile to be built
|
||||
|
|
@ -66,22 +66,6 @@ in
|
|||
https://docs.docker.com/compose/compose-file/build/#context
|
||||
'';
|
||||
};
|
||||
service.build.dockerfile = mkOption {
|
||||
type = nullOr str;
|
||||
default = null;
|
||||
description = ''
|
||||
Sets an alternate Dockerfile. A relative path is resolved from the build context.
|
||||
https://docs.docker.com/compose/compose-file/build/#dockerfile
|
||||
'';
|
||||
};
|
||||
service.build.target = mkOption {
|
||||
type = nullOr str;
|
||||
default = null;
|
||||
description = ''
|
||||
Defines the stage to build as defined inside a multi-stage Dockerfile.
|
||||
https://docs.docker.com/compose/compose-file/build/#target
|
||||
'';
|
||||
};
|
||||
service.hostname = mkOption {
|
||||
type = nullOr str;
|
||||
default = null;
|
||||
|
@ -102,8 +86,7 @@ in
|
|||
description = serviceRef "environment";
|
||||
};
|
||||
service.image = mkOption {
|
||||
type = nullOr str;
|
||||
default = null;
|
||||
type = str;
|
||||
description = serviceRef "image";
|
||||
};
|
||||
service.command = mkOption {
|
||||
|
@ -210,11 +193,6 @@ in
|
|||
default = [];
|
||||
description = serviceRef "external_links";
|
||||
};
|
||||
service.profiles = mkOption {
|
||||
type = listOf str;
|
||||
default = [];
|
||||
description = serviceRef "profiles";
|
||||
};
|
||||
service.extra_hosts = mkOption {
|
||||
type = listOf str;
|
||||
default = [];
|
||||
|
@ -318,11 +296,6 @@ in
|
|||
default = null;
|
||||
description = serviceRef "stop_signal";
|
||||
};
|
||||
service.stop_grace_period = mkOption {
|
||||
type = nullOr str;
|
||||
default = null;
|
||||
description = serviceRef "stop_grace_period";
|
||||
};
|
||||
service.sysctls = mkOption {
|
||||
type = attrsOf (either str int);
|
||||
default = {};
|
||||
|
@ -355,11 +328,10 @@ in
|
|||
volumes
|
||||
environment
|
||||
sysctls
|
||||
image
|
||||
;
|
||||
} // lib.optionalAttrs (config.service.image != null) {
|
||||
inherit (config.service) image;
|
||||
} // lib.optionalAttrs (config.service.build.context != null ) {
|
||||
build = lib.filterAttrs (n: v: v != null) config.service.build;
|
||||
} // lib.optionalAttrs (config.service.build.context != null) {
|
||||
inherit (config.service) build;
|
||||
} // lib.optionalAttrs (cap_add != []) {
|
||||
inherit cap_add;
|
||||
} // lib.optionalAttrs (cap_drop != []) {
|
||||
|
@ -406,8 +378,6 @@ in
|
|||
inherit (config.service) restart;
|
||||
} // lib.optionalAttrs (config.service.stop_signal != null) {
|
||||
inherit (config.service) stop_signal;
|
||||
} // lib.optionalAttrs (config.service.stop_grace_period != null) {
|
||||
inherit (config.service) stop_grace_period;
|
||||
} // lib.optionalAttrs (config.service.tmpfs != []) {
|
||||
inherit (config.service) tmpfs;
|
||||
} // lib.optionalAttrs (config.service.tty != null) {
|
||||
|
@ -416,7 +386,5 @@ in
|
|||
inherit (config.service) working_dir;
|
||||
} // lib.optionalAttrs (config.service.user != null) {
|
||||
inherit (config.service) user;
|
||||
} // lib.optionalAttrs (config.service.profiles != []) {
|
||||
inherit (config.service) profiles;
|
||||
};
|
||||
}
|
||||
|
|
|
@ -163,19 +163,17 @@ in
|
|||
'';
|
||||
};
|
||||
};
|
||||
config = lib.mkMerge [{
|
||||
build.image = builtImage;
|
||||
build.imageName = config.build.image.imageName;
|
||||
build.imageTag =
|
||||
if config.build.image.imageTag != ""
|
||||
then config.build.image.imageTag
|
||||
else lib.head (lib.strings.splitString "-" (baseNameOf config.build.image.outPath));
|
||||
image.rawConfig.Cmd = config.image.command;
|
||||
image.nixBuild = lib.mkDefault (priorityIsDefault options.service.image);
|
||||
}
|
||||
( lib.mkIf (config.service.build.context == null)
|
||||
{
|
||||
service.image = lib.mkDefault "${config.build.imageName}:${config.build.imageTag}";
|
||||
})
|
||||
];
|
||||
config = {
|
||||
build.image = builtImage;
|
||||
build.imageName = config.build.image.imageName;
|
||||
build.imageTag =
|
||||
if config.build.image.imageTag != ""
|
||||
then config.build.image.imageTag
|
||||
else lib.head (lib.strings.splitString "-" (baseNameOf config.build.image.outPath));
|
||||
|
||||
service.image = lib.mkDefault "${config.build.imageName}:${config.build.imageTag}";
|
||||
image.rawConfig.Cmd = config.image.command;
|
||||
|
||||
image.nixBuild = lib.mkDefault (priorityIsDefault options.service.image);
|
||||
};
|
||||
}
|
||||
|
|
|
@ -39,7 +39,7 @@ in
|
|||
service.tmpfs = [
|
||||
"/run" # noexec is fine because exes should be symlinked from elsewhere anyway
|
||||
"/run/wrappers" # noexec breaks this intentionally
|
||||
] ++ lib.optional (config.nixos.evaluatedConfig.boot.tmp.useTmpfs) "/tmp:exec,mode=777";
|
||||
] ++ lib.optional (config.nixos.evaluatedConfig.boot.tmpOnTmpfs) "/tmp:exec,mode=777";
|
||||
|
||||
service.stop_signal = "SIGRTMIN+3";
|
||||
service.tty = true;
|
||||
|
|
|
@ -29,7 +29,7 @@ in
|
|||
enable = true;
|
||||
dockerSocket.enable = true;
|
||||
};
|
||||
|
||||
|
||||
# no caches, because no internet
|
||||
nix.settings.substituters = lib.mkForce [];
|
||||
|
||||
|
@ -45,7 +45,7 @@ in
|
|||
pkgs.stdenv
|
||||
];
|
||||
|
||||
virtualisation.memorySize = 2048;
|
||||
virtualisation.memorySize = 1024;
|
||||
virtualisation.diskSize = 8000;
|
||||
};
|
||||
testScript = ''
|
||||
|
|
|
@ -4,7 +4,7 @@ pkgs.nixosTest {
|
|||
name = "test-basic-arion-kafka";
|
||||
nodes = {
|
||||
machine = { ... }: {
|
||||
virtualisation.memorySize = 4096;
|
||||
virtualisation.memorySize = 3000;
|
||||
virtualisation.diskSize = 10000;
|
||||
imports = [
|
||||
../../nixos-module.nix
|
||||
|
|
Loading…
Reference in a new issue