Skip to content

Commit 0996679

Browse files
committed
write docker logs
1 parent a461206 commit 0996679

File tree

2 files changed

+74
-0
lines changed

2 files changed

+74
-0
lines changed

framework/config.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,8 @@ func Load[X any](t *testing.T) (*X, error) {
130130
t.Cleanup(func() {
131131
err := Store[X](input)
132132
require.NoError(t, err)
133+
err = WriteAllContainersLogs()
134+
require.NoError(t, err)
133135
})
134136
// TODO: not all the people have AWS access, sadly enough, uncomment when granted
135137
//if os.Getenv(EnvVarAWSSecretsManager) == "true" {

framework/docker.go

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import (
44
"archive/tar"
55
"bytes"
66
"context"
7+
"encoding/binary"
78
"errors"
89
"fmt"
910
"github.com/docker/docker/api/types/container"
@@ -14,10 +15,15 @@ import (
1415
"io"
1516
"os"
1617
"os/exec"
18+
"path/filepath"
1719
"strings"
1820
"sync"
1921
)
2022

23+
const (
24+
DefaultCTFLogsDir = "logs"
25+
)
26+
2127
func IsDockerRunning() bool {
2228
cli, err := client.NewClientWithOpts(client.FromEnv)
2329
if err != nil {
@@ -223,3 +229,69 @@ func (dc *DockerClient) copyToContainer(containerID, sourceFile, targetPath stri
223229
}
224230
return nil
225231
}
232+
233+
// WriteAllContainersLogs writes all docker containers logs to default logs directory
234+
func WriteAllContainersLogs() error {
235+
L.Info().Msg("Writing docker containers logs")
236+
if _, err := os.Stat(DefaultCTFLogsDir); os.IsNotExist(err) {
237+
if err := os.MkdirAll(DefaultCTFLogsDir, 0755); err != nil {
238+
return fmt.Errorf("failed to create directory %s: %w", DefaultCTFLogsDir, err)
239+
}
240+
}
241+
cli, err := client.NewClientWithOpts(client.FromEnv, client.WithAPIVersionNegotiation())
242+
if err != nil {
243+
return fmt.Errorf("failed to create Docker client: %w", err)
244+
}
245+
conts, err := cli.ContainerList(context.Background(), container.ListOptions{
246+
All: true,
247+
})
248+
if err != nil {
249+
return err
250+
}
251+
for _, cont := range conts {
252+
logOptions := container.LogsOptions{ShowStdout: true, ShowStderr: true}
253+
logs, err := cli.ContainerLogs(context.Background(), cont.Names[0], logOptions)
254+
if err != nil {
255+
L.Error().Err(err).Str("Container", cont.Names[0]).Msg("failed to fetch logs for container")
256+
continue
257+
}
258+
logFilePath := filepath.Join(DefaultCTFLogsDir, fmt.Sprintf("%s.log", cont.Names[0]))
259+
logFile, err := os.Create(logFilePath)
260+
if err != nil {
261+
L.Error().Err(err).Str("Container", cont.Names[0]).Msg("failed to create container log file")
262+
continue
263+
}
264+
265+
// Read and parse logs
266+
header := make([]byte, 8) // Docker stream header is 8 bytes
267+
for {
268+
// Read the header
269+
_, err := io.ReadFull(logs, header)
270+
if err == io.EOF {
271+
break // End of logs
272+
}
273+
if err != nil {
274+
L.Error().Err(err).Str("Container", cont.Names[0]).Msg("failed to read log stream header")
275+
break
276+
}
277+
278+
// Extract log message size from the header
279+
msgSize := binary.BigEndian.Uint32(header[4:8])
280+
281+
// Read the log message
282+
msg := make([]byte, msgSize)
283+
_, err = io.ReadFull(logs, msg)
284+
if err != nil {
285+
L.Error().Err(err).Str("Container", cont.Names[0]).Msg("failed to read log message")
286+
break
287+
}
288+
289+
// Write the log message to the file
290+
if _, err := logFile.Write(msg); err != nil {
291+
L.Error().Err(err).Str("Container", cont.Names[0]).Msg("failed to write log message to file")
292+
break
293+
}
294+
}
295+
}
296+
return nil
297+
}

0 commit comments

Comments
 (0)