github.com/mhilton/juju-juju@v0.0.0-20150901100907-a94dd2c73455/worker/uniter/operation/factory.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" 9 corecharm "gopkg.in/juju/charm.v5" 10 11 "github.com/juju/juju/worker/uniter/charm" 12 "github.com/juju/juju/worker/uniter/hook" 13 "github.com/juju/juju/worker/uniter/runner" 14 ) 15 16 // FactoryParams holds all the necessary parameters for a new operation factory. 17 type FactoryParams struct { 18 Deployer charm.Deployer 19 RunnerFactory runner.Factory 20 Callbacks Callbacks 21 StorageUpdater StorageUpdater 22 Abort <-chan struct{} 23 MetricSender apiMetricSender 24 MetricSpoolDir string 25 } 26 27 // NewFactory returns a Factory that creates Operations backed by the supplied 28 // parameters. 29 func NewFactory(params FactoryParams) Factory { 30 return &factory{ 31 config: params, 32 } 33 } 34 35 type factory struct { 36 config FactoryParams 37 } 38 39 // newResolved wraps the supplied operation such that it will clear the uniter 40 // resolve flag before executing. 41 func (f *factory) newResolved(wrapped Operation) (Operation, error) { 42 if wrapped == nil { 43 return nil, errors.New("operation required") 44 } 45 return &resolvedOperation{ 46 Operation: wrapped, 47 callbacks: f.config.Callbacks, 48 }, nil 49 } 50 51 // newDeploy is the common code for creating arbitrary deploy operations. 52 func (f *factory) newDeploy(kind Kind, charmURL *corecharm.URL, revert, resolved bool) (Operation, error) { 53 if charmURL == nil { 54 return nil, errors.New("charm url required") 55 } else if kind != Install && kind != Upgrade { 56 return nil, errors.Errorf("unknown deploy kind: %s", kind) 57 } 58 return &deploy{ 59 kind: kind, 60 charmURL: charmURL, 61 revert: revert, 62 resolved: resolved, 63 callbacks: f.config.Callbacks, 64 deployer: f.config.Deployer, 65 abort: f.config.Abort, 66 }, nil 67 } 68 69 // NewInstall is part of the Factory interface. 70 func (f *factory) NewInstall(charmURL *corecharm.URL) (Operation, error) { 71 return f.newDeploy(Install, charmURL, false, false) 72 } 73 74 // NewUpgrade is part of the Factory interface. 75 func (f *factory) NewUpgrade(charmURL *corecharm.URL) (Operation, error) { 76 return f.newDeploy(Upgrade, charmURL, false, false) 77 } 78 79 // NewRevertUpgrade is part of the Factory interface. 80 func (f *factory) NewRevertUpgrade(charmURL *corecharm.URL) (Operation, error) { 81 charmOp, err := f.newDeploy(Upgrade, charmURL, true, false) 82 if err != nil { 83 return nil, err 84 } 85 return f.newResolved(charmOp) 86 } 87 88 // NewResolvedUpgrade is part of the Factory interface. 89 func (f *factory) NewResolvedUpgrade(charmURL *corecharm.URL) (Operation, error) { 90 charmOp, err := f.newDeploy(Upgrade, charmURL, false, true) 91 if err != nil { 92 return nil, err 93 } 94 return f.newResolved(charmOp) 95 } 96 97 // NewRunHook is part of the Factory interface. 98 func (f *factory) NewRunHook(hookInfo hook.Info) (Operation, error) { 99 if err := hookInfo.Validate(); err != nil { 100 return nil, err 101 } 102 return &runHook{ 103 info: hookInfo, 104 callbacks: f.config.Callbacks, 105 runnerFactory: f.config.RunnerFactory, 106 }, nil 107 } 108 109 // NewRetryHook is part of the Factory interface. 110 func (f *factory) NewRetryHook(hookInfo hook.Info) (Operation, error) { 111 hookOp, err := f.NewRunHook(hookInfo) 112 if err != nil { 113 return nil, err 114 } 115 return f.newResolved(hookOp) 116 } 117 118 // NewSkipHook is part of the Factory interface. 119 func (f *factory) NewSkipHook(hookInfo hook.Info) (Operation, error) { 120 hookOp, err := f.NewRunHook(hookInfo) 121 if err != nil { 122 return nil, err 123 } 124 return f.newResolved(&skipOperation{hookOp}) 125 } 126 127 // NewAction is part of the Factory interface. 128 func (f *factory) NewAction(actionId string) (Operation, error) { 129 if !names.IsValidAction(actionId) { 130 return nil, errors.Errorf("invalid action id %q", actionId) 131 } 132 return &runAction{ 133 actionId: actionId, 134 callbacks: f.config.Callbacks, 135 runnerFactory: f.config.RunnerFactory, 136 }, nil 137 } 138 139 // NewCommands is part of the Factory interface. 140 func (f *factory) NewCommands(args CommandArgs, sendResponse CommandResponseFunc) (Operation, error) { 141 if args.Commands == "" { 142 return nil, errors.New("commands required") 143 } else if sendResponse == nil { 144 return nil, errors.New("response sender required") 145 } 146 if args.RemoteUnitName != "" { 147 if args.RelationId == -1 { 148 return nil, errors.New("remote unit not valid without relation") 149 } else if !names.IsValidUnit(args.RemoteUnitName) { 150 return nil, errors.Errorf("invalid remote unit name %q", args.RemoteUnitName) 151 } 152 } 153 return &runCommands{ 154 args: args, 155 sendResponse: sendResponse, 156 callbacks: f.config.Callbacks, 157 runnerFactory: f.config.RunnerFactory, 158 }, nil 159 } 160 161 // NewUpdateRelations is part of the Factory interface. 162 func (f *factory) NewUpdateRelations(ids []int) (Operation, error) { 163 return &updateRelations{ 164 ids: ids, 165 callbacks: f.config.Callbacks, 166 }, nil 167 } 168 169 // NewUpdateStorage is part of the Factory interface. 170 func (f *factory) NewUpdateStorage(tags []names.StorageTag) (Operation, error) { 171 return &updateStorage{ 172 tags: tags, 173 storageUpdater: f.config.StorageUpdater, 174 }, nil 175 } 176 177 // NewResignLeadership is part of the Factory interface. 178 func (f *factory) NewResignLeadership() (Operation, error) { 179 return &resignLeadership{}, nil 180 } 181 182 // NewAcceptLeadership is part of the Factory interface. 183 func (f *factory) NewAcceptLeadership() (Operation, error) { 184 return &acceptLeadership{}, nil 185 } 186 187 // NewSendMetrics is part of the Factory interface. 188 func (f *factory) NewSendMetrics() (Operation, error) { 189 return &sendMetrics{ 190 sender: f.config.MetricSender, 191 spoolDir: f.config.MetricSpoolDir, 192 }, nil 193 }