github.com/mattyw/juju@v0.0.0-20140610034352-732aecd63861/state/apiserver/common/setstatus.go (about) 1 // Copyright 2013 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package common 5 6 import ( 7 "fmt" 8 9 "github.com/juju/juju/state" 10 "github.com/juju/juju/state/api/params" 11 ) 12 13 // StatusSetter implements a common SetStatus method for use by 14 // various facades. 15 type StatusSetter struct { 16 st state.EntityFinder 17 getCanModify GetAuthFunc 18 } 19 20 // NewStatusSetter returns a new StatusSetter. The GetAuthFunc will be 21 // used on each invocation of SetStatus to determine current 22 // permissions. 23 func NewStatusSetter(st state.EntityFinder, getCanModify GetAuthFunc) *StatusSetter { 24 return &StatusSetter{ 25 st: st, 26 getCanModify: getCanModify, 27 } 28 } 29 30 func (s *StatusSetter) setEntityStatus(tag string, status params.Status, info string, data params.StatusData) error { 31 entity0, err := s.st.FindEntity(tag) 32 if err != nil { 33 return err 34 } 35 entity, ok := entity0.(state.StatusSetter) 36 if !ok { 37 return NotSupportedError(tag, "setting status") 38 } 39 return entity.SetStatus(status, info, data) 40 } 41 42 // SetStatus sets the status of each given entity. 43 func (s *StatusSetter) SetStatus(args params.SetStatus) (params.ErrorResults, error) { 44 result := params.ErrorResults{ 45 Results: make([]params.ErrorResult, len(args.Entities)), 46 } 47 if len(args.Entities) == 0 { 48 return result, nil 49 } 50 canModify, err := s.getCanModify() 51 if err != nil { 52 return params.ErrorResults{}, err 53 } 54 for i, arg := range args.Entities { 55 err := ErrPerm 56 if canModify(arg.Tag) { 57 err = s.setEntityStatus(arg.Tag, arg.Status, arg.Info, arg.Data) 58 } 59 result.Results[i].Error = ServerError(err) 60 } 61 return result, nil 62 } 63 64 func (s *StatusSetter) updateEntityStatusData(tag string, data params.StatusData) error { 65 entity0, err := s.st.FindEntity(tag) 66 if err != nil { 67 return err 68 } 69 statusGetter, ok := entity0.(state.StatusGetter) 70 if !ok { 71 return NotSupportedError(tag, "getting status") 72 } 73 existingStatus, existingInfo, existingData, err := statusGetter.Status() 74 if err != nil { 75 return err 76 } 77 newData := existingData 78 if newData == nil { 79 newData = data 80 } else { 81 for k, v := range data { 82 newData[k] = v 83 } 84 } 85 entity, ok := entity0.(state.StatusSetter) 86 if !ok { 87 return NotSupportedError(tag, "updating status") 88 } 89 if len(newData) > 0 && existingStatus != params.StatusError { 90 return fmt.Errorf("machine %q is not in an error state", tag) 91 } 92 return entity.SetStatus(existingStatus, existingInfo, newData) 93 } 94 95 // UpdateStatus updates the status data of each given entity. 96 func (s *StatusSetter) UpdateStatus(args params.SetStatus) (params.ErrorResults, error) { 97 result := params.ErrorResults{ 98 Results: make([]params.ErrorResult, len(args.Entities)), 99 } 100 if len(args.Entities) == 0 { 101 return result, nil 102 } 103 canModify, err := s.getCanModify() 104 if err != nil { 105 return params.ErrorResults{}, err 106 } 107 for i, arg := range args.Entities { 108 err := ErrPerm 109 if canModify(arg.Tag) { 110 err = s.updateEntityStatusData(arg.Tag, arg.Data) 111 } 112 result.Results[i].Error = ServerError(err) 113 } 114 return result, nil 115 }