Skip to content

Commit 121b464

Browse files
committed
Support creation of apollo zip from an input schema file.
1 parent 95d119e commit 121b464

11 files changed

+160
-112
lines changed

src/main.js

+17-2
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ let queryClient = 'sdk'; // or 'http'
5555
let isNeptuneIAMAuth = false;
5656
let createUpdateApolloServer = false;
5757
let createUpdateApolloServerSubgraph = false;
58+
let createUpdateApolloServerEndpoint = '';
5859
let createUpdatePipeline = false;
5960
let createUpdatePipelineName = '';
6061
let createUpdatePipelineEndpoint = '';
@@ -197,6 +198,10 @@ function processArgs() {
197198
createUpdatePipeline = false;
198199
inputCDKpipeline = false;
199200
break;
201+
case '-ase':
202+
case '--create-update-apollo-server-neptune-endpoint':
203+
createUpdateApolloServerEndpoint = array[index + 1];
204+
break;
200205
case '-p':
201206
case '--create-update-aws-pipeline':
202207
createUpdatePipeline = true;
@@ -314,10 +319,15 @@ function createOutputFolder() {
314319

315320
function validateArgs() {
316321
// TODO more argument validation
317-
if (queryClient !== 'http' && (createUpdateApolloServerSubgraph || createUpdateApolloServer)) {
322+
const createApollo = createUpdateApolloServerSubgraph || createUpdateApolloServer;
323+
if (queryClient !== 'http' && createApollo) {
318324
console.error(`Neptune querying using ${queryClient} is not yet supported for Apollo Server. Please use option --output-resolver-query-https.`);
319325
process.exit(1);
320326
}
327+
if (createApollo && !inputGraphDBSchemaNeptuneEndpoint && !createUpdateApolloServerEndpoint) {
328+
console.error(`Apollo artifact creation requires a neptune endpoint. Please specify option --input-graphdb-schema-neptune-endpoint or --create-update-apollo-server-neptune-endpoint.`);
329+
process.exit(1);
330+
}
321331
}
322332

323333
async function main() {
@@ -351,7 +361,12 @@ async function main() {
351361
let neptuneInfo;
352362
// Check if any of the Neptune endpoints are a neptune analytic endpoint and if so, set the neptuneType and IAM to required
353363
// only one of these endpoints are expected to be non-empty at the same time
354-
const nonEmptyEndpoints = [inputGraphDBSchemaNeptuneEndpoint, createUpdatePipelineEndpoint, inputCDKpipelineEndpoint].filter(endpoint => endpoint !== '');
364+
const nonEmptyEndpoints = [
365+
inputGraphDBSchemaNeptuneEndpoint,
366+
createUpdatePipelineEndpoint,
367+
inputCDKpipelineEndpoint,
368+
createUpdateApolloServerEndpoint
369+
].filter(endpoint => endpoint !== '');
355370
if (nonEmptyEndpoints.length > 0) {
356371
neptuneInfo = parseNeptuneEndpoint(nonEmptyEndpoints[0]);
357372
neptuneType = neptuneInfo.neptuneType;
+4-36
Original file line numberDiff line numberDiff line change
@@ -1,47 +1,15 @@
1-
import {readJSONFile, unzipAndGetContents} from '../../testLib';
1+
import {readJSONFile, testApolloArtifacts} from '../../testLib';
22
import fs from "fs";
33
import {parseNeptuneEndpoint} from "../../../src/util.js";
44

55
const testCase = readJSONFile('./test/TestCases/Case08/case01.json');
66
const testDbInfo = parseNeptuneEndpoint(testCase.host + ':' + testCase.port);
7+
const outputFolderPath = './test/TestCases/Case08/case08-01-output';
78

89
describe('Validate Apollo Server output artifacts', () => {
9-
1010
afterAll(async () => {
11-
fs.rmSync('./test/TestCases/Case08/case08-01-output', {recursive: true});
12-
});
13-
14-
test('Validate zip contents', () => {
15-
const expectedFiles = [
16-
'.env',
17-
'index.mjs',
18-
'output.resolver.graphql.js',
19-
'package.json',
20-
'package-lock.json',
21-
'output.schema.graphql',
22-
'neptune.mjs',
23-
'queryHttpNeptune.mjs'
24-
];
25-
26-
const files = fs.readdirSync('./test/TestCases/Case08/case08-01-output');
27-
const apolloZips = files.filter(file => file.startsWith(`apollo-server-${testDbInfo.graphName}-`) && file.endsWith('.zip'));
28-
expect(apolloZips.length).toEqual(1);
29-
30-
const actualFiles = unzipAndGetContents('./test/TestCases/Case08/case08-01-output/unzipped', `./test/TestCases/Case08/case08-01-output/${apolloZips[0]}`);
31-
expect(actualFiles.toSorted()).toEqual(expectedFiles.toSorted());
32-
});
33-
34-
test('Validate .env values', () => {
35-
const expectedContent = [
36-
`NEPTUNE_TYPE=${testDbInfo.neptuneType}`,
37-
`NEPTUNE_HOST=${testCase.host}`,
38-
`NEPTUNE_PORT=${testCase.port}`,
39-
`AWS_REGION=${testDbInfo.region}`,
40-
'LOGGING_ENABLED=false',
41-
'SUBGRAPH=false'
42-
];
43-
const actualContent = fs.readFileSync('./test/TestCases/Case08/case08-01-output/unzipped/.env', 'utf8');
44-
expect(actualContent).toEqual(expectedContent.join('\n'));
11+
fs.rmSync(outputFolderPath, {recursive: true});
4512
});
4613

14+
testApolloArtifacts(outputFolderPath, testDbInfo, false);
4715
});
+4-38
Original file line numberDiff line numberDiff line change
@@ -1,49 +1,15 @@
1-
import {readJSONFile, unzipAndGetContents} from '../../testLib';
1+
import {readJSONFile, testApolloArtifacts} from '../../testLib';
22
import fs from "fs";
33
import {parseNeptuneEndpoint} from "../../../src/util.js";
44

55
const testCase = readJSONFile('./test/TestCases/Case08/case02.json');
66
const testDbInfo = parseNeptuneEndpoint(testCase.host + ':' + testCase.port);
7+
const outputFolderPath = './test/TestCases/Case08/case08-02-output';
78

89
describe('Validate Apollo Server output artifacts are created when using customized output arguments', () => {
9-
1010
afterAll(async () => {
11-
fs.rmSync('./test/TestCases/Case08/case08-02-output', {recursive: true});
12-
});
13-
14-
// the zip contents should be the same regardless of the customized output arguments
15-
test('Validate zip contents', () => {
16-
const expectedFiles = [
17-
'.env',
18-
'index.mjs',
19-
'output.resolver.graphql.js',
20-
'package.json',
21-
'package-lock.json',
22-
'output.schema.graphql',
23-
'neptune.mjs',
24-
'queryHttpNeptune.mjs'
25-
];
26-
27-
const files = fs.readdirSync('./test/TestCases/Case08/case08-02-output');
28-
const apolloZips = files.filter(file => file.startsWith(`apollo-server-${testDbInfo.graphName}-`) && file.endsWith('.zip'));
29-
expect(apolloZips.length).toEqual(1);
30-
31-
const actualFiles = unzipAndGetContents('./test/TestCases/Case08/case08-02-output/unzipped', `./test/TestCases/Case08/case08-02-output/${apolloZips[0]}`);
32-
expect(actualFiles.toSorted()).toEqual(expectedFiles.toSorted());
33-
});
34-
35-
// the .env values should be the same regardless of the customized output arguments
36-
test('Validate .env values', () => {
37-
const expectedContent = [
38-
`NEPTUNE_TYPE=${testDbInfo.neptuneType}`,
39-
`NEPTUNE_HOST=${testCase.host}`,
40-
`NEPTUNE_PORT=${testCase.port}`,
41-
`AWS_REGION=${testDbInfo.region}`,
42-
'LOGGING_ENABLED=false',
43-
'SUBGRAPH=false'
44-
];
45-
const actualContent = fs.readFileSync('./test/TestCases/Case08/case08-02-output/unzipped/.env', 'utf8');
46-
expect(actualContent).toEqual(expectedContent.join('\n'));
11+
fs.rmSync(outputFolderPath, {recursive: true});
4712
});
4813

14+
testApolloArtifacts(outputFolderPath, testDbInfo, false);
4915
});
+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import {readJSONFile} from '../../testLib';
2+
import {main} from "../../../src/main";
3+
4+
const casetest = readJSONFile('./test/TestCases/Case08/case03.json');
5+
6+
async function executeUtility() {
7+
process.argv = casetest.argv;
8+
await main();
9+
}
10+
11+
describe('Create Apollo Server output artifacts from input schema file', () => {
12+
test('Execute utility: ' + casetest.argv.join(' '), async () => {
13+
expect(await executeUtility()).not.toBe(null);
14+
}, 600000);
15+
});
+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import {readJSONFile, testApolloArtifacts} from '../../testLib';
2+
import fs from "fs";
3+
import {parseNeptuneEndpoint} from "../../../src/util.js";
4+
5+
const testCase = readJSONFile('./test/TestCases/Case08/case03.json');
6+
const testDbInfo = parseNeptuneEndpoint(testCase.host + ':' + testCase.port);
7+
const outputFolderPath = './test/TestCases/Case08/case08-03-output';
8+
9+
describe('Validate Apollo Server output artifacts are created when using an input schema file', () => {
10+
afterAll(async () => {
11+
fs.rmSync(outputFolderPath, {recursive: true});
12+
});
13+
14+
testApolloArtifacts(outputFolderPath, testDbInfo, false);
15+
});

test/TestCases/Case08/case03.json

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
{
2+
"name": "Create Apollo Server ZIP from input schema file",
3+
"description":"Test creation of Apollo Server ZIP using an input schema file",
4+
"argv":["--quiet",
5+
"--input-schema-file", "./test/TestCases/airports.source.schema.graphql",
6+
"--create-update-apollo-server-neptune-endpoint", "<AIR_ROUTES_DB_HOST>:<AIR_ROUTES_DB_PORT>",
7+
"--output-folder-path", "./test/TestCases/Case08/case08-03-output",
8+
"--create-update-apollo-server",
9+
"--output-resolver-query-https"],
10+
"host": "<AIR_ROUTES_DB_HOST>",
11+
"port": "<AIR_ROUTES_DB_PORT>"
12+
}
+4-36
Original file line numberDiff line numberDiff line change
@@ -1,47 +1,15 @@
1-
import {readJSONFile, unzipAndGetContents} from '../../testLib';
1+
import {readJSONFile, testApolloArtifacts} from '../../testLib';
22
import fs from "fs";
33
import {parseNeptuneEndpoint} from "../../../src/util.js";
44

55
const testCase = readJSONFile('./test/TestCases/Case09/case01.json');
66
const testDbInfo = parseNeptuneEndpoint(testCase.host + ':' + testCase.port);
77

8+
const outputFolderPath = './test/TestCases/Case09/output';
89
describe('Validate Apollo Server Subgraph output artifacts', () => {
9-
1010
afterAll(async () => {
11-
fs.rmSync('./test/TestCases/Case09/output', {recursive: true});
12-
});
13-
14-
test('Validate zip contents', () => {
15-
const expectedFiles = [
16-
'.env',
17-
'index.mjs',
18-
'output.resolver.graphql.js',
19-
'package.json',
20-
'package-lock.json',
21-
'output.schema.graphql',
22-
'neptune.mjs',
23-
'queryHttpNeptune.mjs'
24-
];
25-
26-
const files = fs.readdirSync('./test/TestCases/Case09/output');
27-
const apolloZips = files.filter(file => file.startsWith(`apollo-server-${testDbInfo.graphName}-`) && file.endsWith('.zip'));
28-
expect(apolloZips.length).toEqual(1);
29-
30-
const actualFiles = unzipAndGetContents('./test/TestCases/Case09/output/unzipped', `./test/TestCases/Case09/output/${apolloZips[0]}`);
31-
expect(actualFiles.toSorted()).toEqual(expectedFiles.toSorted());
32-
});
33-
34-
test('Validate .env values', () => {
35-
const expectedContent = [
36-
`NEPTUNE_TYPE=${testDbInfo.neptuneType}`,
37-
`NEPTUNE_HOST=${testCase.host}`,
38-
`NEPTUNE_PORT=${testCase.port}`,
39-
`AWS_REGION=${testDbInfo.region}`,
40-
`LOGGING_ENABLED=false`,
41-
`SUBGRAPH=true`
42-
];
43-
const actualContent = fs.readFileSync('./test/TestCases/Case09/output/unzipped/.env', 'utf8');
44-
expect(actualContent).toEqual(expectedContent.join('\n'));
11+
fs.rmSync(outputFolderPath, {recursive: true});
4512
});
4613

14+
testApolloArtifacts(outputFolderPath, testDbInfo, true);
4715
});
+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import {readJSONFile} from '../../testLib';
2+
import {main} from "../../../src/main";
3+
4+
const casetest = readJSONFile('./test/TestCases/Case09/case02.json');
5+
6+
async function executeUtility() {
7+
process.argv = casetest.argv;
8+
await main();
9+
}
10+
11+
describe('Create Apollo Server Subgraph output artifacts from input schema file', () => {
12+
test('Execute utility: ' + casetest.argv.join(' '), async () => {
13+
expect(await executeUtility()).not.toBe(null);
14+
}, 600000);
15+
});
+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import {readJSONFile, testApolloArtifacts} from '../../testLib';
2+
import fs from "fs";
3+
import {parseNeptuneEndpoint} from "../../../src/util.js";
4+
5+
const testCase = readJSONFile('./test/TestCases/Case09/case02.json');
6+
const testDbInfo = parseNeptuneEndpoint(testCase.host + ':' + testCase.port);
7+
const outputFolderPath = './test/TestCases/Case09/case09-02-output';
8+
9+
describe('Validate Apollo Server Subgraph output artifacts are created when using an input schema file', () => {
10+
afterAll(async () => {
11+
fs.rmSync(outputFolderPath, {recursive: true});
12+
});
13+
14+
testApolloArtifacts(outputFolderPath, testDbInfo, true);
15+
});

test/TestCases/Case09/case02.json

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
{
2+
"name": "Create Apollo Server Subgraph ZIP from input schema file",
3+
"description":"Test creation of Apollo Server Subgraph ZIP using an input schema file",
4+
"argv":["--quiet",
5+
"--input-schema-file", "./test/TestCases/airports.source.schema.graphql",
6+
"--create-update-apollo-server-neptune-endpoint", "<AIR_ROUTES_DB_HOST>:<AIR_ROUTES_DB_PORT>",
7+
"--output-folder-path", "./test/TestCases/Case09/case09-02-output",
8+
"--create-update-apollo-server-subgraph",
9+
"--output-resolver-query-https"],
10+
"host": "<AIR_ROUTES_DB_HOST>",
11+
"port": "<AIR_ROUTES_DB_PORT>"
12+
}

test/testLib.js

+47
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import axios from 'axios';
33
import fs from 'fs';
44
import AdmZip from 'adm-zip';
55
import gql from 'graphql-tag';
6+
import * as path from "node:path";
67

78
const HOST_PLACEHOLDER = '<AIR_ROUTES_DB_HOST>';
89
const PORT_PLACEHOLDER = '<AIR_ROUTES_DB_PORT>';
@@ -174,6 +175,51 @@ async function testResolverQueriesResults(resolverFile, queriesReferenceFolder,
174175
}
175176
}
176177

178+
/**
179+
* Validates that an apollo zip contains the correct content.
180+
*
181+
* @param {string} outputFolderPath the test output folder path that contains the apollo zip file to validate
182+
* @param {object} testDbInfo object that contains info about the neptune db/graph used to generate the apollo zip file
183+
* @param {string} testDbInfo.graphName neptune db/graph name
184+
* @param {string} testDbInfo.neptuneType neptune-db or neptune-graph
185+
* @param {string} testDbInfo.host neptune host
186+
* @param {int} testDbInfo.port neptune port
187+
* @param {string} testDbInfo.region neptune region
188+
* @param {boolean} subgraph true if the apollo zip contents should be for a subgraph
189+
* @returns {Promise<void>}
190+
*/
191+
async function testApolloArtifacts(outputFolderPath, testDbInfo, subgraph = false) {
192+
test('Validate Apollo zip contents', () => {
193+
const expectedFiles = [
194+
'.env',
195+
'index.mjs',
196+
'output.resolver.graphql.js',
197+
'package.json',
198+
'package-lock.json',
199+
'output.schema.graphql',
200+
'neptune.mjs',
201+
'queryHttpNeptune.mjs'
202+
];
203+
204+
const files = fs.readdirSync(outputFolderPath);
205+
const apolloZips = files.filter(file => file.startsWith(`apollo-server-${testDbInfo.graphName}-`) && file.endsWith('.zip'));
206+
expect(apolloZips.length).toEqual(1);
207+
208+
const actualFiles = unzipAndGetContents(path.join(outputFolderPath, 'unzipped'), path.join(outputFolderPath, apolloZips[0]));
209+
expect(actualFiles.toSorted()).toEqual(expectedFiles.toSorted());
210+
211+
const expectedEnvContent = [
212+
`NEPTUNE_TYPE=${testDbInfo.neptuneType}`,
213+
`NEPTUNE_HOST=${testDbInfo.host}`,
214+
`NEPTUNE_PORT=${testDbInfo.port}`,
215+
`AWS_REGION=${testDbInfo.region}`,
216+
'LOGGING_ENABLED=false',
217+
`SUBGRAPH=${subgraph}`
218+
];
219+
const actualEnvContent = fs.readFileSync(path.join(outputFolderPath, 'unzipped', '.env'), 'utf8');
220+
expect(actualEnvContent).toEqual(expectedEnvContent.join('\n'));
221+
});
222+
}
177223

178224
export {
179225
checkFileContains,
@@ -183,6 +229,7 @@ export {
183229
checkOutputZipLambdaUsesSdk,
184230
loadResolver,
185231
readJSONFile,
232+
testApolloArtifacts,
186233
testResolverQueries,
187234
testResolverQueriesResults,
188235
};

0 commit comments

Comments
 (0)