2016-10-26 04:19:32 -04:00
// +build !windows
package main
import (
"bufio"
2016-11-18 15:38:36 -05:00
"fmt"
2016-10-26 04:19:32 -04:00
"io"
"os/exec"
"strings"
2019-09-09 17:06:12 -04:00
"testing"
2017-03-01 19:37:25 -05:00
"time"
2016-10-26 04:19:32 -04:00
2016-12-30 12:23:00 -05:00
"github.com/docker/docker/integration-cli/checker"
2017-03-01 19:37:25 -05:00
"github.com/docker/docker/integration-cli/daemon"
2019-04-04 09:23:19 -04:00
"gotest.tools/assert"
2018-06-11 09:32:11 -04:00
"gotest.tools/icmd"
2019-08-26 11:51:40 -04:00
"gotest.tools/poll"
2016-10-26 04:19:32 -04:00
)
type logMessage struct {
err error
data [ ] byte
}
2019-09-09 17:05:55 -04:00
func ( s * DockerSwarmSuite ) TestServiceLogs ( c * testing . T ) {
2016-10-26 04:19:32 -04:00
d := s . AddDaemon ( c , true , true )
2016-11-30 00:48:44 -05:00
// we have multiple services here for detecting the goroutine issue #28915
services := map [ string ] string {
"TestServiceLogs1" : "hello1" ,
"TestServiceLogs2" : "hello2" ,
}
for name , message := range services {
2017-09-27 19:17:55 -04:00
out , err := d . Cmd ( "service" , "create" , "--detach" , "--no-resolve-image" , "--name" , name , "busybox" ,
2019-09-09 19:41:57 -04:00
"sh" , "-c" , fmt . Sprintf ( "echo %s; exec tail -f /dev/null" , message ) )
2019-04-04 09:23:19 -04:00
assert . NilError ( c , err )
assert . Assert ( c , strings . TrimSpace ( out ) != "" )
2016-11-30 00:48:44 -05:00
}
2016-11-18 15:38:36 -05:00
// make sure task has been deployed.
2019-08-26 11:51:40 -04:00
poll . WaitOn ( c , pollCheck ( c ,
d . CheckRunningTaskImages , checker . DeepEquals ( map [ string ] int { "busybox:latest" : len ( services ) } ) ) , poll . WithTimeout ( defaultReconciliationTimeout ) )
2016-11-30 00:48:44 -05:00
for name , message := range services {
out , err := d . Cmd ( "service" , "logs" , name )
2019-04-04 09:23:19 -04:00
assert . NilError ( c , err )
2016-11-30 00:48:44 -05:00
c . Logf ( "log for %q: %q" , name , out )
2019-04-04 09:23:19 -04:00
assert . Assert ( c , strings . Contains ( out , message ) )
2016-11-30 00:48:44 -05:00
}
2016-11-18 15:38:36 -05:00
}
2019-09-12 02:27:03 -04:00
// countLogLines returns a closure that can be used with poll.WaitOn() to
2017-03-01 19:37:25 -05:00
// verify that a minimum number of expected container log messages have been
// output.
2019-09-09 17:08:22 -04:00
func countLogLines ( d * daemon . Daemon , name string ) func ( * testing . T ) ( interface { } , string ) {
return func ( c * testing . T ) ( interface { } , string ) {
2017-04-04 18:52:19 -04:00
result := icmd . RunCmd ( d . Command ( "service" , "logs" , "-t" , "--raw" , name ) )
2017-03-21 14:35:55 -04:00
result . Assert ( c , icmd . Expected { } )
2017-04-04 18:52:19 -04:00
// if this returns an emptystring, trying to split it later will return
// an array containing emptystring. a valid log line will NEVER be
// emptystring because we ask for the timestamp.
if result . Stdout ( ) == "" {
2019-09-09 17:08:22 -04:00
return 0 , "Empty stdout"
2017-04-04 18:52:19 -04:00
}
2017-03-21 14:35:55 -04:00
lines := strings . Split ( strings . TrimSpace ( result . Stdout ( ) ) , "\n" )
2019-09-09 17:08:22 -04:00
return len ( lines ) , fmt . Sprintf ( "output, %q" , string ( result . Stdout ( ) ) )
2017-03-01 19:37:25 -05:00
}
}
2019-09-09 17:05:55 -04:00
func ( s * DockerSwarmSuite ) TestServiceLogsCompleteness ( c * testing . T ) {
2017-03-01 19:37:25 -05:00
d := s . AddDaemon ( c , true , true )
name := "TestServiceLogsCompleteness"
// make a service that prints 6 lines
2019-09-09 19:41:57 -04:00
out , err := d . Cmd ( "service" , "create" , "--detach" , "--no-resolve-image" , "--name" , name , "busybox" , "sh" , "-c" , "for line in $(seq 0 5); do echo log test $line; done; exec tail /dev/null" )
2019-04-04 09:23:19 -04:00
assert . NilError ( c , err )
assert . Assert ( c , strings . TrimSpace ( out ) != "" )
2017-03-01 19:37:25 -05:00
// make sure task has been deployed.
2019-08-26 11:51:40 -04:00
poll . WaitOn ( c , pollCheck ( c , d . CheckActiveContainerCount , checker . Equals ( 1 ) ) , poll . WithTimeout ( defaultReconciliationTimeout ) )
2017-03-01 19:37:25 -05:00
// and make sure we have all the log lines
2019-08-26 11:51:40 -04:00
poll . WaitOn ( c , pollCheck ( c , countLogLines ( d , name ) , checker . Equals ( 6 ) ) , poll . WithTimeout ( defaultReconciliationTimeout ) )
2017-03-01 19:37:25 -05:00
2017-03-21 14:35:55 -04:00
out , err = d . Cmd ( "service" , "logs" , name )
2019-04-04 09:23:19 -04:00
assert . NilError ( c , err )
2017-03-21 14:35:55 -04:00
lines := strings . Split ( strings . TrimSpace ( out ) , "\n" )
2017-03-01 19:37:25 -05:00
// i have heard anecdotal reports that logs may come back from the engine
// mis-ordered. if this tests fails, consider the possibility that that
// might be occurring
2017-03-21 14:35:55 -04:00
for i , line := range lines {
2019-04-04 09:23:19 -04:00
assert . Assert ( c , strings . Contains ( line , fmt . Sprintf ( "log test %v" , i ) ) )
2017-03-01 19:37:25 -05:00
}
}
2019-09-09 17:05:55 -04:00
func ( s * DockerSwarmSuite ) TestServiceLogsTail ( c * testing . T ) {
2017-03-01 19:37:25 -05:00
d := s . AddDaemon ( c , true , true )
name := "TestServiceLogsTail"
// make a service that prints 6 lines
2017-09-27 19:17:55 -04:00
out , err := d . Cmd ( "service" , "create" , "--detach" , "--no-resolve-image" , "--name" , name , "busybox" , "sh" , "-c" , "for line in $(seq 1 6); do echo log test $line; done; sleep 100000" )
2019-04-04 09:23:19 -04:00
assert . NilError ( c , err )
assert . Assert ( c , strings . TrimSpace ( out ) != "" )
2017-03-01 19:37:25 -05:00
// make sure task has been deployed.
2019-08-26 11:51:40 -04:00
poll . WaitOn ( c , pollCheck ( c , d . CheckActiveContainerCount , checker . Equals ( 1 ) ) , poll . WithTimeout ( defaultReconciliationTimeout ) )
poll . WaitOn ( c , pollCheck ( c , countLogLines ( d , name ) , checker . Equals ( 6 ) ) , poll . WithTimeout ( defaultReconciliationTimeout ) )
2017-03-01 19:37:25 -05:00
2017-03-21 14:35:55 -04:00
out , err = d . Cmd ( "service" , "logs" , "--tail=2" , name )
2019-04-04 09:23:19 -04:00
assert . NilError ( c , err )
2017-03-21 14:35:55 -04:00
lines := strings . Split ( strings . TrimSpace ( out ) , "\n" )
2017-03-01 19:37:25 -05:00
2017-03-21 14:35:55 -04:00
for i , line := range lines {
// doing i+5 is hacky but not too fragile, it's good enough. if it flakes something else is wrong
2019-04-04 09:23:19 -04:00
assert . Assert ( c , strings . Contains ( line , fmt . Sprintf ( "log test %v" , i + 5 ) ) )
2017-03-01 19:37:25 -05:00
}
}
2019-09-09 17:05:55 -04:00
func ( s * DockerSwarmSuite ) TestServiceLogsSince ( c * testing . T ) {
2017-03-01 19:37:25 -05:00
// See DockerSuite.TestLogsSince, which is where this comes from
d := s . AddDaemon ( c , true , true )
name := "TestServiceLogsSince"
2019-09-09 19:41:57 -04:00
out , err := d . Cmd ( "service" , "create" , "--detach" , "--no-resolve-image" , "--name" , name , "busybox" , "sh" , "-c" , "for i in $(seq 1 3); do usleep 100000; echo log$i; done; exec tail /dev/null" )
2019-04-04 09:23:19 -04:00
assert . NilError ( c , err )
assert . Assert ( c , strings . TrimSpace ( out ) != "" )
2019-08-26 11:51:40 -04:00
poll . WaitOn ( c , pollCheck ( c , d . CheckActiveContainerCount , checker . Equals ( 1 ) ) , poll . WithTimeout ( defaultReconciliationTimeout ) )
2017-03-01 19:37:25 -05:00
// wait a sec for the logs to come in
2019-08-26 11:51:40 -04:00
poll . WaitOn ( c , pollCheck ( c , countLogLines ( d , name ) , checker . Equals ( 3 ) ) , poll . WithTimeout ( defaultReconciliationTimeout ) )
2017-03-01 19:37:25 -05:00
out , err = d . Cmd ( "service" , "logs" , "-t" , name )
2019-04-04 09:23:19 -04:00
assert . NilError ( c , err )
2017-03-01 19:37:25 -05:00
log2Line := strings . Split ( strings . Split ( out , "\n" ) [ 1 ] , " " )
t , err := time . Parse ( time . RFC3339Nano , log2Line [ 0 ] ) // timestamp log2 is written
2019-04-04 09:23:19 -04:00
assert . NilError ( c , err )
2017-03-01 19:37:25 -05:00
u := t . Add ( 50 * time . Millisecond ) // add .05s so log1 & log2 don't show up
since := u . Format ( time . RFC3339Nano )
out , err = d . Cmd ( "service" , "logs" , "-t" , fmt . Sprintf ( "--since=%v" , since ) , name )
2019-04-04 09:23:19 -04:00
assert . NilError ( c , err )
2017-03-01 19:37:25 -05:00
unexpected := [ ] string { "log1" , "log2" }
expected := [ ] string { "log3" }
for _ , v := range unexpected {
2019-04-04 09:23:19 -04:00
assert . Assert ( c , ! strings . Contains ( out , v ) , "unexpected log message returned, since=%v" , u )
2017-03-01 19:37:25 -05:00
}
for _ , v := range expected {
2019-04-04 09:23:19 -04:00
assert . Assert ( c , strings . Contains ( out , v ) , "expected log message %v, was not present, since=%v" , u )
2017-03-01 19:37:25 -05:00
}
}
2019-09-09 17:05:55 -04:00
func ( s * DockerSwarmSuite ) TestServiceLogsFollow ( c * testing . T ) {
2016-11-18 15:38:36 -05:00
d := s . AddDaemon ( c , true , true )
name := "TestServiceLogsFollow"
2019-09-09 19:41:57 -04:00
out , err := d . Cmd ( "service" , "create" , "--detach" , "--no-resolve-image" , "--name" , name , "busybox" , "sh" , "-c" , "trap 'exit 0' TERM; while true; do echo log test; usleep 100000; done" )
2019-04-04 09:23:19 -04:00
assert . NilError ( c , err )
assert . Assert ( c , strings . TrimSpace ( out ) != "" )
2016-10-26 04:19:32 -04:00
// make sure task has been deployed.
2019-08-26 11:51:40 -04:00
poll . WaitOn ( c , pollCheck ( c , d . CheckActiveContainerCount , checker . Equals ( 1 ) ) , poll . WithTimeout ( defaultReconciliationTimeout ) )
2016-10-26 04:19:32 -04:00
args := [ ] string { "service" , "logs" , "-f" , name }
2016-12-09 04:17:53 -05:00
cmd := exec . Command ( dockerBinary , d . PrependHostArg ( args ) ... )
2016-10-26 04:19:32 -04:00
r , w := io . Pipe ( )
cmd . Stdout = w
cmd . Stderr = w
2019-04-04 09:23:19 -04:00
assert . NilError ( c , cmd . Start ( ) )
2017-09-07 13:11:25 -04:00
go cmd . Wait ( )
2016-10-26 04:19:32 -04:00
// Make sure pipe is written to
ch := make ( chan * logMessage )
2016-11-18 15:38:36 -05:00
done := make ( chan struct { } )
2016-10-26 04:19:32 -04:00
go func ( ) {
reader := bufio . NewReader ( r )
2016-11-18 15:38:36 -05:00
for {
msg := & logMessage { }
msg . data , _ , msg . err = reader . ReadLine ( )
select {
case ch <- msg :
case <- done :
return
}
}
2016-10-26 04:19:32 -04:00
} ( )
2016-11-18 15:38:36 -05:00
for i := 0 ; i < 3 ; i ++ {
msg := <- ch
2019-04-04 09:23:19 -04:00
assert . NilError ( c , msg . err )
assert . Assert ( c , strings . Contains ( string ( msg . data ) , "log test" ) )
2016-11-18 15:38:36 -05:00
}
close ( done )
2016-10-26 04:19:32 -04:00
2019-04-04 09:23:19 -04:00
assert . NilError ( c , cmd . Process . Kill ( ) )
2016-10-26 04:19:32 -04:00
}
2017-03-21 14:35:55 -04:00
2019-09-09 17:05:55 -04:00
func ( s * DockerSwarmSuite ) TestServiceLogsTaskLogs ( c * testing . T ) {
2017-03-21 14:35:55 -04:00
d := s . AddDaemon ( c , true , true )
name := "TestServicelogsTaskLogs"
replicas := 2
result := icmd . RunCmd ( d . Command (
// create a service with the name
2017-09-27 19:17:55 -04:00
"service" , "create" , "--detach" , "--no-resolve-image" , "--name" , name ,
2017-03-21 14:35:55 -04:00
// which has some number of replicas
fmt . Sprintf ( "--replicas=%v" , replicas ) ,
// which has this the task id as an environment variable templated in
"--env" , "TASK={{.Task.ID}}" ,
2017-05-21 19:24:07 -04:00
// and runs this command to print exactly 6 logs lines
2019-09-09 19:41:57 -04:00
"busybox" , "sh" , "-c" , "trap 'exit 0' TERM; for line in $(seq 0 5); do echo $TASK log test $line; done; sleep 100000" ,
2017-03-21 14:35:55 -04:00
) )
result . Assert ( c , icmd . Expected { } )
// ^^ verify that we get no error
// then verify that we have an id in stdout
id := strings . TrimSpace ( result . Stdout ( ) )
2019-04-04 09:23:19 -04:00
assert . Assert ( c , id != "" )
2017-03-21 14:35:55 -04:00
// so, right here, we're basically inspecting by id and returning only
// the ID. if they don't match, the service doesn't exist.
result = icmd . RunCmd ( d . Command ( "service" , "inspect" , "--format=\"{{.ID}}\"" , id ) )
result . Assert ( c , icmd . Expected { Out : id } )
// make sure task has been deployed.
2019-08-26 11:51:40 -04:00
poll . WaitOn ( c , pollCheck ( c , d . CheckActiveContainerCount , checker . Equals ( replicas ) ) , poll . WithTimeout ( defaultReconciliationTimeout ) )
poll . WaitOn ( c , pollCheck ( c , countLogLines ( d , name ) , checker . Equals ( 6 * replicas ) ) , poll . WithTimeout ( defaultReconciliationTimeout ) )
2017-03-21 14:35:55 -04:00
// get the task ids
result = icmd . RunCmd ( d . Command ( "service" , "ps" , "-q" , name ) )
result . Assert ( c , icmd . Expected { } )
// make sure we have two tasks
taskIDs := strings . Split ( strings . TrimSpace ( result . Stdout ( ) ) , "\n" )
2019-04-04 09:23:19 -04:00
assert . Equal ( c , len ( taskIDs ) , replicas )
2017-03-21 14:35:55 -04:00
for _ , taskID := range taskIDs {
c . Logf ( "checking task %v" , taskID )
result := icmd . RunCmd ( d . Command ( "service" , "logs" , taskID ) )
result . Assert ( c , icmd . Expected { } )
lines := strings . Split ( strings . TrimSpace ( result . Stdout ( ) ) , "\n" )
c . Logf ( "checking messages for %v" , taskID )
for i , line := range lines {
// make sure the message is in order
2019-04-04 09:23:19 -04:00
assert . Assert ( c , strings . Contains ( line , fmt . Sprintf ( "log test %v" , i ) ) )
2017-03-21 14:35:55 -04:00
// make sure it contains the task id
2019-04-04 09:23:19 -04:00
assert . Assert ( c , strings . Contains ( line , taskID ) )
2017-03-21 14:35:55 -04:00
}
}
}
2017-03-20 13:07:04 -04:00
2019-09-09 17:05:55 -04:00
func ( s * DockerSwarmSuite ) TestServiceLogsTTY ( c * testing . T ) {
2017-03-20 13:07:04 -04:00
d := s . AddDaemon ( c , true , true )
name := "TestServiceLogsTTY"
result := icmd . RunCmd ( d . Command (
// create a service
2017-09-27 19:17:55 -04:00
"service" , "create" , "--detach" , "--no-resolve-image" ,
2017-03-20 13:07:04 -04:00
// name it $name
"--name" , name ,
// use a TTY
"-t" ,
// busybox image, shell string
"busybox" , "sh" , "-c" ,
// echo to stdout and stderr
"echo out; (echo err 1>&2); sleep 10000" ,
) )
result . Assert ( c , icmd . Expected { } )
id := strings . TrimSpace ( result . Stdout ( ) )
2019-04-04 09:23:19 -04:00
assert . Assert ( c , id != "" )
2017-03-20 13:07:04 -04:00
// so, right here, we're basically inspecting by id and returning only
// the ID. if they don't match, the service doesn't exist.
result = icmd . RunCmd ( d . Command ( "service" , "inspect" , "--format=\"{{.ID}}\"" , id ) )
result . Assert ( c , icmd . Expected { Out : id } )
// make sure task has been deployed.
2019-08-26 11:51:40 -04:00
poll . WaitOn ( c , pollCheck ( c , d . CheckActiveContainerCount , checker . Equals ( 1 ) ) , poll . WithTimeout ( defaultReconciliationTimeout ) )
2017-03-20 13:07:04 -04:00
// and make sure we have all the log lines
2019-08-26 11:51:40 -04:00
poll . WaitOn ( c , pollCheck ( c , countLogLines ( d , name ) , checker . Equals ( 2 ) ) , poll . WithTimeout ( defaultReconciliationTimeout ) )
2017-03-20 13:07:04 -04:00
2017-04-04 18:52:19 -04:00
cmd := d . Command ( "service" , "logs" , "--raw" , name )
2017-03-20 13:07:04 -04:00
result = icmd . RunCmd ( cmd )
// for some reason there is carriage return in the output. i think this is
// just expected.
2017-08-23 17:01:29 -04:00
result . Assert ( c , icmd . Expected { Out : "out\r\nerr\r\n" } )
2017-03-20 13:07:04 -04:00
}
2017-05-03 19:04:51 -04:00
2019-09-09 17:05:55 -04:00
func ( s * DockerSwarmSuite ) TestServiceLogsNoHangDeletedContainer ( c * testing . T ) {
2017-05-03 19:04:51 -04:00
d := s . AddDaemon ( c , true , true )
name := "TestServiceLogsNoHangDeletedContainer"
result := icmd . RunCmd ( d . Command (
// create a service
2017-09-27 19:17:55 -04:00
"service" , "create" , "--detach" , "--no-resolve-image" ,
2017-05-03 19:04:51 -04:00
// name it $name
"--name" , name ,
// busybox image, shell string
"busybox" , "sh" , "-c" ,
// echo to stdout and stderr
"while true; do echo line; sleep 2; done" ,
) )
// confirm that the command succeeded
2017-08-23 17:01:29 -04:00
result . Assert ( c , icmd . Expected { } )
2017-05-03 19:04:51 -04:00
// get the service id
id := strings . TrimSpace ( result . Stdout ( ) )
2019-04-04 09:23:19 -04:00
assert . Assert ( c , id != "" )
2017-05-03 19:04:51 -04:00
// make sure task has been deployed.
2019-08-26 11:51:40 -04:00
poll . WaitOn ( c , pollCheck ( c , d . CheckActiveContainerCount , checker . Equals ( 1 ) ) , poll . WithTimeout ( defaultReconciliationTimeout ) )
2017-05-03 19:04:51 -04:00
// and make sure we have all the log lines
2019-08-26 11:51:40 -04:00
poll . WaitOn ( c , pollCheck ( c , countLogLines ( d , name ) , checker . Equals ( 2 ) ) , poll . WithTimeout ( defaultReconciliationTimeout ) )
2017-05-03 19:04:51 -04:00
// now find and nuke the container
result = icmd . RunCmd ( d . Command ( "ps" , "-q" ) )
containerID := strings . TrimSpace ( result . Stdout ( ) )
2019-04-04 09:23:19 -04:00
assert . Assert ( c , containerID != "" )
2019-09-09 19:41:57 -04:00
result = icmd . RunCmd ( d . Command ( "rm" , "-f" , containerID ) )
2017-08-23 17:01:29 -04:00
result . Assert ( c , icmd . Expected { Out : containerID } )
2017-05-03 19:04:51 -04:00
// run logs. use tail 2 to make sure we don't try to get a bunch of logs
// somehow and slow down execution time
cmd := d . Command ( "service" , "logs" , "--tail" , "2" , id )
// start the command and then wait for it to finish with a 3 second timeout
result = icmd . StartCmd ( cmd )
result = icmd . WaitOnCmd ( 3 * time . Second , result )
// then, assert that the result matches expected. if the command timed out,
// if the command is timed out, result.Timeout will be true, but the
// Expected defaults to false
2017-08-23 17:01:29 -04:00
result . Assert ( c , icmd . Expected { } )
2017-05-03 19:04:51 -04:00
}
2017-04-04 18:52:19 -04:00
2019-09-09 17:05:55 -04:00
func ( s * DockerSwarmSuite ) TestServiceLogsDetails ( c * testing . T ) {
2017-04-04 18:52:19 -04:00
d := s . AddDaemon ( c , true , true )
name := "TestServiceLogsDetails"
result := icmd . RunCmd ( d . Command (
// create a service
2017-09-27 19:17:55 -04:00
"service" , "create" , "--detach" , "--no-resolve-image" ,
2017-04-04 18:52:19 -04:00
// name it $name
"--name" , name ,
// add an environment variable
"--env" , "asdf=test1" ,
// add a log driver (without explicitly setting a driver, log-opt doesn't work)
"--log-driver" , "json-file" ,
// add a log option to print the environment variable
"--log-opt" , "env=asdf" ,
// busybox image, shell string
"busybox" , "sh" , "-c" ,
// make a log line
2019-09-09 19:41:57 -04:00
"trap 'exit 0' TERM; echo LogLine; while true; do sleep 1; done;" ,
2017-04-04 18:52:19 -04:00
) )
result . Assert ( c , icmd . Expected { } )
id := strings . TrimSpace ( result . Stdout ( ) )
2019-04-04 09:23:19 -04:00
assert . Assert ( c , id != "" )
2017-04-04 18:52:19 -04:00
// make sure task has been deployed
2019-08-26 11:51:40 -04:00
poll . WaitOn ( c , pollCheck ( c , d . CheckActiveContainerCount , checker . Equals ( 1 ) ) , poll . WithTimeout ( defaultReconciliationTimeout ) )
2017-04-04 18:52:19 -04:00
// and make sure we have all the log lines
2019-08-26 11:51:40 -04:00
poll . WaitOn ( c , pollCheck ( c , countLogLines ( d , name ) , checker . Equals ( 1 ) ) , poll . WithTimeout ( defaultReconciliationTimeout ) )
2017-04-04 18:52:19 -04:00
// First, test without pretty printing
// call service logs with details. set raw to skip pretty printing
result = icmd . RunCmd ( d . Command ( "service" , "logs" , "--raw" , "--details" , name ) )
// in this case, we should get details and we should get log message, but
// there will also be context as details (which will fall after the detail
// we inserted in alphabetical order
2017-08-23 17:01:29 -04:00
result . Assert ( c , icmd . Expected { Out : "asdf=test1" } )
result . Assert ( c , icmd . Expected { Out : "LogLine" } )
2017-04-04 18:52:19 -04:00
// call service logs with details. this time, don't pass raw
result = icmd . RunCmd ( d . Command ( "service" , "logs" , "--details" , id ) )
// in this case, we should get details space logmessage as well. the context
// is part of the pretty part of the logline
2017-08-23 17:01:29 -04:00
result . Assert ( c , icmd . Expected { Out : "asdf=test1 LogLine" } )
2017-04-04 18:52:19 -04:00
}