github.com/niedbalski/juju@v0.0.0-20190215020005-8ff100488e47/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" 11 "gopkg.in/juju/names.v2" 12 13 "github.com/juju/juju/api/common" 14 "github.com/juju/juju/apiserver/params" 15 "github.com/juju/juju/core/status" 16 "github.com/juju/juju/core/watcher" 17 ) 18 19 // This module implements a subset of the interface provided by 20 // state.Application, as needed by the uniter API. 21 22 // Application represents the state of an application. 23 type Application struct { 24 st *State 25 tag names.ApplicationTag 26 life params.Life 27 } 28 29 // Tag returns the application's tag. 30 func (s *Application) Tag() names.ApplicationTag { 31 return s.tag 32 } 33 34 // Name returns the application name. 35 func (s *Application) Name() string { 36 return s.tag.Id() 37 } 38 39 // String returns the application as a string. 40 func (s *Application) String() string { 41 return s.Name() 42 } 43 44 // Watch returns a watcher for observing changes to an application. 45 func (s *Application) Watch() (watcher.NotifyWatcher, error) { 46 return common.Watch(s.st.facade, "Watch", s.tag) 47 } 48 49 // Life returns the application's current life state. 50 func (s *Application) Life() params.Life { 51 return s.life 52 } 53 54 // Refresh refreshes the contents of the application from the underlying 55 // state. 56 func (s *Application) Refresh() error { 57 life, err := s.st.life(s.tag) 58 if err != nil { 59 return err 60 } 61 s.life = life 62 return nil 63 } 64 65 // CharmModifiedVersion increments every time the charm, or any part of it, is 66 // changed in some way. 67 func (s *Application) CharmModifiedVersion() (int, error) { 68 var results params.IntResults 69 args := params.Entities{ 70 Entities: []params.Entity{{Tag: s.tag.String()}}, 71 } 72 err := s.st.facade.FacadeCall("CharmModifiedVersion", args, &results) 73 if err != nil { 74 return -1, err 75 } 76 77 if len(results.Results) != 1 { 78 return -1, fmt.Errorf("expected 1 result, got %d", len(results.Results)) 79 } 80 result := results.Results[0] 81 if result.Error != nil { 82 return -1, result.Error 83 } 84 85 return result.Result, nil 86 } 87 88 // CharmURL returns the application's charm URL, and whether units should 89 // upgrade to the charm with that URL even if they are in an error 90 // state (force flag). 91 // 92 // NOTE: This differs from state.Application.CharmURL() by returning 93 // an error instead as well, because it needs to make an API call. 94 func (s *Application) CharmURL() (*charm.URL, bool, error) { 95 var results params.StringBoolResults 96 args := params.Entities{ 97 Entities: []params.Entity{{Tag: s.tag.String()}}, 98 } 99 err := s.st.facade.FacadeCall("CharmURL", args, &results) 100 if err != nil { 101 return nil, false, err 102 } 103 if len(results.Results) != 1 { 104 return nil, false, fmt.Errorf("expected 1 result, got %d", len(results.Results)) 105 } 106 result := results.Results[0] 107 if result.Error != nil { 108 return nil, false, result.Error 109 } 110 if result.Result != "" { 111 curl, err := charm.ParseURL(result.Result) 112 if err != nil { 113 return nil, false, err 114 } 115 return curl, result.Ok, nil 116 } 117 return nil, false, fmt.Errorf("%q has no charm url set", s.tag) 118 } 119 120 // SetStatus sets the status of the application if the passed unitName, 121 // corresponding to the calling unit, is of the leader. 122 func (s *Application) SetStatus(unitName string, appStatus status.Status, info string, data map[string]interface{}) error { 123 tag := names.NewUnitTag(unitName) 124 var result params.ErrorResults 125 args := params.SetStatus{ 126 Entities: []params.EntityStatusArgs{ 127 { 128 Tag: tag.String(), 129 Status: appStatus.String(), 130 Info: info, 131 Data: data, 132 }, 133 }, 134 } 135 err := s.st.facade.FacadeCall("SetApplicationStatus", args, &result) 136 if err != nil { 137 return errors.Trace(err) 138 } 139 return result.OneError() 140 } 141 142 // Status returns the status of the application if the passed unitName, 143 // corresponding to the calling unit, is of the leader. 144 func (s *Application) Status(unitName string) (params.ApplicationStatusResult, error) { 145 tag := names.NewUnitTag(unitName) 146 var results params.ApplicationStatusResults 147 args := params.Entities{ 148 Entities: []params.Entity{ 149 { 150 Tag: tag.String(), 151 }, 152 }, 153 } 154 err := s.st.facade.FacadeCall("ApplicationStatus", args, &results) 155 if err != nil { 156 return params.ApplicationStatusResult{}, errors.Trace(err) 157 } 158 result := results.Results[0] 159 if result.Error != nil { 160 return params.ApplicationStatusResult{}, result.Error 161 } 162 return result, nil 163 } 164 165 // WatchLeadershipSettings returns a watcher which can be used to wait 166 // for leadership settings changes to be made for the application. 167 func (s *Application) WatchLeadershipSettings() (watcher.NotifyWatcher, error) { 168 return s.st.LeadershipSettings.WatchLeadershipSettings(s.tag.Id()) 169 }