@squiz/dxp-cli-next 5.9.0 → 5.10.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/lib/__tests__/integration/main.spec.js +1 -0
- package/lib/datastore/blueprint/add/add.d.ts +3 -0
- package/lib/datastore/blueprint/add/add.js +109 -0
- package/lib/datastore/blueprint/add/add.spec.d.ts +1 -0
- package/lib/datastore/blueprint/add/add.spec.js +82 -0
- package/lib/datastore/blueprint/blueprintCommand.d.ts +3 -0
- package/lib/datastore/blueprint/blueprintCommand.js +21 -0
- package/lib/datastore/blueprint/list/list.d.ts +3 -0
- package/lib/datastore/blueprint/list/list.js +74 -0
- package/lib/datastore/blueprint/list/list.spec.d.ts +1 -0
- package/lib/datastore/blueprint/list/list.spec.js +50 -0
- package/lib/datastore/blueprint/rename/rename.d.ts +3 -0
- package/lib/datastore/blueprint/rename/rename.js +83 -0
- package/lib/datastore/blueprint/rename/rename.spec.d.ts +1 -0
- package/lib/datastore/blueprint/rename/rename.spec.js +92 -0
- package/lib/datastore/blueprint/update/update.d.ts +3 -0
- package/lib/datastore/blueprint/update/update.js +87 -0
- package/lib/datastore/blueprint/update/update.spec.d.ts +1 -0
- package/lib/datastore/blueprint/update/update.spec.js +99 -0
- package/lib/datastore/bundle/bundle.d.ts +3 -0
- package/lib/datastore/bundle/bundle.js +174 -0
- package/lib/datastore/bundle/bundle.spec.d.ts +1 -0
- package/lib/datastore/bundle/bundle.spec.js +93 -0
- package/lib/datastore/index.d.ts +3 -0
- package/lib/datastore/index.js +16 -0
- package/lib/datastore/simulator/add/add.d.ts +3 -0
- package/lib/datastore/simulator/add/add.js +138 -0
- package/lib/datastore/simulator/add/add.spec.d.ts +1 -0
- package/lib/datastore/simulator/add/add.spec.js +123 -0
- package/lib/datastore/simulator/remove/remove.d.ts +3 -0
- package/lib/datastore/simulator/remove/remove.js +68 -0
- package/lib/datastore/simulator/remove/remove.spec.d.ts +1 -0
- package/lib/datastore/simulator/remove/remove.spec.js +224 -0
- package/lib/datastore/simulator/simulatorCommand.d.ts +3 -0
- package/lib/datastore/simulator/simulatorCommand.js +17 -0
- package/lib/datastore/simulator/utils.d.ts +22 -0
- package/lib/datastore/simulator/utils.js +197 -0
- package/lib/datastore/simulator/utils.spec.d.ts +1 -0
- package/lib/datastore/simulator/utils.spec.js +165 -0
- package/lib/datastore/utils.d.ts +18 -0
- package/lib/datastore/utils.js +229 -0
- package/lib/datastore/utils.spec.d.ts +1 -0
- package/lib/datastore/utils.spec.js +92 -0
- package/lib/dxp.js +1 -0
- package/package.json +6 -4
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
19
|
+
if (mod && mod.__esModule) return mod;
|
|
20
|
+
var result = {};
|
|
21
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
22
|
+
__setModuleDefault(result, mod);
|
|
23
|
+
return result;
|
|
24
|
+
};
|
|
25
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
26
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
27
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
28
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
29
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
30
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
31
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
32
|
+
});
|
|
33
|
+
};
|
|
34
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
35
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
36
|
+
};
|
|
37
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
38
|
+
const add_1 = __importDefault(require("./add"));
|
|
39
|
+
const utils = __importStar(require("../utils"));
|
|
40
|
+
const logSpy = jest.spyOn(global.console, 'log');
|
|
41
|
+
jest.mock('fs', () => {
|
|
42
|
+
return {
|
|
43
|
+
existsSync: jest.fn().mockReturnValue(true),
|
|
44
|
+
};
|
|
45
|
+
});
|
|
46
|
+
describe('datastoreSimulatorAdd', () => {
|
|
47
|
+
it('correctly adds a simulator', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
48
|
+
const checkUpdateAvailableSpy = jest
|
|
49
|
+
.spyOn(utils, 'checkUpdateAvailable')
|
|
50
|
+
.mockImplementation(() => {
|
|
51
|
+
return Promise.resolve(null);
|
|
52
|
+
});
|
|
53
|
+
let executeCommandCount = 0;
|
|
54
|
+
const executeCommandSpy = jest
|
|
55
|
+
.spyOn(utils, 'executeCommand')
|
|
56
|
+
.mockImplementation((cmd, opt) => {
|
|
57
|
+
executeCommandCount++;
|
|
58
|
+
switch (executeCommandCount) {
|
|
59
|
+
case 1:
|
|
60
|
+
expect(cmd).toStrictEqual('docker -v');
|
|
61
|
+
return Promise.resolve('Docker version 20.10.23, build 7155243');
|
|
62
|
+
case 2:
|
|
63
|
+
expect(cmd).toStrictEqual('docker ps -a --format "~{{.Labels}}~" --filter "name=datastore-sim-*"');
|
|
64
|
+
return Promise.resolve(`\~blueprint=/Users/pnolland/Documents/Work/GitRepos/blueprints/boilerplate2/api.yaml,desktop.docker.io/binds/0/Source=/Users/pnolland/Documents/Work/GitRepos/blueprints/boilerplate2,desktop.docker.io/binds/0/SourceKind=hostFile,desktop.docker.io/binds/0/Target=/var/www/instances,port=8085,squiz.datastore.version=4.0.1~
|
|
65
|
+
~desktop.docker.io/binds/0/SourceKind=hostFile,desktop.docker.io/binds/0/Target=/var/www/instances,port=7002,squiz.datastore.version=4.0.1,blueprint=/Users/pnolland/Documents/Work/GitRepos/blueprints/boilerplate/api.yaml,desktop.docker.io/binds/0/Source=/Users/pnolland/Documents/Work/GitRepos/blueprints/boilerplate~
|
|
66
|
+
~desktop.docker.io/binds/0/Target=/var/www/instances,port=7001,squiz.datastore.version=4.0.1,blueprint=/Users/pnolland/Documents/Work/GitRepos/datastore/apps/js-sdk/tests/test-project/api.yaml,desktop.docker.io/binds/0/Source=/Users/pnolland/Documents/Work/GitRepos/datastore/apps/js-sdk/tests/test-project,desktop.docker.io/binds/0/SourceKind=hostFile~`);
|
|
67
|
+
case 3:
|
|
68
|
+
expect(cmd).toStrictEqual('docker run -l "blueprint=/path/to/blueprint.yaml" -l "port=9999" -itd --name datastore-sim-119726bb -p 0.0.0.0:9999:80 -e MYHOST=0.0.0.0 -e MYPORT=9999 -e BLUEPRINT=/path/to/blueprint.yaml -v "/path/to":/var/www/instances squizdxp/datastore:latest');
|
|
69
|
+
return Promise.resolve('');
|
|
70
|
+
case 4:
|
|
71
|
+
expect(cmd).toStrictEqual('docker exec -i datastore-sim-119726bb install simulator:blueprint.yaml --output=json');
|
|
72
|
+
return Promise.resolve(JSON.stringify([
|
|
73
|
+
{
|
|
74
|
+
URL: 'http://0.0.0.0:9999',
|
|
75
|
+
jwtURL: 'http://0.0.0.0:9999/__JWT/issueToken',
|
|
76
|
+
},
|
|
77
|
+
]));
|
|
78
|
+
case 5:
|
|
79
|
+
expect(cmd).toStrictEqual('docker image inspect squizdxp/datastore:latest --format "{{ index .RepoDigests }}"');
|
|
80
|
+
return Promise.resolve('[squizdxp/datastore@sha256:bd61f8f80d9f235d81477454cf512a6edede0ae6d2d0a8c0508956db2418dbe0]');
|
|
81
|
+
case 6:
|
|
82
|
+
expect(cmd).toStrictEqual('docker image inspect squizdxp/datastore:latest --format \'{{ or (index .Config.Labels "squiz.datastore.version") (printf "Unknown") }}\'');
|
|
83
|
+
return Promise.resolve('4.0.1');
|
|
84
|
+
case 7:
|
|
85
|
+
expect(cmd).toStrictEqual(`docker exec -i datastore-sim-119726bb bash -c "echo '${JSON.stringify({
|
|
86
|
+
blueprint: '/path/to/blueprint.yaml',
|
|
87
|
+
container: 'datastore-sim-119726bb',
|
|
88
|
+
imageDigest: 'sha256:bd61f8f80d9f235d81477454cf512a6edede0ae6d2d0a8c0508956db2418dbe0',
|
|
89
|
+
imageVersion: '4.0.1',
|
|
90
|
+
jwt: 'http://0.0.0.0:9999/__JWT/issueToken',
|
|
91
|
+
url: 'http://0.0.0.0:9999',
|
|
92
|
+
}, null, 4).replace(/"/g, '\\"')}' > /var/www/data/containerData.json"`);
|
|
93
|
+
return Promise.resolve('');
|
|
94
|
+
}
|
|
95
|
+
return Promise.reject(false);
|
|
96
|
+
});
|
|
97
|
+
process.env.ENABLE_OVERRIDE_DATASTORE_URL = 'true';
|
|
98
|
+
const program = (0, add_1.default)();
|
|
99
|
+
yield program.parseAsync([
|
|
100
|
+
'node',
|
|
101
|
+
'dxp-cli',
|
|
102
|
+
'datastore',
|
|
103
|
+
'simulator',
|
|
104
|
+
'add',
|
|
105
|
+
'-p',
|
|
106
|
+
'9999',
|
|
107
|
+
'-b',
|
|
108
|
+
'/path/to/blueprint.yaml',
|
|
109
|
+
'-i',
|
|
110
|
+
'squizdxp/datastoreDev',
|
|
111
|
+
]);
|
|
112
|
+
const opts = program.opts();
|
|
113
|
+
expect(opts.port).toEqual('9999');
|
|
114
|
+
expect(opts.image).toEqual('squizdxp/datastoreDev');
|
|
115
|
+
expect(checkUpdateAvailableSpy).toHaveBeenCalledTimes(1);
|
|
116
|
+
expect(logSpy).toHaveBeenCalledTimes(5);
|
|
117
|
+
expect(logSpy).toHaveBeenCalledWith('');
|
|
118
|
+
expect(logSpy).toHaveBeenCalledWith('');
|
|
119
|
+
expect(logSpy).toHaveBeenCalledWith(' URL: http://0.0.0.0:9999');
|
|
120
|
+
expect(logSpy).toHaveBeenCalledWith(' JWT URL: http://0.0.0.0:9999/__JWT/issueToken');
|
|
121
|
+
expect(logSpy).toHaveBeenCalledWith('');
|
|
122
|
+
}));
|
|
123
|
+
});
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
12
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
13
|
+
};
|
|
14
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
+
const commander_1 = require("commander");
|
|
16
|
+
const chalk_1 = __importDefault(require("chalk"));
|
|
17
|
+
const ora_1 = __importDefault(require("ora"));
|
|
18
|
+
const utils_1 = require("../../utils");
|
|
19
|
+
const utils_2 = require("../utils");
|
|
20
|
+
const createRemoveCommand = () => {
|
|
21
|
+
const removeCommand = new commander_1.Command('remove')
|
|
22
|
+
.name('remove')
|
|
23
|
+
.description('Removes a datastore simulator')
|
|
24
|
+
.addOption(new commander_1.Option('-b, --blueprint <string>', 'Path to your datastore API yaml file.').makeOptionMandatory())
|
|
25
|
+
.addOption(new commander_1.Option('-f, --force', 'Force the removal of the datastore simulator'))
|
|
26
|
+
.configureOutput({
|
|
27
|
+
outputError(str, write) {
|
|
28
|
+
write(chalk_1.default.red(str));
|
|
29
|
+
},
|
|
30
|
+
})
|
|
31
|
+
.action((options) => __awaiter(void 0, void 0, void 0, function* () {
|
|
32
|
+
console.log('');
|
|
33
|
+
const spinner = (0, ora_1.default)();
|
|
34
|
+
try {
|
|
35
|
+
yield (0, utils_2.checkUpdateAvailable)();
|
|
36
|
+
yield (0, utils_2.checkDockerInstalled)();
|
|
37
|
+
const forceMessage = 'Removing a simulator can not be undone. Are you sure you want to continue? (y/N)';
|
|
38
|
+
if (!options.force) {
|
|
39
|
+
if ((yield (0, utils_2.forcePrompt)(forceMessage, false)) === false) {
|
|
40
|
+
const removeGuide = `To remove run:\n $ dxp-next datastore simulator remove --blueprint ${options.blueprint} --force\n`;
|
|
41
|
+
throw new Error(removeGuide);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
spinner.start('Removing simulator blueprint.');
|
|
45
|
+
const { fullPath, dirPath, yamlFile, containerName } = (0, utils_2.getSimulatorDetails)(options.blueprint);
|
|
46
|
+
const containerCommand = yield (0, utils_2.executeCommand)(`docker ps -a --filter "name=${containerName}" --format "{{.Names}}"`);
|
|
47
|
+
if (containerCommand === '') {
|
|
48
|
+
throw new Error('Sorry, no simulator container found for that blueprint path. Please try again using a different path.');
|
|
49
|
+
}
|
|
50
|
+
try {
|
|
51
|
+
yield (0, utils_2.executeCommand)(`docker rm -f ${containerName}`);
|
|
52
|
+
}
|
|
53
|
+
catch (error) {
|
|
54
|
+
(0, utils_1.logDebug)(`ERROR: ${JSON.stringify(error)}`);
|
|
55
|
+
throw new Error('Unable to remove simulator.');
|
|
56
|
+
}
|
|
57
|
+
spinner.succeed(`Done! Completely removed container ID "${containerName}".`);
|
|
58
|
+
return;
|
|
59
|
+
}
|
|
60
|
+
catch (error) {
|
|
61
|
+
(0, utils_1.logDebug)(`ERROR: ${JSON.stringify(error)}`);
|
|
62
|
+
spinner.fail();
|
|
63
|
+
(0, utils_1.handleCommandError)(removeCommand, error);
|
|
64
|
+
}
|
|
65
|
+
}));
|
|
66
|
+
return removeCommand;
|
|
67
|
+
};
|
|
68
|
+
exports.default = createRemoveCommand;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,224 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
19
|
+
if (mod && mod.__esModule) return mod;
|
|
20
|
+
var result = {};
|
|
21
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
22
|
+
__setModuleDefault(result, mod);
|
|
23
|
+
return result;
|
|
24
|
+
};
|
|
25
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
26
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
27
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
28
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
29
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
30
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
31
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
32
|
+
});
|
|
33
|
+
};
|
|
34
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
35
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
36
|
+
};
|
|
37
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
38
|
+
const remove_1 = __importDefault(require("./remove"));
|
|
39
|
+
const utils = __importStar(require("../utils"));
|
|
40
|
+
const chalk_1 = __importDefault(require("chalk"));
|
|
41
|
+
const logSpy = jest.spyOn(global.console, 'log');
|
|
42
|
+
const exitSpy = jest.spyOn(process, 'exit').mockImplementation(() => {
|
|
43
|
+
return undefined;
|
|
44
|
+
}); // prevent process exit on error
|
|
45
|
+
beforeEach(() => {
|
|
46
|
+
jest.resetAllMocks();
|
|
47
|
+
});
|
|
48
|
+
describe('datastoreSimulatorRemove', () => {
|
|
49
|
+
it('should not remove a simulator if prompt returns false', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
50
|
+
const checkUpdateAvailableSpy = jest
|
|
51
|
+
.spyOn(utils, 'checkUpdateAvailable')
|
|
52
|
+
.mockImplementation(() => {
|
|
53
|
+
return Promise.resolve(null);
|
|
54
|
+
});
|
|
55
|
+
const forcePromptSpy = jest
|
|
56
|
+
.spyOn(utils, 'forcePrompt')
|
|
57
|
+
.mockResolvedValue(false);
|
|
58
|
+
let executeCommandCount = 0;
|
|
59
|
+
const executeCommandSpy = jest
|
|
60
|
+
.spyOn(utils, 'executeCommand')
|
|
61
|
+
.mockImplementation((cmd, opt) => {
|
|
62
|
+
executeCommandCount++;
|
|
63
|
+
switch (executeCommandCount) {
|
|
64
|
+
case 1:
|
|
65
|
+
expect(cmd).toStrictEqual('docker -v');
|
|
66
|
+
return Promise.resolve('Docker version 20.10.23, build 7155243');
|
|
67
|
+
}
|
|
68
|
+
return Promise.reject(false);
|
|
69
|
+
});
|
|
70
|
+
const program = (0, remove_1.default)();
|
|
71
|
+
const commandErrorSpy = jest.spyOn(program, 'error');
|
|
72
|
+
yield program.parseAsync([
|
|
73
|
+
'node',
|
|
74
|
+
'dxp-cli',
|
|
75
|
+
'datastore',
|
|
76
|
+
'simulator',
|
|
77
|
+
'remove',
|
|
78
|
+
'-b',
|
|
79
|
+
'/path/to/blueprint.yaml',
|
|
80
|
+
]);
|
|
81
|
+
const opts = program.opts();
|
|
82
|
+
expect(opts.blueprint).toEqual('/path/to/blueprint.yaml');
|
|
83
|
+
expect(checkUpdateAvailableSpy).toHaveBeenCalledTimes(1);
|
|
84
|
+
expect(commandErrorSpy).toHaveBeenCalledWith(chalk_1.default.red(`To remove run:
|
|
85
|
+
$ dxp-next datastore simulator remove --blueprint /path/to/blueprint.yaml --force
|
|
86
|
+
`));
|
|
87
|
+
expect(forcePromptSpy).toHaveBeenCalledWith('Removing a simulator can not be undone. Are you sure you want to continue? (y/N)', false);
|
|
88
|
+
expect(logSpy).toHaveBeenCalledTimes(1);
|
|
89
|
+
expect(executeCommandSpy).toHaveBeenCalledTimes(1);
|
|
90
|
+
}));
|
|
91
|
+
it('should remove a simulator if prompt returns true', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
92
|
+
const checkUpdateAvailableSpy = jest
|
|
93
|
+
.spyOn(utils, 'checkUpdateAvailable')
|
|
94
|
+
.mockImplementation(() => {
|
|
95
|
+
return Promise.resolve(null);
|
|
96
|
+
});
|
|
97
|
+
const forcePromptSpy = jest
|
|
98
|
+
.spyOn(utils, 'forcePrompt')
|
|
99
|
+
.mockResolvedValue(true);
|
|
100
|
+
let executeCommandCount = 0;
|
|
101
|
+
const executeCommandSpy = jest
|
|
102
|
+
.spyOn(utils, 'executeCommand')
|
|
103
|
+
.mockImplementation((cmd, opt) => {
|
|
104
|
+
executeCommandCount++;
|
|
105
|
+
switch (executeCommandCount) {
|
|
106
|
+
case 1:
|
|
107
|
+
expect(cmd).toStrictEqual('docker -v');
|
|
108
|
+
return Promise.resolve('Docker version 20.10.23, build 7155243');
|
|
109
|
+
case 2:
|
|
110
|
+
expect(cmd).toStrictEqual('docker ps -a --filter "name=datastore-sim-119726bb" --format "{{.Names}}"');
|
|
111
|
+
return Promise.resolve('datastore-sim-119726bb');
|
|
112
|
+
case 3:
|
|
113
|
+
expect(cmd).toStrictEqual('docker rm -f datastore-sim-119726bb');
|
|
114
|
+
return Promise.resolve('');
|
|
115
|
+
}
|
|
116
|
+
return Promise.reject(false);
|
|
117
|
+
});
|
|
118
|
+
const program = (0, remove_1.default)();
|
|
119
|
+
const commandErrorSpy = jest.spyOn(program, 'error');
|
|
120
|
+
yield program.parseAsync([
|
|
121
|
+
'node',
|
|
122
|
+
'dxp-cli',
|
|
123
|
+
'datastore',
|
|
124
|
+
'simulator',
|
|
125
|
+
'remove',
|
|
126
|
+
'-b',
|
|
127
|
+
'/path/to/blueprint.yaml',
|
|
128
|
+
]);
|
|
129
|
+
const opts = program.opts();
|
|
130
|
+
expect(opts.blueprint).toEqual('/path/to/blueprint.yaml');
|
|
131
|
+
expect(checkUpdateAvailableSpy).toHaveBeenCalledTimes(1);
|
|
132
|
+
expect(commandErrorSpy).not.toHaveBeenCalled();
|
|
133
|
+
expect(forcePromptSpy).toHaveBeenCalledWith('Removing a simulator can not be undone. Are you sure you want to continue? (y/N)', false);
|
|
134
|
+
expect(logSpy).toHaveBeenCalledTimes(1);
|
|
135
|
+
expect(executeCommandSpy).toHaveBeenCalledTimes(3);
|
|
136
|
+
}));
|
|
137
|
+
it('should remove a simulator if --force set', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
138
|
+
const checkUpdateAvailableSpy = jest
|
|
139
|
+
.spyOn(utils, 'checkUpdateAvailable')
|
|
140
|
+
.mockImplementation(() => {
|
|
141
|
+
return Promise.resolve(null);
|
|
142
|
+
});
|
|
143
|
+
const forcePromptSpy = jest
|
|
144
|
+
.spyOn(utils, 'forcePrompt')
|
|
145
|
+
.mockResolvedValue(true);
|
|
146
|
+
let executeCommandCount = 0;
|
|
147
|
+
const executeCommandSpy = jest
|
|
148
|
+
.spyOn(utils, 'executeCommand')
|
|
149
|
+
.mockImplementation((cmd, opt) => {
|
|
150
|
+
executeCommandCount++;
|
|
151
|
+
switch (executeCommandCount) {
|
|
152
|
+
case 1:
|
|
153
|
+
expect(cmd).toStrictEqual('docker -v');
|
|
154
|
+
return Promise.resolve('Docker version 20.10.23, build 7155243');
|
|
155
|
+
case 2:
|
|
156
|
+
expect(cmd).toStrictEqual('docker ps -a --filter "name=datastore-sim-119726bb" --format "{{.Names}}"');
|
|
157
|
+
return Promise.resolve('datastore-sim-119726bb');
|
|
158
|
+
case 3:
|
|
159
|
+
expect(cmd).toStrictEqual('docker rm -f datastore-sim-119726bb');
|
|
160
|
+
return Promise.resolve('');
|
|
161
|
+
}
|
|
162
|
+
return Promise.reject(false);
|
|
163
|
+
});
|
|
164
|
+
const program = (0, remove_1.default)();
|
|
165
|
+
const commandErrorSpy = jest.spyOn(program, 'error');
|
|
166
|
+
yield program.parseAsync([
|
|
167
|
+
'node',
|
|
168
|
+
'dxp-cli',
|
|
169
|
+
'datastore',
|
|
170
|
+
'simulator',
|
|
171
|
+
'remove',
|
|
172
|
+
'-b',
|
|
173
|
+
'/path/to/blueprint.yaml',
|
|
174
|
+
'--force',
|
|
175
|
+
]);
|
|
176
|
+
const opts = program.opts();
|
|
177
|
+
expect(opts.blueprint).toEqual('/path/to/blueprint.yaml');
|
|
178
|
+
expect(checkUpdateAvailableSpy).toHaveBeenCalledTimes(1);
|
|
179
|
+
expect(commandErrorSpy).not.toHaveBeenCalled();
|
|
180
|
+
expect(forcePromptSpy).not.toHaveBeenCalled();
|
|
181
|
+
expect(logSpy).toHaveBeenCalledTimes(1);
|
|
182
|
+
expect(executeCommandSpy).toHaveBeenCalledTimes(3);
|
|
183
|
+
}));
|
|
184
|
+
it('should not remove a simulator if no matching simulator found', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
185
|
+
const checkUpdateAvailableSpy = jest
|
|
186
|
+
.spyOn(utils, 'checkUpdateAvailable')
|
|
187
|
+
.mockImplementation(() => {
|
|
188
|
+
return Promise.resolve(null);
|
|
189
|
+
});
|
|
190
|
+
let executeCommandCount = 0;
|
|
191
|
+
const executeCommandSpy = jest
|
|
192
|
+
.spyOn(utils, 'executeCommand')
|
|
193
|
+
.mockImplementation((cmd, opt) => {
|
|
194
|
+
executeCommandCount++;
|
|
195
|
+
switch (executeCommandCount) {
|
|
196
|
+
case 1:
|
|
197
|
+
expect(cmd).toStrictEqual('docker -v');
|
|
198
|
+
return Promise.resolve('Docker version 20.10.23, build 7155243');
|
|
199
|
+
case 2:
|
|
200
|
+
expect(cmd).toStrictEqual('docker ps -a --filter "name=datastore-sim-119726bb" --format "{{.Names}}"');
|
|
201
|
+
return Promise.resolve('');
|
|
202
|
+
}
|
|
203
|
+
return Promise.reject(false);
|
|
204
|
+
});
|
|
205
|
+
const program = (0, remove_1.default)();
|
|
206
|
+
const commandErrorSpy = jest.spyOn(program, 'error');
|
|
207
|
+
yield program.parseAsync([
|
|
208
|
+
'node',
|
|
209
|
+
'dxp-cli',
|
|
210
|
+
'datastore',
|
|
211
|
+
'simulator',
|
|
212
|
+
'remove',
|
|
213
|
+
'-b',
|
|
214
|
+
'/path/to/blueprint.yaml',
|
|
215
|
+
'--force',
|
|
216
|
+
]);
|
|
217
|
+
const opts = program.opts();
|
|
218
|
+
expect(opts.blueprint).toEqual('/path/to/blueprint.yaml');
|
|
219
|
+
expect(checkUpdateAvailableSpy).toHaveBeenCalledTimes(1);
|
|
220
|
+
expect(commandErrorSpy).toHaveBeenCalledWith(chalk_1.default.red('Sorry, no simulator container found for that blueprint path. Please try again using a different path.'));
|
|
221
|
+
expect(logSpy).toHaveBeenCalledTimes(1);
|
|
222
|
+
expect(executeCommandSpy).toHaveBeenCalledTimes(2);
|
|
223
|
+
}));
|
|
224
|
+
});
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
const commander_1 = require("commander");
|
|
7
|
+
const add_1 = __importDefault(require("./add/add"));
|
|
8
|
+
const remove_1 = __importDefault(require("./remove/remove"));
|
|
9
|
+
const createSimulatorCommand = () => {
|
|
10
|
+
const datastoreSimulatorCommand = new commander_1.Command('simulator');
|
|
11
|
+
datastoreSimulatorCommand
|
|
12
|
+
.description('Datastore Simulator Commands')
|
|
13
|
+
.addCommand((0, add_1.default)())
|
|
14
|
+
.addCommand((0, remove_1.default)());
|
|
15
|
+
return datastoreSimulatorCommand;
|
|
16
|
+
};
|
|
17
|
+
exports.default = createSimulatorCommand;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
declare type datastoreVersionCache = {
|
|
2
|
+
digest: string;
|
|
3
|
+
updatedAt: number;
|
|
4
|
+
version: string;
|
|
5
|
+
};
|
|
6
|
+
export declare const datastoreRepo = "squizdxp/datastore:latest";
|
|
7
|
+
export declare const allowedExtensions: string[];
|
|
8
|
+
export declare const host = "0.0.0.0";
|
|
9
|
+
export declare const availablePorts: string[];
|
|
10
|
+
export declare const executeCommand: (cmd: string, opts?: any) => Promise<unknown>;
|
|
11
|
+
export declare function stringHashShort(value: string): string;
|
|
12
|
+
export declare const promptForContinue: (versionCache: datastoreVersionCache, currentVersion: string) => Promise<boolean>;
|
|
13
|
+
export declare const forcePrompt: (message: string, def?: boolean) => Promise<boolean>;
|
|
14
|
+
export declare function checkDockerInstalled(): Promise<void>;
|
|
15
|
+
export declare const checkUpdateAvailable: () => Promise<null>;
|
|
16
|
+
export declare function getSimulatorDetails(blueprint: string): {
|
|
17
|
+
fullPath: string;
|
|
18
|
+
dirPath: string;
|
|
19
|
+
yamlFile: string;
|
|
20
|
+
containerName: string;
|
|
21
|
+
};
|
|
22
|
+
export {};
|
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
19
|
+
if (mod && mod.__esModule) return mod;
|
|
20
|
+
var result = {};
|
|
21
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
22
|
+
__setModuleDefault(result, mod);
|
|
23
|
+
return result;
|
|
24
|
+
};
|
|
25
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
26
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
27
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
28
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
29
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
30
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
31
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
32
|
+
});
|
|
33
|
+
};
|
|
34
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
35
|
+
exports.getSimulatorDetails = exports.checkUpdateAvailable = exports.checkDockerInstalled = exports.forcePrompt = exports.promptForContinue = exports.stringHashShort = exports.executeCommand = exports.availablePorts = exports.host = exports.allowedExtensions = exports.datastoreRepo = void 0;
|
|
36
|
+
const child_process_1 = require("child_process");
|
|
37
|
+
const ApplicationStore_1 = require("../../ApplicationStore");
|
|
38
|
+
const ApiService_1 = require("../../ApiService");
|
|
39
|
+
const utils_1 = require("../utils");
|
|
40
|
+
const path_1 = require("path");
|
|
41
|
+
const datastoreSimulatorCache = {
|
|
42
|
+
name: 'datastore-simulator',
|
|
43
|
+
type: 'data',
|
|
44
|
+
};
|
|
45
|
+
exports.datastoreRepo = 'squizdxp/datastore:latest';
|
|
46
|
+
exports.allowedExtensions = ['yaml', 'yml'];
|
|
47
|
+
exports.host = '0.0.0.0';
|
|
48
|
+
exports.availablePorts = [
|
|
49
|
+
'7001',
|
|
50
|
+
'7002',
|
|
51
|
+
'7003',
|
|
52
|
+
'7004',
|
|
53
|
+
'7005',
|
|
54
|
+
'7006',
|
|
55
|
+
'7007',
|
|
56
|
+
'7008',
|
|
57
|
+
'7009',
|
|
58
|
+
'7010',
|
|
59
|
+
];
|
|
60
|
+
const dockerAPI = 'https://registry.hub.docker.com/v2/repositories/squizdxp/datastore/tags?page_size=3';
|
|
61
|
+
const executeCommand = (cmd, opts = {}) => __awaiter(void 0, void 0, void 0, function* () {
|
|
62
|
+
return new Promise(function (resolve, reject) {
|
|
63
|
+
(0, child_process_1.exec)(cmd, opts, (err, stdout, stderr) => {
|
|
64
|
+
if (err) {
|
|
65
|
+
reject(err);
|
|
66
|
+
}
|
|
67
|
+
else {
|
|
68
|
+
resolve(stdout);
|
|
69
|
+
}
|
|
70
|
+
});
|
|
71
|
+
});
|
|
72
|
+
});
|
|
73
|
+
exports.executeCommand = executeCommand;
|
|
74
|
+
function stringHashShort(value) {
|
|
75
|
+
return value
|
|
76
|
+
.split('')
|
|
77
|
+
.reduce((prevHash, currVal) => ((prevHash << 5) - prevHash + currVal.charCodeAt(0)) | 0, 0)
|
|
78
|
+
.toString(16)
|
|
79
|
+
.replace('-', '');
|
|
80
|
+
}
|
|
81
|
+
exports.stringHashShort = stringHashShort;
|
|
82
|
+
const promptForContinue = (versionCache, currentVersion) => __awaiter(void 0, void 0, void 0, function* () {
|
|
83
|
+
const inquirer = yield Promise.resolve().then(() => __importStar(require('inquirer')));
|
|
84
|
+
const confirm = yield inquirer.default.prompt([
|
|
85
|
+
{
|
|
86
|
+
default: false,
|
|
87
|
+
message: 'A new version of the Datastore simulator is available ' +
|
|
88
|
+
`(${currentVersion} -> ${versionCache.version}). ` +
|
|
89
|
+
'Would you like to upgrade now? (y/N)',
|
|
90
|
+
name: 'skip',
|
|
91
|
+
type: 'confirm',
|
|
92
|
+
},
|
|
93
|
+
]);
|
|
94
|
+
return confirm.skip;
|
|
95
|
+
});
|
|
96
|
+
exports.promptForContinue = promptForContinue;
|
|
97
|
+
const forcePrompt = (message, def = false) => __awaiter(void 0, void 0, void 0, function* () {
|
|
98
|
+
console.info('WHY!!!!!');
|
|
99
|
+
const inquirer = yield Promise.resolve().then(() => __importStar(require('inquirer')));
|
|
100
|
+
const confirm = yield inquirer.default.prompt([
|
|
101
|
+
{
|
|
102
|
+
default: def,
|
|
103
|
+
message,
|
|
104
|
+
name: 'skip',
|
|
105
|
+
type: 'confirm',
|
|
106
|
+
},
|
|
107
|
+
]);
|
|
108
|
+
return confirm.skip;
|
|
109
|
+
});
|
|
110
|
+
exports.forcePrompt = forcePrompt;
|
|
111
|
+
function checkDockerInstalled() {
|
|
112
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
113
|
+
try {
|
|
114
|
+
yield (0, exports.executeCommand)('docker -v');
|
|
115
|
+
}
|
|
116
|
+
catch (error) {
|
|
117
|
+
throw new Error('Docker not installed. Please install latest version.');
|
|
118
|
+
}
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
exports.checkDockerInstalled = checkDockerInstalled;
|
|
122
|
+
const checkUpdateAvailable = () => __awaiter(void 0, void 0, void 0, function* () {
|
|
123
|
+
let simulatorVersionCmd = `docker image inspect ${exports.datastoreRepo}`;
|
|
124
|
+
simulatorVersionCmd +=
|
|
125
|
+
' --format \'{{ or (index .Config.Labels "squiz.datastore.version") (printf "Unknown") }}\'';
|
|
126
|
+
// Default updatedAt to over 1 hour ago to force a check
|
|
127
|
+
const versionCache = JSON.parse((yield (0, ApplicationStore_1.getApplicationFile)(datastoreSimulatorCache)) ||
|
|
128
|
+
`{"updatedAt": ${Math.floor(Date.now() / 1000 - 7200)}}`);
|
|
129
|
+
let refreshVersionCache = false;
|
|
130
|
+
let versionInfo = versionCache;
|
|
131
|
+
let latestImage;
|
|
132
|
+
let taggedImage;
|
|
133
|
+
if (typeof process.env.DXP_DATASTORE_SIMULATOR_SKIP_VERSION_CHECK ===
|
|
134
|
+
'string' &&
|
|
135
|
+
process.env.DXP_DATASTORE_SIMULATOR_SKIP_VERSION_CHECK) {
|
|
136
|
+
return null;
|
|
137
|
+
}
|
|
138
|
+
else {
|
|
139
|
+
const nowAt = Math.floor(Date.now() / 1000);
|
|
140
|
+
if (nowAt - versionCache.updatedAt > 3600) {
|
|
141
|
+
refreshVersionCache = true;
|
|
142
|
+
}
|
|
143
|
+
if (refreshVersionCache === true) {
|
|
144
|
+
const apiService = new ApiService_1.ApiService(utils_1.validateAxiosStatus);
|
|
145
|
+
apiService.client.interceptors.request.clear();
|
|
146
|
+
apiService.client.interceptors.response.clear();
|
|
147
|
+
const dockerFetch = yield apiService.client.get(dockerAPI);
|
|
148
|
+
const dockerResponse = dockerFetch.data;
|
|
149
|
+
latestImage = dockerResponse.results.filter((image) => {
|
|
150
|
+
return image.name === 'latest';
|
|
151
|
+
})[0];
|
|
152
|
+
taggedImage = dockerResponse.results[1];
|
|
153
|
+
versionInfo = {
|
|
154
|
+
digest: latestImage.images[0].digest || '',
|
|
155
|
+
updatedAt: Date.now() / 1000,
|
|
156
|
+
version: taggedImage.name || '',
|
|
157
|
+
};
|
|
158
|
+
yield (0, ApplicationStore_1.saveApplicationFile)(datastoreSimulatorCache, JSON.stringify(versionInfo));
|
|
159
|
+
}
|
|
160
|
+
let result;
|
|
161
|
+
try {
|
|
162
|
+
result = yield (0, exports.executeCommand)(`docker image inspect ${exports.datastoreRepo} --format "{{ index .RepoDigests }}"`);
|
|
163
|
+
if (versionInfo.digest !== '' &&
|
|
164
|
+
result.slice(20).startsWith(versionInfo.digest) === false) {
|
|
165
|
+
const version = yield (0, exports.executeCommand)(simulatorVersionCmd);
|
|
166
|
+
const currentVersion = version.replace(/\r?\n|\r/g, '');
|
|
167
|
+
const upgradeGuide = 'To upgrade run:\n $ dxp-next datastore simulator upgrade\n';
|
|
168
|
+
if ((yield (0, exports.promptForContinue)(versionInfo, currentVersion)) === true) {
|
|
169
|
+
throw new Error(upgradeGuide);
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
catch (error) {
|
|
174
|
+
if (error.message.includes('No such image')) {
|
|
175
|
+
result = '';
|
|
176
|
+
}
|
|
177
|
+
else {
|
|
178
|
+
throw new Error(error.message);
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
return null;
|
|
183
|
+
});
|
|
184
|
+
exports.checkUpdateAvailable = checkUpdateAvailable;
|
|
185
|
+
function getSimulatorDetails(blueprint) {
|
|
186
|
+
const fullPath = (0, path_1.resolve)(blueprint);
|
|
187
|
+
const dirPath = (0, path_1.dirname)(fullPath);
|
|
188
|
+
const yamlFile = (0, path_1.basename)(fullPath);
|
|
189
|
+
const containerName = `datastore-sim-${stringHashShort(fullPath)}`;
|
|
190
|
+
return {
|
|
191
|
+
fullPath,
|
|
192
|
+
dirPath,
|
|
193
|
+
yamlFile,
|
|
194
|
+
containerName,
|
|
195
|
+
};
|
|
196
|
+
}
|
|
197
|
+
exports.getSimulatorDetails = getSimulatorDetails;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|