@@ -104,7 +104,7 @@ export class Stack {
104
104
}
105
105
106
106
get isManagedByDockge ( ) : boolean {
107
- return fs . existsSync ( this . path ) && fs . statSync ( this . path ) . isDirectory ( ) ;
107
+ return ! ! this . _configFilePath && this . _configFilePath . startsWith ( this . server . stacksDir ) ;
108
108
}
109
109
110
110
get status ( ) : number {
@@ -153,7 +153,7 @@ export class Stack {
153
153
}
154
154
155
155
get path ( ) : string {
156
- return path . join ( this . server . stacksDir , this . name ) ;
156
+ return this . _configFilePath || "" ;
157
157
}
158
158
159
159
get fullPath ( ) : string {
@@ -263,41 +263,12 @@ export class Stack {
263
263
}
264
264
265
265
static async getStackList ( server : DockgeServer , useCacheForManaged = false ) : Promise < Map < string , Stack > > {
266
- let stacksDir = server . stacksDir ;
267
- let stackList : Map < string , Stack > ;
266
+ let stackList : Map < string , Stack > = new Map < string , Stack > ( ) ;
268
267
269
268
// Use cached stack list?
270
269
if ( useCacheForManaged && this . managedStackList . size > 0 ) {
271
270
stackList = this . managedStackList ;
272
- } else {
273
- stackList = new Map < string , Stack > ( ) ;
274
-
275
- // Scan the stacks directory, and get the stack list
276
- let filenameList = await fsAsync . readdir ( stacksDir ) ;
277
-
278
- for ( let filename of filenameList ) {
279
- try {
280
- // Check if it is a directory
281
- let stat = await fsAsync . stat ( path . join ( stacksDir , filename ) ) ;
282
- if ( ! stat . isDirectory ( ) ) {
283
- continue ;
284
- }
285
- // If no compose file exists, skip it
286
- if ( ! await Stack . composeFileExists ( stacksDir , filename ) ) {
287
- continue ;
288
- }
289
- let stack = await this . getStack ( server , filename ) ;
290
- stack . _status = CREATED_FILE ;
291
- stackList . set ( filename , stack ) ;
292
- } catch ( e ) {
293
- if ( e instanceof Error ) {
294
- log . warn ( "getStackList" , `Failed to get stack ${ filename } , error: ${ e . message } ` ) ;
295
- }
296
- }
297
- }
298
-
299
- // Cache by copying
300
- this . managedStackList = new Map ( stackList ) ;
271
+ return stackList ;
301
272
}
302
273
303
274
// Get status from docker compose ls
@@ -306,28 +277,29 @@ export class Stack {
306
277
} ) ;
307
278
308
279
if ( ! res . stdout ) {
280
+ log . warn ( "getStackList" , "No response from docker compose daemon when attempting to retrieve list of stacks" ) ;
309
281
return stackList ;
310
282
}
311
283
312
284
let composeList = JSON . parse ( res . stdout . toString ( ) ) ;
313
285
314
286
for ( let composeStack of composeList ) {
315
- let stack = stackList . get ( composeStack . Name ) ;
287
+ try {
288
+ let stack = new Stack ( server , composeStack . Name ) ;
289
+ stack . _status = this . statusConvert ( composeStack . Status ) ;
316
290
317
- // This stack probably is not managed by Dockge, but we still want to show it
318
- if ( ! stack ) {
319
- // Skip the dockge stack if it is not managed by Dockge
320
- if ( composeStack . Name === "dockge" ) {
321
- continue ;
322
- }
323
- stack = new Stack ( server , composeStack . Name ) ;
291
+ let composeFiles = composeStack . ConfigFiles . split ( "," ) ; // it is possible for a project to have more than one config file
292
+ stack . _configFilePath = path . dirname ( composeFiles [ 0 ] ) ;
293
+ stack . _composeFileName = path . basename ( composeFiles [ 0 ] ) ;
324
294
stackList . set ( composeStack . Name , stack ) ;
295
+ } catch ( e ) {
296
+ if ( e instanceof Error ) {
297
+ log . warn ( "getStackList" , `Failed to get stack ${ composeStack . Name } , error: ${ e . message } ` ) ;
298
+ }
325
299
}
326
-
327
- stack . _status = this . statusConvert ( composeStack . Status ) ;
328
- stack . _configFilePath = composeStack . ConfigFiles ;
329
300
}
330
301
302
+ this . managedStackList = stackList ;
331
303
return stackList ;
332
304
}
333
305
@@ -375,35 +347,24 @@ export class Stack {
375
347
}
376
348
377
349
static async getStack ( server : DockgeServer , stackName : string , skipFSOperations = false ) : Promise < Stack > {
378
- let dir = path . join ( server . stacksDir , stackName ) ;
379
-
350
+ let stack : Stack | undefined ;
380
351
if ( ! skipFSOperations ) {
381
- if ( ! await fileExists ( dir ) || ! ( await fsAsync . stat ( dir ) ) . isDirectory ( ) ) {
382
- // Maybe it is a stack managed by docker compose directly
383
- let stackList = await this . getStackList ( server , true ) ;
384
- let stack = stackList . get ( stackName ) ;
385
-
386
- if ( stack ) {
387
- return stack ;
388
- } else {
389
- // Really not found
390
- throw new ValidationError ( "Stack not found" ) ;
391
- }
352
+ let stackList = await this . getStackList ( server , true ) ;
353
+ stack = stackList . get ( stackName ) ;
354
+ if ( ! stack || ! await fileExists ( stack . path ) || ! ( await fsAsync . stat ( stack . path ) ) . isDirectory ( ) ) {
355
+ throw new ValidationError ( "getStack; Stack not found" ) ;
392
356
}
393
357
} else {
394
- //log.debug("getStack", "Skip FS operations");
395
- }
396
-
397
- let stack : Stack ;
398
-
399
- if ( ! skipFSOperations ) {
400
- stack = new Stack ( server , stackName ) ;
401
- } else {
402
- stack = new Stack ( server , stackName , undefined , undefined , true ) ;
358
+ // search for known stack with this name
359
+ if ( this . managedStackList ) {
360
+ stack = this . managedStackList . get ( stackName ) ;
361
+ }
362
+ if ( ! this . managedStackList || ! stack ) {
363
+ stack = new Stack ( server , stackName , undefined , undefined , true ) ;
364
+ stack . _status = UNKNOWN ;
365
+ stack . _configFilePath = path . resolve ( server . stacksDir , stackName ) ;
366
+ }
403
367
}
404
-
405
- stack . _status = UNKNOWN ;
406
- stack . _configFilePath = path . resolve ( dir ) ;
407
368
return stack ;
408
369
}
409
370
@@ -522,7 +483,6 @@ export class Stack {
522
483
} catch ( e ) {
523
484
}
524
485
}
525
-
526
486
return statusList ;
527
487
} catch ( e ) {
528
488
log . error ( "getServiceStatusList" , e ) ;
0 commit comments