github.com/altoros/juju-vmware@v0.0.0-20150312064031-f19ae857ccca/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.v4" 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 abort <-chan struct{}, 23 ) Factory { 24 return &factory{ 25 deployer: deployer, 26 runnerFactory: runnerFactory, 27 callbacks: callbacks, 28 abort: abort, 29 } 30 } 31 32 type factory struct { 33 deployer charm.Deployer 34 runnerFactory runner.Factory 35 callbacks Callbacks 36 abort <-chan struct{} 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.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.callbacks, 64 deployer: f.deployer, 65 abort: f.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.callbacks, 105 runnerFactory: f.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.callbacks, 135 runnerFactory: f.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.callbacks, 157 runnerFactory: f.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.callbacks, 166 }, nil 167 }