@adobe/aio-cli-plugin-api-mesh 3.4.0 → 3.5.0-beta.1
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/oclif.manifest.json +1 -1
- package/package.json +7 -5
- package/src/commands/__fixtures__/env_invalid +2 -8
- package/src/commands/__fixtures__/sample_secrets_mesh.json +18 -0
- package/src/commands/__fixtures__/secrets_invalid.yaml +3 -0
- package/src/commands/__fixtures__/secrets_valid.yaml +2 -0
- package/src/commands/__fixtures__/secrets_with_batch_variables.yaml +4 -0
- package/src/commands/api-mesh/__tests__/create.test.js +316 -5
- package/src/commands/api-mesh/__tests__/run.test.js +146 -7
- package/src/commands/api-mesh/create.js +21 -1
- package/src/commands/api-mesh/run.js +17 -0
- package/src/commands/api-mesh/update.js +33 -7
- package/src/helpers.js +21 -0
- package/src/lib/devConsole.js +48 -0
- package/src/server.js +7 -0
- package/src/serverUtils.js +21 -0
- package/src/utils.js +149 -60
package/oclif.manifest.json
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":"3.
|
|
1
|
+
{"version":"3.5.0-beta.1","commands":{"PLUGINNAME":{"id":"PLUGINNAME","description":"Your description here","pluginName":"@adobe/aio-cli-plugin-api-mesh","pluginType":"core","aliases":[],"examples":["$ aio PLUGINNAME:some_command"],"flags":{"someflag":{"name":"someflag","type":"option","char":"f","description":"this is some flag"}},"args":[]},"api-mesh:create":{"id":"api-mesh:create","description":"Create a mesh with the given config.","pluginName":"@adobe/aio-cli-plugin-api-mesh","pluginType":"core","aliases":[],"flags":{"ignoreCache":{"name":"ignoreCache","type":"boolean","char":"i","description":"Ignore cache and force manual org -> project -> workspace selection","allowNo":false},"autoConfirmAction":{"name":"autoConfirmAction","type":"boolean","char":"c","description":"Auto confirm action prompt. CLI will not check for user approval before executing the action.","allowNo":false},"json":{"name":"json","type":"boolean","description":"Output JSON","allowNo":false},"env":{"name":"env","type":"option","char":"e","description":"Path to env file","default":".env"},"secrets":{"name":"secrets","type":"option","char":"s","description":"Path to secrets file","default":false}},"args":[{"name":"file"}]},"api-mesh:delete":{"id":"api-mesh:delete","description":"Delete the config of a given mesh","pluginName":"@adobe/aio-cli-plugin-api-mesh","pluginType":"core","aliases":[],"flags":{"ignoreCache":{"name":"ignoreCache","type":"boolean","char":"i","description":"Ignore cache and force manual org -> project -> workspace selection","allowNo":false},"autoConfirmAction":{"name":"autoConfirmAction","type":"boolean","char":"c","description":"Auto confirm action prompt. CLI will not check for user approval before executing the action.","allowNo":false}},"args":[]},"api-mesh:describe":{"id":"api-mesh:describe","description":"Get details of a mesh","pluginName":"@adobe/aio-cli-plugin-api-mesh","pluginType":"core","aliases":[],"flags":{"ignoreCache":{"name":"ignoreCache","type":"boolean","char":"i","description":"Ignore cache and force manual org -> project -> workspace selection","allowNo":false}},"args":[]},"api-mesh:get":{"id":"api-mesh:get","description":"Get the config of a given mesh","pluginName":"@adobe/aio-cli-plugin-api-mesh","pluginType":"core","aliases":[],"flags":{"ignoreCache":{"name":"ignoreCache","type":"boolean","char":"i","description":"Ignore cache and force manual org -> project -> workspace selection","allowNo":false},"json":{"name":"json","type":"boolean","description":"Output JSON","allowNo":false}},"args":[{"name":"file"}]},"api-mesh:init":{"id":"api-mesh:init","description":"This command will create a workspace where you can organise your API mesh configuration and other files","pluginName":"@adobe/aio-cli-plugin-api-mesh","pluginType":"core","aliases":[],"examples":[{"description":"API mesh workspace init","command":"aio api-mesh init commerce-mesh"},{"description":"API mesh workspace init with flags","command":"aio api-mesh init commerce-mesh --path ./mesh_projects/test_mesh --git y --packageManager yarn"}],"flags":{"path":{"name":"path","type":"option","char":"p","default":"."},"packageManager":{"name":"packageManager","type":"option","char":"m","options":["npm","yarn"]},"git":{"name":"git","type":"option","char":"g","options":["y","n"]}},"args":[{"name":"projectName","description":"Project name","required":true}]},"api-mesh:run":{"id":"api-mesh:run","description":"Run a local development server that builds and compiles a mesh locally","pluginName":"@adobe/aio-cli-plugin-api-mesh","pluginType":"core","aliases":[],"examples":[],"flags":{"port":{"name":"port","type":"option","char":"p","description":"Port number for the local dev server"},"debug":{"name":"debug","type":"boolean","description":"Enable debugging mode","allowNo":false},"env":{"name":"env","type":"option","char":"e","description":"Path to env file","default":".env"},"autoConfirmAction":{"name":"autoConfirmAction","type":"boolean","char":"c","description":"Auto confirm action prompt. CLI will not check for user approval before executing the action.","allowNo":false},"select":{"name":"select","type":"boolean","description":"Retrieve existing artifacts from the mesh","allowNo":false},"secrets":{"name":"secrets","type":"option","char":"s","description":"Path to secrets file","default":false}},"args":[{"name":"file","description":"Mesh File"}]},"api-mesh:status":{"id":"api-mesh:status","description":"Get a mesh status with a given meshid.","pluginName":"@adobe/aio-cli-plugin-api-mesh","pluginType":"core","aliases":[],"flags":{"ignoreCache":{"name":"ignoreCache","type":"boolean","char":"i","description":"Ignore cache and force manual org -> project -> workspace selection","allowNo":false}},"args":[]},"api-mesh:update":{"id":"api-mesh:update","description":"Update a mesh with the given config.","pluginName":"@adobe/aio-cli-plugin-api-mesh","pluginType":"core","aliases":[],"flags":{"ignoreCache":{"name":"ignoreCache","type":"boolean","char":"i","description":"Ignore cache and force manual org -> project -> workspace selection","allowNo":false},"autoConfirmAction":{"name":"autoConfirmAction","type":"boolean","char":"c","description":"Auto confirm action prompt. CLI will not check for user approval before executing the action.","allowNo":false},"env":{"name":"env","type":"option","char":"e","description":"Path to env file","default":".env"},"secrets":{"name":"secrets","type":"option","char":"s","description":"Path to secrets file","default":false}},"args":[{"name":"file"}]},"api-mesh:source:discover":{"id":"api-mesh:source:discover","description":"Return the list of avaliable sources","pluginName":"@adobe/aio-cli-plugin-api-mesh","pluginType":"core","aliases":[],"flags":{"confirm":{"name":"confirm","type":"boolean","char":"c","description":"Auto confirm install action prompt. CLI will not check ask user to install source.","allowNo":false}},"args":[]},"api-mesh:source:get":{"id":"api-mesh:source:get","description":"Command returns the content of a specific source.","pluginName":"@adobe/aio-cli-plugin-api-mesh","pluginType":"core","aliases":[],"examples":["$ aio api-mesh:source:get -s=<version>@<source_name>","$ aio api-mesh:source:get -s<source_name>","$ aio api-mesh:source:get -m"],"flags":{"confirm":{"name":"confirm","type":"boolean","char":"c","description":"Auto confirm print action prompt. CLI will not check ask user to print source.","allowNo":false},"source":{"name":"source","type":"option","char":"s","description":"Source name"},"multiple":{"name":"multiple","type":"boolean","char":"m","description":"Select multiple sources","allowNo":false}},"args":[]},"api-mesh:source:install":{"id":"api-mesh:source:install","description":"Command to install the source to your API mesh.","pluginName":"@adobe/aio-cli-plugin-api-mesh","pluginType":"core","aliases":[],"examples":["$ aio api-mesh:source:install <version>@<source_name>","$ aio api-mesh:source:install <source_name> -v <variable_name>=<variable_value>","$ aio api-mesh:source:install <source_name> -f <path_to_variables_file>"],"flags":{"source":{"name":"source","type":"option","char":"s","description":"Source name"},"confirm":{"name":"confirm","type":"boolean","char":"c","description":"Auto confirm override action prompt. CLI will not check ask user to override source.","allowNo":false},"variable":{"name":"variable","type":"option","char":"v","description":"Variables required for the source"},"variable-file":{"name":"variable-file","type":"option","char":"f","description":"Variables file path"},"ignoreCache":{"name":"ignoreCache","type":"boolean","char":"i","description":"Ignore cache and force manual org -> project -> workspace selection","allowNo":false}},"args":[{"name":"source"}]}}}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@adobe/aio-cli-plugin-api-mesh",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.5.0-beta.1",
|
|
4
4
|
"description": "Adobe I/O CLI plugin to develop and manage API mesh sources",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"oclif-plugin"
|
|
@@ -37,13 +37,13 @@
|
|
|
37
37
|
"version": "oclif-dev readme && git add README.md"
|
|
38
38
|
},
|
|
39
39
|
"dependencies": {
|
|
40
|
-
"@adobe-apimesh/mesh-builder": "1.
|
|
40
|
+
"@adobe-apimesh/mesh-builder": "1.6.0",
|
|
41
41
|
"@adobe/aio-cli-lib-console": "^4.0.0",
|
|
42
42
|
"@adobe/aio-lib-core-config": "^3.0.0",
|
|
43
43
|
"@adobe/aio-lib-core-logging": "^2.0.0",
|
|
44
44
|
"@adobe/aio-lib-env": "^2.0.0",
|
|
45
45
|
"@adobe/aio-lib-ims": "^6.0.1",
|
|
46
|
-
"@adobe/plugin-hooks": "0.
|
|
46
|
+
"@adobe/plugin-hooks": "0.3.0",
|
|
47
47
|
"@adobe/plugin-on-fetch": "0.1.0",
|
|
48
48
|
"@graphql-mesh/cli": "0.82.30",
|
|
49
49
|
"@graphql-mesh/graphql": "0.34.13",
|
|
@@ -52,6 +52,7 @@
|
|
|
52
52
|
"@graphql-mesh/plugin-http-details-extensions": "0.1.21",
|
|
53
53
|
"@graphql-mesh/runtime": "0.46.21",
|
|
54
54
|
"@graphql-mesh/soap": "0.14.25",
|
|
55
|
+
"@graphql-mesh/store": "0.9.20",
|
|
55
56
|
"@graphql-mesh/transform-encapsulate": "0.4.21",
|
|
56
57
|
"@graphql-mesh/transform-federation": "0.11.14",
|
|
57
58
|
"@graphql-mesh/transform-filter-schema": "0.15.23",
|
|
@@ -64,7 +65,6 @@
|
|
|
64
65
|
"@graphql-mesh/transform-resolvers-composition": "0.13.20",
|
|
65
66
|
"@graphql-mesh/transform-type-merging": "0.5.20",
|
|
66
67
|
"@graphql-mesh/types": "0.91.12",
|
|
67
|
-
"@graphql-mesh/store": "0.9.20",
|
|
68
68
|
"@oclif/command": "^1.6.1",
|
|
69
69
|
"@oclif/config": "^1.15.1",
|
|
70
70
|
"@oclif/core": "^1.14.1",
|
|
@@ -74,6 +74,7 @@
|
|
|
74
74
|
"child_process": "^1.0.2",
|
|
75
75
|
"content-disposition": "^0.5.4",
|
|
76
76
|
"dotenv": "^16.0.3",
|
|
77
|
+
"envsub": "^4.1.0",
|
|
77
78
|
"eslint-plugin-promise": "^6.0.0",
|
|
78
79
|
"eslint-plugin-security": "^1.5.0",
|
|
79
80
|
"eslint-plugin-sonarjs": "^0.16.0",
|
|
@@ -92,7 +93,8 @@
|
|
|
92
93
|
"pupa": "^3.1.0",
|
|
93
94
|
"source-registry-storage-adapter": "github:devx-services/source-registry-storage-adapter#main",
|
|
94
95
|
"util": "^0.12.5",
|
|
95
|
-
"uuid": "^8.3.2"
|
|
96
|
+
"uuid": "^8.3.2",
|
|
97
|
+
"yaml": "^2.4.2"
|
|
96
98
|
},
|
|
97
99
|
"devDependencies": {
|
|
98
100
|
"@babel/eslint-parser": "^7.15.8",
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
{
|
|
2
|
+
"meshConfig": {
|
|
3
|
+
"sources": [
|
|
4
|
+
{
|
|
5
|
+
"name": "Commerce",
|
|
6
|
+
"handler": {
|
|
7
|
+
"graphql": {
|
|
8
|
+
"endpoint": "https://venia.magento.com/graphql",
|
|
9
|
+
"operationHeaders": {
|
|
10
|
+
"Authorization": "{context.secrets.Token}"
|
|
11
|
+
},
|
|
12
|
+
"useGETForQueries": true
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
]
|
|
17
|
+
}
|
|
18
|
+
}
|
|
@@ -11,6 +11,7 @@ governing permissions and limitations under the License.
|
|
|
11
11
|
*/
|
|
12
12
|
|
|
13
13
|
const mockConsoleCLIInstance = {};
|
|
14
|
+
const crypto = require('crypto');
|
|
14
15
|
|
|
15
16
|
jest.mock('axios');
|
|
16
17
|
jest.mock('@adobe/aio-lib-ims');
|
|
@@ -44,19 +45,56 @@ const {
|
|
|
44
45
|
createAPIMeshCredentials,
|
|
45
46
|
subscribeCredentialToMeshService,
|
|
46
47
|
getTenantFeatures,
|
|
48
|
+
getPublicEncryptionKey,
|
|
47
49
|
} = require('../../../lib/devConsole');
|
|
48
50
|
|
|
49
51
|
const selectedOrg = { id: '1234', code: 'CODE1234@AdobeOrg', name: 'ORG01', type: 'entp' };
|
|
52
|
+
|
|
53
|
+
const os = require('os');
|
|
54
|
+
|
|
50
55
|
const selectedProject = { id: '5678', title: 'Project01' };
|
|
51
56
|
const selectedWorkspace = { id: '123456789', title: 'Workspace01' };
|
|
52
57
|
|
|
58
|
+
jest.mock('@adobe/aio-cli-lib-console', () => ({
|
|
59
|
+
init: jest.fn().mockResolvedValue(mockConsoleCLIInstance),
|
|
60
|
+
cleanStdOut: jest.fn(),
|
|
61
|
+
}));
|
|
62
|
+
|
|
63
|
+
jest.mock('axios');
|
|
64
|
+
jest.mock('@adobe/aio-lib-ims');
|
|
65
|
+
jest.mock('@adobe/aio-lib-env');
|
|
66
|
+
jest.mock('@adobe/aio-cli-lib-console');
|
|
67
|
+
jest.mock('../../../helpers', () => ({
|
|
68
|
+
initSdk: jest.fn().mockResolvedValue({}),
|
|
69
|
+
initRequestId: jest.fn().mockResolvedValue({}),
|
|
70
|
+
promptConfirm: jest.fn().mockResolvedValue(true),
|
|
71
|
+
interpolateMesh: jest.fn().mockResolvedValue({}),
|
|
72
|
+
importFiles: jest.fn().mockResolvedValue(),
|
|
73
|
+
}));
|
|
74
|
+
jest.mock('../../../lib/devConsole');
|
|
75
|
+
jest.mock('chalk', () => ({
|
|
76
|
+
red: jest.fn(text => text), // Return the input text without any color formatting
|
|
77
|
+
bold: jest.fn(text => text),
|
|
78
|
+
}));
|
|
79
|
+
jest.mock('crypto');
|
|
80
|
+
|
|
53
81
|
let logSpy = null;
|
|
54
82
|
let errorLogSpy = null;
|
|
55
83
|
let parseSpy = null;
|
|
84
|
+
let platformSpy = null;
|
|
56
85
|
|
|
57
86
|
const mockIgnoreCacheFlag = Promise.resolve(true);
|
|
58
87
|
const mockAutoApproveAction = Promise.resolve(false);
|
|
59
88
|
|
|
89
|
+
// Mock randomBytes for aesKey and iv
|
|
90
|
+
const mockAesKey = Buffer.from('mockAesKey');
|
|
91
|
+
const mockIv = Buffer.from('mockIv');
|
|
92
|
+
const mockEncryptedAesKey = Buffer.from('mockEncryptedAesKey');
|
|
93
|
+
const mockCipher = {
|
|
94
|
+
update: jest.fn().mockReturnValueOnce('mockEncryptedData'),
|
|
95
|
+
final: jest.fn().mockReturnValueOnce(''),
|
|
96
|
+
};
|
|
97
|
+
|
|
60
98
|
describe('create command tests', () => {
|
|
61
99
|
beforeEach(() => {
|
|
62
100
|
initSdk.mockResolvedValue({
|
|
@@ -69,6 +107,12 @@ describe('create command tests', () => {
|
|
|
69
107
|
projectName: selectedProject.title,
|
|
70
108
|
});
|
|
71
109
|
|
|
110
|
+
global.requestId = 'dummy_request_id';
|
|
111
|
+
|
|
112
|
+
logSpy = jest.spyOn(CreateCommand.prototype, 'log');
|
|
113
|
+
errorLogSpy = jest.spyOn(CreateCommand.prototype, 'error');
|
|
114
|
+
platformSpy = jest.spyOn(os, 'platform');
|
|
115
|
+
|
|
72
116
|
createMesh.mockResolvedValue({
|
|
73
117
|
mesh: {
|
|
74
118
|
meshId: 'dummy_mesh_id',
|
|
@@ -95,6 +139,7 @@ describe('create command tests', () => {
|
|
|
95
139
|
showCloudflareURL: false,
|
|
96
140
|
});
|
|
97
141
|
|
|
142
|
+
getPublicEncryptionKey.mockResolvedValue('dummy_public_key');
|
|
98
143
|
global.requestId = 'dummy_request_id';
|
|
99
144
|
|
|
100
145
|
logSpy = jest.spyOn(CreateCommand.prototype, 'log');
|
|
@@ -109,6 +154,10 @@ describe('create command tests', () => {
|
|
|
109
154
|
});
|
|
110
155
|
});
|
|
111
156
|
|
|
157
|
+
afterEach(() => {
|
|
158
|
+
platformSpy.mockRestore();
|
|
159
|
+
});
|
|
160
|
+
|
|
112
161
|
test('must return proper object structure used by adobe/generator-app-api-mesh', async () => {
|
|
113
162
|
parseSpy.mockResolvedValueOnce({
|
|
114
163
|
args: { file: 'src/commands/__fixtures__/sample_mesh.json' },
|
|
@@ -171,6 +220,15 @@ describe('create command tests', () => {
|
|
|
171
220
|
"parse": [Function],
|
|
172
221
|
"type": "boolean",
|
|
173
222
|
},
|
|
223
|
+
"secrets": {
|
|
224
|
+
"char": "s",
|
|
225
|
+
"default": false,
|
|
226
|
+
"description": "Path to secrets file",
|
|
227
|
+
"input": [],
|
|
228
|
+
"multiple": false,
|
|
229
|
+
"parse": [Function],
|
|
230
|
+
"type": "option",
|
|
231
|
+
},
|
|
174
232
|
}
|
|
175
233
|
`);
|
|
176
234
|
expect(CreateCommand.aliases).toMatchInlineSnapshot(`[]`);
|
|
@@ -716,7 +774,7 @@ describe('create command tests', () => {
|
|
|
716
774
|
`);
|
|
717
775
|
});
|
|
718
776
|
|
|
719
|
-
test('should return error if mesh has placeholders and the provided env file is invalid', async () => {
|
|
777
|
+
test('should return error if mesh has placeholders and the provided env file is invalid and parsed to {}', async () => {
|
|
720
778
|
parseSpy.mockResolvedValueOnce({
|
|
721
779
|
args: { file: 'src/commands/__fixtures__/sample_mesh_with_placeholder' },
|
|
722
780
|
flags: {
|
|
@@ -730,14 +788,17 @@ describe('create command tests', () => {
|
|
|
730
788
|
|
|
731
789
|
await expect(runResult).rejects.toEqual(
|
|
732
790
|
new Error(
|
|
733
|
-
|
|
791
|
+
'Issue in src/commands/__fixtures__/env_invalid file - Interpolated mesh is not a valid JSON. Please check the generated json file.',
|
|
734
792
|
),
|
|
735
793
|
);
|
|
736
794
|
|
|
737
795
|
expect(errorLogSpy.mock.calls).toMatchInlineSnapshot(`
|
|
738
796
|
[
|
|
739
797
|
[
|
|
740
|
-
"
|
|
798
|
+
"Interpolated mesh is not a valid JSON. Please check the generated json file.",
|
|
799
|
+
],
|
|
800
|
+
[
|
|
801
|
+
"Issue in src/commands/__fixtures__/env_invalid file - Interpolated mesh is not a valid JSON. Please check the generated json file.",
|
|
741
802
|
],
|
|
742
803
|
]
|
|
743
804
|
`);
|
|
@@ -761,7 +822,9 @@ describe('create command tests', () => {
|
|
|
761
822
|
|
|
762
823
|
const runResult = CreateCommand.run();
|
|
763
824
|
await expect(runResult).rejects.toEqual(
|
|
764
|
-
new Error(
|
|
825
|
+
new Error(
|
|
826
|
+
'Issue in src/commands/__fixtures__/env_valid file - The mesh file cannot be interpolated due to missing keys : newKey1 , newKey2',
|
|
827
|
+
),
|
|
765
828
|
);
|
|
766
829
|
|
|
767
830
|
await expect(errorLogSpy.mock.calls).toMatchInlineSnapshot(`
|
|
@@ -769,6 +832,9 @@ describe('create command tests', () => {
|
|
|
769
832
|
[
|
|
770
833
|
"The mesh file cannot be interpolated due to missing keys : newKey1 , newKey2",
|
|
771
834
|
],
|
|
835
|
+
[
|
|
836
|
+
"Issue in src/commands/__fixtures__/env_valid file - The mesh file cannot be interpolated due to missing keys : newKey1 , newKey2",
|
|
837
|
+
],
|
|
772
838
|
]
|
|
773
839
|
`);
|
|
774
840
|
});
|
|
@@ -795,7 +861,9 @@ describe('create command tests', () => {
|
|
|
795
861
|
|
|
796
862
|
const runResult = CreateCommand.run();
|
|
797
863
|
await expect(runResult).rejects.toEqual(
|
|
798
|
-
new Error(
|
|
864
|
+
new Error(
|
|
865
|
+
'Issue in src/commands/__fixtures__/env_valid file - Interpolated mesh is not a valid JSON. Please check the generated json file.',
|
|
866
|
+
),
|
|
799
867
|
);
|
|
800
868
|
|
|
801
869
|
await expect(errorLogSpy.mock.calls).toMatchInlineSnapshot(`
|
|
@@ -803,6 +871,9 @@ describe('create command tests', () => {
|
|
|
803
871
|
[
|
|
804
872
|
"Interpolated mesh is not a valid JSON. Please check the generated json file.",
|
|
805
873
|
],
|
|
874
|
+
[
|
|
875
|
+
"Issue in src/commands/__fixtures__/env_valid file - Interpolated mesh is not a valid JSON. Please check the generated json file.",
|
|
876
|
+
],
|
|
806
877
|
]
|
|
807
878
|
`);
|
|
808
879
|
});
|
|
@@ -1831,4 +1902,244 @@ describe('create command tests', () => {
|
|
|
1831
1902
|
'https://graph.adobe.io/api/dummy_mesh_id/graphql?api_key=dummy_api_key',
|
|
1832
1903
|
);
|
|
1833
1904
|
});
|
|
1905
|
+
|
|
1906
|
+
test('should return error if mesh has placeholders and the provided secrets file is invalid', async () => {
|
|
1907
|
+
parseSpy.mockResolvedValueOnce({
|
|
1908
|
+
args: { file: 'src/commands/__fixtures__/sample_secrets_mesh.json' },
|
|
1909
|
+
flags: {
|
|
1910
|
+
ignoreCache: mockIgnoreCacheFlag,
|
|
1911
|
+
autoConfirmAction: Promise.resolve(true),
|
|
1912
|
+
secrets: 'src/commands/__fixtures__/secrets_invalid.yaml',
|
|
1913
|
+
},
|
|
1914
|
+
});
|
|
1915
|
+
|
|
1916
|
+
const runResult = CreateCommand.run();
|
|
1917
|
+
|
|
1918
|
+
await expect(runResult).rejects.toEqual(
|
|
1919
|
+
new Error('Unable to import secrets. Please check the file and try again.'),
|
|
1920
|
+
);
|
|
1921
|
+
|
|
1922
|
+
expect(errorLogSpy.mock.calls).toMatchInlineSnapshot(`
|
|
1923
|
+
[
|
|
1924
|
+
[
|
|
1925
|
+
"Unable to import secrets. Please check the file and try again.",
|
|
1926
|
+
],
|
|
1927
|
+
]
|
|
1928
|
+
`);
|
|
1929
|
+
});
|
|
1930
|
+
|
|
1931
|
+
test('should return error if mesh has placeholders and the provided secrets file is not yaml or yml', async () => {
|
|
1932
|
+
parseSpy.mockResolvedValueOnce({
|
|
1933
|
+
args: { file: 'src/commands/__fixtures__/sample_secrets_mesh.json' },
|
|
1934
|
+
flags: {
|
|
1935
|
+
ignoreCache: mockIgnoreCacheFlag,
|
|
1936
|
+
autoConfirmAction: Promise.resolve(true),
|
|
1937
|
+
secrets: 'src/commands/__fixtures__/.secrets_file.env',
|
|
1938
|
+
},
|
|
1939
|
+
});
|
|
1940
|
+
|
|
1941
|
+
const runResult = CreateCommand.run();
|
|
1942
|
+
|
|
1943
|
+
await expect(runResult).rejects.toEqual(
|
|
1944
|
+
new Error('Unable to import secrets. Please check the file and try again.'),
|
|
1945
|
+
);
|
|
1946
|
+
|
|
1947
|
+
expect(logSpy.mock.calls).toMatchInlineSnapshot(`
|
|
1948
|
+
[
|
|
1949
|
+
[
|
|
1950
|
+
"Invalid file format. Please provide a YAML file (.yaml or .yml).",
|
|
1951
|
+
],
|
|
1952
|
+
]
|
|
1953
|
+
`);
|
|
1954
|
+
|
|
1955
|
+
expect(errorLogSpy.mock.calls).toMatchInlineSnapshot(`
|
|
1956
|
+
[
|
|
1957
|
+
[
|
|
1958
|
+
"Unable to import secrets. Please check the file and try again.",
|
|
1959
|
+
],
|
|
1960
|
+
]
|
|
1961
|
+
`);
|
|
1962
|
+
});
|
|
1963
|
+
|
|
1964
|
+
test('should successfully create a mesh if provided secrets file is valid', async () => {
|
|
1965
|
+
parseSpy.mockResolvedValueOnce({
|
|
1966
|
+
args: { file: 'src/commands/__fixtures__/sample_secrets_mesh.json' },
|
|
1967
|
+
flags: {
|
|
1968
|
+
ignoreCache: mockIgnoreCacheFlag,
|
|
1969
|
+
autoConfirmAction: Promise.resolve(true),
|
|
1970
|
+
secrets: 'src/commands/__fixtures__/secrets_valid.yaml',
|
|
1971
|
+
},
|
|
1972
|
+
});
|
|
1973
|
+
|
|
1974
|
+
crypto.randomBytes.mockReturnValueOnce(mockAesKey).mockReturnValueOnce(mockIv);
|
|
1975
|
+
crypto.createCipheriv.mockReturnValueOnce(mockCipher);
|
|
1976
|
+
crypto.publicEncrypt.mockReturnValueOnce(mockEncryptedAesKey);
|
|
1977
|
+
|
|
1978
|
+
const runResult = await CreateCommand.run();
|
|
1979
|
+
expect(runResult).toMatchInlineSnapshot(`
|
|
1980
|
+
{
|
|
1981
|
+
"apiKey": "dummy_api_key",
|
|
1982
|
+
"mesh": {
|
|
1983
|
+
"meshConfig": {
|
|
1984
|
+
"sources": [
|
|
1985
|
+
{
|
|
1986
|
+
"handler": {
|
|
1987
|
+
"graphql": {
|
|
1988
|
+
"endpoint": "<gql_endpoint>",
|
|
1989
|
+
},
|
|
1990
|
+
},
|
|
1991
|
+
"name": "<api_name>",
|
|
1992
|
+
},
|
|
1993
|
+
],
|
|
1994
|
+
},
|
|
1995
|
+
"meshId": "dummy_mesh_id",
|
|
1996
|
+
},
|
|
1997
|
+
"sdkList": [
|
|
1998
|
+
"dummy_service",
|
|
1999
|
+
],
|
|
2000
|
+
}
|
|
2001
|
+
`);
|
|
2002
|
+
});
|
|
2003
|
+
|
|
2004
|
+
test('should return error if ran against windows platform with batch variables', async () => {
|
|
2005
|
+
platformSpy.mockReturnValue('win32');
|
|
2006
|
+
parseSpy.mockResolvedValueOnce({
|
|
2007
|
+
args: { file: 'src/commands/__fixtures__/sample_secrets_mesh.json' },
|
|
2008
|
+
flags: {
|
|
2009
|
+
ignoreCache: mockIgnoreCacheFlag,
|
|
2010
|
+
autoConfirmAction: Promise.resolve(true),
|
|
2011
|
+
secrets: 'src/commands/__fixtures__/secrets_with_batch_variables.yaml',
|
|
2012
|
+
},
|
|
2013
|
+
});
|
|
2014
|
+
|
|
2015
|
+
const runResult = CreateCommand.run();
|
|
2016
|
+
|
|
2017
|
+
await expect(runResult).rejects.toEqual(
|
|
2018
|
+
new Error('Unable to import secrets. Please check the file and try again.'),
|
|
2019
|
+
);
|
|
2020
|
+
|
|
2021
|
+
expect(logSpy.mock.calls).toMatchInlineSnapshot(`
|
|
2022
|
+
[
|
|
2023
|
+
[
|
|
2024
|
+
"Batch variables are not supported in YAML files on Windows.",
|
|
2025
|
+
],
|
|
2026
|
+
]
|
|
2027
|
+
`);
|
|
2028
|
+
expect(errorLogSpy.mock.calls).toMatchInlineSnapshot(`
|
|
2029
|
+
[
|
|
2030
|
+
[
|
|
2031
|
+
"Unable to import secrets. Please check the file and try again.",
|
|
2032
|
+
],
|
|
2033
|
+
]
|
|
2034
|
+
`);
|
|
2035
|
+
});
|
|
2036
|
+
|
|
2037
|
+
test('should pass if ran against linux platform with batch variables', async () => {
|
|
2038
|
+
platformSpy.mockReturnValue('linux');
|
|
2039
|
+
parseSpy.mockResolvedValueOnce({
|
|
2040
|
+
args: { file: 'src/commands/__fixtures__/sample_secrets_mesh.json' },
|
|
2041
|
+
flags: {
|
|
2042
|
+
ignoreCache: mockIgnoreCacheFlag,
|
|
2043
|
+
autoConfirmAction: Promise.resolve(true),
|
|
2044
|
+
secrets: 'src/commands/__fixtures__/secrets_with_batch_variables.yaml',
|
|
2045
|
+
},
|
|
2046
|
+
});
|
|
2047
|
+
|
|
2048
|
+
crypto.randomBytes.mockReturnValueOnce(mockAesKey).mockReturnValueOnce(mockIv);
|
|
2049
|
+
crypto.createCipheriv.mockReturnValueOnce(mockCipher);
|
|
2050
|
+
crypto.publicEncrypt.mockReturnValueOnce(mockEncryptedAesKey);
|
|
2051
|
+
|
|
2052
|
+
const runResult = await CreateCommand.run();
|
|
2053
|
+
expect(runResult).toMatchInlineSnapshot(`
|
|
2054
|
+
{
|
|
2055
|
+
"apiKey": "dummy_api_key",
|
|
2056
|
+
"mesh": {
|
|
2057
|
+
"meshConfig": {
|
|
2058
|
+
"sources": [
|
|
2059
|
+
{
|
|
2060
|
+
"handler": {
|
|
2061
|
+
"graphql": {
|
|
2062
|
+
"endpoint": "<gql_endpoint>",
|
|
2063
|
+
},
|
|
2064
|
+
},
|
|
2065
|
+
"name": "<api_name>",
|
|
2066
|
+
},
|
|
2067
|
+
],
|
|
2068
|
+
},
|
|
2069
|
+
"meshId": "dummy_mesh_id",
|
|
2070
|
+
},
|
|
2071
|
+
"sdkList": [
|
|
2072
|
+
"dummy_service",
|
|
2073
|
+
],
|
|
2074
|
+
}
|
|
2075
|
+
`);
|
|
2076
|
+
});
|
|
2077
|
+
|
|
2078
|
+
test('should pass if ran against darwin(macOS) platform with batch variables', async () => {
|
|
2079
|
+
platformSpy.mockReturnValue('darwin');
|
|
2080
|
+
parseSpy.mockResolvedValueOnce({
|
|
2081
|
+
args: { file: 'src/commands/__fixtures__/sample_secrets_mesh.json' },
|
|
2082
|
+
flags: {
|
|
2083
|
+
ignoreCache: mockIgnoreCacheFlag,
|
|
2084
|
+
autoConfirmAction: Promise.resolve(true),
|
|
2085
|
+
secrets: 'src/commands/__fixtures__/secrets_with_batch_variables.yaml',
|
|
2086
|
+
},
|
|
2087
|
+
});
|
|
2088
|
+
|
|
2089
|
+
crypto.randomBytes.mockReturnValueOnce(mockAesKey).mockReturnValueOnce(mockIv);
|
|
2090
|
+
crypto.createCipheriv.mockReturnValueOnce(mockCipher);
|
|
2091
|
+
crypto.publicEncrypt.mockReturnValueOnce(mockEncryptedAesKey);
|
|
2092
|
+
|
|
2093
|
+
const runResult = await CreateCommand.run();
|
|
2094
|
+
expect(runResult).toMatchInlineSnapshot(`
|
|
2095
|
+
{
|
|
2096
|
+
"apiKey": "dummy_api_key",
|
|
2097
|
+
"mesh": {
|
|
2098
|
+
"meshConfig": {
|
|
2099
|
+
"sources": [
|
|
2100
|
+
{
|
|
2101
|
+
"handler": {
|
|
2102
|
+
"graphql": {
|
|
2103
|
+
"endpoint": "<gql_endpoint>",
|
|
2104
|
+
},
|
|
2105
|
+
},
|
|
2106
|
+
"name": "<api_name>",
|
|
2107
|
+
},
|
|
2108
|
+
],
|
|
2109
|
+
},
|
|
2110
|
+
"meshId": "dummy_mesh_id",
|
|
2111
|
+
},
|
|
2112
|
+
"sdkList": [
|
|
2113
|
+
"dummy_service",
|
|
2114
|
+
],
|
|
2115
|
+
}
|
|
2116
|
+
`);
|
|
2117
|
+
});
|
|
2118
|
+
|
|
2119
|
+
test('should return error if secrets file is valid but public key for encryption is empty', async () => {
|
|
2120
|
+
parseSpy.mockResolvedValueOnce({
|
|
2121
|
+
args: { file: 'src/commands/__fixtures__/sample_secrets_mesh.json' },
|
|
2122
|
+
flags: {
|
|
2123
|
+
ignoreCache: mockIgnoreCacheFlag,
|
|
2124
|
+
autoConfirmAction: Promise.resolve(true),
|
|
2125
|
+
secrets: 'src/commands/__fixtures__/secrets_valid.yaml',
|
|
2126
|
+
},
|
|
2127
|
+
});
|
|
2128
|
+
getPublicEncryptionKey.mockResolvedValue('');
|
|
2129
|
+
|
|
2130
|
+
crypto.randomBytes.mockReturnValueOnce(mockAesKey).mockReturnValueOnce(mockIv);
|
|
2131
|
+
crypto.createCipheriv.mockReturnValueOnce(mockCipher);
|
|
2132
|
+
|
|
2133
|
+
const runResult = CreateCommand.run();
|
|
2134
|
+
await expect(runResult).rejects.toEqual(
|
|
2135
|
+
new Error('Unable to import secrets. Please check the file and try again.'),
|
|
2136
|
+
);
|
|
2137
|
+
expect(logSpy.mock.calls).toMatchInlineSnapshot(`
|
|
2138
|
+
[
|
|
2139
|
+
[
|
|
2140
|
+
"Unable to encrypt secerts. Invalid Public Key.",
|
|
2141
|
+
],
|
|
2142
|
+
]
|
|
2143
|
+
`);
|
|
2144
|
+
});
|
|
1834
2145
|
});
|