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  }