Skip to content

Commit 1d925ba

Browse files
authored
Merge pull request #505 from getwud/feature/#500_add_trigger_testing_feature
⭐ [UI/API] - Add support for manually running triggers to help w…
2 parents 48d5f28 + fb02feb commit 1d925ba

17 files changed

+297
-93
lines changed

app/api/authentication.js

+1-9
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,11 @@
1-
const registry = require('../registry');
21
const component = require('./component');
32

4-
/**
5-
* Return registered authentications.
6-
* @returns {{id: string}[]}
7-
*/
8-
function getAuthentications() {
9-
return registry.getState().authentication;
10-
}
113
/**
124
* Init Router.
135
* @returns {*}
146
*/
157
function init() {
16-
return component.init(getAuthentications);
8+
return component.init('authentication');
179
}
1810

1911
module.exports = {

app/api/component.js

+20-12
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ const { byValues, byString } = require('sort-es');
22

33
const express = require('express');
44
const nocache = require('nocache');
5+
const registry = require('../registry');
56

67
/**
78
* Map a Component to a displayable (api/ui) item.
@@ -23,9 +24,9 @@ function mapComponentToItem(key, component) {
2324
* @param listFunction
2425
* @returns {{id: string}[]}
2526
*/
26-
function mapComponentsToList(listFunction) {
27-
return Object.keys(listFunction())
28-
.map((key) => mapComponentToItem(key, listFunction()[key]))
27+
function mapComponentsToList(components) {
28+
return Object.keys(components)
29+
.map((key) => mapComponentToItem(key, components[key]))
2930
.sort(byValues([
3031
[(x) => x.type, byString()],
3132
[(x) => x.name, byString()],
@@ -37,8 +38,8 @@ function mapComponentsToList(listFunction) {
3738
* @param req
3839
* @param res
3940
*/
40-
function getAll(req, res, listFunction) {
41-
res.status(200).json(mapComponentsToList(listFunction));
41+
function getAll(req, res, kind) {
42+
res.status(200).json(mapComponentsToList(registry.getState()[kind]));
4243
}
4344

4445
/**
@@ -47,9 +48,15 @@ function getAll(req, res, listFunction) {
4748
* @param res
4849
* @param listFunction
4950
*/
50-
function getById(req, res, listFunction) {
51-
const { id } = req.params;
52-
const component = listFunction()[id];
51+
function getById(req, res, kind) {
52+
const { type, name } = req.params;
53+
let id = `${kind}.${type}.${name}`;
54+
55+
// Hack for registries because id and name are equivalent
56+
if (kind === 'registry') {
57+
id = `${name}`;
58+
}
59+
const component = registry.getState()[kind][id];
5360
if (component) {
5461
res.status(200).json(mapComponentToItem(id, component));
5562
} else {
@@ -59,18 +66,19 @@ function getById(req, res, listFunction) {
5966

6067
/**
6168
* Init the component router.
62-
* @param listFunction
69+
* @param kind
6370
* @returns {*|Router}
6471
*/
65-
function init(listFunction) {
72+
function init(kind) {
6673
const router = express.Router();
6774
router.use(nocache());
68-
router.get('/', (req, res) => getAll(req, res, listFunction));
69-
router.get('/:id', (req, res) => getById(req, res, listFunction));
75+
router.get('/', (req, res) => getAll(req, res, kind));
76+
router.get('/:type/:name', (req, res) => getById(req, res, kind));
7077
return router;
7178
}
7279

7380
module.exports = {
7481
init,
7582
mapComponentsToList,
83+
getById,
7684
};

app/api/registry.js

+3-18
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,15 @@
1-
const registry = require('../registry');
21
const component = require('./component');
32

4-
/**
5-
* Return registered registries.
6-
* @returns {{id: string}[]}
7-
*/
8-
function getRegistries() {
9-
return registry.getState().registry;
10-
}
113
/**
124
* Init Router.
135
* @returns {*}
146
*/
157
function init() {
16-
return component.init(getRegistries);
17-
}
18-
19-
/**
20-
* Get all triggers.
21-
* @returns {{id: string}[]}
22-
*/
23-
function getAllRegistries() {
24-
return component.mapComponentsToList(getRegistries);
8+
const router = component.init('registry');
9+
router.get('/:name', (req, res) => component.getById(req, res, 'registry'));
10+
return router;
2511
}
2612

2713
module.exports = {
2814
init,
29-
getAllRegistries,
3015
};

app/api/trigger.js

+36-15
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,51 @@
1-
const registry = require('../registry');
21
const component = require('./component');
2+
const registry = require('../registry');
33

44
/**
5-
* Return registered triggers.
6-
* @returns {{id: string}[]}
5+
* Run a specific trigger on a specific container provided in the payload.
6+
* @param {*} req
7+
* @param {*} res
8+
* @returns
79
*/
8-
function getTriggers() {
9-
return registry.getState().trigger;
10+
async function runTrigger(req, res) {
11+
const triggerType = req.params.type;
12+
const triggerName = req.params.name;
13+
const containerToTrigger = req.body;
14+
15+
const triggerToRun = registry.getState().trigger[`trigger.${triggerType}.${triggerName}`];
16+
if (!triggerToRun) {
17+
res.status(404).json({
18+
error: `Error when running trigger ${triggerType}.${triggerName} (trigger not found)`,
19+
});
20+
return;
21+
}
22+
if (!containerToTrigger) {
23+
res.status(400).json({
24+
error: `Error when running trigger ${triggerType}.${triggerName} (container is undefined)`,
25+
});
26+
return;
27+
}
28+
29+
try {
30+
await triggerToRun.trigger(containerToTrigger);
31+
res.status(200).json({});
32+
} catch (e) {
33+
res.status(500).json({
34+
error: `Error when running trigger ${triggerType}.${triggerName} (${e.message})`,
35+
});
36+
}
1037
}
38+
1139
/**
1240
* Init Router.
1341
* @returns {*}
1442
*/
1543
function init() {
16-
return component.init(getTriggers);
17-
}
18-
19-
/**
20-
* Get all triggers.
21-
* @returns {{id: string}[]}
22-
*/
23-
function getAllTriggers() {
24-
return component.mapComponentsToList(getTriggers);
44+
const router = component.init('trigger');
45+
router.post('/:type/:name', (req, res) => runTrigger(req, res));
46+
return router;
2547
}
2648

2749
module.exports = {
2850
init,
29-
getAllTriggers,
3051
};

app/api/watcher.js

+1-19
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,13 @@
1-
const registry = require('../registry');
21
const component = require('./component');
32

4-
/**
5-
* Return registered watchers.
6-
* @returns {{id: string}[]}
7-
*/
8-
function getWatchers() {
9-
return registry.getState().watcher;
10-
}
11-
123
/**
134
* Init Router.
145
* @returns {*}
156
*/
167
function init() {
17-
return component.init(getWatchers);
18-
}
19-
20-
/**
21-
* Get all watchers.
22-
* @returns {{id: string}[]}
23-
*/
24-
function getAllWatchers() {
25-
return component.mapComponentsToList(getWatchers);
8+
return component.init('watcher');
269
}
2710

2811
module.exports = {
2912
init,
30-
getAllWatchers,
3113
};

app/nodemon.json

+4-1
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,9 @@
44
"WUD_STORE_PATH": ".store",
55
"WUD_WATCHER_LOCAL_WATCHBYDEFAULT": "true",
66
"WUD_AUTH_BASIC_JOHN_USER": "john",
7-
"WUD_AUTH_BASIC_JOHN_HASH": "$apr1$aefKbZEa$ZSA5Y3zv9vDQOxr283NGx/"
7+
"WUD_AUTH_BASIC_JOHN_HASH": "$apr1$aefKbZEa$ZSA5Y3zv9vDQOxr283NGx/",
8+
"WUD_TRIGGER_NTFY_ONE_TOPIC": "NnlZCpSXEKRvLSfw",
9+
"WUD_TRIGGER_NTFY_TWO_TOPIC": "NnlZCpSXEKRvLSfw",
10+
"WUD_TRIGGER_NTFY_THREE_TOPIC": "NnlZCpSXEKRvLSfw"
811
}
912
}

docs/api/trigger.md

+9-1
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ curl http://wud:3000/api/triggers
3131
This operation lets you get a specific Trigger.
3232

3333
```bash
34-
curl http://wud:3000/api/triggers/smtp.gmail
34+
curl http://wud:3000/api/triggers/smtp/gmail
3535

3636
{
3737
"id":"smtp.gmail",
@@ -47,3 +47,11 @@ curl http://wud:3000/api/triggers/smtp.gmail
4747
}
4848
}
4949
```
50+
51+
## Running a trigger
52+
This operation lets you run a specific Trigger with simulated data.
53+
54+
```bash
55+
export CONTAINER='{"id":"123456789","name":"container_test","watcher":"watcher_test","updateKind":{"kind":"tag","semverDiff":"patch","localValue":"1.2.3","remoteValue":"1.2.4","result":{"link":"https://my-container/release-notes/"}}}'
56+
curl -X POST -H "Content-Type: application/json" -d $CONTAINER http://wud:3000/api/triggers/smtp/gmail
57+
```

docs/api/watcher.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ curl http://wud:3000/api/watchers
2929
This operation lets you get a specific Watcher.
3030

3131
```bash
32-
curl http://wud:3000/api/watchers/docker.local
32+
curl http://wud:3000/api/watchers/docker/local
3333

3434
[
3535
{

docs/changelog/README.md

+1
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
# 7.1.2 (wip)
44
- :star: [UI] - Some ux improvements
5+
- :star: [UI/API] - Add support for manually running triggers to help with configuration
56

67
# 7.1.1
78
- :fire: [NTFY] - Fix basic/bearer authentication

e2e/features/api-authentications.feature

+1-1
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ Feature: WUD Authentications API Exposure
1212
And response body path $[0].configuration.hash should be .\*.*.
1313

1414
Scenario: WUD must allow to get specific Authentication state
15-
When I GET /api/authentications/authentication.basic.john
15+
When I GET /api/authentications/basic/john
1616
Then response code should be 200
1717
And response body should be valid json
1818
And response body path $.id should be authentication.basic.john

e2e/features/api-container.feature

+6-6
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,9 @@ Feature: WUD Container API Exposure
2121
| 0 | ecr | ecr_sub_sub_test | https://229211676173.dkr.ecr.eu-west-1.amazonaws.com/v2 | sub/sub/test | 1.0.0 | 2.0.0 | true |
2222
| 1 | ecr | ecr_sub_test | https://229211676173.dkr.ecr.eu-west-1.amazonaws.com/v2 | sub/test | 1.0.0 | 2.0.0 | true |
2323
| 2 | ecr | ecr_test | https://229211676173.dkr.ecr.eu-west-1.amazonaws.com/v2 | test | 1.0.0 | 2.0.0 | true |
24-
| 3 | ghcr | ghcr_radarr | https://ghcr.io/v2 | linuxserver/radarr | 3.2.1.5070-ls105 | 5.15.1.9463-ls246 | true |
24+
| 3 | ghcr | ghcr_radarr | https://ghcr.io/v2 | linuxserver/radarr | 3.2.1.5070-ls105 | 5.15.1.9463-ls247 | true |
2525
| 4 | gitlab | gitlab_test | https://registry.gitlab.com/v2 | manfred-martin/docker-registry-test | 1.0.0 | 2.0.0 | true |
26-
| 5 | hub | hub_homeassistant_202161 | https://registry-1.docker.io/v2 | homeassistant/home-assistant | 2021.6.1 | 2024.11.3 | true |
26+
| 5 | hub | hub_homeassistant_202161 | https://registry-1.docker.io/v2 | homeassistant/home-assistant | 2021.6.1 | 2024.12.1 | true |
2727
| 6 | hub | hub_homeassistant_latest | https://registry-1.docker.io/v2 | homeassistant/home-assistant | latest | latest | false |
2828
| 7 | hub | hub_nginx_120 | https://registry-1.docker.io/v2 | library/nginx | 1.20-alpine | 1.27-alpine | true |
2929
| 8 | hub | hub_nginx_latest | https://registry-1.docker.io/v2 | library/nginx | latest | latest | true |
@@ -36,8 +36,8 @@ Feature: WUD Container API Exposure
3636
| 15 | hub | hub_vaultwarden_1222 | https://registry-1.docker.io/v2 | vaultwarden/server | 1.32.5-alpine | 1.32.5-alpine | false |
3737
| 16 | hub | hub_vaultwarden_latest | https://registry-1.docker.io/v2 | vaultwarden/server | latest | latest | false |
3838
| 17 | hub | hub_youtubedb_latest | https://registry-1.docker.io/v2 | jeeaaasustest/youtube-dl | latest | latest | false |
39-
| 18 | lscr | lscr_radarr | https://lscr.io/v2 | linuxserver/radarr | 3.2.1.5070-ls105 | 5.15.1.9463-ls246 | true |
40-
| 19 | quay | quay_prometheus | https://quay.io/v2 | prometheus/prometheus | v2.52.0 | v3.0.0 | true |
39+
| 18 | lscr | lscr_radarr | https://lscr.io/v2 | linuxserver/radarr | 3.2.1.5070-ls105 | 5.15.1.9463-ls247 | true |
40+
| 19 | quay | quay_prometheus | https://quay.io/v2 | prometheus/prometheus | v2.52.0 | v3.0.1 | true |
4141

4242
Scenario: WUD must allow to get a container with semver
4343
Given I GET /api/containers
@@ -75,7 +75,7 @@ Feature: WUD Container API Exposure
7575
And response body path $.image.tag.semver should be false
7676
And response body path $.image.digest.value should be sha256:f94d6dd9b5761f33a21bb92848a1f70ea11a1c15f3a142c19a44ea3a4c545a4d
7777
And response body path $.result.tag should be latest
78-
And response body path $.result.digest should be sha256:5341b734e75ce46bbb8e02476434217fd771e23df9a4bfea756a6f3a4a521d3e
78+
And response body path $.result.digest should be sha256:3d696e8357051647b844d8c7cf4a0aa71e84379999a4f6af9b8ca1f7919ade42
7979
And response body path $.updateAvailable should be true
8080

8181
Scenario: WUD must allow to get a container with its link
@@ -85,7 +85,7 @@ Feature: WUD Container API Exposure
8585
Then response code should be 200
8686
And response body should be valid json
8787
And response body path $.link should be https://github.com/home-assistant/core/releases/tag/2021.6.1
88-
And response body path $.result.link should be https://github.com/home-assistant/core/releases/tag/2024.11.3
88+
And response body path $.result.link should be https://github.com/home-assistant/core/releases/tag/2024.12.1
8989

9090
Scenario: WUD must allow to trigger a watch on a container
9191
Given I GET /api/containers

e2e/features/api-trigger.feature

+1-1
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ Feature: WUD Trigger API Exposure
1616
And response body path $[0].configuration.mock should be mock
1717

1818
Scenario: WUD must allow to get specific Triggers state
19-
When I GET /api/triggers/trigger.mock.example
19+
When I GET /api/triggers/mock/example
2020
Then response code should be 200
2121
And response body should be valid json
2222
And response body path $.id should be trigger.mock.example

e2e/features/api-watcher.feature

+1-1
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ Feature: WUD Watcher API Exposure
1313
And response body path $[0].configuration.watchbydefault should be false
1414

1515
Scenario: WUD must allow to get specific Watcher state
16-
When I GET /api/watchers/watcher.docker.local
16+
When I GET /api/watchers/docker/local
1717
Then response code should be 200
1818
And response body should be valid json
1919
And response body path $.id should be watcher.docker.local

e2e/features/prometheus.feature

+4-4
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,9 @@ Feature: Prometheus exposure
2525
| ecr_sub_sub_test | ecr | https://229211676173.dkr.ecr.eu-west-1.amazonaws.com/v2 | sub/sub/test | 1.0.0 | 2.0.0 | true |
2626
| ecr_sub_test | ecr | https://229211676173.dkr.ecr.eu-west-1.amazonaws.com/v2 | sub/test | 1.0.0 | 2.0.0 | true |
2727
| ecr_test | ecr | https://229211676173.dkr.ecr.eu-west-1.amazonaws.com/v2 | test | 1.0.0 | 2.0.0 | true |
28-
| ghcr_radarr | ghcr | https://ghcr.io/v2 | linuxserver/radarr | 3.2.1.5070-ls105 |5.15.1.9463-ls246 | true |
28+
| ghcr_radarr | ghcr | https://ghcr.io/v2 | linuxserver/radarr | 3.2.1.5070-ls105 |5.15.1.9463-ls247 | true |
2929
| gitlab_test | gitlab | https://registry.gitlab.com/v2 | manfred-martin/docker-registry-test | 1.0.0 | 2.0.0 | true |
30-
| hub_homeassistant_202161 | hub | https://registry-1.docker.io/v2 | homeassistant/home-assistant | 2021.6.1 | 2024.11.3 | true |
30+
| hub_homeassistant_202161 | hub | https://registry-1.docker.io/v2 | homeassistant/home-assistant | 2021.6.1 | 2024.12.1 | true |
3131
| hub_homeassistant_latest | hub | https://registry-1.docker.io/v2 | homeassistant/home-assistant | latest | latest | false |
3232
| hub_nginx_120 | hub | https://registry-1.docker.io/v2 | library/nginx | 1.20-alpine | 1.27-alpine | true |
3333
| hub_nginx_latest | hub | https://registry-1.docker.io/v2 | library/nginx | latest | latest | true |
@@ -40,5 +40,5 @@ Feature: Prometheus exposure
4040
| hub_vaultwarden_1222 | hub | https://registry-1.docker.io/v2 | vaultwarden/server | 1.32.5-alpine | 1.32.5-alpine | false |
4141
| hub_vaultwarden_latest | hub | https://registry-1.docker.io/v2 | vaultwarden/server | latest | latest | false |
4242
| hub_youtubedb_latest | hub | https://registry-1.docker.io/v2 | jeeaaasustest/youtube-dl | latest | latest | false |
43-
| lscr_radarr | lscr | https://lscr.io/v2 | linuxserver/radarr | 3.2.1.5070-ls105 |5.15.1.9463-ls246 | true |
44-
| quay_prometheus | quay | https://quay.io/v2 | prometheus/prometheus | v2.52.0 |v3.0.0 | true |
43+
| lscr_radarr | lscr | https://lscr.io/v2 | linuxserver/radarr | 3.2.1.5070-ls105 |5.15.1.9463-ls247 | true |
44+
| quay_prometheus | quay | https://quay.io/v2 | prometheus/prometheus | v2.52.0 |v3.0.1 | true |

0 commit comments

Comments
 (0)