@@ -6,6 +6,7 @@ package support
6
6
7
7
import (
8
8
"archive/zip"
9
+ "bufio"
9
10
"bytes"
10
11
"errors"
11
12
"fmt"
@@ -51,6 +52,7 @@ type bundleBuilder struct {
51
52
config BundleConfig
52
53
finch fpath.Finch
53
54
ecc command.Creator
55
+ lcc command.LimaCmdCreator
54
56
lima wrapper.LimaWrapper
55
57
}
56
58
@@ -61,6 +63,7 @@ func NewBundleBuilder(
61
63
config BundleConfig ,
62
64
finch fpath.Finch ,
63
65
ecc command.Creator ,
66
+ lcc command.LimaCmdCreator ,
64
67
lima wrapper.LimaWrapper ,
65
68
) BundleBuilder {
66
69
return & bundleBuilder {
@@ -69,6 +72,7 @@ func NewBundleBuilder(
69
72
config : config ,
70
73
finch : finch ,
71
74
ecc : ecc ,
75
+ lcc : lcc ,
72
76
lima : lima ,
73
77
}
74
78
}
@@ -108,7 +112,8 @@ func (bb *bundleBuilder) GenerateSupportBundle(additionalFiles []string, exclude
108
112
bb .logger .Infof ("Excluding %s..." , file )
109
113
continue
110
114
}
111
- err := bb .copyInFile (writer , file , path .Join (zipPrefix , logPrefix ))
115
+ bb .logger .Debugf ("Copying %s..." , file )
116
+ err = bb .copyFileFromVMOrLocal (writer , file , path .Join (zipPrefix , logPrefix ))
112
117
if err != nil {
113
118
bb .logger .Warnf ("Could not copy in %q. Error: %s" , file , err )
114
119
}
@@ -120,7 +125,8 @@ func (bb *bundleBuilder) GenerateSupportBundle(additionalFiles []string, exclude
120
125
bb .logger .Infof ("Excluding %s..." , file )
121
126
continue
122
127
}
123
- err := bb .copyInFile (writer , file , path .Join (zipPrefix , configPrefix ))
128
+ bb .logger .Debugf ("Copying %s..." , file )
129
+ err = bb .copyFileFromVMOrLocal (writer , file , path .Join (zipPrefix , configPrefix ))
124
130
if err != nil {
125
131
bb .logger .Warnf ("Could not copy in %q. Error: %s" , file , err )
126
132
}
@@ -132,7 +138,8 @@ func (bb *bundleBuilder) GenerateSupportBundle(additionalFiles []string, exclude
132
138
bb .logger .Infof ("Excluding %s..." , file )
133
139
continue
134
140
}
135
- err := bb .copyInFile (writer , file , path .Join (zipPrefix , additionalPrefix ))
141
+ bb .logger .Debugf ("Copying %s..." , file )
142
+ err = bb .copyFileFromVMOrLocal (writer , file , path .Join (zipPrefix , additionalPrefix ))
136
143
if err != nil {
137
144
bb .logger .Warnf ("Could not add additional file %s. Error: %s" , file , err )
138
145
}
@@ -146,30 +153,28 @@ func (bb *bundleBuilder) GenerateSupportBundle(additionalFiles []string, exclude
146
153
return zipFileName , nil
147
154
}
148
155
149
- func (bb * bundleBuilder ) copyInFile (writer * zip.Writer , fileName string , prefix string ) error {
150
- f , err := bb .fs .Open (fileName )
151
- if err != nil {
152
- return err
153
- }
154
-
155
- bb .logger .Debugf ("Copying %s..." , fileName )
156
+ type bufReader interface {
157
+ ReadBytes (delim byte ) ([]byte , error )
158
+ }
156
159
157
- var buf bytes.Buffer
158
- _ , err = buf .ReadFrom (f )
159
- if err != nil {
160
- return err
160
+ func (bb * bundleBuilder ) copyFileFromVMOrLocal (writer * zip.Writer , filename , zipPath string ) error {
161
+ if isFileFromVM (filename ) {
162
+ return bb .streamFileFromVM (writer , filename , zipPath )
161
163
}
164
+ return bb .copyInFile (writer , filename , zipPath )
165
+ }
162
166
163
- var redacted [] byte
167
+ func ( bb * bundleBuilder ) copyAndRedactFile ( writer io. Writer , reader bufReader ) error {
164
168
var bufErr error
165
169
for bufErr == nil {
166
170
var line []byte
167
- line , bufErr = buf .ReadBytes ('\n' )
171
+ line , bufErr = reader .ReadBytes ('\n' )
168
172
if bufErr != nil && ! errors .Is (bufErr , io .EOF ) {
173
+ bb .logger .Error (bufErr .Error ())
169
174
continue
170
175
}
171
176
172
- line , err = redactFinchInstall (line , bb .finch )
177
+ line , err : = redactFinchInstall (line , bb .finch )
173
178
if err != nil {
174
179
return err
175
180
}
@@ -187,7 +192,20 @@ func (bb *bundleBuilder) copyInFile(writer *zip.Writer, fileName string, prefix
187
192
line = redactPorts (line )
188
193
line = redactSSHKeys (line )
189
194
190
- redacted = append (redacted , line ... )
195
+ _ , err = writer .Write (line )
196
+ if err != nil {
197
+ return err
198
+ }
199
+ }
200
+
201
+ return nil
202
+ }
203
+
204
+ func (bb * bundleBuilder ) copyInFile (writer * zip.Writer , fileName string , prefix string ) error {
205
+ // check filename validity?
206
+ f , err := bb .fs .Open (fileName )
207
+ if err != nil {
208
+ return err
191
209
}
192
210
193
211
baseName := path .Base (fileName )
@@ -196,12 +214,56 @@ func (bb *bundleBuilder) copyInFile(writer *zip.Writer, fileName string, prefix
196
214
return err
197
215
}
198
216
199
- _ , err = zipCopy .Write (redacted )
217
+ buf := new (bytes.Buffer )
218
+ _ , err = buf .ReadFrom (f )
200
219
if err != nil {
201
220
return err
202
221
}
203
222
204
- return nil
223
+ return bb .copyAndRedactFile (zipCopy , buf )
224
+ }
225
+
226
+ func (bb * bundleBuilder ) streamFileFromVM (writer * zip.Writer , filename , prefix string ) error {
227
+ pipeReader , pipeWriter := io .Pipe ()
228
+ errBuf := new (bytes.Buffer )
229
+
230
+ _ , filePathInVM , _ := strings .Cut (filename , ":" )
231
+ cmd := bb .lcc .CreateWithoutStdio ("shell" , "finch" , "sudo" , "cat" , filePathInVM )
232
+ cmd .SetStdout (pipeWriter )
233
+ cmd .SetStderr (errBuf )
234
+
235
+ err := cmd .Start ()
236
+ if err != nil {
237
+ return err
238
+ }
239
+
240
+ waitStatus := make (chan error )
241
+ go func () {
242
+ err := cmd .Wait ()
243
+ if err != nil {
244
+ errorMsg , readErr := io .ReadAll (errBuf )
245
+ if readErr == nil && len (errorMsg ) > 0 {
246
+ err = errors .New (string (errorMsg ))
247
+ }
248
+ }
249
+ _ = pipeWriter .Close ()
250
+ waitStatus <- err
251
+ }()
252
+
253
+ baseName := path .Base (filename )
254
+ zipCopy , err := writer .Create (path .Join (prefix , baseName ))
255
+ if err != nil {
256
+ return err
257
+ }
258
+
259
+ bufReader := bufio .NewReader (pipeReader )
260
+
261
+ err = bb .copyAndRedactFile (zipCopy , bufReader )
262
+ if err != nil {
263
+ return err
264
+ }
265
+
266
+ return <- waitStatus
205
267
}
206
268
207
269
func (bb * bundleBuilder ) getPlatformData () (* PlatformData , error ) {
@@ -280,7 +342,11 @@ func bundleFileName() string {
280
342
}
281
343
282
344
func fileShouldBeExcluded (filename string , exclude []string ) bool {
283
- fileAbs , err := filepath .Abs (filename )
345
+ realFilename := filename
346
+ if isFileFromVM (filename ) {
347
+ _ , realFilename , _ = strings .Cut (filename , ":" )
348
+ }
349
+ fileAbs , err := filepath .Abs (realFilename )
284
350
if err != nil {
285
351
return true
286
352
}
@@ -292,9 +358,13 @@ func fileShouldBeExcluded(filename string, exclude []string) bool {
292
358
if fileAbs == excludeAbs {
293
359
return true
294
360
}
295
- if path .Base (filename ) == excludeFile {
361
+ if path .Base (realFilename ) == excludeFile {
296
362
return true
297
363
}
298
364
}
299
365
return false
300
366
}
367
+
368
+ func isFileFromVM (filename string ) bool {
369
+ return strings .HasPrefix (filename , "vm:" )
370
+ }
0 commit comments