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 }