From f063fd5d396e586e0fec490dc4d1a52d7cd1e24a Mon Sep 17 00:00:00 2001 From: oscarzhou Date: Wed, 24 Jul 2024 20:54:16 +1200 Subject: [PATCH 1/2] fix(cmd): add forceRecreate cmd arg --- deploy.go | 13 ++++++------- go.mod | 2 +- go.sum | 2 ++ swarm.go | 11 +++++++++-- types.go | 2 ++ 5 files changed, 20 insertions(+), 10 deletions(-) diff --git a/deploy.go b/deploy.go index e5a0e25..6837116 100644 --- a/deploy.go +++ b/deploy.go @@ -30,11 +30,10 @@ func (cmd *DeployCommand) Run(cmdCtx *CommandExecutionContext) error { Bool("skipTLSVerify", cmd.SkipTLSVerify). Msg("Deploying Compose stack from Git repository") - defer dockerLogout(cmd.Registry) - err := dockerLogin(cmd.Registry) - if err != nil { - return err + if err := dockerLogin(cmd.Registry); err != nil { + return fmt.Errorf("an error occured in docker login. Error: %w", err) } + defer dockerLogout(cmd.Registry) if cmd.User != "" && cmd.Password != "" { log.Info(). @@ -131,7 +130,7 @@ func (cmd *DeployCommand) Run(cmdCtx *CommandExecutionContext) error { ProjectName: cmd.ProjectName, Env: cmd.Env, }, - ForceRecreate: true, + ForceRecreate: cmd.ForceRecreateStack, }) if err != nil { @@ -152,11 +151,11 @@ func (cmd *SwarmDeployCommand) Run(cmdCtx *CommandExecutionContext) error { Str("destination", cmd.Destination). Msg("Deploying Swarm stack from a Git repository") - defer dockerLogout(cmd.Registry) err := dockerLogin(cmd.Registry) if err != nil { - return err + return fmt.Errorf("an error occured in swarm docker login. Error: %w", err) } + defer dockerLogout(cmd.Registry) if cmd.User != "" && cmd.Password != "" { log.Info(). diff --git a/go.mod b/go.mod index 705b226..592c48e 100644 --- a/go.mod +++ b/go.mod @@ -7,7 +7,7 @@ toolchain go1.22.5 require ( github.com/alecthomas/kong v0.6.1 github.com/go-git/go-git/v5 v5.11.0 - github.com/portainer/portainer/pkg/libstack v0.0.0-20230626042119-89c1d0e33707 + github.com/portainer/portainer/pkg/libstack v0.0.0-20230831224222-4560a53317b0 github.com/rs/zerolog v1.28.0 ) diff --git a/go.sum b/go.sum index d603e52..c5938b3 100644 --- a/go.sum +++ b/go.sum @@ -67,6 +67,8 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/portainer/portainer/pkg/libstack v0.0.0-20230626042119-89c1d0e33707 h1:SmwWcOqHpbHj+4tZNR9AV4VfLWmbelkaAcWYuMkQ9G8= github.com/portainer/portainer/pkg/libstack v0.0.0-20230626042119-89c1d0e33707/go.mod h1:+zCK2UbsH6A3yEGi0yZ45ec5VFRP7svob5Q2lW6LFgk= +github.com/portainer/portainer/pkg/libstack v0.0.0-20230831224222-4560a53317b0 h1:BsSUEHzLdwxQ32QS5qdFYkWT3e7SqCLfrdeW69s1Ku4= +github.com/portainer/portainer/pkg/libstack v0.0.0-20230831224222-4560a53317b0/go.mod h1:+zCK2UbsH6A3yEGi0yZ45ec5VFRP7svob5Q2lW6LFgk= github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M= github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA= github.com/rs/xid v1.4.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= diff --git a/swarm.go b/swarm.go index 2bf9b2d..12bc3a9 100644 --- a/swarm.go +++ b/swarm.go @@ -17,9 +17,16 @@ func deploySwarmStack(cmd SwarmDeployCommand, clonePath string) error { } else { args = append(args, "stack", "deploy", "--with-registry-auth") } - if !cmd.Pull { - args = append(args, "--resolve-image=never") + + resolveImageArgs := "--resolve-image=never" + if cmd.Pull { + resolveImageArgs = "--resolve-image=changed" + } + + if cmd.ForceRecreateStack { + resolveImageArgs = "--resolve-image=always" } + args = append(args, resolveImageArgs) for _, cfile := range cmd.ComposeRelativeFilePaths { args = append(args, "--compose-file", path.Join(clonePath, cfile)) diff --git a/types.go b/types.go index 81fa811..f32e6d2 100644 --- a/types.go +++ b/types.go @@ -23,6 +23,7 @@ type DeployCommand struct { Password string `help:"Password or PAT for Git authentication" short:"p"` Keep bool `help:"Keep stack folder" short:"k"` SkipTLSVerify bool `help:"Skip TLS verification for git" name:"skip-tls-verify"` + ForceRecreateStack bool `help:"Force to recreate the target stack regardless whether the image hash changes" name:"force-recreate"` Env []string `help:"OS ENV for stack" example:"key=value"` Registry []string `help:"Registry credentials" name:"registry"` GitRepository string `arg:"" help:"Git repository to deploy from." name:"git-repo"` @@ -39,6 +40,7 @@ type SwarmDeployCommand struct { Prune bool `help:"Prune services during deployment" short:"r"` Keep bool `help:"Keep stack folder" short:"k"` SkipTLSVerify bool `help:"Skip TLS verification for git" name:"skip-tls-verify"` + ForceRecreateStack bool `help:"Force to recreate the target stack regardless whether the image hash changes" name:"force-recreate"` Env []string `help:"OS ENV for stack."` Registry []string `help:"Registry credentials" name:"registry"` GitRepository string `arg:"" help:"Git repository to deploy from." name:"git-repo"` From f41e4d3fd7b73076f9360134b81a78609bb75786 Mon Sep 17 00:00:00 2001 From: oscarzhou Date: Fri, 26 Jul 2024 14:40:40 +1200 Subject: [PATCH 2/2] fix(swarm): add contiion for --force arg --- deploy.go | 7 +++---- swarm.go | 24 +++++++++++++----------- 2 files changed, 16 insertions(+), 15 deletions(-) diff --git a/deploy.go b/deploy.go index 6837116..b0866ca 100644 --- a/deploy.go +++ b/deploy.go @@ -192,7 +192,7 @@ func (cmd *SwarmDeployCommand) Run(cmdCtx *CommandExecutionContext) error { } forceUpdate := false - if len(runningServices) > 0 { + if cmd.ForceRecreateStack && len(runningServices) > 0 { // To determine whether the current service needs to force update, it // is more reliable to check if there is a created service with the // stack name rather than to check if there is an existing git repository. @@ -261,9 +261,8 @@ func (cmd *SwarmDeployCommand) Run(cmdCtx *CommandExecutionContext) error { } for _, updatedServiceID := range updatedServiceIDs { - _, ok := runningServices[updatedServiceID] - if ok { - _ = updateService(updatedServiceID) + if _, ok := runningServices[updatedServiceID]; ok { + _ = updateService(updatedServiceID, forceUpdate) } } } diff --git a/swarm.go b/swarm.go index 12bc3a9..98931fc 100644 --- a/swarm.go +++ b/swarm.go @@ -18,16 +18,10 @@ func deploySwarmStack(cmd SwarmDeployCommand, clonePath string) error { args = append(args, "stack", "deploy", "--with-registry-auth") } - resolveImageArgs := "--resolve-image=never" - if cmd.Pull { - resolveImageArgs = "--resolve-image=changed" + if !cmd.Pull { + args = append(args, "--resolve-image=never") } - if cmd.ForceRecreateStack { - resolveImageArgs = "--resolve-image=always" - } - args = append(args, resolveImageArgs) - for _, cfile := range cmd.ComposeRelativeFilePaths { args = append(args, "--compose-file", path.Join(clonePath, cfile)) } @@ -75,22 +69,30 @@ func checkRunningService(projectName string) ([]string, error) { return serviceIDs, nil } -func updateService(serviceID string) error { +func updateService(serviceID string, forceRecreate bool) error { command := getDockerBinaryPath() - args := []string{"--config", PORTAINER_DOCKER_CONFIG_PATH, "service", "update", serviceID, "--force"} + args := []string{"--config", PORTAINER_DOCKER_CONFIG_PATH, "service", "update", serviceID} + if forceRecreate { + args = append(args, "--force") + } log.Info(). Strs("args", args). Msg("Updating Swarm service") - _, err := runCommand(command, args) + + out, err := runCommand(command, args) if err != nil { log.Error(). Err(err). + Str("standard_output", out). + Str("context", "SwarmDeployerUpdateService"). Msg("Failed to update swarm services") return err } log.Info(). + Str("standard_output", out). + Str("context", "SwarmDeployerUpdateService"). Msg("Update stack service completed") return nil }