1package main
2
3import (
4	"context"
5	"fmt"
6	"io"
7	"net"
8	"os"
9	"sync"
10
11	"github.com/Microsoft/go-winio"
12	"github.com/pkg/errors"
13)
14
15func main() {
16	if err := logContainerStdoutToFile(); err != nil {
17		fmt.Fprintln(os.Stderr, err)
18		os.Exit(1)
19	}
20}
21
22func logContainerStdoutToFile() (err error) {
23	ctx, cancel := context.WithCancel(context.Background())
24	defer cancel()
25
26	var sout, wait net.Conn
27
28	soutPipe := os.Getenv("CONTAINER_STDOUT")
29	waitPipe := os.Getenv("CONTAINER_WAIT")
30
31	if sout, err = winio.DialPipeContext(ctx, soutPipe); err != nil {
32		return errors.Wrap(err, "couldn't open stdout pipe")
33	}
34	defer sout.Close()
35
36	// The only expected argument should be output file path
37	if len(os.Args[1:]) != 1 {
38		return errors.Errorf("Expected exactly 1 argument, got: %d", len(os.Args[1:]))
39	}
40
41	var dest *os.File
42	destPath := os.Args[1]
43	if dest, err = os.Create(destPath); err != nil {
44		return errors.Wrap(err, "couldn't open destination file")
45	}
46	defer dest.Close()
47
48	if wait, err = winio.DialPipeContext(ctx, waitPipe); err != nil {
49		return errors.Wrap(err, "couldn't open wait pipe")
50	}
51	// Indicate that logging binary is ready to receive output
52	wait.Close()
53
54	var wg sync.WaitGroup
55
56	wg.Add(1)
57	go func() {
58		defer wg.Done()
59		_, err = io.Copy(dest, sout)
60	}()
61	wg.Wait()
62	return
63}
64