teraslice 2.11.0 → 2.12.0
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/dist/src/interfaces.js +12 -0
- package/dist/src/lib/cluster/cluster_master.js +246 -0
- package/dist/src/lib/cluster/node_master.js +355 -0
- package/dist/src/lib/cluster/services/api.js +663 -0
- package/dist/src/lib/cluster/services/assets.js +226 -0
- package/dist/src/lib/cluster/services/cluster/backends/kubernetes/index.js +192 -0
- package/dist/src/lib/cluster/services/cluster/backends/kubernetes/k8s.js +481 -0
- package/dist/src/lib/cluster/services/cluster/backends/kubernetes/k8sResource.js +414 -0
- package/dist/src/lib/cluster/services/cluster/backends/kubernetes/k8sState.js +59 -0
- package/dist/src/lib/cluster/services/cluster/backends/kubernetes/utils.js +43 -0
- package/dist/src/lib/cluster/services/cluster/backends/kubernetesV2/index.js +192 -0
- package/dist/src/lib/cluster/services/cluster/backends/kubernetesV2/interfaces.js +2 -0
- package/dist/src/lib/cluster/services/cluster/backends/kubernetesV2/k8s.js +423 -0
- package/dist/src/lib/cluster/services/cluster/backends/kubernetesV2/k8sDeploymentResource.js +60 -0
- package/dist/src/lib/cluster/services/cluster/backends/kubernetesV2/k8sJobResource.js +55 -0
- package/dist/src/lib/cluster/services/cluster/backends/kubernetesV2/k8sResource.js +359 -0
- package/dist/src/lib/cluster/services/cluster/backends/kubernetesV2/k8sServiceResource.js +37 -0
- package/dist/src/lib/cluster/services/cluster/backends/kubernetesV2/k8sState.js +60 -0
- package/dist/src/lib/cluster/services/cluster/backends/kubernetesV2/utils.js +170 -0
- package/dist/src/lib/cluster/services/cluster/backends/native/dispatch.js +13 -0
- package/dist/src/lib/cluster/services/cluster/backends/native/index.js +526 -0
- package/dist/src/lib/cluster/services/cluster/backends/native/messaging.js +547 -0
- package/dist/src/lib/cluster/services/cluster/backends/state-utils.js +26 -0
- package/dist/src/lib/cluster/services/cluster/index.js +17 -0
- package/dist/src/lib/cluster/services/execution.js +435 -0
- package/dist/src/lib/cluster/services/index.js +6 -0
- package/dist/src/lib/cluster/services/interfaces.js +2 -0
- package/dist/src/lib/cluster/services/jobs.js +454 -0
- package/dist/src/lib/config/default-sysconfig.js +26 -0
- package/dist/src/lib/config/index.js +22 -0
- package/dist/src/lib/config/schemas/system.js +360 -0
- package/dist/src/lib/storage/analytics.js +86 -0
- package/dist/src/lib/storage/assets.js +401 -0
- package/dist/src/lib/storage/backends/elasticsearch_store.js +494 -0
- package/dist/src/lib/storage/backends/mappings/analytics.js +50 -0
- package/dist/src/lib/storage/backends/mappings/asset.js +41 -0
- package/dist/src/lib/storage/backends/mappings/ex.js +62 -0
- package/dist/src/lib/storage/backends/mappings/job.js +38 -0
- package/dist/src/lib/storage/backends/mappings/state.js +38 -0
- package/dist/src/lib/storage/backends/s3_store.js +237 -0
- package/dist/src/lib/storage/execution.js +300 -0
- package/dist/src/lib/storage/index.js +7 -0
- package/dist/src/lib/storage/jobs.js +81 -0
- package/dist/src/lib/storage/state.js +255 -0
- package/dist/src/lib/utils/api_utils.js +157 -0
- package/dist/src/lib/utils/asset_utils.js +94 -0
- package/dist/src/lib/utils/date_utils.js +52 -0
- package/dist/src/lib/utils/encoding_utils.js +27 -0
- package/dist/src/lib/utils/events.js +4 -0
- package/dist/src/lib/utils/file_utils.js +124 -0
- package/dist/src/lib/utils/id_utils.js +15 -0
- package/dist/src/lib/utils/port_utils.js +32 -0
- package/dist/src/lib/workers/assets/index.js +3 -0
- package/dist/src/lib/workers/assets/loader-executable.js +40 -0
- package/dist/src/lib/workers/assets/loader.js +73 -0
- package/dist/src/lib/workers/assets/spawn.js +55 -0
- package/dist/src/lib/workers/context/execution-context.js +12 -0
- package/dist/src/lib/workers/context/terafoundation-context.js +8 -0
- package/dist/src/lib/workers/execution-controller/execution-analytics.js +188 -0
- package/dist/src/lib/workers/execution-controller/index.js +1024 -0
- package/dist/src/lib/workers/execution-controller/recovery.js +151 -0
- package/dist/src/lib/workers/execution-controller/scheduler.js +390 -0
- package/dist/src/lib/workers/execution-controller/slice-analytics.js +96 -0
- package/dist/src/lib/workers/helpers/job.js +80 -0
- package/dist/src/lib/workers/helpers/op-analytics.js +22 -0
- package/dist/src/lib/workers/helpers/terafoundation.js +34 -0
- package/dist/src/lib/workers/helpers/worker-shutdown.js +169 -0
- package/dist/src/lib/workers/metrics/index.js +108 -0
- package/dist/src/lib/workers/worker/index.js +378 -0
- package/dist/src/lib/workers/worker/slice.js +122 -0
- package/dist/test/config/schemas/system_schema-spec.js +37 -0
- package/dist/test/lib/cluster/services/cluster/backends/kubernetes/k8s-spec.js +316 -0
- package/dist/test/lib/cluster/services/cluster/backends/kubernetes/k8sResource-spec.js +795 -0
- package/dist/test/lib/cluster/services/cluster/backends/kubernetes/k8sState-multicluster-spec.js +67 -0
- package/dist/test/lib/cluster/services/cluster/backends/kubernetes/k8sState-spec.js +84 -0
- package/dist/test/lib/cluster/services/cluster/backends/kubernetes/utils-spec.js +132 -0
- package/dist/test/lib/cluster/services/cluster/backends/kubernetes/v2/k8s-v2-spec.js +455 -0
- package/dist/test/lib/cluster/services/cluster/backends/kubernetes/v2/k8sResource-v2-spec.js +818 -0
- package/dist/test/lib/cluster/services/cluster/backends/kubernetes/v2/k8sState-multicluster-v2-spec.js +67 -0
- package/dist/test/lib/cluster/services/cluster/backends/kubernetes/v2/k8sState-v2-spec.js +84 -0
- package/dist/test/lib/cluster/services/cluster/backends/kubernetes/v2/utils-v2-spec.js +320 -0
- package/dist/test/lib/cluster/services/cluster/backends/state-utils-spec.js +37 -0
- package/dist/test/node_master-spec.js +188 -0
- package/dist/test/services/api-spec.js +80 -0
- package/dist/test/services/assets-spec.js +158 -0
- package/dist/test/services/messaging-spec.js +440 -0
- package/dist/test/storage/assets_storage-spec.js +95 -0
- package/dist/test/storage/s3_store-spec.js +138 -0
- package/dist/test/test.config.js +8 -0
- package/dist/test/test.setup.js +6 -0
- package/dist/test/utils/api_utils-spec.js +86 -0
- package/dist/test/utils/asset_utils-spec.js +141 -0
- package/dist/test/utils/elastic_utils-spec.js +25 -0
- package/dist/test/workers/execution-controller/execution-controller-spec.js +371 -0
- package/dist/test/workers/execution-controller/execution-special-test-cases-spec.js +520 -0
- package/dist/test/workers/execution-controller/execution-test-cases-spec.js +338 -0
- package/dist/test/workers/execution-controller/recovery-spec.js +160 -0
- package/dist/test/workers/execution-controller/scheduler-spec.js +249 -0
- package/dist/test/workers/execution-controller/slice-analytics-spec.js +121 -0
- package/dist/test/workers/fixtures/ops/example-op/processor.js +20 -0
- package/dist/test/workers/fixtures/ops/example-op/schema.js +19 -0
- package/dist/test/workers/fixtures/ops/example-reader/fetcher.js +20 -0
- package/dist/test/workers/fixtures/ops/example-reader/schema.js +41 -0
- package/dist/test/workers/fixtures/ops/example-reader/slicer.js +37 -0
- package/dist/test/workers/fixtures/ops/new-op/processor.js +29 -0
- package/dist/test/workers/fixtures/ops/new-op/schema.js +18 -0
- package/dist/test/workers/fixtures/ops/new-reader/fetcher.js +19 -0
- package/dist/test/workers/fixtures/ops/new-reader/schema.js +23 -0
- package/dist/test/workers/fixtures/ops/new-reader/slicer.js +13 -0
- package/dist/test/workers/helpers/configs.js +130 -0
- package/dist/test/workers/helpers/execution-controller-helper.js +49 -0
- package/dist/test/workers/helpers/index.js +5 -0
- package/dist/test/workers/helpers/test-context.js +210 -0
- package/dist/test/workers/helpers/zip-directory.js +25 -0
- package/dist/test/workers/worker/slice-spec.js +333 -0
- package/dist/test/workers/worker/worker-spec.js +356 -0
- package/package.json +94 -94
- package/service.js +0 -0
|
@@ -0,0 +1,818 @@
|
|
|
1
|
+
import yaml from 'js-yaml';
|
|
2
|
+
import { debugLogger } from '@terascope/utils';
|
|
3
|
+
import { K8sDeploymentResource } from '../../../../../../../../src/lib/cluster/services/cluster/backends/kubernetesV2/k8sDeploymentResource.js';
|
|
4
|
+
import { K8sJobResource } from '../../../../../../../../src/lib/cluster/services/cluster/backends/kubernetesV2/k8sJobResource.js';
|
|
5
|
+
import { K8sServiceResource } from '../../../../../../../../src/lib/cluster/services/cluster/backends/kubernetesV2/k8sServiceResource.js';
|
|
6
|
+
describe('k8sResource', () => {
|
|
7
|
+
const logger = debugLogger('k8sResource');
|
|
8
|
+
let execution;
|
|
9
|
+
let terasliceConfig;
|
|
10
|
+
beforeEach(() => {
|
|
11
|
+
terasliceConfig = {
|
|
12
|
+
shutdown_timeout: 60000,
|
|
13
|
+
assets_directory: '',
|
|
14
|
+
assets_volume: '',
|
|
15
|
+
name: 'ts-dev1',
|
|
16
|
+
env_vars: {
|
|
17
|
+
FOO: 'bar',
|
|
18
|
+
EXAMPLE: 'test'
|
|
19
|
+
},
|
|
20
|
+
kubernetes_image: 'teraslice:k8sdev',
|
|
21
|
+
kubernetes_namespace: 'ts-dev1',
|
|
22
|
+
kubernetes_image_pull_secret: ''
|
|
23
|
+
};
|
|
24
|
+
execution = {
|
|
25
|
+
name: 'example-data-generator-job',
|
|
26
|
+
workers: 2,
|
|
27
|
+
job_id: '7ba9afb0-417a-4936-adc5-b15e31d1edd1',
|
|
28
|
+
ex_id: 'e76a0278-d9bc-4d78-bf14-431bcd97528c',
|
|
29
|
+
env_vars: {
|
|
30
|
+
FOO: 'baz'
|
|
31
|
+
}
|
|
32
|
+
// slicer_port: 45680,
|
|
33
|
+
// slicer_hostname: 'teraslice-execution-controller-e76a0278-d9bc-4d78-bf14-431bcd97'
|
|
34
|
+
};
|
|
35
|
+
});
|
|
36
|
+
describe('worker deployment', () => {
|
|
37
|
+
it('has valid resource object.', () => {
|
|
38
|
+
const kr = new K8sDeploymentResource(terasliceConfig, execution, logger, 'example-job-abcd', 'UID1');
|
|
39
|
+
expect(kr.resource.kind).toBe('Deployment');
|
|
40
|
+
expect(kr.resource.spec.replicas).toBe(2);
|
|
41
|
+
expect(kr.resource.metadata.name).toBe('ts-wkr-example-data-generator-job-7ba9afb0-417a');
|
|
42
|
+
// The following properties should be absent in the default case
|
|
43
|
+
// Note: This tests that both affinity and podAntiAffinity are absent
|
|
44
|
+
expect(kr.resource.spec.template.spec).not.toHaveProperty('affinity');
|
|
45
|
+
expect(kr.resource.spec.template.spec).not.toHaveProperty('imagePullSecrets');
|
|
46
|
+
expect(kr.resource.spec.template.spec).not.toHaveProperty('priorityClassName');
|
|
47
|
+
// Configmaps should be mounted on all workers
|
|
48
|
+
expect(kr.resource.spec.template.spec.volumes[0]).toEqual(yaml.load(`
|
|
49
|
+
name: config
|
|
50
|
+
configMap:
|
|
51
|
+
name: ts-dev1-worker
|
|
52
|
+
items:
|
|
53
|
+
- key: teraslice.yaml
|
|
54
|
+
path: teraslice.yaml`));
|
|
55
|
+
expect(kr.resource.spec.template.spec.containers[0].volumeMounts[0])
|
|
56
|
+
.toEqual(yaml.load(`
|
|
57
|
+
mountPath: /app/config
|
|
58
|
+
name: config`));
|
|
59
|
+
});
|
|
60
|
+
it('has valid resource object when terasliceConfig has kubernetes_image_pull_secret.', () => {
|
|
61
|
+
terasliceConfig.kubernetes_image_pull_secret = 'teraslice-image-pull-secret';
|
|
62
|
+
const kr = new K8sDeploymentResource(terasliceConfig, execution, logger, 'example-job-abcd', 'UID1');
|
|
63
|
+
let firstSecret = undefined;
|
|
64
|
+
if (kr.resource.spec.template.spec.imagePullSecrets) {
|
|
65
|
+
firstSecret = kr.resource.spec.template.spec.imagePullSecrets[0];
|
|
66
|
+
}
|
|
67
|
+
expect(firstSecret).toEqual(yaml.load(`
|
|
68
|
+
name: teraslice-image-pull-secret`));
|
|
69
|
+
});
|
|
70
|
+
it('has podAntiAffinity when terasliceConfig has kubernetes_worker_antiaffinity true.', () => {
|
|
71
|
+
terasliceConfig.kubernetes_worker_antiaffinity = true;
|
|
72
|
+
const kr = new K8sDeploymentResource(terasliceConfig, execution, logger, 'example-job-abcd', 'UID1');
|
|
73
|
+
// console.log(yaml.dump(kr.resource.spec.template.spec.affinity));
|
|
74
|
+
expect(kr.resource.spec.template.spec.affinity).toEqual(yaml.load(`
|
|
75
|
+
podAntiAffinity:
|
|
76
|
+
preferredDuringSchedulingIgnoredDuringExecution:
|
|
77
|
+
- weight: 1
|
|
78
|
+
podAffinityTerm:
|
|
79
|
+
labelSelector:
|
|
80
|
+
matchExpressions:
|
|
81
|
+
- key: app.kubernetes.io/name
|
|
82
|
+
operator: In
|
|
83
|
+
values:
|
|
84
|
+
- teraslice
|
|
85
|
+
- key: app.kubernetes.io/instance
|
|
86
|
+
operator: In
|
|
87
|
+
values:
|
|
88
|
+
- ts-dev1
|
|
89
|
+
topologyKey: kubernetes.io/hostname`));
|
|
90
|
+
});
|
|
91
|
+
it('has valid resource object with volumes when terasliceConfig has assets_director and assets_volume.', () => {
|
|
92
|
+
terasliceConfig.assets_directory = '/assets';
|
|
93
|
+
terasliceConfig.assets_volume = 'asset-volume';
|
|
94
|
+
const kr = new K8sDeploymentResource(terasliceConfig, execution, logger, 'example-job-abcd', 'UID1');
|
|
95
|
+
expect(kr.resource.spec.replicas).toBe(2);
|
|
96
|
+
expect(kr.resource.metadata.name).toBe('ts-wkr-example-data-generator-job-7ba9afb0-417a');
|
|
97
|
+
// The following properties should be absent in the default case
|
|
98
|
+
expect(kr.resource.spec.template.spec).not.toHaveProperty('affinity');
|
|
99
|
+
expect(kr.resource.spec.template.spec).not.toHaveProperty('imagePullSecrets');
|
|
100
|
+
expect(kr.resource.spec.template.spec.volumes[0]).toEqual(yaml.load(`
|
|
101
|
+
name: config
|
|
102
|
+
configMap:
|
|
103
|
+
name: ts-dev1-worker
|
|
104
|
+
items:
|
|
105
|
+
- key: teraslice.yaml
|
|
106
|
+
path: teraslice.yaml`));
|
|
107
|
+
expect(kr.resource.spec.template.spec.containers[0].volumeMounts[0])
|
|
108
|
+
.toEqual(yaml.load(`
|
|
109
|
+
mountPath: /app/config
|
|
110
|
+
name: config`));
|
|
111
|
+
// Now check for the assets volume
|
|
112
|
+
expect(kr.resource.spec.template.spec.volumes[1]).toEqual(yaml.load(`
|
|
113
|
+
name: asset-volume
|
|
114
|
+
persistentVolumeClaim:
|
|
115
|
+
claimName: asset-volume`));
|
|
116
|
+
expect(kr.resource.spec.template.spec.containers[0].volumeMounts[1])
|
|
117
|
+
.toEqual(yaml.load(`
|
|
118
|
+
name: asset-volume
|
|
119
|
+
mountPath: /assets`));
|
|
120
|
+
});
|
|
121
|
+
it('has valid resource object with volumes when execution has a single job volume', () => {
|
|
122
|
+
execution.volumes = [
|
|
123
|
+
{ name: 'teraslice-data1', path: '/data' }
|
|
124
|
+
];
|
|
125
|
+
const kr = new K8sDeploymentResource(terasliceConfig, execution, logger, 'example-job-abcd', 'UID1');
|
|
126
|
+
// First check the configMap volumes, which should be present on all
|
|
127
|
+
// deployments
|
|
128
|
+
expect(kr.resource.spec.template.spec.volumes[0]).toEqual(yaml.load(`
|
|
129
|
+
name: config
|
|
130
|
+
configMap:
|
|
131
|
+
name: ts-dev1-worker
|
|
132
|
+
items:
|
|
133
|
+
- key: teraslice.yaml
|
|
134
|
+
path: teraslice.yaml`));
|
|
135
|
+
expect(kr.resource.spec.template.spec.containers[0].volumeMounts[0])
|
|
136
|
+
.toEqual(yaml.load(`
|
|
137
|
+
mountPath: /app/config
|
|
138
|
+
name: config`));
|
|
139
|
+
// Now check for the volume added via config
|
|
140
|
+
expect(kr.resource.spec.template.spec.volumes[1]).toEqual(yaml.load(`
|
|
141
|
+
name: teraslice-data1
|
|
142
|
+
persistentVolumeClaim:
|
|
143
|
+
claimName: teraslice-data1`));
|
|
144
|
+
expect(kr.resource.spec.template.spec.containers[0].volumeMounts[1])
|
|
145
|
+
.toEqual(yaml.load(`
|
|
146
|
+
name: teraslice-data1
|
|
147
|
+
mountPath: /data`));
|
|
148
|
+
});
|
|
149
|
+
it('has valid resource object with volumes when execution has two job volumes', () => {
|
|
150
|
+
execution.volumes = [
|
|
151
|
+
{ name: 'teraslice-data1', path: '/data' },
|
|
152
|
+
{ name: 'tmp', path: '/tmp' }
|
|
153
|
+
];
|
|
154
|
+
const kr = new K8sDeploymentResource(terasliceConfig, execution, logger, 'example-job-abcd', 'UID1');
|
|
155
|
+
// Now check for the volumes added via job
|
|
156
|
+
expect(kr.resource.spec.template.spec.volumes[1]).toEqual(yaml.load(`
|
|
157
|
+
name: teraslice-data1
|
|
158
|
+
persistentVolumeClaim:
|
|
159
|
+
claimName: teraslice-data1`));
|
|
160
|
+
expect(kr.resource.spec.template.spec.containers[0].volumeMounts[1])
|
|
161
|
+
.toEqual(yaml.load(`
|
|
162
|
+
name: teraslice-data1
|
|
163
|
+
mountPath: /data`));
|
|
164
|
+
expect(kr.resource.spec.template.spec.volumes[2]).toEqual(yaml.load(`
|
|
165
|
+
name: tmp
|
|
166
|
+
persistentVolumeClaim:
|
|
167
|
+
claimName: tmp`));
|
|
168
|
+
expect(kr.resource.spec.template.spec.containers[0].volumeMounts[2])
|
|
169
|
+
.toEqual(yaml.load(`
|
|
170
|
+
name: tmp
|
|
171
|
+
mountPath: /tmp`));
|
|
172
|
+
});
|
|
173
|
+
it('does not have memory/cpu limits/requests when not set in config or execution', () => {
|
|
174
|
+
const kr = new K8sDeploymentResource(terasliceConfig, execution, logger, 'example-job-abcd', 'UID1');
|
|
175
|
+
expect(kr.resource.metadata.labels['teraslice.terascope.io/exId'])
|
|
176
|
+
.toEqual('e76a0278-d9bc-4d78-bf14-431bcd97528c');
|
|
177
|
+
expect(kr.resource.spec.template.spec.containers[0].resources).not.toBeDefined();
|
|
178
|
+
expect(kr.resource.spec.template.spec.containers[0].env).not.toContain('NODE_OPTIONS');
|
|
179
|
+
});
|
|
180
|
+
it('has memory and cpu limits and requests when set on terasliceConfig', () => {
|
|
181
|
+
terasliceConfig.cpu = 1;
|
|
182
|
+
terasliceConfig.memory = 2147483648;
|
|
183
|
+
const kr = new K8sDeploymentResource(terasliceConfig, execution, logger, 'example-job-abcd', 'UID1');
|
|
184
|
+
expect(kr.resource.metadata.labels['teraslice.terascope.io/exId'])
|
|
185
|
+
.toEqual('e76a0278-d9bc-4d78-bf14-431bcd97528c');
|
|
186
|
+
expect(kr.resource.spec.template.spec.containers[0].resources).toEqual(yaml.load(`
|
|
187
|
+
requests:
|
|
188
|
+
memory: 2147483648
|
|
189
|
+
cpu: 1
|
|
190
|
+
limits:
|
|
191
|
+
memory: 2147483648
|
|
192
|
+
cpu: 1`));
|
|
193
|
+
const envArray = kr.resource.spec.template.spec.containers[0].env;
|
|
194
|
+
const nodeOptions = envArray.find((i) => i.name === 'NODE_OPTIONS');
|
|
195
|
+
expect(nodeOptions?.value).toEqual('--max-old-space-size=1843');
|
|
196
|
+
});
|
|
197
|
+
it('has the ability to set custom env', () => {
|
|
198
|
+
const kr = new K8sDeploymentResource(terasliceConfig, execution, logger, 'example-job-abcd', 'UID1');
|
|
199
|
+
// NOTE: the env var merge happens in _setResources(), which is
|
|
200
|
+
// somewhat out of place.
|
|
201
|
+
const envArray = kr.resource.spec.template.spec.containers[0].env;
|
|
202
|
+
const foo = envArray.find((i) => i.name === 'FOO');
|
|
203
|
+
const example = envArray.find((i) => i.name === 'EXAMPLE');
|
|
204
|
+
expect(foo?.value).toEqual('baz');
|
|
205
|
+
expect(example?.value).toEqual('test');
|
|
206
|
+
});
|
|
207
|
+
it('execution resources override terasliceConfig resources', () => {
|
|
208
|
+
execution.cpu = 2;
|
|
209
|
+
execution.memory = 1073741824;
|
|
210
|
+
terasliceConfig.cpu = 1;
|
|
211
|
+
terasliceConfig.memory = 2147483648;
|
|
212
|
+
const kr = new K8sDeploymentResource(terasliceConfig, execution, logger, 'example-job-abcd', 'UID1');
|
|
213
|
+
expect(kr.resource.metadata.labels['teraslice.terascope.io/exId'])
|
|
214
|
+
.toEqual('e76a0278-d9bc-4d78-bf14-431bcd97528c');
|
|
215
|
+
expect(kr.resource.spec.template.spec.containers[0].resources).toEqual(yaml.load(`
|
|
216
|
+
requests:
|
|
217
|
+
memory: 1073741824
|
|
218
|
+
cpu: 2
|
|
219
|
+
limits:
|
|
220
|
+
memory: 1073741824
|
|
221
|
+
cpu: 2`));
|
|
222
|
+
const envArray = kr.resource.spec.template.spec.containers[0].env;
|
|
223
|
+
const nodeOptions = envArray.find((i) => i.name === 'NODE_OPTIONS');
|
|
224
|
+
expect(nodeOptions?.value).toEqual('--max-old-space-size=922');
|
|
225
|
+
});
|
|
226
|
+
it('execution cpu overrides terasliceConfig cpu while terasliceConfig memory gets applied', () => {
|
|
227
|
+
execution.cpu = 2;
|
|
228
|
+
terasliceConfig.cpu = 1;
|
|
229
|
+
terasliceConfig.memory = 2147483648;
|
|
230
|
+
const kr = new K8sDeploymentResource(terasliceConfig, execution, logger, 'example-job-abcd', 'UID1');
|
|
231
|
+
expect(kr.resource.metadata.labels['teraslice.terascope.io/exId'])
|
|
232
|
+
.toEqual('e76a0278-d9bc-4d78-bf14-431bcd97528c');
|
|
233
|
+
expect(kr.resource.spec.template.spec.containers[0].resources).toEqual(yaml.load(`
|
|
234
|
+
requests:
|
|
235
|
+
memory: 2147483648
|
|
236
|
+
cpu: 2
|
|
237
|
+
limits:
|
|
238
|
+
memory: 2147483648
|
|
239
|
+
cpu: 2`));
|
|
240
|
+
const envArray = kr.resource.spec.template.spec.containers[0].env;
|
|
241
|
+
const nodeOptions = envArray.find((i) => i.name === 'NODE_OPTIONS');
|
|
242
|
+
expect(nodeOptions?.value).toEqual('--max-old-space-size=1843');
|
|
243
|
+
});
|
|
244
|
+
it('has memory and cpu limits and requests when set on execution', () => {
|
|
245
|
+
execution.cpu = 1;
|
|
246
|
+
execution.memory = 2147483648;
|
|
247
|
+
const kr = new K8sDeploymentResource(terasliceConfig, execution, logger, 'example-job-abcd', 'UID1');
|
|
248
|
+
expect(kr.resource.metadata.labels['teraslice.terascope.io/exId'])
|
|
249
|
+
.toEqual('e76a0278-d9bc-4d78-bf14-431bcd97528c');
|
|
250
|
+
expect(kr.resource.spec.template.spec.containers[0].resources).toEqual(yaml.load(`
|
|
251
|
+
requests:
|
|
252
|
+
memory: 2147483648
|
|
253
|
+
cpu: 1
|
|
254
|
+
limits:
|
|
255
|
+
memory: 2147483648
|
|
256
|
+
cpu: 1`));
|
|
257
|
+
const envArray = kr.resource.spec.template.spec.containers[0].env;
|
|
258
|
+
const nodeOptions = envArray.find((i) => i.name === 'NODE_OPTIONS');
|
|
259
|
+
expect(nodeOptions?.value).toEqual('--max-old-space-size=1843');
|
|
260
|
+
});
|
|
261
|
+
it('has separate memory and cpu limits and requests when set on execution', () => {
|
|
262
|
+
execution.resources_requests_cpu = 1;
|
|
263
|
+
execution.resources_limits_cpu = 2;
|
|
264
|
+
execution.resources_requests_memory = 2147483648;
|
|
265
|
+
execution.resources_limits_memory = 3147483648;
|
|
266
|
+
const kr = new K8sDeploymentResource(terasliceConfig, execution, logger, 'example-job-abcd', 'UID1');
|
|
267
|
+
expect(kr.resource.metadata.labels['teraslice.terascope.io/exId'])
|
|
268
|
+
.toEqual('e76a0278-d9bc-4d78-bf14-431bcd97528c');
|
|
269
|
+
expect(kr.resource.spec.template.spec.containers[0].resources).toEqual(yaml.load(`
|
|
270
|
+
requests:
|
|
271
|
+
memory: 2147483648
|
|
272
|
+
cpu: 1
|
|
273
|
+
limits:
|
|
274
|
+
memory: 3147483648
|
|
275
|
+
cpu: 2`));
|
|
276
|
+
const envArray = kr.resource.spec.template.spec.containers[0].env;
|
|
277
|
+
const nodeOptions = envArray.find((i) => i.name === 'NODE_OPTIONS');
|
|
278
|
+
expect(nodeOptions?.value).toEqual('--max-old-space-size=2702');
|
|
279
|
+
});
|
|
280
|
+
it('has memory limits and requests when set on execution', () => {
|
|
281
|
+
execution.memory = 2147483648;
|
|
282
|
+
const kr = new K8sDeploymentResource(terasliceConfig, execution, logger, 'example-job-abcd', 'UID1');
|
|
283
|
+
expect(kr.resource.spec.template.spec.containers[0].resources).toEqual(yaml.load(`
|
|
284
|
+
requests:
|
|
285
|
+
memory: 2147483648
|
|
286
|
+
limits:
|
|
287
|
+
memory: 2147483648`));
|
|
288
|
+
const envArray = kr.resource.spec.template.spec.containers[0].env;
|
|
289
|
+
const nodeOptions = envArray.find((i) => i.name === 'NODE_OPTIONS');
|
|
290
|
+
expect(nodeOptions?.value).toEqual('--max-old-space-size=1843');
|
|
291
|
+
});
|
|
292
|
+
it('has cpu limits and requests when set on execution', () => {
|
|
293
|
+
execution.cpu = 1;
|
|
294
|
+
const kr = new K8sDeploymentResource(terasliceConfig, execution, logger, 'example-job-abcd', 'UID1');
|
|
295
|
+
expect(kr.resource.spec.template.spec.containers[0].resources).toEqual(yaml.load(`
|
|
296
|
+
requests:
|
|
297
|
+
cpu: 1
|
|
298
|
+
limits:
|
|
299
|
+
cpu: 1`));
|
|
300
|
+
});
|
|
301
|
+
it('has scratch volume when ephemeral_storage is set true on execution', () => {
|
|
302
|
+
execution.ephemeral_storage = true;
|
|
303
|
+
const kr = new K8sDeploymentResource(terasliceConfig, execution, logger, 'example-job-abcd', 'UID1');
|
|
304
|
+
expect(kr.resource.spec.template.spec.containers[0].volumeMounts)
|
|
305
|
+
.toEqual([
|
|
306
|
+
{ mountPath: '/app/config', name: 'config' },
|
|
307
|
+
{ name: 'ephemeral-volume', mountPath: '/ephemeral0' }
|
|
308
|
+
]);
|
|
309
|
+
});
|
|
310
|
+
it('does not have scratch volume when ephemeral_storage is set false on execution', () => {
|
|
311
|
+
execution.ephemeral_storage = false;
|
|
312
|
+
const kr = new K8sDeploymentResource(terasliceConfig, execution, logger, 'example-job-abcd', 'UID1');
|
|
313
|
+
expect(kr.resource.spec.template.spec.containers[0].volumeMounts)
|
|
314
|
+
.toEqual([{ mountPath: '/app/config', name: 'config' }]);
|
|
315
|
+
});
|
|
316
|
+
});
|
|
317
|
+
describe('worker deployments with targets', () => {
|
|
318
|
+
it('does not have affinity or toleration properties when targets equals [].', () => {
|
|
319
|
+
execution.targets = [];
|
|
320
|
+
const kr = new K8sDeploymentResource(terasliceConfig, execution, logger, 'example-job-abcd', 'UID1');
|
|
321
|
+
expect(kr.resource.spec.template.spec).not.toHaveProperty('affinity');
|
|
322
|
+
expect(kr.resource.spec.template.spec).not.toHaveProperty('toleration');
|
|
323
|
+
});
|
|
324
|
+
it('has valid resource object with affinity when execution has one target without constraint', () => {
|
|
325
|
+
execution.targets = [
|
|
326
|
+
{ key: 'zone', value: 'west' }
|
|
327
|
+
];
|
|
328
|
+
const kr = new K8sDeploymentResource(terasliceConfig, execution, logger, 'example-job-abcd', 'UID1');
|
|
329
|
+
expect(kr.resource.spec.template.spec.affinity).toEqual(yaml.load(`
|
|
330
|
+
nodeAffinity:
|
|
331
|
+
requiredDuringSchedulingIgnoredDuringExecution:
|
|
332
|
+
nodeSelectorTerms:
|
|
333
|
+
- matchExpressions:
|
|
334
|
+
- key: zone
|
|
335
|
+
operator: In
|
|
336
|
+
values:
|
|
337
|
+
- west`));
|
|
338
|
+
});
|
|
339
|
+
it('has valid resource object with correct affinities when execution has one target and kubernetes_worker_antiaffinity is set', () => {
|
|
340
|
+
execution.targets = [
|
|
341
|
+
{ key: 'zone', value: 'west' }
|
|
342
|
+
];
|
|
343
|
+
terasliceConfig.kubernetes_worker_antiaffinity = true;
|
|
344
|
+
const kr = new K8sDeploymentResource(terasliceConfig, execution, logger, 'example-job-abcd', 'UID1');
|
|
345
|
+
expect(kr.resource.spec.template.spec.affinity).toEqual(yaml.load(`
|
|
346
|
+
nodeAffinity:
|
|
347
|
+
requiredDuringSchedulingIgnoredDuringExecution:
|
|
348
|
+
nodeSelectorTerms:
|
|
349
|
+
- matchExpressions:
|
|
350
|
+
- key: zone
|
|
351
|
+
operator: In
|
|
352
|
+
values:
|
|
353
|
+
- west
|
|
354
|
+
podAntiAffinity:
|
|
355
|
+
preferredDuringSchedulingIgnoredDuringExecution:
|
|
356
|
+
- weight: 1
|
|
357
|
+
podAffinityTerm:
|
|
358
|
+
labelSelector:
|
|
359
|
+
matchExpressions:
|
|
360
|
+
- key: app.kubernetes.io/name
|
|
361
|
+
operator: In
|
|
362
|
+
values:
|
|
363
|
+
- teraslice
|
|
364
|
+
- key: app.kubernetes.io/instance
|
|
365
|
+
operator: In
|
|
366
|
+
values:
|
|
367
|
+
- ts-dev1
|
|
368
|
+
topologyKey: kubernetes.io/hostname`));
|
|
369
|
+
});
|
|
370
|
+
it('has valid resource object with affinity when execution has one required target', () => {
|
|
371
|
+
execution.targets = [
|
|
372
|
+
{ key: 'zone', value: 'west', constraint: 'required' }
|
|
373
|
+
];
|
|
374
|
+
const kr = new K8sDeploymentResource(terasliceConfig, execution, logger, 'example-job-abcd', 'UID1');
|
|
375
|
+
expect(kr.resource.spec.template.spec.affinity).toEqual(yaml.load(`
|
|
376
|
+
nodeAffinity:
|
|
377
|
+
requiredDuringSchedulingIgnoredDuringExecution:
|
|
378
|
+
nodeSelectorTerms:
|
|
379
|
+
- matchExpressions:
|
|
380
|
+
- key: zone
|
|
381
|
+
operator: In
|
|
382
|
+
values:
|
|
383
|
+
- west`));
|
|
384
|
+
});
|
|
385
|
+
it('has valid resource object with affinity when execution has two required targets', () => {
|
|
386
|
+
execution.targets = [
|
|
387
|
+
{ key: 'zone', value: 'west', constraint: 'required' },
|
|
388
|
+
{ key: 'region', value: '42', constraint: 'required' }
|
|
389
|
+
];
|
|
390
|
+
const kr = new K8sDeploymentResource(terasliceConfig, execution, logger, 'example-job-abcd', 'UID1');
|
|
391
|
+
expect(kr.resource.spec.template.spec.affinity).toEqual(yaml.load(`
|
|
392
|
+
nodeAffinity:
|
|
393
|
+
requiredDuringSchedulingIgnoredDuringExecution:
|
|
394
|
+
nodeSelectorTerms:
|
|
395
|
+
- matchExpressions:
|
|
396
|
+
- key: zone
|
|
397
|
+
operator: In
|
|
398
|
+
values:
|
|
399
|
+
- west
|
|
400
|
+
- key: region
|
|
401
|
+
operator: In
|
|
402
|
+
values:
|
|
403
|
+
- "42"`));
|
|
404
|
+
});
|
|
405
|
+
it('has valid resource object with affinity when execution has one preferred target', () => {
|
|
406
|
+
execution.targets = [
|
|
407
|
+
{ key: 'zone', value: 'west', constraint: 'preferred' }
|
|
408
|
+
];
|
|
409
|
+
const kr = new K8sDeploymentResource(terasliceConfig, execution, logger, 'example-job-abcd', 'UID1');
|
|
410
|
+
expect(kr.resource.spec.template.spec.affinity).toEqual(yaml.load(`
|
|
411
|
+
nodeAffinity:
|
|
412
|
+
preferredDuringSchedulingIgnoredDuringExecution:
|
|
413
|
+
- weight: 1
|
|
414
|
+
preference:
|
|
415
|
+
matchExpressions:
|
|
416
|
+
- key: zone
|
|
417
|
+
operator: In
|
|
418
|
+
values:
|
|
419
|
+
- west`));
|
|
420
|
+
});
|
|
421
|
+
it('has valid resource object with affinity when execution has two preferred targets', () => {
|
|
422
|
+
execution.targets = [
|
|
423
|
+
{ key: 'zone', value: 'west', constraint: 'preferred' },
|
|
424
|
+
{ key: 'region', value: 'texas', constraint: 'preferred' }
|
|
425
|
+
];
|
|
426
|
+
const kr = new K8sDeploymentResource(terasliceConfig, execution, logger, 'example-job-abcd', 'UID1');
|
|
427
|
+
expect(kr.resource.spec.template.spec.affinity).toEqual(yaml.load(`
|
|
428
|
+
nodeAffinity:
|
|
429
|
+
preferredDuringSchedulingIgnoredDuringExecution:
|
|
430
|
+
- weight: 1
|
|
431
|
+
preference:
|
|
432
|
+
matchExpressions:
|
|
433
|
+
- key: zone
|
|
434
|
+
operator: In
|
|
435
|
+
values:
|
|
436
|
+
- west
|
|
437
|
+
- weight: 1
|
|
438
|
+
preference:
|
|
439
|
+
matchExpressions:
|
|
440
|
+
- key: region
|
|
441
|
+
operator: In
|
|
442
|
+
values:
|
|
443
|
+
- texas`));
|
|
444
|
+
});
|
|
445
|
+
it('has valid resource object with tolerance when execution has one accepted target', () => {
|
|
446
|
+
execution.targets = [
|
|
447
|
+
{ key: 'zone', value: 'west', constraint: 'accepted' }
|
|
448
|
+
];
|
|
449
|
+
const kr = new K8sDeploymentResource(terasliceConfig, execution, logger, 'example-job-abcd', 'UID1');
|
|
450
|
+
// console.log(yaml.dump(kr.resource.spec.template.spec.tolerations));
|
|
451
|
+
expect(kr.resource.spec.template.spec.tolerations).toEqual(yaml.load(`
|
|
452
|
+
- key: zone
|
|
453
|
+
operator: Equal
|
|
454
|
+
value: west
|
|
455
|
+
effect: NoSchedule`));
|
|
456
|
+
});
|
|
457
|
+
it('has valid resource object with tolerance when execution has two accepted targets', () => {
|
|
458
|
+
execution.targets = [
|
|
459
|
+
{ key: 'zone', value: 'west', constraint: 'accepted' },
|
|
460
|
+
{ key: 'region', value: 'texas', constraint: 'accepted' }
|
|
461
|
+
];
|
|
462
|
+
const kr = new K8sDeploymentResource(terasliceConfig, execution, logger, 'example-job-abcd', 'UID1');
|
|
463
|
+
// console.log(yaml.dump(kr.resource.spec.template.spec.tolerations));
|
|
464
|
+
expect(kr.resource.spec.template.spec.tolerations).toEqual(yaml.load(`
|
|
465
|
+
- key: zone
|
|
466
|
+
operator: Equal
|
|
467
|
+
value: west
|
|
468
|
+
effect: NoSchedule
|
|
469
|
+
- key: region
|
|
470
|
+
operator: Equal
|
|
471
|
+
value: texas
|
|
472
|
+
effect: NoSchedule`));
|
|
473
|
+
});
|
|
474
|
+
it('has valid resource object with required and preferred affinity when execution has both', () => {
|
|
475
|
+
execution.targets = [
|
|
476
|
+
{ key: 'zone', value: 'west', constraint: 'required' },
|
|
477
|
+
{ key: 'region', value: 'texas', constraint: 'preferred' }
|
|
478
|
+
];
|
|
479
|
+
const kr = new K8sDeploymentResource(terasliceConfig, execution, logger, 'example-job-abcd', 'UID1');
|
|
480
|
+
// console.log(yaml.dump(kr.resource.spec.template.spec.tolerations));
|
|
481
|
+
expect(kr.resource.spec.template.spec.affinity).toEqual(yaml.load(`
|
|
482
|
+
nodeAffinity:
|
|
483
|
+
requiredDuringSchedulingIgnoredDuringExecution:
|
|
484
|
+
nodeSelectorTerms:
|
|
485
|
+
- matchExpressions:
|
|
486
|
+
- key: zone
|
|
487
|
+
operator: In
|
|
488
|
+
values:
|
|
489
|
+
- west
|
|
490
|
+
preferredDuringSchedulingIgnoredDuringExecution:
|
|
491
|
+
- weight: 1
|
|
492
|
+
preference:
|
|
493
|
+
matchExpressions:
|
|
494
|
+
- key: region
|
|
495
|
+
operator: In
|
|
496
|
+
values:
|
|
497
|
+
- texas`));
|
|
498
|
+
});
|
|
499
|
+
it('has valid resource object with affinity and tolerations when execution has two of each', () => {
|
|
500
|
+
execution.targets = [
|
|
501
|
+
{ key: 'zone', value: 'west', constraint: 'required' },
|
|
502
|
+
{ key: 'region', value: '42', constraint: 'required' },
|
|
503
|
+
{ key: 'zone', value: 'west', constraint: 'preferred' },
|
|
504
|
+
{ key: 'region', value: 'texas', constraint: 'preferred' },
|
|
505
|
+
{ key: 'zone', value: 'west', constraint: 'accepted' },
|
|
506
|
+
{ key: 'region', value: 'texas', constraint: 'accepted' }
|
|
507
|
+
];
|
|
508
|
+
const kr = new K8sDeploymentResource(terasliceConfig, execution, logger, 'example-job-abcd', 'UID1');
|
|
509
|
+
expect(kr.resource.spec.template.spec.affinity).toEqual(yaml.load(`
|
|
510
|
+
nodeAffinity:
|
|
511
|
+
requiredDuringSchedulingIgnoredDuringExecution:
|
|
512
|
+
nodeSelectorTerms:
|
|
513
|
+
- matchExpressions:
|
|
514
|
+
- key: zone
|
|
515
|
+
operator: In
|
|
516
|
+
values:
|
|
517
|
+
- west
|
|
518
|
+
- key: region
|
|
519
|
+
operator: In
|
|
520
|
+
values:
|
|
521
|
+
- "42"
|
|
522
|
+
preferredDuringSchedulingIgnoredDuringExecution:
|
|
523
|
+
- weight: 1
|
|
524
|
+
preference:
|
|
525
|
+
matchExpressions:
|
|
526
|
+
- key: zone
|
|
527
|
+
operator: In
|
|
528
|
+
values:
|
|
529
|
+
- west
|
|
530
|
+
- weight: 1
|
|
531
|
+
preference:
|
|
532
|
+
matchExpressions:
|
|
533
|
+
- key: region
|
|
534
|
+
operator: In
|
|
535
|
+
values:
|
|
536
|
+
- texas`));
|
|
537
|
+
expect(kr.resource.spec.template.spec.tolerations).toEqual(yaml.load(`
|
|
538
|
+
- key: zone
|
|
539
|
+
operator: Equal
|
|
540
|
+
value: west
|
|
541
|
+
effect: NoSchedule
|
|
542
|
+
- key: region
|
|
543
|
+
operator: Equal
|
|
544
|
+
value: texas
|
|
545
|
+
effect: NoSchedule`));
|
|
546
|
+
});
|
|
547
|
+
});
|
|
548
|
+
describe('worker deployments with job labels', () => {
|
|
549
|
+
it('generates k8s resources with labels', () => {
|
|
550
|
+
execution.labels = {
|
|
551
|
+
key1: 'value1',
|
|
552
|
+
key2: 'value2'
|
|
553
|
+
};
|
|
554
|
+
const kr = new K8sDeploymentResource(terasliceConfig, execution, logger, 'example-job-abcd', 'UID1');
|
|
555
|
+
// console.log(yaml.dump(kr.resource));
|
|
556
|
+
expect(kr.resource.metadata.labels['job.teraslice.terascope.io/key1']).toEqual('value1');
|
|
557
|
+
expect(kr.resource.metadata.labels['job.teraslice.terascope.io/key2']).toEqual('value2');
|
|
558
|
+
});
|
|
559
|
+
it('generates valid k8s resources with keys containing forbidden characters', () => {
|
|
560
|
+
execution.labels = {
|
|
561
|
+
'key 1': 'value1',
|
|
562
|
+
'key2%': 'value2',
|
|
563
|
+
abcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghij1234: 'value3',
|
|
564
|
+
};
|
|
565
|
+
const kr = new K8sDeploymentResource(terasliceConfig, execution, logger, 'example-job-abcd', 'UID1');
|
|
566
|
+
// console.log(yaml.dump(kr.resource));
|
|
567
|
+
expect(kr.resource.metadata.labels['job.teraslice.terascope.io/key-1']).toEqual('value1');
|
|
568
|
+
expect(kr.resource.metadata.labels['job.teraslice.terascope.io/key2-']).toEqual('value2');
|
|
569
|
+
expect(kr.resource.metadata.labels['job.teraslice.terascope.io/abcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghij123'])
|
|
570
|
+
.toEqual('value3');
|
|
571
|
+
});
|
|
572
|
+
});
|
|
573
|
+
describe('teraslice job with one valid external_ports set', () => {
|
|
574
|
+
it('generates k8s worker deployment with containerPort on container', () => {
|
|
575
|
+
execution.external_ports = [9090];
|
|
576
|
+
const kr = new K8sDeploymentResource(terasliceConfig, execution, logger, 'example-job-abcd', 'UID1');
|
|
577
|
+
// console.log(yaml.dump(kr.resource.spec.template.spec.containers[0].ports));
|
|
578
|
+
expect(kr.resource.spec.template.spec.containers[0].ports)
|
|
579
|
+
.toEqual([
|
|
580
|
+
{ containerPort: 45680 },
|
|
581
|
+
{ containerPort: 9090 }
|
|
582
|
+
]);
|
|
583
|
+
});
|
|
584
|
+
it('generates k8s execution controller job with containerPort on container', () => {
|
|
585
|
+
execution.external_ports = [9090];
|
|
586
|
+
const kr = new K8sJobResource(terasliceConfig, execution, logger);
|
|
587
|
+
// console.log(yaml.dump(kr.resource.spec.template.spec.containers[0].ports));
|
|
588
|
+
expect(kr.resource.spec.template.spec.containers[0].ports)
|
|
589
|
+
.toEqual([
|
|
590
|
+
{ containerPort: 45680 },
|
|
591
|
+
{ containerPort: 9090 }
|
|
592
|
+
]);
|
|
593
|
+
});
|
|
594
|
+
});
|
|
595
|
+
describe('teraslice job with two valid external_ports set', () => {
|
|
596
|
+
it('generates k8s worker deployment with containerPort on container', () => {
|
|
597
|
+
execution.external_ports = [
|
|
598
|
+
9090,
|
|
599
|
+
{ name: 'metrics', port: 9091 }
|
|
600
|
+
];
|
|
601
|
+
const kr = new K8sDeploymentResource(terasliceConfig, execution, logger, 'example-job-abcd', 'UID1');
|
|
602
|
+
// console.log(yaml.dump(kr.resource.spec.template.spec.containers[0].ports));
|
|
603
|
+
expect(kr.resource.spec.template.spec.containers[0].ports)
|
|
604
|
+
.toEqual([
|
|
605
|
+
{ containerPort: 45680 },
|
|
606
|
+
{ containerPort: 9090 },
|
|
607
|
+
{ name: 'metrics', containerPort: 9091 }
|
|
608
|
+
]);
|
|
609
|
+
});
|
|
610
|
+
it('generates k8s execution controller job with containerPort on container', () => {
|
|
611
|
+
execution.external_ports = [9090, 9091];
|
|
612
|
+
const kr = new K8sJobResource(terasliceConfig, execution, logger);
|
|
613
|
+
// console.log(yaml.dump(kr.resource.spec.template.spec.containers[0].ports));
|
|
614
|
+
expect(kr.resource.spec.template.spec.containers[0].ports)
|
|
615
|
+
.toEqual([
|
|
616
|
+
{ containerPort: 45680 },
|
|
617
|
+
{ containerPort: 9090 },
|
|
618
|
+
{ containerPort: 9091 }
|
|
619
|
+
]);
|
|
620
|
+
});
|
|
621
|
+
});
|
|
622
|
+
describe('execution_controller job', () => {
|
|
623
|
+
it('has valid resource object.', () => {
|
|
624
|
+
const kr = new K8sJobResource(terasliceConfig, execution, logger);
|
|
625
|
+
expect(kr.resource.kind).toBe('Job');
|
|
626
|
+
expect(kr.resource.metadata.name).toBe('ts-exc-example-data-generator-job-7ba9afb0-417a');
|
|
627
|
+
// The following properties should be absent in the default case
|
|
628
|
+
expect(kr.resource.spec.template.spec).not.toHaveProperty('affinity');
|
|
629
|
+
expect(kr.resource.spec.template.spec).not.toHaveProperty('imagePullSecrets');
|
|
630
|
+
expect(kr.resource.spec.template.spec).not.toHaveProperty('priorityClassName');
|
|
631
|
+
// Configmaps should be mounted on all workers
|
|
632
|
+
expect(kr.resource.spec.template.spec.volumes[0]).toEqual(yaml.load(`
|
|
633
|
+
name: config
|
|
634
|
+
configMap:
|
|
635
|
+
name: ts-dev1-worker
|
|
636
|
+
items:
|
|
637
|
+
- key: teraslice.yaml
|
|
638
|
+
path: teraslice.yaml`));
|
|
639
|
+
expect(kr.resource.spec.template.spec.containers[0].volumeMounts[0])
|
|
640
|
+
.toEqual(yaml.load(`
|
|
641
|
+
mountPath: /app/config
|
|
642
|
+
name: config`));
|
|
643
|
+
});
|
|
644
|
+
it('has memory and cpu limits and requests when set on terasliceConfig', () => {
|
|
645
|
+
terasliceConfig.cpu_execution_controller = 1;
|
|
646
|
+
terasliceConfig.memory_execution_controller = 2147483648;
|
|
647
|
+
const kr = new K8sJobResource(terasliceConfig, execution, logger);
|
|
648
|
+
expect(kr.resource.spec.template.spec.containers[0].resources).toEqual(yaml.load(`
|
|
649
|
+
requests:
|
|
650
|
+
memory: 2147483648
|
|
651
|
+
cpu: 1
|
|
652
|
+
limits:
|
|
653
|
+
memory: 2147483648
|
|
654
|
+
cpu: 1`));
|
|
655
|
+
const envArray = kr.resource.spec.template.spec.containers[0].env;
|
|
656
|
+
const nodeOptions = envArray.find((i) => i.name === 'NODE_OPTIONS');
|
|
657
|
+
expect(nodeOptions?.value).toEqual('--max-old-space-size=1843');
|
|
658
|
+
});
|
|
659
|
+
it('execution resources override terasliceConfig resources', () => {
|
|
660
|
+
execution.cpu_execution_controller = 2;
|
|
661
|
+
execution.memory_execution_controller = 1073741824;
|
|
662
|
+
terasliceConfig.cpu_execution_controller = 1;
|
|
663
|
+
terasliceConfig.memory_execution_controller = 2147483648;
|
|
664
|
+
const kr = new K8sJobResource(terasliceConfig, execution, logger);
|
|
665
|
+
expect(kr.resource.spec.template.spec.containers[0].resources).toEqual(yaml.load(`
|
|
666
|
+
requests:
|
|
667
|
+
memory: 1073741824
|
|
668
|
+
cpu: 2
|
|
669
|
+
limits:
|
|
670
|
+
memory: 1073741824
|
|
671
|
+
cpu: 2`));
|
|
672
|
+
const envArray = kr.resource.spec.template.spec.containers[0].env;
|
|
673
|
+
const nodeOptions = envArray.find((i) => i.name === 'NODE_OPTIONS');
|
|
674
|
+
expect(nodeOptions?.value).toEqual('--max-old-space-size=922');
|
|
675
|
+
});
|
|
676
|
+
});
|
|
677
|
+
describe('worker deployment with different combinations of job names', () => {
|
|
678
|
+
test.each([
|
|
679
|
+
['aa', 'ts-wkr-aa-7ba9afb0-417a'],
|
|
680
|
+
['00', 'ts-wkr-a0-7ba9afb0-417a'],
|
|
681
|
+
['a', 'ts-wkr-a-7ba9afb0-417a'],
|
|
682
|
+
['0', 'ts-wkr-a-7ba9afb0-417a'],
|
|
683
|
+
['-job-', 'ts-wkr-ajob0-7ba9afb0-417a'],
|
|
684
|
+
['-JOB-', 'ts-wkr-ajob0-7ba9afb0-417a'],
|
|
685
|
+
['teraslice-JOB-name', 'ts-wkr-teraslice-job-name-7ba9afb0-417a']
|
|
686
|
+
])('when Job Name is %s the k8s worker name is: %s', (jobName, k8sName) => {
|
|
687
|
+
execution.name = jobName;
|
|
688
|
+
const kr = new K8sDeploymentResource(terasliceConfig, execution, logger, 'example-job-abcd', 'UID1');
|
|
689
|
+
expect(kr.resource.metadata.name).toBe(k8sName);
|
|
690
|
+
});
|
|
691
|
+
});
|
|
692
|
+
describe('teraslice config with execution_controller_targets set', () => {
|
|
693
|
+
it('generates execution controller job with toleration and affinity', () => {
|
|
694
|
+
terasliceConfig.execution_controller_targets = [
|
|
695
|
+
{ key: 'key1', value: 'value1' },
|
|
696
|
+
{ key: 'key2', value: 'value2' }
|
|
697
|
+
];
|
|
698
|
+
const kr = new K8sJobResource(terasliceConfig, execution, logger);
|
|
699
|
+
expect(kr.resource.kind).toBe('Job');
|
|
700
|
+
expect(kr.resource.metadata.name).toBe('ts-exc-example-data-generator-job-7ba9afb0-417a');
|
|
701
|
+
expect(kr.resource.spec.template.spec).toHaveProperty('affinity');
|
|
702
|
+
expect(kr.resource.spec.template.spec).toHaveProperty('tolerations');
|
|
703
|
+
expect(kr.resource.spec.template.spec.affinity).toEqual(yaml.load(`
|
|
704
|
+
nodeAffinity:
|
|
705
|
+
requiredDuringSchedulingIgnoredDuringExecution:
|
|
706
|
+
nodeSelectorTerms:
|
|
707
|
+
- matchExpressions:
|
|
708
|
+
- key: key1
|
|
709
|
+
operator: In
|
|
710
|
+
values:
|
|
711
|
+
- value1
|
|
712
|
+
- key: key2
|
|
713
|
+
operator: In
|
|
714
|
+
values:
|
|
715
|
+
- value2`));
|
|
716
|
+
expect(kr.resource.spec.template.spec.tolerations).toEqual(yaml.load(`
|
|
717
|
+
- key: key1
|
|
718
|
+
operator: Equal
|
|
719
|
+
value: value1
|
|
720
|
+
effect: NoSchedule
|
|
721
|
+
- key: key2
|
|
722
|
+
operator: Equal
|
|
723
|
+
value: value2
|
|
724
|
+
effect: NoSchedule`));
|
|
725
|
+
});
|
|
726
|
+
});
|
|
727
|
+
describe('teraslice config with execution_controller_targets and job targets set', () => {
|
|
728
|
+
it('generates execution controller job with toleration and affinity and targets', () => {
|
|
729
|
+
terasliceConfig.execution_controller_targets = [
|
|
730
|
+
{ key: 'key1', value: 'value1' },
|
|
731
|
+
];
|
|
732
|
+
execution.targets = [
|
|
733
|
+
{ key: 'zone', value: 'west' },
|
|
734
|
+
{ key: 'region', value: 'texas', constraint: 'accepted' }
|
|
735
|
+
];
|
|
736
|
+
const kr = new K8sJobResource(terasliceConfig, execution, logger);
|
|
737
|
+
expect(kr.resource.kind).toBe('Job');
|
|
738
|
+
expect(kr.resource.metadata.name).toBe('ts-exc-example-data-generator-job-7ba9afb0-417a');
|
|
739
|
+
expect(kr.resource.spec.template.spec).toHaveProperty('affinity');
|
|
740
|
+
expect(kr.resource.spec.template.spec).toHaveProperty('tolerations');
|
|
741
|
+
// console.log(yaml.dump(kr.resource.spec.template.spec.affinity));
|
|
742
|
+
expect(kr.resource.spec.template.spec.affinity).toEqual(yaml.load(`
|
|
743
|
+
nodeAffinity:
|
|
744
|
+
requiredDuringSchedulingIgnoredDuringExecution:
|
|
745
|
+
nodeSelectorTerms:
|
|
746
|
+
- matchExpressions:
|
|
747
|
+
- key: zone
|
|
748
|
+
operator: In
|
|
749
|
+
values:
|
|
750
|
+
- west
|
|
751
|
+
- key: key1
|
|
752
|
+
operator: In
|
|
753
|
+
values:
|
|
754
|
+
- value1`));
|
|
755
|
+
// console.log(yaml.dump(kr.resource.spec.template.spec.tolerations));
|
|
756
|
+
expect(kr.resource.spec.template.spec.tolerations).toEqual(yaml.load(`
|
|
757
|
+
- key: region
|
|
758
|
+
operator: Equal
|
|
759
|
+
value: texas
|
|
760
|
+
effect: NoSchedule
|
|
761
|
+
- key: key1
|
|
762
|
+
operator: Equal
|
|
763
|
+
value: value1
|
|
764
|
+
effect: NoSchedule`));
|
|
765
|
+
});
|
|
766
|
+
});
|
|
767
|
+
describe('teraslice config with kubernetes_priority_class_name set', () => {
|
|
768
|
+
it('generates execution controller job with priorityClassName in pod spec', () => {
|
|
769
|
+
execution.stateful = true;
|
|
770
|
+
terasliceConfig.kubernetes_priority_class_name = 'testPriorityClass';
|
|
771
|
+
const krWorker = new K8sDeploymentResource(terasliceConfig, execution, logger, 'example-job-abcd', 'UID1');
|
|
772
|
+
expect(krWorker.resource.kind).toBe('Deployment');
|
|
773
|
+
expect(krWorker.resource.spec.template.spec).toHaveProperty('priorityClassName');
|
|
774
|
+
expect(krWorker.resource.spec.template.spec.priorityClassName).toEqual('testPriorityClass');
|
|
775
|
+
expect(krWorker.resource.spec.template.metadata.labels['job-property.teraslice.terascope.io/stateful'])
|
|
776
|
+
.toEqual('true');
|
|
777
|
+
const krExporter = new K8sJobResource(terasliceConfig, execution, logger);
|
|
778
|
+
expect(krExporter.resource.kind).toBe('Job');
|
|
779
|
+
expect(krExporter.resource.metadata.name).toBe('ts-exc-example-data-generator-job-7ba9afb0-417a');
|
|
780
|
+
expect(krExporter.resource.spec.template.spec).toHaveProperty('priorityClassName');
|
|
781
|
+
expect(krExporter.resource.spec.template.spec.priorityClassName).toEqual('testPriorityClass');
|
|
782
|
+
expect(krExporter.resource.spec.template.metadata.labels['job-property.teraslice.terascope.io/stateful'])
|
|
783
|
+
.toEqual('true');
|
|
784
|
+
});
|
|
785
|
+
});
|
|
786
|
+
describe('teraslice config with kubernetes_overrides_enabled set false', () => {
|
|
787
|
+
it('generates pods without overlay in pod .spec', () => {
|
|
788
|
+
execution.pod_spec_override = { initContainers: [] };
|
|
789
|
+
terasliceConfig.kubernetes_overrides_enabled = false;
|
|
790
|
+
const krWorker = new K8sDeploymentResource(terasliceConfig, execution, logger, 'example-job-abcd', 'UID1');
|
|
791
|
+
expect(krWorker.resource.spec.template.spec).not.toHaveProperty('initContainers');
|
|
792
|
+
});
|
|
793
|
+
});
|
|
794
|
+
describe('teraslice config with kubernetes_overrides_enabled set true', () => {
|
|
795
|
+
it('generates pods with overlay in pod .spec', () => {
|
|
796
|
+
execution.pod_spec_override = { initContainers: [] };
|
|
797
|
+
terasliceConfig.kubernetes_overrides_enabled = true;
|
|
798
|
+
const krWorker = new K8sDeploymentResource(terasliceConfig, execution, logger, 'example-job-abcd', 'UID1');
|
|
799
|
+
expect(krWorker.resource.spec.template.spec).toHaveProperty('initContainers');
|
|
800
|
+
});
|
|
801
|
+
});
|
|
802
|
+
describe('execution_controller service', () => {
|
|
803
|
+
it('has valid resource object.', () => {
|
|
804
|
+
const kr = new K8sServiceResource(terasliceConfig, execution, logger, 'example-job-abcd', 'UID1');
|
|
805
|
+
expect(kr.resource.kind).toBe('Service');
|
|
806
|
+
expect(kr.resource.metadata.name).toBe('svc-ts-exc-example-data-generator-job-7ba9afb0-417a');
|
|
807
|
+
expect(kr.resource.spec).toEqual(yaml.load(`
|
|
808
|
+
selector:
|
|
809
|
+
app.kubernetes.io/component: "execution_controller"
|
|
810
|
+
teraslice.terascope.io/exId: "e76a0278-d9bc-4d78-bf14-431bcd97528c"
|
|
811
|
+
ports:
|
|
812
|
+
- port: 45680
|
|
813
|
+
targetPort: 45680
|
|
814
|
+
`));
|
|
815
|
+
});
|
|
816
|
+
});
|
|
817
|
+
});
|
|
818
|
+
//# sourceMappingURL=k8sResource-v2-spec.js.map
|