@toa.io/operations 1.0.0-alpha.253 → 1.0.0-alpha.256
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 +11 -0
- package/package.json +7 -7
- package/src/deployment/.deployment/describe.js +54 -2
- package/src/deployment/chart/templates/mono.yaml +168 -0
- package/src/deployment/deployment.js +5 -2
- package/src/deployment/factory.js +25 -6
- package/src/deployment/images/factory.js +12 -0
- package/src/deployment/images/mono.Dockerfile +18 -0
- package/src/deployment/images/mono.js +82 -0
- package/src/deployment/registry.js +5 -1
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
# Change Log
|
|
2
|
+
|
|
3
|
+
All notable changes to this project will be documented in this file.
|
|
4
|
+
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
|
5
|
+
|
|
6
|
+
# [1.0.0-alpha.256](https://github.com/toa-io/toa/compare/v1.0.0-alpha.255...v1.0.0-alpha.256) (2026-08-23)
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
### Features
|
|
10
|
+
|
|
11
|
+
* deploy a single mono image with toa deploy --mono ([a7f14f9](https://github.com/toa-io/toa/commit/a7f14f9877a280e9c74d16c195028b35d74fb15a))
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@toa.io/operations",
|
|
3
|
-
"version": "1.0.0-alpha.
|
|
3
|
+
"version": "1.0.0-alpha.256",
|
|
4
4
|
"description": "Toa Deployment",
|
|
5
5
|
"homepage": "https://toa.io",
|
|
6
6
|
"author": {
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
"url": "https://github.com/toa-io/toa/issues"
|
|
17
17
|
},
|
|
18
18
|
"engines": {
|
|
19
|
-
"node": ">=
|
|
19
|
+
"node": ">= 24.0.0"
|
|
20
20
|
},
|
|
21
21
|
"publishConfig": {
|
|
22
22
|
"access": "public"
|
|
@@ -27,12 +27,12 @@
|
|
|
27
27
|
"test": "echo \"Error: run tests from root\" && exit 1"
|
|
28
28
|
},
|
|
29
29
|
"dependencies": {
|
|
30
|
-
"@toa.io/filesystem": "1.0.0-alpha.
|
|
31
|
-
"@toa.io/generic": "1.0.0-alpha.
|
|
32
|
-
"@toa.io/norm": "1.0.0-alpha.
|
|
33
|
-
"@toa.io/yaml": "1.0.0-alpha.
|
|
30
|
+
"@toa.io/filesystem": "1.0.0-alpha.254",
|
|
31
|
+
"@toa.io/generic": "1.0.0-alpha.254",
|
|
32
|
+
"@toa.io/norm": "1.0.0-alpha.256",
|
|
33
|
+
"@toa.io/yaml": "1.0.0-alpha.254",
|
|
34
34
|
"execa": "5.1.1",
|
|
35
35
|
"fs-extra": "11.1.1"
|
|
36
36
|
},
|
|
37
|
-
"gitHead": "
|
|
37
|
+
"gitHead": "a8990df97f971060686bd70a965f78e98070a983"
|
|
38
38
|
}
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
3
|
const desc = require('./.describe')
|
|
4
|
+
const { addVariables } = require('./.describe/variables')
|
|
5
|
+
const { addMounts } = require('./.describe/mounts')
|
|
4
6
|
|
|
5
|
-
const describe = (context, compositions, dependency) => {
|
|
7
|
+
const describe = (context, compositions, dependency, image) => {
|
|
6
8
|
const { services } = dependency
|
|
7
9
|
|
|
8
10
|
dependency.variables.global ??= []
|
|
@@ -17,9 +19,24 @@ const describe = (context, compositions, dependency) => {
|
|
|
17
19
|
}
|
|
18
20
|
)
|
|
19
21
|
|
|
20
|
-
const components = desc.components(compositions)
|
|
21
22
|
const credentials = context.registry?.credentials
|
|
22
23
|
|
|
24
|
+
if (image !== undefined) {
|
|
25
|
+
const mono = unit(context, dependency)
|
|
26
|
+
|
|
27
|
+
mono.image = image.reference
|
|
28
|
+
|
|
29
|
+
return {
|
|
30
|
+
compositions: [],
|
|
31
|
+
components: mono.components,
|
|
32
|
+
services: [],
|
|
33
|
+
credentials,
|
|
34
|
+
mono
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
const components = desc.components(compositions)
|
|
39
|
+
|
|
23
40
|
desc.compositions(compositions, dependency)
|
|
24
41
|
desc.services(services, dependency.variables, dependency.probe)
|
|
25
42
|
|
|
@@ -31,4 +48,39 @@ const describe = (context, compositions, dependency) => {
|
|
|
31
48
|
}
|
|
32
49
|
}
|
|
33
50
|
|
|
51
|
+
function unit (context, dependency) {
|
|
52
|
+
const components = (context.components ?? []).map((component) => component.locator.label)
|
|
53
|
+
|
|
54
|
+
const mono = {
|
|
55
|
+
replicas: context.mono?.replicas,
|
|
56
|
+
resources: context.mono?.resources,
|
|
57
|
+
components,
|
|
58
|
+
variables: []
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
addVariables(mono, dependency.variables ?? {})
|
|
62
|
+
addMounts(mono, dependency.mounts)
|
|
63
|
+
|
|
64
|
+
for (const service of dependency.services ?? []) {
|
|
65
|
+
if (service.variables !== undefined)
|
|
66
|
+
for (const variable of service.variables)
|
|
67
|
+
if (!mono.variables.some((item) => item.name === variable.name))
|
|
68
|
+
mono.variables.push(variable)
|
|
69
|
+
|
|
70
|
+
if (service.port !== undefined)
|
|
71
|
+
mono.port = service.port
|
|
72
|
+
|
|
73
|
+
if (service.ingress !== undefined)
|
|
74
|
+
mono.ingress = service.ingress
|
|
75
|
+
|
|
76
|
+
if (service.probe !== undefined && service.probe !== false)
|
|
77
|
+
mono.probe = service.probe
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
if (mono.probe === undefined && dependency.probe !== undefined && dependency.probe !== false)
|
|
81
|
+
mono.probe = dependency.probe
|
|
82
|
+
|
|
83
|
+
return mono
|
|
84
|
+
}
|
|
85
|
+
|
|
34
86
|
exports.describe = describe
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
{{- if .Values.mono }}
|
|
2
|
+
{{- with .Values.mono }}
|
|
3
|
+
apiVersion: apps/v1
|
|
4
|
+
kind: Deployment
|
|
5
|
+
metadata:
|
|
6
|
+
name: mono
|
|
7
|
+
spec:
|
|
8
|
+
replicas: {{ .replicas | default 2 }}
|
|
9
|
+
progressDeadlineSeconds: 900
|
|
10
|
+
strategy:
|
|
11
|
+
type: RollingUpdate
|
|
12
|
+
rollingUpdate:
|
|
13
|
+
maxUnavailable: 0
|
|
14
|
+
maxSurge: 50%
|
|
15
|
+
selector:
|
|
16
|
+
matchLabels:
|
|
17
|
+
toa.io/composition: mono
|
|
18
|
+
template:
|
|
19
|
+
metadata:
|
|
20
|
+
labels:
|
|
21
|
+
toa.io/composition: mono
|
|
22
|
+
{{- range .components }}
|
|
23
|
+
{{ . }}: "1"
|
|
24
|
+
{{- end }}
|
|
25
|
+
spec:
|
|
26
|
+
containers:
|
|
27
|
+
- name: mono
|
|
28
|
+
image: {{ .image }}
|
|
29
|
+
{{- if .port }}
|
|
30
|
+
ports:
|
|
31
|
+
- containerPort: {{ .port }}
|
|
32
|
+
{{- else if .probe }}
|
|
33
|
+
ports:
|
|
34
|
+
- containerPort: {{ .probe.port }}
|
|
35
|
+
{{- end }}
|
|
36
|
+
{{- if .resources }}
|
|
37
|
+
resources:
|
|
38
|
+
{{- if or .resources.cpu .resources.memory }}
|
|
39
|
+
requests:
|
|
40
|
+
{{- if .resources.cpu }}
|
|
41
|
+
cpu: {{ index .resources.cpu 0 }}
|
|
42
|
+
{{- end }}
|
|
43
|
+
{{- if .resources.memory }}
|
|
44
|
+
memory: {{ index .resources.memory 0 }}
|
|
45
|
+
{{- end }}
|
|
46
|
+
limits:
|
|
47
|
+
{{- if .resources.cpu }}
|
|
48
|
+
cpu: {{ index .resources.cpu 1 }}
|
|
49
|
+
{{- end }}
|
|
50
|
+
{{- if .resources.memory }}
|
|
51
|
+
memory: {{ index .resources.memory 1 }}
|
|
52
|
+
{{- end }}
|
|
53
|
+
{{- end }}
|
|
54
|
+
{{- end }}
|
|
55
|
+
{{- if .variables }}
|
|
56
|
+
env:
|
|
57
|
+
{{- range .variables }}
|
|
58
|
+
{{- include "env.var" . | indent 12 }}
|
|
59
|
+
{{- end }}
|
|
60
|
+
{{- end }}
|
|
61
|
+
{{- if .probe }}
|
|
62
|
+
startupProbe:
|
|
63
|
+
httpGet:
|
|
64
|
+
path: {{ .probe.path }}
|
|
65
|
+
port: {{ .probe.port }}
|
|
66
|
+
{{- if .probe.delay }}
|
|
67
|
+
initialDelaySeconds: {{ .probe.delay }}
|
|
68
|
+
{{- end }}
|
|
69
|
+
periodSeconds: 2
|
|
70
|
+
timeoutSeconds: 3
|
|
71
|
+
failureThreshold: 150
|
|
72
|
+
readinessProbe:
|
|
73
|
+
httpGet:
|
|
74
|
+
path: {{ .probe.path }}
|
|
75
|
+
port: {{ .probe.port }}
|
|
76
|
+
periodSeconds: 10
|
|
77
|
+
timeoutSeconds: 3
|
|
78
|
+
failureThreshold: 3
|
|
79
|
+
{{- end }}
|
|
80
|
+
{{- if .mounts }}
|
|
81
|
+
volumeMounts:
|
|
82
|
+
{{- range .mounts }}
|
|
83
|
+
- name: {{ .name }}
|
|
84
|
+
mountPath: {{ .path }}
|
|
85
|
+
{{- end }}
|
|
86
|
+
{{- end }}
|
|
87
|
+
lifecycle:
|
|
88
|
+
preStop:
|
|
89
|
+
exec:
|
|
90
|
+
command: [sleep, "5"]
|
|
91
|
+
terminationGracePeriodSeconds: 45
|
|
92
|
+
{{- if $.Values.credentials }}
|
|
93
|
+
imagePullSecrets:
|
|
94
|
+
- name: {{ $.Values.credentials }}
|
|
95
|
+
{{- end }}
|
|
96
|
+
{{- if .mounts }}
|
|
97
|
+
volumes:
|
|
98
|
+
{{- range .mounts }}
|
|
99
|
+
- name: {{ .name }}
|
|
100
|
+
persistentVolumeClaim:
|
|
101
|
+
claimName: {{ .claim }}
|
|
102
|
+
{{- end }}
|
|
103
|
+
{{- end }}
|
|
104
|
+
topologySpreadConstraints:
|
|
105
|
+
- maxSkew: 1
|
|
106
|
+
topologyKey: kubernetes.io/hostname
|
|
107
|
+
whenUnsatisfiable: ScheduleAnyway
|
|
108
|
+
labelSelector:
|
|
109
|
+
matchLabels:
|
|
110
|
+
toa.io/composition: mono
|
|
111
|
+
{{- if .port }}
|
|
112
|
+
---
|
|
113
|
+
apiVersion: v1
|
|
114
|
+
kind: Service
|
|
115
|
+
metadata:
|
|
116
|
+
name: mono
|
|
117
|
+
spec:
|
|
118
|
+
type: ClusterIP
|
|
119
|
+
selector:
|
|
120
|
+
toa.io/composition: mono
|
|
121
|
+
ports:
|
|
122
|
+
- name: port-{{ .port }}
|
|
123
|
+
protocol: TCP
|
|
124
|
+
port: {{ .port }}
|
|
125
|
+
targetPort: {{ .port }}
|
|
126
|
+
{{- end }}
|
|
127
|
+
{{- if .ingress }}
|
|
128
|
+
---
|
|
129
|
+
apiVersion: networking.k8s.io/v1
|
|
130
|
+
kind: Ingress
|
|
131
|
+
metadata:
|
|
132
|
+
name: mono
|
|
133
|
+
{{- if .ingress.annotations }}
|
|
134
|
+
annotations:
|
|
135
|
+
{{ toYaml .ingress.annotations | indent 4 }}
|
|
136
|
+
{{- end }}
|
|
137
|
+
spec:
|
|
138
|
+
{{- if .ingress.class }}
|
|
139
|
+
ingressClassName: {{ .ingress.class }}
|
|
140
|
+
{{- end }}
|
|
141
|
+
rules:
|
|
142
|
+
{{- range .ingress.hosts }}
|
|
143
|
+
- host: {{ . }}
|
|
144
|
+
http:
|
|
145
|
+
paths:
|
|
146
|
+
- path: /
|
|
147
|
+
pathType: Prefix
|
|
148
|
+
backend:
|
|
149
|
+
service:
|
|
150
|
+
name: mono
|
|
151
|
+
port:
|
|
152
|
+
number: {{ $.Values.mono.port | default 8000 }}
|
|
153
|
+
{{- end }}
|
|
154
|
+
{{- if .ingress.default }}
|
|
155
|
+
- http:
|
|
156
|
+
paths:
|
|
157
|
+
- path: /
|
|
158
|
+
pathType: Prefix
|
|
159
|
+
backend:
|
|
160
|
+
service:
|
|
161
|
+
name: mono
|
|
162
|
+
port:
|
|
163
|
+
number: {{ $.Values.mono.port | default 8000 }}
|
|
164
|
+
{{- end }}
|
|
165
|
+
{{- end }}
|
|
166
|
+
---
|
|
167
|
+
{{- end }}
|
|
168
|
+
{{- end }}
|
|
@@ -13,11 +13,11 @@ class Deployment {
|
|
|
13
13
|
#process
|
|
14
14
|
#target
|
|
15
15
|
|
|
16
|
-
constructor (context, compositions, dependencies, process) {
|
|
16
|
+
constructor (context, compositions, dependencies, process, image) {
|
|
17
17
|
const dependency = merge(dependencies)
|
|
18
18
|
|
|
19
19
|
this.#chart = declare(context, dependency)
|
|
20
|
-
this.#values = describe(context, compositions, dependency)
|
|
20
|
+
this.#values = describe(context, compositions, dependency, image)
|
|
21
21
|
this.#process = process
|
|
22
22
|
}
|
|
23
23
|
|
|
@@ -69,6 +69,9 @@ class Deployment {
|
|
|
69
69
|
addVariables(this.#values.compositions, variables, used)
|
|
70
70
|
addVariables(this.#values.services, variables, used)
|
|
71
71
|
|
|
72
|
+
if (this.#values.mono !== undefined)
|
|
73
|
+
addVariables([this.#values.mono], variables, used)
|
|
74
|
+
|
|
72
75
|
return variables
|
|
73
76
|
}
|
|
74
77
|
}
|
|
@@ -11,24 +11,42 @@ const { Service } = require('./service')
|
|
|
11
11
|
|
|
12
12
|
class Factory {
|
|
13
13
|
#context
|
|
14
|
+
#root
|
|
15
|
+
#mono
|
|
14
16
|
#compositions
|
|
15
17
|
#dependencies
|
|
16
18
|
#registry
|
|
17
19
|
#process
|
|
20
|
+
#image
|
|
18
21
|
|
|
19
|
-
constructor (context) {
|
|
22
|
+
constructor (context, options = {}) {
|
|
20
23
|
this.#context = context
|
|
24
|
+
this.#root = options.root
|
|
25
|
+
this.#mono = options.mono === true
|
|
21
26
|
this.#process = new Process()
|
|
22
27
|
|
|
23
28
|
const imagesFactory = new ImagesFactory(context.name, context.runtime, context.registry)
|
|
24
29
|
|
|
25
30
|
this.#registry = new Registry(context.name, context.registry, imagesFactory, this.#process)
|
|
26
|
-
this.#compositions = context.compositions.map((composition) => this.#composition(composition))
|
|
27
31
|
this.#dependencies = this.#getDependencies()
|
|
32
|
+
this.#compositions = []
|
|
33
|
+
|
|
34
|
+
if (this.#mono)
|
|
35
|
+
this.#image = this.#registry.mono({
|
|
36
|
+
components: context.components
|
|
37
|
+
}, this.#root)
|
|
38
|
+
else
|
|
39
|
+
this.#compositions = context.compositions.map((composition) => this.#composition(composition))
|
|
28
40
|
}
|
|
29
41
|
|
|
30
42
|
operator () {
|
|
31
|
-
const deployment = new Deployment(
|
|
43
|
+
const deployment = new Deployment(
|
|
44
|
+
this.#context,
|
|
45
|
+
this.#compositions,
|
|
46
|
+
this.#dependencies,
|
|
47
|
+
this.#process,
|
|
48
|
+
this.#image
|
|
49
|
+
)
|
|
32
50
|
|
|
33
51
|
return new Operator(deployment, this.#registry)
|
|
34
52
|
}
|
|
@@ -70,7 +88,8 @@ class Factory {
|
|
|
70
88
|
const dependency = module.deployment(instances, annotation)
|
|
71
89
|
|
|
72
90
|
/** @type {toa.deployment.Service[]} */
|
|
73
|
-
const services = dependency.services?.map((service) =>
|
|
91
|
+
const services = dependency.services?.map((service) =>
|
|
92
|
+
this.#mono ? service : this.#service(path, service))
|
|
74
93
|
|
|
75
94
|
return { ...dependency, services }
|
|
76
95
|
}
|
|
@@ -86,10 +105,10 @@ class Factory {
|
|
|
86
105
|
return new Service(service, image)
|
|
87
106
|
}
|
|
88
107
|
|
|
89
|
-
static async create (path, environment) {
|
|
108
|
+
static async create (path, environment, options = {}) {
|
|
90
109
|
const context = await load(path, environment)
|
|
91
110
|
|
|
92
|
-
return new Factory(context)
|
|
111
|
+
return new Factory(context, { ...options, root: path })
|
|
93
112
|
}
|
|
94
113
|
}
|
|
95
114
|
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
const { Composition } = require('./composition')
|
|
4
4
|
const { Service } = require('./service')
|
|
5
|
+
const { Mono } = require('./mono')
|
|
5
6
|
|
|
6
7
|
class Factory {
|
|
7
8
|
/** @type {string} */
|
|
@@ -45,6 +46,17 @@ class Factory {
|
|
|
45
46
|
|
|
46
47
|
return instance
|
|
47
48
|
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* @returns {Mono}
|
|
52
|
+
*/
|
|
53
|
+
mono (composition, root) {
|
|
54
|
+
const instance = new Mono(this.#scope, this.#runtime, this.#registry, composition, root)
|
|
55
|
+
|
|
56
|
+
instance.tag()
|
|
57
|
+
|
|
58
|
+
return instance
|
|
59
|
+
}
|
|
48
60
|
}
|
|
49
61
|
|
|
50
62
|
exports.Factory = Factory
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
FROM {{build.image}}
|
|
2
|
+
|
|
3
|
+
{{build.arguments}}
|
|
4
|
+
|
|
5
|
+
ENV NODE_ENV=production
|
|
6
|
+
RUN if [ "{{runtime.registry}}" != "" ]; then npm set registry {{runtime.registry}}; fi
|
|
7
|
+
RUN if [ "{{runtime.proxy}}" != "" ]; then npm set proxy {{runtime.proxy}}; fi
|
|
8
|
+
|
|
9
|
+
WORKDIR /composition
|
|
10
|
+
COPY --chown=node:node . /composition
|
|
11
|
+
|
|
12
|
+
{{build.run}}
|
|
13
|
+
|
|
14
|
+
RUN --mount=type=cache,target=/root/.npm \
|
|
15
|
+
for entry in components/*; do if [ -f "$entry/package.json" ]; then (cd $entry && npm i --omit=dev); fi; done
|
|
16
|
+
|
|
17
|
+
USER node
|
|
18
|
+
CMD toa mono .
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const { join } = require('node:path')
|
|
4
|
+
const fs = require('fs-extra')
|
|
5
|
+
const { createHash } = require('node:crypto')
|
|
6
|
+
|
|
7
|
+
const { Image } = require('./image')
|
|
8
|
+
|
|
9
|
+
class Mono extends Image {
|
|
10
|
+
dockerfile = join(__dirname, 'mono.Dockerfile')
|
|
11
|
+
|
|
12
|
+
#root
|
|
13
|
+
#image
|
|
14
|
+
#components
|
|
15
|
+
|
|
16
|
+
constructor (scope, runtime, registry, composition, root) {
|
|
17
|
+
super(scope, runtime, registry)
|
|
18
|
+
|
|
19
|
+
this.#root = root
|
|
20
|
+
this.#image = composition.image
|
|
21
|
+
this.#components = composition.components
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
get name () {
|
|
25
|
+
return 'mono'
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
get version () {
|
|
29
|
+
const hash = createHash('sha256')
|
|
30
|
+
|
|
31
|
+
for (const component of this.#components) {
|
|
32
|
+
hash.update(component.locator.id)
|
|
33
|
+
hash.update(component.version)
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
return hash.digest('hex').slice(0, 8)
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
get base () {
|
|
40
|
+
let image = this.#image
|
|
41
|
+
|
|
42
|
+
for (const component of this.#components) {
|
|
43
|
+
const value = component.build?.image
|
|
44
|
+
|
|
45
|
+
if (image !== null && image !== value)
|
|
46
|
+
throw new Error('Mono deployment requires different base images for its components. Specify base image for the composition in the context.')
|
|
47
|
+
|
|
48
|
+
image = value
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
return image
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
get run () {
|
|
55
|
+
const commands = []
|
|
56
|
+
|
|
57
|
+
for (const component of this.#components) {
|
|
58
|
+
const run = component.build?.run
|
|
59
|
+
|
|
60
|
+
if (run !== undefined)
|
|
61
|
+
commands.push(run)
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
return commands.join('\n')
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
async prepare (root) {
|
|
68
|
+
const context = await super.prepare(root)
|
|
69
|
+
|
|
70
|
+
await fs.copy(join(this.#root, CONTEXT), join(context, CONTEXT))
|
|
71
|
+
await fs.ensureDir(join(context, 'components'))
|
|
72
|
+
|
|
73
|
+
for (const component of this.#components)
|
|
74
|
+
await fs.copy(component.path, join(context, 'components', component.locator.label))
|
|
75
|
+
|
|
76
|
+
return context
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
const CONTEXT = 'context.toa.yaml'
|
|
81
|
+
|
|
82
|
+
exports.Mono = Mono
|
|
@@ -35,6 +35,10 @@ class Registry {
|
|
|
35
35
|
return this.#create('service', path, service)
|
|
36
36
|
}
|
|
37
37
|
|
|
38
|
+
mono (composition, root) {
|
|
39
|
+
return this.#create('mono', composition, root)
|
|
40
|
+
}
|
|
41
|
+
|
|
38
42
|
async prepare (root) {
|
|
39
43
|
const path = await workspace.create('images', root)
|
|
40
44
|
|
|
@@ -61,7 +65,7 @@ class Registry {
|
|
|
61
65
|
}
|
|
62
66
|
|
|
63
67
|
/**
|
|
64
|
-
* @param {'composition' | 'service'} type
|
|
68
|
+
* @param {'composition' | 'service' | 'mono'} type
|
|
65
69
|
* @param {...any} args
|
|
66
70
|
* @returns {toa.deployment.images.Image}
|
|
67
71
|
*/
|