@toa.io/operations 1.0.0-alpha.29 → 1.0.0-alpha.290
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 +42 -0
- package/image/runtime.Dockerfile +4 -0
- package/package.json +8 -10
- package/readme.md +93 -0
- package/src/deployment/.deployment/.describe/components.js +1 -5
- package/src/deployment/.deployment/.describe/compositions.js +26 -7
- package/src/deployment/.deployment/.describe/dependencies.js +1 -6
- package/src/deployment/.deployment/.describe/events.js +63 -0
- package/src/deployment/.deployment/.describe/fold.js +42 -0
- package/src/deployment/.deployment/.describe/fold.test.js +108 -0
- package/src/deployment/.deployment/.describe/index.js +4 -13
- package/src/deployment/.deployment/.describe/mounts.js +17 -0
- package/src/deployment/.deployment/.describe/resources.js +103 -0
- package/src/deployment/.deployment/.describe/resources.test.js +129 -0
- package/src/deployment/.deployment/.describe/services.js +32 -6
- package/src/deployment/.deployment/.describe/services.test.js +78 -0
- package/src/deployment/.deployment/.describe/variables.js +5 -9
- package/src/deployment/.deployment/declare.js +1 -5
- package/src/deployment/.deployment/describe.js +125 -10
- package/src/deployment/.deployment/index.js +3 -9
- package/src/deployment/.deployment/merge.js +66 -6
- package/src/deployment/.deployment/merge.test.js +133 -0
- package/src/deployment/chart/templates/components.yaml +1 -1
- package/src/deployment/chart/templates/compositions.yaml +96 -4
- package/src/deployment/chart/templates/mono.yaml +182 -0
- package/src/deployment/chart/templates/services.yaml +82 -7
- package/src/deployment/chart/values.yaml +23 -1
- package/src/deployment/composition.js +6 -6
- package/src/deployment/deployment.js +55 -25
- package/src/deployment/drain.js +70 -0
- package/src/deployment/drain.test.js +64 -0
- package/src/deployment/factory.js +121 -32
- package/src/deployment/images/bundle.js +82 -0
- package/src/deployment/images/composition.Dockerfile +8 -16
- package/src/deployment/images/composition.js +9 -56
- package/src/deployment/images/dependencies.Dockerfile +16 -0
- package/src/deployment/images/dependencies.js +141 -0
- package/src/deployment/images/dependencies.test.js +214 -0
- package/src/deployment/images/factory.js +31 -15
- package/src/deployment/images/format.js +52 -0
- package/src/deployment/images/format.test.js +74 -0
- package/src/deployment/images/image.fixtures.js +13 -13
- package/src/deployment/images/image.js +77 -38
- package/src/deployment/images/image.test.js +11 -5
- package/src/deployment/images/index.js +1 -5
- package/src/deployment/images/mono.Dockerfile +11 -0
- package/src/deployment/images/mono.js +15 -0
- package/src/deployment/images/publish.js +93 -0
- package/src/deployment/images/runtime-base.test.js +97 -0
- package/src/deployment/images/service.Dockerfile +5 -4
- package/src/deployment/images/service.js +13 -13
- package/src/deployment/index.js +1 -5
- package/src/deployment/operator.js +13 -13
- package/src/deployment/operator.test.js +8 -7
- package/src/deployment/registry.js +165 -47
- package/src/deployment/registry.test.js +407 -0
- package/src/deployment/service.js +4 -6
- package/src/deployment/workspace.js +13 -8
- package/src/index.js +1 -3
- package/src/process.js +51 -13
- package/src/process.test.js +33 -0
- package/types/_deployment/composition.d.ts +1 -3
- package/types/_deployment/dependency.d.ts +13 -7
- package/types/_deployment/deployment.d.ts +3 -7
- package/types/_deployment/factory.d.ts +2 -4
- package/types/_deployment/images/factory.d.ts +6 -8
- package/types/_deployment/images/image.d.ts +16 -1
- package/types/_deployment/images/registry.d.ts +8 -11
- package/types/_deployment/operator.d.ts +7 -9
- package/types/_deployment/registry.d.ts +4 -4
- package/types/_deployment/service.d.ts +4 -3
- package/types/dependency.ts +79 -0
- package/types/index.ts +1 -0
- package/types/dependency.d.ts +0 -39
- package/types/index.d.ts +0 -1
|
@@ -5,29 +5,121 @@ 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
|
|
11
|
+
strategy:
|
|
12
|
+
type: RollingUpdate
|
|
13
|
+
rollingUpdate:
|
|
14
|
+
# a replacement must pass readiness before a running replica is taken out, and every
|
|
15
|
+
# replacement starts at once: the rollout takes one start-up, not one per replica
|
|
16
|
+
maxUnavailable: 0
|
|
17
|
+
maxSurge: 100%
|
|
8
18
|
selector:
|
|
9
19
|
matchLabels:
|
|
10
|
-
toa
|
|
20
|
+
toa/composition: {{ .name }}
|
|
11
21
|
template:
|
|
12
22
|
metadata:
|
|
13
23
|
labels:
|
|
14
|
-
toa
|
|
24
|
+
toa/composition: {{ .name }}
|
|
15
25
|
{{- range .components }}
|
|
16
|
-
{{ . }}: "1"
|
|
26
|
+
toa/component-{{ . }}: "1"
|
|
27
|
+
{{- end }}
|
|
28
|
+
{{- range .hosted }}
|
|
29
|
+
toa/service-{{ . }}: "1"
|
|
17
30
|
{{- end }}
|
|
18
31
|
spec:
|
|
19
32
|
containers:
|
|
20
33
|
- name: {{ .name }}
|
|
21
34
|
image: {{ .image }}
|
|
22
|
-
{{- if .
|
|
35
|
+
{{- if .resources }}
|
|
36
|
+
resources:
|
|
37
|
+
{{- if or .resources.cpu .resources.memory }}
|
|
38
|
+
requests:
|
|
39
|
+
{{- if .resources.cpu }}
|
|
40
|
+
cpu: {{ index .resources.cpu 0 }}
|
|
41
|
+
{{- end }}
|
|
42
|
+
{{- if .resources.memory }}
|
|
43
|
+
memory: {{ index .resources.memory 0 }}
|
|
44
|
+
{{- end }}
|
|
45
|
+
limits:
|
|
46
|
+
{{- if .resources.cpu }}
|
|
47
|
+
cpu: {{ index .resources.cpu 1 }}
|
|
48
|
+
{{- end }}
|
|
49
|
+
{{- if .resources.memory }}
|
|
50
|
+
memory: {{ index .resources.memory 1 }}
|
|
51
|
+
{{- end }}
|
|
52
|
+
{{- end }}
|
|
53
|
+
{{- end }}
|
|
54
|
+
{{- if or .variables .services }}
|
|
23
55
|
env:
|
|
56
|
+
{{- if .services }}
|
|
57
|
+
- name: TOA_SERVICES
|
|
58
|
+
value: {{ join " " .services | quote }}
|
|
59
|
+
{{- end }}
|
|
24
60
|
{{- range .variables }}
|
|
25
61
|
{{- include "env.var" . | indent 12 }}
|
|
26
62
|
{{- end }}
|
|
27
63
|
{{- end }}
|
|
64
|
+
{{- if or .backends .probe }}
|
|
65
|
+
ports:
|
|
66
|
+
{{- range .backends }}
|
|
67
|
+
- containerPort: {{ .port }}
|
|
68
|
+
{{- end }}
|
|
69
|
+
{{- if .probe }}
|
|
70
|
+
- containerPort: {{ .probe.port }}
|
|
71
|
+
{{- end }}
|
|
72
|
+
{{- end }}
|
|
73
|
+
{{- if .probe }}
|
|
74
|
+
startupProbe:
|
|
75
|
+
httpGet:
|
|
76
|
+
path: {{ .probe.path }}
|
|
77
|
+
port: {{ .probe.port }}
|
|
78
|
+
{{- if .probe.delay }}
|
|
79
|
+
initialDelaySeconds: {{ .probe.delay }}
|
|
80
|
+
{{- end }}
|
|
81
|
+
periodSeconds: 2
|
|
82
|
+
timeoutSeconds: 3
|
|
83
|
+
failureThreshold: 150
|
|
84
|
+
readinessProbe:
|
|
85
|
+
httpGet:
|
|
86
|
+
path: {{ .probe.path }}
|
|
87
|
+
port: {{ .probe.port }}
|
|
88
|
+
# a replica is ready when it says so, not at the next tick of a slow clock
|
|
89
|
+
periodSeconds: 2
|
|
90
|
+
timeoutSeconds: 3
|
|
91
|
+
failureThreshold: 5
|
|
92
|
+
{{- end }}
|
|
93
|
+
{{- if .mounts }}
|
|
94
|
+
volumeMounts:
|
|
95
|
+
{{- range .mounts }}
|
|
96
|
+
- name: {{ .name }}
|
|
97
|
+
mountPath: {{ .path }}
|
|
98
|
+
{{- end }}
|
|
99
|
+
{{- end }}
|
|
100
|
+
lifecycle:
|
|
101
|
+
preStop:
|
|
102
|
+
exec:
|
|
103
|
+
command: [sleep, "5"]
|
|
104
|
+
terminationGracePeriodSeconds: 45
|
|
28
105
|
{{- if $.Values.credentials }}
|
|
29
106
|
imagePullSecrets:
|
|
30
107
|
- name: {{ $.Values.credentials }}
|
|
31
108
|
{{- end }}
|
|
109
|
+
{{- if .mounts }}
|
|
110
|
+
volumes:
|
|
111
|
+
{{- range .mounts }}
|
|
112
|
+
- name: {{ .name }}
|
|
113
|
+
persistentVolumeClaim:
|
|
114
|
+
claimName: {{ .claim }}
|
|
115
|
+
{{- end }}
|
|
116
|
+
{{- end }}
|
|
117
|
+
topologySpreadConstraints:
|
|
118
|
+
- maxSkew: 1
|
|
119
|
+
topologyKey: kubernetes.io/hostname
|
|
120
|
+
whenUnsatisfiable: ScheduleAnyway
|
|
121
|
+
labelSelector:
|
|
122
|
+
matchLabels:
|
|
123
|
+
toa/composition: {{ .name }}
|
|
32
124
|
---
|
|
33
125
|
{{- end }}
|
|
@@ -0,0 +1,182 @@
|
|
|
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: 100%
|
|
15
|
+
selector:
|
|
16
|
+
matchLabels:
|
|
17
|
+
toa/composition: mono
|
|
18
|
+
template:
|
|
19
|
+
metadata:
|
|
20
|
+
labels:
|
|
21
|
+
toa/composition: mono
|
|
22
|
+
{{- range .components }}
|
|
23
|
+
toa/component-{{ . }}: "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
|
+
# a replica is ready when it says so, not at the next tick of a slow clock
|
|
79
|
+
periodSeconds: 2
|
|
80
|
+
timeoutSeconds: 3
|
|
81
|
+
failureThreshold: 5
|
|
82
|
+
{{- end }}
|
|
83
|
+
{{- if .mounts }}
|
|
84
|
+
volumeMounts:
|
|
85
|
+
{{- range .mounts }}
|
|
86
|
+
- name: {{ .name }}
|
|
87
|
+
mountPath: {{ .path }}
|
|
88
|
+
{{- end }}
|
|
89
|
+
{{- end }}
|
|
90
|
+
lifecycle:
|
|
91
|
+
preStop:
|
|
92
|
+
exec:
|
|
93
|
+
command: [sleep, "5"]
|
|
94
|
+
terminationGracePeriodSeconds: 45
|
|
95
|
+
{{- if $.Values.credentials }}
|
|
96
|
+
imagePullSecrets:
|
|
97
|
+
- name: {{ $.Values.credentials }}
|
|
98
|
+
{{- end }}
|
|
99
|
+
{{- if .mounts }}
|
|
100
|
+
volumes:
|
|
101
|
+
{{- range .mounts }}
|
|
102
|
+
- name: {{ .name }}
|
|
103
|
+
persistentVolumeClaim:
|
|
104
|
+
claimName: {{ .claim }}
|
|
105
|
+
{{- end }}
|
|
106
|
+
{{- end }}
|
|
107
|
+
topologySpreadConstraints:
|
|
108
|
+
- maxSkew: 1
|
|
109
|
+
topologyKey: kubernetes.io/hostname
|
|
110
|
+
whenUnsatisfiable: ScheduleAnyway
|
|
111
|
+
labelSelector:
|
|
112
|
+
matchLabels:
|
|
113
|
+
toa/composition: mono
|
|
114
|
+
{{- if .backends }}
|
|
115
|
+
---
|
|
116
|
+
apiVersion: v1
|
|
117
|
+
kind: Service
|
|
118
|
+
metadata:
|
|
119
|
+
name: mono
|
|
120
|
+
{{- if .annotations }}
|
|
121
|
+
annotations:
|
|
122
|
+
{{ toYaml .annotations | indent 4 }}
|
|
123
|
+
{{- end }}
|
|
124
|
+
spec:
|
|
125
|
+
type: ClusterIP
|
|
126
|
+
selector:
|
|
127
|
+
toa/composition: mono
|
|
128
|
+
ports:
|
|
129
|
+
{{- range .backends }}
|
|
130
|
+
- name: port-{{ .port }}
|
|
131
|
+
protocol: TCP
|
|
132
|
+
port: {{ .port }}
|
|
133
|
+
targetPort: {{ .port }}
|
|
134
|
+
{{- end }}
|
|
135
|
+
{{- end }}
|
|
136
|
+
{{- if .ingress }}
|
|
137
|
+
---
|
|
138
|
+
apiVersion: networking.k8s.io/v1
|
|
139
|
+
kind: Ingress
|
|
140
|
+
metadata:
|
|
141
|
+
name: mono
|
|
142
|
+
{{- if .ingress.annotations }}
|
|
143
|
+
annotations:
|
|
144
|
+
{{ toYaml .ingress.annotations | indent 4 }}
|
|
145
|
+
{{- end }}
|
|
146
|
+
spec:
|
|
147
|
+
{{- if .ingress.class }}
|
|
148
|
+
ingressClassName: {{ .ingress.class }}
|
|
149
|
+
{{- end }}
|
|
150
|
+
{{- $backends := .backends }}
|
|
151
|
+
rules:
|
|
152
|
+
{{- range .ingress.hosts }}
|
|
153
|
+
- host: {{ . }}
|
|
154
|
+
http:
|
|
155
|
+
paths:
|
|
156
|
+
{{- range $backends }}
|
|
157
|
+
- path: {{ .path }}
|
|
158
|
+
pathType: Prefix
|
|
159
|
+
backend:
|
|
160
|
+
service:
|
|
161
|
+
name: mono
|
|
162
|
+
port:
|
|
163
|
+
number: {{ .port }}
|
|
164
|
+
{{- end }}
|
|
165
|
+
{{- end }}
|
|
166
|
+
{{- if .ingress.default }}
|
|
167
|
+
- http:
|
|
168
|
+
paths:
|
|
169
|
+
{{- range $backends }}
|
|
170
|
+
- path: {{ .path }}
|
|
171
|
+
pathType: Prefix
|
|
172
|
+
backend:
|
|
173
|
+
service:
|
|
174
|
+
name: mono
|
|
175
|
+
port:
|
|
176
|
+
number: {{ .port }}
|
|
177
|
+
{{- end }}
|
|
178
|
+
{{- end }}
|
|
179
|
+
{{- end }}
|
|
180
|
+
---
|
|
181
|
+
{{- end }}
|
|
182
|
+
{{- end }}
|
|
@@ -1,21 +1,52 @@
|
|
|
1
1
|
{{- range .Values.services }}
|
|
2
|
+
{{- if not .workload }}
|
|
2
3
|
apiVersion: apps/v1
|
|
3
4
|
kind: Deployment
|
|
4
5
|
metadata:
|
|
5
6
|
name: extension-{{ required "deployment name is required" .name }}
|
|
6
7
|
spec:
|
|
7
8
|
replicas: {{ .replicas | default 2 }}
|
|
9
|
+
# A backstop for stuck rollouts only. Must stay above the `helm upgrade --timeout`
|
|
10
|
+
# the deploy runs with, so a slow but progressing rollout is not marked failed.
|
|
11
|
+
progressDeadlineSeconds: 900
|
|
12
|
+
strategy:
|
|
13
|
+
type: RollingUpdate
|
|
14
|
+
rollingUpdate:
|
|
15
|
+
# a replacement must pass readiness before a running replica is taken out, and every
|
|
16
|
+
# replacement starts at once: the rollout takes one start-up, not one per replica
|
|
17
|
+
maxUnavailable: 0
|
|
18
|
+
maxSurge: 100%
|
|
8
19
|
selector:
|
|
9
20
|
matchLabels:
|
|
10
|
-
toa
|
|
21
|
+
toa/service: extension-{{ .name }}
|
|
11
22
|
template:
|
|
12
23
|
metadata:
|
|
13
24
|
labels:
|
|
14
|
-
toa
|
|
25
|
+
toa/service: extension-{{ .name }}
|
|
26
|
+
toa/service-{{ .name }}: "1"
|
|
15
27
|
spec:
|
|
16
28
|
containers:
|
|
17
29
|
- name: extension-{{ .name }}
|
|
18
30
|
image: {{ .image }}
|
|
31
|
+
{{- if .resources }}
|
|
32
|
+
resources:
|
|
33
|
+
{{- if or .resources.cpu .resources.memory }}
|
|
34
|
+
requests:
|
|
35
|
+
{{- if .resources.cpu }}
|
|
36
|
+
cpu: {{ index .resources.cpu 0 }}
|
|
37
|
+
{{- end }}
|
|
38
|
+
{{- if .resources.memory }}
|
|
39
|
+
memory: {{ index .resources.memory 0 }}
|
|
40
|
+
{{- end }}
|
|
41
|
+
limits:
|
|
42
|
+
{{- if .resources.cpu }}
|
|
43
|
+
cpu: {{ index .resources.cpu 1 }}
|
|
44
|
+
{{- end }}
|
|
45
|
+
{{- if .resources.memory }}
|
|
46
|
+
memory: {{ index .resources.memory 1 }}
|
|
47
|
+
{{- end }}
|
|
48
|
+
{{- end }}
|
|
49
|
+
{{- end }}
|
|
19
50
|
{{- if .variables }}
|
|
20
51
|
env:
|
|
21
52
|
{{- range .variables }}
|
|
@@ -23,31 +54,63 @@ spec:
|
|
|
23
54
|
{{- end }}
|
|
24
55
|
{{- end }}
|
|
25
56
|
{{- if .probe }}
|
|
26
|
-
|
|
57
|
+
startupProbe:
|
|
27
58
|
httpGet:
|
|
28
59
|
path: {{ .probe.path }}
|
|
29
60
|
port: {{ .probe.port }}
|
|
30
61
|
{{- if .probe.delay }}
|
|
31
62
|
initialDelaySeconds: {{ .probe.delay }}
|
|
32
63
|
{{- end }}
|
|
64
|
+
periodSeconds: 2
|
|
65
|
+
timeoutSeconds: 3
|
|
66
|
+
failureThreshold: 150
|
|
67
|
+
readinessProbe:
|
|
68
|
+
httpGet:
|
|
69
|
+
path: {{ .probe.path }}
|
|
70
|
+
port: {{ .probe.port }}
|
|
71
|
+
# a replica is ready when it says so, not at the next tick of a slow clock
|
|
72
|
+
periodSeconds: 2
|
|
73
|
+
timeoutSeconds: 3
|
|
74
|
+
failureThreshold: 5
|
|
33
75
|
{{- end }}
|
|
76
|
+
lifecycle:
|
|
77
|
+
preStop:
|
|
78
|
+
exec:
|
|
79
|
+
command: [sleep, "5"]
|
|
80
|
+
terminationGracePeriodSeconds: 45
|
|
81
|
+
topologySpreadConstraints:
|
|
82
|
+
- maxSkew: 1
|
|
83
|
+
topologyKey: kubernetes.io/hostname
|
|
84
|
+
whenUnsatisfiable: ScheduleAnyway
|
|
85
|
+
labelSelector:
|
|
86
|
+
matchLabels:
|
|
87
|
+
toa/service: extension-{{ .name }}
|
|
88
|
+
{{- end }}
|
|
89
|
+
{{- if .port }}
|
|
34
90
|
---
|
|
35
91
|
apiVersion: v1
|
|
36
92
|
kind: Service
|
|
37
93
|
metadata:
|
|
38
94
|
name: extension-{{ .name }}
|
|
95
|
+
{{- if .annotations }}
|
|
96
|
+
annotations:
|
|
97
|
+
{{ toYaml .annotations | indent 4 }}
|
|
98
|
+
{{- end }}
|
|
39
99
|
spec:
|
|
40
100
|
type: ClusterIP
|
|
41
101
|
selector:
|
|
42
|
-
toa
|
|
102
|
+
toa/service-{{ .name }}: "1"
|
|
43
103
|
ports:
|
|
44
104
|
- name: port-{{ .port }}
|
|
45
105
|
protocol: TCP
|
|
46
106
|
port: {{ .port }}
|
|
47
107
|
targetPort: {{ .port }}
|
|
48
|
-
|
|
108
|
+
{{- end }}
|
|
49
109
|
{{- if .ingress }}
|
|
50
110
|
{{- $service := .name }}
|
|
111
|
+
{{- $port := .port }}
|
|
112
|
+
{{- $path := .ingress.path | default "/" }}
|
|
113
|
+
---
|
|
51
114
|
apiVersion: networking.k8s.io/v1
|
|
52
115
|
kind: Ingress
|
|
53
116
|
metadata:
|
|
@@ -65,13 +128,25 @@ spec:
|
|
|
65
128
|
- host: {{ . }}
|
|
66
129
|
http:
|
|
67
130
|
paths:
|
|
68
|
-
- path:
|
|
131
|
+
- path: {{ $path }}
|
|
132
|
+
pathType: Prefix
|
|
133
|
+
backend:
|
|
134
|
+
service:
|
|
135
|
+
name: extension-{{ $service }}
|
|
136
|
+
port:
|
|
137
|
+
number: {{ $port }}
|
|
138
|
+
{{- end }}
|
|
139
|
+
{{- if .ingress.default }}
|
|
140
|
+
- http:
|
|
141
|
+
paths:
|
|
142
|
+
- path: {{ $path }}
|
|
69
143
|
pathType: Prefix
|
|
70
144
|
backend:
|
|
71
145
|
service:
|
|
72
146
|
name: extension-{{ $service }}
|
|
73
147
|
port:
|
|
74
|
-
number:
|
|
148
|
+
number: {{ $port }}
|
|
75
149
|
{{- end }}
|
|
76
150
|
{{- end }}
|
|
151
|
+
---
|
|
77
152
|
{{- 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,17 +25,32 @@ compositions:
|
|
|
18
25
|
replicas: 3
|
|
19
26
|
components:
|
|
20
27
|
- users-users
|
|
21
|
-
#
|
|
28
|
+
# the extensions whose services this composition runs in its own pod
|
|
29
|
+
services:
|
|
30
|
+
- '@toa.io/extensions.exposition'
|
|
31
|
+
# each of those, as its own Service selects it
|
|
32
|
+
hosted:
|
|
33
|
+
- exposition-gateway
|
|
34
|
+
# the ports they bind
|
|
35
|
+
backends:
|
|
36
|
+
- port: 8000
|
|
37
|
+
path: /
|
|
22
38
|
components:
|
|
23
39
|
- todos-tasks
|
|
24
40
|
- todos-stats
|
|
25
41
|
- users-users
|
|
26
42
|
services:
|
|
43
|
+
# a service a composition runs carries `workload`, and gets no deployment of its own —
|
|
44
|
+
# its Service and Ingress stay, and select that composition's pods
|
|
27
45
|
- name: resources-gateway
|
|
28
46
|
image: localhost:5000/resources-gateway:0.0.0
|
|
29
47
|
port: 8000
|
|
30
48
|
replicas: 2
|
|
49
|
+
resources:
|
|
50
|
+
cpu: [100m, 1]
|
|
51
|
+
memory: [100Mi, 1Gi]
|
|
31
52
|
ingress:
|
|
53
|
+
default: true
|
|
32
54
|
hosts: [dummies.toa.io]
|
|
33
55
|
class: alb
|
|
34
56
|
annotations:
|
|
@@ -1,18 +1,18 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
class Composition {
|
|
1
|
+
export class Composition {
|
|
4
2
|
name
|
|
5
3
|
image
|
|
6
4
|
/** @type {string[]} */
|
|
7
5
|
components
|
|
8
6
|
|
|
9
|
-
constructor
|
|
7
|
+
constructor(composition, image) {
|
|
10
8
|
this.name = composition.name
|
|
11
9
|
this.image = image.reference
|
|
12
10
|
this.components = composition.components.map(component)
|
|
11
|
+
this.resources = composition.resources
|
|
12
|
+
|
|
13
|
+
// the extensions whose services this composition runs, as `TOA_SERVICES` for the process
|
|
14
|
+
if (composition.services !== undefined) this.services = composition.services
|
|
13
15
|
}
|
|
14
16
|
}
|
|
15
17
|
|
|
16
18
|
const component = (component) => component.locator.label
|
|
17
|
-
|
|
18
|
-
exports.Composition = Composition
|
|
@@ -1,78 +1,105 @@
|
|
|
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 { cp } from 'node:fs/promises'
|
|
2
5
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
const { dump } = require('@toa.io/yaml')
|
|
6
|
-
const fs = require('fs-extra')
|
|
6
|
+
import { merge, declare, describe } from './.deployment/index.js'
|
|
7
|
+
import { drain } from './drain.js'
|
|
7
8
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
class Deployment {
|
|
9
|
+
export class Deployment {
|
|
11
10
|
#chart
|
|
12
11
|
#values
|
|
13
12
|
#process
|
|
14
13
|
#target
|
|
15
14
|
|
|
16
|
-
constructor
|
|
15
|
+
constructor(context, compositions, dependencies, process, image) {
|
|
17
16
|
const dependency = merge(dependencies)
|
|
18
17
|
|
|
19
18
|
this.#chart = declare(context, dependency)
|
|
20
|
-
this.#values = describe(context, compositions, dependency)
|
|
19
|
+
this.#values = describe(context, compositions, dependency, image)
|
|
21
20
|
this.#process = process
|
|
22
21
|
}
|
|
23
22
|
|
|
24
|
-
async export
|
|
23
|
+
async export(target) {
|
|
25
24
|
const chart = dump(this.#chart)
|
|
26
25
|
const values = dump(this.#values)
|
|
27
26
|
|
|
28
27
|
await Promise.all([
|
|
29
28
|
write(join(target, 'Chart.yaml'), chart),
|
|
30
29
|
write(join(target, 'values.yaml'), values),
|
|
31
|
-
|
|
30
|
+
cp(TEMPLATES, join(target, 'templates'), { recursive: true })
|
|
32
31
|
])
|
|
33
32
|
|
|
34
33
|
this.#target = target
|
|
35
34
|
}
|
|
36
35
|
|
|
37
|
-
async install
|
|
36
|
+
async install(options) {
|
|
38
37
|
if (options.target) this.#target = options.target
|
|
39
|
-
if (this.#target === undefined) throw new Error(
|
|
38
|
+
if (this.#target === undefined) throw new Error("Deployment hasn't been exported")
|
|
40
39
|
|
|
41
40
|
const args = []
|
|
42
41
|
|
|
43
42
|
if (options.namespace !== undefined) args.push('-n', options.namespace)
|
|
44
43
|
if (options.wait === true) args.push('--wait')
|
|
44
|
+
if (options.timeout !== undefined) args.push('--timeout', options.timeout)
|
|
45
|
+
|
|
46
|
+
await this.#update()
|
|
47
|
+
await this.#process.execute('helm', [
|
|
48
|
+
'upgrade',
|
|
49
|
+
this.#chart.name,
|
|
50
|
+
'-i',
|
|
51
|
+
...args,
|
|
52
|
+
this.#target
|
|
53
|
+
])
|
|
45
54
|
|
|
46
|
-
|
|
47
|
-
|
|
55
|
+
// ready is not done: the replicas replaced are still draining when helm answers
|
|
56
|
+
if (options.wait === true) await drain(this.#process, options)
|
|
48
57
|
}
|
|
49
58
|
|
|
50
|
-
async template
|
|
51
|
-
if (this.#target === undefined) throw new Error(
|
|
59
|
+
async template(options) {
|
|
60
|
+
if (this.#target === undefined) throw new Error("Deployment hasn't been exported")
|
|
52
61
|
|
|
53
|
-
await this.#
|
|
62
|
+
await this.#update({ silently: true })
|
|
54
63
|
|
|
55
64
|
const args = []
|
|
56
65
|
|
|
57
66
|
if (options.namespace !== undefined) args.push('-n', options.namespace)
|
|
58
67
|
|
|
59
|
-
return await this.#process.execute(
|
|
68
|
+
return await this.#process.execute(
|
|
69
|
+
'helm',
|
|
60
70
|
['template', this.#chart.name, ...args, this.#target],
|
|
61
|
-
{ silently: true }
|
|
71
|
+
{ silently: true }
|
|
72
|
+
)
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* A chart with no subcharts has nothing to resolve, and the call still reaches out for
|
|
77
|
+
* the repositories it would have read.
|
|
78
|
+
*
|
|
79
|
+
* @param {object} [options]
|
|
80
|
+
* @returns {Promise<void>}
|
|
81
|
+
*/
|
|
82
|
+
async #update(options = {}) {
|
|
83
|
+
if (this.#chart.dependencies.length === 0) return
|
|
84
|
+
|
|
85
|
+
await this.#process.execute('helm', ['dependency', 'update', this.#target], options)
|
|
62
86
|
}
|
|
63
87
|
|
|
64
|
-
variables
|
|
88
|
+
variables() {
|
|
65
89
|
const variables = []
|
|
66
90
|
const used = new Set()
|
|
67
91
|
|
|
68
92
|
addVariables(this.#values.compositions, variables, used)
|
|
69
93
|
addVariables(this.#values.services, variables, used)
|
|
70
94
|
|
|
95
|
+
if (this.#values.mono !== undefined)
|
|
96
|
+
addVariables([this.#values.mono], variables, used)
|
|
97
|
+
|
|
71
98
|
return variables
|
|
72
99
|
}
|
|
73
100
|
}
|
|
74
101
|
|
|
75
|
-
function addVariables
|
|
102
|
+
function addVariables(list, variables, used = new Set()) {
|
|
76
103
|
for (const item of list) {
|
|
77
104
|
if (item.variables === undefined) continue
|
|
78
105
|
|
|
@@ -85,6 +112,9 @@ function addVariables (list, variables, used = new Set()) {
|
|
|
85
112
|
}
|
|
86
113
|
}
|
|
87
114
|
|
|
88
|
-
const TEMPLATES = join(
|
|
115
|
+
const TEMPLATES = join(import.meta.dirname, 'chart/templates')
|
|
89
116
|
|
|
90
|
-
|
|
117
|
+
function dump(object) {
|
|
118
|
+
// js-yaml writes plain objects only, and the values carry locators and images
|
|
119
|
+
return jsyaml.dump(JSON.parse(JSON.stringify(object)), { noRefs: true, lineWidth: -1 })
|
|
120
|
+
}
|