1
- import { default as dockerComposeV1 , default as v1 , v2 as dockerComposeV2 , v2 } from "docker-compose" ;
1
+ import { default as v1 , v2 } from "docker-compose" ;
2
2
import { log , pullLog } from "../../../common" ;
3
3
import { ComposeInfo } from "../types" ;
4
4
import { defaultComposeOptions } from "./default-compose-options" ;
5
5
import { ComposeDownOptions , ComposeOptions } from "./types" ;
6
6
7
7
export interface ComposeClient {
8
- info : ComposeInfo ;
8
+ getInfo ( ) : Promise < ComposeInfo > ;
9
9
up ( options : ComposeOptions , services ?: Array < string > ) : Promise < void > ;
10
10
pull ( options : ComposeOptions , services ?: Array < string > ) : Promise < void > ;
11
11
stop ( options : ComposeOptions ) : Promise < void > ;
12
12
down ( options : ComposeOptions , downOptions : ComposeDownOptions ) : Promise < void > ;
13
13
}
14
14
15
- export async function getComposeClient ( environment : NodeJS . ProcessEnv ) : Promise < ComposeClient > {
16
- const info = await getComposeInfo ( ) ;
17
-
18
- switch ( info ?. compatability ) {
19
- case undefined :
20
- return new MissingComposeClient ( ) ;
21
- case "v1" :
22
- return new ComposeV1Client ( info , environment ) ;
23
- case "v2" :
24
- return new ComposeV2Client ( info , environment ) ;
25
- }
26
- }
27
-
28
- async function getComposeInfo ( ) : Promise < ComposeInfo | undefined > {
29
- try {
30
- return {
31
- version : ( await dockerComposeV2 . version ( ) ) . data . version ,
32
- compatability : "v2" ,
33
- } ;
34
- } catch ( err ) {
35
- try {
36
- return {
37
- version : ( await dockerComposeV1 . version ( ) ) . data . version ,
38
- compatability : "v1" ,
39
- } ;
40
- } catch {
41
- return undefined ;
42
- }
43
- }
15
+ export function getComposeClient ( environment : NodeJS . ProcessEnv ) : ComposeClient {
16
+ return new LazyComposeClient ( environment ) ;
44
17
}
45
18
46
- class ComposeV1Client implements ComposeClient {
47
- constructor (
48
- public readonly info : ComposeInfo ,
49
- private readonly environment : NodeJS . ProcessEnv
50
- ) { }
19
+ class LazyComposeClient implements ComposeClient {
20
+ private info : ComposeInfo | undefined = undefined ;
21
+ private client : typeof v1 | typeof v2 | undefined = undefined ;
22
+ constructor ( private readonly environment : NodeJS . ProcessEnv ) { }
51
23
52
- async up ( options : ComposeOptions , services : Array < string > | undefined ) : Promise < void > {
53
- try {
54
- if ( services ) {
55
- log . info ( `Upping Compose environment services ${ services . join ( ", " ) } ...` ) ;
56
- await v1 . upMany ( services , await defaultComposeOptions ( this . environment , options ) ) ;
57
- } else {
58
- log . info ( `Upping Compose environment...` ) ;
59
- await v1 . upAll ( await defaultComposeOptions ( this . environment , options ) ) ;
60
- }
61
- log . info ( `Upped Compose environment` ) ;
62
- } catch ( err ) {
63
- await handleAndRethrow ( err , async ( error : Error ) => {
64
- try {
65
- log . error ( `Failed to up Compose environment: ${ error . message } ` ) ;
66
- await this . down ( options , { removeVolumes : true , timeout : 0 } ) ;
67
- } catch {
68
- log . error ( `Failed to down Compose environment after failed up` ) ;
69
- }
70
- } ) ;
24
+ async getInfo ( ) : Promise < ComposeInfo | undefined > {
25
+ if ( this . info !== undefined ) {
26
+ return this . info ;
71
27
}
72
- }
73
28
74
- async pull ( options : ComposeOptions , services : Array < string > | undefined ) : Promise < void > {
75
29
try {
76
- if ( services ) {
77
- log . info ( `Pulling Compose environment images "${ services . join ( '", "' ) } "...` ) ;
78
- await v1 . pullMany ( services , await defaultComposeOptions ( this . environment , { ...options , logger : pullLog } ) ) ;
79
- } else {
80
- log . info ( `Pulling Compose environment images...` ) ;
81
- await v1 . pullAll ( await defaultComposeOptions ( this . environment , { ...options , logger : pullLog } ) ) ;
82
- }
83
- log . info ( `Pulled Compose environment` ) ;
30
+ this . info = {
31
+ version : ( await v2 . version ( ) ) . data . version ,
32
+ compatibility : "v2" ,
33
+ } ;
84
34
} catch ( err ) {
85
- await handleAndRethrow ( err , async ( error : Error ) =>
86
- log . error ( `Failed to pull Compose environment images: ${ error . message } ` )
87
- ) ;
35
+ try {
36
+ this . info = {
37
+ version : ( await v1 . version ( ) ) . data . version ,
38
+ compatibility : "v1" ,
39
+ } ;
40
+ } catch {
41
+ return undefined ;
42
+ }
88
43
}
44
+
45
+ return this . info ;
89
46
}
90
47
91
- async stop ( options : ComposeOptions ) : Promise < void > {
92
- try {
93
- log . info ( `Stopping Compose environment...` ) ;
94
- await v1 . stop ( await defaultComposeOptions ( this . environment , options ) ) ;
95
- log . info ( `Stopped Compose environment` ) ;
96
- } catch ( err ) {
97
- await handleAndRethrow ( err , async ( error : Error ) =>
98
- log . error ( `Failed to stop Compose environment: ${ error . message } ` )
99
- ) ;
48
+ private async getClient ( ) : Promise < typeof v1 | typeof v2 > {
49
+ if ( this . client !== undefined ) {
50
+ return this . client ;
100
51
}
101
- }
102
52
103
- async down ( options : ComposeOptions , downOptions : ComposeDownOptions ) : Promise < void > {
104
- try {
105
- log . info ( `Downing Compose environment...` ) ;
106
- await v1 . down ( {
107
- ...( await defaultComposeOptions ( this . environment , options ) ) ,
108
- commandOptions : composeDownCommandOptions ( downOptions ) ,
109
- } ) ;
110
- log . info ( `Downed Compose environment` ) ;
111
- } catch ( err ) {
112
- await handleAndRethrow ( err , async ( error : Error ) =>
113
- log . error ( `Failed to down Compose environment: ${ error . message } ` )
114
- ) ;
53
+ const info = await this . getInfo ( ) ;
54
+ switch ( info ?. compatibility ) {
55
+ case undefined :
56
+ throw new Error ( "Compose is not installed" ) ;
57
+ case "v1" :
58
+ this . client = v1 ;
59
+ return v1 ;
60
+ case "v2" :
61
+ this . client = v2 ;
62
+ return v2 ;
115
63
}
116
64
}
117
- }
118
-
119
- class ComposeV2Client implements ComposeClient {
120
- constructor (
121
- public readonly info : ComposeInfo ,
122
- private readonly environment : NodeJS . ProcessEnv
123
- ) { }
124
65
125
66
async up ( options : ComposeOptions , services : Array < string > | undefined ) : Promise < void > {
67
+ const client = await this . getClient ( ) ;
68
+
126
69
try {
127
70
if ( services ) {
128
71
log . info ( `Upping Compose environment services ${ services . join ( ", " ) } ...` ) ;
129
- await v2 . upMany ( services , await defaultComposeOptions ( this . environment , options ) ) ;
72
+ await client . upMany ( services , await defaultComposeOptions ( this . environment , options ) ) ;
130
73
} else {
131
74
log . info ( `Upping Compose environment...` ) ;
132
- await v2 . upAll ( await defaultComposeOptions ( this . environment , options ) ) ;
75
+ await client . upAll ( await defaultComposeOptions ( this . environment , options ) ) ;
133
76
}
134
77
log . info ( `Upped Compose environment` ) ;
135
78
} catch ( err ) {
@@ -145,13 +88,15 @@ class ComposeV2Client implements ComposeClient {
145
88
}
146
89
147
90
async pull ( options : ComposeOptions , services : Array < string > | undefined ) : Promise < void > {
91
+ const client = await this . getClient ( ) ;
92
+
148
93
try {
149
94
if ( services ) {
150
95
log . info ( `Pulling Compose environment images "${ services . join ( '", "' ) } "...` ) ;
151
- await v2 . pullMany ( services , await defaultComposeOptions ( this . environment , { ...options , logger : pullLog } ) ) ;
96
+ await client . pullMany ( services , await defaultComposeOptions ( this . environment , { ...options , logger : pullLog } ) ) ;
152
97
} else {
153
98
log . info ( `Pulling Compose environment images...` ) ;
154
- await v2 . pullAll ( await defaultComposeOptions ( this . environment , { ...options , logger : pullLog } ) ) ;
99
+ await client . pullAll ( await defaultComposeOptions ( this . environment , { ...options , logger : pullLog } ) ) ;
155
100
}
156
101
log . info ( `Pulled Compose environment` ) ;
157
102
} catch ( err ) {
@@ -162,9 +107,11 @@ class ComposeV2Client implements ComposeClient {
162
107
}
163
108
164
109
async stop ( options : ComposeOptions ) : Promise < void > {
110
+ const client = await this . getClient ( ) ;
111
+
165
112
try {
166
113
log . info ( `Stopping Compose environment...` ) ;
167
- await v2 . stop ( await defaultComposeOptions ( this . environment , options ) ) ;
114
+ await client . stop ( await defaultComposeOptions ( this . environment , options ) ) ;
168
115
log . info ( `Stopped Compose environment` ) ;
169
116
} catch ( err ) {
170
117
await handleAndRethrow ( err , async ( error : Error ) =>
@@ -174,9 +121,10 @@ class ComposeV2Client implements ComposeClient {
174
121
}
175
122
176
123
async down ( options : ComposeOptions , downOptions : ComposeDownOptions ) : Promise < void > {
124
+ const client = await this . getClient ( ) ;
177
125
try {
178
126
log . info ( `Downing Compose environment...` ) ;
179
- await v2 . down ( {
127
+ await client . down ( {
180
128
...( await defaultComposeOptions ( this . environment , options ) ) ,
181
129
commandOptions : composeDownCommandOptions ( downOptions ) ,
182
130
} ) ;
@@ -189,26 +137,6 @@ class ComposeV2Client implements ComposeClient {
189
137
}
190
138
}
191
139
192
- class MissingComposeClient implements ComposeClient {
193
- public readonly info = undefined ;
194
-
195
- up ( ) : Promise < void > {
196
- throw new Error ( "Compose is not installed" ) ;
197
- }
198
-
199
- pull ( ) : Promise < void > {
200
- throw new Error ( "Compose is not installed" ) ;
201
- }
202
-
203
- stop ( ) : Promise < void > {
204
- throw new Error ( "Compose is not installed" ) ;
205
- }
206
-
207
- down ( ) : Promise < void > {
208
- throw new Error ( "Compose is not installed" ) ;
209
- }
210
- }
211
-
212
140
// eslint-disable-next-line @typescript-eslint/no-explicit-any
213
141
async function handleAndRethrow ( err : any , handle : ( error : Error ) => Promise < void > ) : Promise < never > {
214
142
const error = err instanceof Error ? err : new Error ( err . err . trim ( ) ) ;
0 commit comments