mirror of
https://github.com/linuxkit/linuxkit.git
synced 2025-12-02 12:26:17 +00:00
91 lines
2.2 KiB
Go
91 lines
2.2 KiB
Go
package main
|
|
|
|
import (
|
|
"archive/tar"
|
|
"bytes"
|
|
"context"
|
|
"encoding/json"
|
|
"io/ioutil"
|
|
"log"
|
|
)
|
|
|
|
const (
|
|
systemLogDir = "editionslogs"
|
|
systemContainerLabel = "com.docker.editions.system"
|
|
)
|
|
|
|
// SystemContainerCapturer gets the logs from containers which are run
|
|
// specifically for Docker Editions.
|
|
type SystemContainerCapturer struct{}
|
|
|
|
// Capture writes output from a CommandCapturer to a tar archive
|
|
func (s SystemContainerCapturer) Capture(parentCtx context.Context, w *tar.Writer) {
|
|
ctx, cancel := context.WithTimeout(context.Background(), defaultCaptureTimeout)
|
|
defer cancel()
|
|
|
|
errCh := make(chan error)
|
|
|
|
go func() {
|
|
// URL encoded.
|
|
// Reads more like this:
|
|
// /v1.25/containers/json?all=1&filters={"label":{"com.docker.editions.system":true}}
|
|
resp, err := dockerHTTPGet(ctx, "/containers/json?all=1&filters=%7B%22label%22%3A%7B%22"+systemContainerLabel+"%22%3Atrue%7D%7D")
|
|
if err != nil {
|
|
errCh <- err
|
|
return
|
|
}
|
|
|
|
defer resp.Body.Close()
|
|
|
|
names := []struct {
|
|
ID string `json:"id"`
|
|
Names []string
|
|
}{}
|
|
|
|
if err := json.NewDecoder(resp.Body).Decode(&names); err != nil {
|
|
errCh <- err
|
|
return
|
|
}
|
|
|
|
for _, c := range names {
|
|
resp, err := dockerHTTPGet(ctx, "/containers/"+c.ID+"/logs?stderr=1&stdout=1×tamps=1&tail=all")
|
|
if err != nil {
|
|
log.Println("ERROR (get request):", err)
|
|
continue
|
|
}
|
|
|
|
defer resp.Body.Close()
|
|
|
|
logLines, err := ioutil.ReadAll(resp.Body)
|
|
if err != nil {
|
|
log.Println("ERROR (reading response):", err)
|
|
continue
|
|
}
|
|
|
|
// Docker API returns a Names array where the names are
|
|
// like this: ["/foobar", "/quux"]
|
|
//
|
|
// Use the first one from it.
|
|
//
|
|
// Additionally, the slash from it helps delimit a path
|
|
// separator in the tar archive.
|
|
//
|
|
// TODO(nathanleclaire): This seems fragile, but I'm
|
|
// not sure what approach would be much better.
|
|
tarWrite(w, bytes.NewBuffer(logLines), systemLogDir+c.Names[0])
|
|
}
|
|
|
|
errCh <- nil
|
|
}()
|
|
|
|
select {
|
|
case <-ctx.Done():
|
|
log.Println("System container log capture context error", ctx.Err())
|
|
case err := <-errCh:
|
|
if err != nil {
|
|
log.Println("System container log capture error", err)
|
|
}
|
|
log.Println("System container log capture finished successfully")
|
|
}
|
|
}
|