Skip to content

Commit 1b0fc5f

Browse files
fmastedeepfire
authored andcommitted
workbench: remove mounted volumes as much as possible
Use the meta stanza for default values Use the template stanza to populate folders merge node-0 and generator tasks Use only one genesis folder
1 parent de9b2b2 commit 1b0fc5f

14 files changed

+371
-296
lines changed

nix/workbench/backend/nomad-job.nix

+168-49
Original file line numberDiff line numberDiff line change
@@ -7,19 +7,56 @@
77
, lib
88
, stateDir
99
, profileNix
10-
, clusterImage
11-
, unixHttpServerPort
10+
, ociImages
11+
# Needs unix_http_server.file
12+
, supervisorConf
1213
}:
1314

1415
let
1516

16-
# Container defaults: See ./oci-images.nix
17-
container_workdir = "/tmp/cluster";
18-
container_supervisor_nix = "${container_workdir}/${stateDir}/supervisor/nix-store";
19-
container_supervisord_url = "unix://${unixHttpServerPort}";
20-
container_supervisord_conf = "${container_workdir}/${stateDir}/supervisor/supervisord.conf";
17+
# Container defaults:
18+
## Stored on the job's "meta" stanza and intended to be overrided with `jq`.
19+
## See ./oci-images.nix for further details.
20+
#
21+
# The template stanza can only generate files inside /local (NOMAD_TASK_DIR)
22+
## - https://developer.hashicorp.com/nomad/docs/job-specification/template#template-destinations
23+
## - https://developer.hashicorp.com/nomad/docs/runtime/environment#task-directories
24+
## - https://developer.hashicorp.com/nomad/docs/concepts/filesystem
25+
container_workdir = "/local";
26+
# Usually "/local/run/current"
27+
container_statedir = "${container_workdir}/${stateDir}";
28+
# A link to the supervisord nix-installed inside the OCI image.
29+
container_supervisor_nix = "${container_statedir}/supervisor/nix-store";
30+
# The URL to the listening inet or socket of the supervisord server:
31+
# The problem is that if we use "127.0.0.1:9001" as parameter (without the
32+
# "http" part) the container returns:
33+
# error: <class 'ValueError'>, Unknown protocol for serverurl 127.0.0.1:9001: file: /nix/store/izqhlj5i1x9ldyn43d02kcy4mafmj3ci-python3.9-supervisor-4.2.4/lib/python3.9/site-packages/supervisor/xmlrpc.py line: 508
34+
# Without using the `--serverurl` parameter at all (using INI config file's
35+
# [inet_http_server] port stanza) also without "http://":
36+
# error: <class 'socket.gaierror'>, [Errno -2] Name or service not known: file: /nix/store/hb1lzaisgx2m9n29hqhh6yp6hasplq1v-python3-3.9.10/lib/python3.9/socket.py line: 954
37+
# If I add the "http" part to the INI file, when starting `supervisord` inside
38+
# the container I get (from journald):
39+
# Nov 02 11:44:36 hostname cluster-18f3852f-e067-6394-8159-66a7b8da2ecc[1088457]: Error: Cannot open an HTTP server: socket.error reported -2
40+
# Nov 02 11:44:36 hostname cluster-18f3852f-e067-6394-8159-66a7b8da2ecc[1088457]: For help, use /nix/store/izqhlj5i1x9ldyn43d02kcy4mafmj3ci-python3.9-supervisor-4.2.4/bin/supervisord -h
41+
container_supervisord_url = "unix://${supervisorConf.value.unix_http_server.file}";
42+
# Location of the supervisord config file inside the container.
43+
# This file can be mounted as a volume or created as a template.
44+
container_supervisord_conf = "${container_statedir}/supervisor/supervisord.conf";
2145
container_supervisord_loglevel = "info";
2246

47+
# About the "template" stanza:
48+
# The templates documentations show "left_delimiter" and "right_delimiter"
49+
# options which default to "{{" and "}}" repectively. See:
50+
# https://developer.hashicorp.com/nomad/docs/job-specification/template#left_delimiter
51+
# But those don't work to escape text to avoid HCL expressions interpolation.
52+
# We are using what says here:
53+
# "In both quoted and heredoc string expressions, Nomad supports template
54+
# sequences that begin with ${ and %{. These are described in more detail in
55+
# the following section. To include these sequences literally without
56+
# beginning a template sequence, double the leading character: $${ or %%{."
57+
# https://developer.hashicorp.com/nomad/docs/job-specification/hcl2/expressions#string-literals
58+
escapeTemplate = str: builtins.replaceStrings ["\${" "%{"] ["\$\${" "%%{"] str;
59+
2360
# About the JSON Job Specification and its odd assumptions:
2461
#
2562
# At least in Nomad version v1.4.3, the CLI command to submit new jobs
@@ -29,12 +66,11 @@ let
2966
# HCL format that is heavily specified in the docs. Nice!
3067
#
3168
# But note that it starts saying "Nomad HCL is parsed in the command line and
32-
# sent to Nomad in JSON format via the HTTP API." and here are the API docs
33-
# with "JSON Job Specification" in its title:
69+
# sent to Nomad in JSON format via the HTTP API." and here there are the API
70+
# docs that have "JSON Job Specification" in its title:
3471
# https://developer.hashicorp.com/nomad/api-docs/json-jobs
3572
# well, this is the format that `nomad job run` expects if you use the `-json`
36-
# argument. If you don't provide the `-json` argument it expects HCL or its
37-
# JSON representation: https://github.com/hashicorp/hcl/blob/main/json/spec.md
73+
# argument.
3874
#
3975
# I finally found this in the HCL overview page:
4076
# https://developer.hashicorp.com/nomad/docs/job-specification/hcl2
@@ -44,6 +80,9 @@ let
4480
# JSON format is unspecified, so the API format is preferred. You can use the
4581
# API format with the -json command line flag."
4682
#
83+
# So, if you don't provide the `-json` argument it expects HCL or its JSON
84+
# representation: https://github.com/hashicorp/hcl/blob/main/json/spec.md
85+
#
4786
# We are using what HashiCorp calls an unespecified format but it the same
4887
# format the SRE team is using.
4988

@@ -157,6 +196,8 @@ let
157196
# This makes it easier to change them using `jq` inside the workbench!
158197
meta = {
159198
# Only top level "KEY=STRING" are allowed!
199+
WORKING_DIRECTORY = container_workdir;
200+
STATE_DIRECTORY = container_statedir;
160201
SUPERVISOR_NIX = container_supervisor_nix;
161202
SUPERVISORD_URL = container_supervisord_url;
162203
SUPERVISORD_CONFIG = container_supervisord_conf;
@@ -189,7 +230,7 @@ let
189230
# container, web application, or batch processing.
190231
# https://developer.hashicorp.com/nomad/docs/job-specification/task
191232
task = let
192-
valueF = (name: nodeSpecs: volumes: taskDefaults // {
233+
valueF = (name: volumes: (taskDefaults // {
193234

194235
driver = "podman";
195236

@@ -202,36 +243,117 @@ let
202243
# Specifies environment variables that will be passed to the running
203244
# process.
204245
# `null` because we are using a "template" (see below).
205-
env = {
206-
#SUPERVISOR_NIX = container_supervisor_nix;
207-
#SUPERVISORD_URL = container_supervisord_url;
208-
#SUPERVISORD_CONFIG = container_supervisord_conf;
209-
#SUPERVISORD_LOGLEVEL = container_supervisord_loglevel;
210-
};
246+
env = {};
211247

212248
# Specifies the set of templates to render for the task. Templates can
213249
# be used to inject both static and dynamic configuration with data
214250
# populated from environment variables, Consul and Vault.
215-
template = {
216-
# podman container input environment variables.
217-
env = true;
218-
# File name to create inside the allocation directory.
219-
destination = "envars";
220-
# See runtime for available variables:
221-
# https://developer.hashicorp.com/nomad/docs/runtime/environment
222-
data = ''
223-
SUPERVISOR_NIX="{{ env "NOMAD_META_SUPERVISOR_NIX" }}"
224-
SUPERVISORD_URL="{{ env "NOMAD_META_SUPERVISORD_URL" }}"
225-
SUPERVISORD_CONFIG="{{ env "NOMAD_META_SUPERVISORD_CONFIG" }}"
226-
SUPERVISORD_LOGLEVEL="{{ env "NOMAD_META_SUPERVISORD_LOGLEVEL" }}"
227-
'';
228-
# Specifies the behavior Nomad should take if the rendered template
229-
# changes. Nomad will always write the new contents of the template
230-
# to the specified destination. The following possible values
231-
# describe Nomad's action after writing the template to disk.
232-
change_mode = "noop";
233-
error_on_missing_key = true;
234-
};
251+
template = [
252+
# Envars
253+
{
254+
# podman container input environment variables.
255+
env = true;
256+
# File name to create inside the allocation directory.
257+
# Created in NOMAD_DATA_DIR/alloc/ALLOC_ID/TASK_NAME/envars
258+
destination = "envars";
259+
# See runtime for available variables:
260+
# https://developer.hashicorp.com/nomad/docs/runtime/environment
261+
data = ''
262+
SUPERVISOR_NIX="{{ env "NOMAD_META_SUPERVISOR_NIX" }}"
263+
SUPERVISORD_URL="{{ env "NOMAD_META_SUPERVISORD_URL" }}"
264+
SUPERVISORD_CONFIG="{{ env "NOMAD_META_SUPERVISORD_CONFIG" }}"
265+
SUPERVISORD_LOGLEVEL="{{ env "NOMAD_META_SUPERVISORD_LOGLEVEL" }}"
266+
'';
267+
# Specifies the behavior Nomad should take if the rendered
268+
# template changes. Nomad will always write the new contents of
269+
# the template to the specified destination. The following
270+
# possible values describe Nomad's action after writing the
271+
# template to disk.
272+
change_mode = "noop";
273+
error_on_missing_key = true;
274+
}
275+
# supervisord configuration file.
276+
{
277+
env = false;
278+
destination = "${container_supervisord_conf}";
279+
data = escapeTemplate (__readFile
280+
supervisorConf.INI);
281+
change_mode = "noop";
282+
error_on_missing_key = true;
283+
}
284+
# Generator start.sh script.
285+
{
286+
env = false;
287+
destination = "${container_statedir}/generator/start.sh";
288+
data = escapeTemplate
289+
profileNix.generator-service.startupScript.value;
290+
change_mode = "noop";
291+
error_on_missing_key = true;
292+
}
293+
# Generator configuration file.
294+
{
295+
env = false;
296+
destination = "${container_statedir}/generator/run-script.json";
297+
data = escapeTemplate (__readFile
298+
profileNix.generator-service.runScript.JSON.outPath);
299+
change_mode = "noop";
300+
error_on_missing_key = true;
301+
}
302+
/* TODO: Tracer still needs to use volumes because tracer.socket is shared.
303+
# Tracer start.sh script.
304+
{
305+
env = false;
306+
destination = "${container_statedir}/tracer/start.sh";
307+
data = escapeTemplate
308+
profileNix.tracer-service.startupScript.value;
309+
change_mode = "noop";
310+
error_on_missing_key = true;
311+
}
312+
# Tracer configuration file.
313+
{
314+
env = false;
315+
destination = "${container_statedir}/tracer/config.json";
316+
data = escapeTemplate (lib.generators.toJSON {}
317+
profileNix.tracer-service.config.value);
318+
change_mode = "noop";
319+
error_on_missing_key = true;
320+
}
321+
*/
322+
]
323+
++
324+
(lib.lists.flatten (lib.mapAttrsToList
325+
(_: nodeSpec: [
326+
# Node start.sh script.
327+
{
328+
env = false;
329+
destination = "${container_statedir}/${nodeSpec.name}/start.sh";
330+
data = escapeTemplate
331+
profileNix.node-services."${nodeSpec.name}".startupScript.value;
332+
change_mode = "noop";
333+
error_on_missing_key = true;
334+
}
335+
# Node configuration file.
336+
{
337+
env = false;
338+
destination = "${container_statedir}/${nodeSpec.name}/config.json";
339+
data = escapeTemplate (lib.generators.toJSON {}
340+
profileNix.node-services."${nodeSpec.name}".nodeConfig.value);
341+
change_mode = "noop";
342+
error_on_missing_key = true;
343+
}
344+
# Node topology file.
345+
{
346+
env = false;
347+
destination = "${container_statedir}/${nodeSpec.name}/topology.json";
348+
data = escapeTemplate (lib.generators.toJSON {}
349+
profileNix.node-services."${nodeSpec.name}".topology.value);
350+
change_mode = "noop";
351+
error_on_missing_key = true;
352+
}
353+
])
354+
profileNix.node-specs.value
355+
))
356+
;
235357

236358
# Specifies where a group volume should be mounted.
237359
volume_mount = null; #TODO
@@ -267,7 +389,7 @@ let
267389
# missing), oci-archive and docker-archive. Images reference as
268390
# short-names will be treated according to user-configured
269391
# preferences.
270-
image = "${clusterImage.imageName}:${clusterImage.imageTag}";
392+
image = "${ociImages.value.clusterNode.imageName}:${ociImages.value.clusterNode.imageTag}";
271393

272394
# Always pull the latest image on container start.
273395
force_pull = false;
@@ -314,19 +436,16 @@ let
314436
# overrides any vault block set at the group or job level.
315437
vault = null;
316438

317-
});
439+
}));
318440
in lib.listToAttrs (
319-
[
320-
{name = "generator"; value = valueF "generator" null [ stateDir ];}
321-
]
322-
++ lib.optionals profileNix.value.node.tracer [
323-
{name = "tracer"; value = valueF "tracer" null [ stateDir ];}
441+
lib.optionals profileNix.value.node.tracer [
442+
{name = "tracer"; value = valueF "tracer" [];}
324443
]
325444
++
326445
(lib.mapAttrsToList
327-
(_: nodeSpecs: {
328-
name = nodeSpecs.name;
329-
value = valueF nodeSpecs.name nodeSpecs [];
446+
(_: nodeSpec: {
447+
name = nodeSpec.name;
448+
value = valueF nodeSpec.name [];
330449
})
331450
(profileNix.node-specs.value)
332451
)
@@ -522,5 +641,5 @@ let
522641
# user = null;
523642
};
524643

525-
in pkgs.writeText "nomad-job.json"
644+
in pkgs.writeText "workbench-cluster-nomad-job.json"
526645
(lib.generators.toJSON {} clusterJob)

nix/workbench/backend/nomad.nix

+16-28
Original file line numberDiff line numberDiff line change
@@ -64,51 +64,39 @@ let
6464
# fuse-overlayfs
6565
]);
6666

67+
# Backend-specific Nix bits:
6768
materialise-profile =
6869
{ stateDir, profileNix }:
6970
let
70-
unixHttpServerPort = "/tmp/supervisor.sock";
71-
supervisorConfPath =
72-
import ./supervisor-conf.nix
73-
{ inherit (profileNix) node-services;
74-
inherit pkgs lib stateDir;
75-
inherit unixHttpServerPort;
76-
};
7771
ociImages =
7872
import ./oci-images.nix
79-
{ inherit pkgs;
73+
{ inherit pkgs lib;
8074
inherit
8175
(pkgs.cardanoNodePackages)
8276
cardano-node cardano-tracer tx-generator;
8377
};
84-
nomadJobJSONPath =
78+
supervisorConf =
79+
import ./supervisor-conf.nix
80+
{ inherit (profileNix) node-services;
81+
inherit pkgs lib stateDir;
82+
unixHttpServerPort = "/tmp/supervisor.sock";
83+
};
84+
nomadJobJSON =
8585
import ./nomad-job.nix
8686
{ inherit pkgs lib stateDir;
8787
inherit profileNix;
88-
inherit (ociImages) clusterImage;
89-
inherit unixHttpServerPort;
88+
inherit ociImages;
89+
inherit supervisorConf;
9090
};
9191
in pkgs.runCommand "workbench-backend-output-${profileNix.name}-${name}"
92-
(rec {
93-
inherit supervisorConfPath;
94-
# All In One
95-
clusterImage = ociImages.clusterImage;
96-
clusterImageCopyToPodman = clusterImage.copyToPodman;
97-
clusterImageName = clusterImage.imageName;
98-
clusterImageTag = clusterImage.imageTag;
99-
inherit nomadJobJSONPath;
92+
({
93+
ociImagesJSON = ociImages.JSON;
94+
inherit nomadJobJSON;
10095
})
10196
''
10297
mkdir $out
103-
104-
ln -s $supervisorConfPath $out/supervisor.conf
105-
106-
ln -s $clusterImage $out/clusterImage
107-
echo $clusterImageName > $out/clusterImageName
108-
echo $clusterImageTag > $out/clusterImageTag
109-
ln -s $clusterImageCopyToPodman/bin/copy-to-podman $out/clusterImageCopyToPodman
110-
111-
ln -s $nomadJobJSONPath $out/nomad-job.json
98+
ln -s $ociImagesJSON $out/oci-images.json
99+
ln -s $nomadJobJSON $out/nomad-job.json
112100
'';
113101
in
114102
{

0 commit comments

Comments
 (0)