Skip to content

Commit 9561c90

Browse files
committed
Update e fix dipendenze
Added stitched schemas Fixed stitched schemas k8s-harbor fix package.json Fix Harbor token and deleted comments Fix up
1 parent f9a1b72 commit 9561c90

15 files changed

+2046
-2986
lines changed

deploy/crownlabs/values.yaml

+1
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ qlkube:
2828
rbacResourcesName: crownlabs-qlkube
2929
ingress:
3030
hostname: qlkube.crownlabs.example.com
31+
harborToken: {}
3132
configuration:
3233
exposedAPIs:
3334
apis:

qlkube/.gitignore

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
node_modules
2-
.env
2+
.env
3+
.harbor_token.json
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
apiVersion: v1
2+
kind: Secret
3+
metadata:
4+
name: {{ include "qlkube.fullname" . }}-harbor-token
5+
labels:
6+
{{- include "qlkube.labels" . | nindent 4 }}
7+
type: Opaque
8+
stringData:
9+
harbor_token.json: |
10+
{{ .Values.harborToken | toJson | ndent 4 }}

qlkube/deploy/qlkube/values.yaml

+2
Original file line numberDiff line numberDiff line change
@@ -91,3 +91,5 @@ resources:
9191
memory: 250Mi
9292

9393
rbacResourcesName: crownlabs-qlkube
94+
95+
harborToken: {}

qlkube/package.json

+22-13
Original file line numberDiff line numberDiff line change
@@ -24,25 +24,34 @@
2424
"homepage": "https://github.com/netgroup-polito/CrownLabs/qlkube#readme",
2525
"devDependencies": {
2626
"husky": "^6.0.0",
27-
"lint-staged": "^10.5.4",
27+
"lint-staged": "15.2.7",
2828
"nodemon": "^2.0.7",
2929
"prettier": "^2.2.1"
3030
},
3131
"dependencies": {
32-
"@graphql-tools/schema": "^7.1.4",
33-
"@kubernetes/client-node": "^0.15.1",
34-
"apollo-server": "2.25.4",
35-
"apollo-server-express": "^2.25.1",
32+
"@apollo/server": "^4.10.4",
33+
"@apollo/server-plugin-landing-page-graphql-playground": "^4.0.1",
34+
"@graphql-tools/schema": "10.0.4",
35+
"@graphql-tools/stitch": "^9.2.9",
36+
"@graphql-tools/wrap": "10.0.5",
37+
"@kubernetes/client-node": "^0.21.0",
38+
"apollo-link-http": "^1.5.17",
39+
"body-parser": "^1.20.2",
3640
"compression": "^1.7.4",
3741
"dotenv": "^9.0.2",
3842
"express": "^4.19.2",
39-
"express-graphql": "^0.12.0",
40-
"got": "^9.6.0",
41-
"graphql": "^15.5.1",
42-
"graphql-tools": "^8.1.0",
43-
"oasgraph": "^0.14.3",
44-
"pino": "^5.13.6",
45-
"promise-any": "^0.2.0"
43+
"got": "^12.6.1",
44+
"graphql": "^16.9.0",
45+
"graphql-http": "^1.22.1",
46+
"graphql-subscriptions": "^2.0.0",
47+
"graphql-tag": "^2.12.6",
48+
"graphql-tools": "9.0.1",
49+
"graphql-ws": "^5.16.0",
50+
"node-fetch": "^3.3.2",
51+
"openapi-to-graphql": "^3.0.7",
52+
"pino": "^9.2.0",
53+
"promise-any": "^0.2.0",
54+
"ws": "^8.17.1"
4655
},
4756
"prettier": {
4857
"printWidth": 80,
@@ -56,7 +65,7 @@
5665
"*.{ts,tsx,js,jsx,json,css}": "prettier --write"
5766
},
5867
"resolutions": {
59-
"yargs-parser": "20.2.2",
68+
"yargs-parser": "21.1.1",
6069
"ansi-regex": "^5.0.1"
6170
}
6271
}

qlkube/src/decorateBaseSchema.js

+6-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
const { gql } = require('apollo-server-core');
1+
const { gql } = require('graphql-tag');
22
const { extendSchema } = require('graphql/utilities');
33
const { addResolversToSchema } = require('@graphql-tools/schema');
44
const { capitalizeType, graphqlLogger } = require('./utils.js');
@@ -67,7 +67,11 @@ function decorateBaseSchema(
6767
};
6868

6969
const extendedSchema = extendSchema(baseSchema, extension);
70-
const newSchema = addResolversToSchema(extendedSchema, resolvers);
70+
const newSchema = addResolversToSchema({
71+
schema: extendedSchema,
72+
resolvers: resolvers,
73+
});
74+
7175
return newSchema;
7276
}
7377

qlkube/src/decorateSubscription.js

+11-4
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
1-
const { withFilter } = require('apollo-server');
2-
const { gql, ForbiddenError } = require('apollo-server-core');
1+
const { ForbiddenError } = require('@apollo/server');
2+
const { withFilter } = require('graphql-subscriptions');
3+
const { gql } = require('graphql-tag');
34
const { addResolversToSchema } = require('@graphql-tools/schema');
45
const { extendSchema } = require('graphql/utilities');
56
const { pubsubAsyncIterator } = require('./pubsub');
@@ -389,7 +390,10 @@ function decorateSubscription(baseSchema, targetType, enumType, kubeApiUrl) {
389390
};
390391

391392
const extendedSchema = extendSchema(baseSchema, extension);
392-
const newSchema = addResolversToSchema(extendedSchema, resolvers);
393+
const newSchema = addResolversToSchema({
394+
schema: extendedSchema,
395+
resolvers: resolvers,
396+
});
393397
newSchema._subscriptionType = newSchema._typeMap.Subscription;
394398
return newSchema;
395399
}
@@ -598,7 +602,10 @@ function decorateLabelsSubscription(
598602
};
599603

600604
const extendedSchema = extendSchema(baseSchema, extension);
601-
const newSchema = addResolversToSchema(extendedSchema, resolvers);
605+
const newSchema = addResolversToSchema({
606+
schema: extendedSchema,
607+
resolvers: resolvers,
608+
});
602609
newSchema._subscriptionType = newSchema._typeMap.Subscription;
603610
return newSchema;
604611
}

qlkube/src/index.js

+90-30
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,26 @@
1-
const { ApolloServer } = require('apollo-server-express');
1+
const { ApolloServer } = require('@apollo/server');
2+
const { expressMiddleware } = require('@apollo/server/express4');
3+
const {
4+
ApolloServerPluginDrainHttpServer,
5+
} = require('@apollo/server/plugin/drainHttpServer');
26
const compression = require('compression');
37
const dotenv = require('dotenv');
48
const express = require('express');
59
const fs = require('fs').promises;
610
const { printSchema } = require('graphql');
11+
const {
12+
ApolloServerPluginLandingPageGraphQLPlayground,
13+
} = require('@apollo/server-plugin-landing-page-graphql-playground');
714
const { createServer } = require('http');
15+
const { WebSocketServer } = require('ws');
16+
const bodyParser = require('body-parser');
17+
const { useServer } = require('graphql-ws/lib/use/ws');
818
const logger = require('pino')({ useLevelLabels: true });
919
const { setupSubscriptions } = require('./decorateSubscription.js');
10-
const getOpenApiSpec = require('./oas');
20+
const { getOpenApiSpec } = require('./oas');
1121
const { decorateOpenapi } = require('./decorateOpenapi');
12-
const { createSchema } = require('./schema');
22+
const { joinSchemas } = require('./joinSchemas.js');
23+
const { createSchema, createHarborSchema } = require('./schema');
1324
const { subscriptions } = require('./subscriptions.js');
1425
const { kinformer } = require('./informer.js');
1526
const {
@@ -18,6 +29,8 @@ const {
1829
graphqlLogger,
1930
} = require('./utils.js');
2031

32+
const repl = require('repl');
33+
2134
dotenv.config();
2235

2336
main().catch(e =>
@@ -30,6 +43,7 @@ async function main() {
3043
const kubeApiUrl = inCluster
3144
? 'https://kubernetes.default.svc'
3245
: 'http://localhost:8001';
46+
const harborApiUrl = 'https://harbor.crownlabs.polito.it';
3347
const inClusterToken = inCluster
3448
? await fs.readFile(
3549
'/var/run/secrets/kubernetes.io/serviceaccount/token',
@@ -38,21 +52,70 @@ async function main() {
3852
: '';
3953
const oas = await getOpenApiSpec(kubeApiUrl, inClusterToken);
4054
const targetOas = decorateOpenapi(oas);
41-
let schema = await createSchema(targetOas, kubeApiUrl, inClusterToken);
55+
56+
const harborToken = JSON.parse(
57+
await fs.readFile(
58+
inCluster ? '/var/run/secrets/harbor_token.json' : './.harbor_token.json',
59+
'utf8'
60+
)
61+
);
62+
63+
const harborOas = await getOpenApiSpec(harborApiUrl, harborToken);
64+
65+
let kubeSchema = await createSchema(targetOas, kubeApiUrl, inClusterToken);
66+
let harborSchema = await createHarborSchema(
67+
harborOas,
68+
harborApiUrl,
69+
harborToken
70+
);
71+
72+
let schema = joinSchemas(kubeSchema, harborSchema);
73+
4274
try {
4375
schema = setupSubscriptions(subscriptions, schema, kubeApiUrl);
4476
} catch (e) {
4577
console.error(e);
4678
process.exit(1);
4779
}
4880

81+
const app = express();
82+
app.use(compression());
83+
app.use(bodyParser.json());
84+
85+
app.get('/schema', (req, res) => {
86+
res.setHeader('content-type', 'text/plain');
87+
res.send(
88+
printSchema(schema)
89+
.split('\n')
90+
.filter(l => l.trim() != '_') // remove empty values from enums
91+
.join('\n')
92+
);
93+
});
94+
app.get('/healthz', (req, res) => {
95+
res.sendStatus(200);
96+
});
97+
98+
const httpServer = createServer(app);
99+
49100
const server = new ApolloServer({
50101
schema,
51102
playground: true,
52-
plugins: [graphqlQueryRegistry],
103+
plugins: [
104+
ApolloServerPluginDrainHttpServer({ httpServer: httpServer }),
105+
ApolloServerPluginLandingPageGraphQLPlayground(),
106+
{
107+
async serverWillStart() {
108+
return {
109+
async drainServer() {
110+
await serverCleanup.dispose();
111+
},
112+
};
113+
},
114+
},
115+
],
53116
formatError: error => {
54117
try {
55-
const msgs = [...error.message.match(/(\d+)\s*\-(.*)$/)];
118+
const msgs = [...(error.message.match(/(\d+)\s*\-(.*)$/) || [])];
56119
if (msgs.length != 3) return error;
57120
let msg = JSON.parse(msgs[2]);
58121
try {
@@ -84,7 +147,7 @@ async function main() {
84147
},
85148
},
86149

87-
context: ({ req, connection }) => {
150+
context: async ({ req, connection }) => {
88151
if (connection) {
89152
const { token } = connection.context;
90153
return { token };
@@ -96,36 +159,33 @@ async function main() {
96159
},
97160
});
98161

99-
const app = express();
100-
app.use(compression());
101-
app.get('/schema', (req, res) => {
102-
res.setHeader('content-type', 'text/plain');
103-
res.send(
104-
printSchema(schema)
105-
.split('\n')
106-
.filter(l => l.trim() != '_') // remove empty values from enums
107-
.join('\n')
108-
);
109-
});
110-
app.get('/healthz', (req, res) => {
111-
res.sendStatus(200);
112-
});
113-
server.applyMiddleware({
114-
app,
115-
path: '/',
162+
await server.start();
163+
164+
app.use(
165+
'/',
166+
expressMiddleware(server, {
167+
context: async ({ req }) => {
168+
const token = getBearerToken(req.headers);
169+
return { token };
170+
},
171+
})
172+
);
173+
174+
const wsServer = new WebSocketServer({
175+
server: httpServer,
176+
path: '/subscriptions',
116177
});
117-
const httpServer = createServer(app);
118-
server.installSubscriptionHandlers(httpServer);
178+
const serverCleanup = useServer({ schema }, wsServer);
119179

120180
const PORT = process.env.CROWNLABS_QLKUBE_PORT || 8080;
121181

122182
httpServer.listen({ port: PORT }, () => {
183+
console.log(`🚀 Server ready at http://localhost:${PORT}/`);
123184
console.log(
124-
`🚀 Server ready at http://localhost:${PORT}${server.graphqlPath}`
125-
);
126-
console.log(
127-
`🚀 Subscriptions ready at ws://localhost:${PORT}${server.subscriptionsPath}`
185+
`🚀 Subscriptions ready at ws://localhost:${PORT}/subscriptions`
128186
);
187+
global.harborSchema = harborSchema;
188+
repl.start('> ');
129189
});
130190

131191
/**

qlkube/src/joinSchemas.js

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
const { stitchSchemas } = require('@graphql-tools/stitch');
2+
const { RenameRootFields } = require('@graphql-tools/wrap');
3+
4+
module.exports.joinSchemas = (kubeSchema, harborSchema) => {
5+
let schema = stitchSchemas({
6+
subschemas: [
7+
{
8+
schema: kubeSchema,
9+
},
10+
{
11+
schema: harborSchema,
12+
transforms: [
13+
new RenameRootFields((operation, name, field) => {
14+
return 'reg_' + name;
15+
}),
16+
],
17+
},
18+
],
19+
});
20+
return schema;
21+
};

0 commit comments

Comments
 (0)