github.com/juju/juju@v0.0.0-20240327075706-a90865de2538/worker/uniter/container/remoteinit.go (about) 1 // Copyright 2020 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package container 5 6 import ( 7 "github.com/juju/juju/worker/uniter/operation" 8 "github.com/juju/juju/worker/uniter/remotestate" 9 "github.com/juju/juju/worker/uniter/resolver" 10 ) 11 12 type remoteContainerInitResolver struct{} 13 14 // NewRemoteContainerInitResolver returns a new resolver with determines which container related operation 15 // should be run based on local and remote uniter states. 16 func NewRemoteContainerInitResolver() resolver.Resolver { 17 return &remoteContainerInitResolver{} 18 } 19 20 // NextOp implements the resolver.Resolver interface. 21 func (r *remoteContainerInitResolver) NextOp( 22 localState resolver.LocalState, 23 remoteState remotestate.Snapshot, 24 opFactory operation.Factory, 25 ) (operation.Operation, error) { 26 noOp := func() (operation.Operation, error) { 27 if localState.Kind == operation.RemoteInit { 28 // If we are resuming from an unexpected state, skip init. 29 // Retry will occur when remotestate updates. 30 return opFactory.NewSkipRemoteInit(false) 31 } 32 return nil, resolver.ErrNoOperation 33 } 34 if remoteState.ContainerRunningStatus == nil { 35 return noOp() 36 } 37 // Check if init or workload containers are running. 38 if !remoteState.ContainerRunningStatus.Initialising && 39 !remoteState.ContainerRunningStatus.Running { 40 return noOp() 41 } 42 // If we haven't yet handled the init container. 43 if !localState.OutdatedRemoteCharm && localState.ContainerRunningStatus != nil { 44 if localState.ContainerRunningStatus.InitialisingTime == remoteState.ContainerRunningStatus.InitialisingTime { 45 // We've already initialised the container. 46 return noOp() 47 } 48 } else if !localState.OutdatedRemoteCharm { 49 // Nothing to do 50 return noOp() 51 } 52 switch localState.Kind { 53 case operation.RunHook: 54 if localState.Step == operation.Pending { 55 return opFactory.NewRemoteInit(*remoteState.ContainerRunningStatus) 56 } 57 case operation.Continue: 58 return opFactory.NewRemoteInit(*remoteState.ContainerRunningStatus) 59 case operation.RemoteInit: 60 if localState.Step == operation.Pending { 61 return opFactory.NewRemoteInit(*remoteState.ContainerRunningStatus) 62 } 63 // If we are resuming from an unexpected state, skip init but retry the remote init op. 64 return opFactory.NewSkipRemoteInit(true) 65 } 66 return noOp() 67 }