github.com/altoros/juju-vmware@v0.0.0-20150312064031-f19ae857ccca/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/errors" 10 "github.com/juju/juju/apiserver/params" 11 "github.com/juju/juju/state" 12 "github.com/juju/names" 13 ) 14 15 // StatusSetter implements a common SetStatus method for use by 16 // various facades. 17 type StatusSetter struct { 18 st state.EntityFinder 19 getCanModify GetAuthFunc 20 } 21 22 // NewStatusSetter returns a new StatusSetter. The GetAuthFunc will be 23 // used on each invocation of SetStatus to determine current 24 // permissions. 25 func NewStatusSetter(st state.EntityFinder, getCanModify GetAuthFunc) *StatusSetter { 26 return &StatusSetter{ 27 st: st, 28 getCanModify: getCanModify, 29 } 30 } 31 32 func (s *StatusSetter) setEntityStatus(tag names.Tag, status params.Status, info string, data map[string]interface{}) error { 33 entity, err := s.st.FindEntity(tag) 34 if err != nil { 35 return err 36 } 37 switch entity := entity.(type) { 38 case state.StatusSetter: 39 return entity.SetStatus(state.Status(status), info, data) 40 default: 41 return NotSupportedError(tag, fmt.Sprintf("setting status, %T", entity)) 42 } 43 } 44 45 // SetStatus sets the status of each given entity. 46 func (s *StatusSetter) SetStatus(args params.SetStatus) (params.ErrorResults, error) { 47 result := params.ErrorResults{ 48 Results: make([]params.ErrorResult, len(args.Entities)), 49 } 50 if len(args.Entities) == 0 { 51 return result, nil 52 } 53 canModify, err := s.getCanModify() 54 if err != nil { 55 return params.ErrorResults{}, err 56 } 57 for i, arg := range args.Entities { 58 tag, err := names.ParseTag(arg.Tag) 59 if err != nil { 60 result.Results[i].Error = ServerError(ErrPerm) 61 continue 62 } 63 err = ErrPerm 64 if canModify(tag) { 65 err = s.setEntityStatus(tag, arg.Status, arg.Info, arg.Data) 66 } 67 result.Results[i].Error = ServerError(err) 68 } 69 return result, nil 70 } 71 72 func (s *StatusSetter) updateEntityStatusData(tag names.Tag, data map[string]interface{}) error { 73 entity0, err := s.st.FindEntity(tag) 74 if err != nil { 75 return err 76 } 77 statusGetter, ok := entity0.(state.StatusGetter) 78 if !ok { 79 return NotSupportedError(tag, "getting status") 80 } 81 existingStatus, existingInfo, existingData, err := statusGetter.Status() 82 if err != nil { 83 return err 84 } 85 newData := existingData 86 if newData == nil { 87 newData = data 88 } else { 89 for k, v := range data { 90 newData[k] = v 91 } 92 } 93 entity, ok := entity0.(state.StatusSetter) 94 if !ok { 95 return NotSupportedError(tag, "updating status") 96 } 97 if len(newData) > 0 && existingStatus != state.StatusError { 98 return fmt.Errorf("%s is not in an error state", names.ReadableString(tag)) 99 } 100 return entity.SetStatus(existingStatus, existingInfo, newData) 101 } 102 103 // UpdateStatus updates the status data of each given entity. 104 func (s *StatusSetter) UpdateStatus(args params.SetStatus) (params.ErrorResults, error) { 105 result := params.ErrorResults{ 106 Results: make([]params.ErrorResult, len(args.Entities)), 107 } 108 if len(args.Entities) == 0 { 109 return result, nil 110 } 111 canModify, err := s.getCanModify() 112 if err != nil { 113 return params.ErrorResults{}, errors.Trace(err) 114 } 115 for i, arg := range args.Entities { 116 tag, err := names.ParseTag(arg.Tag) 117 if err != nil { 118 result.Results[i].Error = ServerError(ErrPerm) 119 continue 120 } 121 err = ErrPerm 122 if canModify(tag) { 123 err = s.updateEntityStatusData(tag, arg.Data) 124 } 125 result.Results[i].Error = ServerError(err) 126 } 127 return result, nil 128 }