mirror of
https://github.com/docker/compose.git
synced 2025-07-22 13:14:29 +02:00
attach to log stream by default on up
Signed-off-by: Nicolas De Loof <nicolas.deloof@gmail.com>
This commit is contained in:
parent
809c2bc45a
commit
39e4107e12
@ -56,7 +56,7 @@ func (cs *aciComposeService) Pull(ctx context.Context, project *types.Project) e
|
|||||||
return errdefs.ErrNotImplemented
|
return errdefs.ErrNotImplemented
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cs *aciComposeService) Up(ctx context.Context, project *types.Project, detach bool) error {
|
func (cs *aciComposeService) Up(ctx context.Context, project *types.Project, detach bool, w io.Writer) error {
|
||||||
logrus.Debugf("Up on project with name %q", project.Name)
|
logrus.Debugf("Up on project with name %q", project.Name)
|
||||||
|
|
||||||
if err := autocreateFileshares(ctx, project); err != nil {
|
if err := autocreateFileshares(ctx, project); err != nil {
|
||||||
|
@ -41,7 +41,7 @@ func (c *composeService) Pull(ctx context.Context, project *types.Project) error
|
|||||||
return errdefs.ErrNotImplemented
|
return errdefs.ErrNotImplemented
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *composeService) Up(context.Context, *types.Project, bool) error {
|
func (c *composeService) Up(context.Context, *types.Project, bool, io.Writer) error {
|
||||||
return errdefs.ErrNotImplemented
|
return errdefs.ErrNotImplemented
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -32,7 +32,7 @@ type Service interface {
|
|||||||
// Pull executes the equivalent of a `compose pull`
|
// Pull executes the equivalent of a `compose pull`
|
||||||
Pull(ctx context.Context, project *types.Project) error
|
Pull(ctx context.Context, project *types.Project) error
|
||||||
// Up executes the equivalent to a `compose up`
|
// Up executes the equivalent to a `compose up`
|
||||||
Up(ctx context.Context, project *types.Project, detach bool) error
|
Up(ctx context.Context, project *types.Project, detach bool, w io.Writer) error
|
||||||
// Down executes the equivalent to a `compose down`
|
// Down executes the equivalent to a `compose down`
|
||||||
Down(ctx context.Context, projectName string) error
|
Down(ctx context.Context, projectName string) error
|
||||||
// Logs executes the equivalent to a `compose logs`
|
// Logs executes the equivalent to a `compose logs`
|
||||||
|
@ -18,13 +18,14 @@ package compose
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"github.com/docker/compose-cli/progress"
|
||||||
|
"os"
|
||||||
|
|
||||||
"github.com/compose-spec/compose-go/cli"
|
"github.com/compose-spec/compose-go/cli"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
|
|
||||||
"github.com/docker/compose-cli/api/client"
|
"github.com/docker/compose-cli/api/client"
|
||||||
"github.com/docker/compose-cli/context/store"
|
"github.com/docker/compose-cli/context/store"
|
||||||
"github.com/docker/compose-cli/progress"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func upCommand(contextType string) *cobra.Command {
|
func upCommand(contextType string) *cobra.Command {
|
||||||
@ -54,25 +55,26 @@ func runUp(ctx context.Context, opts composeOptions, services []string) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err = progress.Run(ctx, func(ctx context.Context) (string, error) {
|
options, err := opts.toProjectOptions()
|
||||||
options, err := opts.toProjectOptions()
|
if err != nil {
|
||||||
if err != nil {
|
return err
|
||||||
return "", err
|
}
|
||||||
}
|
project, err := cli.ProjectFromOptions(options)
|
||||||
project, err := cli.ProjectFromOptions(options)
|
if err != nil {
|
||||||
if err != nil {
|
return err
|
||||||
return "", err
|
}
|
||||||
}
|
if opts.DomainName != "" {
|
||||||
if opts.DomainName != "" {
|
// arbitrarily set the domain name on the first service ; ACI backend will expose the entire project
|
||||||
// arbitrarily set the domain name on the first service ; ACI backend will expose the entire project
|
project.Services[0].DomainName = opts.DomainName
|
||||||
project.Services[0].DomainName = opts.DomainName
|
}
|
||||||
}
|
|
||||||
|
|
||||||
err = filter(project, services)
|
err = filter(project, services)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return err
|
||||||
}
|
}
|
||||||
return "", c.ComposeService().Up(ctx, project, opts.Detach)
|
|
||||||
|
_, err = progress.Run(ctx, func(ctx context.Context) (string, error) {
|
||||||
|
return "", c.ComposeService().Up(ctx, project, opts.Detach, os.Stdout)
|
||||||
})
|
})
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -53,7 +53,7 @@ func (e ecsLocalSimulation) Pull(ctx context.Context, project *types.Project) er
|
|||||||
return errdefs.ErrNotImplemented
|
return errdefs.ErrNotImplemented
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e ecsLocalSimulation) Up(ctx context.Context, project *types.Project, detach bool) error {
|
func (e ecsLocalSimulation) Up(ctx context.Context, project *types.Project, detach bool, w io.Writer) error {
|
||||||
cmd := exec.Command("docker-compose", "version", "--short")
|
cmd := exec.Command("docker-compose", "version", "--short")
|
||||||
b := bytes.Buffer{}
|
b := bytes.Buffer{}
|
||||||
b.WriteString("v")
|
b.WriteString("v")
|
||||||
|
@ -24,7 +24,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func (b *ecsAPIService) Logs(ctx context.Context, project string, w io.Writer) error {
|
func (b *ecsAPIService) Logs(ctx context.Context, project string, w io.Writer) error {
|
||||||
consumer := formatter.NewLogConsumer(w)
|
consumer := formatter.NewLogConsumer(ctx, w)
|
||||||
err := b.aws.GetLogs(ctx, project, consumer.Log)
|
err := b.aws.GetLogs(ctx, project, consumer.Log)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -19,6 +19,7 @@ package ecs
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io"
|
||||||
"os"
|
"os"
|
||||||
"os/signal"
|
"os/signal"
|
||||||
"syscall"
|
"syscall"
|
||||||
@ -39,7 +40,7 @@ func (b *ecsAPIService) Pull(ctx context.Context, project *types.Project) error
|
|||||||
return errdefs.ErrNotImplemented
|
return errdefs.ErrNotImplemented
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *ecsAPIService) Up(ctx context.Context, project *types.Project, detach bool) error {
|
func (b *ecsAPIService) Up(ctx context.Context, project *types.Project, detach bool, w io.Writer) error {
|
||||||
err := b.aws.CheckRequirements(ctx, b.Region)
|
err := b.aws.CheckRequirements(ctx, b.Region)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -151,7 +151,7 @@ func (cs *composeService) Pull(ctx context.Context, project *types.Project) erro
|
|||||||
return errdefs.ErrNotImplemented
|
return errdefs.ErrNotImplemented
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cs *composeService) Up(ctx context.Context, project *types.Project, detach bool) error {
|
func (cs *composeService) Up(ctx context.Context, project *types.Project, detach bool, w io.Writer) error {
|
||||||
fmt.Printf("Up command on project %q", project.Name)
|
fmt.Printf("Up command on project %q", project.Name)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -18,6 +18,7 @@ package formatter
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"strconv"
|
"strconv"
|
||||||
@ -25,8 +26,9 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
// NewLogConsumer creates a new LogConsumer
|
// NewLogConsumer creates a new LogConsumer
|
||||||
func NewLogConsumer(w io.Writer) LogConsumer {
|
func NewLogConsumer(ctx context.Context, w io.Writer) LogConsumer {
|
||||||
return LogConsumer{
|
return LogConsumer{
|
||||||
|
ctx: ctx,
|
||||||
colors: map[string]colorFunc{},
|
colors: map[string]colorFunc{},
|
||||||
width: 0,
|
width: 0,
|
||||||
writer: w,
|
writer: w,
|
||||||
@ -35,6 +37,9 @@ func NewLogConsumer(w io.Writer) LogConsumer {
|
|||||||
|
|
||||||
// Log formats a log message as received from service/container
|
// Log formats a log message as received from service/container
|
||||||
func (l *LogConsumer) Log(service, container, message string) {
|
func (l *LogConsumer) Log(service, container, message string) {
|
||||||
|
if l.ctx.Err() == context.Canceled {
|
||||||
|
return
|
||||||
|
}
|
||||||
cf, ok := l.colors[service]
|
cf, ok := l.colors[service]
|
||||||
if !ok {
|
if !ok {
|
||||||
cf = <-loop
|
cf = <-loop
|
||||||
@ -70,6 +75,7 @@ func (l *LogConsumer) computeWidth() {
|
|||||||
|
|
||||||
// LogConsumer consume logs from services and format them
|
// LogConsumer consume logs from services and format them
|
||||||
type LogConsumer struct {
|
type LogConsumer struct {
|
||||||
|
ctx context.Context
|
||||||
colors map[string]colorFunc
|
colors map[string]colorFunc
|
||||||
width int
|
width int
|
||||||
writer io.Writer
|
writer io.Writer
|
||||||
|
118
local/compose.go
118
local/compose.go
@ -293,13 +293,14 @@ func toProgressEvent(prefix string, jm jsonmessage.JSONMessage, w progress.Write
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *composeService) Up(ctx context.Context, project *types.Project, detach bool) error {
|
func (s *composeService) Up(ctx context.Context, project *types.Project, detach bool, w io.Writer) error {
|
||||||
err := s.ensureImagesExists(ctx, project)
|
err := s.ensureImagesExists(ctx, project)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
for k, network := range project.Networks {
|
for k, network := range project.Networks {
|
||||||
if !network.External.External && network.Name == k {
|
if !network.External.External && network.Name != "" {
|
||||||
network.Name = fmt.Sprintf("%s_%s", project.Name, k)
|
network.Name = fmt.Sprintf("%s_%s", project.Name, k)
|
||||||
project.Networks[k] = network
|
project.Networks[k] = network
|
||||||
}
|
}
|
||||||
@ -329,9 +330,117 @@ func (s *composeService) Up(ctx context.Context, project *types.Project, detach
|
|||||||
err = InDependencyOrder(ctx, project, func(c context.Context, service types.ServiceConfig) error {
|
err = InDependencyOrder(ctx, project, func(c context.Context, service types.ServiceConfig) error {
|
||||||
return s.ensureService(c, project, service)
|
return s.ensureService(c, project, service)
|
||||||
})
|
})
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if detach {
|
||||||
|
err = inDependencyOrder(ctx, project, func(c context.Context, service types.ServiceConfig) error {
|
||||||
|
return s.startService(ctx, project, service)
|
||||||
|
})
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if detach {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
progress.ContextWriter(ctx).Stop()
|
||||||
|
return s.attach(ctx, project, w)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *composeService) attach(ctx context.Context, project *types.Project, w io.Writer) error {
|
||||||
|
consumer := formatter.NewLogConsumer(ctx, w)
|
||||||
|
containers, err := s.apiClient.ContainerList(ctx, moby.ContainerListOptions{
|
||||||
|
Filters: filters.NewArgs(
|
||||||
|
projectFilter(project.Name),
|
||||||
|
),
|
||||||
|
All: true,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
var names []string
|
||||||
|
for _, c := range containers {
|
||||||
|
names = append(names, getContainerName(c))
|
||||||
|
}
|
||||||
|
fmt.Printf("Attaching to %s\n", strings.Join(names, ", "))
|
||||||
|
|
||||||
|
eg, ctx := errgroup.WithContext(ctx)
|
||||||
|
for _, c := range containers {
|
||||||
|
container := c
|
||||||
|
|
||||||
|
eg.Go(func() error {
|
||||||
|
return s.attachContainer(ctx, container, project, consumer)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
eg.Go(func() error {
|
||||||
|
<-ctx.Done()
|
||||||
|
fmt.Println("Gracefully stopping...")
|
||||||
|
ctx = context.Background()
|
||||||
|
_, err = progress.Run(ctx, func(ctx context.Context) (string, error) {
|
||||||
|
return "", s.Down(ctx, project.Name)
|
||||||
|
})
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
|
||||||
|
return eg.Wait()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *composeService) attachContainer(ctx context.Context, container moby.Container, project *types.Project, consumer formatter.LogConsumer) error {
|
||||||
|
serviceName := container.Labels[serviceLabel]
|
||||||
|
service, err := project.GetService(serviceName)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
reader, err := s.getContainerStdout(ctx, container)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
w := consumer.GetWriter(serviceName, container.ID)
|
||||||
|
if service.Tty {
|
||||||
|
_, err = io.Copy(w, reader)
|
||||||
|
} else {
|
||||||
|
_, err = stdcopy.StdCopy(w, w, reader)
|
||||||
|
}
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *composeService) getContainerStdout(ctx context.Context, container moby.Container) (io.Reader, error) {
|
||||||
|
var reader io.Reader
|
||||||
|
if container.State == containerRunning {
|
||||||
|
logs, err := s.apiClient.ContainerLogs(ctx, container.ID, moby.ContainerLogsOptions{
|
||||||
|
ShowStdout: true,
|
||||||
|
ShowStderr: true,
|
||||||
|
Follow: true,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
reader = logs
|
||||||
|
} else {
|
||||||
|
cnx, err := s.apiClient.ContainerAttach(ctx, container.ID, moby.ContainerAttachOptions{
|
||||||
|
Stream: true,
|
||||||
|
Stdin: true,
|
||||||
|
Stdout: true,
|
||||||
|
Stderr: true,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
reader = cnx.Reader
|
||||||
|
|
||||||
|
err = s.apiClient.ContainerStart(ctx, container.ID, moby.ContainerStartOptions{})
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return reader, nil
|
||||||
|
}
|
||||||
|
|
||||||
func getContainerName(c moby.Container) string {
|
func getContainerName(c moby.Container) string {
|
||||||
// Names return container canonical name /foo + link aliases /linked_by/foo
|
// Names return container canonical name /foo + link aliases /linked_by/foo
|
||||||
for _, name := range c.Names {
|
for _, name := range c.Names {
|
||||||
@ -367,6 +476,7 @@ func (s *composeService) Down(ctx context.Context, projectName string) error {
|
|||||||
Filters: filters.NewArgs(
|
Filters: filters.NewArgs(
|
||||||
projectFilter(projectName),
|
projectFilter(projectName),
|
||||||
),
|
),
|
||||||
|
All: true,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@ -467,7 +577,7 @@ func (s *composeService) Logs(ctx context.Context, projectName string, w io.Writ
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
consumer := formatter.NewLogConsumer(w)
|
consumer := formatter.NewLogConsumer(ctx, w)
|
||||||
eg, ctx := errgroup.WithContext(ctx)
|
eg, ctx := errgroup.WithContext(ctx)
|
||||||
for _, c := range list {
|
for _, c := range list {
|
||||||
service := c.Labels[serviceLabel]
|
service := c.Labels[serviceLabel]
|
||||||
@ -521,7 +631,7 @@ func containersToServiceStatus(containers []moby.Container) ([]compose.ServiceSt
|
|||||||
containers := containersByLabel[service]
|
containers := containersByLabel[service]
|
||||||
runnningContainers := []moby.Container{}
|
runnningContainers := []moby.Container{}
|
||||||
for _, container := range containers {
|
for _, container := range containers {
|
||||||
if container.State == "running" {
|
if container.State == containerRunning {
|
||||||
runnningContainers = append(runnningContainers, container)
|
runnningContainers = append(runnningContainers, container)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
29
local/container.go
Normal file
29
local/container.go
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
// +build local
|
||||||
|
|
||||||
|
/*
|
||||||
|
Copyright 2020 Docker Compose CLI authors
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package local
|
||||||
|
|
||||||
|
const (
|
||||||
|
containerCreated = "created"
|
||||||
|
containerRestarting = "restarting"
|
||||||
|
containerRunning = "running"
|
||||||
|
containerRemoving = "removing" //nolint
|
||||||
|
containerPaused = "paused" //nolint
|
||||||
|
containerExited = "exited" //nolint
|
||||||
|
containerDead = "dead" //nolint
|
||||||
|
)
|
@ -39,16 +39,12 @@ const (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func (s *composeService) ensureService(ctx context.Context, project *types.Project, service types.ServiceConfig) error {
|
func (s *composeService) ensureService(ctx context.Context, project *types.Project, service types.ServiceConfig) error {
|
||||||
err := s.waitDependencies(ctx, project, service)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
actual, err := s.apiClient.ContainerList(ctx, moby.ContainerListOptions{
|
actual, err := s.apiClient.ContainerList(ctx, moby.ContainerListOptions{
|
||||||
Filters: filters.NewArgs(
|
Filters: filters.NewArgs(
|
||||||
filters.Arg("label", fmt.Sprintf("%s=%s", projectLabel, project.Name)),
|
projectFilter(project.Name),
|
||||||
filters.Arg("label", fmt.Sprintf("%s=%s", serviceLabel, service.Name)),
|
serviceFilter(service.Name),
|
||||||
),
|
),
|
||||||
|
All: true,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@ -93,6 +89,8 @@ func (s *composeService) ensureService(ctx context.Context, project *types.Proje
|
|||||||
|
|
||||||
for _, container := range actual {
|
for _, container := range actual {
|
||||||
container := container
|
container := container
|
||||||
|
name := getContainerName(container)
|
||||||
|
|
||||||
diverged := container.Labels[configHashLabel] != expected
|
diverged := container.Labels[configHashLabel] != expected
|
||||||
if diverged || service.Extensions[extLifecycle] == forceRecreate {
|
if diverged || service.Extensions[extLifecycle] == forceRecreate {
|
||||||
eg.Go(func() error {
|
eg.Go(func() error {
|
||||||
@ -101,14 +99,18 @@ func (s *composeService) ensureService(ctx context.Context, project *types.Proje
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
if container.State == "running" {
|
w := progress.ContextWriter(ctx)
|
||||||
// already running, skip
|
switch container.State {
|
||||||
continue
|
case containerRunning:
|
||||||
|
w.Event(progress.RunningEvent(name))
|
||||||
|
case containerCreated:
|
||||||
|
case containerRestarting:
|
||||||
|
w.Event(progress.CreatedEvent(name))
|
||||||
|
default:
|
||||||
|
eg.Go(func() error {
|
||||||
|
return s.restartContainer(ctx, container)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
eg.Go(func() error {
|
|
||||||
return s.restartContainer(ctx, service, container)
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
return eg.Wait()
|
return eg.Wait()
|
||||||
}
|
}
|
||||||
@ -163,21 +165,19 @@ func getScale(config types.ServiceConfig) int {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (s *composeService) createContainer(ctx context.Context, project *types.Project, service types.ServiceConfig, name string, number int) error {
|
func (s *composeService) createContainer(ctx context.Context, project *types.Project, service types.ServiceConfig, name string, number int) error {
|
||||||
eventName := fmt.Sprintf("Service %q", service.Name)
|
|
||||||
w := progress.ContextWriter(ctx)
|
w := progress.ContextWriter(ctx)
|
||||||
w.Event(progress.CreatingEvent(eventName))
|
w.Event(progress.CreatingEvent(name))
|
||||||
err := s.runContainer(ctx, project, service, name, number, nil)
|
err := s.runContainer(ctx, project, service, name, number, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
w.Event(progress.CreatedEvent(eventName))
|
w.Event(progress.CreatedEvent(name))
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *composeService) recreateContainer(ctx context.Context, project *types.Project, service types.ServiceConfig, container moby.Container) error {
|
func (s *composeService) recreateContainer(ctx context.Context, project *types.Project, service types.ServiceConfig, container moby.Container) error {
|
||||||
w := progress.ContextWriter(ctx)
|
w := progress.ContextWriter(ctx)
|
||||||
eventName := fmt.Sprintf("Service %q", service.Name)
|
w.Event(progress.NewEvent(getContainerName(container), progress.Working, "Recreate"))
|
||||||
w.Event(progress.NewEvent(eventName, progress.Working, "Recreate"))
|
|
||||||
err := s.apiClient.ContainerStop(ctx, container.ID, nil)
|
err := s.apiClient.ContainerStop(ctx, container.ID, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@ -200,7 +200,7 @@ func (s *composeService) recreateContainer(ctx context.Context, project *types.P
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
w.Event(progress.NewEvent(eventName, progress.Done, "Recreated"))
|
w.Event(progress.NewEvent(getContainerName(container), progress.Done, "Recreated"))
|
||||||
setDependentLifecycle(project, service.Name, forceRecreate)
|
setDependentLifecycle(project, service.Name, forceRecreate)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -218,15 +218,14 @@ func setDependentLifecycle(project *types.Project, service string, strategy stri
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *composeService) restartContainer(ctx context.Context, service types.ServiceConfig, container moby.Container) error {
|
func (s *composeService) restartContainer(ctx context.Context, container moby.Container) error {
|
||||||
w := progress.ContextWriter(ctx)
|
w := progress.ContextWriter(ctx)
|
||||||
eventName := fmt.Sprintf("Service %q", service.Name)
|
w.Event(progress.NewEvent(getContainerName(container), progress.Working, "Restart"))
|
||||||
w.Event(progress.NewEvent(eventName, progress.Working, "Restart"))
|
|
||||||
err := s.apiClient.ContainerStart(ctx, container.ID, moby.ContainerStartOptions{})
|
err := s.apiClient.ContainerStart(ctx, container.ID, moby.ContainerStartOptions{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
w.Event(progress.NewEvent(eventName, progress.Done, "Restarted"))
|
w.Event(progress.NewEvent(getContainerName(container), progress.Done, "Restarted"))
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -247,10 +246,6 @@ func (s *composeService) runContainer(ctx context.Context, project *types.Projec
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
err = s.apiClient.ContainerStart(ctx, id, moby.ContainerStartOptions{})
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -291,5 +286,38 @@ func (s *composeService) isServiceHealthy(ctx context.Context, project *types.Pr
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true, nil
|
return true, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *composeService) startService(ctx context.Context, project *types.Project, service types.ServiceConfig) error {
|
||||||
|
err := s.waitDependencies(ctx, project, service)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
containers, err := s.apiClient.ContainerList(ctx, moby.ContainerListOptions{
|
||||||
|
Filters: filters.NewArgs(
|
||||||
|
projectFilter(project.Name),
|
||||||
|
serviceFilter(service.Name),
|
||||||
|
),
|
||||||
|
All: true,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
eg, ctx := errgroup.WithContext(ctx)
|
||||||
|
for _, c := range containers {
|
||||||
|
container := c
|
||||||
|
if container.State == containerRunning {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
eg.Go(func() error {
|
||||||
|
w := progress.ContextWriter(ctx)
|
||||||
|
w.Event(progress.StartingEvent(getContainerName(container)))
|
||||||
|
err := s.apiClient.ContainerStart(ctx, container.ID, moby.ContainerStartOptions{})
|
||||||
|
if err == nil {
|
||||||
|
w.Event(progress.StartedEvent(getContainerName(container)))
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return eg.Wait()
|
||||||
}
|
}
|
||||||
|
@ -51,3 +51,7 @@ func serviceFilter(serviceName string) filters.KeyValuePair {
|
|||||||
func hasProjectLabelFilter() filters.KeyValuePair {
|
func hasProjectLabelFilter() filters.KeyValuePair {
|
||||||
return filters.Arg("label", projectLabel)
|
return filters.Arg("label", projectLabel)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func serviceFilter(serviceName string) filters.KeyValuePair {
|
||||||
|
return filters.Arg("label", fmt.Sprintf("%s=%s", serviceLabel, serviceName))
|
||||||
|
}
|
||||||
|
@ -58,6 +58,21 @@ func CreatingEvent(ID string) Event {
|
|||||||
return NewEvent(ID, Working, "Creating")
|
return NewEvent(ID, Working, "Creating")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// StartingEvent creates a new Starting in progress Event
|
||||||
|
func StartingEvent(ID string) Event {
|
||||||
|
return NewEvent(ID, Working, "Starting")
|
||||||
|
}
|
||||||
|
|
||||||
|
// StartedEvent creates a new Started in progress Event
|
||||||
|
func StartedEvent(ID string) Event {
|
||||||
|
return NewEvent(ID, Done, "Started")
|
||||||
|
}
|
||||||
|
|
||||||
|
// RunningEvent creates a new Running in progress Event
|
||||||
|
func RunningEvent(ID string) Event {
|
||||||
|
return NewEvent(ID, Done, "Running")
|
||||||
|
}
|
||||||
|
|
||||||
// CreatedEvent creates a new Created (done) Event
|
// CreatedEvent creates a new Created (done) Event
|
||||||
func CreatedEvent(ID string) Event {
|
func CreatedEvent(ID string) Event {
|
||||||
return NewEvent(ID, Done, "Created")
|
return NewEvent(ID, Done, "Created")
|
||||||
|
@ -30,7 +30,7 @@ func (p *proxy) Up(ctx context.Context, request *composev1.ComposeUpRequest) (*c
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return &composev1.ComposeUpResponse{ProjectName: project.Name}, Client(ctx).ComposeService().Up(ctx, project, true)
|
return &composev1.ComposeUpResponse{ProjectName: project.Name}, Client(ctx).ComposeService().Up(ctx, project, true, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *proxy) Down(ctx context.Context, request *composev1.ComposeDownRequest) (*composev1.ComposeDownResponse, error) {
|
func (p *proxy) Down(ctx context.Context, request *composev1.ComposeDownRequest) (*composev1.ComposeDownResponse, error) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user