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' ) ;
2
6
const compression = require ( 'compression' ) ;
3
7
const dotenv = require ( 'dotenv' ) ;
4
8
const express = require ( 'express' ) ;
5
9
const fs = require ( 'fs' ) . promises ;
6
10
const { printSchema } = require ( 'graphql' ) ;
11
+ const {
12
+ ApolloServerPluginLandingPageGraphQLPlayground,
13
+ } = require ( '@apollo/server-plugin-landing-page-graphql-playground' ) ;
7
14
const { createServer } = require ( 'http' ) ;
15
+ const { WebSocketServer } = require ( 'ws' ) ;
16
+ const bodyParser = require ( 'body-parser' ) ;
17
+ const { useServer } = require ( 'graphql-ws/lib/use/ws' ) ;
8
18
const logger = require ( 'pino' ) ( { useLevelLabels : true } ) ;
9
19
const { setupSubscriptions } = require ( './decorateSubscription.js' ) ;
10
- const getOpenApiSpec = require ( './oas' ) ;
20
+ const { getOpenApiSpec } = require ( './oas' ) ;
11
21
const { decorateOpenapi } = require ( './decorateOpenapi' ) ;
12
- const { createSchema } = require ( './schema' ) ;
22
+ const { joinSchemas } = require ( './joinSchemas.js' ) ;
23
+ const { createSchema, createHarborSchema } = require ( './schema' ) ;
13
24
const { subscriptions } = require ( './subscriptions.js' ) ;
14
25
const { kinformer } = require ( './informer.js' ) ;
15
26
const {
@@ -18,6 +29,8 @@ const {
18
29
graphqlLogger,
19
30
} = require ( './utils.js' ) ;
20
31
32
+ const repl = require ( 'repl' ) ;
33
+
21
34
dotenv . config ( ) ;
22
35
23
36
main ( ) . catch ( e =>
@@ -30,6 +43,7 @@ async function main() {
30
43
const kubeApiUrl = inCluster
31
44
? 'https://kubernetes.default.svc'
32
45
: 'http://localhost:8001' ;
46
+ const harborApiUrl = 'https://harbor.crownlabs.polito.it' ;
33
47
const inClusterToken = inCluster
34
48
? await fs . readFile (
35
49
'/var/run/secrets/kubernetes.io/serviceaccount/token' ,
@@ -38,21 +52,70 @@ async function main() {
38
52
: '' ;
39
53
const oas = await getOpenApiSpec ( kubeApiUrl , inClusterToken ) ;
40
54
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
+
42
74
try {
43
75
schema = setupSubscriptions ( subscriptions , schema , kubeApiUrl ) ;
44
76
} catch ( e ) {
45
77
console . error ( e ) ;
46
78
process . exit ( 1 ) ;
47
79
}
48
80
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
+
49
100
const server = new ApolloServer ( {
50
101
schema,
51
102
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
+ ] ,
53
116
formatError : error => {
54
117
try {
55
- const msgs = [ ...error . message . match ( / ( \d + ) \s * \- ( .* ) $ / ) ] ;
118
+ const msgs = [ ...( error . message . match ( / ( \d + ) \s * \- ( .* ) $ / ) || [ ] ) ] ;
56
119
if ( msgs . length != 3 ) return error ;
57
120
let msg = JSON . parse ( msgs [ 2 ] ) ;
58
121
try {
@@ -84,7 +147,7 @@ async function main() {
84
147
} ,
85
148
} ,
86
149
87
- context : ( { req, connection } ) => {
150
+ context : async ( { req, connection } ) => {
88
151
if ( connection ) {
89
152
const { token } = connection . context ;
90
153
return { token } ;
@@ -96,36 +159,33 @@ async function main() {
96
159
} ,
97
160
} ) ;
98
161
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' ,
116
177
} ) ;
117
- const httpServer = createServer ( app ) ;
118
- server . installSubscriptionHandlers ( httpServer ) ;
178
+ const serverCleanup = useServer ( { schema } , wsServer ) ;
119
179
120
180
const PORT = process . env . CROWNLABS_QLKUBE_PORT || 8080 ;
121
181
122
182
httpServer . listen ( { port : PORT } , ( ) => {
183
+ console . log ( `🚀 Server ready at http://localhost:${ PORT } /` ) ;
123
184
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`
128
186
) ;
187
+ global . harborSchema = harborSchema ;
188
+ repl . start ( '> ' ) ;
129
189
} ) ;
130
190
131
191
/**
0 commit comments