Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions pkg/compose/compose.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,8 @@ type composeService struct {
clock clockwork.Clock
maxConcurrency int
dryRun bool

Monitor *monitor
}

// Close releases any connections/resources held by the underlying clients.
Expand Down
28 changes: 21 additions & 7 deletions pkg/compose/monitor.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,15 +35,17 @@ type monitor struct {
api client.APIClient
project string
// services tells us which service to consider and those we can ignore, maybe ran by a concurrent compose command
services map[string]bool
listeners []api.ContainerEventListener
services map[string]bool
listeners []api.ContainerEventListener
restarting chan string
}

func newMonitor(api client.APIClient, project string) *monitor {
return &monitor{
api: api,
project: project,
services: map[string]bool{},
api: api,
project: project,
services: map[string]bool{},
restarting: make(chan string),
}
}

Expand Down Expand Up @@ -91,6 +93,8 @@ func (c *monitor) Start(ctx context.Context) error {
select {
case err := <-errCh:
return err
case ctr := <-c.restarting:
restarting.Add(ctr)
case event := <-evtCh:
if len(c.services) > 0 && !c.services[event.Actor.Attributes[api.ServiceLabel]] {
continue
Expand All @@ -100,6 +104,8 @@ func (c *monitor) Start(ctx context.Context) error {
return err
}

logrus.Debugf("event: Container %s %s", ctr.Name, event.Action)

switch event.Action {
case events.ActionCreate:
if len(c.services) == 0 || c.services[ctr.Labels[api.ServiceLabel]] {
Expand Down Expand Up @@ -140,7 +146,9 @@ func (c *monitor) Start(ctx context.Context) error {
// when a container is in restarting phase, and we stop the application (abort-on-container-exit)
// we won't get any additional start+die events, just this stop as a proof container is down
logrus.Debugf("container %s stopped", ctr.Name)
containers.Remove(ctr.ID)
if !restarting.Has(ctr.ID) {
containers.Remove(ctr.ID)
}
case events.ActionDie:
logrus.Debugf("container %s exited with code %d", ctr.Name, ctr.ExitCode)
inspect, err := c.api.ContainerInspect(ctx, event.Actor.ID)
Expand All @@ -165,7 +173,9 @@ func (c *monitor) Start(ctx context.Context) error {
for _, listener := range c.listeners {
listener(newContainerEvent(event.TimeNano, ctr, api.ContainerEventExited))
}
containers.Remove(ctr.ID)
if !restarting.Has(ctr.ID) {
containers.Remove(ctr.ID)
}
}
}
}
Expand Down Expand Up @@ -216,3 +226,7 @@ func (c *monitor) getContainerSummary(event events.Message) (*api.ContainerSumma
func (c *monitor) withListener(listener api.ContainerEventListener) {
c.listeners = append(c.listeners, listener)
}

func (c *monitor) Restarting(id string) {
c.restarting <- id
}
5 changes: 5 additions & 0 deletions pkg/compose/restart.go
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,11 @@ func (s *composeService) restart(ctx context.Context, projectName string, option
eventName := getContainerProgressName(ctr)
w.Event(progress.RestartingEvent(eventName))
timeout := utils.DurationSecondToInt(options.Timeout)
if s.Monitor != nil {
// Let monitor know we are restarting container, as there's no way to guess based on engine events
s.Monitor.Restarting(ctr.ID)
}

err = s.apiClient().ContainerRestart(ctx, ctr.ID, container.StopOptions{Timeout: timeout})
if err != nil {
return err
Expand Down
1 change: 1 addition & 0 deletions pkg/compose/up.go
Original file line number Diff line number Diff line change
Expand Up @@ -271,6 +271,7 @@ func (s *composeService) Up(ctx context.Context, project *types.Project, options
})
})

s.Monitor = monitor
eg.Go(func() error {
err := monitor.Start(globalCtx)
// cancel the global context to terminate signal-handler goroutines
Expand Down