github.com/wallyworld/juju@v0.0.0-20161013125918-6cf1bc9d917a/apiserver/applicationscaler/facade.go (about)

     1  // Copyright 2016 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package applicationscaler
     5  
     6  import (
     7  	"github.com/juju/errors"
     8  	"github.com/juju/juju/apiserver/common"
     9  	"github.com/juju/juju/apiserver/facade"
    10  	"github.com/juju/juju/apiserver/params"
    11  	"github.com/juju/juju/state"
    12  	"github.com/juju/juju/state/watcher"
    13  	"gopkg.in/juju/names.v2"
    14  )
    15  
    16  // Backend exposes functionality required by Facade.
    17  type Backend interface {
    18  
    19  	// WatchScaledServices returns a watcher that sends service ids
    20  	// that might not have enough units.
    21  	WatchScaledServices() state.StringsWatcher
    22  
    23  	// RescaleService ensures that the named service has at least its
    24  	// configured minimum unit count.
    25  	RescaleService(name string) error
    26  }
    27  
    28  // Facade allows model-manager clients to watch and rescale services.
    29  type Facade struct {
    30  	backend   Backend
    31  	resources facade.Resources
    32  }
    33  
    34  // NewFacade creates a new authorized Facade.
    35  func NewFacade(backend Backend, res facade.Resources, auth facade.Authorizer) (*Facade, error) {
    36  	if !auth.AuthModelManager() {
    37  		return nil, common.ErrPerm
    38  	}
    39  	return &Facade{
    40  		backend:   backend,
    41  		resources: res,
    42  	}, nil
    43  }
    44  
    45  // Watch returns a watcher that sends the names of services whose
    46  // unit count may be below their configured minimum.
    47  func (facade *Facade) Watch() (params.StringsWatchResult, error) {
    48  	watch := facade.backend.WatchScaledServices()
    49  	if changes, ok := <-watch.Changes(); ok {
    50  		id := facade.resources.Register(watch)
    51  		return params.StringsWatchResult{
    52  			StringsWatcherId: id,
    53  			Changes:          changes,
    54  		}, nil
    55  	}
    56  	return params.StringsWatchResult{}, watcher.EnsureErr(watch)
    57  }
    58  
    59  // Rescale causes any supplied services to be scaled up to their
    60  // minimum size.
    61  func (facade *Facade) Rescale(args params.Entities) params.ErrorResults {
    62  	result := params.ErrorResults{
    63  		Results: make([]params.ErrorResult, len(args.Entities)),
    64  	}
    65  	for i, entity := range args.Entities {
    66  		err := facade.rescaleOne(entity.Tag)
    67  		result.Results[i].Error = common.ServerError(err)
    68  	}
    69  	return result
    70  }
    71  
    72  // rescaleOne scales up the supplied service, if necessary; or returns a
    73  // suitable error.
    74  func (facade *Facade) rescaleOne(tagString string) error {
    75  	tag, err := names.ParseTag(tagString)
    76  	if err != nil {
    77  		return errors.Trace(err)
    78  	}
    79  	ApplicationTag, ok := tag.(names.ApplicationTag)
    80  	if !ok {
    81  		return common.ErrPerm
    82  	}
    83  	return facade.backend.RescaleService(ApplicationTag.Id())
    84  }