Query control API to show the loaded modules
This feature extends the /status Control API endpoint to include the currently loaded modules.
Currently, the available modules are loaded by the discovery process at startup and logged to the Unit log file.
2024/06/26 09:36:16 [info] 55991#2488927 discovery started
2024/06/26 09:36:16 [notice] 55991#2488927 module: php 8.3.4 "/var/lib/unit/modules/php.unit.so"
2024/06/26 09:36:16 [notice] 55991#2488927 module: python 3.12.2 "/var/lib/unit/modules/python3.unit.so"
2024/06/26 09:36:16 [notice] 55991#2488927 module: wasm-wasi-component 0.1 "/var/lib/unit/modules/wasm_wasi_component.unit.so"
2024/06/26 09:36:17 [info] 55990#2488925 controller started
This information is already transferred to the Control API because attempts to configure an application with an unloaded "type" fails with a suitable error, e.g.
$ echo '{"bogus":{"type":"cobol"}}' | unitc /config/applications
{
"error": "Invalid configuration.",
"detail": "The module to run \"cobol\" is not found among the available application modules."
}
It would be much more convenient if the loaded modules information was also queryable at runtime. So the /status endpoint would return something like:
{
"modules": [
"php 8.3.4",
"python 3.12.2",
"wasm-wasi-component 0.1"
],
"connections": { … },
"requests": { … },
"applications": { … }
}
This would provide a more convenient way of checking what language modules are loaded. It would also benefit command line tools that auto-configure Unit to serve applications.
The language modules and versions are handily stored in the languages array member of the nxt_runtime_t structure...
We have access to the following information
typedef struct {
nxt_app_type_t type;
u_char *version;
char *file;
nxt_app_module_t *module;
nxt_array_t *mounts; /* of nxt_fs_mount_t */
} nxt_app_lang_module_t;
Would showing the path (e.g /opt/unit/modules/python.unit.so) to the module be useful? Might be handy for debugging to make sure it's loading the modules you expect it to...
Would showing the path (e.g /opt/unit/modules/python.unit.so) to the module be useful?
I have wished for this information several times in fact! :) I think having this will better enable our users to roll their own docker images and to compile Unit for themselves.
Given that we have the type and version as separate entities in the struct, it makes sense to have an array of objects instead of the simple naive array I was envisaging.
I wasn't sure about the information disclosure of the path. And I didn't have a use case for it. But now I think about it, knowing exactly which module is loaded seems like a good idea.
I have an initial version that will return something like
{
"modules": {
"python": {
"version": "3.12.2",
"lib": "/opt/unit/modules/python.unit.so"
},
"wasm": {
"version": "0.1",
"lib": "/opt/unit/modules/wasm.unit.so"
},
"wasm-wasi-component": {
"version": "0.1",
"lib": "/opt/unit/modules/wasm_wasi_component.unit.so"
}
},
...
}
I look forward to trying it :)
I suggested an array of objects because we may find multiple versions of the same language module installed (especially for PHP and Python).
Are you saying you want the JSON formatted differently?
Currently it's modelled on the "applications" section
"applications": {
"luw-echo-request": {
"processes": {
"running": 1,
"starting": 0,
"idle": 1
},
"requests": {
"active": 0
}
},
"luw-upload-reflector": {
"processes": {
"running": 1,
"starting": 0,
"idle": 1
},
"requests": {
"active": 0
}
},
"echo-request-raw": {
"processes": {
"running": 1,
"starting": 0,
"idle": 1
},
"requests": {
"active": 0
}
},
"rust-echo-request": {
"processes": {
"running": 1,
"starting": 0,
"idle": 1
},
"requests": {
"active": 0
}
},
"rust-upload-reflector": {
"processes": {
"running": 1,
"starting": 0,
"idle": 1
},
"requests": {
"active": 0
}
},
"rust-hello-world": {
"processes": {
"running": 1,
"starting": 0,
"idle": 1
},
"requests": {
"active": 0
}
},
"sc-test": {
"processes": {
"running": 1,
"starting": 0,
"idle": 1
},
"requests": {
"active": 0
}
},
"large-upload": {
"processes": {
"running": 1,
"starting": 0,
"idle": 1
},
"requests": {
"active": 0
}
},
"rust-large-upload": {
"processes": {
"running": 1,
"starting": 0,
"idle": 1
},
"requests": {
"active": 0
}
}
}
I think Liam probably means:
{
"modules": {
"python": [
{
"version": "3.12.2",
"lib": "/opt/unit/modules/python3.12.unit.so"
},
{
"version": "3.11.0",
"lib": "/opt/unit/modules/python3.11.unit.so"
}
],
"wasm": [ ... ]
}
I actually meant something different but then realised that it's not possible to have ambiguous module names.
So @ac000 's original example looks ideal.
Excellent! Well done @ac000