@ -1,6 +1,7 @@
package actions
package actions
import (
import (
"errors"
"github.com/containrrr/watchtower/internal/util"
"github.com/containrrr/watchtower/internal/util"
"github.com/containrrr/watchtower/pkg/container"
"github.com/containrrr/watchtower/pkg/container"
"github.com/containrrr/watchtower/pkg/lifecycle"
"github.com/containrrr/watchtower/pkg/lifecycle"
@ -81,8 +82,9 @@ func Update(client container.Client, params types.UpdateParams) (*metrics2.Metri
if params . RollingRestart {
if params . RollingRestart {
metric . Failed += performRollingRestart ( containersToUpdate , client , params )
metric . Failed += performRollingRestart ( containersToUpdate , client , params )
} else {
} else {
metric . Failed += stopContainersInReversedOrder ( containersToUpdate , client , params )
imageIDsOfStoppedContainers := make ( map [ string ] bool )
metric . Failed += restartContainersInSortedOrder ( containersToUpdate , client , params )
metric . Failed , imageIDsOfStoppedContainers = stopContainersInReversedOrder ( containersToUpdate , client , params )
metric . Failed += restartContainersInSortedOrder ( containersToUpdate , client , params , imageIDsOfStoppedContainers )
}
}
metric . Updated = staleCount - ( metric . Failed - staleCheckFailed )
metric . Updated = staleCount - ( metric . Failed - staleCheckFailed )
@ -99,15 +101,17 @@ func performRollingRestart(containers []container.Container, client container.Cl
for i := len ( containers ) - 1 ; i >= 0 ; i -- {
for i := len ( containers ) - 1 ; i >= 0 ; i -- {
if containers [ i ] . ToRestart ( ) {
if containers [ i ] . ToRestart ( ) {
if err := stopStaleContainer ( containers [ i ] , client , params ) ; err != nil {
err := stopStaleContainer ( containers [ i ] , client , params )
if err != nil {
failed ++
failed ++
}
} else {
if err := restartStaleContainer ( containers [ i ] , client , params ) ; err != nil {
if err := restartStaleContainer ( containers [ i ] , client , params ) ; err != nil {
failed ++
failed ++
}
}
cleanupImageIDs [ containers [ i ] . ImageID ( ) ] = true
cleanupImageIDs [ containers [ i ] . ImageID ( ) ] = true
}
}
}
}
}
if params . Cleanup {
if params . Cleanup {
cleanupImages ( client , cleanupImageIDs )
cleanupImages ( client , cleanupImageIDs )
@ -115,14 +119,18 @@ func performRollingRestart(containers []container.Container, client container.Cl
return failed
return failed
}
}
func stopContainersInReversedOrder ( containers [ ] container . Container , client container . Client , params types . UpdateParams ) int {
func stopContainersInReversedOrder ( containers [ ] container . Container , client container . Client , params types . UpdateParams ) ( int , map [ string ] bool ) {
imageIDsOfStoppedContainers := make ( map [ string ] bool )
failed := 0
failed := 0
for i := len ( containers ) - 1 ; i >= 0 ; i -- {
for i := len ( containers ) - 1 ; i >= 0 ; i -- {
if err := stopStaleContainer ( containers [ i ] , client , params ) ; err != nil {
if err := stopStaleContainer ( containers [ i ] , client , params ) ; err != nil {
failed ++
failed ++
} else {
imageIDsOfStoppedContainers [ containers [ i ] . ImageID ( ) ] = true
}
}
}
}
return failed
return failed , imageIDsOfStoppedContainers
}
}
func stopStaleContainer ( container container . Container , client container . Client , params types . UpdateParams ) error {
func stopStaleContainer ( container container . Container , client container . Client , params types . UpdateParams ) error {
@ -135,11 +143,16 @@ func stopStaleContainer(container container.Container, client container.Client,
return nil
return nil
}
}
if params . LifecycleHooks {
if params . LifecycleHooks {
if err := lifecycle . ExecutePreUpdateCommand ( client , container ) ; err != nil {
SkipUpdate , err := lifecycle . ExecutePreUpdateCommand ( client , container )
if err != nil {
log . Error ( err )
log . Error ( err )
log . Info ( "Skipping container as the pre-update command failed" )
log . Info ( "Skipping container as the pre-update command failed" )
return err
return err
}
}
if SkipUpdate {
log . Debug ( "Skipping container as the pre-update command returned exit code 75 (EX_TEMPFAIL)" )
return errors . New ( "Skipping container as the pre-update command returned exit code 75 (EX_TEMPFAIL)" )
}
}
}
if err := client . StopContainer ( container , params . Timeout ) ; err != nil {
if err := client . StopContainer ( container , params . Timeout ) ; err != nil {
@ -149,7 +162,7 @@ func stopStaleContainer(container container.Container, client container.Client,
return nil
return nil
}
}
func restartContainersInSortedOrder ( containers [ ] container . Container , client container . Client , params types . UpdateParams ) int {
func restartContainersInSortedOrder ( containers [ ] container . Container , client container . Client , params types . UpdateParams , imageIDsOfStoppedContainers map [ string ] bool ) int {
imageIDs := make ( map [ string ] bool )
imageIDs := make ( map [ string ] bool )
failed := 0
failed := 0
@ -158,11 +171,13 @@ func restartContainersInSortedOrder(containers []container.Container, client con
if ! c . ToRestart ( ) {
if ! c . ToRestart ( ) {
continue
continue
}
}
if imageIDsOfStoppedContainers [ c . ImageID ( ) ] {
if err := restartStaleContainer ( c , client , params ) ; err != nil {
if err := restartStaleContainer ( c , client , params ) ; err != nil {
failed ++
failed ++
}
}
imageIDs [ c . ImageID ( ) ] = true
imageIDs [ c . ImageID ( ) ] = true
}
}
}
if params . Cleanup {
if params . Cleanup {
cleanupImages ( client , imageIDs )
cleanupImages ( client , imageIDs )