1
// Copyright 2016 Canonical Ltd.
2
// Licensed under the LGPLv3, see LICENCE file for details.
7
"github.com/juju/errors"
8
"gopkg.in/juju/names.v2"
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"
18
// Backend exposes information about any current model migrations.
19
type Backend interface {
21
MigrationPhase() (migration.Phase, error)
22
WatchMigrationPhase() state.NotifyWatcher
25
// Facade lets clients watch and get models' migration phases.
28
resources facade.Resources
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
44
// auth is very simplistic: it only accepts the model tag reported by
46
func (facade *Facade) auth(tagString string) error {
47
tag, err := names.ParseModelTag(tagString)
49
return errors.Trace(err)
51
if tag.Id() != facade.backend.ModelUUID() {
57
// Phase returns the current migration phase or an error for every
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),
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)
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)
77
phase, err := facade.backend.MigrationPhase()
79
return "", errors.Trace(err)
81
return phase.String(), nil
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),
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)
99
// oneWatch does auth, and watcher creation/registration, for a single
101
func (facade *Facade) oneWatch(tagString string) (string, error) {
102
if err := facade.auth(tagString); err != nil {
103
return "", errors.Trace(err)
105
watch := facade.backend.WatchMigrationPhase()
106
if _, ok := <-watch.Changes(); ok {
107
return facade.resources.Register(watch), nil
109
return "", watcher.EnsureErr(watch)