@toa.io/operations 1.0.0-alpha.27 → 1.0.0-alpha.272
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 +153 -0
- package/image/runtime.Dockerfile +4 -0
- package/package.json +8 -8
- package/readme.md +16 -0
- package/src/deployment/.deployment/.describe/compositions.js +7 -2
- package/src/deployment/.deployment/.describe/events.js +67 -0
- package/src/deployment/.deployment/.describe/mounts.js +24 -0
- package/src/deployment/.deployment/.describe/resources.js +37 -0
- package/src/deployment/.deployment/.describe/services.js +28 -1
- package/src/deployment/.deployment/.describe/services.test.js +61 -0
- package/src/deployment/.deployment/.describe/variables.js +6 -5
- package/src/deployment/.deployment/describe.js +130 -6
- package/src/deployment/.deployment/merge.js +45 -1
- package/src/deployment/.deployment/merge.test.js +74 -0
- package/src/deployment/chart/templates/compositions.yaml +70 -0
- package/src/deployment/chart/templates/mono.yaml +177 -0
- package/src/deployment/chart/templates/services.yaml +71 -4
- package/src/deployment/chart/values.yaml +11 -1
- package/src/deployment/composition.js +1 -0
- package/src/deployment/deployment.js +6 -2
- package/src/deployment/factory.js +24 -8
- package/src/deployment/images/composition.Dockerfile +2 -2
- package/src/deployment/images/composition.js +16 -11
- package/src/deployment/images/factory.js +12 -3
- package/src/deployment/images/image.js +16 -7
- package/src/deployment/images/mono.Dockerfile +18 -0
- package/src/deployment/images/mono.js +71 -0
- package/src/deployment/images/runtime-base.test.js +90 -0
- package/src/deployment/images/service.Dockerfile +3 -3
- package/src/deployment/operator.js +4 -0
- package/src/deployment/registry.js +64 -16
- package/src/deployment/registry.test.js +175 -0
- package/types/_deployment/dependency.d.ts +2 -0
- package/types/_deployment/images/image.d.ts +4 -2
- package/types/_deployment/registry.d.ts +9 -7
- package/types/dependency.ts +71 -0
- package/types/dependency.d.ts +0 -39
- /package/types/{index.d.ts → index.ts} +0 -0
|
@@ -13,14 +13,58 @@ const merge = (dependencies) => {
|
|
|
13
13
|
/** @type {toa.deployment.dependency.Variables} */
|
|
14
14
|
const variables = {}
|
|
15
15
|
|
|
16
|
+
/** event labels consumed by something other than a component's own receivers */
|
|
17
|
+
const events = []
|
|
18
|
+
|
|
19
|
+
const mounts = {}
|
|
20
|
+
|
|
21
|
+
/** @type {toa.deployment.dependency.Probe | false | undefined} */
|
|
22
|
+
let probe
|
|
23
|
+
|
|
16
24
|
for (const dependency of dependencies) {
|
|
17
25
|
if (dependency.references !== undefined) references.push(...dependency.references)
|
|
18
26
|
if (dependency.services !== undefined) services.push(...dependency.services)
|
|
19
27
|
if (dependency.proxies !== undefined) proxies.push(...dependency.proxies)
|
|
20
28
|
if (dependency.variables !== undefined) append(variables, dependency.variables)
|
|
29
|
+
if (dependency.events !== undefined) events.push(...dependency.events)
|
|
30
|
+
if (dependency.mounts !== undefined) append(mounts, dependency.mounts)
|
|
31
|
+
if (dependency.probe !== undefined) probe = dependency.probe
|
|
21
32
|
}
|
|
22
33
|
|
|
23
|
-
|
|
34
|
+
reserve(services, probe)
|
|
35
|
+
|
|
36
|
+
return { references, services, proxies, variables, mounts, events, probe }
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* In Kubernetes these are separate pods, but `toa mono` and a local run put every
|
|
41
|
+
* service in one process — so a port may be claimed once and only once.
|
|
42
|
+
*/
|
|
43
|
+
const reserve = (services, probe) => {
|
|
44
|
+
const claimed = new Map()
|
|
45
|
+
|
|
46
|
+
if (probe !== undefined && probe !== false)
|
|
47
|
+
claimed.set(probe.port, 'the readiness probe')
|
|
48
|
+
|
|
49
|
+
for (const service of services)
|
|
50
|
+
for (const [port, claimant] of ports(service)) {
|
|
51
|
+
const conflicting = claimed.get(port)
|
|
52
|
+
|
|
53
|
+
if (conflicting !== undefined)
|
|
54
|
+
throw new Error(`Port ${port} is claimed by both ${conflicting} and ${claimant}`)
|
|
55
|
+
|
|
56
|
+
claimed.set(port, claimant)
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
function * ports (service) {
|
|
61
|
+
const name = `'${service.group}-${service.name}'`
|
|
62
|
+
|
|
63
|
+
if (service.port !== undefined)
|
|
64
|
+
yield [service.port, name]
|
|
65
|
+
|
|
66
|
+
if (service.probe !== undefined && service.probe !== false && service.probe.port !== service.port)
|
|
67
|
+
yield [service.probe.port, `the readiness probe of ${name}`]
|
|
24
68
|
}
|
|
25
69
|
|
|
26
70
|
const append = (merged, variables) => {
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const { merge } = require('./merge')
|
|
4
|
+
|
|
5
|
+
const service = (name, extra = {}) => ({ group: 'group', name, version: '0', ...extra })
|
|
6
|
+
|
|
7
|
+
it('should merge services of all dependencies', () => {
|
|
8
|
+
const merged = merge([
|
|
9
|
+
{ services: [service('one', { port: 8000 })] },
|
|
10
|
+
{ services: [service('two', { port: 8001 })] }
|
|
11
|
+
])
|
|
12
|
+
|
|
13
|
+
expect(merged.services).toHaveLength(2)
|
|
14
|
+
})
|
|
15
|
+
|
|
16
|
+
/*
|
|
17
|
+
* In Kubernetes these are separate pods, but `toa mono` and a local run put every
|
|
18
|
+
* service in one process.
|
|
19
|
+
*/
|
|
20
|
+
describe('port reservation', () => {
|
|
21
|
+
it('should reject two services claiming one port', () => {
|
|
22
|
+
const dependencies = [
|
|
23
|
+
{ services: [service('one', { port: 8000 })] },
|
|
24
|
+
{ services: [service('two', { port: 8000 })] }
|
|
25
|
+
]
|
|
26
|
+
|
|
27
|
+
expect(() => merge(dependencies))
|
|
28
|
+
.toThrow("Port 8000 is claimed by both 'group-one' and 'group-two'")
|
|
29
|
+
})
|
|
30
|
+
|
|
31
|
+
it('should reject a service claiming the port of the readiness probe', () => {
|
|
32
|
+
const dependencies = [
|
|
33
|
+
{ probe: { path: '/.ready', port: 8001 } },
|
|
34
|
+
{ services: [service('one', { port: 8001 })] }
|
|
35
|
+
]
|
|
36
|
+
|
|
37
|
+
expect(() => merge(dependencies))
|
|
38
|
+
.toThrow("Port 8001 is claimed by both the readiness probe and 'group-one'")
|
|
39
|
+
})
|
|
40
|
+
|
|
41
|
+
it('should reject a probe claiming the port of another service', () => {
|
|
42
|
+
const dependencies = [
|
|
43
|
+
{ services: [service('one', { port: 8000 })] },
|
|
44
|
+
{ services: [service('two', { port: 8002, probe: { path: '/.ready', port: 8000 } })] }
|
|
45
|
+
]
|
|
46
|
+
|
|
47
|
+
expect(() => merge(dependencies))
|
|
48
|
+
.toThrow("Port 8000 is claimed by both 'group-one' and the readiness probe of 'group-two'")
|
|
49
|
+
})
|
|
50
|
+
|
|
51
|
+
it('should allow a service to probe its own port', () => {
|
|
52
|
+
const dependencies = [
|
|
53
|
+
{ services: [service('one', { port: 8000, probe: { path: '/.ready', port: 8000 } })] }
|
|
54
|
+
]
|
|
55
|
+
|
|
56
|
+
expect(() => merge(dependencies)).not.toThrow()
|
|
57
|
+
})
|
|
58
|
+
|
|
59
|
+
it('should ignore services without a port', () => {
|
|
60
|
+
const dependencies = [
|
|
61
|
+
{ services: [service('one'), service('two')] }
|
|
62
|
+
]
|
|
63
|
+
|
|
64
|
+
expect(() => merge(dependencies)).not.toThrow()
|
|
65
|
+
})
|
|
66
|
+
|
|
67
|
+
it('should ignore a disabled probe', () => {
|
|
68
|
+
const dependencies = [
|
|
69
|
+
{ probe: false, services: [service('one', { port: 8000, probe: false })] }
|
|
70
|
+
]
|
|
71
|
+
|
|
72
|
+
expect(() => merge(dependencies)).not.toThrow()
|
|
73
|
+
})
|
|
74
|
+
})
|
|
@@ -5,6 +5,9 @@ metadata:
|
|
|
5
5
|
name: composition-{{ required "composition name is required" .name }}
|
|
6
6
|
spec:
|
|
7
7
|
replicas: {{ .replicas | default 2 }}
|
|
8
|
+
# A backstop for stuck rollouts only. Must stay above the `helm upgrade --timeout`
|
|
9
|
+
# the deploy runs with, so a slow but progressing rollout is not marked failed.
|
|
10
|
+
progressDeadlineSeconds: 900
|
|
8
11
|
selector:
|
|
9
12
|
matchLabels:
|
|
10
13
|
toa.io/composition: {{ .name }}
|
|
@@ -19,15 +22,82 @@ spec:
|
|
|
19
22
|
containers:
|
|
20
23
|
- name: {{ .name }}
|
|
21
24
|
image: {{ .image }}
|
|
25
|
+
{{- if .resources }}
|
|
26
|
+
resources:
|
|
27
|
+
{{- if or .resources.cpu .resources.memory }}
|
|
28
|
+
requests:
|
|
29
|
+
{{- if .resources.cpu }}
|
|
30
|
+
cpu: {{ index .resources.cpu 0 }}
|
|
31
|
+
{{- end }}
|
|
32
|
+
{{- if .resources.memory }}
|
|
33
|
+
memory: {{ index .resources.memory 0 }}
|
|
34
|
+
{{- end }}
|
|
35
|
+
limits:
|
|
36
|
+
{{- if .resources.cpu }}
|
|
37
|
+
cpu: {{ index .resources.cpu 1 }}
|
|
38
|
+
{{- end }}
|
|
39
|
+
{{- if .resources.memory }}
|
|
40
|
+
memory: {{ index .resources.memory 1 }}
|
|
41
|
+
{{- end }}
|
|
42
|
+
{{- end }}
|
|
43
|
+
{{- end }}
|
|
22
44
|
{{- if .variables }}
|
|
23
45
|
env:
|
|
24
46
|
{{- range .variables }}
|
|
25
47
|
{{- include "env.var" . | indent 12 }}
|
|
26
48
|
{{- end }}
|
|
27
49
|
{{- end }}
|
|
50
|
+
{{- if .probe }}
|
|
51
|
+
ports:
|
|
52
|
+
- containerPort: {{ .probe.port }}
|
|
53
|
+
startupProbe:
|
|
54
|
+
httpGet:
|
|
55
|
+
path: {{ .probe.path }}
|
|
56
|
+
port: {{ .probe.port }}
|
|
57
|
+
{{- if .probe.delay }}
|
|
58
|
+
initialDelaySeconds: {{ .probe.delay }}
|
|
59
|
+
{{- end }}
|
|
60
|
+
periodSeconds: 2
|
|
61
|
+
timeoutSeconds: 3
|
|
62
|
+
failureThreshold: 150
|
|
63
|
+
readinessProbe:
|
|
64
|
+
httpGet:
|
|
65
|
+
path: {{ .probe.path }}
|
|
66
|
+
port: {{ .probe.port }}
|
|
67
|
+
periodSeconds: 10
|
|
68
|
+
timeoutSeconds: 3
|
|
69
|
+
failureThreshold: 3
|
|
70
|
+
{{- end }}
|
|
71
|
+
{{- if .mounts }}
|
|
72
|
+
volumeMounts:
|
|
73
|
+
{{- range .mounts }}
|
|
74
|
+
- name: {{ .name }}
|
|
75
|
+
mountPath: {{ .path }}
|
|
76
|
+
{{- end }}
|
|
77
|
+
{{- end }}
|
|
78
|
+
lifecycle:
|
|
79
|
+
preStop:
|
|
80
|
+
exec:
|
|
81
|
+
command: [sleep, "5"]
|
|
82
|
+
terminationGracePeriodSeconds: 45
|
|
28
83
|
{{- if $.Values.credentials }}
|
|
29
84
|
imagePullSecrets:
|
|
30
85
|
- name: {{ $.Values.credentials }}
|
|
31
86
|
{{- end }}
|
|
87
|
+
{{- if .mounts }}
|
|
88
|
+
volumes:
|
|
89
|
+
{{- range .mounts }}
|
|
90
|
+
- name: {{ .name }}
|
|
91
|
+
persistentVolumeClaim:
|
|
92
|
+
claimName: {{ .claim }}
|
|
93
|
+
{{- end }}
|
|
94
|
+
{{- end }}
|
|
95
|
+
topologySpreadConstraints:
|
|
96
|
+
- maxSkew: 1
|
|
97
|
+
topologyKey: kubernetes.io/hostname
|
|
98
|
+
whenUnsatisfiable: ScheduleAnyway
|
|
99
|
+
labelSelector:
|
|
100
|
+
matchLabels:
|
|
101
|
+
toa.io/composition: {{ .name }}
|
|
32
102
|
---
|
|
33
103
|
{{- end }}
|
|
@@ -0,0 +1,177 @@
|
|
|
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 or .backends .probe }}
|
|
30
|
+
ports:
|
|
31
|
+
{{- range .backends }}
|
|
32
|
+
- containerPort: {{ .port }}
|
|
33
|
+
{{- end }}
|
|
34
|
+
{{- if .probe }}
|
|
35
|
+
- containerPort: {{ .probe.port }}
|
|
36
|
+
{{- end }}
|
|
37
|
+
{{- end }}
|
|
38
|
+
{{- if .resources }}
|
|
39
|
+
resources:
|
|
40
|
+
{{- if or .resources.cpu .resources.memory }}
|
|
41
|
+
requests:
|
|
42
|
+
{{- if .resources.cpu }}
|
|
43
|
+
cpu: {{ index .resources.cpu 0 }}
|
|
44
|
+
{{- end }}
|
|
45
|
+
{{- if .resources.memory }}
|
|
46
|
+
memory: {{ index .resources.memory 0 }}
|
|
47
|
+
{{- end }}
|
|
48
|
+
limits:
|
|
49
|
+
{{- if .resources.cpu }}
|
|
50
|
+
cpu: {{ index .resources.cpu 1 }}
|
|
51
|
+
{{- end }}
|
|
52
|
+
{{- if .resources.memory }}
|
|
53
|
+
memory: {{ index .resources.memory 1 }}
|
|
54
|
+
{{- end }}
|
|
55
|
+
{{- end }}
|
|
56
|
+
{{- end }}
|
|
57
|
+
{{- if .variables }}
|
|
58
|
+
env:
|
|
59
|
+
{{- range .variables }}
|
|
60
|
+
{{- include "env.var" . | indent 12 }}
|
|
61
|
+
{{- end }}
|
|
62
|
+
{{- end }}
|
|
63
|
+
{{- if .probe }}
|
|
64
|
+
startupProbe:
|
|
65
|
+
httpGet:
|
|
66
|
+
path: {{ .probe.path }}
|
|
67
|
+
port: {{ .probe.port }}
|
|
68
|
+
{{- if .probe.delay }}
|
|
69
|
+
initialDelaySeconds: {{ .probe.delay }}
|
|
70
|
+
{{- end }}
|
|
71
|
+
periodSeconds: 2
|
|
72
|
+
timeoutSeconds: 3
|
|
73
|
+
failureThreshold: 150
|
|
74
|
+
readinessProbe:
|
|
75
|
+
httpGet:
|
|
76
|
+
path: {{ .probe.path }}
|
|
77
|
+
port: {{ .probe.port }}
|
|
78
|
+
periodSeconds: 10
|
|
79
|
+
timeoutSeconds: 3
|
|
80
|
+
failureThreshold: 3
|
|
81
|
+
{{- end }}
|
|
82
|
+
{{- if .mounts }}
|
|
83
|
+
volumeMounts:
|
|
84
|
+
{{- range .mounts }}
|
|
85
|
+
- name: {{ .name }}
|
|
86
|
+
mountPath: {{ .path }}
|
|
87
|
+
{{- end }}
|
|
88
|
+
{{- end }}
|
|
89
|
+
lifecycle:
|
|
90
|
+
preStop:
|
|
91
|
+
exec:
|
|
92
|
+
command: [sleep, "5"]
|
|
93
|
+
terminationGracePeriodSeconds: 45
|
|
94
|
+
{{- if $.Values.credentials }}
|
|
95
|
+
imagePullSecrets:
|
|
96
|
+
- name: {{ $.Values.credentials }}
|
|
97
|
+
{{- end }}
|
|
98
|
+
{{- if .mounts }}
|
|
99
|
+
volumes:
|
|
100
|
+
{{- range .mounts }}
|
|
101
|
+
- name: {{ .name }}
|
|
102
|
+
persistentVolumeClaim:
|
|
103
|
+
claimName: {{ .claim }}
|
|
104
|
+
{{- end }}
|
|
105
|
+
{{- end }}
|
|
106
|
+
topologySpreadConstraints:
|
|
107
|
+
- maxSkew: 1
|
|
108
|
+
topologyKey: kubernetes.io/hostname
|
|
109
|
+
whenUnsatisfiable: ScheduleAnyway
|
|
110
|
+
labelSelector:
|
|
111
|
+
matchLabels:
|
|
112
|
+
toa.io/composition: mono
|
|
113
|
+
{{- if .backends }}
|
|
114
|
+
---
|
|
115
|
+
apiVersion: v1
|
|
116
|
+
kind: Service
|
|
117
|
+
metadata:
|
|
118
|
+
name: mono
|
|
119
|
+
spec:
|
|
120
|
+
type: ClusterIP
|
|
121
|
+
selector:
|
|
122
|
+
toa.io/composition: mono
|
|
123
|
+
ports:
|
|
124
|
+
{{- range .backends }}
|
|
125
|
+
- name: port-{{ .port }}
|
|
126
|
+
protocol: TCP
|
|
127
|
+
port: {{ .port }}
|
|
128
|
+
targetPort: {{ .port }}
|
|
129
|
+
{{- end }}
|
|
130
|
+
{{- end }}
|
|
131
|
+
{{- if .ingress }}
|
|
132
|
+
---
|
|
133
|
+
apiVersion: networking.k8s.io/v1
|
|
134
|
+
kind: Ingress
|
|
135
|
+
metadata:
|
|
136
|
+
name: mono
|
|
137
|
+
{{- if .ingress.annotations }}
|
|
138
|
+
annotations:
|
|
139
|
+
{{ toYaml .ingress.annotations | indent 4 }}
|
|
140
|
+
{{- end }}
|
|
141
|
+
spec:
|
|
142
|
+
{{- if .ingress.class }}
|
|
143
|
+
ingressClassName: {{ .ingress.class }}
|
|
144
|
+
{{- end }}
|
|
145
|
+
{{- $backends := .backends }}
|
|
146
|
+
rules:
|
|
147
|
+
{{- range .ingress.hosts }}
|
|
148
|
+
- host: {{ . }}
|
|
149
|
+
http:
|
|
150
|
+
paths:
|
|
151
|
+
{{- range $backends }}
|
|
152
|
+
- path: {{ .path }}
|
|
153
|
+
pathType: Prefix
|
|
154
|
+
backend:
|
|
155
|
+
service:
|
|
156
|
+
name: mono
|
|
157
|
+
port:
|
|
158
|
+
number: {{ .port }}
|
|
159
|
+
{{- end }}
|
|
160
|
+
{{- end }}
|
|
161
|
+
{{- if .ingress.default }}
|
|
162
|
+
- http:
|
|
163
|
+
paths:
|
|
164
|
+
{{- range $backends }}
|
|
165
|
+
- path: {{ .path }}
|
|
166
|
+
pathType: Prefix
|
|
167
|
+
backend:
|
|
168
|
+
service:
|
|
169
|
+
name: mono
|
|
170
|
+
port:
|
|
171
|
+
number: {{ .port }}
|
|
172
|
+
{{- end }}
|
|
173
|
+
{{- end }}
|
|
174
|
+
{{- end }}
|
|
175
|
+
---
|
|
176
|
+
{{- end }}
|
|
177
|
+
{{- end }}
|
|
@@ -5,6 +5,16 @@ metadata:
|
|
|
5
5
|
name: extension-{{ required "deployment name is required" .name }}
|
|
6
6
|
spec:
|
|
7
7
|
replicas: {{ .replicas | default 2 }}
|
|
8
|
+
# A backstop for stuck rollouts only. Must stay above the `helm upgrade --timeout`
|
|
9
|
+
# the deploy runs with, so a slow but progressing rollout is not marked failed.
|
|
10
|
+
progressDeadlineSeconds: 900
|
|
11
|
+
strategy:
|
|
12
|
+
type: RollingUpdate
|
|
13
|
+
rollingUpdate:
|
|
14
|
+
# a replacement must pass readiness before a running replica is taken out,
|
|
15
|
+
# otherwise a single pod serves all traffic while the others start up
|
|
16
|
+
maxUnavailable: 0
|
|
17
|
+
maxSurge: 50%
|
|
8
18
|
selector:
|
|
9
19
|
matchLabels:
|
|
10
20
|
toa.io/service: extension-{{ .name }}
|
|
@@ -16,6 +26,25 @@ spec:
|
|
|
16
26
|
containers:
|
|
17
27
|
- name: extension-{{ .name }}
|
|
18
28
|
image: {{ .image }}
|
|
29
|
+
{{- if .resources }}
|
|
30
|
+
resources:
|
|
31
|
+
{{- if or .resources.cpu .resources.memory }}
|
|
32
|
+
requests:
|
|
33
|
+
{{- if .resources.cpu }}
|
|
34
|
+
cpu: {{ index .resources.cpu 0 }}
|
|
35
|
+
{{- end }}
|
|
36
|
+
{{- if .resources.memory }}
|
|
37
|
+
memory: {{ index .resources.memory 0 }}
|
|
38
|
+
{{- end }}
|
|
39
|
+
limits:
|
|
40
|
+
{{- if .resources.cpu }}
|
|
41
|
+
cpu: {{ index .resources.cpu 1 }}
|
|
42
|
+
{{- end }}
|
|
43
|
+
{{- if .resources.memory }}
|
|
44
|
+
memory: {{ index .resources.memory 1 }}
|
|
45
|
+
{{- end }}
|
|
46
|
+
{{- end }}
|
|
47
|
+
{{- end }}
|
|
19
48
|
{{- if .variables }}
|
|
20
49
|
env:
|
|
21
50
|
{{- range .variables }}
|
|
@@ -23,14 +52,37 @@ spec:
|
|
|
23
52
|
{{- end }}
|
|
24
53
|
{{- end }}
|
|
25
54
|
{{- if .probe }}
|
|
26
|
-
|
|
55
|
+
startupProbe:
|
|
27
56
|
httpGet:
|
|
28
57
|
path: {{ .probe.path }}
|
|
29
58
|
port: {{ .probe.port }}
|
|
30
59
|
{{- if .probe.delay }}
|
|
31
60
|
initialDelaySeconds: {{ .probe.delay }}
|
|
32
61
|
{{- end }}
|
|
62
|
+
periodSeconds: 2
|
|
63
|
+
timeoutSeconds: 3
|
|
64
|
+
failureThreshold: 150
|
|
65
|
+
readinessProbe:
|
|
66
|
+
httpGet:
|
|
67
|
+
path: {{ .probe.path }}
|
|
68
|
+
port: {{ .probe.port }}
|
|
69
|
+
periodSeconds: 10
|
|
70
|
+
timeoutSeconds: 3
|
|
71
|
+
failureThreshold: 3
|
|
33
72
|
{{- end }}
|
|
73
|
+
lifecycle:
|
|
74
|
+
preStop:
|
|
75
|
+
exec:
|
|
76
|
+
command: [sleep, "5"]
|
|
77
|
+
terminationGracePeriodSeconds: 45
|
|
78
|
+
topologySpreadConstraints:
|
|
79
|
+
- maxSkew: 1
|
|
80
|
+
topologyKey: kubernetes.io/hostname
|
|
81
|
+
whenUnsatisfiable: ScheduleAnyway
|
|
82
|
+
labelSelector:
|
|
83
|
+
matchLabels:
|
|
84
|
+
toa.io/service: extension-{{ .name }}
|
|
85
|
+
{{- if .port }}
|
|
34
86
|
---
|
|
35
87
|
apiVersion: v1
|
|
36
88
|
kind: Service
|
|
@@ -45,9 +97,12 @@ spec:
|
|
|
45
97
|
protocol: TCP
|
|
46
98
|
port: {{ .port }}
|
|
47
99
|
targetPort: {{ .port }}
|
|
48
|
-
|
|
100
|
+
{{- end }}
|
|
49
101
|
{{- if .ingress }}
|
|
50
102
|
{{- $service := .name }}
|
|
103
|
+
{{- $port := .port }}
|
|
104
|
+
{{- $path := .ingress.path | default "/" }}
|
|
105
|
+
---
|
|
51
106
|
apiVersion: networking.k8s.io/v1
|
|
52
107
|
kind: Ingress
|
|
53
108
|
metadata:
|
|
@@ -65,13 +120,25 @@ spec:
|
|
|
65
120
|
- host: {{ . }}
|
|
66
121
|
http:
|
|
67
122
|
paths:
|
|
68
|
-
- path:
|
|
123
|
+
- path: {{ $path }}
|
|
69
124
|
pathType: Prefix
|
|
70
125
|
backend:
|
|
71
126
|
service:
|
|
72
127
|
name: extension-{{ $service }}
|
|
73
128
|
port:
|
|
74
|
-
number:
|
|
129
|
+
number: {{ $port }}
|
|
130
|
+
{{- end }}
|
|
131
|
+
{{- if .ingress.default }}
|
|
132
|
+
- http:
|
|
133
|
+
paths:
|
|
134
|
+
- path: {{ $path }}
|
|
135
|
+
pathType: Prefix
|
|
136
|
+
backend:
|
|
137
|
+
service:
|
|
138
|
+
name: extension-{{ $service }}
|
|
139
|
+
port:
|
|
140
|
+
number: {{ $port }}
|
|
75
141
|
{{- end }}
|
|
76
142
|
{{- end }}
|
|
143
|
+
---
|
|
77
144
|
{{- end }}
|
|
@@ -3,9 +3,16 @@ compositions:
|
|
|
3
3
|
- name: todos
|
|
4
4
|
image: localhost:5000/composition-todos:0.0.0
|
|
5
5
|
replicas: 2
|
|
6
|
+
mounts:
|
|
7
|
+
- name: mount-name
|
|
8
|
+
path: /storage
|
|
9
|
+
claim: storage-pvc
|
|
6
10
|
components:
|
|
7
11
|
- todos-tasks
|
|
8
12
|
- todos-stats
|
|
13
|
+
resources:
|
|
14
|
+
cpu: [100m, 1]
|
|
15
|
+
memory: [100Mi, 1Gi]
|
|
9
16
|
variables:
|
|
10
17
|
- name: TOA_CONFIGURATION_TODOS_TASKS
|
|
11
18
|
value: foo
|
|
@@ -18,7 +25,6 @@ compositions:
|
|
|
18
25
|
replicas: 3
|
|
19
26
|
components:
|
|
20
27
|
- users-users
|
|
21
|
-
# TODO: create component services only if sync binding is being used
|
|
22
28
|
components:
|
|
23
29
|
- todos-tasks
|
|
24
30
|
- todos-stats
|
|
@@ -28,7 +34,11 @@ services:
|
|
|
28
34
|
image: localhost:5000/resources-gateway:0.0.0
|
|
29
35
|
port: 8000
|
|
30
36
|
replicas: 2
|
|
37
|
+
resources:
|
|
38
|
+
cpu: [100m, 1]
|
|
39
|
+
memory: [100Mi, 1Gi]
|
|
31
40
|
ingress:
|
|
41
|
+
default: true
|
|
32
42
|
hosts: [dummies.toa.io]
|
|
33
43
|
class: alb
|
|
34
44
|
annotations:
|
|
@@ -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
|
|
|
@@ -42,6 +42,7 @@ class Deployment {
|
|
|
42
42
|
|
|
43
43
|
if (options.namespace !== undefined) args.push('-n', options.namespace)
|
|
44
44
|
if (options.wait === true) args.push('--wait')
|
|
45
|
+
if (options.timeout !== undefined) args.push('--timeout', options.timeout)
|
|
45
46
|
|
|
46
47
|
await this.#process.execute('helm', ['dependency', 'update', this.#target])
|
|
47
48
|
await this.#process.execute('helm', ['upgrade', this.#chart.name, '-i', ...args, this.#target])
|
|
@@ -68,6 +69,9 @@ class Deployment {
|
|
|
68
69
|
addVariables(this.#values.compositions, variables, used)
|
|
69
70
|
addVariables(this.#values.services, variables, used)
|
|
70
71
|
|
|
72
|
+
if (this.#values.mono !== undefined)
|
|
73
|
+
addVariables([this.#values.mono], variables, used)
|
|
74
|
+
|
|
71
75
|
return variables
|
|
72
76
|
}
|
|
73
77
|
}
|
|
@@ -11,25 +11,40 @@ const { Service } = require('./service')
|
|
|
11
11
|
|
|
12
12
|
class Factory {
|
|
13
13
|
#context
|
|
14
|
+
#mono
|
|
14
15
|
#compositions
|
|
15
16
|
#dependencies
|
|
16
17
|
#registry
|
|
17
18
|
#process
|
|
18
|
-
#
|
|
19
|
+
#image
|
|
19
20
|
|
|
20
|
-
constructor (context) {
|
|
21
|
+
constructor (context, options = {}) {
|
|
21
22
|
this.#context = context
|
|
23
|
+
this.#mono = options.mono === true
|
|
22
24
|
this.#process = new Process()
|
|
23
25
|
|
|
24
26
|
const imagesFactory = new ImagesFactory(context.name, context.runtime, context.registry)
|
|
25
27
|
|
|
26
|
-
this.#registry = new Registry(context.registry, imagesFactory, this.#process)
|
|
27
|
-
this.#compositions = context.compositions.map((composition) => this.#composition(composition))
|
|
28
|
+
this.#registry = new Registry(context.name, context.registry, imagesFactory, this.#process)
|
|
28
29
|
this.#dependencies = this.#getDependencies()
|
|
30
|
+
this.#compositions = []
|
|
31
|
+
|
|
32
|
+
if (this.#mono)
|
|
33
|
+
this.#image = this.#registry.mono({
|
|
34
|
+
components: context.components
|
|
35
|
+
})
|
|
36
|
+
else
|
|
37
|
+
this.#compositions = context.compositions.map((composition) => this.#composition(composition))
|
|
29
38
|
}
|
|
30
39
|
|
|
31
40
|
operator () {
|
|
32
|
-
const deployment = new Deployment(
|
|
41
|
+
const deployment = new Deployment(
|
|
42
|
+
this.#context,
|
|
43
|
+
this.#compositions,
|
|
44
|
+
this.#dependencies,
|
|
45
|
+
this.#process,
|
|
46
|
+
this.#image
|
|
47
|
+
)
|
|
33
48
|
|
|
34
49
|
return new Operator(deployment, this.#registry)
|
|
35
50
|
}
|
|
@@ -71,7 +86,8 @@ class Factory {
|
|
|
71
86
|
const dependency = module.deployment(instances, annotation)
|
|
72
87
|
|
|
73
88
|
/** @type {toa.deployment.Service[]} */
|
|
74
|
-
const services = dependency.services?.map((service) =>
|
|
89
|
+
const services = dependency.services?.map((service) =>
|
|
90
|
+
this.#mono ? service : this.#service(path, service))
|
|
75
91
|
|
|
76
92
|
return { ...dependency, services }
|
|
77
93
|
}
|
|
@@ -87,10 +103,10 @@ class Factory {
|
|
|
87
103
|
return new Service(service, image)
|
|
88
104
|
}
|
|
89
105
|
|
|
90
|
-
static async create (path, environment) {
|
|
106
|
+
static async create (path, environment, options = {}) {
|
|
91
107
|
const context = await load(path, environment)
|
|
92
108
|
|
|
93
|
-
return new Factory(context)
|
|
109
|
+
return new Factory(context, options)
|
|
94
110
|
}
|
|
95
111
|
}
|
|
96
112
|
|
|
@@ -5,7 +5,6 @@ FROM {{build.image}}
|
|
|
5
5
|
ENV NODE_ENV=production
|
|
6
6
|
RUN if [ "{{runtime.registry}}" != "" ]; then npm set registry {{runtime.registry}}; fi
|
|
7
7
|
RUN if [ "{{runtime.proxy}}" != "" ]; then npm set proxy {{runtime.proxy}}; fi
|
|
8
|
-
RUN npm i -g @toa.io/runtime@{{runtime.version}} --omit=dev
|
|
9
8
|
|
|
10
9
|
WORKDIR /composition
|
|
11
10
|
COPY --chown=node:node . /composition
|
|
@@ -13,7 +12,8 @@ COPY --chown=node:node . /composition
|
|
|
13
12
|
{{build.run}}
|
|
14
13
|
|
|
15
14
|
# run 'npm i' in each component
|
|
16
|
-
RUN
|
|
15
|
+
RUN --mount=type=cache,target=/root/.npm \
|
|
16
|
+
for entry in *; do if [ -f "$entry/package.json" ]; then (cd $entry && npm i --omit=dev); fi; done
|
|
17
17
|
|
|
18
18
|
USER node
|
|
19
19
|
CMD toa compose *
|