github.com/altoros/juju-vmware@v0.0.0-20150312064031-f19ae857ccca/api/uniter/service.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/names" 10 "gopkg.in/juju/charm.v4" 11 12 "github.com/juju/juju/api/common" 13 "github.com/juju/juju/api/watcher" 14 "github.com/juju/juju/apiserver/params" 15 ) 16 17 // This module implements a subset of the interface provided by 18 // state.Service, as needed by the uniter API. 19 20 // Service represents the state of a service. 21 type Service struct { 22 st *State 23 tag names.ServiceTag 24 life params.Life 25 } 26 27 // Tag returns the service's tag. 28 func (s *Service) Tag() names.ServiceTag { 29 return s.tag 30 } 31 32 // Name returns the service name. 33 func (s *Service) Name() string { 34 return s.tag.Id() 35 } 36 37 // String returns the service as a string. 38 func (s *Service) String() string { 39 return s.Name() 40 } 41 42 // Watch returns a watcher for observing changes to a service. 43 func (s *Service) Watch() (watcher.NotifyWatcher, error) { 44 return common.Watch(s.st.facade, s.tag) 45 } 46 47 // WatchRelations returns a StringsWatcher that notifies of changes to 48 // the lifecycles of relations involving s. 49 func (s *Service) WatchRelations() (watcher.StringsWatcher, error) { 50 var results params.StringsWatchResults 51 args := params.Entities{ 52 Entities: []params.Entity{{Tag: s.tag.String()}}, 53 } 54 err := s.st.facade.FacadeCall("WatchServiceRelations", args, &results) 55 if err != nil { 56 return nil, err 57 } 58 if len(results.Results) != 1 { 59 return nil, fmt.Errorf("expected 1 result, got %d", len(results.Results)) 60 } 61 result := results.Results[0] 62 if result.Error != nil { 63 return nil, result.Error 64 } 65 w := watcher.NewStringsWatcher(s.st.facade.RawAPICaller(), result) 66 return w, nil 67 } 68 69 // Life returns the service's current life state. 70 func (s *Service) Life() params.Life { 71 return s.life 72 } 73 74 // Refresh refreshes the contents of the Service from the underlying 75 // state. 76 func (s *Service) Refresh() error { 77 life, err := s.st.life(s.tag) 78 if err != nil { 79 return err 80 } 81 s.life = life 82 return nil 83 } 84 85 // CharmURL returns the service's charm URL, and whether units should 86 // upgrade to the charm with that URL even if they are in an error 87 // state (force flag). 88 // 89 // NOTE: This differs from state.Service.CharmURL() by returning 90 // an error instead as well, because it needs to make an API call. 91 func (s *Service) CharmURL() (*charm.URL, bool, error) { 92 var results params.StringBoolResults 93 args := params.Entities{ 94 Entities: []params.Entity{{Tag: s.tag.String()}}, 95 } 96 err := s.st.facade.FacadeCall("CharmURL", args, &results) 97 if err != nil { 98 return nil, false, err 99 } 100 if len(results.Results) != 1 { 101 return nil, false, fmt.Errorf("expected 1 result, got %d", len(results.Results)) 102 } 103 result := results.Results[0] 104 if result.Error != nil { 105 return nil, false, result.Error 106 } 107 if result.Result != "" { 108 curl, err := charm.ParseURL(result.Result) 109 if err != nil { 110 return nil, false, err 111 } 112 return curl, result.Ok, nil 113 } 114 return nil, false, fmt.Errorf("%q has no charm url set", s.tag) 115 } 116 117 // OwnerTag returns the service's owner user tag. 118 func (s *Service) OwnerTag() (names.UserTag, error) { 119 if s.st.BestAPIVersion() > 0 { 120 return s.serviceOwnerTag() 121 } 122 return s.ownerTag() 123 } 124 125 func (s *Service) serviceOwnerTag() (names.UserTag, error) { 126 var invalidTag names.UserTag 127 var results params.StringResults 128 args := params.Entities{ 129 Entities: []params.Entity{{Tag: s.tag.String()}}, 130 } 131 err := s.st.facade.FacadeCall("ServiceOwner", args, &results) 132 if err != nil { 133 return invalidTag, err 134 } 135 if len(results.Results) != 1 { 136 return invalidTag, fmt.Errorf("expected 1 result, got %d", len(results.Results)) 137 } 138 result := results.Results[0] 139 if result.Error != nil { 140 return invalidTag, result.Error 141 } 142 return names.ParseUserTag(result.Result) 143 } 144 145 func (s *Service) ownerTag() (names.UserTag, error) { 146 var invalidTag names.UserTag 147 var result params.StringResult 148 args := params.Entities{ 149 Entities: []params.Entity{{Tag: s.tag.String()}}, 150 } 151 err := s.st.facade.FacadeCall("GetOwnerTag", args, &result) 152 if err != nil { 153 return invalidTag, err 154 } 155 if result.Error != nil { 156 return invalidTag, result.Error 157 } 158 return names.ParseUserTag(result.Result) 159 }