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

     1  // Copyright 2016 Canonical Ltd.
     2  // Licensed under the LGPLv3, see LICENCE file for details.
     3  
     4  package migrationflag
     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/core/migration"
    14  	"github.com/juju/juju/state"
    15  	"github.com/juju/juju/state/watcher"
    16  )
    17  
    18  // Backend exposes information about any current model migrations.
    19  type Backend interface {
    20  	ModelUUID() string
    21  	MigrationPhase() (migration.Phase, error)
    22  	WatchMigrationPhase() state.NotifyWatcher
    23  }
    24  
    25  // Facade lets clients watch and get models' migration phases.
    26  type Facade struct {
    27  	backend   Backend
    28  	resources facade.Resources
    29  }
    30  
    31  // New creates a Facade backed by backend and resources. If auth
    32  // doesn't identity the client as a machine agent or a unit agent,
    33  // it will return common.ErrPerm.
    34  func New(backend Backend, resources facade.Resources, auth facade.Authorizer) (*Facade, error) {
    35  	if !auth.AuthMachineAgent() && !auth.AuthUnitAgent() {
    36  		return nil, common.ErrPerm
    37  	}
    38  	return &Facade{
    39  		backend:   backend,
    40  		resources: resources,
    41  	}, nil
    42  }
    43  
    44  // auth is very simplistic: it only accepts the model tag reported by
    45  // the backend.
    46  func (facade *Facade) auth(tagString string) error {
    47  	tag, err := names.ParseModelTag(tagString)
    48  	if err != nil {
    49  		return errors.Trace(err)
    50  	}
    51  	if tag.Id() != facade.backend.ModelUUID() {
    52  		return common.ErrPerm
    53  	}
    54  	return nil
    55  }
    56  
    57  // Phase returns the current migration phase or an error for every
    58  // supplied entity.
    59  func (facade *Facade) Phase(entities params.Entities) params.PhaseResults {
    60  	count := len(entities.Entities)
    61  	results := params.PhaseResults{
    62  		Results: make([]params.PhaseResult, count),
    63  	}
    64  	for i, entity := range entities.Entities {
    65  		phase, err := facade.onePhase(entity.Tag)
    66  		results.Results[i].Phase = phase
    67  		results.Results[i].Error = common.ServerError(err)
    68  	}
    69  	return results
    70  }
    71  
    72  // onePhase does auth and lookup for a single entity.
    73  func (facade *Facade) onePhase(tagString string) (string, error) {
    74  	if err := facade.auth(tagString); err != nil {
    75  		return "", errors.Trace(err)
    76  	}
    77  	phase, err := facade.backend.MigrationPhase()
    78  	if err != nil {
    79  		return "", errors.Trace(err)
    80  	}
    81  	return phase.String(), nil
    82  }
    83  
    84  // Watch returns an id for use with the NotifyWatcher facade, or an
    85  // error, for every supplied entity.
    86  func (facade *Facade) Watch(entities params.Entities) params.NotifyWatchResults {
    87  	count := len(entities.Entities)
    88  	results := params.NotifyWatchResults{
    89  		Results: make([]params.NotifyWatchResult, count),
    90  	}
    91  	for i, entity := range entities.Entities {
    92  		id, err := facade.oneWatch(entity.Tag)
    93  		results.Results[i].NotifyWatcherId = id
    94  		results.Results[i].Error = common.ServerError(err)
    95  	}
    96  	return results
    97  }
    98  
    99  // oneWatch does auth, and watcher creation/registration, for a single
   100  // entity.
   101  func (facade *Facade) oneWatch(tagString string) (string, error) {
   102  	if err := facade.auth(tagString); err != nil {
   103  		return "", errors.Trace(err)
   104  	}
   105  	watch := facade.backend.WatchMigrationPhase()
   106  	if _, ok := <-watch.Changes(); ok {
   107  		return facade.resources.Register(watch), nil
   108  	}
   109  	return "", watcher.EnsureErr(watch)
   110  }