| package logging | |
| import ( | |
| "bytes" | |
| "runtime" | |
| "strings" | |
| "testing" | |
| "time" | |
| "github.com/moby/moby/api/pkg/stdcopy" | |
| "github.com/moby/moby/api/types/container" | |
| "github.com/moby/moby/client" | |
| testContainer "github.com/moby/moby/v2/integration/internal/container" | |
| "github.com/moby/moby/v2/internal/testutil" | |
| "github.com/moby/moby/v2/internal/testutil/daemon" | |
| "gotest.tools/v3/assert" | |
| "gotest.tools/v3/poll" | |
| ) | |
| // TestReadPluginNoRead tests that reads are supported even if the plugin isn't capable. | |
| func TestReadPluginNoRead(t *testing.T) { | |
| if runtime.GOOS == "windows" { | |
| t.Skip("no unix domain sockets on Windows") | |
| } | |
| t.Parallel() | |
| ctx := testutil.StartSpan(baseContext, t) | |
| d := daemon.New(t) | |
| d.StartWithBusybox(ctx, t, "--iptables=false", "--ip6tables=false") | |
| defer d.Stop(t) | |
| apiclient, err := d.NewClient() | |
| assert.Assert(t, err) | |
| createPlugin(ctx, t, apiclient, "test", "discard", asLogDriver) | |
| _, err = apiclient.PluginEnable(ctx, "test", client.PluginEnableOptions{Timeout: 30}) | |
| assert.Check(t, err) | |
| d.Stop(t) | |
| cfg := &container.Config{ | |
| Image: "busybox", | |
| Cmd: []string{"/bin/echo", "hello world"}, | |
| } | |
| for desc, test := range map[string]struct { | |
| dOpts []string | |
| logsSupported bool | |
| }{ | |
| "default": {logsSupported: true}, | |
| "disabled caching": {[]string{"--log-opt=cache-disabled=true"}, false}, | |
| "explicitly enabled caching": {[]string{"--log-opt=cache-disabled=false"}, true}, | |
| } { | |
| t.Run(desc, func(t *testing.T) { | |
| ctx := testutil.StartSpan(ctx, t) | |
| d.Start(t, append([]string{"--iptables=false", "--ip6tables=false"}, test.dOpts...)...) | |
| defer d.Stop(t) | |
| c, err := apiclient.ContainerCreate(ctx, client.ContainerCreateOptions{ | |
| Config: cfg, | |
| HostConfig: &container.HostConfig{ | |
| LogConfig: container.LogConfig{Type: "test"}, | |
| }, | |
| }) | |
| assert.Assert(t, err) | |
| defer apiclient.ContainerRemove(ctx, c.ID, client.ContainerRemoveOptions{Force: true}) | |
| _, err = apiclient.ContainerStart(ctx, c.ID, client.ContainerStartOptions{}) | |
| assert.Assert(t, err) | |
| poll.WaitOn(t, testContainer.IsStopped(ctx, apiclient, c.ID)) | |
| logs, err := apiclient.ContainerLogs(ctx, c.ID, client.ContainerLogsOptions{ShowStdout: true}) | |
| if !test.logsSupported { | |
| assert.Assert(t, err != nil) | |
| return | |
| } | |
| assert.Assert(t, err) | |
| defer logs.Close() | |
| buf := bytes.NewBuffer(nil) | |
| errCh := make(chan error, 1) | |
| go func() { | |
| _, err := stdcopy.StdCopy(buf, buf, logs) | |
| errCh <- err | |
| }() | |
| select { | |
| case <-time.After(60 * time.Second): | |
| t.Fatal("timeout waiting for IO to complete") | |
| case err := <-errCh: | |
| assert.Assert(t, err) | |
| } | |
| assert.Assert(t, strings.TrimSpace(buf.String()) == "hello world", buf.Bytes()) | |
| }) | |
| } | |
| } |