1
// Copyright 2013 Canonical Ltd.
2
// Licensed under the AGPLv3, see LICENCE file for details.
9
"github.com/juju/errors"
10
"gopkg.in/juju/charm.v6-unstable"
11
"gopkg.in/juju/names.v2"
13
"github.com/juju/juju/api/common"
14
apiwatcher "github.com/juju/juju/api/watcher"
15
"github.com/juju/juju/apiserver/params"
16
"github.com/juju/juju/status"
17
"github.com/juju/juju/watcher"
20
// This module implements a subset of the interface provided by
21
// state.Application, as needed by the uniter API.
23
// Application represents the state of an application.
24
type Application struct {
26
tag names.ApplicationTag
30
// Tag returns the application's tag.
31
func (s *Application) Tag() names.ApplicationTag {
35
// Name returns the application name.
36
func (s *Application) Name() string {
40
// String returns the application as a string.
41
func (s *Application) String() string {
45
// Watch returns a watcher for observing changes to an application.
46
func (s *Application) Watch() (watcher.NotifyWatcher, error) {
47
return common.Watch(s.st.facade, s.tag)
50
// WatchRelations returns a StringsWatcher that notifies of changes to
51
// the lifecycles of relations involving s.
52
func (s *Application) WatchRelations() (watcher.StringsWatcher, error) {
53
var results params.StringsWatchResults
54
args := params.Entities{
55
Entities: []params.Entity{{Tag: s.tag.String()}},
57
err := s.st.facade.FacadeCall("WatchApplicationRelations", args, &results)
61
if len(results.Results) != 1 {
62
return nil, fmt.Errorf("expected 1 result, got %d", len(results.Results))
64
result := results.Results[0]
65
if result.Error != nil {
66
return nil, result.Error
68
w := apiwatcher.NewStringsWatcher(s.st.facade.RawAPICaller(), result)
72
// Life returns the application's current life state.
73
func (s *Application) Life() params.Life {
77
// Refresh refreshes the contents of the Service from the underlying
79
func (s *Application) Refresh() error {
80
life, err := s.st.life(s.tag)
88
// CharmModifiedVersion increments every time the charm, or any part of it, is
89
// changed in some way.
90
func (s *Application) CharmModifiedVersion() (int, error) {
91
var results params.IntResults
92
args := params.Entities{
93
Entities: []params.Entity{{Tag: s.tag.String()}},
95
err := s.st.facade.FacadeCall("CharmModifiedVersion", args, &results)
100
if len(results.Results) != 1 {
101
return -1, fmt.Errorf("expected 1 result, got %d", len(results.Results))
103
result := results.Results[0]
104
if result.Error != nil {
105
return -1, result.Error
108
return result.Result, nil
111
// CharmURL returns the service's charm URL, and whether units should
112
// upgrade to the charm with that URL even if they are in an error
113
// state (force flag).
115
// NOTE: This differs from state.Service.CharmURL() by returning
116
// an error instead as well, because it needs to make an API call.
117
func (s *Application) CharmURL() (*charm.URL, bool, error) {
118
var results params.StringBoolResults
119
args := params.Entities{
120
Entities: []params.Entity{{Tag: s.tag.String()}},
122
err := s.st.facade.FacadeCall("CharmURL", args, &results)
124
return nil, false, err
126
if len(results.Results) != 1 {
127
return nil, false, fmt.Errorf("expected 1 result, got %d", len(results.Results))
129
result := results.Results[0]
130
if result.Error != nil {
131
return nil, false, result.Error
133
if result.Result != "" {
134
curl, err := charm.ParseURL(result.Result)
136
return nil, false, err
138
return curl, result.Ok, nil
140
return nil, false, fmt.Errorf("%q has no charm url set", s.tag)
143
// SetStatus sets the status of the service if the passed unitName,
144
// corresponding to the calling unit, is of the leader.
145
func (s *Application) SetStatus(unitName string, serviceStatus status.Status, info string, data map[string]interface{}) error {
146
tag := names.NewUnitTag(unitName)
147
var result params.ErrorResults
148
args := params.SetStatus{
149
Entities: []params.EntityStatusArgs{
152
Status: serviceStatus.String(),
158
err := s.st.facade.FacadeCall("SetApplicationStatus", args, &result)
160
return errors.Trace(err)
162
return result.OneError()
165
// Status returns the status of the service if the passed unitName,
166
// corresponding to the calling unit, is of the leader.
167
func (s *Application) Status(unitName string) (params.ApplicationStatusResult, error) {
168
tag := names.NewUnitTag(unitName)
169
var results params.ApplicationStatusResults
170
args := params.Entities{
171
Entities: []params.Entity{
177
err := s.st.facade.FacadeCall("ApplicationStatus", args, &results)
179
return params.ApplicationStatusResult{}, errors.Trace(err)
181
result := results.Results[0]
182
if result.Error != nil {
183
return params.ApplicationStatusResult{}, result.Error
188
// WatchLeadershipSettings returns a watcher which can be used to wait
189
// for leadership settings changes to be made for the application.
190
func (s *Application) WatchLeadershipSettings() (watcher.NotifyWatcher, error) {
191
return s.st.LeadershipSettings.WatchLeadershipSettings(s.tag.Id())