github.com/axw/juju@v0.0.0-20161005053422-4bd6544d08d4/apiserver/machineactions/machineactions.go (about) 1 // Copyright 2016 Canonical Ltd. 2 // Copyright 2016 Cloudbase Solutions 3 // Licensed under the AGPLv3, see LICENCE file for details. 4 5 // machineactions implements the the apiserver side of 6 // running actions on machines 7 package machineactions 8 9 import ( 10 "github.com/juju/juju/apiserver/common" 11 "github.com/juju/juju/apiserver/facade" 12 "github.com/juju/juju/apiserver/params" 13 "github.com/juju/juju/state" 14 "gopkg.in/juju/names.v2" 15 ) 16 17 type Backend interface { 18 ActionByTag(tag names.ActionTag) (state.Action, error) 19 FindEntity(tag names.Tag) (state.Entity, error) 20 TagToActionReceiverFn(findEntity func(names.Tag) (state.Entity, error)) func(string) (state.ActionReceiver, error) 21 ConvertActions(ar state.ActionReceiver, fn common.GetActionsFn) ([]params.ActionResult, error) 22 } 23 24 // Facade implements the machineactions interface and is the concrete 25 // implementation of the api end point. 26 type Facade struct { 27 backend Backend 28 resources facade.Resources 29 accessMachine common.AuthFunc 30 } 31 32 // NewFacade creates a new server-side machineactions API end point. 33 func NewFacade( 34 backend Backend, 35 resources facade.Resources, 36 authorizer facade.Authorizer, 37 ) (*Facade, error) { 38 if !authorizer.AuthMachineAgent() { 39 return nil, common.ErrPerm 40 } 41 return &Facade{ 42 backend: backend, 43 resources: resources, 44 accessMachine: authorizer.AuthOwner, 45 }, nil 46 } 47 48 // Actions returns the Actions by Tags passed and ensures that the machine asking 49 // for them is the machine that has the actions 50 func (f *Facade) Actions(args params.Entities) params.ActionResults { 51 actionFn := common.AuthAndActionFromTagFn(f.accessMachine, f.backend.ActionByTag) 52 return common.Actions(args, actionFn) 53 } 54 55 // BeginActions marks the actions represented by the passed in Tags as running. 56 func (f *Facade) BeginActions(args params.Entities) params.ErrorResults { 57 actionFn := common.AuthAndActionFromTagFn(f.accessMachine, f.backend.ActionByTag) 58 return common.BeginActions(args, actionFn) 59 } 60 61 // FinishActions saves the result of a completed Action 62 func (f *Facade) FinishActions(args params.ActionExecutionResults) params.ErrorResults { 63 actionFn := common.AuthAndActionFromTagFn(f.accessMachine, f.backend.ActionByTag) 64 return common.FinishActions(args, actionFn) 65 } 66 67 // WatchActionNotifications returns a StringsWatcher for observing 68 // incoming action calls to a machine. 69 func (f *Facade) WatchActionNotifications(args params.Entities) params.StringsWatchResults { 70 tagToActionReceiver := f.backend.TagToActionReceiverFn(f.backend.FindEntity) 71 watchOne := common.WatchOneActionReceiverNotifications(tagToActionReceiver, f.resources.Register) 72 return common.WatchActionNotifications(args, f.accessMachine, watchOne) 73 } 74 75 // RunningActions lists the actions running for the entities passed in. 76 // If we end up needing more than ListRunning at some point we could follow/abstract 77 // what's done in the client actions package. 78 func (f *Facade) RunningActions(args params.Entities) params.ActionsByReceivers { 79 canAccess := f.accessMachine 80 tagToActionReceiver := f.backend.TagToActionReceiverFn(f.backend.FindEntity) 81 82 response := params.ActionsByReceivers{ 83 Actions: make([]params.ActionsByReceiver, len(args.Entities)), 84 } 85 86 for i, entity := range args.Entities { 87 currentResult := &response.Actions[i] 88 receiver, err := tagToActionReceiver(entity.Tag) 89 if err != nil { 90 currentResult.Error = common.ServerError(common.ErrBadId) 91 continue 92 } 93 currentResult.Receiver = receiver.Tag().String() 94 95 if !canAccess(receiver.Tag()) { 96 currentResult.Error = common.ServerError(common.ErrPerm) 97 continue 98 } 99 100 results, err := f.backend.ConvertActions(receiver, receiver.RunningActions) 101 if err != nil { 102 currentResult.Error = common.ServerError(err) 103 continue 104 } 105 currentResult.Actions = results 106 } 107 108 return response 109 }