github.com/niedbalski/juju@v0.0.0-20190215020005-8ff100488e47/apiserver/facades/agent/unitassigner/unitassigner.go (about)

     1  // Copyright 2015 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package unitassigner
     5  
     6  import (
     7  	"github.com/juju/errors"
     8  	"gopkg.in/juju/names.v2"
     9  
    10  	"github.com/juju/juju/apiserver/common"
    11  	"github.com/juju/juju/apiserver/facade"
    12  	"github.com/juju/juju/apiserver/params"
    13  	"github.com/juju/juju/state"
    14  	"github.com/juju/juju/state/watcher"
    15  )
    16  
    17  // assignerState defines the state methods this facade needs, so they can be mocked
    18  // for testing.
    19  type assignerState interface {
    20  	WatchForUnitAssignment() state.StringsWatcher
    21  	AssignStagedUnits(ids []string) ([]state.UnitAssignmentResult, error)
    22  }
    23  
    24  type statusSetter interface {
    25  	SetStatus(args params.SetStatus) (params.ErrorResults, error)
    26  }
    27  
    28  // API implements the functionality for assigning units to machines.
    29  type API struct {
    30  	st           assignerState
    31  	res          facade.Resources
    32  	statusSetter statusSetter
    33  }
    34  
    35  // New returns a new unitAssigner api instance.
    36  func New(st *state.State, res facade.Resources, _ facade.Authorizer) (*API, error) {
    37  	setter := common.NewStatusSetter(&common.UnitAgentFinder{st}, common.AuthAlways())
    38  	return &API{
    39  		st:           st,
    40  		res:          res,
    41  		statusSetter: setter,
    42  	}, nil
    43  }
    44  
    45  //  AssignUnits assigns the units with the given ids to the correct machine. The
    46  //  error results are returned in the same order as the given entities.
    47  func (a *API) AssignUnits(args params.Entities) (params.ErrorResults, error) {
    48  	result := params.ErrorResults{}
    49  
    50  	// state uses ids, but the API uses Tags, so we have to convert back and
    51  	// forth (whee!).  The list of ids is (crucially) in the same order as the
    52  	// list of tags.  This is the same order as the list of errors we return.
    53  	ids := make([]string, len(args.Entities))
    54  	for i, e := range args.Entities {
    55  		tag, err := names.ParseUnitTag(e.Tag)
    56  		if err != nil {
    57  			return result, err
    58  		}
    59  		ids[i] = tag.Id()
    60  	}
    61  
    62  	res, err := a.st.AssignStagedUnits(ids)
    63  	if err != nil {
    64  		return result, common.ServerError(err)
    65  	}
    66  
    67  	// The results come back from state in an undetermined order and do not
    68  	// include results for units that were not found, so we have to make up for
    69  	// that here.
    70  	resultMap := make(map[string]error, len(ids))
    71  	for _, r := range res {
    72  		resultMap[r.Unit] = r.Error
    73  	}
    74  
    75  	result.Results = make([]params.ErrorResult, len(args.Entities))
    76  	for i, id := range ids {
    77  		if err, ok := resultMap[id]; ok {
    78  			result.Results[i].Error = common.ServerError(err)
    79  		} else {
    80  			result.Results[i].Error =
    81  				common.ServerError(errors.NotFoundf("unit %q", args.Entities[i].Tag))
    82  		}
    83  	}
    84  
    85  	return result, nil
    86  }
    87  
    88  // WatchUnitAssignments returns a strings watcher that is notified when new unit
    89  // assignments are added to the db.
    90  func (a *API) WatchUnitAssignments() (params.StringsWatchResult, error) {
    91  	watch := a.st.WatchForUnitAssignment()
    92  	if changes, ok := <-watch.Changes(); ok {
    93  		return params.StringsWatchResult{
    94  			StringsWatcherId: a.res.Register(watch),
    95  			Changes:          changes,
    96  		}, nil
    97  	}
    98  	return params.StringsWatchResult{}, watcher.EnsureErr(watch)
    99  }
   100  
   101  // SetAgentStatus will set status for agents of Units passed in args, if one
   102  // of the args is not an Unit it will fail.
   103  func (a *API) SetAgentStatus(args params.SetStatus) (params.ErrorResults, error) {
   104  	return a.statusSetter.SetStatus(args)
   105  }