@contrail/cli 1.0.48 → 1.0.49
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/lib/cli.js
CHANGED
|
@@ -14,6 +14,7 @@ import { installApp, uninstallApp } from './apps/install-app/app-installer';
|
|
|
14
14
|
import { upgradeApp } from './apps/upgrade-app/app-upgrader';
|
|
15
15
|
import { cliInstallWorkflowTemplateDefinitions, listWorkflowTemplateDefinitions } from './workflow-template-definitions/workflow-template-definition-commands';
|
|
16
16
|
import { configureProject } from './projects/project-uploader';
|
|
17
|
+
import { Load, UploadAndLoad } from './loader-process/loader-process';
|
|
17
18
|
const cliUsage = require('command-line-usage');
|
|
18
19
|
/**
|
|
19
20
|
* Built using documentation here:
|
|
@@ -136,6 +137,22 @@ export async function cli(args) {
|
|
|
136
137
|
}
|
|
137
138
|
break;
|
|
138
139
|
}
|
|
140
|
+
case 'loader': {
|
|
141
|
+
switch (command) {
|
|
142
|
+
case 'uploadAndLoad': {
|
|
143
|
+
await UploadAndLoad(args);
|
|
144
|
+
break;
|
|
145
|
+
}
|
|
146
|
+
case 'load': {
|
|
147
|
+
await Load(args);
|
|
148
|
+
break;
|
|
149
|
+
}
|
|
150
|
+
default: {
|
|
151
|
+
printIllegalCommand();
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
break;
|
|
155
|
+
}
|
|
139
156
|
case 'projects': {
|
|
140
157
|
switch (command) {
|
|
141
158
|
case 'configure': {
|
|
@@ -275,6 +292,18 @@ const helpSections = [
|
|
|
275
292
|
// , {name: 'delete', summary: 'Delete all colors.'}
|
|
276
293
|
],
|
|
277
294
|
},
|
|
295
|
+
{
|
|
296
|
+
header: 'Loader Commands - Domain: loader',
|
|
297
|
+
content: [{
|
|
298
|
+
name: 'uploadAndLoad <File Path> <Config Path>',
|
|
299
|
+
summary: 'Upload a csv file and kick off a load job for the uploaded file. The file path must be a reference to a .csv file and the config path must be a reference to a .json or a .yml file.'
|
|
300
|
+
},
|
|
301
|
+
{
|
|
302
|
+
name: 'load <Config Path>',
|
|
303
|
+
summary: 'Upload a csv file and kick off a load job for the uploaded file. The config path must be a reference to a .json or a .yml file.'
|
|
304
|
+
}
|
|
305
|
+
],
|
|
306
|
+
},
|
|
278
307
|
{
|
|
279
308
|
header: 'Project Commands - Domain: projects',
|
|
280
309
|
content: [{
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
import { Entities, Files } from '@contrail/sdk';
|
|
2
|
+
import { authUser } from '../auth/login';
|
|
3
|
+
import chalk from 'chalk';
|
|
4
|
+
import * as fs from 'fs';
|
|
5
|
+
import { getSeparatorByPlatform } from '../common';
|
|
6
|
+
import yaml from 'js-yaml';
|
|
7
|
+
export async function UploadAndLoad(args) {
|
|
8
|
+
try {
|
|
9
|
+
await authUser();
|
|
10
|
+
console.log('%s Uploading file', chalk.yellow.bold('LOADER'));
|
|
11
|
+
const incomingFileName = args[3];
|
|
12
|
+
const configFileName = args[4];
|
|
13
|
+
await uploadAndLoadLocalFile(incomingFileName, configFileName);
|
|
14
|
+
console.log('%s Uploaded', chalk.yellow.bold('LOADER'));
|
|
15
|
+
}
|
|
16
|
+
catch (e) {
|
|
17
|
+
console.log(`%s Starting Load Failed. ${e}`, chalk.red.bold('FAIL'));
|
|
18
|
+
return;
|
|
19
|
+
}
|
|
20
|
+
console.log('%s Starting Load Complete.', chalk.green.bold('COMPLETE'));
|
|
21
|
+
}
|
|
22
|
+
export async function Load(args) {
|
|
23
|
+
try {
|
|
24
|
+
await authUser();
|
|
25
|
+
console.log('%s Uploading file', chalk.yellow.bold('LOADER'));
|
|
26
|
+
const configFileName = args[3];
|
|
27
|
+
await loadLocalFile(configFileName);
|
|
28
|
+
console.log('%s Uploaded', chalk.yellow.bold('LOADER'));
|
|
29
|
+
}
|
|
30
|
+
catch (e) {
|
|
31
|
+
console.log(`%s Starting Load Failed. ${e}`, chalk.red.bold('FAIL'));
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
console.log('%s Starting Load Complete.', chalk.green.bold('COMPLETE'));
|
|
35
|
+
}
|
|
36
|
+
async function getLocalFile(incomingFileName) {
|
|
37
|
+
const ext = getFileExtension(incomingFileName);
|
|
38
|
+
if (ext !== '.csv') {
|
|
39
|
+
throw new Error('Upload file must be a .csv');
|
|
40
|
+
}
|
|
41
|
+
const TARGET_DIR = process.cwd();
|
|
42
|
+
try {
|
|
43
|
+
const separator = getSeparatorByPlatform();
|
|
44
|
+
return fs.readFileSync(TARGET_DIR + separator + incomingFileName);
|
|
45
|
+
}
|
|
46
|
+
catch (e) {
|
|
47
|
+
throw new Error(`ERROR LOADING CSV: ${e}`);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
async function getLocalUploadConfig(configFileName) {
|
|
51
|
+
const ext = getFileExtension(configFileName);
|
|
52
|
+
if (ext !== '.json' && ext !== '.yml') {
|
|
53
|
+
throw new Error('Upload file must be a .json or .yml');
|
|
54
|
+
}
|
|
55
|
+
const CURRENT_DIR = process.cwd();
|
|
56
|
+
const separator = getSeparatorByPlatform();
|
|
57
|
+
const fullPath = CURRENT_DIR + separator + configFileName;
|
|
58
|
+
console.log('Getting config from path: ', fullPath);
|
|
59
|
+
if (ext === '.yml') {
|
|
60
|
+
try {
|
|
61
|
+
const doc = yaml.load(fs.readFileSync(fullPath, 'utf8'));
|
|
62
|
+
return doc;
|
|
63
|
+
}
|
|
64
|
+
catch (e) {
|
|
65
|
+
throw new Error(`ERROR LOADING UPLOAD CONFIGURATION FILE: ${e}`);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
try {
|
|
69
|
+
const doc = JSON.parse(fs.readFileSync(fullPath, 'utf8'));
|
|
70
|
+
return doc;
|
|
71
|
+
}
|
|
72
|
+
catch (e) {
|
|
73
|
+
throw new Error(`ERROR LOADING UPLOAD CONFIGURATION FILE: ${e}`);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
async function uploadFile(incomingFileName) {
|
|
77
|
+
const csvContent = await getLocalFile(incomingFileName);
|
|
78
|
+
const entities = new Entities();
|
|
79
|
+
const fileName = `${incomingFileName.slice(0, incomingFileName.length - 5)}-Upload-${new Date().getTime()}.csv`;
|
|
80
|
+
const file = await entities.create({
|
|
81
|
+
entityName: 'file',
|
|
82
|
+
object: { contentType: 'text/csv', fileName: fileName, ttl: 24 * 60 * 60 * 1000 }
|
|
83
|
+
});
|
|
84
|
+
console.log('VibeIQ file ID:', file.id);
|
|
85
|
+
// Upload the CSV data to the newly created VibeIQ file
|
|
86
|
+
const fileDetails = {
|
|
87
|
+
contentType: 'text/csv',
|
|
88
|
+
};
|
|
89
|
+
await new Files().uploadFileAsStream(file.uploadPost, csvContent, fileDetails);
|
|
90
|
+
console.log('File uploaded.');
|
|
91
|
+
return file;
|
|
92
|
+
}
|
|
93
|
+
async function loadFile(config) {
|
|
94
|
+
const entities = new Entities();
|
|
95
|
+
// start a load job referencing the newly created file
|
|
96
|
+
console.log('Loading with config: ', config);
|
|
97
|
+
const loadJob = await entities.create({
|
|
98
|
+
entityName: 'loader-process',
|
|
99
|
+
object: Object.assign({}, config)
|
|
100
|
+
});
|
|
101
|
+
console.log('Load has been kicked off. loader-process ID: ', loadJob.id);
|
|
102
|
+
}
|
|
103
|
+
async function uploadAndLoadLocalFile(incomingFileName, configFileName) {
|
|
104
|
+
const file = await uploadFile(incomingFileName);
|
|
105
|
+
const config = await getLocalUploadConfig(configFileName);
|
|
106
|
+
const fullConfig = Object.assign({ fileLocation: file.id }, config);
|
|
107
|
+
await loadFile(fullConfig);
|
|
108
|
+
}
|
|
109
|
+
async function loadLocalFile(configFileName) {
|
|
110
|
+
const config = await getLocalUploadConfig(configFileName);
|
|
111
|
+
await loadFile(config);
|
|
112
|
+
}
|
|
113
|
+
function getFileExtension(fileName) {
|
|
114
|
+
let ext = '';
|
|
115
|
+
const parts = fileName === null || fileName === void 0 ? void 0 : fileName.split('.');
|
|
116
|
+
if ((parts === null || parts === void 0 ? void 0 : parts.length) > 1) {
|
|
117
|
+
ext = '.' + parts[(parts === null || parts === void 0 ? void 0 : parts.length) - 1];
|
|
118
|
+
}
|
|
119
|
+
return ext;
|
|
120
|
+
}
|
package/package.json
CHANGED
package/src/cli.ts
CHANGED
|
@@ -15,6 +15,7 @@ import { installApp, uninstallApp } from './apps/install-app/app-installer';
|
|
|
15
15
|
import { upgradeApp } from './apps/upgrade-app/app-upgrader';
|
|
16
16
|
import { cliInstallWorkflowTemplateDefinitions, listWorkflowTemplateDefinitions } from './workflow-template-definitions/workflow-template-definition-commands';
|
|
17
17
|
import { configureProject } from './projects/project-uploader';
|
|
18
|
+
import { Load, UploadAndLoad } from './loader-process/loader-process';
|
|
18
19
|
|
|
19
20
|
const cliUsage = require('command-line-usage');
|
|
20
21
|
|
|
@@ -130,7 +131,6 @@ export async function cli(args) {
|
|
|
130
131
|
}
|
|
131
132
|
break;
|
|
132
133
|
}
|
|
133
|
-
|
|
134
134
|
case 'colors': {
|
|
135
135
|
switch (command) {
|
|
136
136
|
case 'load': {
|
|
@@ -147,6 +147,22 @@ export async function cli(args) {
|
|
|
147
147
|
}
|
|
148
148
|
break;
|
|
149
149
|
}
|
|
150
|
+
case 'loader': {
|
|
151
|
+
switch (command) {
|
|
152
|
+
case 'uploadAndLoad': {
|
|
153
|
+
await UploadAndLoad(args);
|
|
154
|
+
break;
|
|
155
|
+
}
|
|
156
|
+
case 'load': {
|
|
157
|
+
await Load(args);
|
|
158
|
+
break;
|
|
159
|
+
}
|
|
160
|
+
default: {
|
|
161
|
+
printIllegalCommand();
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
break;
|
|
165
|
+
}
|
|
150
166
|
case 'projects': {
|
|
151
167
|
switch (command) {
|
|
152
168
|
case 'configure': {
|
|
@@ -291,6 +307,18 @@ const helpSections = [
|
|
|
291
307
|
// , {name: 'delete', summary: 'Delete all colors.'}
|
|
292
308
|
],
|
|
293
309
|
},
|
|
310
|
+
{
|
|
311
|
+
header: 'Loader Commands - Domain: loader',
|
|
312
|
+
content: [{
|
|
313
|
+
name: 'uploadAndLoad <File Path> <Config Path>',
|
|
314
|
+
summary: 'Upload a csv file and kick off a load job for the uploaded file. The file path must be a reference to a .csv file and the config path must be a reference to a .json or a .yml file.'
|
|
315
|
+
},
|
|
316
|
+
{
|
|
317
|
+
name: 'load <Config Path>',
|
|
318
|
+
summary: 'Upload a csv file and kick off a load job for the uploaded file. The config path must be a reference to a .json or a .yml file.'
|
|
319
|
+
}
|
|
320
|
+
],
|
|
321
|
+
},
|
|
294
322
|
{
|
|
295
323
|
header: 'Project Commands - Domain: projects',
|
|
296
324
|
content: [{
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
import { Entities, Files } from '@contrail/sdk';
|
|
2
|
+
import { authUser } from '../auth/login';
|
|
3
|
+
import chalk from 'chalk';
|
|
4
|
+
import * as fs from 'fs';
|
|
5
|
+
import { getSeparatorByPlatform } from '../common';
|
|
6
|
+
import yaml from 'js-yaml';
|
|
7
|
+
|
|
8
|
+
export async function UploadAndLoad(args) {
|
|
9
|
+
try {
|
|
10
|
+
await authUser();
|
|
11
|
+
console.log('%s Uploading file', chalk.yellow.bold('LOADER'));
|
|
12
|
+
const incomingFileName = args[3];
|
|
13
|
+
const configFileName = args[4];
|
|
14
|
+
|
|
15
|
+
await uploadAndLoadLocalFile(incomingFileName, configFileName);
|
|
16
|
+
console.log('%s Uploaded', chalk.yellow.bold('LOADER'));
|
|
17
|
+
|
|
18
|
+
}
|
|
19
|
+
catch (e) {
|
|
20
|
+
console.log(`%s Starting Load Failed. ${e}`, chalk.red.bold('FAIL'));
|
|
21
|
+
return;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
console.log('%s Starting Load Complete.', chalk.green.bold('COMPLETE'));
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export async function Load(args) {
|
|
28
|
+
try {
|
|
29
|
+
await authUser();
|
|
30
|
+
console.log('%s Uploading file', chalk.yellow.bold('LOADER'));
|
|
31
|
+
const configFileName = args[3];
|
|
32
|
+
|
|
33
|
+
await loadLocalFile(configFileName);
|
|
34
|
+
console.log('%s Uploaded', chalk.yellow.bold('LOADER'));
|
|
35
|
+
|
|
36
|
+
}
|
|
37
|
+
catch (e) {
|
|
38
|
+
console.log(`%s Starting Load Failed. ${e}`, chalk.red.bold('FAIL'));
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
console.log('%s Starting Load Complete.', chalk.green.bold('COMPLETE'));
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
async function getLocalFile(incomingFileName) {
|
|
46
|
+
|
|
47
|
+
const ext = getFileExtension(incomingFileName);
|
|
48
|
+
if (ext !== '.csv') {
|
|
49
|
+
throw new Error('Upload file must be a .csv');
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
const TARGET_DIR = process.cwd();
|
|
53
|
+
try {
|
|
54
|
+
const separator = getSeparatorByPlatform();
|
|
55
|
+
return fs.readFileSync(TARGET_DIR + separator + incomingFileName);
|
|
56
|
+
} catch (e) {
|
|
57
|
+
throw new Error(`ERROR LOADING CSV: ${e}`);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
async function getLocalUploadConfig(configFileName) {
|
|
62
|
+
|
|
63
|
+
const ext = getFileExtension(configFileName);
|
|
64
|
+
if (ext !== '.json' && ext !== '.yml') {
|
|
65
|
+
throw new Error('Upload file must be a .json or .yml');
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
const CURRENT_DIR = process.cwd();
|
|
69
|
+
const separator = getSeparatorByPlatform();
|
|
70
|
+
const fullPath = CURRENT_DIR + separator + configFileName;
|
|
71
|
+
console.log('Getting config from path: ', fullPath);
|
|
72
|
+
|
|
73
|
+
if (ext === '.yml') {
|
|
74
|
+
try {
|
|
75
|
+
const doc = yaml.load(fs.readFileSync(fullPath, 'utf8'));
|
|
76
|
+
return doc;
|
|
77
|
+
} catch (e) {
|
|
78
|
+
throw new Error(`ERROR LOADING UPLOAD CONFIGURATION FILE: ${e}`);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
try {
|
|
83
|
+
const doc = JSON.parse(fs.readFileSync(fullPath, 'utf8'));
|
|
84
|
+
return doc;
|
|
85
|
+
} catch (e) {
|
|
86
|
+
throw new Error(`ERROR LOADING UPLOAD CONFIGURATION FILE: ${e}`);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
async function uploadFile(incomingFileName) {
|
|
92
|
+
const csvContent = await getLocalFile(incomingFileName);
|
|
93
|
+
|
|
94
|
+
const entities = new Entities();
|
|
95
|
+
const fileName = `${incomingFileName.slice(0, incomingFileName.length - 5)}-Upload-${new Date().getTime()}.csv`;
|
|
96
|
+
const file = await entities.create({
|
|
97
|
+
entityName: 'file',
|
|
98
|
+
object: { contentType: 'text/csv', fileName: fileName, ttl: 24 * 60 * 60 * 1000 }
|
|
99
|
+
});
|
|
100
|
+
console.log('VibeIQ file ID:', file.id);
|
|
101
|
+
|
|
102
|
+
// Upload the CSV data to the newly created VibeIQ file
|
|
103
|
+
const fileDetails = {
|
|
104
|
+
contentType: 'text/csv',
|
|
105
|
+
};
|
|
106
|
+
await new Files().uploadFileAsStream(file.uploadPost, csvContent as any, fileDetails);
|
|
107
|
+
console.log('File uploaded.');
|
|
108
|
+
|
|
109
|
+
return file;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
async function loadFile(config) {
|
|
113
|
+
|
|
114
|
+
const entities = new Entities();
|
|
115
|
+
// start a load job referencing the newly created file
|
|
116
|
+
console.log('Loading with config: ', config);
|
|
117
|
+
const loadJob = await entities.create(
|
|
118
|
+
{
|
|
119
|
+
entityName: 'loader-process',
|
|
120
|
+
object: {
|
|
121
|
+
...config
|
|
122
|
+
}
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
console.log('Load has been kicked off. loader-process ID: ', loadJob.id);
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
async function uploadAndLoadLocalFile(incomingFileName, configFileName) {
|
|
129
|
+
const file = await uploadFile(incomingFileName);
|
|
130
|
+
const config = await getLocalUploadConfig(configFileName);
|
|
131
|
+
const fullConfig = {
|
|
132
|
+
fileLocation: file.id,
|
|
133
|
+
...config
|
|
134
|
+
};
|
|
135
|
+
await loadFile(fullConfig);
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
async function loadLocalFile(configFileName) {
|
|
139
|
+
const config = await getLocalUploadConfig(configFileName);
|
|
140
|
+
await loadFile(config);
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
function getFileExtension(fileName) {
|
|
144
|
+
let ext = '';
|
|
145
|
+
|
|
146
|
+
const parts = fileName?.split('.');
|
|
147
|
+
if (parts?.length > 1) {
|
|
148
|
+
ext = '.' + parts[parts?.length - 1];
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
return ext;
|
|
152
|
+
}
|