Browse Source

introduce compose logs --tail and --follow options

Signed-off-by: Nicolas De Loof <[email protected]>
Nicolas De Loof 4 years ago
parent
commit
7d0e1dfc3c
8 changed files with 25 additions and 10 deletions
  1. 2 0
      api/compose/api.go
  2. 1 1
      cli/cmd/compose/compose.go
  3. 10 1
      cli/cmd/compose/logs.go
  4. 1 1
      ecs/aws.go
  5. 4 4
      ecs/aws_mock.go
  6. 1 1
      ecs/logs.go
  7. 4 1
      ecs/sdk.go
  8. 2 1
      local/compose/logs.go

+ 2 - 0
api/compose/api.go

@@ -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 (

+ 1 - 1
cli/cmd/compose/compose.go

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

+ 10 - 1
cli/cmd/compose/logs.go

@@ -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,
 	})
 }

+ 1 - 1
ecs/aws.go

@@ -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)

+ 4 - 4
ecs/aws_mock.go

@@ -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

+ 1 - 1
ecs/logs.go

@@ -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
 }
 

+ 4 - 1
ecs/sdk.go

@@ -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)
 	}
 }

+ 2 - 1
local/compose/logs.go

@@ -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