1
// Copyright 2016 Canonical Ltd.
2
// Licensed under the AGPLv3, see LICENCE file for details.
7
"github.com/juju/errors"
8
"gopkg.in/juju/names.v2"
10
"github.com/juju/juju/api/base"
11
"github.com/juju/juju/apiserver/params"
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.
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 {
36
// Life returns Alive, Dying, Dead, ErrDenied, or some other error.
37
Life(names.Tag) (Life, error)
39
// SetPassword returns nil, ErrDenied, or some other error.
40
SetPassword(names.Tag, string) error
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")
49
// NewConnFacade returns a ConnFacade backed by the supplied APICaller.
50
func NewConnFacade(caller base.APICaller) (ConnFacade, error) {
51
facadeCaller := base.NewFacadeCaller(caller, "Agent")
57
// connFacade implements ConnFacade.
58
type connFacade struct {
59
caller base.FacadeCaller
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()}},
68
err := facade.caller.FacadeCall("GetEntities", args, &results)
70
return "", errors.Trace(err)
72
if len(results.Entities) != 1 {
73
return "", errors.Errorf("expected 1 result, got %d", len(results.Entities))
75
if err := results.Entities[0].Error; err != nil {
76
if params.IsCodeNotFoundOrCodeUnauthorized(err) {
79
return "", errors.Trace(err)
81
life := Life(results.Entities[0].Life)
83
case Alive, Dying, Dead:
86
return "", errors.Errorf("unknown life value %q", life)
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{{
98
err := facade.caller.FacadeCall("SetPasswords", args, &results)
100
return errors.Trace(err)
102
if len(results.Results) != 1 {
103
return errors.Errorf("expected 1 result, got %d", len(results.Results))
105
if err := results.Results[0].Error; err != nil {
106
if params.IsCodeDead(err) {
108
} else if params.IsCodeNotFoundOrCodeUnauthorized(err) {
111
return errors.Trace(err)