Skip to content
This repository was archived by the owner on Nov 27, 2023. It is now read-only.

921 fix public subnet retrieval #1298

Open
wants to merge 12 commits into
base: main
Choose a base branch
from
3 changes: 3 additions & 0 deletions api/compose/api.go
Original file line number Diff line number Diff line change
@@ -184,6 +184,7 @@ type Stack struct {
type LogConsumer interface {
Log(service, container, message string)
Status(service, container, msg string)
Register(service string, source string)
}

// ContainerEventListener is a callback to process ContainerEvent from services
@@ -201,6 +202,8 @@ type ContainerEvent struct {
const (
// ContainerEventLog is a ContainerEvent of type log. Line is set
ContainerEventLog = iota
// ContainerEventAttach is a ContainerEvent of type attach. First event sent about a container
ContainerEventAttach
// ContainerEventExit is a ContainerEvent of type exit. ExitCode is set
ContainerEventExit
)
16 changes: 11 additions & 5 deletions cli/cmd/compose/logs.go
Original file line number Diff line number Diff line change
@@ -31,8 +31,10 @@ import (
type logsOptions struct {
*projectOptions
composeOptions
follow bool
tail string
follow bool
tail string
noColor bool
noPrefix bool
}

func logsCommand(p *projectOptions, contextType string) *cobra.Command {
@@ -46,9 +48,13 @@ func logsCommand(p *projectOptions, contextType string) *cobra.Command {
return runLogs(cmd.Context(), opts, args)
},
}
logsCmd.Flags().BoolVar(&opts.follow, "follow", false, "Follow log output.")
flags := logsCmd.Flags()
flags.BoolVar(&opts.follow, "follow", false, "Follow log output.")
flags.BoolVar(&opts.noColor, "no-color", false, "Produce monochrome output.")
flags.BoolVar(&opts.noPrefix, "no-log-prefix", false, "Don't print prefix in logs.")

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.")
flags.StringVar(&opts.tail, "tail", "all", "Number of lines to show from the end of the logs for each container.")
}
return logsCmd
}
@@ -63,7 +69,7 @@ func runLogs(ctx context.Context, opts logsOptions, services []string) error {
if err != nil {
return err
}
consumer := formatter.NewLogConsumer(ctx, os.Stdout)
consumer := formatter.NewLogConsumer(ctx, os.Stdout, !opts.noColor, !opts.noPrefix)
return c.ComposeService().Logs(ctx, projectName, consumer, compose.LogOptions{
Services: services,
Follow: opts.follow,
31 changes: 2 additions & 29 deletions cli/cmd/compose/start.go
Original file line number Diff line number Diff line change
@@ -28,7 +28,6 @@ import (

type startOptions struct {
*projectOptions
Detach bool
}

func startCommand(p *projectOptions) *cobra.Command {
@@ -42,8 +41,6 @@ func startCommand(p *projectOptions) *cobra.Command {
return runStart(cmd.Context(), opts, args)
},
}

startCmd.Flags().BoolVarP(&opts.Detach, "detach", "d", false, "Detached mode: Run containers in the background")
return startCmd
}

@@ -58,32 +55,8 @@ func runStart(ctx context.Context, opts startOptions, services []string) error {
return err
}

if opts.Detach {
_, err = progress.Run(ctx, func(ctx context.Context) (string, error) {
return "", c.ComposeService().Start(ctx, project, compose.StartOptions{})
})
return err
}

queue := make(chan compose.ContainerEvent)
printer := printer{
queue: queue,
}
err = c.ComposeService().Start(ctx, project, compose.StartOptions{
Attach: func(event compose.ContainerEvent) {
queue <- event
},
})
if err != nil {
return err
}

_, err = printer.run(ctx, false, "", func() error {
ctx := context.Background()
_, err := progress.Run(ctx, func(ctx context.Context) (string, error) {
return "", c.ComposeService().Stop(ctx, project)
})
return err
_, err = progress.Run(ctx, func(ctx context.Context) (string, error) {
return "", c.ComposeService().Start(ctx, project, compose.StartOptions{})
})
return err
}
49 changes: 37 additions & 12 deletions cli/cmd/compose/up.go
Original file line number Diff line number Diff line change
@@ -36,6 +36,7 @@ import (
"github.com/compose-spec/compose-go/types"
"github.com/sirupsen/logrus"
"github.com/spf13/cobra"
"golang.org/x/sync/errgroup"
)

// composeOptions hold options common to `up` and `run` to run compose project
@@ -57,6 +58,8 @@ type upOptions struct {
cascadeStop bool
exitCodeFrom string
scale []string
noColor bool
noPrefix bool
}

func (o upOptions) recreateStrategy() string {
@@ -102,6 +105,8 @@ func upCommand(p *projectOptions, contextType string) *cobra.Command {
flags.BoolVar(&opts.Build, "build", false, "Build images before starting containers.")
flags.BoolVar(&opts.removeOrphans, "remove-orphans", false, "Remove containers for services not defined in the Compose file.")
flags.StringArrayVar(&opts.scale, "scale", []string{}, "Scale SERVICE to NUM instances. Overrides the `scale` setting in the Compose file if present.")
flags.BoolVar(&opts.noColor, "no-color", false, "Produce monochrome output.")
flags.BoolVar(&opts.noPrefix, "no-log-prefix", false, "Don't print prefix in logs.")

switch contextType {
case store.AciContextType:
@@ -199,6 +204,16 @@ func runCreateStart(ctx context.Context, opts upOptions, services []string) erro
stopFunc() // nolint:errcheck
}()

consumer := formatter.NewLogConsumer(ctx, os.Stdout, !opts.noColor, !opts.noPrefix)

var exitCode int
eg, ctx := errgroup.WithContext(ctx)
eg.Go(func() error {
code, err := printer.run(ctx, opts.cascadeStop, opts.exitCodeFrom, consumer, stopFunc)
exitCode = code
return err
})

err = c.ComposeService().Start(ctx, project, compose.StartOptions{
Attach: func(event compose.ContainerEvent) {
queue <- event
@@ -208,7 +223,7 @@ func runCreateStart(ctx context.Context, opts upOptions, services []string) erro
return err
}

exitCode, err := printer.run(ctx, opts.cascadeStop, opts.exitCodeFrom, stopFunc)
err = eg.Wait()
if exitCode != 0 {
return cmd.ExitCodeError{ExitCode: exitCode}
}
@@ -298,27 +313,37 @@ type printer struct {
queue chan compose.ContainerEvent
}

func (p printer) run(ctx context.Context, cascadeStop bool, exitCodeFrom string, stopFn func() error) (int, error) { //nolint:unparam
consumer := formatter.NewLogConsumer(ctx, os.Stdout)
func (p printer) run(ctx context.Context, cascadeStop bool, exitCodeFrom string, consumer compose.LogConsumer, stopFn func() error) (int, error) { //nolint:unparam
var aborting bool
var count int
for {
event := <-p.queue
switch event.Type {
case compose.ContainerEventAttach:
consumer.Register(event.Service, event.Source)
count++
case compose.ContainerEventExit:
if !aborting {
consumer.Status(event.Service, event.Source, fmt.Sprintf("exited with code %d", event.ExitCode))
}
if cascadeStop && !aborting {
aborting = true
fmt.Println("Aborting on container exit...")
err := stopFn()
if err != nil {
return 0, err
if cascadeStop {
if !aborting {
aborting = true
fmt.Println("Aborting on container exit...")
err := stopFn()
if err != nil {
return 0, err
}
}
if exitCodeFrom == "" || exitCodeFrom == event.Service {
logrus.Error(event.ExitCode)
return event.ExitCode, nil
}
}
if exitCodeFrom == "" || exitCodeFrom == event.Service {
logrus.Error(event.ExitCode)
return event.ExitCode, nil
count--
if count == 0 {
// Last container terminated, done
return 0, nil
}
case compose.ContainerEventLog:
if !aborting {
4 changes: 4 additions & 0 deletions cli/formatter/colors.go
Original file line number Diff line number Diff line change
@@ -35,6 +35,10 @@ var names = []string{
// colorFunc use ANSI codes to render colored text on console
type colorFunc func(s string) string

var monochrome = func(s string) string {
return s
}

func ansiColor(code, s string) string {
return fmt.Sprintf("%s%s%s", ansi(code), s, ansi("0"))
}
87 changes: 59 additions & 28 deletions cli/formatter/logs.go
Original file line number Diff line number Diff line change
@@ -17,7 +17,6 @@
package formatter

import (
"bytes"
"context"
"fmt"
"io"
@@ -28,59 +27,91 @@ import (
)

// NewLogConsumer creates a new LogConsumer
func NewLogConsumer(ctx context.Context, w io.Writer) compose.LogConsumer {
func NewLogConsumer(ctx context.Context, w io.Writer, color bool, prefix bool) compose.LogConsumer {
return &logConsumer{
ctx: ctx,
colors: map[string]colorFunc{},
width: 0,
writer: w,
ctx: ctx,
presenters: map[string]*presenter{},
width: 0,
writer: w,
color: color,
prefix: prefix,
}
}

func (l *logConsumer) Register(service string, source string) {
l.register(service, source)
}

func (l *logConsumer) register(service string, source string) *presenter {
cf := monochrome
if l.color {
cf = <-loop
}
p := &presenter{
colors: cf,
service: service,
container: source,
}
l.presenters[source] = p
if l.prefix {
l.computeWidth()
for _, p := range l.presenters {
p.setPrefix(l.width)
}
}
return p
}

// Log formats a log message as received from service/container
func (l *logConsumer) Log(service, container, message string) {
if l.ctx.Err() != nil {
return
}
cf := l.getColorFunc(service)
prefix := fmt.Sprintf("%-"+strconv.Itoa(l.width)+"s |", container)

p, ok := l.presenters[container]
if !ok { // should have been registered, but ¯\_(ツ)_/¯
p = l.register(service, container)
}
for _, line := range strings.Split(message, "\n") {
buf := bytes.NewBufferString(fmt.Sprintf("%s %s\n", cf(prefix), line))
l.writer.Write(buf.Bytes()) // nolint:errcheck
fmt.Fprintf(l.writer, "%s %s\n", p.prefix, line) // nolint:errcheck
}
}

func (l *logConsumer) Status(service, container, msg string) {
cf := l.getColorFunc(service)
buf := bytes.NewBufferString(cf(fmt.Sprintf("%s %s\n", container, msg)))
l.writer.Write(buf.Bytes()) // nolint:errcheck
}

func (l *logConsumer) getColorFunc(service string) colorFunc {
cf, ok := l.colors[service]
p, ok := l.presenters[container]
if !ok {
cf = <-loop
l.colors[service] = cf
l.computeWidth()
p = l.register(service, container)
}
return cf
s := p.colors(fmt.Sprintf("%s %s\n", container, msg))
l.writer.Write([]byte(s)) // nolint:errcheck
}

func (l *logConsumer) computeWidth() {
width := 0
for n := range l.colors {
for n := range l.presenters {
if len(n) > width {
width = len(n)
}
}
l.width = width + 3
l.width = width + 1
}

// LogConsumer consume logs from services and format them
type logConsumer struct {
ctx context.Context
colors map[string]colorFunc
width int
writer io.Writer
ctx context.Context
presenters map[string]*presenter
width int
writer io.Writer
color bool
prefix bool
}

type presenter struct {
colors colorFunc
service string
container string
prefix string
}

func (p *presenter) setPrefix(width int) {
p.prefix = p.colors(fmt.Sprintf("%-"+strconv.Itoa(width)+"s |", p.container))
}
2 changes: 1 addition & 1 deletion ecs/aws.go
Original file line number Diff line number Diff line change
@@ -69,7 +69,7 @@ type API interface {
getURLWithPortMapping(ctx context.Context, targetGroupArns []string) ([]compose.PortPublisher, error)
ListTasks(ctx context.Context, cluster string, family string) ([]string, error)
GetPublicIPs(ctx context.Context, interfaces ...string) (map[string]string, error)
ResolveLoadBalancer(ctx context.Context, nameOrArn string) (awsResource, string, string, []awsResource, error)
ResolveLoadBalancer(ctx context.Context, nameOrArn string) (awsResource, string, string, vpcSubNets, error)
GetLoadBalancerURL(ctx context.Context, arn string) (string, error)
GetParameter(ctx context.Context, name string) (string, error)
SecurityGroupExists(ctx context.Context, sg string) (bool, error)
Loading
Oops, something went wrong.