github.com/juju/juju@v0.0.0-20240430160146-1752b71fcf00/worker/uniter/operation/interface.go (about)

     1  // Copyright 2014-2015 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package operation
     5  
     6  import (
     7  	"github.com/juju/errors"
     8  	"github.com/juju/names/v5"
     9  	utilexec "github.com/juju/utils/v3/exec"
    10  
    11  	"github.com/juju/juju/core/model"
    12  	"github.com/juju/juju/worker/uniter/charm"
    13  	"github.com/juju/juju/worker/uniter/hook"
    14  	"github.com/juju/juju/worker/uniter/remotestate"
    15  	"github.com/juju/juju/worker/uniter/runner"
    16  	"github.com/juju/juju/worker/uniter/runner/context"
    17  )
    18  
    19  //go:generate go run go.uber.org/mock/mockgen -package mocks -destination mocks/interface_mock.go github.com/juju/juju/worker/uniter/operation Operation,Factory,Callbacks
    20  
    21  // Logger is here to stop the desire of creating a package level Logger.
    22  // Don't do this, pass one in to the needed functions.
    23  type logger interface{}
    24  
    25  var _ logger = struct{}{}
    26  
    27  // Logger determines the logging methods used by the operations package.
    28  type Logger interface {
    29  	Errorf(string, ...interface{})
    30  	Warningf(string, ...interface{})
    31  	Infof(string, ...interface{})
    32  	Debugf(string, ...interface{})
    33  	Tracef(string, ...interface{})
    34  }
    35  
    36  // Operation encapsulates the stages of the various things the uniter can do,
    37  // and the state changes that need to be recorded as they happen. Operations
    38  // are designed to be Run (or Skipped) by an Executor, which supplies starting
    39  // state and records the changes returned.
    40  type Operation interface {
    41  
    42  	// String returns a short representation of the operation.
    43  	String() string
    44  
    45  	// NeedsGlobalMachineLock returns a bool expressing whether we need to lock the machine.
    46  	NeedsGlobalMachineLock() bool
    47  
    48  	// ExecutionGroup returns a string used to construct the name of the machine lock.
    49  	ExecutionGroup() string
    50  
    51  	// Prepare ensures that the operation is valid and ready to be executed.
    52  	// If it returns a non-nil state, that state will be validated and recorded.
    53  	// If it returns ErrSkipExecute, it indicates that the operation can be
    54  	// committed directly.
    55  	Prepare(state State) (*State, error)
    56  
    57  	// Execute carries out the operation. It must not be called without having
    58  	// called Prepare first. If it returns a non-nil state, that state will be
    59  	// validated and recorded.
    60  	Execute(state State) (*State, error)
    61  
    62  	// Commit ensures that the operation's completion is recorded. If it returns
    63  	// a non-nil state, that state will be validated and recorded.
    64  	Commit(state State) (*State, error)
    65  
    66  	// RemoteStateChanged is called when the remote state changed during execution
    67  	// of the operation.
    68  	RemoteStateChanged(snapshot remotestate.Snapshot)
    69  }
    70  
    71  // WrappedOperation extends Operation to provide access to the wrapped operation.
    72  type WrappedOperation interface {
    73  	Operation
    74  
    75  	WrappedOperation() Operation
    76  }
    77  
    78  // Unwrap peels back one layer of a wrapped operation.
    79  func Unwrap(op Operation) Operation {
    80  	if op == nil {
    81  		return nil
    82  	}
    83  	if wrapped, ok := op.(WrappedOperation); ok {
    84  		return wrapped.WrappedOperation()
    85  	}
    86  	return op
    87  }
    88  
    89  // Executor records and exposes uniter state, and applies suitable changes as
    90  // operations are run or skipped.
    91  type Executor interface {
    92  
    93  	// State returns a copy of the executor's current operation state.
    94  	State() State
    95  
    96  	// Run will Prepare, Execute, and Commit the supplied operation, writing
    97  	// indicated state changes between steps. If any step returns an unknown
    98  	// error, the run will be aborted and an error will be returned.
    99  	// On remote state change, the executor will fire the operation's
   100  	// RemoteStateChanged method.
   101  	Run(Operation, <-chan remotestate.Snapshot) error
   102  
   103  	// Skip will Commit the supplied operation, and write any state change
   104  	// indicated. If Commit returns an error, so will Skip.
   105  	Skip(Operation) error
   106  }
   107  
   108  // Factory creates operations.
   109  type Factory interface {
   110  
   111  	// NewInstall creates an install operation for the supplied charm.
   112  	NewInstall(charmURL string) (Operation, error)
   113  
   114  	// NewUpgrade creates an upgrade operation for the supplied charm.
   115  	NewUpgrade(charmURL string) (Operation, error)
   116  
   117  	// NewRemoteInit inits the remote charm on CAAS pod.
   118  	NewRemoteInit(runningStatus remotestate.ContainerRunningStatus) (Operation, error)
   119  
   120  	// NewSkipRemoteInit skips a remote-init operation.
   121  	NewSkipRemoteInit(retry bool) (Operation, error)
   122  
   123  	// NewNoOpFinishUpgradeSeries creates a noop which simply resets the
   124  	// status of a units upgrade series.
   125  	NewNoOpFinishUpgradeSeries() (Operation, error)
   126  
   127  	// NewRevertUpgrade creates an operation to clear the unit's resolved flag,
   128  	// and execute an upgrade to the supplied charm that is careful to excise
   129  	// remnants of a previously failed upgrade to a different charm.
   130  	NewRevertUpgrade(charmURL string) (Operation, error)
   131  
   132  	// NewResolvedUpgrade creates an operation to clear the unit's resolved flag,
   133  	// and execute an upgrade to the supplied charm that is careful to preserve
   134  	// non-overlapping remnants of a previously failed upgrade to the same charm.
   135  	NewResolvedUpgrade(charmURL string) (Operation, error)
   136  
   137  	// NewRunHook creates an operation to execute the supplied hook.
   138  	NewRunHook(hookInfo hook.Info) (Operation, error)
   139  
   140  	// NewSkipHook creates an operation to mark the supplied hook as
   141  	// completed successfully, without executing the hook.
   142  	NewSkipHook(hookInfo hook.Info) (Operation, error)
   143  
   144  	// NewAction creates an operation to execute the supplied action.
   145  	NewAction(actionId string) (Operation, error)
   146  
   147  	// NewFailAction creates an operation that marks an action as failed.
   148  	NewFailAction(actionId string) (Operation, error)
   149  
   150  	// NewCommands creates an operation to execute the supplied script in the
   151  	// indicated relation context, and pass the results back over the supplied
   152  	// func.
   153  	NewCommands(args CommandArgs, sendResponse CommandResponseFunc) (Operation, error)
   154  
   155  	// NewAcceptLeadership creates an operation to ensure the uniter acts as
   156  	// application leader.
   157  	NewAcceptLeadership() (Operation, error)
   158  
   159  	// NewResignLeadership creates an operation to ensure the uniter does not
   160  	// act as application leader.
   161  	NewResignLeadership() (Operation, error)
   162  
   163  	// NewNoOpSecretsRemoved creates an operation to update the secrets
   164  	// state when secrets are removed.
   165  	NewNoOpSecretsRemoved(uris []string) (Operation, error)
   166  }
   167  
   168  // CommandArgs stores the arguments for a Command operation.
   169  type CommandArgs struct {
   170  	// Commands is the arbitrary commands to execute on the unit
   171  	Commands string
   172  	// RelationId is the relation context to execute the commands in.
   173  	RelationId int
   174  	// RemoteUnitName is the remote unit for the relation context.
   175  	RemoteUnitName string
   176  	// TODO(jam): 2019-10-24 Include RemoteAppName
   177  	// ForceRemoteUnit skips unit inference and existence validation.
   178  	ForceRemoteUnit bool
   179  	// RunLocation describes where the command must run.
   180  	RunLocation runner.RunLocation
   181  }
   182  
   183  // Validate the command arguments.
   184  func (args CommandArgs) Validate() error {
   185  	if args.Commands == "" {
   186  		return errors.New("commands required")
   187  	}
   188  	if args.RemoteUnitName != "" {
   189  		if args.RelationId == -1 {
   190  			return errors.New("remote unit not valid without relation")
   191  		} else if !names.IsValidUnit(args.RemoteUnitName) {
   192  			return errors.Errorf("invalid remote unit name %q", args.RemoteUnitName)
   193  		}
   194  	}
   195  	return nil
   196  }
   197  
   198  // CommandResponseFunc is for marshalling command responses back to the source
   199  // of the original request.
   200  type CommandResponseFunc func(*utilexec.ExecResponse, error) bool
   201  
   202  // Callbacks exposes all the uniter code that's required by the various operations.
   203  // It's far from cohesive, and fundamentally represents inappropriate coupling, so
   204  // it's a prime candidate for future refactoring.
   205  type Callbacks interface {
   206  	// PrepareHook and CommitHook exist so that we can defer worrying about how
   207  	// to untangle Uniter.relationers from everything else. They're only used by
   208  	// RunHook operations.
   209  	PrepareHook(info hook.Info) (name string, err error)
   210  	CommitHook(info hook.Info) error
   211  
   212  	// SetExecutingStatus sets the agent state to "Executing" with a message.
   213  	SetExecutingStatus(string) error
   214  
   215  	// NotifyHook* exist so that we can defer worrying about how to untangle the
   216  	// callbacks inserted for uniter_test. They're only used by RunHook operations.
   217  
   218  	NotifyHookCompleted(string, context.Context)
   219  	NotifyHookFailed(string, context.Context)
   220  
   221  	// The following methods exist primarily to allow us to test operation code
   222  	// without using a live api connection.
   223  
   224  	// FailAction marks the supplied action failed. It's only used by
   225  	// RunActions operations.
   226  	FailAction(actionId, message string) error
   227  
   228  	// ActionStatus returns the status of the action required by the action operation for
   229  	// cancelation.
   230  	ActionStatus(actionId string) (string, error)
   231  
   232  	// GetArchiveInfo is used to find out how to download a charm archive. It's
   233  	// only used by Deploy operations.
   234  	GetArchiveInfo(charmURL string) (charm.BundleInfo, error)
   235  
   236  	// SetCurrentCharm records intent to deploy a given charm. It must be called
   237  	// *before* recording local state referencing that charm, to ensure there's
   238  	// no path by which the controller can legitimately garbage collect that
   239  	// charm or the application's settings for it. It's only used by Deploy operations.
   240  	SetCurrentCharm(charmURL string) error
   241  
   242  	// SetUpgradeSeriesStatus is intended to give the uniter a chance to
   243  	// upgrade the status of a running series upgrade before or after
   244  	// upgrade series hook code completes and, for display purposes, to
   245  	// supply a reason as to why it is making the change.
   246  	SetUpgradeSeriesStatus(status model.UpgradeSeriesStatus, reason string) error
   247  
   248  	// SetSecretRotated updates the secret rotation status.
   249  	SetSecretRotated(url string, originalRevision int) error
   250  
   251  	// SecretsRemoved updates the unit secret state when
   252  	// secrets are removed.
   253  	SecretsRemoved(uris []string) error
   254  
   255  	// RemoteInit copies the charm to the remote instance. CAAS only.
   256  	RemoteInit(runningStatus remotestate.ContainerRunningStatus, abort <-chan struct{}) error
   257  }
   258  
   259  // StorageUpdater is an interface used for updating local knowledge of storage
   260  // attachments.
   261  type StorageUpdater interface {
   262  	// UpdateStorage updates local knowledge of the storage attachments
   263  	// with the specified tags.
   264  	UpdateStorage([]names.StorageTag) error
   265  }