Skip to content

Commit ef71e96

Browse files
authored
Delete federated service (#1192)
* Add service delete command and mutation * update checks operation to match new schema
1 parent 8013a0f commit ef71e96

6 files changed

Lines changed: 253 additions & 4 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+
locations {
22+
column
23+
line
24+
}
25+
message
26+
}
27+
warnings {
28+
locations {
29+
column
30+
line
31+
}
32+
message
33+
}
34+
updatedGateway
35+
}
36+
}
37+
}
38+
`;

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

Lines changed: 97 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ export interface CheckPartialSchema_service_validatePartialSchemaOfImplementingS
1111
/**
1212
* Hash of the composed schema
1313
*/
14-
schemaHash: string;
14+
schemaHash: string | null;
1515
}
1616

1717
export interface CheckPartialSchema_service_validatePartialSchemaOfImplementingServiceAgainstGraph_errors {
@@ -216,6 +216,102 @@ export interface RegisterOperationsVariables {
216216
/* eslint-disable */
217217
// This file was automatically generated and should not be edited.
218218

219+
// ====================================================
220+
// GraphQL mutation operation: RemoveServiceAndCompose
221+
// ====================================================
222+
223+
export interface RemoveServiceAndCompose_service_removeImplementingServiceAndTriggerComposition_compositionConfig_implementingServiceLocations {
224+
__typename: "ImplementingServiceLocation";
225+
/**
226+
* The name of the implementing service
227+
*/
228+
name: string;
229+
/**
230+
* The path in storage to access the implementing service config file
231+
*/
232+
path: string;
233+
}
234+
235+
export interface RemoveServiceAndCompose_service_removeImplementingServiceAndTriggerComposition_compositionConfig {
236+
__typename: "CompositionConfig";
237+
/**
238+
* List of implementing services that comprise a composed graph
239+
*/
240+
implementingServiceLocations: RemoveServiceAndCompose_service_removeImplementingServiceAndTriggerComposition_compositionConfig_implementingServiceLocations[];
241+
}
242+
243+
export interface RemoveServiceAndCompose_service_removeImplementingServiceAndTriggerComposition_errors_locations {
244+
__typename: "SourceLocation";
245+
column: number;
246+
line: number;
247+
}
248+
249+
export interface RemoveServiceAndCompose_service_removeImplementingServiceAndTriggerComposition_errors {
250+
__typename: "SchemaCompositionError";
251+
locations: (RemoveServiceAndCompose_service_removeImplementingServiceAndTriggerComposition_errors_locations | null)[];
252+
message: string;
253+
}
254+
255+
export interface RemoveServiceAndCompose_service_removeImplementingServiceAndTriggerComposition_warnings_locations {
256+
__typename: "SourceLocation";
257+
column: number;
258+
line: number;
259+
}
260+
261+
export interface RemoveServiceAndCompose_service_removeImplementingServiceAndTriggerComposition_warnings {
262+
__typename: "SchemaCompositionWarning";
263+
locations: (RemoveServiceAndCompose_service_removeImplementingServiceAndTriggerComposition_warnings_locations | null)[];
264+
message: string;
265+
}
266+
267+
export interface RemoveServiceAndCompose_service_removeImplementingServiceAndTriggerComposition {
268+
__typename: "CompositionAndRemoveResult";
269+
/**
270+
* The produced composition config. Will be null if there are any errors
271+
*/
272+
compositionConfig: RemoveServiceAndCompose_service_removeImplementingServiceAndTriggerComposition_compositionConfig | null;
273+
/**
274+
* List of errors during composition. Errors mean that Apollo was unable to compose the
275+
* graph's implementing services into a GraphQL schema. This partial schema should not be
276+
* published to the implementing service if there were any errors encountered
277+
*/
278+
errors: (RemoveServiceAndCompose_service_removeImplementingServiceAndTriggerComposition_errors | null)[];
279+
/**
280+
* List of warnings encountered during composing implementing services into a complete schema.
281+
* Though a schema was composed for the graph with the proposed partial schema,
282+
* these warnings may indicate undesired behavior or lost information. We recommend that no service
283+
* is pushed with warnings that are not fully understood. Pushing an implementing service with warnings
284+
* in its composition result will result in updating the composition config.
285+
*/
286+
warnings: (RemoveServiceAndCompose_service_removeImplementingServiceAndTriggerComposition_warnings | null)[];
287+
/**
288+
* Whether the gateway link was updated.
289+
*/
290+
updatedGateway: boolean;
291+
}
292+
293+
export interface RemoveServiceAndCompose_service {
294+
__typename: "ServiceMutation";
295+
/**
296+
* Remove an implementing service from a graph and update its service list manifest
297+
*/
298+
removeImplementingServiceAndTriggerComposition: RemoveServiceAndCompose_service_removeImplementingServiceAndTriggerComposition;
299+
}
300+
301+
export interface RemoveServiceAndCompose {
302+
service: RemoveServiceAndCompose_service | null;
303+
}
304+
305+
export interface RemoveServiceAndComposeVariables {
306+
id: string;
307+
graphVariant: string;
308+
name: string;
309+
}
310+
311+
/* tslint:disable */
312+
/* eslint-disable */
313+
// This file was automatically generated and should not be edited.
314+
219315
// ====================================================
220316
// GraphQL query operation: SchemaTagInfo
221317
// ====================================================

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ interface TasksOutput {
8888
federation?: {
8989
errors: ({ message: string } | null)[];
9090
warnings: ({ message: string } | null)[];
91-
schemaHash?: string;
91+
schemaHash?: string | null;
9292
};
9393
}
9494

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
import { flags } from "@oclif/command";
2+
3+
import { ProjectCommand } from "../../Command";
4+
5+
export default class ServiceDelete extends ProjectCommand {
6+
static description =
7+
"Delete a federated service from Engine and recompose remaining services";
8+
static flags = {
9+
...ProjectCommand.flags,
10+
tag: flags.string({
11+
char: "t",
12+
description: "The variant of the service to delete"
13+
}),
14+
federated: flags.boolean({
15+
char: "f",
16+
default: false,
17+
description:
18+
"Indicates that the schema is a partial schema from a federated service"
19+
}),
20+
serviceName: flags.string({
21+
required: true,
22+
description:
23+
"Provides the name of the implementing service for a federated graph"
24+
})
25+
};
26+
27+
async run() {
28+
let result;
29+
await this.runTasks(({ flags, project, config }) => [
30+
{
31+
title: "Removing service from Engine",
32+
task: async () => {
33+
if (!config.name) {
34+
throw new Error("No service found to link to Engine");
35+
}
36+
37+
if (!flags.federated) {
38+
this.error(
39+
"Deleting a service is only supported for federated services. Use the --federated flag if this is a federated service."
40+
);
41+
}
42+
43+
const graphVariant = flags.tag || config.tag || "current";
44+
45+
const {
46+
errors,
47+
warnings,
48+
updatedGateway
49+
} = await project.engine.removeServiceAndCompose({
50+
id: config.name,
51+
graphVariant,
52+
name: flags.serviceName
53+
});
54+
55+
result = {
56+
serviceName: flags.serviceName,
57+
graphVariant,
58+
graphName: config.name,
59+
warnings,
60+
errors,
61+
updatedGateway
62+
};
63+
64+
return;
65+
}
66+
}
67+
]);
68+
69+
this.log("\n");
70+
71+
if (result.errors && result.errors.length) {
72+
this.error(result.errors.map(error => error.message).join("\n"));
73+
}
74+
75+
if (result.warnings && result.warnings.length) {
76+
this.warn(result.warnings.map(warning => warning.message).join("\n"));
77+
}
78+
79+
if (result.updatedGateway) {
80+
this.log(
81+
`The ${result.serviceName} service with ${
82+
result.graphVariant
83+
} tag was removed from ${
84+
result.graphName
85+
}. Remaining services were composed.`
86+
);
87+
this.log("\n");
88+
}
89+
}
90+
}

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)