@itentialopensource/adapter-kafkav2 0.3.12
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/.eslintignore +6 -0
- package/.eslintrc.js +18 -0
- package/.gitlab/.gitkeep +0 -0
- package/.gitlab/issue_templates/.gitkeep +0 -0
- package/.gitlab/issue_templates/Default.md +17 -0
- package/.gitlab/issue_templates/bugReportTemplate.md +76 -0
- package/.gitlab/issue_templates/featureRequestTemplate.md +14 -0
- package/.jshintrc +0 -0
- package/CHANGELOG.md +152 -0
- package/CODE_OF_CONDUCT.md +48 -0
- package/CONTRIBUTING.md +158 -0
- package/LICENSE +201 -0
- package/README.md +380 -0
- package/Release_Notes.md +0 -0
- package/adapter.js +814 -0
- package/error.json +178 -0
- package/package.json +71 -0
- package/pronghorn.json +44 -0
- package/propertiesSchema.json +198 -0
- package/refs?service=git-upload-pack +0 -0
- package/sampleProperties.json +41 -0
- package/test/integration/adapterTestIntegration.js +445 -0
- package/test/unit/adapterTestUnit.js +412 -0
- package/utils/artifactize.js +146 -0
- package/utils/packModificationScript.js +35 -0
- package/utils/pre-commit.sh +27 -0
- package/utils/setup.js +33 -0
- package/utils/testRunner.js +298 -0
- package/workflows/kafka_test.json +1 -0
|
@@ -0,0 +1,412 @@
|
|
|
1
|
+
/* @copyright Itential, LLC 2019 (pre-modifications) */
|
|
2
|
+
|
|
3
|
+
// Set globals
|
|
4
|
+
/* global describe it log pronghornProps */
|
|
5
|
+
/* eslint global-require:warn */
|
|
6
|
+
/* eslint no-unused-vars: warn */
|
|
7
|
+
|
|
8
|
+
// include required items for testing & logging
|
|
9
|
+
const assert = require('assert');
|
|
10
|
+
const fs = require('fs-extra');
|
|
11
|
+
const mocha = require('mocha');
|
|
12
|
+
const path = require('path');
|
|
13
|
+
const util = require('util');
|
|
14
|
+
const winston = require('winston');
|
|
15
|
+
const execute = require('child_process').execSync;
|
|
16
|
+
const { expect } = require('chai');
|
|
17
|
+
const { use } = require('chai');
|
|
18
|
+
const td = require('testdouble');
|
|
19
|
+
|
|
20
|
+
const anything = td.matchers.anything();
|
|
21
|
+
|
|
22
|
+
// stub and attemptTimeout are used throughout the code so set them here
|
|
23
|
+
let logLevel = 'none';
|
|
24
|
+
const stub = true;
|
|
25
|
+
const isRapidFail = false;
|
|
26
|
+
const attemptTimeout = 120000;
|
|
27
|
+
|
|
28
|
+
// these variables can be changed to run in integrated mode so easier to set them here
|
|
29
|
+
// always check these in with bogus data!!!
|
|
30
|
+
const host = 'replace.hostorip.here';
|
|
31
|
+
const username = 'username';
|
|
32
|
+
const password = 'password';
|
|
33
|
+
const port = 80;
|
|
34
|
+
const sslenable = false;
|
|
35
|
+
const sslinvalid = false;
|
|
36
|
+
|
|
37
|
+
// these are the adapter properties. You generally should not need to alter
|
|
38
|
+
// any of these after they are initially set up
|
|
39
|
+
global.pronghornProps = {
|
|
40
|
+
pathProps: {
|
|
41
|
+
encrypted: false
|
|
42
|
+
},
|
|
43
|
+
adapterProps: {
|
|
44
|
+
adapters: [{
|
|
45
|
+
id: 'Test-kafkav2',
|
|
46
|
+
type: 'Kafkav2',
|
|
47
|
+
interval_time: 5000,
|
|
48
|
+
stub: true,
|
|
49
|
+
properties: {
|
|
50
|
+
topics: []
|
|
51
|
+
}
|
|
52
|
+
}]
|
|
53
|
+
}
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
global.$HOME = `${__dirname}/../..`;
|
|
57
|
+
|
|
58
|
+
// set the log levels that Pronghorn uses, spam and trace are not defaulted in so without
|
|
59
|
+
// this you may error on log.trace calls.
|
|
60
|
+
const myCustomLevels = {
|
|
61
|
+
levels: {
|
|
62
|
+
spam: 6,
|
|
63
|
+
trace: 5,
|
|
64
|
+
debug: 4,
|
|
65
|
+
info: 3,
|
|
66
|
+
warn: 2,
|
|
67
|
+
error: 1,
|
|
68
|
+
none: 0
|
|
69
|
+
}
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
// need to see if there is a log level passed in
|
|
73
|
+
process.argv.forEach((val) => {
|
|
74
|
+
// is there a log level defined to be passed in?
|
|
75
|
+
if (val.indexOf('--LOG') === 0) {
|
|
76
|
+
// get the desired log level
|
|
77
|
+
const inputVal = val.split('=')[1];
|
|
78
|
+
|
|
79
|
+
// validate the log level is supported, if so set it
|
|
80
|
+
if (Object.hasOwnProperty.call(myCustomLevels.levels, inputVal)) {
|
|
81
|
+
logLevel = inputVal;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
// need to set global logging
|
|
87
|
+
global.log = winston.createLogger({
|
|
88
|
+
level: logLevel,
|
|
89
|
+
levels: myCustomLevels.levels,
|
|
90
|
+
transports: [
|
|
91
|
+
new winston.transports.Console()
|
|
92
|
+
]
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Runs the error asserts for the test
|
|
97
|
+
*/
|
|
98
|
+
function runErrorAsserts(data, error, code, origin, displayStr) {
|
|
99
|
+
assert.equal(null, data);
|
|
100
|
+
assert.notEqual(undefined, error);
|
|
101
|
+
assert.notEqual(null, error);
|
|
102
|
+
assert.notEqual(undefined, error.IAPerror);
|
|
103
|
+
assert.notEqual(null, error.IAPerror);
|
|
104
|
+
assert.notEqual(undefined, error.IAPerror.displayString);
|
|
105
|
+
assert.notEqual(null, error.IAPerror.displayString);
|
|
106
|
+
assert.equal(code, error.icode);
|
|
107
|
+
assert.equal(origin, error.IAPerror.origin);
|
|
108
|
+
assert.equal(displayStr, error.IAPerror.displayString);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
// require the adapter that we are going to be using
|
|
112
|
+
const Kafkav2 = require('../../adapter');
|
|
113
|
+
|
|
114
|
+
// delete the .DS_Store directory in entities -- otherwise this will cause errors
|
|
115
|
+
const dirPath = path.join(__dirname, '../../entities/.DS_Store');
|
|
116
|
+
if (fs.existsSync(dirPath)) {
|
|
117
|
+
try {
|
|
118
|
+
fs.removeSync(dirPath);
|
|
119
|
+
console.log('.DS_Store deleted');
|
|
120
|
+
} catch (e) {
|
|
121
|
+
console.log('Error when deleting .DS_Store:', e);
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
// begin the testing - these should be pretty well defined between the describe and the it!
|
|
126
|
+
describe('[unit] Kafka Adapter Test', () => {
|
|
127
|
+
describe('Kafka Class Tests', () => {
|
|
128
|
+
const a = new Kafkav2(
|
|
129
|
+
pronghornProps.adapterProps.adapters[0].id,
|
|
130
|
+
pronghornProps.adapterProps.adapters[0].properties
|
|
131
|
+
);
|
|
132
|
+
|
|
133
|
+
if (isRapidFail) {
|
|
134
|
+
const state = {};
|
|
135
|
+
state.passed = true;
|
|
136
|
+
|
|
137
|
+
mocha.afterEach(function x() {
|
|
138
|
+
state.passed = state.passed
|
|
139
|
+
&& (this.currentTest.state === 'passed');
|
|
140
|
+
});
|
|
141
|
+
mocha.beforeEach(function x() {
|
|
142
|
+
if (!state.passed) {
|
|
143
|
+
return this.currentTest.skip();
|
|
144
|
+
}
|
|
145
|
+
return true;
|
|
146
|
+
});
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
describe('#class instance created', () => {
|
|
150
|
+
it('should be a class with properties', (done) => {
|
|
151
|
+
assert.notEqual(null, a);
|
|
152
|
+
assert.notEqual(undefined, a);
|
|
153
|
+
const check = global.pronghornProps.adapterProps.adapters[0].id;
|
|
154
|
+
assert.equal(check, a.id);
|
|
155
|
+
done();
|
|
156
|
+
}).timeout(attemptTimeout);
|
|
157
|
+
});
|
|
158
|
+
|
|
159
|
+
let wffunctions = [];
|
|
160
|
+
describe('#getWorkflowFunctions', () => {
|
|
161
|
+
it('should retrieve workflow functions', (done) => {
|
|
162
|
+
wffunctions = a.getWorkflowFunctions();
|
|
163
|
+
assert.notEqual(0, wffunctions.length);
|
|
164
|
+
done();
|
|
165
|
+
}).timeout(attemptTimeout);
|
|
166
|
+
});
|
|
167
|
+
|
|
168
|
+
describe('package.json', () => {
|
|
169
|
+
it('should have a package.json', (done) => {
|
|
170
|
+
fs.exists('package.json', (val) => {
|
|
171
|
+
assert.equal(true, val);
|
|
172
|
+
done();
|
|
173
|
+
});
|
|
174
|
+
});
|
|
175
|
+
it('package.json should be validated', (done) => {
|
|
176
|
+
const packageDotJson = require('../../package.json');
|
|
177
|
+
const { PJV } = require('package-json-validator');
|
|
178
|
+
const options = {
|
|
179
|
+
warnings: true, // show warnings
|
|
180
|
+
recommendations: true // show recommendations
|
|
181
|
+
};
|
|
182
|
+
const results = PJV.validate(JSON.stringify(packageDotJson), 'npm', options);
|
|
183
|
+
|
|
184
|
+
if (results.valid === false) {
|
|
185
|
+
log.error('The package.json contains the following errors: ');
|
|
186
|
+
log.error(util.inspect(results));
|
|
187
|
+
assert.equal(true, results.valid);
|
|
188
|
+
} else {
|
|
189
|
+
assert.equal(true, results.valid);
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
done();
|
|
193
|
+
});
|
|
194
|
+
it('package.json should be customized', (done) => {
|
|
195
|
+
const packageDotJson = require('../../package.json');
|
|
196
|
+
assert.notEqual(-1, packageDotJson.name.indexOf('kafkav2'));
|
|
197
|
+
assert.notEqual(undefined, packageDotJson.version);
|
|
198
|
+
assert.notEqual(null, packageDotJson.version);
|
|
199
|
+
assert.notEqual('', packageDotJson.version);
|
|
200
|
+
done();
|
|
201
|
+
});
|
|
202
|
+
});
|
|
203
|
+
|
|
204
|
+
describe('pronghorn.json', () => {
|
|
205
|
+
it('should have a pronghorn.json', (done) => {
|
|
206
|
+
fs.exists('pronghorn.json', (val) => {
|
|
207
|
+
assert.equal(true, val);
|
|
208
|
+
done();
|
|
209
|
+
});
|
|
210
|
+
});
|
|
211
|
+
it('pronghorn.json should be customized', (done) => {
|
|
212
|
+
const pronghornDotJson = require('../../pronghorn.json');
|
|
213
|
+
assert.notEqual(-1, pronghornDotJson.id.indexOf('kafkav2'));
|
|
214
|
+
assert.equal('Kafkav2', pronghornDotJson.export);
|
|
215
|
+
assert.equal('Kafkav2', pronghornDotJson.displayName);
|
|
216
|
+
assert.equal('Kafkav2', pronghornDotJson.title);
|
|
217
|
+
done();
|
|
218
|
+
});
|
|
219
|
+
it('pronghorn.json should only expose workflow functions', (done) => {
|
|
220
|
+
const pronghornDotJson = require('../../pronghorn.json');
|
|
221
|
+
|
|
222
|
+
for (let m = 0; m < pronghornDotJson.methods.length; m += 1) {
|
|
223
|
+
let found = false;
|
|
224
|
+
let paramissue = false;
|
|
225
|
+
|
|
226
|
+
for (let w = 0; w < wffunctions.length; w += 1) {
|
|
227
|
+
if (pronghornDotJson.methods[m].name === wffunctions[w]) {
|
|
228
|
+
found = true;
|
|
229
|
+
const methLine = execute(`grep "${wffunctions[w]}(" adapter.js | grep "callback) {"`).toString();
|
|
230
|
+
let wfparams = [];
|
|
231
|
+
|
|
232
|
+
if (methLine.indexOf('(') >= 0 && methLine.indexOf(')') >= 0) {
|
|
233
|
+
const temp = methLine.substring(methLine.indexOf('(') + 1, methLine.indexOf(')'));
|
|
234
|
+
wfparams = temp.split(',');
|
|
235
|
+
|
|
236
|
+
for (let t = 0; t < wfparams.length; t += 1) {
|
|
237
|
+
// remove default value from the parameter name
|
|
238
|
+
wfparams[t] = wfparams[t].substring(0, wfparams[t].search(/=/) > 0 ? wfparams[t].search(/#|\?|=/) : wfparams[t].length);
|
|
239
|
+
// remove spaces
|
|
240
|
+
wfparams[t] = wfparams[t].trim();
|
|
241
|
+
|
|
242
|
+
if (wfparams[t] === 'callback') {
|
|
243
|
+
wfparams.splice(t, 1);
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
// if there are inputs defined but not on the method line
|
|
249
|
+
if (wfparams.length === 0 && (pronghornDotJson.methods[m].input
|
|
250
|
+
&& pronghornDotJson.methods[m].input.length > 0)) {
|
|
251
|
+
paramissue = true;
|
|
252
|
+
} else if (wfparams.length > 0 && (!pronghornDotJson.methods[m].input
|
|
253
|
+
|| pronghornDotJson.methods[m].input.length === 0)) {
|
|
254
|
+
// if there are no inputs defined but there are on the method line
|
|
255
|
+
paramissue = true;
|
|
256
|
+
} else {
|
|
257
|
+
for (let p = 0; p < pronghornDotJson.methods[m].input.length; p += 1) {
|
|
258
|
+
let pfound = false;
|
|
259
|
+
for (let wfp = 0; wfp < wfparams.length; wfp += 1) {
|
|
260
|
+
if (pronghornDotJson.methods[m].input[p].name.toUpperCase() === wfparams[wfp].toUpperCase()) {
|
|
261
|
+
pfound = true;
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
if (!pfound) {
|
|
266
|
+
paramissue = true;
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
for (let wfp = 0; wfp < wfparams.length; wfp += 1) {
|
|
270
|
+
let pfound = false;
|
|
271
|
+
for (let p = 0; p < pronghornDotJson.methods[m].input.length; p += 1) {
|
|
272
|
+
if (pronghornDotJson.methods[m].input[p].name.toUpperCase() === wfparams[wfp].toUpperCase()) {
|
|
273
|
+
pfound = true;
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
if (!pfound) {
|
|
278
|
+
paramissue = true;
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
break;
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
if (!found) {
|
|
288
|
+
// this is the reason to go through both loops - log which ones are not found so
|
|
289
|
+
// they can be worked
|
|
290
|
+
log.error(`${pronghornDotJson.methods[m].name} not found in workflow functions`);
|
|
291
|
+
}
|
|
292
|
+
if (paramissue) {
|
|
293
|
+
// this is the reason to go through both loops - log which ones are not found so
|
|
294
|
+
// they can be worked
|
|
295
|
+
log.error(`${pronghornDotJson.methods[m].name} has a parameter mismatch`);
|
|
296
|
+
}
|
|
297
|
+
assert.equal(true, found);
|
|
298
|
+
assert.equal(false, paramissue);
|
|
299
|
+
}
|
|
300
|
+
done();
|
|
301
|
+
}).timeout(attemptTimeout);
|
|
302
|
+
it('pronghorn.json should expose all workflow functions', (done) => {
|
|
303
|
+
const pronghornDotJson = require('../../pronghorn.json');
|
|
304
|
+
for (let w = 0; w < wffunctions.length; w += 1) {
|
|
305
|
+
let found = false;
|
|
306
|
+
|
|
307
|
+
for (let m = 0; m < pronghornDotJson.methods.length; m += 1) {
|
|
308
|
+
if (pronghornDotJson.methods[m].name === wffunctions[w]) {
|
|
309
|
+
found = true;
|
|
310
|
+
break;
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
if (!found) {
|
|
315
|
+
// this is the reason to go through both loops - log which ones are not found so
|
|
316
|
+
// they can be worked
|
|
317
|
+
log.error(`${wffunctions[w]} not found in pronghorn.json`);
|
|
318
|
+
}
|
|
319
|
+
assert.equal(true, found);
|
|
320
|
+
}
|
|
321
|
+
done();
|
|
322
|
+
});
|
|
323
|
+
});
|
|
324
|
+
|
|
325
|
+
describe('propertiesSchema.json', () => {
|
|
326
|
+
it('should have a propertiesSchema.json', (done) => {
|
|
327
|
+
fs.exists('propertiesSchema.json', (val) => {
|
|
328
|
+
assert.equal(true, val);
|
|
329
|
+
done();
|
|
330
|
+
});
|
|
331
|
+
});
|
|
332
|
+
it('propertiesSchema.json should be customized', (done) => {
|
|
333
|
+
const propertiesDotJson = require('../../propertiesSchema.json');
|
|
334
|
+
assert.equal('adapter-kafkav2', propertiesDotJson.$id);
|
|
335
|
+
done();
|
|
336
|
+
});
|
|
337
|
+
});
|
|
338
|
+
|
|
339
|
+
describe('error.json', () => {
|
|
340
|
+
it('should have an error.json', (done) => {
|
|
341
|
+
fs.exists('error.json', (val) => {
|
|
342
|
+
assert.equal(true, val);
|
|
343
|
+
done();
|
|
344
|
+
});
|
|
345
|
+
});
|
|
346
|
+
});
|
|
347
|
+
|
|
348
|
+
describe('README.md', () => {
|
|
349
|
+
it('should have a README', (done) => {
|
|
350
|
+
fs.exists('README.md', (val) => {
|
|
351
|
+
assert.equal(true, val);
|
|
352
|
+
done();
|
|
353
|
+
});
|
|
354
|
+
});
|
|
355
|
+
it('README.md should be customized', (done) => {
|
|
356
|
+
fs.readFile('README.md', 'utf8', (err, data) => {
|
|
357
|
+
assert.equal(-1, data.indexOf('[System]'));
|
|
358
|
+
assert.equal(-1, data.indexOf('[system]'));
|
|
359
|
+
assert.equal(-1, data.indexOf('[version]'));
|
|
360
|
+
assert.equal(-1, data.indexOf('[namespace]'));
|
|
361
|
+
done();
|
|
362
|
+
});
|
|
363
|
+
});
|
|
364
|
+
});
|
|
365
|
+
|
|
366
|
+
describe('#connect', () => {
|
|
367
|
+
it('should have a connect function', (done) => {
|
|
368
|
+
assert.equal(true, typeof a.connect === 'function');
|
|
369
|
+
done();
|
|
370
|
+
});
|
|
371
|
+
});
|
|
372
|
+
|
|
373
|
+
describe('#healthCheck', () => {
|
|
374
|
+
it('should have a healthCheck function', (done) => {
|
|
375
|
+
assert.equal(true, typeof a.healthCheck === 'function');
|
|
376
|
+
done();
|
|
377
|
+
});
|
|
378
|
+
});
|
|
379
|
+
|
|
380
|
+
/*
|
|
381
|
+
-----------------------------------------------------------------------
|
|
382
|
+
-----------------------------------------------------------------------
|
|
383
|
+
*** All code above this comment will be replaced during a migration ***
|
|
384
|
+
******************* DO NOT REMOVE THIS COMMENT BLOCK ******************
|
|
385
|
+
-----------------------------------------------------------------------
|
|
386
|
+
-----------------------------------------------------------------------
|
|
387
|
+
*/
|
|
388
|
+
describe('#sendMessage - errors', () => {
|
|
389
|
+
it('should have a sendMessage function', (done) => {
|
|
390
|
+
assert.equal(true, typeof a.sendMessage === 'function');
|
|
391
|
+
done();
|
|
392
|
+
});
|
|
393
|
+
it('should error on sendMessage - no payloads', (done) => {
|
|
394
|
+
try {
|
|
395
|
+
a.sendMessage(null, (data, error) => {
|
|
396
|
+
try {
|
|
397
|
+
const displayE = 'payloads is required';
|
|
398
|
+
runErrorAsserts(data, error, 'AD.300', 'Test-kafkav2-adapter-sendMessage', displayE);
|
|
399
|
+
done();
|
|
400
|
+
} catch (ex) {
|
|
401
|
+
log.error(`Test Failure: ${ex}`);
|
|
402
|
+
done(ex);
|
|
403
|
+
}
|
|
404
|
+
});
|
|
405
|
+
} catch (exc) {
|
|
406
|
+
log.error(`Adapter Exception: ${exc}`);
|
|
407
|
+
done(exc);
|
|
408
|
+
}
|
|
409
|
+
}).timeout(attemptTimeout);
|
|
410
|
+
});
|
|
411
|
+
});
|
|
412
|
+
});
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/* @copyright Itential, LLC 2019 */
|
|
3
|
+
|
|
4
|
+
const fs = require('fs-extra');
|
|
5
|
+
const path = require('path');
|
|
6
|
+
|
|
7
|
+
async function createBundle(adapterOldDir) {
|
|
8
|
+
// set directories
|
|
9
|
+
const artifactDir = path.join(adapterOldDir, '../artifactTemp');
|
|
10
|
+
const workflowsDir = path.join(adapterOldDir, 'workflows');
|
|
11
|
+
|
|
12
|
+
// read adapter's package and set names
|
|
13
|
+
const adapterPackage = fs.readJSONSync(path.join(adapterOldDir, 'package.json'));
|
|
14
|
+
const originalName = adapterPackage.name.substring(adapterPackage.name.lastIndexOf('/') + 1);
|
|
15
|
+
const shortenedName = originalName.replace('adapter-', '');
|
|
16
|
+
const artifactName = originalName.replace('adapter', 'bundled-adapter');
|
|
17
|
+
|
|
18
|
+
const adapterNewDir = path.join(artifactDir, 'bundles', 'adapters', originalName);
|
|
19
|
+
fs.ensureDirSync(adapterNewDir);
|
|
20
|
+
|
|
21
|
+
const ops = [];
|
|
22
|
+
|
|
23
|
+
// copy old adapterDir to bundled hierarchy location
|
|
24
|
+
ops.push(() => fs.copySync(adapterOldDir, adapterNewDir));
|
|
25
|
+
|
|
26
|
+
// copy readme
|
|
27
|
+
ops.push(() => fs.copySync(path.join(adapterOldDir, 'README.md'), path.join(artifactDir, 'README.md')));
|
|
28
|
+
|
|
29
|
+
// copy changelog
|
|
30
|
+
if (fs.existsSync(path.join(adapterOldDir, 'CHANGELOG.md'))) {
|
|
31
|
+
ops.push(() => fs.copySync(path.join(adapterOldDir, 'CHANGELOG.md'), path.join(artifactDir, 'CHANGELOG.md')));
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
// copy license
|
|
35
|
+
if (fs.existsSync(path.join(adapterOldDir, 'LICENSE'))) {
|
|
36
|
+
ops.push(() => fs.copySync(path.join(adapterOldDir, 'LICENSE'), path.join(artifactDir, 'LICENSE')));
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
// create package
|
|
40
|
+
const artifactPackage = {
|
|
41
|
+
name: artifactName,
|
|
42
|
+
version: adapterPackage.version,
|
|
43
|
+
description: `A bundled version of the ${originalName} to be used in adapter-artifacts for easy installation`,
|
|
44
|
+
scripts: {
|
|
45
|
+
test: 'echo "Error: no test specified" && exit 1',
|
|
46
|
+
deploy: 'npm publish --registry=http://registry.npmjs.org'
|
|
47
|
+
},
|
|
48
|
+
keywords: [
|
|
49
|
+
'IAP',
|
|
50
|
+
'artifacts',
|
|
51
|
+
'Itential',
|
|
52
|
+
'Pronghorn',
|
|
53
|
+
'Adapter',
|
|
54
|
+
'Adapter-Artifacts',
|
|
55
|
+
shortenedName
|
|
56
|
+
],
|
|
57
|
+
author: 'Itential Artifacts',
|
|
58
|
+
license: 'Apache-2.0',
|
|
59
|
+
repository: adapterPackage.repository,
|
|
60
|
+
private: false,
|
|
61
|
+
devDependencies: {
|
|
62
|
+
r2: '^2.0.1',
|
|
63
|
+
ajv: '6.10.0',
|
|
64
|
+
'better-ajv-errors': '^0.6.1',
|
|
65
|
+
'fs-extra': '^7.0.1'
|
|
66
|
+
}
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
ops.push(() => fs.writeJSONSync(path.join(artifactDir, 'package.json'), artifactPackage, { spaces: 2 }));
|
|
70
|
+
|
|
71
|
+
// create manifest
|
|
72
|
+
const manifest = {
|
|
73
|
+
bundleName: originalName,
|
|
74
|
+
version: adapterPackage.version,
|
|
75
|
+
fingerprint: 'Some verifiable token',
|
|
76
|
+
createdEpoch: '1554836984020',
|
|
77
|
+
artifacts: [
|
|
78
|
+
{
|
|
79
|
+
id: `${shortenedName}-adapter`,
|
|
80
|
+
name: `${shortenedName}-adapter`,
|
|
81
|
+
type: 'adapter',
|
|
82
|
+
location: `/bundles/adapters/${originalName}`,
|
|
83
|
+
description: artifactPackage.description,
|
|
84
|
+
properties: {
|
|
85
|
+
entryPoint: false
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
]
|
|
89
|
+
};
|
|
90
|
+
|
|
91
|
+
// add workflows into artifact
|
|
92
|
+
if (fs.existsSync(workflowsDir)) {
|
|
93
|
+
const workflowFileNames = fs.readdirSync(workflowsDir);
|
|
94
|
+
|
|
95
|
+
// if folder isnt empty and only file is not readme
|
|
96
|
+
if (workflowFileNames.length !== 0 && (!(workflowFileNames.length === 1 && workflowFileNames[0].split('.')[1] === 'md'))) {
|
|
97
|
+
// add workflows to correct location in bundle
|
|
98
|
+
ops.push(() => fs.copySync(workflowsDir, path.join(artifactDir, 'bundles', 'workflows')));
|
|
99
|
+
|
|
100
|
+
// add workflows to manifest
|
|
101
|
+
workflowFileNames.forEach((filename) => {
|
|
102
|
+
const [filenameNoExt, ext] = filename.split('.');
|
|
103
|
+
if (ext === 'json') {
|
|
104
|
+
manifest.artifacts.push({
|
|
105
|
+
id: `workflow-${filenameNoExt}`,
|
|
106
|
+
name: filenameNoExt,
|
|
107
|
+
type: 'workflow',
|
|
108
|
+
location: `/bundles/workflows/${filename}`,
|
|
109
|
+
description: 'Main entry point to artifact',
|
|
110
|
+
properties: {
|
|
111
|
+
entryPoint: false
|
|
112
|
+
}
|
|
113
|
+
});
|
|
114
|
+
}
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
ops.push(() => fs.writeJSONSync(path.join(artifactDir, 'manifest.json'), manifest, { spaces: 2 }));
|
|
120
|
+
|
|
121
|
+
// Run the commands in parallel
|
|
122
|
+
try {
|
|
123
|
+
await Promise.all(ops.map(async (op) => op()));
|
|
124
|
+
} catch (e) {
|
|
125
|
+
throw new Error(e);
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
const pathObj = {
|
|
129
|
+
bundlePath: artifactDir,
|
|
130
|
+
bundledAdapterPath: path.join(artifactDir, 'bundles', 'adapters', originalName)
|
|
131
|
+
};
|
|
132
|
+
return pathObj;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
async function artifactize(entryPathToAdapter) {
|
|
136
|
+
const truePath = path.resolve(entryPathToAdapter);
|
|
137
|
+
const packagePath = path.join(truePath, 'package');
|
|
138
|
+
// remove adapter from package and move bundle in
|
|
139
|
+
const pathObj = await createBundle(packagePath);
|
|
140
|
+
const { bundlePath } = pathObj;
|
|
141
|
+
fs.removeSync(packagePath);
|
|
142
|
+
fs.moveSync(bundlePath, packagePath);
|
|
143
|
+
return 'Bundle successfully created and old folder system removed';
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
module.exports = { createBundle, artifactize };
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/* @copyright Itential, LLC 2019 */
|
|
3
|
+
|
|
4
|
+
const fs = require('fs-extra');
|
|
5
|
+
const path = require('path');
|
|
6
|
+
const { spawnSync } = require('child_process');
|
|
7
|
+
const { createBundle } = require('./artifactize');
|
|
8
|
+
|
|
9
|
+
const nodeEntryPath = path.resolve('.');
|
|
10
|
+
createBundle(nodeEntryPath).then((pathObj) => {
|
|
11
|
+
const { bundlePath, bundledAdapterPath } = pathObj;
|
|
12
|
+
const npmIgnorePath = path.join(bundledAdapterPath, '.npmignore');
|
|
13
|
+
const adapterPackagePath = path.join(bundledAdapterPath, 'package.json');
|
|
14
|
+
const artifactPackagePath = path.join(bundlePath, 'package.json');
|
|
15
|
+
|
|
16
|
+
// remove node_modules from .npmIgnore so that node_modules are included in the resulting tar from npm pack
|
|
17
|
+
let npmIgnoreString;
|
|
18
|
+
if (fs.existsSync(npmIgnorePath)) {
|
|
19
|
+
npmIgnoreString = fs.readFileSync(npmIgnorePath, 'utf8');
|
|
20
|
+
npmIgnoreString = npmIgnoreString.replace('node_modules', '');
|
|
21
|
+
npmIgnoreString = npmIgnoreString.replace('\n\n', '\n');
|
|
22
|
+
fs.writeFileSync(npmIgnorePath, npmIgnoreString);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
// add files to package so that node_modules are included in the resulting tar from npm pack
|
|
26
|
+
const adapterPackage = fs.readJSONSync(adapterPackagePath);
|
|
27
|
+
adapterPackage.files = ['*'];
|
|
28
|
+
fs.writeJSONSync(artifactPackagePath, adapterPackage, { spaces: 2 });
|
|
29
|
+
const npmResult = spawnSync('npm', ['pack', '-q', bundlePath], { cwd: path.resolve(bundlePath, '..') });
|
|
30
|
+
if (npmResult.status === 0) {
|
|
31
|
+
fs.removeSync(bundlePath);
|
|
32
|
+
console.log('Bundle folder removed');
|
|
33
|
+
}
|
|
34
|
+
console.log('Script successful');
|
|
35
|
+
});
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
#!/bin/sh
|
|
2
|
+
# @copyright Itential, LLC 2019
|
|
3
|
+
|
|
4
|
+
#exit on any failure in the pipeline
|
|
5
|
+
set -e
|
|
6
|
+
|
|
7
|
+
# --------------------------------------------------
|
|
8
|
+
# pre-commit
|
|
9
|
+
# --------------------------------------------------
|
|
10
|
+
# Contains the standard set of tasks to runbefore
|
|
11
|
+
# committing changes to the repo. If any tasks fail
|
|
12
|
+
# then the commit will be aborted.
|
|
13
|
+
# --------------------------------------------------
|
|
14
|
+
|
|
15
|
+
printf "%b" "Running pre-commit hooks...\\n"
|
|
16
|
+
|
|
17
|
+
# verify testing script is stubbed and no credentials
|
|
18
|
+
# node utils/testRunner.js -r
|
|
19
|
+
|
|
20
|
+
# security audit on the code
|
|
21
|
+
npm audit --registry=https://registry.npmjs.org --audit-level=moderate
|
|
22
|
+
|
|
23
|
+
# lint the code
|
|
24
|
+
npm run lint
|
|
25
|
+
|
|
26
|
+
# test the code
|
|
27
|
+
npm run test
|
package/utils/setup.js
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/* @copyright Itential, LLC 2019 */
|
|
3
|
+
|
|
4
|
+
const fs = require('fs');
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* This script will execute before an npm install command. The purpose is to
|
|
8
|
+
* write out some standard git hooks that will enable folks working on this
|
|
9
|
+
* project to benefit from the protections that the hooks provide.
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
const precommit = fs.readFileSync('utils/pre-commit.sh', 'utf8');
|
|
13
|
+
|
|
14
|
+
fs.stat('.git', (err) => {
|
|
15
|
+
if (err == null) {
|
|
16
|
+
// git repo, not an npm repo.
|
|
17
|
+
// add pre-commit hook if it doesn't exist
|
|
18
|
+
fs.stat('.git/hooks/pre-commit', (statErr) => {
|
|
19
|
+
if (statErr == null || statErr.code === 'ENOENT') {
|
|
20
|
+
fs.writeFile('.git/hooks/pre-commit', precommit, {
|
|
21
|
+
mode: 0o755
|
|
22
|
+
}, (writeErr) => {
|
|
23
|
+
if (writeErr) {
|
|
24
|
+
return console.log(writeErr.message);
|
|
25
|
+
}
|
|
26
|
+
return null;
|
|
27
|
+
});
|
|
28
|
+
} else {
|
|
29
|
+
console.log(statErr.message);
|
|
30
|
+
}
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
});
|