{ config, pkgs, lib, ... }: let cfg = config.services.lifecycled; # TODO: Add the ability to extend this with an rfc 42-like interface. # In the meantime, one can modify the environment (as # long as it's not overriding anything from here) with # systemd.services.lifecycled.serviceConfig.Environment configFile = pkgs.writeText "lifecycled" '' LIFECYCLED_HANDLER=${cfg.handler} ${lib.optionalString (cfg.cloudwatchGroup != null) "LIFECYCLED_CLOUDWATCH_GROUP=${cfg.cloudwatchGroup}"} ${lib.optionalString (cfg.cloudwatchStream != null) "LIFECYCLED_CLOUDWATCH_STREAM=${cfg.cloudwatchStream}"} ${lib.optionalString cfg.debug "LIFECYCLED_DEBUG=${lib.boolToString cfg.debug}"} ${lib.optionalString (cfg.instanceId != null) "LIFECYCLED_INSTANCE_ID=${cfg.instanceId}"} ${lib.optionalString cfg.json "LIFECYCLED_JSON=${lib.boolToString cfg.json}"} ${lib.optionalString cfg.noSpot "LIFECYCLED_NO_SPOT=${lib.boolToString cfg.noSpot}"} ${lib.optionalString (cfg.snsTopic != null) "LIFECYCLED_SNS_TOPIC=${cfg.snsTopic}"} ${lib.optionalString (cfg.awsRegion != null) "AWS_REGION=${cfg.awsRegion}"} ''; in { meta.maintainers = with lib.maintainers; [ cole-h grahamc ]; options = { services.lifecycled = { enable = lib.mkEnableOption "lifecycled, a daemon for responding to AWS AutoScaling Lifecycle Hooks"; queueCleaner = { enable = lib.mkEnableOption "lifecycled-queue-cleaner"; frequency = lib.mkOption { type = lib.types.str; default = "hourly"; description = '' How often to trigger the queue cleaner. NOTE: This string should be a valid value for a systemd timer's `OnCalendar` configuration. See {manpage}`systemd.timer(5)` for more information. ''; }; parallel = lib.mkOption { type = lib.types.ints.unsigned; default = 20; description = '' The number of parallel deletes to run. ''; }; }; instanceId = lib.mkOption { type = lib.types.nullOr lib.types.str; default = null; description = '' The instance ID to listen for events for. ''; }; snsTopic = lib.mkOption { type = lib.types.nullOr lib.types.str; default = null; description = '' The SNS topic that receives events. ''; }; noSpot = lib.mkOption { type = lib.types.bool; default = false; description = '' Disable the spot termination listener. ''; }; handler = lib.mkOption { type = lib.types.path; description = '' The script to invoke to handle events. ''; }; json = lib.mkOption { type = lib.types.bool; default = false; description = '' Enable JSON logging. ''; }; cloudwatchGroup = lib.mkOption { type = lib.types.nullOr lib.types.str; default = null; description = '' Write logs to a specific Cloudwatch Logs group. ''; }; cloudwatchStream = lib.mkOption { type = lib.types.nullOr lib.types.str; default = null; description = '' Write logs to a specific Cloudwatch Logs stream. Defaults to the instance ID. ''; }; debug = lib.mkOption { type = lib.types.bool; default = false; description = '' Enable debugging information. ''; }; # XXX: Can be removed if / when # https://github.com/buildkite/lifecycled/pull/91 is merged. awsRegion = lib.mkOption { type = lib.types.nullOr lib.types.str; default = null; description = '' The region used for accessing AWS services. ''; }; }; }; ### Implementation ### config = lib.mkMerge [ (lib.mkIf cfg.enable { environment.etc."lifecycled".source = configFile; systemd.packages = [ pkgs.lifecycled ]; systemd.services.lifecycled = { wantedBy = [ "network-online.target" ]; restartTriggers = [ configFile ]; }; }) (lib.mkIf cfg.queueCleaner.enable { systemd.services.lifecycled-queue-cleaner = { description = "Lifecycle Daemon Queue Cleaner"; environment = lib.optionalAttrs (cfg.awsRegion != null) { AWS_REGION = cfg.awsRegion; }; serviceConfig = { Type = "oneshot"; ExecStart = "${pkgs.lifecycled}/bin/lifecycled-queue-cleaner -parallel ${toString cfg.queueCleaner.parallel}"; }; }; systemd.timers.lifecycled-queue-cleaner = { description = "Lifecycle Daemon Queue Cleaner Timer"; wantedBy = [ "timers.target" ]; after = [ "network-online.target" ]; timerConfig = { Unit = "lifecycled-queue-cleaner.service"; OnCalendar = "${cfg.queueCleaner.frequency}"; }; }; }) ]; }