Skip to content

Commit 8db2ff2

Browse files
committed
Add service delete command and mutation
1 parent b242ee8 commit 8db2ff2

5 files changed

Lines changed: 268 additions & 10 deletions

File tree

packages/apollo-language-server/src/engine/index.ts

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import { REGISTER_OPERATIONS } from "./operations/registerOperations";
77
import { SCHEMA_TAGS_AND_FIELD_STATS } from "./operations/schemaTagsAndFieldStats";
88
import { UPLOAD_AND_COMPOSE_PARTIAL_SCHEMA } from "./operations/uploadAndComposePartialSchema";
99
import { CHECK_PARTIAL_SCHEMA } from "./operations/checkPartialSchema";
10+
import { REMOVE_SERVICE_AND_COMPOSE } from "./operations/removeServiceAndCompose";
1011
import {
1112
CheckSchema,
1213
CheckSchemaVariables,
@@ -22,7 +23,9 @@ import {
2223
SchemaTagInfo,
2324
SchemaTagInfoVariables,
2425
CheckPartialSchema,
25-
CheckPartialSchemaVariables
26+
CheckPartialSchemaVariables,
27+
RemoveServiceAndCompose,
28+
RemoveServiceAndComposeVariables
2629
} from "../graphqlTypes";
2730
import { SCHEMA_TAG_INFO_QUERY } from "./operations/schemaTagInfo";
2831

@@ -173,6 +176,25 @@ export class ApolloEngineClient extends GraphQLDataSource {
173176
});
174177
}
175178

179+
public async removeServiceAndCompose(
180+
variables: RemoveServiceAndComposeVariables
181+
) {
182+
return this.execute<RemoveServiceAndCompose>({
183+
query: REMOVE_SERVICE_AND_COMPOSE,
184+
variables
185+
}).then(({ data, errors }) => {
186+
if (errors) {
187+
throw new Error(errors.map(error => error.message).join("\n"));
188+
}
189+
190+
if (!data || !data.service) {
191+
throw new Error("Error in request from Engine");
192+
}
193+
194+
return data.service.removeImplementingServiceAndTriggerComposition;
195+
});
196+
}
197+
176198
public async validateOperations(variables: ValidateOperationsVariables) {
177199
return this.execute<ValidateOperations>({
178200
query: VALIDATE_OPERATIONS,
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
import gql from "graphql-tag";
2+
3+
export const REMOVE_SERVICE_AND_COMPOSE = gql`
4+
mutation RemoveServiceAndCompose(
5+
$id: ID!
6+
$graphVariant: String!
7+
$name: String!
8+
) {
9+
service(id: $id) {
10+
removeImplementingServiceAndTriggerComposition(
11+
graphVariant: $graphVariant
12+
name: $name
13+
) {
14+
compositionConfig {
15+
implementingServiceLocations {
16+
name
17+
path
18+
}
19+
}
20+
errors {
21+
location {
22+
column
23+
line
24+
}
25+
message
26+
}
27+
warnings {
28+
location {
29+
column
30+
line
31+
}
32+
message
33+
}
34+
updatedGateway
35+
}
36+
}
37+
}
38+
`;

packages/apollo-language-server/src/graphqlTypes.ts

Lines changed: 108 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -54,11 +54,11 @@ export interface CheckPartialSchema_service {
5454
__typename: "ServiceMutation";
5555
/**
5656
* This mutation will not result in any changes to the implementing service
57-
*
57+
*
5858
* Run composition with the Implementing Service's partial schema replaced with the one provided
5959
* in the mutation's input. Store the composed schema, return the hash of the composed schema,
6060
* and any warnings and errors pertaining to composition.
61-
*
61+
*
6262
* This mutation will not run validation against operations.
6363
*/
6464
validatePartialSchemaOfImplementingServiceAgainstGraph: CheckPartialSchema_service_validatePartialSchemaOfImplementingServiceAgainstGraph;
@@ -167,11 +167,11 @@ export interface CheckSchema_service {
167167
/**
168168
* Validate, diff, and store a schema so the diff can be viewed by users in the UI.
169169
* This mutation will not mark the schema as "published".
170-
*
170+
*
171171
* One of "proposedSchema" or "proposedSchemaHash" must be provided.
172172
* If both are provided, the computed schema hash will be compared with the input hash,
173173
* an error will be returned if the hashes don't match.
174-
*
174+
*
175175
* If the "proposedSchemaHash" is specified, the already stored schema will be loaded.
176176
*/
177177
checkSchema: CheckSchema_service_checkSchema;
@@ -218,6 +218,106 @@ export interface RegisterOperationsVariables {
218218
/* eslint-disable */
219219
// This file was automatically generated and should not be edited.
220220

221+
// ====================================================
222+
// GraphQL mutation operation: RemoveServiceAndCompose
223+
// ====================================================
224+
225+
export interface RemoveServiceAndCompose_service_removeImplementingServiceAndTriggerComposition_compositionConfig_implementingServices {
226+
__typename: "FederatedImplementingService";
227+
/**
228+
* Identifies which graph this implementing service belongs to.
229+
* Formerly known as "service_id"
230+
*/
231+
graphID: string;
232+
/**
233+
* Specifies which variant of a graph this implementing service belongs to".
234+
* Formerly known as "tag"
235+
*/
236+
graphVariant: string;
237+
name: string;
238+
path: string;
239+
}
240+
241+
export interface RemoveServiceAndCompose_service_removeImplementingServiceAndTriggerComposition_compositionConfig {
242+
__typename: "CompositionConfig";
243+
/**
244+
* List of implementing services that comprise a composed graph
245+
*/
246+
implementingServices: RemoveServiceAndCompose_service_removeImplementingServiceAndTriggerComposition_compositionConfig_implementingServices[];
247+
}
248+
249+
export interface RemoveServiceAndCompose_service_removeImplementingServiceAndTriggerComposition_errors_location {
250+
__typename: "SourceLocation";
251+
column: number;
252+
line: number;
253+
}
254+
255+
export interface RemoveServiceAndCompose_service_removeImplementingServiceAndTriggerComposition_errors {
256+
__typename: "SchemaCompositionError";
257+
location: RemoveServiceAndCompose_service_removeImplementingServiceAndTriggerComposition_errors_location;
258+
message: string;
259+
}
260+
261+
export interface RemoveServiceAndCompose_service_removeImplementingServiceAndTriggerComposition_warnings_location {
262+
__typename: "SourceLocation";
263+
column: number;
264+
line: number;
265+
}
266+
267+
export interface RemoveServiceAndCompose_service_removeImplementingServiceAndTriggerComposition_warnings {
268+
__typename: "SchemaCompositionWarning";
269+
location: RemoveServiceAndCompose_service_removeImplementingServiceAndTriggerComposition_warnings_location;
270+
message: string;
271+
}
272+
273+
export interface RemoveServiceAndCompose_service_removeImplementingServiceAndTriggerComposition {
274+
__typename: "CompositionResult";
275+
/**
276+
* The produced composition config. Will be null if there are any errors
277+
*/
278+
compositionConfig: RemoveServiceAndCompose_service_removeImplementingServiceAndTriggerComposition_compositionConfig | null;
279+
/**
280+
* List of errors during composition. Errors mean that Apollo was unable to compose the
281+
* graph's implementing services into a GraphQL schema. This partial schema should not be
282+
* published to the implementing service if there were any errors encountered
283+
*/
284+
errors: (RemoveServiceAndCompose_service_removeImplementingServiceAndTriggerComposition_errors | null)[];
285+
/**
286+
* List of warnings encountered during composing implementing services into a complete schema.
287+
* Though a schema was composed for the graph with the proposed partial schema,
288+
* these warnings may indicate undesired behavior or lost information. We recommend that no service
289+
* is pushed with warnings that are not fully understood. Pushing an implementing service with warnings
290+
* in its composition result will result in updating the composition config.
291+
*/
292+
warnings: (RemoveServiceAndCompose_service_removeImplementingServiceAndTriggerComposition_warnings | null)[];
293+
/**
294+
* Whether the gateway link was updated.
295+
*/
296+
updatedGateway: boolean;
297+
}
298+
299+
export interface RemoveServiceAndCompose_service {
300+
__typename: "ServiceMutation";
301+
/**
302+
* Remove an implementing service from a graph and update its service list manifest
303+
*/
304+
removeImplementingServiceAndTriggerComposition: RemoveServiceAndCompose_service_removeImplementingServiceAndTriggerComposition;
305+
}
306+
307+
export interface RemoveServiceAndCompose {
308+
service: RemoveServiceAndCompose_service | null;
309+
}
310+
311+
export interface RemoveServiceAndComposeVariables {
312+
id: string;
313+
graphVariant: string;
314+
name: string;
315+
}
316+
317+
/* tslint:disable */
318+
/* eslint-disable */
319+
// This file was automatically generated and should not be edited.
320+
221321
// ====================================================
222322
// GraphQL query operation: SchemaTagInfo
223323
// ====================================================
@@ -388,10 +488,10 @@ export interface UploadAndComposePartialSchema_service {
388488
/**
389489
* Creates or updates an implementing service of a given "name" on the graph variant, then
390490
* updates the graph variant's composition configs/artifacts to reflect these changes.
391-
*
491+
*
392492
* An enriched SDL of the implementing service can be uploaded
393493
* via "implementingServiceConfiguration.partialSchema.partialSchemaSDL".
394-
*
494+
*
395495
* Alternatively, previously uploaded partial schema could be re-associated with the
396496
* implementing service via "implementingServiceConfiguration.partialSchema.partialSchemaHash".
397497
*/
@@ -1595,10 +1695,10 @@ export interface OperationDocumentInput {
15951695
/**
15961696
* Input for registering a partial schema to an implementing service.
15971697
* One of the fields must be specified (validated server-side).
1598-
*
1698+
*
15991699
* If a new partialSchemaSDL is passed in, this operation will store it before
16001700
* creating the association.
1601-
*
1701+
*
16021702
* If both the sdl and hash are specified, an error will be thrown if the provided
16031703
* hash doesn't match our hash of the sdl contents
16041704
*/
Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
import { flags } from "@oclif/command";
2+
import { table } from "heroku-cli-util";
3+
import { introspectionFromSchema } from "graphql";
4+
5+
import { gitInfo } from "../../git";
6+
import { ProjectCommand } from "../../Command";
7+
import { GraphQLServiceProject } from "apollo-language-server";
8+
9+
export default class ServiceDelete extends ProjectCommand {
10+
static description =
11+
"Delete a federated service from Engine and recompose remaining services";
12+
static flags = {
13+
...ProjectCommand.flags,
14+
tag: flags.string({
15+
char: "t",
16+
description: "The variant of the service to delete",
17+
default: "current"
18+
}),
19+
federated: flags.boolean({
20+
char: "f",
21+
default: false,
22+
description:
23+
"Indicates that the schema is a partial schema from a federated service"
24+
}),
25+
serviceName: flags.string({
26+
required: true,
27+
description:
28+
"Provides the name of the implementing service for a federated graph"
29+
})
30+
};
31+
32+
async run() {
33+
let result;
34+
await this.runTasks(({ flags, project, config }) => [
35+
{
36+
title: "Removing service from Engine",
37+
task: async () => {
38+
if (!config.name) {
39+
throw new Error("No service found to link to Engine");
40+
}
41+
42+
if (!flags.federated) {
43+
this.error(
44+
"Deleting a service is only supported for federated services. Use the --federated flag if this is a federated service."
45+
);
46+
}
47+
48+
const {
49+
// compositionConfig,
50+
errors,
51+
warnings,
52+
updatedGateway
53+
} = await project.engine.removeServiceAndCompose({
54+
id: config.name,
55+
graphVariant: config.tag,
56+
name: flags.serviceName // XXX should this also use queried service info?
57+
});
58+
59+
result = {
60+
serviceName: flags.serviceName,
61+
graphVariant: config.tag,
62+
graphName: config.name,
63+
warnings,
64+
errors,
65+
updatedGateway
66+
};
67+
68+
return;
69+
}
70+
}
71+
]);
72+
73+
this.log("\n");
74+
75+
if (result.errors && result.errors.length) {
76+
this.error(result.errors.join("\n"));
77+
}
78+
79+
if (result.warnings && result.warnings.length) {
80+
this.warn(result.warnings.join("\n"));
81+
}
82+
83+
if (result.updatedGateway) {
84+
this.log(
85+
`The ${result.serviceName} service with ${
86+
result.graphVariant
87+
} tag was removed from ${
88+
result.graphName
89+
}. Remaining services were composed.`
90+
);
91+
this.log("\n");
92+
this.log("\n");
93+
}
94+
}
95+
}

packages/apollo/src/commands/service/push.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,10 @@ export default class ServicePush extends ProjectCommand {
8686
graphVariant: config.tag,
8787
name: flags.serviceName || info.name,
8888
url: flags.serviceURL || info.url,
89-
revision: flags.serviceRevision || gitContext.commit,
89+
revision:
90+
flags.serviceRevision ||
91+
(gitContext && gitContext.commit) ||
92+
"",
9093
activePartialSchema: {
9194
sdl: info.sdl
9295
}

0 commit comments

Comments
 (0)