github.com/juju/juju@v0.0.0-20240430160146-1752b71fcf00/worker/uniter/op_callbacks.go (about) 1 // Copyright 2012-2015 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package uniter 5 6 import ( 7 "fmt" 8 9 "github.com/juju/charm/v12/hooks" 10 "github.com/juju/errors" 11 "github.com/juju/names/v5" 12 13 "github.com/juju/juju/core/model" 14 "github.com/juju/juju/core/status" 15 "github.com/juju/juju/rpc/params" 16 "github.com/juju/juju/worker/uniter/charm" 17 "github.com/juju/juju/worker/uniter/hook" 18 "github.com/juju/juju/worker/uniter/remotestate" 19 "github.com/juju/juju/worker/uniter/runner/context" 20 ) 21 22 // operationCallbacks implements operation.Callbacks, and exists entirely to 23 // keep those methods off the Uniter itself. 24 type operationCallbacks struct { 25 u *Uniter 26 } 27 28 // PrepareHook is part of the operation.Callbacks interface. 29 func (opc *operationCallbacks) PrepareHook(hi hook.Info) (string, error) { 30 name := string(hi.Kind) 31 switch { 32 case hi.Kind.IsWorkload(): 33 name = fmt.Sprintf("%s-%s", hi.WorkloadName, hi.Kind) 34 case hi.Kind.IsRelation(): 35 var err error 36 name, err = opc.u.relationStateTracker.PrepareHook(hi) 37 if err != nil { 38 return "", err 39 } 40 case hi.Kind.IsStorage(): 41 if err := opc.u.storage.ValidateHook(hi); err != nil { 42 return "", err 43 } 44 storageName, err := names.StorageName(hi.StorageId) 45 if err != nil { 46 return "", err 47 } 48 name = fmt.Sprintf("%s-%s", storageName, hi.Kind) 49 // TODO(axw) if the agent is not installed yet, 50 // set the status to "preparing storage". 51 case hi.Kind.IsSecret(): 52 err := opc.u.secretsTracker.PrepareHook(hi) 53 if err != nil { 54 return "", err 55 } 56 case hi.Kind == hooks.ConfigChanged: 57 // TODO(axw) 58 //opc.u.f.DiscardConfigEvent() 59 case hi.Kind == hooks.LeaderSettingsChanged: 60 // TODO(axw) 61 //opc.u.f.DiscardLeaderSettingsEvent() 62 } 63 return name, nil 64 } 65 66 // CommitHook is part of the operation.Callbacks interface. 67 func (opc *operationCallbacks) CommitHook(hi hook.Info) error { 68 switch { 69 case hi.Kind == hooks.Start: 70 opc.u.Probe.SetHasStarted(true) 71 case hi.Kind == hooks.Stop: 72 opc.u.Probe.SetHasStarted(false) 73 case hi.Kind.IsWorkload(): 74 case hi.Kind.IsRelation(): 75 return opc.u.relationStateTracker.CommitHook(hi) 76 case hi.Kind.IsStorage(): 77 return opc.u.storage.CommitHook(hi) 78 case hi.Kind.IsSecret(): 79 return opc.u.secretsTracker.CommitHook(hi) 80 } 81 return nil 82 } 83 84 func notifyHook(hook string, ctx context.Context, method func(string)) { 85 if r, err := ctx.HookRelation(); err == nil { 86 remote, _ := ctx.RemoteUnitName() 87 if remote == "" { 88 remote, _ = ctx.RemoteApplicationName() 89 } 90 if remote != "" { 91 remote = " " + remote 92 } 93 hook = hook + remote + " " + r.FakeId() 94 } 95 method(hook) 96 } 97 98 // NotifyHookCompleted is part of the operation.Callbacks interface. 99 func (opc *operationCallbacks) NotifyHookCompleted(hook string, ctx context.Context) { 100 if opc.u.observer != nil { 101 notifyHook(hook, ctx, opc.u.observer.HookCompleted) 102 } 103 } 104 105 // NotifyHookFailed is part of the operation.Callbacks interface. 106 func (opc *operationCallbacks) NotifyHookFailed(hook string, ctx context.Context) { 107 if opc.u.observer != nil { 108 notifyHook(hook, ctx, opc.u.observer.HookFailed) 109 } 110 } 111 112 // FailAction is part of the operation.Callbacks interface. 113 func (opc *operationCallbacks) FailAction(actionId, message string) error { 114 if !names.IsValidAction(actionId) { 115 return errors.Errorf("invalid action id %q", actionId) 116 } 117 tag := names.NewActionTag(actionId) 118 err := opc.u.st.ActionFinish(tag, params.ActionFailed, nil, message) 119 if params.IsCodeNotFoundOrCodeUnauthorized(err) || params.IsCodeAlreadyExists(err) { 120 err = nil 121 } 122 return err 123 } 124 125 func (opc *operationCallbacks) ActionStatus(actionId string) (string, error) { 126 if !names.IsValidAction(actionId) { 127 return "", errors.NotValidf("invalid action id %q", actionId) 128 } 129 tag := names.NewActionTag(actionId) 130 return opc.u.st.ActionStatus(tag) 131 } 132 133 // GetArchiveInfo is part of the operation.Callbacks interface. 134 func (opc *operationCallbacks) GetArchiveInfo(url string) (charm.BundleInfo, error) { 135 ch, err := opc.u.st.Charm(url) 136 if err != nil { 137 return nil, errors.Trace(err) 138 } 139 return ch, nil 140 } 141 142 // SetCurrentCharm is part of the operation.Callbacks interface. 143 func (opc *operationCallbacks) SetCurrentCharm(charmURL string) error { 144 return opc.u.unit.SetCharmURL(charmURL) 145 } 146 147 // SetExecutingStatus is part of the operation.Callbacks interface. 148 func (opc *operationCallbacks) SetExecutingStatus(message string) error { 149 return setAgentStatus(opc.u, status.Executing, message, nil) 150 } 151 152 // SetUpgradeSeriesStatus is part of the operation.Callbacks interface. 153 func (opc *operationCallbacks) SetUpgradeSeriesStatus(upgradeSeriesStatus model.UpgradeSeriesStatus, reason string) error { 154 return setUpgradeSeriesStatus(opc.u, upgradeSeriesStatus, reason) 155 } 156 157 // RemoteInit is part of the operation.Callbacks interface. 158 func (opc *operationCallbacks) RemoteInit(runningStatus remotestate.ContainerRunningStatus, abort <-chan struct{}) error { 159 if opc.u.modelType != model.CAAS || opc.u.sidecar { 160 // Non CAAS model or sidecar CAAS model do not have remote init process. 161 return nil 162 } 163 if opc.u.remoteInitFunc == nil { 164 return nil 165 } 166 return opc.u.remoteInitFunc(runningStatus, abort) 167 } 168 169 // SetSecretRotated is part of the operation.Callbacks interface. 170 func (opc *operationCallbacks) SetSecretRotated(uri string, oldRevision int) error { 171 return opc.u.secretsClient.SecretRotated(uri, oldRevision) 172 } 173 174 // SecretsRemoved is part of the operation.Callbacks interface. 175 func (opc *operationCallbacks) SecretsRemoved(uris []string) error { 176 return opc.u.secretsTracker.SecretsRemoved(uris) 177 }