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