1{ config, pkgs, lib, ... }:
2
3with lib;
4let
5 cfg = config.services.lifecycled;
6
7 # TODO: Add the ability to extend this with an rfc 42-like interface.
8 # In the meantime, one can modify the environment (as
9 # long as it's not overriding anything from here) with
10 # systemd.services.lifecycled.serviceConfig.Environment
11 configFile = pkgs.writeText "lifecycled" ''
12 LIFECYCLED_HANDLER=${cfg.handler}
13 ${lib.optionalString (cfg.cloudwatchGroup != null) "LIFECYCLED_CLOUDWATCH_GROUP=${cfg.cloudwatchGroup}"}
14 ${lib.optionalString (cfg.cloudwatchStream != null) "LIFECYCLED_CLOUDWATCH_STREAM=${cfg.cloudwatchStream}"}
15 ${lib.optionalString cfg.debug "LIFECYCLED_DEBUG=${lib.boolToString cfg.debug}"}
16 ${lib.optionalString (cfg.instanceId != null) "LIFECYCLED_INSTANCE_ID=${cfg.instanceId}"}
17 ${lib.optionalString cfg.json "LIFECYCLED_JSON=${lib.boolToString cfg.json}"}
18 ${lib.optionalString cfg.noSpot "LIFECYCLED_NO_SPOT=${lib.boolToString cfg.noSpot}"}
19 ${lib.optionalString (cfg.snsTopic != null) "LIFECYCLED_SNS_TOPIC=${cfg.snsTopic}"}
20 ${lib.optionalString (cfg.awsRegion != null) "AWS_REGION=${cfg.awsRegion}"}
21 '';
22in
23{
24 meta.maintainers = with maintainers; [ cole-h grahamc ];
25
26 options = {
27 services.lifecycled = {
28 enable = mkEnableOption (lib.mdDoc "lifecycled");
29
30 queueCleaner = {
31 enable = mkEnableOption (lib.mdDoc "lifecycled-queue-cleaner");
32
33 frequency = mkOption {
34 type = types.str;
35 default = "hourly";
36 description = lib.mdDoc ''
37 How often to trigger the queue cleaner.
38
39 NOTE: This string should be a valid value for a systemd
40 timer's `OnCalendar` configuration. See
41 {manpage}`systemd.timer(5)`
42 for more information.
43 '';
44 };
45
46 parallel = mkOption {
47 type = types.ints.unsigned;
48 default = 20;
49 description = lib.mdDoc ''
50 The number of parallel deletes to run.
51 '';
52 };
53 };
54
55 instanceId = mkOption {
56 type = types.nullOr types.str;
57 default = null;
58 description = lib.mdDoc ''
59 The instance ID to listen for events for.
60 '';
61 };
62
63 snsTopic = mkOption {
64 type = types.nullOr types.str;
65 default = null;
66 description = lib.mdDoc ''
67 The SNS topic that receives events.
68 '';
69 };
70
71 noSpot = mkOption {
72 type = types.bool;
73 default = false;
74 description = lib.mdDoc ''
75 Disable the spot termination listener.
76 '';
77 };
78
79 handler = mkOption {
80 type = types.path;
81 description = lib.mdDoc ''
82 The script to invoke to handle events.
83 '';
84 };
85
86 json = mkOption {
87 type = types.bool;
88 default = false;
89 description = lib.mdDoc ''
90 Enable JSON logging.
91 '';
92 };
93
94 cloudwatchGroup = mkOption {
95 type = types.nullOr types.str;
96 default = null;
97 description = lib.mdDoc ''
98 Write logs to a specific Cloudwatch Logs group.
99 '';
100 };
101
102 cloudwatchStream = mkOption {
103 type = types.nullOr types.str;
104 default = null;
105 description = lib.mdDoc ''
106 Write logs to a specific Cloudwatch Logs stream. Defaults to the instance ID.
107 '';
108 };
109
110 debug = mkOption {
111 type = types.bool;
112 default = false;
113 description = lib.mdDoc ''
114 Enable debugging information.
115 '';
116 };
117
118 # XXX: Can be removed if / when
119 # https://github.com/buildkite/lifecycled/pull/91 is merged.
120 awsRegion = mkOption {
121 type = types.nullOr types.str;
122 default = null;
123 description = lib.mdDoc ''
124 The region used for accessing AWS services.
125 '';
126 };
127 };
128 };
129
130 ### Implementation ###
131
132 config = mkMerge [
133 (mkIf cfg.enable {
134 environment.etc."lifecycled".source = configFile;
135
136 systemd.packages = [ pkgs.lifecycled ];
137 systemd.services.lifecycled = {
138 wantedBy = [ "network-online.target" ];
139 restartTriggers = [ configFile ];
140 };
141 })
142
143 (mkIf cfg.queueCleaner.enable {
144 systemd.services.lifecycled-queue-cleaner = {
145 description = "Lifecycle Daemon Queue Cleaner";
146 environment = optionalAttrs (cfg.awsRegion != null) { AWS_REGION = cfg.awsRegion; };
147 serviceConfig = {
148 Type = "oneshot";
149 ExecStart = "${pkgs.lifecycled}/bin/lifecycled-queue-cleaner -parallel ${toString cfg.queueCleaner.parallel}";
150 };
151 };
152
153 systemd.timers.lifecycled-queue-cleaner = {
154 description = "Lifecycle Daemon Queue Cleaner Timer";
155 wantedBy = [ "timers.target" ];
156 after = [ "network-online.target" ];
157 timerConfig = {
158 Unit = "lifecycled-queue-cleaner.service";
159 OnCalendar = "${cfg.queueCleaner.frequency}";
160 };
161 };
162 })
163 ];
164}