jaque import is a compiler, not a migration wizard you babysit through a
dozen screens: point it at a config tree, get CUE and an honest report
back. It exists because a Nagios use chain and CUE's unification are
different enough semantics that no line-by-line transliteration would be
trustworthy -- the importer resolves Nagios's own inheritance rules first,
then re-derives CUE structure from the result.
Status: round-trip correctness is property-tested against generated configs; the importer has never been run against a real third-party Nagios config, because the project has no such corpus yet. Treat its output as a strong first draft, not a finished migration -- see section 5.
1. Running it
jaque import -from nagios /etc/nagios/ -o jaque.cue
The positional argument is a directory (jaque looks for nagios.cfg
inside it, per Nagios's own convention) or a single file. -from accepts
nagios today. -o writes the CUE to a file; without it, CUE goes to
stdout and the report to stderr, deliberately on separate streams so
piping to a file never mixes them.
2. The pipeline
nagios.cfg
-> include resolution (cfg_file=, cfg_dir=, resource.cfg for $USERn$)
-> parse (define blocks -> AST, every node keeps file:line)
-> inheritance resolution (use/name/register -> effective objects)
-> semantic mapping (effective objects -> jaque's internal IR)
-> structure recovery (shared values factored back into CUE templates)
-> emit (CUE AST via cue/ast + cue/format) + report
Nagios's use chains are ordered multiple inheritance with additive
values (+value) and unset (null) -- semantics that do not map 1:1 onto
CUE's unification, so the importer never translates a template directly.
It flattens every object using Nagios's own resolution rules first (the
correctness anchor, and the most heavily golden-tested part of the
pipeline), then factors shared values back out into CUE templates for a
readable emit. When that recovery is ambiguous, it emits flat rather than
guess, and says so in the report.
3. The migration report
Every source object gets one line: mapped, approximated (translated,
but something changed -- the report says what), or unsupported (dropped,
with file:line). The header carries the trust-anchor number:
objects: N emitted of M in source (P% survived)
That is the one metric that matters -- not "import succeeded," but how much
of the source tree actually made it across. The report is designed to be
truthful before it is flattering: an object silently dropped and called
mapped anyway is worse than one honestly marked unsupported.
4. What is mapped versus approximated versus unsupported
| Category | Examples |
|---|---|
| Mapped, 1:1 | Hosts, services, most check_command translations, parents, timeperiods reducible to (weekday, range) windows, contacts onto jaque's four contact types, hostgroup-based services (kept as a group-level definition, never exploded into per-host copies). |
| Approximated | notification_options combinations that do not map cleanly onto jaque's notification kinds -- the report names what changed. |
| Not supported today | Event handlers, obsess_over_*, most escalation directives, and -- deliberately -- any object mixing active and passive checks. jaque's schema models a check as one type; an object trying to be both active and passive at once has nowhere well-defined to go, so it is reported rather than guessed at. |
5. Verified how far, honestly
Round-trip correctness (emit -> re-parse -> compare)
is property-tested against generated configs. What is not yet done:
verification against a real-world corpus at the scale that would let this
page claim a concrete coverage percentage across "typical" Nagios estates.
Treat the emitted CUE as a strong first draft, always validated with
jaque -config jaque.cue before you trust it, and read the unsupported
lines before deciding the import is complete.
6. Icinga 2: not yet
The importer pipeline is built to host more than one frontend, but only Nagios is implemented today. An Icinga 2 frontend is not built.
7. Security considerations
The importer parses a config tree offline, at import time, not at request time -- it is not a network-facing surface. The tree itself is still untrusted input if it came from somewhere other than the estate you already run: read the migration report and validate the emitted CUE before loading it into a jaque you care about.