Skip to content

Commit 5c9d3a1

Browse files
committed
WIP Add NixOS module
TODO: - [ ] NixOS/nixpkgs#143207 - [ ] switch to master or nixos-unstable with niv
1 parent ee331fa commit 5c9d3a1

12 files changed

Lines changed: 562 additions & 6 deletions

File tree

flake.nix

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,5 +38,10 @@
3838
in composition.config.out.dockerComposeYaml;
3939
};
4040

41+
nixosModules.arion = {
42+
imports = [ ./nixos-module.nix ];
43+
disabledModules = [ "virtualisation/arion.nix" ];
44+
};
45+
4146
};
4247
}

nix/sources.json

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -36,15 +36,15 @@
3636
"url_template": "https://github.com/<owner>/<repo>/archive/<rev>.tar.gz"
3737
},
3838
"nixos-unstable": {
39-
"branch": "nixos-unstable",
39+
"branch": "evalModules-add-extendModules-and-type",
4040
"description": "A read-only mirror of NixOS/nixpkgs tracking the released channels. Send issues and PRs to",
4141
"homepage": "https://github.com/NixOS/nixpkgs",
42-
"owner": "NixOS",
42+
"owner": "hercules-ci",
4343
"repo": "nixpkgs",
44-
"rev": "c6c4a3d45ab200f17805d2d86a1ff1cc7ca2b186",
45-
"sha256": "1f6q98vx3sqxcn6qp5vpy00223r9hy93w9pxq65h9gdwzy3w4qxv",
44+
"rev": "45ca3b6be5aedcc19068594aa117fbaed8a1d8b9",
45+
"sha256": "1jjh0vsvv7skx6cb9mgwvskksadl5ih2m80xdl7plviavpx7mc8h",
4646
"type": "tarball",
47-
"url": "https://github.com/NixOS/nixpkgs/archive/c6c4a3d45ab200f17805d2d86a1ff1cc7ca2b186.tar.gz",
47+
"url": "https://github.com/hercules-ci/nixpkgs/archive/45ca3b6be5aedcc19068594aa117fbaed8a1d8b9.tar.gz",
4848
"url_template": "https://github.com/<owner>/<repo>/archive/<rev>.tar.gz",
4949
"version": ""
5050
},

nixos-module.nix

Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
{ config, lib, pkgs, ... }:
2+
let
3+
inherit (lib)
4+
attrValues
5+
mkIf
6+
mkOption
7+
mkMerge
8+
types
9+
;
10+
11+
cfg = config.virtualisation.arion;
12+
13+
projectType = types.submoduleWith {
14+
modules = [ projectModule ];
15+
};
16+
17+
projectModule = { config, name, ... }: {
18+
options = {
19+
settings = mkOption {
20+
description = ''
21+
Arion project definition, otherwise known as arion-compose.nix contents.
22+
23+
See <link xlink:href="https://docs.hercules-ci.com/arion/options/">https://docs.hercules-ci.com/arion/options/</link>.
24+
'';
25+
type = arionSettingsType;
26+
visible = "shallow";
27+
};
28+
_systemd = mkOption { internal = true; };
29+
};
30+
config = {
31+
_systemd.services."arion-${name}" = {
32+
wantedBy = [ "multi-user.target" ];
33+
after = [ "sockets.target" ];
34+
35+
path = [
36+
cfg.package
37+
cfg.docker.client.package
38+
];
39+
environment.ARION_PREBUILT = config.settings.out.dockerComposeYaml;
40+
script = ''
41+
arion --prebuilt-file "$ARION_PREBUILT" up
42+
'';
43+
};
44+
};
45+
};
46+
47+
arionSettingsType =
48+
(cfg.package.eval { modules = [ ]; }).type;
49+
50+
in
51+
{
52+
disabledModules = [ "virtualisation/arion.nix" ];
53+
54+
options = {
55+
virtualisation.arion = {
56+
backend = mkOption {
57+
type = types.enum [ "podman-socket" "docker" ];
58+
description = ''
59+
Which container implementation to use.
60+
'';
61+
};
62+
package = mkOption {
63+
type = types.package;
64+
65+
default = (import ./. { inherit pkgs; }).arion;
66+
description = ''
67+
Arion package to use. This will provide <literal>arion</literal>
68+
executable that starts the project.
69+
70+
It also must provide the arion <literal>eval</literal> function as
71+
an attribute.
72+
'';
73+
};
74+
docker.client.package = mkOption {
75+
type = types.package;
76+
internal = true;
77+
};
78+
projects = mkOption {
79+
type = types.attrsOf projectType;
80+
default = { };
81+
description = ''
82+
Arion projects to be run as a service.
83+
'';
84+
};
85+
};
86+
};
87+
88+
config = mkIf (cfg.projects != { }) (
89+
mkMerge [
90+
{
91+
systemd = mkMerge (map (p: p._systemd) (attrValues cfg.projects));
92+
}
93+
(mkIf (cfg.backend == "podman-socket") {
94+
virtualisation.docker.enable = false;
95+
virtualisation.podman.enable = true;
96+
virtualisation.podman.dockerSocket.enable = true;
97+
virtualisation.podman.defaultNetwork.dnsname.enable = true;
98+
99+
virtualisation.arion.docker.client.package = pkgs.docker-client;
100+
})
101+
(mkIf (cfg.backend == "docker") {
102+
virtualisation.docker.enable = true;
103+
virtualisation.arion.docker.client.package = pkgs.docker;
104+
})
105+
]
106+
);
107+
}

tests/default.nix

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,25 @@
11
{ pkgs ? import ../pkgs.nix, arionTestingFlags ? {} }:
22
let
3-
inherit (pkgs) nixosTest recurseIntoAttrs arion;
3+
inherit (pkgs) nixosTest recurseIntoAttrs arion lib;
4+
5+
hasEvalModulesType = (lib.evalModules { modules = [ {} ]; })?type;
6+
7+
ifSupportsModule = lib.optionalAttrs hasEvalModulesType;
8+
49
in
510

611
recurseIntoAttrs {
712

813
test = nixosTest ./arion-test;
914

15+
testNixOSDocker = ifSupportsModule (import ./nixos-virtualization-arion-test/test.nix pkgs {
16+
virtualisation.arion.backend = "docker";
17+
});
18+
19+
testNixOSPodman = ifSupportsModule (import ./nixos-virtualization-arion-test/test.nix pkgs {
20+
virtualisation.arion.backend = "podman-socket";
21+
});
22+
1023
testWithPodman =
1124
if arionTestingFlags.nixosHasPodmanDockerSocket
1225
then nixosTest (pkgs.callPackage ./arion-test { usePodman = true; })
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
2+
# NixOS module test
3+
4+
This tests the NixOS module.
5+
6+
The images used here are experimental and not meant for production.
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
{ pkgs, ... }: {
2+
project.name = "whale";
3+
4+
docker-compose.raw = {
5+
volumes.zookeeper = { };
6+
volumes.kafka = { };
7+
};
8+
9+
services.kafka = {
10+
service.useHostStore = true;
11+
# service.volumes = [
12+
# {
13+
# type = "volume";
14+
# source = "kafka";
15+
# target = "/data";
16+
# # volume.nocopy = true;
17+
# }
18+
# ];
19+
service.ports = [ "9092:9092" ];
20+
service.depends_on = [ "zookeeper" ];
21+
image.contents = [
22+
(pkgs.runCommand "root" { } ''
23+
mkdir -p $out/bin
24+
ln -s ${pkgs.runtimeShell} $out/bin/sh
25+
'')
26+
];
27+
image.command = [
28+
"${pkgs.apacheKafka}/bin/kafka-server-start.sh"
29+
"${./kafka/server.properties}"
30+
];
31+
};
32+
33+
services.zookeeper = {
34+
service.useHostStore = true;
35+
service.ports = [ "2181:2181" ];
36+
# service.volumes = [
37+
# {
38+
# type = "volume";
39+
# source = "zookeeper";
40+
# target = "/data";
41+
# # volume.nocopy = true;
42+
# }
43+
# ];
44+
image.contents = [
45+
(pkgs.buildEnv {
46+
name = "root";
47+
paths = [
48+
# pkgs.sed
49+
pkgs.busybox
50+
];
51+
})
52+
];
53+
image.command = [
54+
"${pkgs.zookeeper.override { jre = pkgs.jdk8_headless; }}/bin/zkServer.sh"
55+
"--config"
56+
"${./zookeeper}"
57+
"start-foreground"
58+
];
59+
};
60+
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
# NOTE: This isn't used in the module!
2+
import <nixpkgs> {
3+
# We specify the architecture explicitly. Use a Linux remote builder when
4+
# calling arion from other platforms.
5+
system = "x86_64-linux";
6+
}
Lines changed: 141 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,141 @@
1+
# Licensed to the Apache Software Foundation (ASF) under one or more
2+
# contributor license agreements. See the NOTICE file distributed with
3+
# this work for additional information regarding copyright ownership.
4+
# The ASF licenses this file to You under the Apache License, Version 2.0
5+
# (the "License"); you may not use this file except in compliance with
6+
# the License. You may obtain a copy of the License at
7+
#
8+
# http://www.apache.org/licenses/LICENSE-2.0
9+
#
10+
# Unless required by applicable law or agreed to in writing, software
11+
# distributed under the License is distributed on an "AS IS" BASIS,
12+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
# See the License for the specific language governing permissions and
14+
# limitations under the License.
15+
16+
# see kafka.server.KafkaConfig for additional details and defaults
17+
18+
############################# Server Basics #############################
19+
20+
# The id of the broker. This must be set to a unique integer for each broker.
21+
broker.id=0
22+
23+
############################# Socket Server Settings #############################
24+
25+
# The address the socket server listens on. It will get the value returned from
26+
# java.net.InetAddress.getCanonicalHostName() if not configured.
27+
# FORMAT:
28+
# listeners = listener_name://host_name:port
29+
# EXAMPLE:
30+
# listeners = PLAINTEXT://your.host.name:9092
31+
listeners=LOCALHOST://0.0.0.0:9092,SERVICE://kafka:9093
32+
33+
# Hostname and port the broker will advertise to producers and consumers. If not set,
34+
# it uses the value for "listeners" if configured. Otherwise, it will use the value
35+
# returned from java.net.InetAddress.getCanonicalHostName().
36+
# advertised.listeners=PLAINTEXT://whale_kafka_1:9092
37+
advertised.listeners=LOCALHOST://localhost:9092,SERVICE://kafka:9093
38+
39+
# ???
40+
inter.broker.listener.name=LOCALHOST
41+
42+
# Maps listener names to security protocols, the default is for them to be the same. See the config documentation for more details
43+
#listener.security.protocol.map=PLAINTEXT:PLAINTEXT,SSL:SSL,SASL_PLAINTEXT:SASL_PLAINTEXT,SASL_SSL:SASL_SSL
44+
listener.security.protocol.map=LOCALHOST:PLAINTEXT,SERVICE:PLAINTEXT
45+
46+
# The number of threads that the server uses for receiving requests from the network and sending responses to the network
47+
num.network.threads=3
48+
49+
# The number of threads that the server uses for processing requests, which may include disk I/O
50+
num.io.threads=8
51+
52+
# The send buffer (SO_SNDBUF) used by the socket server
53+
socket.send.buffer.bytes=102400
54+
55+
# The receive buffer (SO_RCVBUF) used by the socket server
56+
socket.receive.buffer.bytes=102400
57+
58+
# The maximum size of a request that the socket server will accept (protection against OOM)
59+
socket.request.max.bytes=104857600
60+
61+
62+
############################# Log Basics #############################
63+
64+
# A comma separated list of directories under which to store log files
65+
log.dirs=/tmp/kafka-logs
66+
67+
# The default number of log partitions per topic. More partitions allow greater
68+
# parallelism for consumption, but this will also result in more files across
69+
# the brokers.
70+
num.partitions=1
71+
72+
# The number of threads per data directory to be used for log recovery at startup and flushing at shutdown.
73+
# This value is recommended to be increased for installations with data dirs located in RAID array.
74+
num.recovery.threads.per.data.dir=1
75+
76+
############################# Internal Topic Settings #############################
77+
# The replication factor for the group metadata internal topics "__consumer_offsets" and "__transaction_state"
78+
# For anything other than development testing, a value greater than 1 is recommended to ensure availability such as 3.
79+
offsets.topic.replication.factor=1
80+
transaction.state.log.replication.factor=1
81+
transaction.state.log.min.isr=1
82+
83+
############################# Log Flush Policy #############################
84+
85+
# Messages are immediately written to the filesystem but by default we only fsync() to sync
86+
# the OS cache lazily. The following configurations control the flush of data to disk.
87+
# There are a few important trade-offs here:
88+
# 1. Durability: Unflushed data may be lost if you are not using replication.
89+
# 2. Latency: Very large flush intervals may lead to latency spikes when the flush does occur as there will be a lot of data to flush.
90+
# 3. Throughput: The flush is generally the most expensive operation, and a small flush interval may lead to excessive seeks.
91+
# The settings below allow one to configure the flush policy to flush data after a period of time or
92+
# every N messages (or both). This can be done globally and overridden on a per-topic basis.
93+
94+
# The number of messages to accept before forcing a flush of data to disk
95+
#log.flush.interval.messages=10000
96+
97+
# The maximum amount of time a message can sit in a log before we force a flush
98+
#log.flush.interval.ms=1000
99+
100+
############################# Log Retention Policy #############################
101+
102+
# The following configurations control the disposal of log segments. The policy can
103+
# be set to delete segments after a period of time, or after a given size has accumulated.
104+
# A segment will be deleted whenever *either* of these criteria are met. Deletion always happens
105+
# from the end of the log.
106+
107+
# The minimum age of a log file to be eligible for deletion due to age
108+
log.retention.hours=168
109+
110+
# A size-based retention policy for logs. Segments are pruned from the log unless the remaining
111+
# segments drop below log.retention.bytes. Functions independently of log.retention.hours.
112+
#log.retention.bytes=1073741824
113+
114+
# The maximum size of a log segment file. When this size is reached a new log segment will be created.
115+
log.segment.bytes=1073741824
116+
117+
# The interval at which log segments are checked to see if they can be deleted according
118+
# to the retention policies
119+
log.retention.check.interval.ms=300000
120+
121+
############################# Zookeeper #############################
122+
123+
# Zookeeper connection string (see zookeeper docs for details).
124+
# This is a comma separated host:port pairs, each corresponding to a zk
125+
# server. e.g. "127.0.0.1:3000,127.0.0.1:3001,127.0.0.1:3002".
126+
# You can also append an optional chroot string to the urls to specify the
127+
# root directory for all kafka znodes.
128+
zookeeper.connect=zookeeper:2181
129+
130+
# Timeout in ms for connecting to zookeeper
131+
zookeeper.connection.timeout.ms=18000
132+
133+
134+
############################# Group Coordinator Settings #############################
135+
136+
# The following configuration specifies the time, in milliseconds, that the GroupCoordinator will delay the initial consumer rebalance.
137+
# The rebalance will be further delayed by the value of group.initial.rebalance.delay.ms as new members join the group, up to a maximum of max.poll.interval.ms.
138+
# The default value for this is 3 seconds.
139+
# We override this to 0 here as it makes for a better out-of-the-box experience for development and testing.
140+
# However, in production environments the default value of 3 seconds is more suitable as this will help to avoid unnecessary, and potentially expensive, rebalances during application startup.
141+
group.initial.rebalance.delay.ms=0

0 commit comments

Comments
 (0)