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  }