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