@@ -20,6 +20,20 @@ pub enum EngineType {
20
20
Other ,
21
21
}
22
22
23
+ impl EngineType {
24
+ /// Returns `true` if the engine type is [`Podman`](Self::Podman) or [`PodmanRemote`](Self::PodmanRemote).
25
+ #[ must_use]
26
+ pub fn is_podman ( & self ) -> bool {
27
+ matches ! ( self , Self :: Podman | Self :: PodmanRemote )
28
+ }
29
+
30
+ /// Returns `true` if the engine type is [`Docker`](EngineType::Docker).
31
+ #[ must_use]
32
+ pub fn is_docker ( & self ) -> bool {
33
+ matches ! ( self , Self :: Docker )
34
+ }
35
+ }
36
+
23
37
#[ derive( Clone , Debug , PartialEq , Eq ) ]
24
38
pub struct Engine {
25
39
pub kind : EngineType ,
@@ -117,82 +131,97 @@ fn get_engine_info(
117
131
EngineType :: Other
118
132
} ;
119
133
120
- let mut cmd = Command :: new ( ce) ;
121
- cmd. args ( & [ "version" , "-f" , "{{ .Server.Os }},,,{{ .Server.Arch }}" ] ) ;
122
-
123
- let out = cmd. run_and_get_output ( msg_info) ?;
124
-
125
- let stdout = out. stdout ( ) ?. to_lowercase ( ) ;
126
-
127
- let osarch = stdout
128
- . trim ( )
129
- . split_once ( ",,," )
130
- . map ( |( os, arch) | -> Result < _ > { Ok ( ( ContainerOs :: new ( os) ?, Architecture :: new ( arch) ?) ) } )
131
- . transpose ( ) ;
132
-
133
- let osarch = match ( kind, osarch) {
134
- ( _, Ok ( Some ( osarch) ) ) => Some ( osarch) ,
135
- ( EngineType :: PodmanRemote | EngineType :: Podman , Ok ( None ) ) => get_podman_info ( ce, msg_info) ?,
136
- ( _, Err ( e) ) => {
137
- return Err ( e. wrap_err ( format ! (
138
- "command `{}` returned unexpected data" ,
139
- cmd. command_pretty( msg_info, |_| false )
140
- ) ) ) ;
134
+ // this can fail: podman can give partial output
135
+ // linux,,,Error: template: version:1:15: executing "version" at <.Arch>:
136
+ // can't evaluate field Arch in type *define.Version
137
+ let os_arch_server = engine_info (
138
+ ce,
139
+ & [ "version" , "-f" , "{{ .Server.Os }},,,{{ .Server.Arch }}" ] ,
140
+ ",,," ,
141
+ msg_info,
142
+ ) ;
143
+
144
+ let ( os_arch_other, os_arch_server_result) = match os_arch_server {
145
+ Ok ( Some ( os_arch) ) => ( Ok ( Some ( os_arch) ) , None ) ,
146
+ result => {
147
+ if kind. is_podman ( ) {
148
+ ( get_podman_info ( ce, msg_info) , result. err ( ) )
149
+ } else {
150
+ ( get_custom_info ( ce, msg_info) , result. err ( ) )
151
+ }
141
152
}
142
- ( EngineType :: Docker | EngineType :: Other , Ok ( None ) ) => None ,
143
153
} ;
144
154
145
- let osarch = if osarch. is_some ( ) {
146
- osarch
147
- } else if !out. status . success ( ) {
148
- get_custom_info ( ce, msg_info) . with_error ( || {
149
- cmd. status_result ( msg_info, out. status , Some ( & out) )
150
- . expect_err ( "status_result should error" )
151
- } ) ?
152
- } else {
153
- get_custom_info ( ce, msg_info) ?
155
+ let os_arch = match ( os_arch_other, os_arch_server_result) {
156
+ ( Ok ( os_arch) , _) => os_arch,
157
+ ( Err ( e) , Some ( server_err) ) => return Err ( server_err. to_section_report ( ) . with_error ( || e) ) ,
158
+ ( Err ( e) , None ) => return Err ( e. to_section_report ( ) ) ,
154
159
} ;
155
160
156
- let ( os, arch) = osarch . map_or ( <_ >:: default ( ) , |( os, arch) | ( Some ( os) , Some ( arch) ) ) ;
161
+ let ( os, arch) = os_arch . map_or ( <_ >:: default ( ) , |( os, arch) | ( Some ( os) , Some ( arch) ) ) ;
157
162
Ok ( ( kind, arch, os) )
158
163
}
159
164
160
- fn get_podman_info (
165
+ #[ derive( Debug , thiserror:: Error ) ]
166
+ pub enum EngineInfoError {
167
+ #[ error( transparent) ]
168
+ Eyre ( eyre:: Report ) ,
169
+ #[ error( "could not get os and arch" ) ]
170
+ CommandError ( #[ from] CommandError ) ,
171
+ }
172
+
173
+ impl EngineInfoError {
174
+ pub fn to_section_report ( self ) -> eyre:: Report {
175
+ match self {
176
+ EngineInfoError :: Eyre ( e) => e,
177
+ EngineInfoError :: CommandError ( e) => {
178
+ e. to_section_report ( ) . wrap_err ( "could not get os and arch" )
179
+ }
180
+ }
181
+ }
182
+ }
183
+
184
+ /// Get engine info
185
+ fn engine_info (
161
186
ce : & Path ,
187
+ args : & [ & str ] ,
188
+ sep : & str ,
162
189
msg_info : & mut MessageInfo ,
163
- ) -> Result < Option < ( ContainerOs , Architecture ) > > {
190
+ ) -> Result < Option < ( ContainerOs , Architecture ) > , EngineInfoError > {
164
191
let mut cmd = Command :: new ( ce) ;
165
- cmd. args ( & [ "info" , "-f" , "{{ .Version.OsArch }}" ] ) ;
166
- cmd. run_and_get_stdout ( msg_info)
167
- . map ( |s| {
168
- s. to_lowercase ( )
169
- . trim ( )
170
- . split_once ( '/' )
171
- . map ( |( os, arch) | -> Result < _ > {
172
- Ok ( ( ContainerOs :: new ( os) ?, Architecture :: new ( arch) ?) )
173
- } )
174
- } )
175
- . wrap_err ( "could not determine os and architecture of vm" ) ?
192
+ cmd. args ( args) ;
193
+ let out = cmd
194
+ . run_and_get_output ( msg_info)
195
+ . map_err ( EngineInfoError :: Eyre ) ?;
196
+
197
+ cmd. status_result ( msg_info, out. status , Some ( & out) ) ?;
198
+
199
+ out. stdout ( ) ?
200
+ . to_lowercase ( )
201
+ . trim ( )
202
+ . split_once ( sep)
203
+ . map ( |( os, arch) | -> Result < _ > { Ok ( ( ContainerOs :: new ( os) ?, Architecture :: new ( arch) ?) ) } )
176
204
. transpose ( )
205
+ . map_err ( EngineInfoError :: Eyre )
206
+ }
207
+
208
+ fn get_podman_info (
209
+ ce : & Path ,
210
+ msg_info : & mut MessageInfo ,
211
+ ) -> Result < Option < ( ContainerOs , Architecture ) > , EngineInfoError > {
212
+ engine_info ( ce, & [ "info" , "-f" , "{{ .Version.OsArch }}" ] , "/" , msg_info)
177
213
}
178
214
179
215
fn get_custom_info (
180
216
ce : & Path ,
181
217
msg_info : & mut MessageInfo ,
182
- ) -> Result < Option < ( ContainerOs , Architecture ) > > {
183
- let mut cmd = Command :: new ( ce) ;
184
- cmd. args ( & [ "info" , "-f" , "{{ .Client.Os }},,,{{ .Client.Arch }}" ] ) ;
185
- cmd. run_and_get_stdout ( msg_info)
186
- . map ( |s| {
187
- s. to_lowercase ( )
188
- . trim ( )
189
- . split_once ( ",,," )
190
- . map ( |( os, arch) | -> Result < _ > {
191
- Ok ( ( ContainerOs :: new ( os) ?, Architecture :: new ( arch) ?) )
192
- } )
193
- } )
194
- . unwrap_or_default ( )
195
- . transpose ( )
218
+ ) -> Result < Option < ( ContainerOs , Architecture ) > , EngineInfoError > {
219
+ engine_info (
220
+ ce,
221
+ & [ "version" , "-f" , "{{ .Client.Os }},,,{{ .Client.Arch }}" ] ,
222
+ ",,," ,
223
+ msg_info,
224
+ )
196
225
}
197
226
198
227
pub fn get_container_engine ( ) -> Result < PathBuf , which:: Error > {
0 commit comments