@toa.io/operations 1.0.0-alpha.27 → 1.0.0-alpha.270
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 +109 -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/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 +84 -6
- package/src/deployment/.deployment/merge.js +41 -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/images/image.d.ts +4 -2
- package/types/_deployment/registry.d.ts +9 -7
- package/types/dependency.ts +69 -0
- package/types/dependency.d.ts +0 -39
- /package/types/{index.d.ts → index.ts} +0 -0
|
@@ -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 *
|
|
@@ -5,6 +5,7 @@ const fs = require('fs-extra')
|
|
|
5
5
|
const { createHash } = require('node:crypto')
|
|
6
6
|
|
|
7
7
|
const { Image } = require('./image')
|
|
8
|
+
const { undef } = require('@toa.io/concise/source/expressions/undefined')
|
|
8
9
|
|
|
9
10
|
class Composition extends Image {
|
|
10
11
|
dockerfile = join(__dirname, 'composition.Dockerfile')
|
|
@@ -37,23 +38,27 @@ class Composition extends Image {
|
|
|
37
38
|
}
|
|
38
39
|
|
|
39
40
|
get base () {
|
|
40
|
-
if (this.#image !== undefined)
|
|
41
|
-
return this.#image
|
|
42
|
-
}
|
|
41
|
+
if (this.#image !== undefined) return this.#image
|
|
43
42
|
|
|
44
|
-
|
|
43
|
+
const images = new Set(this.#components.map((component) => component.build?.image))
|
|
45
44
|
|
|
46
|
-
|
|
47
|
-
|
|
45
|
+
if (images.size > 1)
|
|
46
|
+
throw new Error(`Composition '${this.#name}' requires different base images for its components. Specify base image for the composition in the context.`)
|
|
47
|
+
|
|
48
|
+
return images.values().next().value
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
get run () {
|
|
52
|
+
const commands = []
|
|
48
53
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
}
|
|
54
|
+
for (const component of this.#components) {
|
|
55
|
+
const run = component.build?.run
|
|
52
56
|
|
|
53
|
-
|
|
57
|
+
if (run !== undefined)
|
|
58
|
+
commands.push(run)
|
|
54
59
|
}
|
|
55
60
|
|
|
56
|
-
return
|
|
61
|
+
return commands.join('\n')
|
|
57
62
|
}
|
|
58
63
|
|
|
59
64
|
async prepare (root) {
|
|
@@ -2,10 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
const { Composition } = require('./composition')
|
|
4
4
|
const { Service } = require('./service')
|
|
5
|
+
const { Mono } = require('./mono')
|
|
5
6
|
|
|
6
|
-
/**
|
|
7
|
-
* @implements {toa.deployment.images.Factory}
|
|
8
|
-
*/
|
|
9
7
|
class Factory {
|
|
10
8
|
/** @type {string} */
|
|
11
9
|
#scope
|
|
@@ -48,6 +46,17 @@ class Factory {
|
|
|
48
46
|
|
|
49
47
|
return instance
|
|
50
48
|
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* @returns {Mono}
|
|
52
|
+
*/
|
|
53
|
+
mono (composition) {
|
|
54
|
+
const instance = new Mono(this.#scope, this.#runtime, this.#registry, composition)
|
|
55
|
+
|
|
56
|
+
instance.tag()
|
|
57
|
+
|
|
58
|
+
return instance
|
|
59
|
+
}
|
|
51
60
|
}
|
|
52
61
|
|
|
53
62
|
exports.Factory = Factory
|
|
@@ -26,9 +26,7 @@ class Image {
|
|
|
26
26
|
#registry
|
|
27
27
|
#runtime
|
|
28
28
|
#values = {
|
|
29
|
-
build: {
|
|
30
|
-
image: 'node:20.9.0-alpine3.18'
|
|
31
|
-
}
|
|
29
|
+
build: {}
|
|
32
30
|
}
|
|
33
31
|
|
|
34
32
|
constructor (scope, runtime, registry) {
|
|
@@ -54,6 +52,8 @@ class Image {
|
|
|
54
52
|
|
|
55
53
|
get base () {}
|
|
56
54
|
|
|
55
|
+
get run () {}
|
|
56
|
+
|
|
57
57
|
async prepare (root) {
|
|
58
58
|
if (this.dockerfile === undefined) throw new Error('Dockerfile isn\'t specified')
|
|
59
59
|
|
|
@@ -65,7 +65,7 @@ class Image {
|
|
|
65
65
|
|
|
66
66
|
const template = await read(this.dockerfile, 'utf-8')
|
|
67
67
|
const contents = template.replace(/{{(\S{1,32})}}/g, (_, key) => this.#value(key))
|
|
68
|
-
const ignore = 'Dockerfile'
|
|
68
|
+
const ignore = ['Dockerfile', '**/node_modules'].join('\r\n')
|
|
69
69
|
|
|
70
70
|
await write(join(path, 'Dockerfile'), contents)
|
|
71
71
|
await write(join(path, '.dockerignore'), ignore)
|
|
@@ -77,13 +77,19 @@ class Image {
|
|
|
77
77
|
|
|
78
78
|
#setValues () {
|
|
79
79
|
this.#values.runtime = this.#runtime
|
|
80
|
-
this.#values.build = overwrite(
|
|
80
|
+
this.#values.build = overwrite({
|
|
81
|
+
image: `${RUNTIME_IMAGE}:${this.#runtime.version}`
|
|
82
|
+
}, this.#registry.build)
|
|
81
83
|
|
|
82
84
|
const image = this.base
|
|
83
85
|
|
|
84
|
-
if (image !== undefined)
|
|
86
|
+
if (image !== undefined)
|
|
85
87
|
this.#values.build.image = image
|
|
86
|
-
|
|
88
|
+
|
|
89
|
+
const run = this.run
|
|
90
|
+
|
|
91
|
+
if (run !== undefined)
|
|
92
|
+
this.#values.build.run = (this.#values.build.run === undefined ? '' : this.#values.build.run + '\n') + run
|
|
87
93
|
|
|
88
94
|
if (this.#values.build.arguments !== undefined) this.#values.build.arguments = createArguments(this.#values.build.arguments)
|
|
89
95
|
if (this.#values.build.run !== undefined) this.#values.build.run = createRunCommands(this.#values.build.run)
|
|
@@ -121,4 +127,7 @@ function createArguments (variables) {
|
|
|
121
127
|
return args.join('\n')
|
|
122
128
|
}
|
|
123
129
|
|
|
130
|
+
const RUNTIME_IMAGE = 'ghcr.io/toa-io/runtime'
|
|
131
|
+
|
|
124
132
|
exports.Image = Image
|
|
133
|
+
exports.RUNTIME_IMAGE = RUNTIME_IMAGE
|