Skip to content

Commit

Permalink
Merge pull request #295 from apollographql/adam/20/3/prefer-graph-var…
Browse files Browse the repository at this point in the history
…iant

Update op-reg plugin to use graphVariant and add support for APOLLO_GRAPH_VARIANT
  • Loading branch information
zionts authored Apr 23, 2020
2 parents 68cfe4d + 7663551 commit 0a38454
Show file tree
Hide file tree
Showing 7 changed files with 34 additions and 25 deletions.
4 changes: 4 additions & 0 deletions packages/apollo-server-plugin-operation-registry/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
# Change Log

### Upcoming

- Deprecate schemaTag option, add preferred graphVariant option [PR #295](https://github.com/apollographql/apollo-platform-commercial/pull/295)

### vNEXT (Currently `alpha` tag)

- Add lifecycle hooks: `onUnregisteredOperation`, and `onForbiddenOperation`. [PR #158](https://github.com/apollographql/apollo-platform-commercial/pull/158) [PR #251](https://github.com/apollographql/apollo-platform-commercial/pull/251) [PR #TODO](https://github.com/apollographql/apollo-platform-commercial/pull/TODO)
Expand Down
12 changes: 6 additions & 6 deletions packages/apollo-server-plugin-operation-registry/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

The operation registry plugin is the interface into the Apollo Platform's **operation registry** and enables operation **safelisting**, which allows selective execution based on the operation. Safelisting eliminates the risk of unexpected operations that could cause downtime from being run against a graph.

In order to enable safelisting, follow the [step by step guide in the Apollo docs](https://www.apollographql.com/docs/platform/operation-registry/). These steps describe how to extract and upload operations defined within client applications to the [Apollo Graph Manager](https://engine.apollographql.com) using the Apollo CLI. Once operations have been registered, this plugin for Apollo Server fetches the manifest of these operations from the [Apollo Graph Manager](https://engine.apollographql.com) and forbids the execution of any operations that are not in that manifest.
In order to enable safelisting, follow the [step by step guide in the Apollo docs](https://www.apollographql.com/docs/platform/operation-registry/). These steps describe how to extract and upload operations defined within client applications to the [Apollo Graph Manager](https://engine.apollographql.com) using the Apollo CLI. Once operations have been registered, this plugin for Apollo Server fetches the manifest of these operations from the [Apollo Graph Manager](https://engine.apollographql.com) and forbids the execution of any operations that are not in that manifest.

### Usage

Expand Down Expand Up @@ -59,15 +59,15 @@ server.listen().then(({ url }) => {
```
</details>

#### Schema Tag/Variant
#### Variant

Clients can register their operations to specific tags/variants, so the plugin contains the `schemaTag` field to specify which tag/variant to pull operation manifests from.
Clients can register their operations to a specific variant, so the plugin contains the `graphVariant` field to specify which variant to pull operation manifests from.

```js
const server = new ApolloServer({
plugins: [
require("apollo-server-plugin-operation-registry")({
schemaTag: "overrideTag"
graphVariant: "production"
})
]
});
Expand All @@ -76,11 +76,11 @@ const server = new ApolloServer({

### Metrics

The plugin will transmit metrics regarding unregistered operations which can be viewed within [the Apollo Graph Manager](https://engine.apollographql.com). The following example shows the unregistered operations sent by a particular client:
The plugin will transmit metrics regarding unregistered operations which can be viewed within [the Apollo Graph Manager](https://engine.apollographql.com). The following example shows the unregistered operations sent by a particular client:

<p align="center">
<img
src="https://cl.ly/2a5b9c82287d/download/clients-page.png"
alt="The clients page showing unregistered operations"
/>
/>
</p>
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ export interface Options {
| ForbidUnregisteredOperationsPredicate;
dryRun?: boolean;
schemaTag?: string;
graphVariant?: string;
onUnregisteredOperation?: (
requestContext: GraphQLRequestContext,
operationRegistryRequestContext: OperationRegistryRequestContext,
Expand All @@ -63,7 +64,13 @@ export interface Options {
export default function plugin(options: Options = Object.create(null)) {
let agent: Agent;
let store: InMemoryLRUCache;
let schemaTag = options.schemaTag || 'current';
const graphVariant = options.graphVariant || options.schemaTag || process.env.APOLLO_GRAPH_VARIANT || 'current';
if (options.graphVariant && options.schemaTag) {
throw new Error('Cannot specify both graphVariant and schemaTag. Please use graphVariant.');
}
if (options.schemaTag) {
console.warn('[Deprecation warning] schemaTag option is deprecated. Please use graphVariant options instead.');
}

// Setup logging facilities, scoped under the appropriate name.
const logger = loglevel.getLogger(`apollo-server:${pluginName}`);
Expand Down Expand Up @@ -109,7 +116,7 @@ for observability purposes, but all operations will be permitted.`,

if (!engine || !engine.serviceID) {
const messageEngineConfigurationRequired =
'The Engine API key must be set to use the operation registry.';
'The Apollo API key must be set to use the operation registry.';
throw new Error(`${pluginName}: ${messageEngineConfigurationRequired}`);
}

Expand All @@ -125,7 +132,7 @@ for observability purposes, but all operations will be permitted.`,

agent = new Agent({
schemaHash,
schemaTag,
graphVariant,
engine,
store,
logger,
Expand Down Expand Up @@ -211,9 +218,7 @@ for observability purposes, but all operations will be permitted.`,
let shouldForbidOperation: boolean =
typeof options.forbidUnregisteredOperations === 'boolean'
? options.forbidUnregisteredOperations
: typeof options.forbidUnregisteredOperations === 'function'
? true
: false;
: typeof options.forbidUnregisteredOperations === 'function';

if (typeof options.forbidUnregisteredOperations === 'function') {
logger.debug(
Expand Down Expand Up @@ -301,7 +306,7 @@ for observability purposes, but all operations will be permitted.`,
Object.assign(error.extensions, {
operationSignature: signature,
exception: {
message: `Please register your operation with \`npx apollo client:push --tag="${schemaTag}"\`. See https://www.apollographql.com/docs/platform/operation-registry/ for more details.`,
message: `Please register your operation with \`npx apollo client:push --tag="${graphVariant}"\`. See https://www.apollographql.com/docs/platform/operation-registry/ for more details.`,
},
});
throw error;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -442,8 +442,8 @@ describe('Agent', () => {
});
});

describe('When given a schemaTag', () => {
const schemaTag = 'master';
describe('When given a graphVariant', () => {
const graphVariant = 'master';
const getOperationManifestRelativeUrl = (
...args: Parameters<typeof getOperationManifestUrl>
) =>
Expand All @@ -454,13 +454,13 @@ describe('Agent', () => {

it('fetches manifests for the corresponding schema tag', async () => {
nockStorageSecret(genericServiceID, genericApiKeyHash);
const agent = createAgent({ schemaTag });
const agent = createAgent({ graphVariant: graphVariant });
const nockedManifest = nockBase()
.get(
getOperationManifestRelativeUrl(
genericServiceID,
genericStorageSecret,
schemaTag,
graphVariant,
),
)
.reply(200, manifest(sampleManifestRecords.a));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ export const defaultAgentOptions: AgentOptions = {
engine: { serviceID: genericServiceID, apiKeyHash: genericApiKeyHash },
store: defaultStore(),
pollSeconds: defaultTestAgentPollSeconds,
schemaTag: 'current',
graphVariant: 'current',
};

// Each nock is good for exactly one request!
Expand Down
10 changes: 5 additions & 5 deletions packages/apollo-server-plugin-operation-registry/src/agent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ export interface AgentOptions {
schemaHash: string;
engine: any;
store: InMemoryLRUCache;
schemaTag: string;
graphVariant: string;
}

type SignatureStore = Set<string>;
Expand Down Expand Up @@ -181,9 +181,9 @@ export default class Agent {

private async fetchLegacyManifest(): Promise<Response> {
this.logger.debug(`Fetching legacy manifest.`);
if (this.options.schemaTag !== 'current') {
if (this.options.graphVariant !== 'current') {
this.logger.warn(
`The legacy manifest contains operations registered for the "current" tag, but the specified schema tag is "${this.options.schemaTag}".`,
`The legacy manifest contains operations registered for the "current" variant, but the specified variant is "${this.options.graphVariant}".`,
);
}
const legacyManifestUrl = getLegacyOperationManifestUrl(
Expand All @@ -206,7 +206,7 @@ export default class Agent {
const storageSecretManifestUrl = getOperationManifestUrl(
this.options.engine.serviceID,
storageSecret,
this.options.schemaTag,
this.options.graphVariant,
);

this.logger.debug(
Expand All @@ -219,7 +219,7 @@ export default class Agent {

if (response.status === 404 || response.status === 403) {
this.logger.warn(
`No manifest found for tag "${this.options.schemaTag}" at ${storageSecretManifestUrl}. ${callToAction}`,
`No manifest found for tag "${this.options.graphVariant}" at ${storageSecretManifestUrl}. ${callToAction}`,
);
return this.fetchLegacyManifest();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,9 +52,9 @@ export function getStorageSecretUrl(
export function getOperationManifestUrl(
graphId: string,
storageSecret: string,
schemaTag: string = 'current',
graphVariant: string = 'current',
): string {
return `${urlOperationManifestBase}/${graphId}/${storageSecret}/${schemaTag}/manifest.v2.json`;
return `${urlOperationManifestBase}/${graphId}/${storageSecret}/${graphVariant}/manifest.v2.json`;
}

export function getLegacyOperationManifestUrl(
Expand Down

0 comments on commit 0a38454

Please sign in to comment.