github.com/juju/juju@v0.0.0-20240430160146-1752b71fcf00/api/agent/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 "github.com/juju/names/v5" 11 12 "github.com/juju/juju/api/common" 13 "github.com/juju/juju/core/life" 14 "github.com/juju/juju/core/status" 15 "github.com/juju/juju/core/watcher" 16 "github.com/juju/juju/rpc/params" 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 life.Value 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() life.Value { 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() (string, 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 "", false, err 102 } 103 if len(results.Results) != 1 { 104 return "", false, fmt.Errorf("expected 1 result, got %d", len(results.Results)) 105 } 106 result := results.Results[0] 107 if result.Error != nil { 108 return "", false, result.Error 109 } 110 if result.Result != "" { 111 return result.Result, result.Ok, nil 112 } 113 return "", false, fmt.Errorf("%q has no charm url set", s.tag) 114 } 115 116 // SetStatus sets the status of the application if the passed unitName, 117 // corresponding to the calling unit, is of the leader. 118 func (s *Application) SetStatus(unitName string, appStatus status.Status, info string, data map[string]interface{}) error { 119 tag := names.NewUnitTag(unitName) 120 var result params.ErrorResults 121 args := params.SetStatus{ 122 Entities: []params.EntityStatusArgs{ 123 { 124 Tag: tag.String(), 125 Status: appStatus.String(), 126 Info: info, 127 Data: data, 128 }, 129 }, 130 } 131 err := s.st.facade.FacadeCall("SetApplicationStatus", args, &result) 132 if err != nil { 133 return errors.Trace(err) 134 } 135 return result.OneError() 136 } 137 138 // Status returns the status of the application if the passed unitName, 139 // corresponding to the calling unit, is of the leader. 140 func (s *Application) Status(unitName string) (params.ApplicationStatusResult, error) { 141 tag := names.NewUnitTag(unitName) 142 var results params.ApplicationStatusResults 143 args := params.Entities{ 144 Entities: []params.Entity{ 145 { 146 Tag: tag.String(), 147 }, 148 }, 149 } 150 err := s.st.facade.FacadeCall("ApplicationStatus", args, &results) 151 if err != nil { 152 return params.ApplicationStatusResult{}, errors.Trace(err) 153 } 154 result := results.Results[0] 155 if result.Error != nil { 156 return params.ApplicationStatusResult{}, result.Error 157 } 158 return result, nil 159 } 160 161 // WatchLeadershipSettings returns a watcher which can be used to wait 162 // for leadership settings changes to be made for the application. 163 func (s *Application) WatchLeadershipSettings() (watcher.NotifyWatcher, error) { 164 return s.st.LeadershipSettings.WatchLeadershipSettings(s.tag.Id()) 165 }