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 }