github.com/niedbalski/juju@v0.0.0-20190215020005-8ff100488e47/worker/uniter/runner/factory.go (about) 1 // Copyright 2012-2014 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package runner 5 6 import ( 7 "github.com/juju/errors" 8 "gopkg.in/juju/charm.v6" 9 "gopkg.in/juju/names.v2" 10 11 "github.com/juju/juju/api/uniter" 12 "github.com/juju/juju/apiserver/params" 13 "github.com/juju/juju/core/actions" 14 "github.com/juju/juju/worker/common/charmrunner" 15 "github.com/juju/juju/worker/uniter/hook" 16 "github.com/juju/juju/worker/uniter/runner/context" 17 ) 18 19 // Factory represents a long-lived object that can create runners 20 // relevant to a specific unit. 21 type Factory interface { 22 23 // NewCommandRunner returns an execution context suitable for running 24 // an arbitrary script. 25 NewCommandRunner(commandInfo context.CommandInfo) (Runner, error) 26 27 // NewHookRunner returns an execution context suitable for running the 28 // supplied hook definition (which must be valid). 29 NewHookRunner(hookInfo hook.Info) (Runner, error) 30 31 // NewActionRunner returns an execution context suitable for running the 32 // action identified by the supplied id. 33 NewActionRunner(actionId string) (Runner, error) 34 } 35 36 // NewFactory returns a Factory capable of creating runners for executing 37 // charm hooks, actions and commands. 38 func NewFactory( 39 state *uniter.State, 40 paths context.Paths, 41 contextFactory context.ContextFactory, 42 ) ( 43 Factory, error, 44 ) { 45 f := &factory{ 46 state: state, 47 paths: paths, 48 contextFactory: contextFactory, 49 } 50 51 return f, nil 52 } 53 54 type factory struct { 55 contextFactory context.ContextFactory 56 57 // API connection fields. 58 state *uniter.State 59 60 // Fields that shouldn't change in a factory's lifetime. 61 paths context.Paths 62 } 63 64 // NewCommandRunner exists to satisfy the Factory interface. 65 func (f *factory) NewCommandRunner(commandInfo context.CommandInfo) (Runner, error) { 66 ctx, err := f.contextFactory.CommandContext(commandInfo) 67 if err != nil { 68 return nil, errors.Trace(err) 69 } 70 runner := NewRunner(ctx, f.paths) 71 return runner, nil 72 } 73 74 // NewHookRunner exists to satisfy the Factory interface. 75 func (f *factory) NewHookRunner(hookInfo hook.Info) (Runner, error) { 76 if err := hookInfo.Validate(); err != nil { 77 return nil, errors.Trace(err) 78 } 79 80 ctx, err := f.contextFactory.HookContext(hookInfo) 81 if err != nil { 82 return nil, errors.Trace(err) 83 } 84 runner := NewRunner(ctx, f.paths) 85 return runner, nil 86 } 87 88 // NewActionRunner exists to satisfy the Factory interface. 89 func (f *factory) NewActionRunner(actionId string) (Runner, error) { 90 ch, err := getCharm(f.paths.GetCharmDir()) 91 if err != nil { 92 return nil, errors.Trace(err) 93 } 94 95 ok := names.IsValidAction(actionId) 96 if !ok { 97 return nil, charmrunner.NewBadActionError(actionId, "not valid actionId") 98 } 99 tag := names.NewActionTag(actionId) 100 action, err := f.state.Action(tag) 101 if params.IsCodeNotFoundOrCodeUnauthorized(err) { 102 return nil, charmrunner.ErrActionNotAvailable 103 } else if params.IsCodeActionNotAvailable(err) { 104 return nil, charmrunner.ErrActionNotAvailable 105 } else if err != nil { 106 return nil, errors.Trace(err) 107 } 108 109 name := action.Name() 110 111 spec, ok := actions.PredefinedActionsSpec[name] 112 if !ok { 113 var ok bool 114 spec, ok = ch.Actions().ActionSpecs[name] 115 if !ok { 116 return nil, charmrunner.NewBadActionError(name, "not defined") 117 } 118 } 119 120 params := action.Params() 121 if err := spec.ValidateParams(params); err != nil { 122 return nil, charmrunner.NewBadActionError(name, err.Error()) 123 } 124 125 actionData := context.NewActionData(name, &tag, params) 126 ctx, err := f.contextFactory.ActionContext(actionData) 127 runner := NewRunner(ctx, f.paths) 128 return runner, nil 129 } 130 131 func getCharm(charmPath string) (charm.Charm, error) { 132 ch, err := charm.ReadCharm(charmPath) 133 if err != nil { 134 return nil, err 135 } 136 return ch, nil 137 }