~nskaggs/+junk/xenial-test

« back to all changes in this revision

Viewing changes to src/github.com/juju/juju/api/agent/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 AGPLv3, see LICENCE file for details.
 
3
 
 
4
package agent
 
5
 
 
6
import (
 
7
        "github.com/juju/errors"
 
8
        "gopkg.in/juju/names.v2"
 
9
 
 
10
        "github.com/juju/juju/api/base"
 
11
        "github.com/juju/juju/apiserver/params"
 
12
)
 
13
 
 
14
// Life is a local representation of entity life. Should probably be
 
15
// in a core/life or core/entity package; and quite probably, so
 
16
// should the ConnFacade interface.
 
17
type Life string
 
18
 
 
19
const (
 
20
        Alive Life = "alive"
 
21
        Dying Life = "dying"
 
22
        Dead  Life = "dead"
 
23
)
 
24
 
 
25
// ConnFacade exposes the parts of the Agent facade needed by the bits
 
26
// that currently live in apicaller. This criterion is every bit as
 
27
// terrible as it sounds -- surely there should be a new facade at the
 
28
// apiserver level somewhere? -- but:
 
29
//  1) this feels like a convenient/transitional method grouping, not a
 
30
//     fundamental *role*; and
 
31
//  2) at least it's a narrowed interface, and eschews the object-style
 
32
//     sins of *State/*Entity.
 
33
// Progress not perfection.
 
34
type ConnFacade interface {
 
35
 
 
36
        // Life returns Alive, Dying, Dead, ErrDenied, or some other error.
 
37
        Life(names.Tag) (Life, error)
 
38
 
 
39
        // SetPassword returns nil, ErrDenied, or some other error.
 
40
        SetPassword(names.Tag, string) error
 
41
}
 
42
 
 
43
// ErrDenied is returned by Life and SetPassword to indicate that the
 
44
// requested operation is impossible (and hence that the entity is
 
45
// either dead or gone, and in either case that no further meaningful
 
46
// interaction is possible).
 
47
var ErrDenied = errors.New("entity operation impossible")
 
48
 
 
49
// NewConnFacade returns a ConnFacade backed by the supplied APICaller.
 
50
func NewConnFacade(caller base.APICaller) (ConnFacade, error) {
 
51
        facadeCaller := base.NewFacadeCaller(caller, "Agent")
 
52
        return &connFacade{
 
53
                caller: facadeCaller,
 
54
        }, nil
 
55
}
 
56
 
 
57
// connFacade implements ConnFacade.
 
58
type connFacade struct {
 
59
        caller base.FacadeCaller
 
60
}
 
61
 
 
62
// Life is part of the ConnFacade interface.
 
63
func (facade *connFacade) Life(entity names.Tag) (Life, error) {
 
64
        var results params.AgentGetEntitiesResults
 
65
        args := params.Entities{
 
66
                Entities: []params.Entity{{Tag: entity.String()}},
 
67
        }
 
68
        err := facade.caller.FacadeCall("GetEntities", args, &results)
 
69
        if err != nil {
 
70
                return "", errors.Trace(err)
 
71
        }
 
72
        if len(results.Entities) != 1 {
 
73
                return "", errors.Errorf("expected 1 result, got %d", len(results.Entities))
 
74
        }
 
75
        if err := results.Entities[0].Error; err != nil {
 
76
                if params.IsCodeNotFoundOrCodeUnauthorized(err) {
 
77
                        return "", ErrDenied
 
78
                }
 
79
                return "", errors.Trace(err)
 
80
        }
 
81
        life := Life(results.Entities[0].Life)
 
82
        switch life {
 
83
        case Alive, Dying, Dead:
 
84
                return life, nil
 
85
        }
 
86
        return "", errors.Errorf("unknown life value %q", life)
 
87
}
 
88
 
 
89
// SetPassword is part of the ConnFacade interface.
 
90
func (facade *connFacade) SetPassword(entity names.Tag, password string) error {
 
91
        var results params.ErrorResults
 
92
        args := params.EntityPasswords{
 
93
                Changes: []params.EntityPassword{{
 
94
                        Tag:      entity.String(),
 
95
                        Password: password,
 
96
                }},
 
97
        }
 
98
        err := facade.caller.FacadeCall("SetPasswords", args, &results)
 
99
        if err != nil {
 
100
                return errors.Trace(err)
 
101
        }
 
102
        if len(results.Results) != 1 {
 
103
                return errors.Errorf("expected 1 result, got %d", len(results.Results))
 
104
        }
 
105
        if err := results.Results[0].Error; err != nil {
 
106
                if params.IsCodeDead(err) {
 
107
                        return ErrDenied
 
108
                } else if params.IsCodeNotFoundOrCodeUnauthorized(err) {
 
109
                        return ErrDenied
 
110
                }
 
111
                return errors.Trace(err)
 
112
        }
 
113
        return nil
 
114
}