153: Add service.healthcheck and extend service.depends_on r=roberth a=t4ccer

Add option to define custom health checks for services, and extend `depends_on` so it can also include `<service>.condition` field for conditions based on health checks.

Co-authored-by: t4ccer <t4ccer@gmail.com>
This commit is contained in:
bors[bot] 2022-05-18 17:12:19 +00:00 committed by GitHub
commit bd3e2fe4e3
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 187 additions and 7 deletions

View file

@ -1,5 +1,15 @@
# Revision history for Arion # Revision history for Arion
## Next
### Changed
* Healthcheck-based dependencies in `service.depends_on`.
### Added
* Support `service.healthcheck` for defining custom healthchecks.
## 0.1.3.0 -- 2020-05-03 ## 0.1.3.0 -- 2020-05-03
### Changed ### Changed

View file

@ -514,7 +514,7 @@ See link:https://docs.docker.com/compose/compose-file/#depends_on[Docker Compose
[discrete] [discrete]
=== details === details
Type:: list of strings Type:: list of strings or attribute set of submodules
Default:: Default::
+ +
---- ----
@ -668,6 +668,123 @@ Default::
No Example:: {blank} No Example:: {blank}
== services.<name>.service.healthcheck
None
[discrete]
=== details
Type:: submodule
No Default:: {blank}
No Example:: {blank}
== services.<name>.service.healthcheck.interval
See link:https://docs.docker.com/compose/compose-file/#healthcheck[Docker Compose#healthcheck]
[discrete]
=== details
Type:: string
Default::
+
----
"30s"
----
Example::
+
----
"1m"
----
== services.<name>.service.healthcheck.retries
See link:https://docs.docker.com/compose/compose-file/#healthcheck[Docker Compose#healthcheck]
[discrete]
=== details
Type:: signed integer
Default::
+
----
3
----
No Example:: {blank}
== services.<name>.service.healthcheck.start_period
See link:https://docs.docker.com/compose/compose-file/#healthcheck[Docker Compose#healthcheck]
[discrete]
=== details
Type:: string
Default::
+
----
"0s"
----
Example::
+
----
"30s"
----
== services.<name>.service.healthcheck.test
See link:https://docs.docker.com/compose/compose-file/#healthcheck[Docker Compose#healthcheck]
[discrete]
=== details
Type:: null or list of strings
Default::
+
----
null
----
Example::
+
----
["CMD","pg_isready"]
----
== services.<name>.service.healthcheck.timeout
See link:https://docs.docker.com/compose/compose-file/#healthcheck[Docker Compose#healthcheck]
[discrete]
=== details
Type:: string
Default::
+
----
"30s"
----
Example::
+
----
"10s"
----
== services.<name>.service.hostStoreAsReadOnly == services.<name>.service.hostStoreAsReadOnly
Adds a ':ro' (read-only) access mode to the host nix store bind mount. Adds a ':ro' (read-only) access mode to the host nix store bind mount.

View file

@ -4,11 +4,11 @@
the user-facing options service.image, service.volumes, etc. the user-facing options service.image, service.volumes, etc.
*/ */
{ pkgs, lib, config, ... }: { pkgs, lib, config, options, ... }:
let let
inherit (lib) mkOption types; inherit (lib) mkOption types;
inherit (types) listOf nullOr attrsOf str either int bool; inherit (types) listOf nullOr attrsOf str either int bool submodule enum;
link = url: text: link = url: text:
''link:${url}[${text}]''; ''link:${url}[${text}]'';
@ -100,11 +100,62 @@ in
default = null; default = null;
description = dockerComposeRef "container_name"; description = dockerComposeRef "container_name";
}; };
service.depends_on = mkOption { service.depends_on =
type = listOf str; let conditionsModule = {
options = {
condition = mkOption {
type = enum ["service_started" "service_healthy" "service_completed_successfully"];
description = dockerComposeRef "depends_on";
default = "service_started";
};
};
};
in mkOption {
type = either (listOf str) (attrsOf (submodule conditionsModule));
default = []; default = [];
description = dockerComposeRef "depends_on"; description = dockerComposeRef "depends_on";
}; };
service.healthcheck = mkOption {
type = submodule ({ config, options, ...}: {
options = {
_out = mkOption {
internal = true;
default = lib.optionalAttrs (options.test.highestPrio < 1500) {
inherit (config) test interval timeout start_period retries;
};
};
test = mkOption {
type = nullOr (listOf str);
default = null;
example = [ "CMD" "pg_isready" ];
description = dockerComposeRef "healthcheck";
};
interval = mkOption {
type = str;
default = "30s";
example = "1m";
description = dockerComposeRef "healthcheck";
};
timeout = mkOption {
type = str;
default = "30s";
example = "10s";
description = dockerComposeRef "healthcheck";
};
start_period = mkOption {
type = str;
default = "0s";
example = "30s";
description = dockerComposeRef "healthcheck";
};
retries = mkOption {
type = int;
default = 3;
description = dockerComposeRef "healthcheck";
};
};
});
};
service.devices = mkOption { service.devices = mkOption {
type = listOf str; type = listOf str;
default = []; default = [];
@ -250,6 +301,8 @@ in
inherit (config.service) container_name; inherit (config.service) container_name;
} // lib.optionalAttrs (config.service.depends_on != []) { } // lib.optionalAttrs (config.service.depends_on != []) {
inherit (config.service) depends_on; inherit (config.service) depends_on;
} // lib.optionalAttrs (options.service.healthcheck.highestPrio < 1500) {
healthcheck = config.service.healthcheck._out;
} // lib.optionalAttrs (config.service.devices != []) { } // lib.optionalAttrs (config.service.devices != []) {
inherit (config.service) devices; inherit (config.service) devices;
} // lib.optionalAttrs (config.service.entrypoint != null) { } // lib.optionalAttrs (config.service.entrypoint != null) {