@faros-fde-sandbox/airbyte-local-cli 0.1.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/DEVELOPER.md +76 -0
- package/LICENSE +201 -0
- package/README.md +440 -0
- package/lib/command.d.ts +11 -0
- package/lib/command.js +261 -0
- package/lib/command.js.map +1 -0
- package/lib/constants/airbyteConfig.d.ts +16 -0
- package/lib/constants/airbyteConfig.js +85 -0
- package/lib/constants/airbyteConfig.js.map +1 -0
- package/lib/constants/airbyteTypes.d.ts +14 -0
- package/lib/constants/airbyteTypes.js +214 -0
- package/lib/constants/airbyteTypes.js.map +1 -0
- package/lib/constants/constants.d.ts +11 -0
- package/lib/constants/constants.js +16 -0
- package/lib/constants/constants.js.map +1 -0
- package/lib/docker.d.ts +84 -0
- package/lib/docker.js +705 -0
- package/lib/docker.js.map +1 -0
- package/lib/index.d.ts +1 -0
- package/lib/index.js +89 -0
- package/lib/index.js.map +1 -0
- package/lib/logger.d.ts +2 -0
- package/lib/logger.js +11 -0
- package/lib/logger.js.map +1 -0
- package/lib/types.d.ts +178 -0
- package/lib/types.js +63 -0
- package/lib/types.js.map +1 -0
- package/lib/utils.d.ts +105 -0
- package/lib/utils.js +732 -0
- package/lib/utils.js.map +1 -0
- package/lib/version.d.ts +1 -0
- package/lib/version.js +5 -0
- package/lib/version.js.map +1 -0
- package/package.json +84 -0
- package/scripts/lint +37 -0
- package/src/command.ts +304 -0
- package/src/constants/airbyteConfig.ts +96 -0
- package/src/constants/airbyteTypes.ts +226 -0
- package/src/constants/constants.ts +12 -0
- package/src/docker.ts +757 -0
- package/src/index.ts +109 -0
- package/src/logger.ts +5 -0
- package/src/tsconfig.json +6 -0
- package/src/types.ts +204 -0
- package/src/utils.ts +827 -0
- package/src/version.ts +1 -0
- package/test/__snapshots__/docker.it.test.ts.snap +422 -0
- package/test/__snapshots__/utils.it.test.ts.snap +365 -0
- package/test/command.test.ts +315 -0
- package/test/docker.it.test.ts +330 -0
- package/test/docker.test.ts +119 -0
- package/test/exec/.shellspec +13 -0
- package/test/exec/spec/index_spec.sh +441 -0
- package/test/exec/spec/spec_helper.sh +24 -0
- package/test/index.test.ts +158 -0
- package/test/pester/index.Tests.ps1 +315 -0
- package/test/resources/databricks_spec.json +145 -0
- package/test/resources/dockerIt_runDstSync/faros_airbyte_cli_dst_catalog.json +16 -0
- package/test/resources/dockerIt_runDstSync/faros_airbyte_cli_dst_config.json.template +9 -0
- package/test/resources/dockerIt_runDstSync/faros_airbyte_cli_src_output +51 -0
- package/test/resources/dockerIt_runSrcSync/faros_airbyte_cli_src_catalog.json +1 -0
- package/test/resources/dockerIt_runSrcSync/faros_airbyte_cli_src_config.json +3 -0
- package/test/resources/dockerIt_runSrcSync/state.json +1 -0
- package/test/resources/faros_airbyte_cli_src_config.json +8 -0
- package/test/resources/faros_airbyte_cli_src_config_chris.json +3 -0
- package/test/resources/faros_airbyte_cli_src_config_jennie.json +3 -0
- package/test/resources/graphql_spec.json +103 -0
- package/test/resources/test__state.json +1 -0
- package/test/resources/test__state_utf16.json +0 -0
- package/test/resources/test_config_file.json +38 -0
- package/test/resources/test_config_file_crlf.json +38 -0
- package/test/resources/test_config_file_dst_only.json.template +25 -0
- package/test/resources/test_config_file_graph_copy.json.template +25 -0
- package/test/resources/test_config_file_invalid +5 -0
- package/test/resources/test_config_file_src_only space.json +8 -0
- package/test/resources/test_config_file_src_only.json +8 -0
- package/test/resources/test_config_file_utf16.json +0 -0
- package/test/resources/test_src_input +9 -0
- package/test/resources/test_src_input_invalid_json +1 -0
- package/test/tsconfig.json +12 -0
- package/test/utils.it.test.ts +605 -0
- package/test/utils.test.ts +448 -0
- package/tsconfig.json +14 -0
|
@@ -0,0 +1,365 @@
|
|
|
1
|
+
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
|
2
|
+
|
|
3
|
+
exports[`generateConfig should succeed 1`] = `
|
|
4
|
+
"{
|
|
5
|
+
"src": {
|
|
6
|
+
"image": "farosai/airbyte-faros-graphql-source",
|
|
7
|
+
"config": {
|
|
8
|
+
"foo": "bar"
|
|
9
|
+
}
|
|
10
|
+
},
|
|
11
|
+
"dst": {
|
|
12
|
+
"image": "farosai/airbyte-faros-destination",
|
|
13
|
+
"config": {
|
|
14
|
+
"edition_configs": {
|
|
15
|
+
"api_key": "<UPDATE_YOUR_FAROS_API_KEY>",
|
|
16
|
+
"edition": "cloud"
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
"
|
|
22
|
+
`;
|
|
23
|
+
|
|
24
|
+
exports[`generateConfig should succeed with image inputs 1`] = `
|
|
25
|
+
"{
|
|
26
|
+
"src": {
|
|
27
|
+
"image": "farosai/airbyte-faros-graphql-source",
|
|
28
|
+
"config": {
|
|
29
|
+
"foo": "bar"
|
|
30
|
+
}
|
|
31
|
+
},
|
|
32
|
+
"dst": {
|
|
33
|
+
"image": "farosai/airbyte-faros-destination",
|
|
34
|
+
"config": {
|
|
35
|
+
"foo": "bar"
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
"
|
|
40
|
+
`;
|
|
41
|
+
|
|
42
|
+
exports[`generateConfig should succeed with static configs 1`] = `
|
|
43
|
+
"{
|
|
44
|
+
"src": {
|
|
45
|
+
"image": "farosai/airbyte-github-source",
|
|
46
|
+
"config": {
|
|
47
|
+
"authentication": {
|
|
48
|
+
"type": "token",
|
|
49
|
+
"personal_access_token": "<UPDATE_YOUR_GITHUB_TOKEN>"
|
|
50
|
+
},
|
|
51
|
+
"organizations": [
|
|
52
|
+
"<UPDATE_MY_ORG_1>",
|
|
53
|
+
"<UPDATE_MY_ORG_2>"
|
|
54
|
+
]
|
|
55
|
+
}
|
|
56
|
+
},
|
|
57
|
+
"dst": {
|
|
58
|
+
"image": "farosai/airbyte-faros-destination",
|
|
59
|
+
"config": {
|
|
60
|
+
"edition_configs": {
|
|
61
|
+
"api_key": "<UPDATE_YOUR_FAROS_API_KEY>",
|
|
62
|
+
"edition": "cloud"
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
"
|
|
68
|
+
`;
|
|
69
|
+
|
|
70
|
+
exports[`parseConfigFile should parse crlf 1`] = `
|
|
71
|
+
{
|
|
72
|
+
"dst": {
|
|
73
|
+
"catalog": {},
|
|
74
|
+
"config": {
|
|
75
|
+
"edition_config": {
|
|
76
|
+
"api_key": "***",
|
|
77
|
+
"api_url": "https://prod.api.faros.ai",
|
|
78
|
+
"edition": "cloud",
|
|
79
|
+
"graph": "default",
|
|
80
|
+
},
|
|
81
|
+
},
|
|
82
|
+
"dockerOptions": {
|
|
83
|
+
"maxCpus": 2,
|
|
84
|
+
"maxMemory": 2048,
|
|
85
|
+
},
|
|
86
|
+
"image": "farosai/airbyte-servicenow-destination",
|
|
87
|
+
},
|
|
88
|
+
"src": {
|
|
89
|
+
"catalog": {},
|
|
90
|
+
"config": {
|
|
91
|
+
"password": "***",
|
|
92
|
+
"url": "https://test-instance.service-now.com",
|
|
93
|
+
"username": "test-username",
|
|
94
|
+
},
|
|
95
|
+
"dockerOptions": {
|
|
96
|
+
"additionalOptions": {
|
|
97
|
+
"HostConfig": {
|
|
98
|
+
"Binds": [
|
|
99
|
+
"/test/path:/test/path/test.json",
|
|
100
|
+
],
|
|
101
|
+
},
|
|
102
|
+
},
|
|
103
|
+
"maxCpus": 2,
|
|
104
|
+
"maxMemory": 2048,
|
|
105
|
+
},
|
|
106
|
+
"image": "farosai/airbyte-servicenow-source",
|
|
107
|
+
},
|
|
108
|
+
}
|
|
109
|
+
`;
|
|
110
|
+
|
|
111
|
+
exports[`parseConfigFile should parse utf16 encoding 1`] = `
|
|
112
|
+
{
|
|
113
|
+
"dst": {
|
|
114
|
+
"catalog": {},
|
|
115
|
+
"config": {
|
|
116
|
+
"edition_config": {
|
|
117
|
+
"api_key": "***",
|
|
118
|
+
"api_url": "https://prod.api.faros.ai",
|
|
119
|
+
"edition": "cloud",
|
|
120
|
+
"graph": "default",
|
|
121
|
+
},
|
|
122
|
+
},
|
|
123
|
+
"dockerOptions": {
|
|
124
|
+
"maxCpus": 2,
|
|
125
|
+
"maxMemory": 2048,
|
|
126
|
+
},
|
|
127
|
+
"image": "farosai/airbyte-servicenow-destination",
|
|
128
|
+
},
|
|
129
|
+
"src": {
|
|
130
|
+
"catalog": {},
|
|
131
|
+
"config": {
|
|
132
|
+
"password": "***",
|
|
133
|
+
"url": "https://test-instance.service-now.com",
|
|
134
|
+
"username": "test-username",
|
|
135
|
+
},
|
|
136
|
+
"dockerOptions": {
|
|
137
|
+
"maxCpus": 2,
|
|
138
|
+
"maxMemory": 2048,
|
|
139
|
+
},
|
|
140
|
+
"image": "farosai/airbyte-servicenow-source",
|
|
141
|
+
},
|
|
142
|
+
}
|
|
143
|
+
`;
|
|
144
|
+
|
|
145
|
+
exports[`parseConfigFile should pass 1`] = `
|
|
146
|
+
{
|
|
147
|
+
"dst": {
|
|
148
|
+
"catalog": {},
|
|
149
|
+
"config": {
|
|
150
|
+
"edition_config": {
|
|
151
|
+
"api_key": "***",
|
|
152
|
+
"api_url": "https://prod.api.faros.ai",
|
|
153
|
+
"edition": "cloud",
|
|
154
|
+
"graph": "default",
|
|
155
|
+
},
|
|
156
|
+
},
|
|
157
|
+
"dockerOptions": {
|
|
158
|
+
"maxCpus": 2,
|
|
159
|
+
"maxMemory": 2048,
|
|
160
|
+
},
|
|
161
|
+
"image": "farosai/airbyte-servicenow-destination",
|
|
162
|
+
},
|
|
163
|
+
"src": {
|
|
164
|
+
"catalog": {},
|
|
165
|
+
"config": {
|
|
166
|
+
"password": "***",
|
|
167
|
+
"url": "https://test-instance.service-now.com",
|
|
168
|
+
"username": "test-username",
|
|
169
|
+
},
|
|
170
|
+
"dockerOptions": {
|
|
171
|
+
"additionalOptions": {
|
|
172
|
+
"HostConfig": {
|
|
173
|
+
"Binds": [
|
|
174
|
+
"/test/path:/test/path/test.json",
|
|
175
|
+
],
|
|
176
|
+
},
|
|
177
|
+
},
|
|
178
|
+
"maxCpus": 2,
|
|
179
|
+
"maxMemory": 2048,
|
|
180
|
+
},
|
|
181
|
+
"image": "farosai/airbyte-servicenow-source",
|
|
182
|
+
},
|
|
183
|
+
}
|
|
184
|
+
`;
|
|
185
|
+
|
|
186
|
+
exports[`processSrcInputFile should succeed writing to an output file 1`] = `
|
|
187
|
+
"{"state":{"data":{"format":"base64/gzip","data":"H4sIAAAAAAAAA6uuBQBDv6ajAgAAAA=="}},"type":"STATE","redactedConfig":{"user":"chris"},"sourceType":"example","sourceVersion":"0.12.3"}
|
|
188
|
+
{"state":{"data":{"format":"base64/gzip","data":"H4sIAAAAAAAAA6uuBQBDv6ajAgAAAA=="}},"type":"STATE","sourceStatus":{"status":"SUCCESS"}}
|
|
189
|
+
{"state":{"data":{"format":"base64/gzip","data":"H4sIAAAAAAAAA6uuBQBDv6ajAgAAAA=="}},"type":"STATE","logs":[{"timestamp":***,"message":{"level":30,"msg":"Source version: 0.12.3"}},{"timestamp":***,"message":{"level":30,"msg":"Config: {\\"user\\":\\"chris\\"}"}},{"timestamp":***,"message":{"level":30,"msg":"Catalog: {}"}},{"timestamp":***,"message":{"level":30,"msg":"State: {}"}},{"timestamp":***,"message":{"level":30,"msg":"Syncing ExampleSource"}},{"timestamp":***,"message":{"level":30,"msg":"Finished syncing ExampleSource"}}]}
|
|
190
|
+
"
|
|
191
|
+
`;
|
|
192
|
+
|
|
193
|
+
exports[`write files to temporary dir loadStateFile should pass with existing state file 1`] = `
|
|
194
|
+
"{"format":"base64/gzip","data":"dGVzdA=="}
|
|
195
|
+
"
|
|
196
|
+
`;
|
|
197
|
+
|
|
198
|
+
exports[`write files to temporary dir loadStateFile should pass with utf16 state file 1`] = `
|
|
199
|
+
"{"format":"base64/gzip","data":"dGVzdA=="}
|
|
200
|
+
"
|
|
201
|
+
`;
|
|
202
|
+
|
|
203
|
+
exports[`write files to temporary dir writeCatalog should succeed with default only 1`] = `
|
|
204
|
+
{
|
|
205
|
+
"streams": [
|
|
206
|
+
{
|
|
207
|
+
"destination_sync_mode": "append",
|
|
208
|
+
"stream": {
|
|
209
|
+
"json_schema": {},
|
|
210
|
+
"name": "builds",
|
|
211
|
+
"supported_sync_modes": [
|
|
212
|
+
"full_refresh",
|
|
213
|
+
"incremental",
|
|
214
|
+
],
|
|
215
|
+
},
|
|
216
|
+
"sync_mode": "incremental",
|
|
217
|
+
},
|
|
218
|
+
],
|
|
219
|
+
}
|
|
220
|
+
`;
|
|
221
|
+
|
|
222
|
+
exports[`write files to temporary dir writeCatalog should succeed with default only 2`] = `
|
|
223
|
+
{
|
|
224
|
+
"streams": [
|
|
225
|
+
{
|
|
226
|
+
"destination_sync_mode": "append",
|
|
227
|
+
"stream": {
|
|
228
|
+
"json_schema": {},
|
|
229
|
+
"name": "testPrefix__builds",
|
|
230
|
+
"supported_sync_modes": [
|
|
231
|
+
"full_refresh",
|
|
232
|
+
"incremental",
|
|
233
|
+
],
|
|
234
|
+
},
|
|
235
|
+
"sync_mode": "incremental",
|
|
236
|
+
},
|
|
237
|
+
],
|
|
238
|
+
}
|
|
239
|
+
`;
|
|
240
|
+
|
|
241
|
+
exports[`write files to temporary dir writeCatalog should succeed with dst override 1`] = `
|
|
242
|
+
{
|
|
243
|
+
"streams": [
|
|
244
|
+
{
|
|
245
|
+
"destination_sync_mode": "append",
|
|
246
|
+
"stream": {
|
|
247
|
+
"json_schema": {},
|
|
248
|
+
"name": "builds",
|
|
249
|
+
"supported_sync_modes": [
|
|
250
|
+
"full_refresh",
|
|
251
|
+
"incremental",
|
|
252
|
+
],
|
|
253
|
+
},
|
|
254
|
+
"sync_mode": "incremental",
|
|
255
|
+
},
|
|
256
|
+
],
|
|
257
|
+
}
|
|
258
|
+
`;
|
|
259
|
+
|
|
260
|
+
exports[`write files to temporary dir writeCatalog should succeed with dst override 2`] = `
|
|
261
|
+
{
|
|
262
|
+
"streams": [
|
|
263
|
+
{
|
|
264
|
+
"destination_sync_mode": "overwrite",
|
|
265
|
+
"stream": {
|
|
266
|
+
"json_schema": {},
|
|
267
|
+
"name": "testPrefix__builds",
|
|
268
|
+
"supported_sync_modes": [
|
|
269
|
+
"full_refresh",
|
|
270
|
+
"incremental",
|
|
271
|
+
],
|
|
272
|
+
},
|
|
273
|
+
"sync_mode": "full_refresh",
|
|
274
|
+
},
|
|
275
|
+
],
|
|
276
|
+
}
|
|
277
|
+
`;
|
|
278
|
+
|
|
279
|
+
exports[`write files to temporary dir writeCatalog should succeed with src override 1`] = `
|
|
280
|
+
{
|
|
281
|
+
"streams": [
|
|
282
|
+
{
|
|
283
|
+
"destination_sync_mode": "overwrite",
|
|
284
|
+
"stream": {
|
|
285
|
+
"json_schema": {},
|
|
286
|
+
"name": "builds",
|
|
287
|
+
"supported_sync_modes": [
|
|
288
|
+
"full_refresh",
|
|
289
|
+
"incremental",
|
|
290
|
+
],
|
|
291
|
+
},
|
|
292
|
+
"sync_mode": "full_refresh",
|
|
293
|
+
},
|
|
294
|
+
],
|
|
295
|
+
}
|
|
296
|
+
`;
|
|
297
|
+
|
|
298
|
+
exports[`write files to temporary dir writeCatalog should succeed with src override 2`] = `
|
|
299
|
+
{
|
|
300
|
+
"streams": [
|
|
301
|
+
{
|
|
302
|
+
"destination_sync_mode": "overwrite",
|
|
303
|
+
"stream": {
|
|
304
|
+
"json_schema": {},
|
|
305
|
+
"name": "testOverridePrefix__builds",
|
|
306
|
+
"supported_sync_modes": [
|
|
307
|
+
"full_refresh",
|
|
308
|
+
"incremental",
|
|
309
|
+
],
|
|
310
|
+
},
|
|
311
|
+
"sync_mode": "full_refresh",
|
|
312
|
+
},
|
|
313
|
+
],
|
|
314
|
+
}
|
|
315
|
+
`;
|
|
316
|
+
|
|
317
|
+
exports[`writeStateFile should prioritize STREAM states over LEGACY state 1`] = `
|
|
318
|
+
[
|
|
319
|
+
{
|
|
320
|
+
"stream": {
|
|
321
|
+
"stream_descriptor": {
|
|
322
|
+
"name": "users",
|
|
323
|
+
},
|
|
324
|
+
"stream_state": {
|
|
325
|
+
"cursor": "2024-01-01",
|
|
326
|
+
},
|
|
327
|
+
},
|
|
328
|
+
"type": "STREAM",
|
|
329
|
+
},
|
|
330
|
+
]
|
|
331
|
+
`;
|
|
332
|
+
|
|
333
|
+
exports[`writeStateFile should write LEGACY state data only 1`] = `
|
|
334
|
+
{
|
|
335
|
+
"data": "dGVzdA==",
|
|
336
|
+
"format": "base64/gzip",
|
|
337
|
+
}
|
|
338
|
+
`;
|
|
339
|
+
|
|
340
|
+
exports[`writeStateFile should write STREAM states as an array 1`] = `
|
|
341
|
+
[
|
|
342
|
+
{
|
|
343
|
+
"stream": {
|
|
344
|
+
"stream_descriptor": {
|
|
345
|
+
"name": "users",
|
|
346
|
+
},
|
|
347
|
+
"stream_state": {
|
|
348
|
+
"cursor": "2024-01-01",
|
|
349
|
+
},
|
|
350
|
+
},
|
|
351
|
+
"type": "STREAM",
|
|
352
|
+
},
|
|
353
|
+
{
|
|
354
|
+
"stream": {
|
|
355
|
+
"stream_descriptor": {
|
|
356
|
+
"name": "orders",
|
|
357
|
+
},
|
|
358
|
+
"stream_state": {
|
|
359
|
+
"cursor": "2024-02-01",
|
|
360
|
+
},
|
|
361
|
+
},
|
|
362
|
+
"type": "STREAM",
|
|
363
|
+
},
|
|
364
|
+
]
|
|
365
|
+
`;
|
|
@@ -0,0 +1,315 @@
|
|
|
1
|
+
import {parseAndValidateInputs} from '../src/command';
|
|
2
|
+
import {parseConfigFile} from '../src/utils';
|
|
3
|
+
|
|
4
|
+
jest.mock('../src/utils');
|
|
5
|
+
|
|
6
|
+
const defaultConfig = {
|
|
7
|
+
srcPull: true,
|
|
8
|
+
dstPull: true,
|
|
9
|
+
srcCheckConnection: false,
|
|
10
|
+
dstUseHostNetwork: false,
|
|
11
|
+
fullRefresh: false,
|
|
12
|
+
rawMessages: false,
|
|
13
|
+
keepContainers: false,
|
|
14
|
+
logLevel: 'info',
|
|
15
|
+
debug: false,
|
|
16
|
+
silent: false,
|
|
17
|
+
image: false,
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
afterEach(() => {
|
|
21
|
+
jest.resetAllMocks();
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
describe('Check options conflict', () => {
|
|
25
|
+
it('should fail if using both --config-file and --src', () => {
|
|
26
|
+
jest.spyOn(process, 'exit').mockImplementation(() => {
|
|
27
|
+
throw new Error('process.exit() was called by commander js');
|
|
28
|
+
});
|
|
29
|
+
const argv = ['./airbyte-local-cli', 'index.js', '--config-file', 'config-file-path', '--src', 'source-image'];
|
|
30
|
+
expect(() => parseAndValidateInputs(argv)).toThrow('process.exit() was called by commander js');
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
it('should fail if using both --config-file and --dst', () => {
|
|
34
|
+
jest.spyOn(process, 'exit').mockImplementation(() => {
|
|
35
|
+
throw new Error('process.exit() was called by commander js');
|
|
36
|
+
});
|
|
37
|
+
const argv = ['./airbyte-local-cli', 'index.js', '--config-file', 'config-file-path', '--dst', 'destination-image'];
|
|
38
|
+
expect(() => parseAndValidateInputs(argv)).toThrow();
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
it('should fail if using both --src-only and --src-output-file', () => {
|
|
42
|
+
jest.spyOn(process, 'exit').mockImplementation(() => {
|
|
43
|
+
throw new Error('process.exit() was called by commander js');
|
|
44
|
+
});
|
|
45
|
+
const argv = ['./airbyte-local-cli', 'index.js', '--src-only', '--src-output-file', 'some_test_path'];
|
|
46
|
+
expect(() => parseAndValidateInputs(argv)).toThrow();
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
it('should fail if using both --dst-only and --src-only', () => {
|
|
50
|
+
jest.spyOn(process, 'exit').mockImplementation(() => {
|
|
51
|
+
throw new Error('process.exit() was called by commander js');
|
|
52
|
+
});
|
|
53
|
+
const argv = ['./airbyte-local-cli', 'index.js', '--src-only', '--dst-only', 'some_test_path'];
|
|
54
|
+
expect(() => parseAndValidateInputs(argv)).toThrow();
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
it('should fail if using both --dst-only and --src-output-file', () => {
|
|
58
|
+
jest.spyOn(process, 'exit').mockImplementation(() => {
|
|
59
|
+
throw new Error('process.exit() was called by commander js');
|
|
60
|
+
});
|
|
61
|
+
const argv = [
|
|
62
|
+
'./airbyte-local-cli',
|
|
63
|
+
'index.js',
|
|
64
|
+
'--dst-only',
|
|
65
|
+
'some_test_path',
|
|
66
|
+
'--src-output-file',
|
|
67
|
+
'some_test_path',
|
|
68
|
+
];
|
|
69
|
+
expect(() => parseAndValidateInputs(argv)).toThrow();
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
it('should fail if using both --dst-only and --src-check-connection', () => {
|
|
73
|
+
jest.spyOn(process, 'exit').mockImplementation(() => {
|
|
74
|
+
throw new Error('process.exit() was called by commander js');
|
|
75
|
+
});
|
|
76
|
+
const argv = ['./airbyte-local-cli', 'index.js', '--src-check-connection', '--dst-only', 'some_test_path'];
|
|
77
|
+
expect(() => parseAndValidateInputs(argv)).toThrow();
|
|
78
|
+
});
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
describe('Check src and dst config parsing', () => {
|
|
82
|
+
it('should parse and validate options: src and dst', () => {
|
|
83
|
+
const argv = ['./airbyte-local-cli', 'index.js', '--src', 'source-image', '--dst', 'destination-image'];
|
|
84
|
+
const result = parseAndValidateInputs(argv);
|
|
85
|
+
expect(result).toEqual({
|
|
86
|
+
...defaultConfig,
|
|
87
|
+
src: {image: 'source-image', config: {}},
|
|
88
|
+
dst: {image: 'destination-image', config: {}},
|
|
89
|
+
});
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
it('should parse and validate options: configFile', () => {
|
|
93
|
+
const mockedParseConfigFile = parseConfigFile as jest.Mock;
|
|
94
|
+
mockedParseConfigFile.mockReturnValue({
|
|
95
|
+
src: {image: 'source-image', config: {}},
|
|
96
|
+
dst: {image: 'destination-image', config: {}},
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
const argv = ['./airbyte-local-cli', 'index.js', '--config-file', 'config-file-path'];
|
|
100
|
+
const result = parseAndValidateInputs(argv);
|
|
101
|
+
expect(result).toEqual({
|
|
102
|
+
...defaultConfig,
|
|
103
|
+
src: {image: 'source-image', config: {}},
|
|
104
|
+
dst: {image: 'destination-image', config: {}},
|
|
105
|
+
});
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
it('should parse and validate options: src.* and dst.*', () => {
|
|
109
|
+
const argv = [
|
|
110
|
+
'./airbyte-local-cli',
|
|
111
|
+
'index.js',
|
|
112
|
+
'--src',
|
|
113
|
+
'source-image',
|
|
114
|
+
'--dst',
|
|
115
|
+
'destination-image',
|
|
116
|
+
'--src.username',
|
|
117
|
+
'src-username',
|
|
118
|
+
'--src.password',
|
|
119
|
+
'src-password',
|
|
120
|
+
'--dst.username',
|
|
121
|
+
'dst-username',
|
|
122
|
+
'--dst.password',
|
|
123
|
+
'dst-password',
|
|
124
|
+
];
|
|
125
|
+
const result = parseAndValidateInputs(argv);
|
|
126
|
+
expect(result).toEqual({
|
|
127
|
+
...defaultConfig,
|
|
128
|
+
src: {image: 'source-image', config: {username: 'src-username', password: 'src-password'}},
|
|
129
|
+
dst: {image: 'destination-image', config: {username: 'dst-username', password: 'dst-password'}},
|
|
130
|
+
});
|
|
131
|
+
});
|
|
132
|
+
|
|
133
|
+
it('should parse and validate options: nested src.* and dst.*', () => {
|
|
134
|
+
const argv = [
|
|
135
|
+
'./airbyte-local-cli',
|
|
136
|
+
'index.js',
|
|
137
|
+
'--src',
|
|
138
|
+
'source-image',
|
|
139
|
+
'--dst',
|
|
140
|
+
'destination-image',
|
|
141
|
+
'--dst.edition_config.graph',
|
|
142
|
+
'default',
|
|
143
|
+
'--dst.edition_config.edition',
|
|
144
|
+
'cloud',
|
|
145
|
+
];
|
|
146
|
+
const result = parseAndValidateInputs(argv);
|
|
147
|
+
expect(result).toEqual({
|
|
148
|
+
...defaultConfig,
|
|
149
|
+
src: {image: 'source-image', config: {}},
|
|
150
|
+
dst: {
|
|
151
|
+
image: 'destination-image',
|
|
152
|
+
config: {
|
|
153
|
+
edition_config: {graph: 'default', edition: 'cloud'},
|
|
154
|
+
},
|
|
155
|
+
},
|
|
156
|
+
});
|
|
157
|
+
});
|
|
158
|
+
|
|
159
|
+
it('should parse and validate options: json object as string', () => {
|
|
160
|
+
const argv = [
|
|
161
|
+
'./airbyte-local-cli',
|
|
162
|
+
'index.js',
|
|
163
|
+
'--src',
|
|
164
|
+
'source-image',
|
|
165
|
+
'--dst',
|
|
166
|
+
'destination-image',
|
|
167
|
+
'--dst.edition_config',
|
|
168
|
+
'{"edition":"cloud", "graphql_api": "v2"}',
|
|
169
|
+
'--dst.edition_config.graph',
|
|
170
|
+
'default',
|
|
171
|
+
'--dst.edition_config.edition',
|
|
172
|
+
'cloud',
|
|
173
|
+
];
|
|
174
|
+
const result = parseAndValidateInputs(argv);
|
|
175
|
+
expect(result).toEqual({
|
|
176
|
+
...defaultConfig,
|
|
177
|
+
src: {image: 'source-image', config: {}},
|
|
178
|
+
dst: {
|
|
179
|
+
image: 'destination-image',
|
|
180
|
+
config: {
|
|
181
|
+
edition_config: {graph: 'default', edition: 'cloud', graphql_api: 'v2'},
|
|
182
|
+
},
|
|
183
|
+
},
|
|
184
|
+
});
|
|
185
|
+
});
|
|
186
|
+
});
|
|
187
|
+
|
|
188
|
+
describe(`Check subcommand 'generate-config'`, () => {
|
|
189
|
+
it('should parse without destination argument', () => {
|
|
190
|
+
const argv = ['./airbyte-local-cli', 'index.js', 'generate-config', 'jira'];
|
|
191
|
+
const cfg = parseAndValidateInputs(argv);
|
|
192
|
+
expect(cfg.generateConfig).toEqual({src: 'jira'});
|
|
193
|
+
});
|
|
194
|
+
|
|
195
|
+
it('should parse with destination argument', () => {
|
|
196
|
+
const argv = ['./airbyte-local-cli', 'index.js', 'generate-config', 'jira', 'other'];
|
|
197
|
+
const cfg = parseAndValidateInputs(argv);
|
|
198
|
+
expect(cfg.generateConfig).toEqual({src: 'jira', dst: 'other'});
|
|
199
|
+
});
|
|
200
|
+
|
|
201
|
+
it('should parse with silent option', () => {
|
|
202
|
+
const argv = ['./airbyte-local-cli', 'index.js', 'generate-config', '--silent', 'jira'];
|
|
203
|
+
const cfg = parseAndValidateInputs(argv);
|
|
204
|
+
expect(cfg.silent).toEqual(true);
|
|
205
|
+
expect(cfg.generateConfig).toEqual({src: 'jira'});
|
|
206
|
+
});
|
|
207
|
+
|
|
208
|
+
it('should parse with silent option', () => {
|
|
209
|
+
const argv = ['./airbyte-local-cli', 'index.js', 'generate-config', '--image', 'jira-image'];
|
|
210
|
+
const cfg = parseAndValidateInputs(argv);
|
|
211
|
+
expect(cfg.image).toEqual(true);
|
|
212
|
+
expect(cfg.generateConfig).toEqual({src: 'jira-image'});
|
|
213
|
+
});
|
|
214
|
+
});
|
|
215
|
+
|
|
216
|
+
describe('Check other options', () => {
|
|
217
|
+
it('should parse and validate options: all optional ones', () => {
|
|
218
|
+
const argv = [
|
|
219
|
+
'./airbyte-local-cli',
|
|
220
|
+
'index.js',
|
|
221
|
+
'--src',
|
|
222
|
+
'source-image',
|
|
223
|
+
'--dst',
|
|
224
|
+
'destination-image',
|
|
225
|
+
'--state-file',
|
|
226
|
+
'test_state_file',
|
|
227
|
+
'--src-output-file',
|
|
228
|
+
'test_src_output_file',
|
|
229
|
+
'--dst-only',
|
|
230
|
+
'test_src_input_file',
|
|
231
|
+
'--connection-name',
|
|
232
|
+
'test_connection_name',
|
|
233
|
+
'--log-level',
|
|
234
|
+
'debug',
|
|
235
|
+
'--full-refresh',
|
|
236
|
+
'--no-src-pull',
|
|
237
|
+
'--no-dst-pull',
|
|
238
|
+
'--src-check-connection',
|
|
239
|
+
'--dst-use-host-network',
|
|
240
|
+
'--raw-messages',
|
|
241
|
+
'--keep-containers',
|
|
242
|
+
'--debug',
|
|
243
|
+
];
|
|
244
|
+
const result = parseAndValidateInputs(argv);
|
|
245
|
+
expect(result).toEqual({
|
|
246
|
+
...defaultConfig,
|
|
247
|
+
src: {image: 'source-image', config: {}},
|
|
248
|
+
dst: {image: 'destination-image', config: {}},
|
|
249
|
+
srcOutputFile: 'test_src_output_file',
|
|
250
|
+
srcInputFile: 'test_src_input_file',
|
|
251
|
+
srcCheckConnection: true,
|
|
252
|
+
dstUseHostNetwork: true,
|
|
253
|
+
srcPull: false,
|
|
254
|
+
dstPull: false,
|
|
255
|
+
connectionName: 'test_connection_name',
|
|
256
|
+
stateFile: 'test_state_file',
|
|
257
|
+
fullRefresh: true,
|
|
258
|
+
rawMessages: true,
|
|
259
|
+
keepContainers: true,
|
|
260
|
+
logLevel: 'debug',
|
|
261
|
+
debug: true,
|
|
262
|
+
});
|
|
263
|
+
});
|
|
264
|
+
|
|
265
|
+
it('should parse and validate options: debug', () => {
|
|
266
|
+
const argv = ['./airbyte-local-cli', 'index.js', '--src', 'source-image', '--dst', 'destination-image', '--debug'];
|
|
267
|
+
const result = parseAndValidateInputs(argv);
|
|
268
|
+
expect(result).toEqual({
|
|
269
|
+
...defaultConfig,
|
|
270
|
+
src: {image: 'source-image', config: {}},
|
|
271
|
+
dst: {image: 'destination-image', config: {}},
|
|
272
|
+
logLevel: 'debug',
|
|
273
|
+
debug: true,
|
|
274
|
+
});
|
|
275
|
+
});
|
|
276
|
+
|
|
277
|
+
it('should not fail on src-only without providing dst image', () => {
|
|
278
|
+
const argv = ['./airbyte-local-cli', 'index.js', '--src', 'source-image', '--src-only'];
|
|
279
|
+
const result = parseAndValidateInputs(argv);
|
|
280
|
+
expect(result).toEqual({
|
|
281
|
+
...defaultConfig,
|
|
282
|
+
src: {image: 'source-image', config: {}},
|
|
283
|
+
dst: {image: undefined, config: {}},
|
|
284
|
+
srcOutputFile: 'STDOUT',
|
|
285
|
+
dstPull: false,
|
|
286
|
+
});
|
|
287
|
+
});
|
|
288
|
+
|
|
289
|
+
it('should not fail on dst-only without providing src image', () => {
|
|
290
|
+
const argv = ['./airbyte-local-cli', 'index.js', '--dst', 'destination-image', '--dst-only', 'test_src_input_file'];
|
|
291
|
+
const result = parseAndValidateInputs(argv);
|
|
292
|
+
expect(result).toEqual({
|
|
293
|
+
...defaultConfig,
|
|
294
|
+
src: {image: undefined, config: {}},
|
|
295
|
+
dst: {image: 'destination-image', config: {}},
|
|
296
|
+
srcInputFile: 'test_src_input_file',
|
|
297
|
+
srcPull: false,
|
|
298
|
+
});
|
|
299
|
+
});
|
|
300
|
+
});
|
|
301
|
+
|
|
302
|
+
describe('Check unknown options', () => {
|
|
303
|
+
it('should throw error for unknown options', () => {
|
|
304
|
+
const argv = ['./airbyte-local-cli', 'index.js', '--unknown-option'];
|
|
305
|
+
expect(() => parseAndValidateInputs(argv)).toThrow('Unknown option: --unknown-option');
|
|
306
|
+
});
|
|
307
|
+
|
|
308
|
+
it('should throw error for unknown options for generate-config', () => {
|
|
309
|
+
jest.spyOn(process, 'exit').mockImplementation(() => {
|
|
310
|
+
throw new Error('process.exit() was called by commander js');
|
|
311
|
+
});
|
|
312
|
+
const argv = ['./airbyte-local-cli', 'index.js', 'generate-config', '--unknown-option'];
|
|
313
|
+
expect(() => parseAndValidateInputs(argv)).toThrow('process.exit() was called by commander js');
|
|
314
|
+
});
|
|
315
|
+
});
|