@platformatic/watt-extra 0.1.0 → 0.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.github/workflows/test.yml +58 -0
- package/README.md +15 -15
- package/app.js +4 -4
- package/lib/{wattpro.js → watt.js} +4 -4
- package/package.json +3 -3
- package/plugins/alerts.js +1 -1
- package/plugins/auth.js +1 -1
- package/plugins/compliancy.js +1 -1
- package/plugins/flamegraphs.js +2 -2
- package/plugins/init.js +6 -6
- package/plugins/metadata.js +1 -1
- package/plugins/scheduler.js +1 -1
- package/plugins/update.js +1 -1
- package/test/alerts.test.js +10 -10
- package/test/health.test.js +1 -1
- package/test/patch-config.test.js +13 -13
- package/test/scheduler.test.js +1 -1
- package/test/trigger-flamegraphs.test.js +5 -5
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
name: Test
|
|
2
|
+
on:
|
|
3
|
+
pull_request:
|
|
4
|
+
paths-ignore:
|
|
5
|
+
- "**.md"
|
|
6
|
+
workflow_dispatch:
|
|
7
|
+
|
|
8
|
+
concurrency:
|
|
9
|
+
group: "${{ github.workflow }} @ ${{ github.event.pull_request.head.label || github.head_ref || github.ref }}"
|
|
10
|
+
cancel-in-progress: true
|
|
11
|
+
|
|
12
|
+
permissions:
|
|
13
|
+
packages: write
|
|
14
|
+
contents: read
|
|
15
|
+
|
|
16
|
+
jobs:
|
|
17
|
+
test:
|
|
18
|
+
name: Test
|
|
19
|
+
runs-on: ubuntu-latest
|
|
20
|
+
timeout-minutes: 15
|
|
21
|
+
|
|
22
|
+
services:
|
|
23
|
+
valkey:
|
|
24
|
+
image: "valkey/valkey:9.0"
|
|
25
|
+
ports:
|
|
26
|
+
- "6379:6379"
|
|
27
|
+
options: >-
|
|
28
|
+
--health-cmd "valkey-cli ping"
|
|
29
|
+
--health-interval 10s
|
|
30
|
+
--health-timeout 5s
|
|
31
|
+
--health-retries 5
|
|
32
|
+
|
|
33
|
+
strategy:
|
|
34
|
+
matrix:
|
|
35
|
+
node-version: [22.x, 24.x]
|
|
36
|
+
|
|
37
|
+
steps:
|
|
38
|
+
- uses: actions/checkout@v5
|
|
39
|
+
- uses: pnpm/action-setup@v4.1.0
|
|
40
|
+
with:
|
|
41
|
+
version: 10
|
|
42
|
+
|
|
43
|
+
- name: Use Node.js ${{ matrix.node-version }}
|
|
44
|
+
uses: actions/setup-node@v4
|
|
45
|
+
with:
|
|
46
|
+
node-version: ${{ matrix.node-version }}
|
|
47
|
+
# https://github.com/actions/setup-node/blob/main/docs/advanced-usage.md#use-private-packages
|
|
48
|
+
registry-url: "https://registry.npmjs.org"
|
|
49
|
+
|
|
50
|
+
- name: Install
|
|
51
|
+
run: |
|
|
52
|
+
pnpm install
|
|
53
|
+
env:
|
|
54
|
+
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
|
|
55
|
+
|
|
56
|
+
- name: Test
|
|
57
|
+
run: |
|
|
58
|
+
pnpm run test
|
package/README.md
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Watt-Extra
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Watt-Extra is an enterprise-ready runtime manager for Platformatic applications that provides production-grade capabilities including monitoring, compliance checking, caching, authentication, and integration with Infrastructure Control Center (ICC) services.
|
|
4
4
|
|
|
5
5
|
## Overview
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
Watt-Extra wraps existing Platformatic applications (Service, Composer, Node, or Next.js) to enhance them with enterprise features without requiring any code changes. It acts as a transparent layer that:
|
|
8
8
|
|
|
9
9
|
- **Monitors** application performance and health metrics
|
|
10
10
|
- **Enforces** compliance policies and security rules
|
|
@@ -23,7 +23,7 @@ None.
|
|
|
23
23
|
|
|
24
24
|
### Optional
|
|
25
25
|
|
|
26
|
-
- `PLT_ICC_URL` - Infrastructure Control Center URL for connecting to control plane services. When not set,
|
|
26
|
+
- `PLT_ICC_URL` - Infrastructure Control Center URL for connecting to control plane services. When not set, Watt-Extra runs in standalone mode without ICC integration
|
|
27
27
|
- `PLT_APP_NAME` - Unique identifier for your application instance. Optional when `PLT_ICC_URL` is set - if not provided, it will be automatically determined from Kubernetes labels following these rules:
|
|
28
28
|
1. Uses `app.kubernetes.io/instance` label first
|
|
29
29
|
2. Falls back to ReplicaSet naming convention (`{app-name}-{hash}`)
|
|
@@ -34,7 +34,7 @@ None.
|
|
|
34
34
|
|
|
35
35
|
### Standalone Mode
|
|
36
36
|
|
|
37
|
-
|
|
37
|
+
Watt-Extra can run without connecting to an Infrastructure Control Center (ICC). When `PLT_ICC_URL` is not set:
|
|
38
38
|
|
|
39
39
|
- No ICC connection attempts are made
|
|
40
40
|
- All ICC-dependent plugins (alerts, compliance, metadata, scheduler) skip their operations
|
|
@@ -43,7 +43,7 @@ WattPro can run without connecting to an Infrastructure Control Center (ICC). Wh
|
|
|
43
43
|
## Installation
|
|
44
44
|
|
|
45
45
|
```bash
|
|
46
|
-
npm install @platformatic/
|
|
46
|
+
npm install @platformatic/watt-extra
|
|
47
47
|
```
|
|
48
48
|
|
|
49
49
|
## Usage
|
|
@@ -52,36 +52,36 @@ Add a script to your package.json:
|
|
|
52
52
|
|
|
53
53
|
```json
|
|
54
54
|
"scripts": {
|
|
55
|
-
"
|
|
55
|
+
"watt-extra": "watt-extra start"
|
|
56
56
|
}
|
|
57
57
|
```
|
|
58
58
|
|
|
59
59
|
Then run:
|
|
60
60
|
|
|
61
61
|
```bash
|
|
62
|
-
npm run
|
|
62
|
+
npm run watt-extra
|
|
63
63
|
```
|
|
64
64
|
|
|
65
65
|
### Command Line Interface
|
|
66
66
|
|
|
67
|
-
|
|
67
|
+
Watt-Extra provides a command-line interface:
|
|
68
68
|
|
|
69
69
|
```bash
|
|
70
70
|
# Show help
|
|
71
|
-
|
|
71
|
+
watt-extra --help
|
|
72
72
|
|
|
73
73
|
# Start the runtime manager
|
|
74
|
-
|
|
74
|
+
watt-extra start
|
|
75
75
|
|
|
76
76
|
# Set log level
|
|
77
|
-
|
|
77
|
+
watt-extra start --log-level=debug
|
|
78
78
|
|
|
79
79
|
# Set ICC URL
|
|
80
|
-
|
|
80
|
+
watt-extra start --icc-url=http://icc-server:3000
|
|
81
81
|
|
|
82
82
|
# Set application name
|
|
83
|
-
|
|
83
|
+
watt-extra start --app-name=my-application
|
|
84
84
|
|
|
85
85
|
# Set application directory. This is useful for development and test
|
|
86
|
-
|
|
86
|
+
watt-extra start --app-dir=/path/to/application
|
|
87
87
|
```
|
package/app.js
CHANGED
|
@@ -34,7 +34,7 @@ async function buildApp (logger) {
|
|
|
34
34
|
app.log.info('Starting Runtime -app')
|
|
35
35
|
try {
|
|
36
36
|
app.log.info('Spawning the app')
|
|
37
|
-
await app.
|
|
37
|
+
await app.watt.spawn()
|
|
38
38
|
} catch (err) {
|
|
39
39
|
app.log.error(err, 'Failed to spawn the app')
|
|
40
40
|
throw new Error('Failed to spawn the app: ' + err.message)
|
|
@@ -48,7 +48,7 @@ async function buildApp (logger) {
|
|
|
48
48
|
return
|
|
49
49
|
}
|
|
50
50
|
|
|
51
|
-
if (!app.
|
|
51
|
+
if (!app.watt.runtime) {
|
|
52
52
|
throw new Error('Runtime not started, cannot send to ICC')
|
|
53
53
|
}
|
|
54
54
|
try {
|
|
@@ -112,8 +112,8 @@ async function buildApp (logger) {
|
|
|
112
112
|
|
|
113
113
|
app.close = async function close () {
|
|
114
114
|
app.log.info('Closing runtime')
|
|
115
|
-
if (app.
|
|
116
|
-
await app.
|
|
115
|
+
if (app.watt.runtime) {
|
|
116
|
+
await app.watt.close()
|
|
117
117
|
}
|
|
118
118
|
await app.closeUpdates()
|
|
119
119
|
}
|
|
@@ -26,7 +26,7 @@ async function restartRuntime (runtime) {
|
|
|
26
26
|
}
|
|
27
27
|
}
|
|
28
28
|
|
|
29
|
-
class
|
|
29
|
+
class Watt {
|
|
30
30
|
#env
|
|
31
31
|
#logger
|
|
32
32
|
#require
|
|
@@ -340,7 +340,7 @@ class WattPro {
|
|
|
340
340
|
}
|
|
341
341
|
|
|
342
342
|
return {
|
|
343
|
-
module: this.#require.resolve('
|
|
343
|
+
module: this.#require.resolve('undici-slicer-interceptor'),
|
|
344
344
|
options: cacheConfig,
|
|
345
345
|
}
|
|
346
346
|
}
|
|
@@ -406,7 +406,7 @@ class WattPro {
|
|
|
406
406
|
config.httpCache = {
|
|
407
407
|
...config.httpCache,
|
|
408
408
|
cacheTagsHeader,
|
|
409
|
-
store: this.#require.resolve('
|
|
409
|
+
store: this.#require.resolve('undici-cache-redis'),
|
|
410
410
|
clientOpts: httpCache,
|
|
411
411
|
}
|
|
412
412
|
}
|
|
@@ -577,4 +577,4 @@ class WattPro {
|
|
|
577
577
|
}
|
|
578
578
|
}
|
|
579
579
|
|
|
580
|
-
export default
|
|
580
|
+
export default Watt
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@platformatic/watt-extra",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.2",
|
|
4
4
|
"description": "The Platformatic runtime manager",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"scripts": {
|
|
@@ -31,9 +31,9 @@
|
|
|
31
31
|
"@datadog/pprof": "^5.9.0",
|
|
32
32
|
"@fastify/error": "^4.2.0",
|
|
33
33
|
"@platformatic/runtime": "^3.0.1",
|
|
34
|
-
"@platformatic/slicer-interceptor": "^0.3.0",
|
|
35
|
-
"@platformatic/undici-cache-redis": "^0.7.1",
|
|
36
34
|
"@platformatic/wattpm-pprof-capture": "^3.0.1",
|
|
35
|
+
"undici-cache-redis": "^1.0.0",
|
|
36
|
+
"undici-slicer-interceptor": "^0.4.1",
|
|
37
37
|
"undici-traffic-interceptor": "^0.1.4",
|
|
38
38
|
"avvio": "^9.1.0",
|
|
39
39
|
"chalk": "^4.1.2",
|
package/plugins/alerts.js
CHANGED
package/plugins/auth.js
CHANGED
|
@@ -52,7 +52,7 @@ async function authPlugin (app) {
|
|
|
52
52
|
app.log.info('JWT token expired, reloading')
|
|
53
53
|
app.token = await loadToken()
|
|
54
54
|
|
|
55
|
-
app.
|
|
55
|
+
app.watt?.updateSharedContext({
|
|
56
56
|
iccAuthHeaders: { authorization: `Bearer ${app.token}` }
|
|
57
57
|
}).catch((err) => {
|
|
58
58
|
app.log.error({ err }, 'Failed to update jwt token in shared context')
|
package/plugins/compliancy.js
CHANGED
package/plugins/flamegraphs.js
CHANGED
|
@@ -16,7 +16,7 @@ async function flamegraphs (app, _opts) {
|
|
|
16
16
|
|
|
17
17
|
app.log.info('Start profiling services')
|
|
18
18
|
|
|
19
|
-
const runtime = app.
|
|
19
|
+
const runtime = app.watt.runtime
|
|
20
20
|
const { applications } = await runtime.getApplications()
|
|
21
21
|
|
|
22
22
|
const promises = []
|
|
@@ -52,7 +52,7 @@ async function flamegraphs (app, _opts) {
|
|
|
52
52
|
}
|
|
53
53
|
|
|
54
54
|
const podId = app.instanceId
|
|
55
|
-
const runtime = app.
|
|
55
|
+
const runtime = app.watt.runtime
|
|
56
56
|
|
|
57
57
|
if (!serviceIds) {
|
|
58
58
|
const { applications } = await runtime.getApplications()
|
package/plugins/init.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import
|
|
1
|
+
import Watt from '../lib/watt.js'
|
|
2
2
|
import os from 'node:os'
|
|
3
3
|
|
|
4
4
|
async function initPlugin (app) {
|
|
@@ -17,13 +17,13 @@ async function initPlugin (app) {
|
|
|
17
17
|
}
|
|
18
18
|
|
|
19
19
|
async function initApplication () {
|
|
20
|
-
app.log.info('Starting
|
|
20
|
+
app.log.info('Starting Watt-Extra runtime manager')
|
|
21
21
|
|
|
22
22
|
let applicationName = app.env.PLT_APP_NAME
|
|
23
23
|
const applicationDir = app.env.PLT_APP_DIR
|
|
24
24
|
const instanceId = os.hostname()
|
|
25
25
|
|
|
26
|
-
app.log.info({ applicationName, applicationDir }, 'Loading
|
|
26
|
+
app.log.info({ applicationName, applicationDir }, 'Loading watt-extra application')
|
|
27
27
|
|
|
28
28
|
// Skip ICC initialization if PLT_ICC_URL is not set
|
|
29
29
|
if (!app.env.PLT_ICC_URL) {
|
|
@@ -59,12 +59,12 @@ async function initPlugin (app) {
|
|
|
59
59
|
app.instanceId = os.hostname()
|
|
60
60
|
}
|
|
61
61
|
}
|
|
62
|
-
const
|
|
63
|
-
app.
|
|
62
|
+
const watt = new Watt(app)
|
|
63
|
+
app.watt = watt
|
|
64
64
|
app.initApplication = initApplication
|
|
65
65
|
|
|
66
66
|
const headers = await app.getAuthorizationHeader()
|
|
67
|
-
await app.
|
|
67
|
+
await app.watt.updateSharedContext({ iccAuthHeaders: headers })
|
|
68
68
|
}
|
|
69
69
|
|
|
70
70
|
export default initPlugin
|
package/plugins/metadata.js
CHANGED
|
@@ -15,7 +15,7 @@ async function metadata (app, _opts) {
|
|
|
15
15
|
}
|
|
16
16
|
|
|
17
17
|
const applicationId = app.instanceConfig?.applicationId
|
|
18
|
-
const runtime = app.
|
|
18
|
+
const runtime = app.watt.runtime
|
|
19
19
|
if (!applicationId) {
|
|
20
20
|
app.log.warn('Cannot process metadata: no applicationId available')
|
|
21
21
|
throw new MetadataAppIdError()
|
package/plugins/scheduler.js
CHANGED
|
@@ -8,7 +8,7 @@ async function scheduler (app, _opts) {
|
|
|
8
8
|
|
|
9
9
|
try {
|
|
10
10
|
const applicationId = app.instanceConfig?.applicationId
|
|
11
|
-
const runtime = app.
|
|
11
|
+
const runtime = app.watt.runtime
|
|
12
12
|
const config = await runtime.getRuntimeConfig()
|
|
13
13
|
const { default: build, setDefaultHeaders } = await import('../clients/cron/cron.mjs')
|
|
14
14
|
|
package/plugins/update.js
CHANGED
|
@@ -112,7 +112,7 @@ async function updatePlugin (app) {
|
|
|
112
112
|
}
|
|
113
113
|
|
|
114
114
|
app.updateConfig = async (message) => {
|
|
115
|
-
await app.
|
|
115
|
+
await app.watt.applyIccConfigUpdates(message.data)
|
|
116
116
|
}
|
|
117
117
|
|
|
118
118
|
app.connectToUpdates = connectToUpdates
|
package/test/alerts.test.js
CHANGED
|
@@ -82,7 +82,7 @@ test('should send alert when service becomes unhealthy', async (t) => {
|
|
|
82
82
|
}
|
|
83
83
|
}
|
|
84
84
|
|
|
85
|
-
app.
|
|
85
|
+
app.watt.runtime.emit('health', healthInfo)
|
|
86
86
|
|
|
87
87
|
await sleep(200)
|
|
88
88
|
|
|
@@ -158,7 +158,7 @@ test('should not send alert when service is healthy', async (t) => {
|
|
|
158
158
|
}
|
|
159
159
|
}
|
|
160
160
|
|
|
161
|
-
app.
|
|
161
|
+
app.watt.runtime.emit('health', healthInfo)
|
|
162
162
|
|
|
163
163
|
await sleep(200)
|
|
164
164
|
|
|
@@ -227,7 +227,7 @@ test('should cache health data and include it in alerts', async (t) => {
|
|
|
227
227
|
}
|
|
228
228
|
}
|
|
229
229
|
|
|
230
|
-
app.
|
|
230
|
+
app.watt.runtime.emit('health', healthyInfo)
|
|
231
231
|
await sleep(100) // Small delay between events
|
|
232
232
|
}
|
|
233
233
|
|
|
@@ -252,7 +252,7 @@ test('should cache health data and include it in alerts', async (t) => {
|
|
|
252
252
|
}
|
|
253
253
|
}
|
|
254
254
|
|
|
255
|
-
app.
|
|
255
|
+
app.watt.runtime.emit('health', unhealthyInfo)
|
|
256
256
|
await sleep(200)
|
|
257
257
|
|
|
258
258
|
assert.ok(alertReceived, 'Alert should have been received')
|
|
@@ -320,7 +320,7 @@ test('should not fail when health info is missing', async (t) => {
|
|
|
320
320
|
await icc.close()
|
|
321
321
|
})
|
|
322
322
|
|
|
323
|
-
app.
|
|
323
|
+
app.watt.runtime.emit('health', null)
|
|
324
324
|
|
|
325
325
|
await sleep(200)
|
|
326
326
|
|
|
@@ -393,11 +393,11 @@ test('should respect alert retention window', async (t) => {
|
|
|
393
393
|
})
|
|
394
394
|
|
|
395
395
|
// Send first unhealthy event - should trigger alert
|
|
396
|
-
app.
|
|
396
|
+
app.watt.runtime.emit('health', createHealthInfo(true))
|
|
397
397
|
await sleep(100)
|
|
398
398
|
|
|
399
399
|
// Send second unhealthy event immediately - should be ignored due to retention window
|
|
400
|
-
app.
|
|
400
|
+
app.watt.runtime.emit('health', createHealthInfo(true))
|
|
401
401
|
await sleep(100)
|
|
402
402
|
|
|
403
403
|
assert.strictEqual(alertsReceived.length, 1, 'Only one alert should be sent within retention window')
|
|
@@ -405,7 +405,7 @@ test('should respect alert retention window', async (t) => {
|
|
|
405
405
|
await sleep(500)
|
|
406
406
|
|
|
407
407
|
// Send third unhealthy event - should trigger second alert
|
|
408
|
-
app.
|
|
408
|
+
app.watt.runtime.emit('health', createHealthInfo(true))
|
|
409
409
|
await sleep(100)
|
|
410
410
|
|
|
411
411
|
assert.strictEqual(alertsReceived.length, 2, 'Second alert should be sent after retention window expires')
|
|
@@ -514,7 +514,7 @@ test('should send alert when flamegraphs are disabled', async (t) => {
|
|
|
514
514
|
}
|
|
515
515
|
}
|
|
516
516
|
|
|
517
|
-
app.
|
|
517
|
+
app.watt.runtime.emit('health', healthInfo)
|
|
518
518
|
|
|
519
519
|
await sleep(200)
|
|
520
520
|
|
|
@@ -593,7 +593,7 @@ test('should send alert when failed to send a flamegraph', async (t) => {
|
|
|
593
593
|
}
|
|
594
594
|
}
|
|
595
595
|
|
|
596
|
-
app.
|
|
596
|
+
app.watt.runtime.emit('health', healthInfo)
|
|
597
597
|
|
|
598
598
|
await sleep(200)
|
|
599
599
|
|
package/test/health.test.js
CHANGED
|
@@ -35,7 +35,7 @@ test('check that health is configured in runtime', async (t) => {
|
|
|
35
35
|
await icc.close()
|
|
36
36
|
})
|
|
37
37
|
|
|
38
|
-
const runtimeConfig = await app.
|
|
38
|
+
const runtimeConfig = await app.watt.runtime.getRuntimeConfig()
|
|
39
39
|
|
|
40
40
|
assert.ok(runtimeConfig.health, 'Health configuration should be present')
|
|
41
41
|
assert.strictEqual(runtimeConfig.health.enabled, true, 'Health monitoring should be enabled')
|
|
@@ -35,7 +35,7 @@ test('should spawn a service app settings labels for metrics', async (t) => {
|
|
|
35
35
|
await icc.close()
|
|
36
36
|
})
|
|
37
37
|
|
|
38
|
-
const mainConfig = app.
|
|
38
|
+
const mainConfig = app.watt.runtime.getRuntimeConfig(true)
|
|
39
39
|
|
|
40
40
|
const { metrics, telemetry } = mainConfig
|
|
41
41
|
|
|
@@ -122,7 +122,7 @@ test('should configure system resources', async (t) => {
|
|
|
122
122
|
await app.close()
|
|
123
123
|
await icc.close()
|
|
124
124
|
})
|
|
125
|
-
const config = await app.
|
|
125
|
+
const config = await app.watt.runtime.getRuntimeConfig(true)
|
|
126
126
|
|
|
127
127
|
// Check generic resources
|
|
128
128
|
assert.strictEqual(config.workers, 1)
|
|
@@ -162,13 +162,13 @@ test('should remove server https configs', async (t) => {
|
|
|
162
162
|
})
|
|
163
163
|
|
|
164
164
|
{
|
|
165
|
-
const mainConfig = app.
|
|
165
|
+
const mainConfig = app.watt.runtime.getRuntimeConfig(true)
|
|
166
166
|
const { server } = mainConfig
|
|
167
167
|
assert.strictEqual(server.https, undefined)
|
|
168
168
|
}
|
|
169
169
|
|
|
170
170
|
{
|
|
171
|
-
const runtimeConfig = await app.
|
|
171
|
+
const runtimeConfig = await app.watt.runtime.getRuntimeConfig(true)
|
|
172
172
|
|
|
173
173
|
const { server } = runtimeConfig
|
|
174
174
|
assert.strictEqual(server.https, undefined)
|
|
@@ -199,7 +199,7 @@ test('should configure health options', async (t) => {
|
|
|
199
199
|
await icc.close()
|
|
200
200
|
})
|
|
201
201
|
|
|
202
|
-
const runtimeConfig = await app.
|
|
202
|
+
const runtimeConfig = await app.watt.runtime.getRuntimeConfig(true)
|
|
203
203
|
|
|
204
204
|
const { health } = runtimeConfig
|
|
205
205
|
assert.strictEqual(health.enabled, true)
|
|
@@ -233,12 +233,12 @@ test('should call updateServicesResources with maxHeapTotal', async (t) => {
|
|
|
233
233
|
|
|
234
234
|
const updateCalls = []
|
|
235
235
|
const originalUpdateServicesResources =
|
|
236
|
-
app.
|
|
237
|
-
app.
|
|
236
|
+
app.watt.runtime.updateServicesResources
|
|
237
|
+
app.watt.runtime.updateServicesResources = async (resourceUpdates) => {
|
|
238
238
|
updateCalls.push(resourceUpdates)
|
|
239
239
|
if (originalUpdateServicesResources) {
|
|
240
240
|
return originalUpdateServicesResources.call(
|
|
241
|
-
app.
|
|
241
|
+
app.watt.runtime,
|
|
242
242
|
resourceUpdates
|
|
243
243
|
)
|
|
244
244
|
}
|
|
@@ -253,7 +253,7 @@ test('should call updateServicesResources with maxHeapTotal', async (t) => {
|
|
|
253
253
|
},
|
|
254
254
|
}
|
|
255
255
|
|
|
256
|
-
await app.
|
|
256
|
+
await app.watt.applyIccConfigUpdates(config)
|
|
257
257
|
|
|
258
258
|
assert.strictEqual(
|
|
259
259
|
updateCalls.length,
|
|
@@ -302,7 +302,7 @@ test('should handle updateServicesResources with different heap sizes', async (t
|
|
|
302
302
|
})
|
|
303
303
|
|
|
304
304
|
const updateCalls = []
|
|
305
|
-
app.
|
|
305
|
+
app.watt.runtime.updateServicesResources = async (resourceUpdates) => {
|
|
306
306
|
updateCalls.push(resourceUpdates)
|
|
307
307
|
}
|
|
308
308
|
|
|
@@ -318,7 +318,7 @@ test('should handle updateServicesResources with different heap sizes', async (t
|
|
|
318
318
|
]
|
|
319
319
|
|
|
320
320
|
for (const config of configs) {
|
|
321
|
-
await app.
|
|
321
|
+
await app.watt.applyIccConfigUpdates(config)
|
|
322
322
|
}
|
|
323
323
|
|
|
324
324
|
assert.strictEqual(updateCalls.length, 1)
|
|
@@ -353,7 +353,7 @@ test('should handle updateServicesResources error gracefully', async (t) => {
|
|
|
353
353
|
})
|
|
354
354
|
|
|
355
355
|
let errorThrown = false
|
|
356
|
-
app.
|
|
356
|
+
app.watt.runtime.updateServicesResources = async (resourceUpdates) => {
|
|
357
357
|
assert.strictEqual(resourceUpdates[0].health.maxHeapTotal, '256MB')
|
|
358
358
|
errorThrown = true
|
|
359
359
|
throw new Error('Mock update error')
|
|
@@ -365,7 +365,7 @@ test('should handle updateServicesResources error gracefully', async (t) => {
|
|
|
365
365
|
},
|
|
366
366
|
}
|
|
367
367
|
|
|
368
|
-
await app.
|
|
368
|
+
await app.watt.applyIccConfigUpdates(config)
|
|
369
369
|
|
|
370
370
|
assert.strictEqual(
|
|
371
371
|
errorThrown,
|
package/test/scheduler.test.js
CHANGED
|
@@ -42,7 +42,7 @@ test('should spawn a runtime disabling all the scheduler jobs', async (t) => {
|
|
|
42
42
|
await icc.close()
|
|
43
43
|
})
|
|
44
44
|
|
|
45
|
-
const config = await app.
|
|
45
|
+
const config = await app.watt.runtime.getRuntimeConfig()
|
|
46
46
|
|
|
47
47
|
const { scheduler } = config
|
|
48
48
|
|
|
@@ -36,7 +36,7 @@ function setupMockIccServer (wss, receivedMessages, validateAuth = false) {
|
|
|
36
36
|
}
|
|
37
37
|
|
|
38
38
|
function createMockApp (port, includeScalerUrl = true) {
|
|
39
|
-
const
|
|
39
|
+
const mockWatt = {
|
|
40
40
|
runtime: {
|
|
41
41
|
getApplications: () => ({
|
|
42
42
|
applications: [{ id: 'service-1' }, { id: 'service-2' }],
|
|
@@ -65,7 +65,7 @@ function createMockApp (port, includeScalerUrl = true) {
|
|
|
65
65
|
PLT_DISABLE_FLAMEGRAPHS: false,
|
|
66
66
|
PLT_FLAMEGRAPHS_INTERVAL_SEC: 1
|
|
67
67
|
},
|
|
68
|
-
|
|
68
|
+
watt: mockWatt,
|
|
69
69
|
}
|
|
70
70
|
|
|
71
71
|
if (includeScalerUrl) {
|
|
@@ -102,7 +102,7 @@ test('should handle trigger-flamegraph command and upload flamegraphs from servi
|
|
|
102
102
|
|
|
103
103
|
const app = createMockApp(port)
|
|
104
104
|
|
|
105
|
-
app.
|
|
105
|
+
app.watt.runtime.sendCommandToApplication = async (
|
|
106
106
|
serviceId,
|
|
107
107
|
command
|
|
108
108
|
) => {
|
|
@@ -162,7 +162,7 @@ test('should handle trigger-flamegraph when no runtime is available', async (t)
|
|
|
162
162
|
)
|
|
163
163
|
|
|
164
164
|
const app = createMockApp(port + 1)
|
|
165
|
-
app.
|
|
165
|
+
app.watt.runtime = null
|
|
166
166
|
|
|
167
167
|
await updatePlugin(app)
|
|
168
168
|
await app.connectToUpdates()
|
|
@@ -195,7 +195,7 @@ test('should handle trigger-flamegraph when flamegraph upload fails', async (t)
|
|
|
195
195
|
|
|
196
196
|
const app = createMockApp(port + 2)
|
|
197
197
|
|
|
198
|
-
app.
|
|
198
|
+
app.watt.runtime.sendCommandToApplication = async (
|
|
199
199
|
serviceId,
|
|
200
200
|
command,
|
|
201
201
|
options
|