@toa.io/operations 1.0.0-alpha.274 → 1.0.0-alpha.277
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/CHANGELOG.md +20 -0
- package/package.json +8 -7
- package/src/deployment/.deployment/.describe/components.js +1 -5
- package/src/deployment/.deployment/.describe/compositions.js +3 -7
- package/src/deployment/.deployment/.describe/dependencies.js +1 -6
- package/src/deployment/.deployment/.describe/events.js +1 -5
- package/src/deployment/.deployment/.describe/index.js +4 -13
- package/src/deployment/.deployment/.describe/mounts.js +1 -5
- package/src/deployment/.deployment/.describe/resources.js +1 -5
- package/src/deployment/.deployment/.describe/services.js +2 -6
- package/src/deployment/.deployment/.describe/services.test.js +11 -11
- package/src/deployment/.deployment/.describe/variables.js +1 -5
- package/src/deployment/.deployment/declare.js +1 -5
- package/src/deployment/.deployment/describe.js +10 -10
- package/src/deployment/.deployment/index.js +3 -9
- package/src/deployment/.deployment/merge.js +1 -5
- package/src/deployment/.deployment/merge.test.js +10 -12
- package/src/deployment/chart/templates/mono.yaml +4 -0
- package/src/deployment/chart/templates/services.yaml +4 -0
- package/src/deployment/composition.js +1 -5
- package/src/deployment/deployment.js +10 -11
- package/src/deployment/factory.js +28 -22
- package/src/deployment/images/composition.Dockerfile +1 -1
- package/src/deployment/images/composition.js +11 -11
- package/src/deployment/images/factory.js +4 -8
- package/src/deployment/images/format.js +48 -0
- package/src/deployment/images/format.test.js +74 -0
- package/src/deployment/images/image.fixtures.js +11 -11
- package/src/deployment/images/image.js +7 -18
- package/src/deployment/images/image.test.js +6 -5
- package/src/deployment/images/index.js +1 -5
- package/src/deployment/images/mono.Dockerfile +1 -1
- package/src/deployment/images/mono.js +13 -12
- package/src/deployment/images/runtime-base.test.js +15 -14
- package/src/deployment/images/service.js +8 -8
- package/src/deployment/index.js +1 -5
- package/src/deployment/operator.js +2 -6
- package/src/deployment/operator.test.js +8 -7
- package/src/deployment/registry.js +3 -7
- package/src/deployment/registry.test.js +39 -37
- package/src/deployment/service.js +1 -5
- package/src/deployment/workspace.js +4 -8
- package/src/index.js +1 -3
- package/src/process.js +2 -6
- package/types/_deployment/composition.d.ts +1 -1
- package/types/_deployment/dependency.d.ts +1 -1
- package/types/_deployment/deployment.d.ts +3 -3
- package/types/_deployment/factory.d.ts +2 -2
- package/types/_deployment/images/factory.d.ts +2 -2
- package/types/_deployment/images/registry.d.ts +2 -2
- package/types/_deployment/operator.d.ts +2 -2
- package/types/_deployment/registry.d.ts +2 -2
- package/types/_deployment/service.d.ts +4 -1
- package/types/dependency.ts +2 -0
- package/types/index.ts +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,26 @@
|
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
|
4
4
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
|
5
5
|
|
|
6
|
+
# [1.0.0-alpha.277](https://github.com/toa-io/toa/compare/v1.0.0-alpha.276...v1.0.0-alpha.277) (2026-09-03)
|
|
7
|
+
|
|
8
|
+
### Bug Fixes
|
|
9
|
+
|
|
10
|
+
* read a manifest the way js-yaml read one before ([fcea1b2](https://github.com/toa-io/toa/commit/fcea1b21996d6efa6c3198acbfc9f70f1ce0c35c))
|
|
11
|
+
* settle what the module loader made asynchronous ([d4ab9df](https://github.com/toa-io/toa/commit/d4ab9dfb09e382da311dba08f52214e7645f4a6c))
|
|
12
|
+
* what the loader resolves, and what it will not ([1b8a02f](https://github.com/toa-io/toa/commit/1b8a02ff0a5e0f18ee62e3f71bc81116f86f9af1))
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
# [1.0.0-alpha.276](https://github.com/toa-io/toa/compare/v1.0.0-alpha.275...v1.0.0-alpha.276) (2026-09-03)
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
### Bug Fixes
|
|
19
|
+
|
|
20
|
+
* **operations:** let a deployment state that it has no probe ([477b483](https://github.com/toa-io/toa/commit/477b483560cf2464d486a78e432f8e9b47f011dd))
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
|
|
6
26
|
# [1.0.0-alpha.274](https://github.com/toa-io/toa/compare/v1.0.0-alpha.273...v1.0.0-alpha.274) (2026-09-02)
|
|
7
27
|
|
|
8
28
|
**Note:** Version bump only for package @toa.io/operations
|
package/package.json
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@toa.io/operations",
|
|
3
|
-
"version": "1.0.0-alpha.
|
|
3
|
+
"version": "1.0.0-alpha.277",
|
|
4
|
+
"type": "module",
|
|
4
5
|
"description": "Toa Deployment",
|
|
5
6
|
"homepage": "https://toa.io",
|
|
6
7
|
"author": {
|
|
@@ -27,11 +28,11 @@
|
|
|
27
28
|
"test": "echo \"Error: run tests from root\" && exit 1"
|
|
28
29
|
},
|
|
29
30
|
"dependencies": {
|
|
30
|
-
"@toa.io/generic": "1.0.0-alpha.
|
|
31
|
-
"@toa.io/norm": "1.0.0-alpha.
|
|
32
|
-
"execa": "
|
|
33
|
-
"fs-extra": "11.
|
|
34
|
-
"js-yaml": "4.
|
|
31
|
+
"@toa.io/generic": "1.0.0-alpha.277",
|
|
32
|
+
"@toa.io/norm": "1.0.0-alpha.277",
|
|
33
|
+
"execa": "10.0.1",
|
|
34
|
+
"fs-extra": "11.4.0",
|
|
35
|
+
"js-yaml": "5.4.1"
|
|
35
36
|
},
|
|
36
|
-
"gitHead": "
|
|
37
|
+
"gitHead": "0c0071418c2c56a44e621ba5ced5cdd23dff1738"
|
|
37
38
|
}
|
|
@@ -1,10 +1,8 @@
|
|
|
1
|
-
'use strict'
|
|
2
|
-
|
|
3
1
|
/**
|
|
4
2
|
* @param {toa.deployment.Composition[]} compositions
|
|
5
3
|
* @returns {string[]}
|
|
6
4
|
*/
|
|
7
|
-
const components = (compositions) => {
|
|
5
|
+
export const components = (compositions) => {
|
|
8
6
|
/** @type {Set<string>} */
|
|
9
7
|
const components = new Set()
|
|
10
8
|
|
|
@@ -16,5 +14,3 @@ const components = (compositions) => {
|
|
|
16
14
|
|
|
17
15
|
return Array.from(components)
|
|
18
16
|
}
|
|
19
|
-
|
|
20
|
-
exports.components = components
|
|
@@ -1,9 +1,7 @@
|
|
|
1
|
-
|
|
1
|
+
import { addVariables } from './variables.js'
|
|
2
|
+
import { addMounts } from './mounts.js'
|
|
2
3
|
|
|
3
|
-
|
|
4
|
-
const { addMounts } = require('./mounts')
|
|
5
|
-
|
|
6
|
-
function compositions (compositions, dependency) {
|
|
4
|
+
export function compositions (compositions, dependency) {
|
|
7
5
|
for (const composition of compositions) {
|
|
8
6
|
addVariables(composition, dependency.variables)
|
|
9
7
|
addMounts(composition, dependency.mounts)
|
|
@@ -12,5 +10,3 @@ function compositions (compositions, dependency) {
|
|
|
12
10
|
composition.probe ??= dependency.probe
|
|
13
11
|
}
|
|
14
12
|
}
|
|
15
|
-
|
|
16
|
-
exports.compositions = compositions
|
|
@@ -1,10 +1,8 @@
|
|
|
1
|
-
'use strict'
|
|
2
|
-
|
|
3
1
|
/**
|
|
4
2
|
* @param {toa.deployment.dependency.Reference[]} references
|
|
5
3
|
* @returns {*}
|
|
6
4
|
*/
|
|
7
|
-
const dependencies = (references) => {
|
|
5
|
+
export const dependencies = (references) => {
|
|
8
6
|
return references?.reduce((map, reference) => {
|
|
9
7
|
const { name, alias, values } = reference
|
|
10
8
|
|
|
@@ -13,6 +11,3 @@ const dependencies = (references) => {
|
|
|
13
11
|
return map
|
|
14
12
|
}, {})
|
|
15
13
|
}
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
exports.dependencies = dependencies
|
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
'use strict'
|
|
2
|
-
|
|
3
1
|
/**
|
|
4
2
|
* Tells each component which of its events something consumes. An event nobody consumes gets
|
|
5
3
|
* no emitter, no exchange and no outbox row, and a component none of whose events are consumed
|
|
@@ -11,7 +9,7 @@
|
|
|
11
9
|
* @param {toa.norm.Context} context
|
|
12
10
|
* @param {toa.deployment.Dependency} dependency
|
|
13
11
|
*/
|
|
14
|
-
function events (context, dependency) {
|
|
12
|
+
export function events (context, dependency) {
|
|
15
13
|
const components = deployed(context)
|
|
16
14
|
const consumed = collect(components, context.events, dependency.events)
|
|
17
15
|
|
|
@@ -63,5 +61,3 @@ function collect (components, declared, contributed) {
|
|
|
63
61
|
}
|
|
64
62
|
|
|
65
63
|
const VARIABLE = 'TOA_EVENTS_'
|
|
66
|
-
|
|
67
|
-
exports.events = events
|
|
@@ -1,13 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
const { compositions } = require('./compositions')
|
|
6
|
-
const { variables } = require('./variables')
|
|
7
|
-
const { services } = require('./services')
|
|
8
|
-
|
|
9
|
-
exports.dependencies = dependencies
|
|
10
|
-
exports.components = components
|
|
11
|
-
exports.compositions = compositions
|
|
12
|
-
exports.variables = variables
|
|
13
|
-
exports.services = services
|
|
1
|
+
export { dependencies } from './dependencies.js'
|
|
2
|
+
export { components } from './components.js'
|
|
3
|
+
export { compositions } from './compositions.js'
|
|
4
|
+
export { services } from './services.js'
|
|
@@ -1,6 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
function addMounts (composition, mounts, keys = composition.components) {
|
|
1
|
+
export function addMounts (composition, mounts, keys = composition.components) {
|
|
4
2
|
if (mounts === undefined)
|
|
5
3
|
return
|
|
6
4
|
|
|
@@ -20,5 +18,3 @@ function addMounts (composition, mounts, keys = composition.components) {
|
|
|
20
18
|
}
|
|
21
19
|
}
|
|
22
20
|
}
|
|
23
|
-
|
|
24
|
-
exports.addMounts = addMounts
|
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
'use strict'
|
|
2
|
-
|
|
3
1
|
/**
|
|
4
2
|
* Every deployment states what it may take. One that states nothing is `BestEffort`: the
|
|
5
3
|
* first evicted under memory pressure and the last given CPU under contention — which on
|
|
@@ -10,7 +8,7 @@
|
|
|
10
8
|
* Deploying without any is a decision rather than an omission, and it is spelled
|
|
11
9
|
* `resources: null` — at either place.
|
|
12
10
|
*/
|
|
13
|
-
function resources (context, values) {
|
|
11
|
+
export function resources (context, values) {
|
|
14
12
|
for (const unit of units(values)) {
|
|
15
13
|
// `null` is an answer and `undefined` is not one, so the fallback reads only the latter
|
|
16
14
|
if (unit.deployment.resources === undefined)
|
|
@@ -33,5 +31,3 @@ function * units (values) {
|
|
|
33
31
|
for (const service of values.services ?? [])
|
|
34
32
|
yield { deployment: service, subject: `Service '${service.name}'` }
|
|
35
33
|
}
|
|
36
|
-
|
|
37
|
-
exports.resources = resources
|
|
@@ -1,8 +1,6 @@
|
|
|
1
|
-
|
|
1
|
+
import { addVariables } from './variables.js'
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
function services (services, variables, probe, ingress) {
|
|
3
|
+
export function services (services, variables, probe, ingress) {
|
|
6
4
|
for (const service of services) {
|
|
7
5
|
addVariables(service, variables)
|
|
8
6
|
|
|
@@ -34,5 +32,3 @@ function expose (service, ingress = {}) {
|
|
|
34
32
|
if (service.port === undefined)
|
|
35
33
|
throw new Error(`Service '${service.name}' declares an ingress, but no port.`)
|
|
36
34
|
}
|
|
37
|
-
|
|
38
|
-
exports.services = services
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
|
|
1
|
+
import { it } from 'node:test'
|
|
2
|
+
import assert from 'node:assert/strict'
|
|
2
3
|
|
|
3
|
-
|
|
4
|
+
import { services } from './services.js'
|
|
4
5
|
|
|
5
6
|
const service = (extra = {}) => ({ group: 'group', name: 'group-one', version: '0', ...extra })
|
|
6
7
|
|
|
@@ -9,7 +10,7 @@ it('should leave a service without an ingress alone', () => {
|
|
|
9
10
|
|
|
10
11
|
services(list, {}, undefined, { hosts: ['api.dev'] })
|
|
11
12
|
|
|
12
|
-
|
|
13
|
+
assert.strictEqual(list[0].ingress, undefined)
|
|
13
14
|
})
|
|
14
15
|
|
|
15
16
|
/*
|
|
@@ -21,7 +22,7 @@ it('should supply hosts, class and annotations from the context', () => {
|
|
|
21
22
|
|
|
22
23
|
services(list, {}, undefined, { hosts: ['api.dev'], class: 'alb', annotations: { a: 'b' } })
|
|
23
24
|
|
|
24
|
-
|
|
25
|
+
assert.deepStrictEqual(list[0].ingress, {
|
|
25
26
|
path: '/.introspection',
|
|
26
27
|
hosts: ['api.dev'],
|
|
27
28
|
class: 'alb',
|
|
@@ -34,8 +35,8 @@ it('should keep what the service declared itself', () => {
|
|
|
34
35
|
|
|
35
36
|
services(list, {}, undefined, { hosts: ['api.dev'], class: 'alb' })
|
|
36
37
|
|
|
37
|
-
|
|
38
|
-
|
|
38
|
+
assert.deepStrictEqual(list[0].ingress.hosts, ['own.dev'])
|
|
39
|
+
assert.deepStrictEqual(list[0].ingress.class, 'alb')
|
|
39
40
|
})
|
|
40
41
|
|
|
41
42
|
it('should ignore properties the service left undefined', () => {
|
|
@@ -43,19 +44,18 @@ it('should ignore properties the service left undefined', () => {
|
|
|
43
44
|
|
|
44
45
|
services(list, {}, undefined, { hosts: ['api.dev'], class: 'alb' })
|
|
45
46
|
|
|
46
|
-
|
|
47
|
+
assert.deepStrictEqual(list[0].ingress.class, 'alb')
|
|
47
48
|
})
|
|
48
49
|
|
|
49
50
|
it('should reject an ingress with nowhere to land', () => {
|
|
50
51
|
const list = [service({ port: 8002, ingress: { path: '/.introspection' } })]
|
|
51
52
|
|
|
52
|
-
|
|
53
|
-
.toThrow("Service 'group-one' declares an ingress, but no hosts are defined")
|
|
53
|
+
assert.throws(() => services(list, {}, undefined, undefined), (error) => /Service 'group-one' declares an ingress, but no hosts are defined/.test(error.message))
|
|
54
54
|
})
|
|
55
55
|
|
|
56
56
|
it('should reject an ingress without a port', () => {
|
|
57
57
|
const list = [service({ ingress: { path: '/.introspection' } })]
|
|
58
58
|
|
|
59
|
-
|
|
60
|
-
.toThrow("Service 'group-one' declares an ingress, but no port")
|
|
59
|
+
assert.throws(() => services(list, {}, undefined, { hosts: ['api.dev'] }), (error) => /Service 'group-one' declares an ingress, but no port/.test(error.message))
|
|
61
60
|
})
|
|
61
|
+
|
|
@@ -1,6 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
function addVariables (composition, variables, keys = composition.components) {
|
|
1
|
+
export function addVariables (composition, variables, keys = composition.components) {
|
|
4
2
|
composition.variables ??= []
|
|
5
3
|
|
|
6
4
|
const used = new Set(composition.variables.map((variable) => variable.name))
|
|
@@ -17,5 +15,3 @@ function addVariables (composition, variables, keys = composition.components) {
|
|
|
17
15
|
}
|
|
18
16
|
}
|
|
19
17
|
}
|
|
20
|
-
|
|
21
|
-
exports.addVariables = addVariables
|
|
@@ -1,11 +1,9 @@
|
|
|
1
|
-
'use strict'
|
|
2
|
-
|
|
3
1
|
/**
|
|
4
2
|
* @param {toa.norm.Context} context
|
|
5
3
|
* @param {toa.deployment.Dependency} dependency
|
|
6
4
|
* @returns {toa.deployment.Declaration}
|
|
7
5
|
*/
|
|
8
|
-
const declare = (context, dependency) => {
|
|
6
|
+
export const declare = (context, dependency) => {
|
|
9
7
|
const { references } = dependency
|
|
10
8
|
const { name, description, version } = context
|
|
11
9
|
|
|
@@ -25,5 +23,3 @@ const DECLARATION = {
|
|
|
25
23
|
apiVersion: 'v2',
|
|
26
24
|
type: 'application'
|
|
27
25
|
}
|
|
28
|
-
|
|
29
|
-
exports.declare = declare
|
|
@@ -1,12 +1,10 @@
|
|
|
1
|
-
|
|
1
|
+
import * as desc from './.describe/index.js'
|
|
2
|
+
import { addVariables } from './.describe/variables.js'
|
|
3
|
+
import { addMounts } from './.describe/mounts.js'
|
|
4
|
+
import { resources } from './.describe/resources.js'
|
|
5
|
+
import { events } from './.describe/events.js'
|
|
2
6
|
|
|
3
|
-
const
|
|
4
|
-
const { addVariables } = require('./.describe/variables')
|
|
5
|
-
const { addMounts } = require('./.describe/mounts')
|
|
6
|
-
const { resources } = require('./.describe/resources')
|
|
7
|
-
const { events } = require('./.describe/events')
|
|
8
|
-
|
|
9
|
-
const describe = (context, compositions, dependency, image) => {
|
|
7
|
+
export const describe = (context, compositions, dependency, image) => {
|
|
10
8
|
const { services } = dependency
|
|
11
9
|
|
|
12
10
|
dependency.variables.global ??= []
|
|
@@ -132,6 +130,10 @@ function unit (context, dependency) {
|
|
|
132
130
|
if (service.port !== undefined)
|
|
133
131
|
(mono.backends ??= []).push({ port: service.port, path: service.ingress?.path ?? '/' })
|
|
134
132
|
|
|
133
|
+
// one Service fronts every backend, so its annotations are the union
|
|
134
|
+
if (service.annotations !== undefined)
|
|
135
|
+
mono.annotations = Object.assign(mono.annotations ?? {}, service.annotations)
|
|
136
|
+
|
|
135
137
|
if (service.ingress !== undefined) {
|
|
136
138
|
const { path, hosts, ...ingress } = service.ingress
|
|
137
139
|
|
|
@@ -154,5 +156,3 @@ function unit (context, dependency) {
|
|
|
154
156
|
|
|
155
157
|
return mono
|
|
156
158
|
}
|
|
157
|
-
|
|
158
|
-
exports.describe = describe
|
|
@@ -1,9 +1,3 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
const { describe } = require('./describe')
|
|
5
|
-
const { merge } = require('./merge')
|
|
6
|
-
|
|
7
|
-
exports.declare = declare
|
|
8
|
-
exports.describe = describe
|
|
9
|
-
exports.merge = merge
|
|
1
|
+
export { declare } from './declare.js'
|
|
2
|
+
export { describe } from './describe.js'
|
|
3
|
+
export { merge } from './merge.js'
|
|
@@ -1,6 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
const merge = (dependencies) => {
|
|
1
|
+
export const merge = (dependencies) => {
|
|
4
2
|
/** @type {toa.deployment.dependency.Reference[]} */
|
|
5
3
|
const references = []
|
|
6
4
|
|
|
@@ -74,5 +72,3 @@ const append = (merged, variables) => {
|
|
|
74
72
|
merged[component].push(...vars)
|
|
75
73
|
}
|
|
76
74
|
}
|
|
77
|
-
|
|
78
|
-
exports.merge = merge
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
|
|
1
|
+
import { describe, it } from 'node:test'
|
|
2
|
+
import assert from 'node:assert/strict'
|
|
2
3
|
|
|
3
|
-
|
|
4
|
+
import { merge } from './merge.js'
|
|
4
5
|
|
|
5
6
|
const service = (name, extra = {}) => ({ group: 'group', name, version: '0', ...extra })
|
|
6
7
|
|
|
@@ -10,7 +11,7 @@ it('should merge services of all dependencies', () => {
|
|
|
10
11
|
{ services: [service('two', { port: 8001 })] }
|
|
11
12
|
])
|
|
12
13
|
|
|
13
|
-
|
|
14
|
+
assert.strictEqual(merged.services.length, 2)
|
|
14
15
|
})
|
|
15
16
|
|
|
16
17
|
/*
|
|
@@ -24,8 +25,7 @@ describe('port reservation', () => {
|
|
|
24
25
|
{ services: [service('two', { port: 8000 })] }
|
|
25
26
|
]
|
|
26
27
|
|
|
27
|
-
|
|
28
|
-
.toThrow("Port 8000 is claimed by both 'group-one' and 'group-two'")
|
|
28
|
+
assert.throws(() => merge(dependencies), (error) => /Port 8000 is claimed by both 'group-one' and 'group-two'/.test(error.message))
|
|
29
29
|
})
|
|
30
30
|
|
|
31
31
|
it('should reject a service claiming the port of the readiness probe', () => {
|
|
@@ -34,8 +34,7 @@ describe('port reservation', () => {
|
|
|
34
34
|
{ services: [service('one', { port: 8001 })] }
|
|
35
35
|
]
|
|
36
36
|
|
|
37
|
-
|
|
38
|
-
.toThrow("Port 8001 is claimed by both the readiness probe and 'group-one'")
|
|
37
|
+
assert.throws(() => merge(dependencies), (error) => /Port 8001 is claimed by both the readiness probe and 'group-one'/.test(error.message))
|
|
39
38
|
})
|
|
40
39
|
|
|
41
40
|
it('should reject a probe claiming the port of another service', () => {
|
|
@@ -44,8 +43,7 @@ describe('port reservation', () => {
|
|
|
44
43
|
{ services: [service('two', { port: 8002, probe: { path: '/.ready', port: 8000 } })] }
|
|
45
44
|
]
|
|
46
45
|
|
|
47
|
-
|
|
48
|
-
.toThrow("Port 8000 is claimed by both 'group-one' and the readiness probe of 'group-two'")
|
|
46
|
+
assert.throws(() => merge(dependencies), (error) => /Port 8000 is claimed by both 'group-one' and the readiness probe of 'group-two'/.test(error.message))
|
|
49
47
|
})
|
|
50
48
|
|
|
51
49
|
it('should allow a service to probe its own port', () => {
|
|
@@ -53,7 +51,7 @@ describe('port reservation', () => {
|
|
|
53
51
|
{ services: [service('one', { port: 8000, probe: { path: '/.ready', port: 8000 } })] }
|
|
54
52
|
]
|
|
55
53
|
|
|
56
|
-
|
|
54
|
+
assert.doesNotThrow(() => merge(dependencies))
|
|
57
55
|
})
|
|
58
56
|
|
|
59
57
|
it('should ignore services without a port', () => {
|
|
@@ -61,7 +59,7 @@ describe('port reservation', () => {
|
|
|
61
59
|
{ services: [service('one'), service('two')] }
|
|
62
60
|
]
|
|
63
61
|
|
|
64
|
-
|
|
62
|
+
assert.doesNotThrow(() => merge(dependencies))
|
|
65
63
|
})
|
|
66
64
|
|
|
67
65
|
it('should ignore a disabled probe', () => {
|
|
@@ -69,6 +67,6 @@ describe('port reservation', () => {
|
|
|
69
67
|
{ probe: false, services: [service('one', { port: 8000, probe: false })] }
|
|
70
68
|
]
|
|
71
69
|
|
|
72
|
-
|
|
70
|
+
assert.doesNotThrow(() => merge(dependencies))
|
|
73
71
|
})
|
|
74
72
|
})
|
|
@@ -1,13 +1,11 @@
|
|
|
1
|
-
|
|
1
|
+
import { join } from 'node:path'
|
|
2
|
+
import { writeFile as write } from 'node:fs/promises'
|
|
3
|
+
import { yaml as jsyaml } from '@toa.io/generic'
|
|
4
|
+
import fs from 'fs-extra'
|
|
2
5
|
|
|
3
|
-
|
|
4
|
-
const { writeFile: write } = require('node:fs/promises')
|
|
5
|
-
const jsyaml = require('js-yaml')
|
|
6
|
-
const fs = require('fs-extra')
|
|
6
|
+
import { merge, declare, describe } from './.deployment/index.js'
|
|
7
7
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
class Deployment {
|
|
8
|
+
export class Deployment {
|
|
11
9
|
#chart
|
|
12
10
|
#values
|
|
13
11
|
#process
|
|
@@ -89,10 +87,11 @@ function addVariables (list, variables, used = new Set()) {
|
|
|
89
87
|
}
|
|
90
88
|
}
|
|
91
89
|
|
|
92
|
-
const TEMPLATES = join(
|
|
90
|
+
const TEMPLATES = join(import.meta.dirname, 'chart/templates')
|
|
91
|
+
|
|
93
92
|
|
|
94
|
-
exports.Deployment = Deployment
|
|
95
93
|
|
|
96
94
|
function dump (object) {
|
|
97
|
-
|
|
95
|
+
// js-yaml writes plain objects only, and the values carry locators and images
|
|
96
|
+
return jsyaml.dump(JSON.parse(JSON.stringify(object)), { noRefs: true, lineWidth: -1 })
|
|
98
97
|
}
|
|
@@ -1,15 +1,20 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
1
|
+
import { readFileSync } from 'node:fs'
|
|
2
|
+
import { join } from 'node:path'
|
|
3
|
+
import { createRequire } from 'node:module'
|
|
4
|
+
import { pathToFileURL } from 'node:url'
|
|
5
|
+
import { context as load } from '@toa.io/norm'
|
|
6
|
+
import { Process } from '../process.js'
|
|
7
|
+
import { Operator } from './operator.js'
|
|
8
|
+
import { Factory as ImagesFactory } from './images/index.js'
|
|
9
|
+
import { Deployment } from './deployment.js'
|
|
10
|
+
|
|
11
|
+
// a dependency is resolved the way a package is
|
|
12
|
+
const require = createRequire(import.meta.url)
|
|
13
|
+
import { Registry } from './registry.js'
|
|
14
|
+
import { Composition } from './composition.js'
|
|
15
|
+
import { Service } from './service.js'
|
|
16
|
+
|
|
17
|
+
export class Factory {
|
|
13
18
|
#context
|
|
14
19
|
#mono
|
|
15
20
|
#compositions
|
|
@@ -37,11 +42,12 @@ class Factory {
|
|
|
37
42
|
this.#compositions = context.compositions.map((composition) => this.#composition(composition))
|
|
38
43
|
}
|
|
39
44
|
|
|
40
|
-
operator () {
|
|
45
|
+
async operator () {
|
|
41
46
|
const deployment = new Deployment(
|
|
42
47
|
this.#context,
|
|
43
48
|
this.#compositions,
|
|
44
|
-
|
|
49
|
+
// the constructor cannot await, so what it started is settled here
|
|
50
|
+
await this.#dependencies,
|
|
45
51
|
this.#process,
|
|
46
52
|
this.#image
|
|
47
53
|
)
|
|
@@ -59,14 +65,14 @@ class Factory {
|
|
|
59
65
|
return new Composition(composition, image)
|
|
60
66
|
}
|
|
61
67
|
|
|
62
|
-
#getDependencies () {
|
|
68
|
+
async #getDependencies () {
|
|
63
69
|
/** @type {toa.deployment.Dependency[]} */
|
|
64
70
|
const dependencies = []
|
|
65
71
|
|
|
66
72
|
if (this.#context.dependencies === undefined) return dependencies
|
|
67
73
|
|
|
68
74
|
for (const [reference, instances] of Object.entries(this.#context.dependencies)) {
|
|
69
|
-
const dependency = this.#getDependency(reference, instances)
|
|
75
|
+
const dependency = await this.#getDependency(reference, instances)
|
|
70
76
|
|
|
71
77
|
if (dependency !== undefined) dependencies.push(dependency)
|
|
72
78
|
}
|
|
@@ -74,9 +80,11 @@ class Factory {
|
|
|
74
80
|
return dependencies
|
|
75
81
|
}
|
|
76
82
|
|
|
77
|
-
#getDependency (
|
|
78
|
-
|
|
79
|
-
|
|
83
|
+
async #getDependency (reference, instances) {
|
|
84
|
+
// a dependency may be named the way a package is or written as a directory,
|
|
85
|
+
// and a module is loaded by file
|
|
86
|
+
const module = await import(pathToFileURL(require.resolve(reference)).href)
|
|
87
|
+
const pkg = JSON.parse(readFileSync(require.resolve(join(reference, 'package.json')), 'utf8'))
|
|
80
88
|
|
|
81
89
|
if (module.deployment === undefined) return
|
|
82
90
|
|
|
@@ -87,7 +95,7 @@ class Factory {
|
|
|
87
95
|
|
|
88
96
|
/** @type {toa.deployment.Service[]} */
|
|
89
97
|
const services = dependency.services?.map((service) =>
|
|
90
|
-
this.#mono ? service : this.#service(
|
|
98
|
+
this.#mono ? service : this.#service(reference, service))
|
|
91
99
|
|
|
92
100
|
return { ...dependency, services }
|
|
93
101
|
}
|
|
@@ -109,5 +117,3 @@ class Factory {
|
|
|
109
117
|
return new Factory(context, options)
|
|
110
118
|
}
|
|
111
119
|
}
|
|
112
|
-
|
|
113
|
-
exports.Factory = Factory
|
|
@@ -13,7 +13,7 @@ COPY --chown=node:node . /composition
|
|
|
13
13
|
|
|
14
14
|
# run 'npm i' in each component
|
|
15
15
|
RUN --mount=type=cache,target=/root/.npm \
|
|
16
|
-
for entry in *; do if
|
|
16
|
+
for entry in *; do if grep -qs '"dependencies"' "$entry/package.json"; then (cd $entry && npm i --omit=dev); fi; done
|
|
17
17
|
|
|
18
18
|
USER node
|
|
19
19
|
CMD toa compose *
|
|
@@ -1,13 +1,12 @@
|
|
|
1
|
-
|
|
1
|
+
import { join } from 'node:path'
|
|
2
|
+
import fs from 'fs-extra'
|
|
3
|
+
import { createHash } from 'node:crypto'
|
|
2
4
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
const { createHash } = require('node:crypto')
|
|
5
|
+
import { Image } from './image.js'
|
|
6
|
+
import { declare } from './format.js'
|
|
6
7
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
class Composition extends Image {
|
|
10
|
-
dockerfile = join(__dirname, 'composition.Dockerfile')
|
|
8
|
+
export class Composition extends Image {
|
|
9
|
+
dockerfile = join(import.meta.dirname, 'composition.Dockerfile')
|
|
11
10
|
|
|
12
11
|
#name
|
|
13
12
|
#image
|
|
@@ -64,11 +63,12 @@ class Composition extends Image {
|
|
|
64
63
|
const context = await super.prepare(root)
|
|
65
64
|
|
|
66
65
|
for (const component of this.#components) {
|
|
67
|
-
|
|
66
|
+
const target = join(context, component.locator.label)
|
|
67
|
+
|
|
68
|
+
await fs.copy(component.path, target)
|
|
69
|
+
await declare(component.path, target, component.locator.label)
|
|
68
70
|
}
|
|
69
71
|
|
|
70
72
|
return context
|
|
71
73
|
}
|
|
72
74
|
}
|
|
73
|
-
|
|
74
|
-
exports.Composition = Composition
|