~nskaggs/+junk/xenial-test

« back to all changes in this revision

Viewing changes to src/github.com/juju/juju/apiserver/migrationflag/facade.go

  • Committer: Nicholas Skaggs
  • Date: 2016-10-24 20:56:05 UTC
  • Revision ID: nicholas.skaggs@canonical.com-20161024205605-z8lta0uvuhtxwzwl
Initi with beta15

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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
}