introduce compose logs --tail and --follow options

Signed-off-by: Nicolas De Loof <nicolas.deloof@gmail.com>
This commit is contained in:
Nicolas De Loof 2021-01-26 16:46:15 +01:00
parent 24b5aeaa32
commit 7d0e1dfc3c
8 changed files with 25 additions and 10 deletions

View File

@ -122,6 +122,8 @@ type ServiceStatus struct {
// LogOptions defines optional parameters for the `Log` API
type LogOptions struct {
Services []string
Tail string
Follow bool
}
const (

View File

@ -97,7 +97,7 @@ func Command(contextType string) *cobra.Command {
stopCommand(&opts),
psCommand(&opts),
listCommand(),
logsCommand(&opts),
logsCommand(&opts, contextType),
convertCommand(&opts),
runCommand(&opts),
)

View File

@ -24,15 +24,18 @@ import (
"github.com/docker/compose-cli/api/client"
"github.com/docker/compose-cli/api/compose"
"github.com/docker/compose-cli/api/context/store"
"github.com/docker/compose-cli/cli/formatter"
)
type logsOptions struct {
*projectOptions
composeOptions
follow bool
tail string
}
func logsCommand(p *projectOptions) *cobra.Command {
func logsCommand(p *projectOptions, contextType string) *cobra.Command {
opts := logsOptions{
projectOptions: p,
}
@ -43,6 +46,10 @@ func logsCommand(p *projectOptions) *cobra.Command {
return runLogs(cmd.Context(), opts, args)
},
}
logsCmd.Flags().BoolVarP(&opts.follow, "follow", "f", false, "Follow log output.")
if contextType == store.DefaultContextType {
logsCmd.Flags().StringVar(&opts.tail, "tail", "all", "Number of lines to show from the end of the logs for each container.")
}
return logsCmd
}
@ -59,5 +66,7 @@ func runLogs(ctx context.Context, opts logsOptions, services []string) error {
consumer := formatter.NewLogConsumer(ctx, os.Stdout)
return c.ComposeService().Logs(ctx, projectName, consumer, compose.LogOptions{
Services: services,
Follow: opts.follow,
Tail: opts.tail,
})
}

View File

@ -63,7 +63,7 @@ type API interface {
InspectSecret(ctx context.Context, id string) (secrets.Secret, error)
ListSecrets(ctx context.Context) ([]secrets.Secret, error)
DeleteSecret(ctx context.Context, id string, recover bool) error
GetLogs(ctx context.Context, name string, consumer func(service, container, message string)) error
GetLogs(ctx context.Context, name string, consumer func(service string, container string, message string), follow bool) error
DescribeService(ctx context.Context, cluster string, arn string) (compose.ServiceStatus, error)
DescribeServiceTasks(ctx context.Context, cluster string, project string, service string) ([]compose.ContainerSummary, error)
getURLWithPortMapping(ctx context.Context, targetGroupArns []string) ([]compose.PortPublisher, error)

View File

@ -285,17 +285,17 @@ func (mr *MockAPIMockRecorder) GetLoadBalancerURL(arg0, arg1 interface{}) *gomoc
}
// GetLogs mocks base method
func (m *MockAPI) GetLogs(arg0 context.Context, arg1 string, arg2 func(string, string, string)) error {
func (m *MockAPI) GetLogs(arg0 context.Context, arg1 string, arg2 func(string, string, string), arg3 bool) error {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "GetLogs", arg0, arg1, arg2)
ret := m.ctrl.Call(m, "GetLogs", arg0, arg1, arg2, arg3)
ret0, _ := ret[0].(error)
return ret0
}
// GetLogs indicates an expected call of GetLogs
func (mr *MockAPIMockRecorder) GetLogs(arg0, arg1, arg2 interface{}) *gomock.Call {
func (mr *MockAPIMockRecorder) GetLogs(arg0, arg1, arg2, arg3 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetLogs", reflect.TypeOf((*MockAPI)(nil).GetLogs), arg0, arg1, arg2)
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetLogs", reflect.TypeOf((*MockAPI)(nil).GetLogs), arg0, arg1, arg2, arg3)
}
// GetParameter mocks base method

View File

@ -26,7 +26,7 @@ func (b *ecsAPIService) Logs(ctx context.Context, projectName string, consumer c
if len(options.Services) > 0 {
consumer = filteredLogConsumer(consumer, options.Services)
}
err := b.aws.GetLogs(ctx, projectName, consumer.Log)
err := b.aws.GetLogs(ctx, projectName, consumer.Log, options.Follow)
return err
}

View File

@ -805,7 +805,7 @@ func (s sdk) DeleteSecret(ctx context.Context, id string, recover bool) error {
return err
}
func (s sdk) GetLogs(ctx context.Context, name string, consumer func(service, container, message string)) error {
func (s sdk) GetLogs(ctx context.Context, name string, consumer func(service string, container string, message string), follow bool) error {
logGroup := fmt.Sprintf("/docker-compose/%s", name)
var startTime int64
for {
@ -837,6 +837,9 @@ func (s sdk) GetLogs(ctx context.Context, name string, consumer func(service, co
}
}
}
if !follow {
return nil
}
time.Sleep(500 * time.Millisecond)
}
}

View File

@ -64,7 +64,8 @@ func (s *composeService) Logs(ctx context.Context, projectName string, consumer
r, err := s.apiClient.ContainerLogs(ctx, container.ID, types.ContainerLogsOptions{
ShowStdout: true,
ShowStderr: true,
Follow: true,
Follow: options.Follow,
Tail: options.Tail,
})
defer r.Close() // nolint errcheck