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  }