github.com/wallyworld/juju@v0.0.0-20161013125918-6cf1bc9d917a/api/uniter/application.go (about) 1 // Copyright 2013 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package uniter 5 6 import ( 7 "fmt" 8 9 "github.com/juju/errors" 10 "gopkg.in/juju/charm.v6-unstable" 11 "gopkg.in/juju/names.v2" 12 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" 18 ) 19 20 // This module implements a subset of the interface provided by 21 // state.Application, as needed by the uniter API. 22 23 // Application represents the state of an application. 24 type Application struct { 25 st *State 26 tag names.ApplicationTag 27 life params.Life 28 } 29 30 // Tag returns the application's tag. 31 func (s *Application) Tag() names.ApplicationTag { 32 return s.tag 33 } 34 35 // Name returns the application name. 36 func (s *Application) Name() string { 37 return s.tag.Id() 38 } 39 40 // String returns the application as a string. 41 func (s *Application) String() string { 42 return s.Name() 43 } 44 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) 48 } 49 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()}}, 56 } 57 err := s.st.facade.FacadeCall("WatchApplicationRelations", args, &results) 58 if err != nil { 59 return nil, err 60 } 61 if len(results.Results) != 1 { 62 return nil, fmt.Errorf("expected 1 result, got %d", len(results.Results)) 63 } 64 result := results.Results[0] 65 if result.Error != nil { 66 return nil, result.Error 67 } 68 w := apiwatcher.NewStringsWatcher(s.st.facade.RawAPICaller(), result) 69 return w, nil 70 } 71 72 // Life returns the application's current life state. 73 func (s *Application) Life() params.Life { 74 return s.life 75 } 76 77 // Refresh refreshes the contents of the Service from the underlying 78 // state. 79 func (s *Application) Refresh() error { 80 life, err := s.st.life(s.tag) 81 if err != nil { 82 return err 83 } 84 s.life = life 85 return nil 86 } 87 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()}}, 94 } 95 err := s.st.facade.FacadeCall("CharmModifiedVersion", args, &results) 96 if err != nil { 97 return -1, err 98 } 99 100 if len(results.Results) != 1 { 101 return -1, fmt.Errorf("expected 1 result, got %d", len(results.Results)) 102 } 103 result := results.Results[0] 104 if result.Error != nil { 105 return -1, result.Error 106 } 107 108 return result.Result, nil 109 } 110 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). 114 // 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()}}, 121 } 122 err := s.st.facade.FacadeCall("CharmURL", args, &results) 123 if err != nil { 124 return nil, false, err 125 } 126 if len(results.Results) != 1 { 127 return nil, false, fmt.Errorf("expected 1 result, got %d", len(results.Results)) 128 } 129 result := results.Results[0] 130 if result.Error != nil { 131 return nil, false, result.Error 132 } 133 if result.Result != "" { 134 curl, err := charm.ParseURL(result.Result) 135 if err != nil { 136 return nil, false, err 137 } 138 return curl, result.Ok, nil 139 } 140 return nil, false, fmt.Errorf("%q has no charm url set", s.tag) 141 } 142 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{ 150 { 151 Tag: tag.String(), 152 Status: serviceStatus.String(), 153 Info: info, 154 Data: data, 155 }, 156 }, 157 } 158 err := s.st.facade.FacadeCall("SetApplicationStatus", args, &result) 159 if err != nil { 160 return errors.Trace(err) 161 } 162 return result.OneError() 163 } 164 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{ 172 { 173 Tag: tag.String(), 174 }, 175 }, 176 } 177 err := s.st.facade.FacadeCall("ApplicationStatus", args, &results) 178 if err != nil { 179 return params.ApplicationStatusResult{}, errors.Trace(err) 180 } 181 result := results.Results[0] 182 if result.Error != nil { 183 return params.ApplicationStatusResult{}, result.Error 184 } 185 return result, nil 186 } 187 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()) 192 }