refactor: use adapted upstream detach=false logic [ci skip]

See coop-cloud/organising#607.
This commit is contained in:
2024-07-02 12:54:48 +02:00
parent 2014cd6622
commit 9554ad40c8
10 changed files with 110 additions and 45 deletions

View File

@ -9,6 +9,8 @@ import (
"os/signal"
"time"
stdlibErr "errors"
"coopcloud.tech/abra/pkg/upstream/convert"
"github.com/docker/cli/cli/command/service/progress"
"github.com/docker/cli/cli/command/stack/formatter"
@ -129,7 +131,7 @@ func IsDeployed(ctx context.Context, cl *dockerClient.Client, stackName string)
func pruneServices(ctx context.Context, cl *dockerClient.Client, namespace convert.Namespace, services map[string]struct{}) {
oldServices, err := GetStackServices(ctx, cl, namespace.Name())
if err != nil {
logrus.Infof("Failed to list services: %s\n", err)
logrus.Infof("failed to list services: %s\n", err)
}
pruneServices := []swarm.Service{}
@ -161,7 +163,7 @@ func validateResolveImageFlag(opts *Deploy) error {
case ResolveImageAlways, ResolveImageChanged, ResolveImageNever:
return nil
default:
return errors.Errorf("Invalid option %s for flag --resolve-image", opts.ResolveImage)
return errors.Errorf("invalid option %s for flag --resolve-image", opts.ResolveImage)
}
}
@ -206,7 +208,16 @@ func deployCompose(ctx context.Context, cl *dockerClient.Client, opts Deploy, co
return err
}
return deployServices(ctx, cl, services, namespace, opts.SendRegistryAuth, opts.ResolveImage, appName, dontWait)
serviceIDs, err := deployServices(ctx, cl, services, namespace, opts.SendRegistryAuth, opts.ResolveImage, appName, dontWait)
if err != nil {
return err
}
logrus.Infof("waiting for %s to deploy... please hold 🤚", appName)
if err := waitOnServices(ctx, cl, serviceIDs, appName); err == nil {
logrus.Infof("Successfully deployed %s", appName)
}
return err
}
func getServicesDeclaredNetworks(serviceConfigs []composetypes.ServiceConfig) map[string]struct{} {
@ -276,7 +287,7 @@ func createConfigs(ctx context.Context, cl *dockerClient.Client, configs []swarm
}
case dockerClient.IsErrNotFound(err):
// config does not exist, then we create a new one.
logrus.Infof("Creating config %s\n", configSpec.Name)
logrus.Infof("creating config %s\n", configSpec.Name)
if _, err := cl.ConfigCreate(ctx, configSpec); err != nil {
return errors.Wrapf(err, "failed to create config %s", configSpec.Name)
}
@ -307,7 +318,7 @@ func createNetworks(ctx context.Context, cl *dockerClient.Client, namespace conv
createOpts.Driver = defaultNetworkDriver
}
logrus.Infof("Creating network %s\n", name)
logrus.Infof("creating network %s\n", name)
if _, err := cl.NetworkCreate(ctx, name, createOpts); err != nil {
return errors.Wrapf(err, "failed to create network %s", name)
}
@ -323,10 +334,10 @@ func deployServices(
sendAuth bool,
resolveImage string,
appName string,
dontWait bool) error {
dontWait bool) ([]string, error) {
existingServices, err := GetStackServices(ctx, cl, namespace.Name())
if err != nil {
return err
return nil, err
}
existingServiceMap := make(map[string]swarm.Service)
@ -334,7 +345,8 @@ func deployServices(
existingServiceMap[service.Spec.Name] = service
}
serviceIDs := make(map[string]string)
var serviceIDs []string
for internalName, serviceSpec := range services {
var (
name = namespace.Scope(internalName)
@ -378,16 +390,16 @@ func deployServices(
response, err := cl.ServiceUpdate(ctx, service.ID, service.Version, serviceSpec, updateOpts)
if err != nil {
return errors.Wrapf(err, "failed to update service %s", name)
return nil, errors.Wrapf(err, "failed to update service %s", name)
}
serviceIDs[service.ID] = name
for _, warning := range response.Warnings {
logrus.Warn(warning)
}
serviceIDs = append(serviceIDs, service.ID)
} else {
logrus.Infof("Creating service %s\n", name)
logrus.Infof("creating service %s\n", name)
createOpts := types.ServiceCreateOptions{EncodedRegistryAuth: encodedAuth}
@ -398,43 +410,19 @@ func deployServices(
serviceCreateResponse, err := cl.ServiceCreate(ctx, serviceSpec, createOpts)
if err != nil {
return errors.Wrapf(err, "failed to create service %s", name)
return nil, errors.Wrapf(err, "failed to create service %s", name)
}
serviceIDs[serviceCreateResponse.ID] = name
serviceIDs = append(serviceIDs, serviceCreateResponse.ID)
}
}
var serviceNames []string
for _, serviceName := range serviceIDs {
serviceNames = append(serviceNames, serviceName)
}
if dontWait {
logrus.Warn("skipping converge logic checks")
return nil
return nil, nil
}
logrus.Infof("Waiting for %s to deploy... please hold 🤚", appName)
ch := make(chan error, len(serviceIDs))
for serviceID, serviceName := range serviceIDs {
logrus.Debugf("waiting on %s to converge", serviceName)
go func(sID, sName, aName string) {
ch <- WaitOnService(ctx, cl, sID, aName)
}(serviceID, serviceName, appName)
}
for _, serviceID := range serviceIDs {
err := <-ch
if err != nil {
return err
}
logrus.Debugf("assuming %s converged successfully", serviceID)
}
logrus.Infof("Successfully deployed %s", appName)
return nil
return serviceIDs, nil
}
func getStackNetworks(ctx context.Context, dockerclient client.APIClient, namespace string) ([]types.NetworkResource, error) {
@ -449,6 +437,22 @@ func getStackConfigs(ctx context.Context, dockerclient client.APIClient, namespa
return dockerclient.ConfigList(ctx, types.ConfigListOptions{Filters: getStackFilter(namespace)})
}
func waitOnServices(ctx context.Context, cl *dockerClient.Client, serviceIDs []string, appName string) error {
var errs []error
for _, serviceID := range serviceIDs {
if err := WaitOnService(ctx, cl, serviceID, appName); err != nil {
errs = append(errs, fmt.Errorf("%s: %w", serviceID, err))
}
}
if len(errs) > 0 {
return stdlibErr.Join(errs...)
}
return nil
}
// https://github.com/docker/cli/blob/master/cli/command/service/helpers.go
// https://github.com/docker/cli/blob/master/cli/command/service/progress/progress.go
func WaitOnService(ctx context.Context, cl *dockerClient.Client, serviceID, appName string) error {