Skip to content

Commit

Permalink
Merge pull request #2915 from apollographql/enterprise-merge/remoteHo…
Browse files Browse the repository at this point in the history
…stedServiceLists

Add remote hosted endpoint support
  • Loading branch information
Jackson Kearl authored Jun 27, 2019
2 parents af0edf3 + 886e9a0 commit 1c964c0
Show file tree
Hide file tree
Showing 6 changed files with 488 additions and 25 deletions.
102 changes: 102 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@
"@types/micro": "7.3.3",
"@types/multer": "1.3.7",
"@types/node": "8.10.49",
"@types/nock": "9.1.3",
"@types/node-fetch": "2.3.2",
"@types/request": "2.48.1",
"@types/request-promise": "4.1.44",
Expand Down Expand Up @@ -128,6 +129,7 @@
"meteor-promise": "0.8.7",
"mock-req": "0.2.0",
"multer": "1.4.1",
"nock": "^10.0.6",
"node-fetch": "2.3.0",
"prettier": "1.17.1",
"prettier-check": "2.0.0",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
import nock from 'nock';
import { ApolloGateway } from '../..';

import {
mockGetRawPartialSchema,
mockFetchStorageSecret,
mockGetCompositionConfigLink,
mockGetCompositionConfigs,
mockGetImplementingServices,
mockLocalhostSDLQuery,
} from './nockMocks';

afterEach(() => {
expect(nock.isDone()).toBeTruthy();
});

it('Queries remote endpoints for their SDLs', async () => {
const url = 'http://localhost:4001';
const sdl = `
extend type Query {
me: User
everyone: [User]
}
"My User."
type User @key(fields: "id") {
id: ID!
name: String
username: String
}
`;

mockLocalhostSDLQuery({ url, sdl });

const gateway = new ApolloGateway({
serviceList: [{ name: 'accounts', url: `${url}/graphql` }],
});
await gateway.load();
expect(gateway.schema!.getType('User')!.description).toBe('My User.');
});

// This test is maybe a bit terrible, but IDK a better way to mock all the requests
it('Extracts service definitions from remote storage', async () => {
const serviceName = 'jacksons-service';
// hash of `service:${serviceName}:AABBCCDDEEFFGG`, but we don't want to depend on createSHA.
const apiKeyHash = // createSHA('sha512').update(apiKey).digest('hex');
'fa54332e7e8f1522edf721cea7ada93dc7c736f9343f4483989268a956b9101fabd18a53b62d837072abd87018b0b67e052ff732a98b3999e15d39d66d8e56dc';

const storageSecret = 'secret';
const implementingServicePath =
'path-to-implementing-service-definition.json';
const partialSchemaPath = 'path-to-accounts-partial-schema.json';
const federatedServiceName = 'accounts';
const federatedServiceURL = 'http://localhost:4001';
const federatedServiceSchema = `
extend type Query {
me: User
everyone: [User]
}
"This is my User"
type User @key(fields: "id") {
id: ID!
name: String
username: String
}`;

mockFetchStorageSecret({ apiKeyHash, storageSecret, serviceName });

mockGetCompositionConfigLink(storageSecret);

mockGetCompositionConfigs({
storageSecret,
implementingServicePath,
federatedServiceName,
});

mockGetImplementingServices({
storageSecret,
implementingServicePath,
partialSchemaPath,
federatedServiceName,
federatedServiceURL,
});

mockGetRawPartialSchema({
storageSecret,
partialSchemaPath,
federatedServiceSchema,
});

const gateway = new ApolloGateway({});

await gateway.load({ apiKeyHash, graphId: serviceName });
expect(gateway.schema!.getType('User')!.description).toBe('This is my User');
});
102 changes: 102 additions & 0 deletions packages/apollo-gateway/src/__tests__/integration/nockMocks.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
import nock from 'nock';

export const mockLocalhostSDLQuery = ({
url,
sdl,
}: {
url: string;
sdl: string;
}) =>
nock(url)
.post('/graphql', {
query: 'query GetServiceDefinition { _service { sdl } }',
})
.reply(200, { data: { _service: { sdl } } });

export const mockFetchStorageSecret = ({
apiKeyHash,
storageSecret,
serviceName,
}: {
apiKeyHash: string;
storageSecret: string;
serviceName: string;
}) =>
nock('https://storage.googleapis.com:443')
.get(
`/engine-partial-schema-prod/${serviceName}/storage-secret/${apiKeyHash}.json`,
)
.reply(200, `"${storageSecret}"`);

// get composition config link, using received storage secret
export const mockGetCompositionConfigLink = (storageSecret: string) =>
nock('https://storage.googleapis.com:443')
.get(
`/engine-partial-schema-prod/${storageSecret}/current/v1/composition-config-link`,
)
.reply(200, {
configPath: `${storageSecret}/current/v1/composition-configs/composition-config-path.json`,
});

// get composition configs, using received composition config link
export const mockGetCompositionConfigs = ({
storageSecret,
implementingServicePath,
federatedServiceName,
}: {
storageSecret: string;
implementingServicePath: string;
federatedServiceName: string;
}) =>
nock('https://storage.googleapis.com:443')
.get(
`/engine-partial-schema-prod/${storageSecret}/current/v1/composition-configs/composition-config-path.json`,
)
.reply(200, {
implementingServiceLocations: [
{
name: federatedServiceName,
path: `${storageSecret}/current/v1/implementing-services/${federatedServiceName}/${implementingServicePath}.json`,
},
],
});

// get implementing service reference, using received composition-config
export const mockGetImplementingServices = ({
storageSecret,
implementingServicePath,
partialSchemaPath,
federatedServiceName,
federatedServiceURL,
}: {
storageSecret: string;
implementingServicePath: string;
partialSchemaPath: string;
federatedServiceName: string;
federatedServiceURL: string;
}) =>
nock('https://storage.googleapis.com:443')
.get(
`/engine-partial-schema-prod/${storageSecret}/current/v1/implementing-services/${federatedServiceName}/${implementingServicePath}.json`,
)
.reply(200, {
name: federatedServiceName,
partialSchemaPath: `${storageSecret}/current/raw-partial-schemas/${partialSchemaPath}`,
url: federatedServiceURL,
});

// get raw-partial-schema, using received composition-config
export const mockGetRawPartialSchema = ({
storageSecret,
partialSchemaPath,
federatedServiceSchema,
}: {
storageSecret: string;
partialSchemaPath: string;
federatedServiceSchema: string;
}) =>
nock('https://storage.googleapis.com:443')
.get(
`/engine-partial-schema-prod/${storageSecret}/current/raw-partial-schemas/${partialSchemaPath}`,
)
.reply(200, federatedServiceSchema);
Loading

0 comments on commit 1c964c0

Please sign in to comment.