fix: use scale for restarting

The other approach wasn't working. Duplicating containers on restart.
You'd end up with 2 containers per restart...
This commit is contained in:
decentral1se 2022-01-01 17:22:35 +01:00
parent a556ca625b
commit abd094387f
Signed by: decentral1se
GPG Key ID: 03789458B3D0C410
2 changed files with 72 additions and 21 deletions

View File

@ -3,28 +3,28 @@ package app
import ( import (
"errors" "errors"
"fmt" "fmt"
"time"
"coopcloud.tech/abra/cli/internal" "coopcloud.tech/abra/cli/internal"
"coopcloud.tech/abra/pkg/autocomplete" "coopcloud.tech/abra/pkg/autocomplete"
"coopcloud.tech/abra/pkg/client" "coopcloud.tech/abra/pkg/client"
containerPkg "coopcloud.tech/abra/pkg/container" upstream "coopcloud.tech/abra/pkg/upstream/service"
"github.com/docker/docker/api/types/filters" stack "coopcloud.tech/abra/pkg/upstream/stack"
"github.com/sirupsen/logrus" "github.com/sirupsen/logrus"
"github.com/urfave/cli/v2" "github.com/urfave/cli/v2"
) )
var appRestartCommand = &cli.Command{ var appRestartCommand = &cli.Command{
Name: "restart", Name: "restart",
Usage: "Restart an app", Usage: "Restart an app",
Aliases: []string{"re"}, Aliases: []string{"re"},
ArgsUsage: "<service>", ArgsUsage: "<service>",
Description: `This command restarts a service within a deployed app.`, Description: `This command restarts a service within a deployed app.`,
BashComplete: autocomplete.AppNameComplete,
Action: func(c *cli.Context) error { Action: func(c *cli.Context) error {
app := internal.ValidateApp(c) app := internal.ValidateApp(c)
serviceName := c.Args().Get(1) serviceNameShort := c.Args().Get(1)
if serviceName == "" { if serviceNameShort == "" {
err := errors.New("missing service?") err := errors.New("missing service?")
internal.ShowSubcommandHelpAndError(c, err) internal.ShowSubcommandHelpAndError(c, err)
} }
@ -34,25 +34,32 @@ var appRestartCommand = &cli.Command{
logrus.Fatal(err) logrus.Fatal(err)
} }
serviceFilter := fmt.Sprintf("%s_%s", app.StackName(), serviceName) serviceName := fmt.Sprintf("%s_%s", app.StackName(), serviceNameShort)
filters := filters.NewArgs()
filters.Add("name", serviceFilter)
targetContainer, err := containerPkg.GetContainer(c.Context, cl, filters, true) logrus.Debugf("attempting to scale %s to 0 (restart logic)", serviceName)
if err != nil { if err := upstream.RunServiceScale(c.Context, cl, serviceName, 0); err != nil {
logrus.Fatal(err) logrus.Fatal(err)
} }
logrus.Debugf("attempting to restart %s", serviceFilter) if err := stack.WaitOnService(c.Context, cl, serviceName, app.Name); err != nil {
timeout := 30 * time.Second
if err := cl.ContainerRestart(c.Context, targetContainer.ID, &timeout); err != nil {
logrus.Fatal(err) logrus.Fatal(err)
} }
logrus.Infof("%s service restarted", serviceFilter) logrus.Debugf("%s has been scaled to 0 (restart logic)", serviceName)
logrus.Debugf("attempting to scale %s to 1 (restart logic)", serviceName)
if err := upstream.RunServiceScale(c.Context, cl, serviceName, 1); err != nil {
logrus.Fatal(err)
}
if err := stack.WaitOnService(c.Context, cl, serviceName, app.Name); err != nil {
logrus.Fatal(err)
}
logrus.Debugf("%s has been scaled to 1 (restart logic)", serviceName)
logrus.Infof("%s service successfully restarted", serviceNameShort)
return nil return nil
}, },
BashComplete: autocomplete.AppNameComplete,
} }

View File

@ -0,0 +1,44 @@
package upstream
import (
"context"
"fmt"
"github.com/docker/docker/api/types"
"github.com/docker/docker/client"
"github.com/sirupsen/logrus"
)
// RunServiceScale scales a service (useful for restart action)
func RunServiceScale(ctx context.Context, cl *client.Client, serviceID string, scale uint64) error {
service, _, err := cl.ServiceInspectWithRaw(ctx, serviceID, types.ServiceInspectOptions{})
if err != nil {
return err
}
serviceMode := &service.Spec.Mode
if serviceMode.Replicated != nil {
serviceMode.Replicated.Replicas = &scale
} else if serviceMode.ReplicatedJob != nil {
serviceMode.ReplicatedJob.TotalCompletions = &scale
} else {
return fmt.Errorf("scale can only be used with replicated or replicated-job mode")
}
response, err := cl.ServiceUpdate(
ctx,
service.ID,
service.Version,
service.Spec,
types.ServiceUpdateOptions{},
)
if err != nil {
return err
}
for _, warning := range response.Warnings {
logrus.Warn(warning)
}
return nil
}