mirror of https://github.com/docker/compose.git
Merge pull request #983 from docker/refactor_progress_events
Refactor progress events
This commit is contained in:
commit
96d21fe448
25
aci/aci.go
25
aci/aci.go
|
@ -107,11 +107,7 @@ func createOrUpdateACIContainers(ctx context.Context, aciContext store.AciContex
|
||||||
}
|
}
|
||||||
|
|
||||||
groupDisplay := "Group " + *groupDefinition.Name
|
groupDisplay := "Group " + *groupDefinition.Name
|
||||||
w.Event(progress.Event{
|
w.Event(progress.CreatingEvent(groupDisplay))
|
||||||
ID: groupDisplay,
|
|
||||||
Status: progress.Working,
|
|
||||||
StatusText: "Waiting",
|
|
||||||
})
|
|
||||||
|
|
||||||
future, err := containerGroupsClient.CreateOrUpdate(
|
future, err := containerGroupsClient.CreateOrUpdate(
|
||||||
ctx,
|
ctx,
|
||||||
|
@ -120,21 +116,14 @@ func createOrUpdateACIContainers(ctx context.Context, aciContext store.AciContex
|
||||||
groupDefinition,
|
groupDefinition,
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
w.Event(progress.ErrorEvent(groupDisplay))
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
w.Event(progress.Event{
|
w.Event(progress.CreatedEvent(groupDisplay))
|
||||||
ID: groupDisplay,
|
|
||||||
Status: progress.Done,
|
|
||||||
StatusText: "Created",
|
|
||||||
})
|
|
||||||
for _, c := range *groupDefinition.Containers {
|
for _, c := range *groupDefinition.Containers {
|
||||||
if c.Name != nil && *c.Name != convert.ComposeDNSSidecarName {
|
if c.Name != nil && *c.Name != convert.ComposeDNSSidecarName {
|
||||||
w.Event(progress.Event{
|
w.Event(progress.CreatingEvent(*c.Name))
|
||||||
ID: *c.Name,
|
|
||||||
Status: progress.Working,
|
|
||||||
StatusText: "Waiting",
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -145,11 +134,7 @@ func createOrUpdateACIContainers(ctx context.Context, aciContext store.AciContex
|
||||||
|
|
||||||
for _, c := range *groupDefinition.Containers {
|
for _, c := range *groupDefinition.Containers {
|
||||||
if c.Name != nil && *c.Name != convert.ComposeDNSSidecarName {
|
if c.Name != nil && *c.Name != convert.ComposeDNSSidecarName {
|
||||||
w.Event(progress.Event{
|
w.Event(progress.CreatedEvent(*c.Name))
|
||||||
ID: *c.Name,
|
|
||||||
Status: progress.Done,
|
|
||||||
StatusText: "Done",
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -84,15 +84,17 @@ func (cs *aciVolumeService) Create(ctx context.Context, name string, options int
|
||||||
return volumes.Volume{}, errors.New("could not read Azure VolumeCreateOptions struct from generic parameter")
|
return volumes.Volume{}, errors.New("could not read Azure VolumeCreateOptions struct from generic parameter")
|
||||||
}
|
}
|
||||||
w := progress.ContextWriter(ctx)
|
w := progress.ContextWriter(ctx)
|
||||||
w.Event(event(opts.Account, progress.Working, "Validating"))
|
w.Event(progress.NewEvent(opts.Account, progress.Working, "Validating"))
|
||||||
accountClient, err := login.NewStorageAccountsClient(cs.aciContext.SubscriptionID)
|
accountClient, err := login.NewStorageAccountsClient(cs.aciContext.SubscriptionID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
w.Event(progress.ErrorEvent(opts.Account))
|
||||||
return volumes.Volume{}, err
|
return volumes.Volume{}, err
|
||||||
}
|
}
|
||||||
account, err := accountClient.GetProperties(ctx, cs.aciContext.ResourceGroup, opts.Account, "")
|
account, err := accountClient.GetProperties(ctx, cs.aciContext.ResourceGroup, opts.Account, "")
|
||||||
if err == nil {
|
if err == nil {
|
||||||
w.Event(event(opts.Account, progress.Done, "Use existing"))
|
w.Event(progress.NewEvent(opts.Account, progress.Done, "Use existing"))
|
||||||
} else if !account.HasHTTPStatus(http.StatusNotFound) {
|
} else if !account.HasHTTPStatus(http.StatusNotFound) {
|
||||||
|
w.Event(progress.ErrorEvent(opts.Account))
|
||||||
return volumes.Volume{}, err
|
return volumes.Volume{}, err
|
||||||
} else {
|
} else {
|
||||||
result, err := accountClient.CheckNameAvailability(ctx, storage.AccountCheckNameAvailabilityParameters{
|
result, err := accountClient.CheckNameAvailability(ctx, storage.AccountCheckNameAvailabilityParameters{
|
||||||
|
@ -100,32 +102,34 @@ func (cs *aciVolumeService) Create(ctx context.Context, name string, options int
|
||||||
Type: to.StringPtr("Microsoft.Storage/storageAccounts"),
|
Type: to.StringPtr("Microsoft.Storage/storageAccounts"),
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
w.Event(progress.ErrorEvent(opts.Account))
|
||||||
return volumes.Volume{}, err
|
return volumes.Volume{}, err
|
||||||
}
|
}
|
||||||
if !*result.NameAvailable {
|
if !*result.NameAvailable {
|
||||||
|
w.Event(progress.ErrorEvent(opts.Account))
|
||||||
return volumes.Volume{}, errors.New("error: " + *result.Message)
|
return volumes.Volume{}, errors.New("error: " + *result.Message)
|
||||||
}
|
}
|
||||||
parameters := defaultStorageAccountParams(cs.aciContext)
|
parameters := defaultStorageAccountParams(cs.aciContext)
|
||||||
|
|
||||||
w.Event(event(opts.Account, progress.Working, "Creating"))
|
w.Event(progress.CreatingEvent(opts.Account))
|
||||||
|
|
||||||
future, err := accountClient.Create(ctx, cs.aciContext.ResourceGroup, opts.Account, parameters)
|
future, err := accountClient.Create(ctx, cs.aciContext.ResourceGroup, opts.Account, parameters)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
w.Event(errorEvent(opts.Account))
|
w.Event(progress.ErrorEvent(opts.Account))
|
||||||
return volumes.Volume{}, err
|
return volumes.Volume{}, err
|
||||||
}
|
}
|
||||||
if err := future.WaitForCompletionRef(ctx, accountClient.Client); err != nil {
|
if err := future.WaitForCompletionRef(ctx, accountClient.Client); err != nil {
|
||||||
w.Event(errorEvent(opts.Account))
|
w.Event(progress.ErrorEvent(opts.Account))
|
||||||
return volumes.Volume{}, err
|
return volumes.Volume{}, err
|
||||||
}
|
}
|
||||||
account, err = future.Result(accountClient)
|
account, err = future.Result(accountClient)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
w.Event(errorEvent(opts.Account))
|
w.Event(progress.ErrorEvent(opts.Account))
|
||||||
return volumes.Volume{}, err
|
return volumes.Volume{}, err
|
||||||
}
|
}
|
||||||
w.Event(event(opts.Account, progress.Done, "Created"))
|
w.Event(progress.CreatedEvent(opts.Account))
|
||||||
}
|
}
|
||||||
w.Event(event(name, progress.Working, "Creating"))
|
w.Event(progress.CreatingEvent(name))
|
||||||
fileShareClient, err := login.NewFileShareClient(cs.aciContext.SubscriptionID)
|
fileShareClient, err := login.NewFileShareClient(cs.aciContext.SubscriptionID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return volumes.Volume{}, err
|
return volumes.Volume{}, err
|
||||||
|
@ -133,38 +137,22 @@ func (cs *aciVolumeService) Create(ctx context.Context, name string, options int
|
||||||
|
|
||||||
fileShare, err := fileShareClient.Get(ctx, cs.aciContext.ResourceGroup, *account.Name, name, "")
|
fileShare, err := fileShareClient.Get(ctx, cs.aciContext.ResourceGroup, *account.Name, name, "")
|
||||||
if err == nil {
|
if err == nil {
|
||||||
w.Event(errorEvent(name))
|
w.Event(progress.ErrorEvent(name))
|
||||||
return volumes.Volume{}, errors.Wrapf(errdefs.ErrAlreadyExists, "Azure fileshare %q already exists", name)
|
return volumes.Volume{}, errors.Wrapf(errdefs.ErrAlreadyExists, "Azure fileshare %q already exists", name)
|
||||||
}
|
}
|
||||||
if !fileShare.HasHTTPStatus(http.StatusNotFound) {
|
if !fileShare.HasHTTPStatus(http.StatusNotFound) {
|
||||||
w.Event(errorEvent(name))
|
w.Event(progress.ErrorEvent(name))
|
||||||
return volumes.Volume{}, err
|
return volumes.Volume{}, err
|
||||||
}
|
}
|
||||||
fileShare, err = fileShareClient.Create(ctx, cs.aciContext.ResourceGroup, *account.Name, name, storage.FileShare{})
|
fileShare, err = fileShareClient.Create(ctx, cs.aciContext.ResourceGroup, *account.Name, name, storage.FileShare{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
w.Event(errorEvent(name))
|
w.Event(progress.ErrorEvent(name))
|
||||||
return volumes.Volume{}, err
|
return volumes.Volume{}, err
|
||||||
}
|
}
|
||||||
w.Event(event(name, progress.Done, "Created"))
|
w.Event(progress.CreatedEvent(name))
|
||||||
return toVolume(*account.Name, *fileShare.Name), nil
|
return toVolume(*account.Name, *fileShare.Name), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func event(resource string, status progress.EventStatus, text string) progress.Event {
|
|
||||||
return progress.Event{
|
|
||||||
ID: resource,
|
|
||||||
Status: status,
|
|
||||||
StatusText: text,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func errorEvent(resource string) progress.Event {
|
|
||||||
return progress.Event{
|
|
||||||
ID: resource,
|
|
||||||
Status: progress.Error,
|
|
||||||
StatusText: "Error",
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func checkVolumeUsage(ctx context.Context, aciContext store.AciContext, id string) error {
|
func checkVolumeUsage(ctx context.Context, aciContext store.AciContext, id string) error {
|
||||||
containerGroups, err := getACIContainerGroups(ctx, aciContext.SubscriptionID, aciContext.ResourceGroup)
|
containerGroups, err := getACIContainerGroups(ctx, aciContext.SubscriptionID, aciContext.ResourceGroup)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
14
ecs/down.go
14
ecs/down.go
|
@ -65,11 +65,13 @@ func (b *ecsAPIService) previousStackEvents(ctx context.Context, project string)
|
||||||
func doDelete(ctx context.Context, delete func(ctx context.Context, arn string) error) func(r stackResource) error {
|
func doDelete(ctx context.Context, delete func(ctx context.Context, arn string) error) func(r stackResource) error {
|
||||||
return func(r stackResource) error {
|
return func(r stackResource) error {
|
||||||
w := progress.ContextWriter(ctx)
|
w := progress.ContextWriter(ctx)
|
||||||
w.Event(progress.Event{
|
w.Event(progress.RemovingEvent(r.LogicalID))
|
||||||
ID: r.LogicalID,
|
err := delete(ctx, r.ARN)
|
||||||
Status: progress.Working,
|
if err != nil {
|
||||||
StatusText: "DeleteInProgress",
|
w.Event(progress.ErrorEvent(r.LogicalID))
|
||||||
})
|
return err
|
||||||
return delete(ctx, r.ARN)
|
}
|
||||||
|
w.Event(progress.RemovedEvent(r.LogicalID))
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
12
ecs/wait.go
12
ecs/wait.go
|
@ -101,11 +101,7 @@ func (b *ecsAPIService) WaitStackCompletion(ctx context.Context, name string, op
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
w.Event(progress.Event{
|
w.Event(progress.NewEvent(resource, progressStatus, fmt.Sprintf("%s %s", toCamelCase(status), reason)))
|
||||||
ID: resource,
|
|
||||||
Status: progressStatus,
|
|
||||||
StatusText: fmt.Sprintf("%s %s", toCamelCase(status), reason),
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
if operation != stackCreate || stackErr != nil {
|
if operation != stackCreate || stackErr != nil {
|
||||||
continue
|
continue
|
||||||
|
@ -116,11 +112,7 @@ func (b *ecsAPIService) WaitStackCompletion(ctx context.Context, name string, op
|
||||||
}
|
}
|
||||||
stackErr = err
|
stackErr = err
|
||||||
operation = stackDelete
|
operation = stackDelete
|
||||||
w.Event(progress.Event{
|
w.Event(progress.ErrorMessageEvent(name, err.Error()))
|
||||||
ID: name,
|
|
||||||
Status: progress.Error,
|
|
||||||
StatusText: err.Error(),
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -117,29 +117,19 @@ func (s *composeService) Down(ctx context.Context, projectName string) error {
|
||||||
for _, c := range list {
|
for _, c := range list {
|
||||||
container := c
|
container := c
|
||||||
eg.Go(func() error {
|
eg.Go(func() error {
|
||||||
w.Event(progress.Event{
|
w.Event(progress.NewEvent(getContainerName(container), progress.Working, "Stopping"))
|
||||||
ID: getContainerName(container),
|
|
||||||
Text: "Stopping",
|
|
||||||
Status: progress.Working,
|
|
||||||
})
|
|
||||||
err := s.apiClient.ContainerStop(ctx, container.ID, nil)
|
err := s.apiClient.ContainerStop(ctx, container.ID, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
w.Event(progress.ErrorMessageEvent(getContainerName(container), "Error while Stopping"))
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
w.Event(progress.Event{
|
w.Event(progress.RemovingEvent(getContainerName(container)))
|
||||||
ID: getContainerName(container),
|
|
||||||
Text: "Removing",
|
|
||||||
Status: progress.Working,
|
|
||||||
})
|
|
||||||
err = s.apiClient.ContainerRemove(ctx, container.ID, moby.ContainerRemoveOptions{})
|
err = s.apiClient.ContainerRemove(ctx, container.ID, moby.ContainerRemoveOptions{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
w.Event(progress.ErrorMessageEvent(getContainerName(container), "Error while Removing"))
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
w.Event(progress.Event{
|
w.Event(progress.RemovedEvent(getContainerName(container)))
|
||||||
ID: getContainerName(container),
|
|
||||||
Text: "Removed",
|
|
||||||
Status: progress.Done,
|
|
||||||
})
|
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -591,20 +581,14 @@ func (s *composeService) ensureNetwork(ctx context.Context, n types.NetworkConfi
|
||||||
}
|
}
|
||||||
createOpts.IPAM.Config = append(createOpts.IPAM.Config, config)
|
createOpts.IPAM.Config = append(createOpts.IPAM.Config, config)
|
||||||
}
|
}
|
||||||
|
networkEventName := fmt.Sprintf("Network %q", n.Name)
|
||||||
w := progress.ContextWriter(ctx)
|
w := progress.ContextWriter(ctx)
|
||||||
w.Event(progress.Event{
|
w.Event(progress.CreatingEvent(networkEventName))
|
||||||
ID: fmt.Sprintf("Network %q", n.Name),
|
|
||||||
Status: progress.Working,
|
|
||||||
StatusText: "Create",
|
|
||||||
})
|
|
||||||
if _, err := s.apiClient.NetworkCreate(ctx, n.Name, createOpts); err != nil {
|
if _, err := s.apiClient.NetworkCreate(ctx, n.Name, createOpts); err != nil {
|
||||||
|
w.Event(progress.ErrorEvent(networkEventName))
|
||||||
return errors.Wrapf(err, "failed to create network %s", n.Name)
|
return errors.Wrapf(err, "failed to create network %s", n.Name)
|
||||||
}
|
}
|
||||||
w.Event(progress.Event{
|
w.Event(progress.CreatedEvent(networkEventName))
|
||||||
ID: fmt.Sprintf("Network %q", n.Name),
|
|
||||||
Status: progress.Done,
|
|
||||||
StatusText: "Created",
|
|
||||||
})
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
return err
|
return err
|
||||||
|
@ -614,27 +598,15 @@ func (s *composeService) ensureNetwork(ctx context.Context, n types.NetworkConfi
|
||||||
|
|
||||||
func (s *composeService) ensureNetworkDown(ctx context.Context, networkID string, networkName string) error {
|
func (s *composeService) ensureNetworkDown(ctx context.Context, networkID string, networkName string) error {
|
||||||
w := progress.ContextWriter(ctx)
|
w := progress.ContextWriter(ctx)
|
||||||
w.Event(progress.Event{
|
eventName := fmt.Sprintf("Network %q", networkName)
|
||||||
ID: fmt.Sprintf("Network %q", networkName),
|
w.Event(progress.RemovingEvent(eventName))
|
||||||
Status: progress.Working,
|
|
||||||
StatusText: "Delete",
|
|
||||||
})
|
|
||||||
|
|
||||||
if err := s.apiClient.NetworkRemove(ctx, networkID); err != nil {
|
if err := s.apiClient.NetworkRemove(ctx, networkID); err != nil {
|
||||||
msg := fmt.Sprintf("failed to create network %s", networkID)
|
w.Event(progress.ErrorEvent(eventName))
|
||||||
w.Event(progress.Event{
|
return errors.Wrapf(err, fmt.Sprintf("failed to create network %s", networkID))
|
||||||
ID: fmt.Sprintf("Network %q", networkName),
|
|
||||||
Status: progress.Error,
|
|
||||||
StatusText: "Error: " + msg,
|
|
||||||
})
|
|
||||||
return errors.Wrapf(err, msg)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
w.Event(progress.Event{
|
w.Event(progress.RemovedEvent(eventName))
|
||||||
ID: fmt.Sprintf("Network %q", networkName),
|
|
||||||
Status: progress.Done,
|
|
||||||
StatusText: "Deleted",
|
|
||||||
})
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -643,12 +615,9 @@ func (s *composeService) ensureVolume(ctx context.Context, volume types.VolumeCo
|
||||||
_, err := s.apiClient.VolumeInspect(ctx, volume.Name)
|
_, err := s.apiClient.VolumeInspect(ctx, volume.Name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if errdefs.IsNotFound(err) {
|
if errdefs.IsNotFound(err) {
|
||||||
|
eventName := fmt.Sprintf("Volume %q", volume.Name)
|
||||||
w := progress.ContextWriter(ctx)
|
w := progress.ContextWriter(ctx)
|
||||||
w.Event(progress.Event{
|
w.Event(progress.CreatingEvent(eventName))
|
||||||
ID: fmt.Sprintf("Volume %q", volume.Name),
|
|
||||||
Status: progress.Working,
|
|
||||||
StatusText: "Create",
|
|
||||||
})
|
|
||||||
// TODO we miss support for driver_opts and labels
|
// TODO we miss support for driver_opts and labels
|
||||||
_, err := s.apiClient.VolumeCreate(ctx, mobyvolume.VolumeCreateBody{
|
_, err := s.apiClient.VolumeCreate(ctx, mobyvolume.VolumeCreateBody{
|
||||||
Labels: volume.Labels,
|
Labels: volume.Labels,
|
||||||
|
@ -656,14 +625,11 @@ func (s *composeService) ensureVolume(ctx context.Context, volume types.VolumeCo
|
||||||
Driver: volume.Driver,
|
Driver: volume.Driver,
|
||||||
DriverOpts: volume.DriverOpts,
|
DriverOpts: volume.DriverOpts,
|
||||||
})
|
})
|
||||||
w.Event(progress.Event{
|
|
||||||
ID: fmt.Sprintf("Volume %q", volume.Name),
|
|
||||||
Status: progress.Done,
|
|
||||||
StatusText: "Created",
|
|
||||||
})
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
w.Event(progress.ErrorEvent(eventName))
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
w.Event(progress.CreatedEvent(eventName))
|
||||||
}
|
}
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
@ -163,31 +163,21 @@ 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.Event{
|
w.Event(progress.CreatingEvent(eventName))
|
||||||
ID: fmt.Sprintf("Service %q", service.Name),
|
|
||||||
Status: progress.Working,
|
|
||||||
StatusText: "Create",
|
|
||||||
})
|
|
||||||
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.Event{
|
w.Event(progress.CreatedEvent(eventName))
|
||||||
ID: fmt.Sprintf("Service %q", service.Name),
|
|
||||||
Status: progress.Done,
|
|
||||||
StatusText: "Created",
|
|
||||||
})
|
|
||||||
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)
|
||||||
w.Event(progress.Event{
|
eventName := fmt.Sprintf("Service %q", service.Name)
|
||||||
ID: fmt.Sprintf("Service %q", service.Name),
|
w.Event(progress.NewEvent(eventName, progress.Working, "Recreate"))
|
||||||
Status: progress.Working,
|
|
||||||
StatusText: "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
|
||||||
|
@ -210,11 +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.Event{
|
w.Event(progress.NewEvent(eventName, progress.Done, "Recreated"))
|
||||||
ID: fmt.Sprintf("Service %q", service.Name),
|
|
||||||
Status: progress.Done,
|
|
||||||
StatusText: "Recreated",
|
|
||||||
})
|
|
||||||
setDependentLifecycle(project, service.Name, forceRecreate)
|
setDependentLifecycle(project, service.Name, forceRecreate)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -234,20 +220,13 @@ 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, service types.ServiceConfig, container moby.Container) error {
|
||||||
w := progress.ContextWriter(ctx)
|
w := progress.ContextWriter(ctx)
|
||||||
w.Event(progress.Event{
|
eventName := fmt.Sprintf("Service %q", service.Name)
|
||||||
ID: fmt.Sprintf("Service %q", service.Name),
|
w.Event(progress.NewEvent(eventName, progress.Working, "Restart"))
|
||||||
Status: progress.Working,
|
|
||||||
StatusText: "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.Event{
|
w.Event(progress.NewEvent(eventName, progress.Done, "Restarted"))
|
||||||
ID: fmt.Sprintf("Service %q", service.Name),
|
|
||||||
Status: progress.Done,
|
|
||||||
StatusText: "Restarted",
|
|
||||||
})
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,87 @@
|
||||||
|
/*
|
||||||
|
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 progress
|
||||||
|
|
||||||
|
import "time"
|
||||||
|
|
||||||
|
// EventStatus indicates the status of an action
|
||||||
|
type EventStatus int
|
||||||
|
|
||||||
|
const (
|
||||||
|
// Working means that the current task is working
|
||||||
|
Working EventStatus = iota
|
||||||
|
// Done means that the current task is done
|
||||||
|
Done
|
||||||
|
// Error means that the current task has errored
|
||||||
|
Error
|
||||||
|
)
|
||||||
|
|
||||||
|
// Event represents a progress event.
|
||||||
|
type Event struct {
|
||||||
|
ID string
|
||||||
|
Text string
|
||||||
|
Status EventStatus
|
||||||
|
StatusText string
|
||||||
|
|
||||||
|
startTime time.Time
|
||||||
|
endTime time.Time
|
||||||
|
spinner *spinner
|
||||||
|
}
|
||||||
|
|
||||||
|
// ErrorMessageEvent creates a new Error Event with message
|
||||||
|
func ErrorMessageEvent(ID string, msg string) Event {
|
||||||
|
return NewEvent(ID, Error, msg)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ErrorEvent creates a new Error Event
|
||||||
|
func ErrorEvent(ID string) Event {
|
||||||
|
return NewEvent(ID, Error, "Error")
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreatingEvent creates a new Create in progress Event
|
||||||
|
func CreatingEvent(ID string) Event {
|
||||||
|
return NewEvent(ID, Working, "Creating")
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreatedEvent creates a new Created (done) Event
|
||||||
|
func CreatedEvent(ID string) Event {
|
||||||
|
return NewEvent(ID, Done, "Created")
|
||||||
|
}
|
||||||
|
|
||||||
|
// RemovingEvent creates a new Removing in progress Event
|
||||||
|
func RemovingEvent(ID string) Event {
|
||||||
|
return NewEvent(ID, Working, "Removing")
|
||||||
|
}
|
||||||
|
|
||||||
|
// RemovedEvent creates a new removed (done) Event
|
||||||
|
func RemovedEvent(ID string) Event {
|
||||||
|
return NewEvent(ID, Done, "Removed")
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewEvent new event
|
||||||
|
func NewEvent(ID string, status EventStatus, statusText string) Event {
|
||||||
|
return Event{
|
||||||
|
ID: ID,
|
||||||
|
Status: status,
|
||||||
|
StatusText: statusText,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *Event) stop() {
|
||||||
|
e.endTime = time.Now()
|
||||||
|
e.spinner.Stop()
|
||||||
|
}
|
|
@ -20,42 +20,12 @@ import (
|
||||||
"context"
|
"context"
|
||||||
"os"
|
"os"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/containerd/console"
|
"github.com/containerd/console"
|
||||||
"github.com/moby/term"
|
"github.com/moby/term"
|
||||||
"golang.org/x/sync/errgroup"
|
"golang.org/x/sync/errgroup"
|
||||||
)
|
)
|
||||||
|
|
||||||
// EventStatus indicates the status of an action
|
|
||||||
type EventStatus int
|
|
||||||
|
|
||||||
const (
|
|
||||||
// Working means that the current task is working
|
|
||||||
Working EventStatus = iota
|
|
||||||
// Done means that the current task is done
|
|
||||||
Done
|
|
||||||
// Error means that the current task has errored
|
|
||||||
Error
|
|
||||||
)
|
|
||||||
|
|
||||||
// Event represents a progress event.
|
|
||||||
type Event struct {
|
|
||||||
ID string
|
|
||||||
Text string
|
|
||||||
Status EventStatus
|
|
||||||
StatusText string
|
|
||||||
|
|
||||||
startTime time.Time
|
|
||||||
endTime time.Time
|
|
||||||
spinner *spinner
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *Event) stop() {
|
|
||||||
e.endTime = time.Now()
|
|
||||||
e.spinner.Stop()
|
|
||||||
}
|
|
||||||
|
|
||||||
// Writer can write multiple progress events
|
// Writer can write multiple progress events
|
||||||
type Writer interface {
|
type Writer interface {
|
||||||
Start(context.Context) error
|
Start(context.Context) error
|
||||||
|
|
Loading…
Reference in New Issue