launchpad.net/~rogpeppe/juju-core/500-errgo-fix@v0.0.0-20140213181702-000000002356/state/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 "launchpad.net/errgo/errors" 10 "launchpad.net/juju-core/charm" 11 "launchpad.net/juju-core/names" 12 "launchpad.net/juju-core/state/api/base" 13 "launchpad.net/juju-core/state/api/params" 14 "launchpad.net/juju-core/state/api/watcher" 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 string 24 life params.Life 25 } 26 27 // Name returns the service name. 28 func (s *Service) Name() string { 29 _, serviceName, err := names.ParseTag(s.tag, names.ServiceTagKind) 30 if err != nil { 31 panic(fmt.Sprintf("%q is not a valid service tag", s.tag)) 32 } 33 return serviceName 34 } 35 36 // String returns the service as a string. 37 func (s *Service) String() string { 38 return s.Name() 39 } 40 41 // Watch returns a watcher for observing changes to a service. 42 func (s *Service) Watch() (watcher.NotifyWatcher, error) { 43 var results params.NotifyWatchResults 44 args := params.Entities{ 45 Entities: []params.Entity{{Tag: s.tag}}, 46 } 47 err := s.st.caller.Call("Uniter", "", "Watch", args, &results) 48 if err != nil { 49 return nil, base.WrapError(err) 50 } 51 if len(results.Results) != 1 { 52 return nil, errors.Newf("expected one result, got %d", len(results.Results)) 53 } 54 result := results.Results[0] 55 if result.Error != nil { 56 return nil, result.Error 57 } 58 w := watcher.NewNotifyWatcher(s.st.caller, result) 59 return w, nil 60 } 61 62 // WatchRelations returns a StringsWatcher that notifies of changes to 63 // the lifecycles of relations involving s. 64 func (s *Service) WatchRelations() (watcher.StringsWatcher, error) { 65 var results params.StringsWatchResults 66 args := params.Entities{ 67 Entities: []params.Entity{{Tag: s.tag}}, 68 } 69 err := s.st.caller.Call("Uniter", "", "WatchServiceRelations", args, &results) 70 if err != nil { 71 return nil, base.WrapError(err) 72 } 73 if len(results.Results) != 1 { 74 return nil, errors.Newf("expected one result, got %d", len(results.Results)) 75 } 76 result := results.Results[0] 77 if result.Error != nil { 78 return nil, result.Error 79 } 80 w := watcher.NewStringsWatcher(s.st.caller, result) 81 return w, nil 82 } 83 84 // Life returns the service's current life state. 85 func (s *Service) Life() params.Life { 86 return s.life 87 } 88 89 // Refresh refreshes the contents of the Service from the underlying 90 // state. 91 func (s *Service) Refresh() error { 92 life, err := s.st.life(s.tag) 93 if err != nil { 94 return base.WrapError(err) 95 } 96 s.life = life 97 return nil 98 } 99 100 // CharmURL returns the service's charm URL, and whether units should 101 // upgrade to the charm with that URL even if they are in an error 102 // state (force flag). 103 // 104 // NOTE: This differs from state.Service.CharmURL() by returning 105 // an error instead as well, because it needs to make an API call. 106 func (s *Service) CharmURL() (*charm.URL, bool, error) { 107 var results params.StringBoolResults 108 args := params.Entities{ 109 Entities: []params.Entity{{Tag: s.tag}}, 110 } 111 err := s.st.caller.Call("Uniter", "", "CharmURL", args, &results) 112 if err != nil { 113 return nil, false, base.WrapError(err) 114 } 115 if len(results.Results) != 1 { 116 return nil, false, errors.Newf("expected one result, got %d", len(results.Results)) 117 } 118 result := results.Results[0] 119 if result.Error != nil { 120 return nil, false, result.Error 121 } 122 if result.Result != "" { 123 curl, err := charm.ParseURL(result.Result) 124 if err != nil { 125 return nil, false, base.WrapError(err) 126 } 127 return curl, result.Ok, nil 128 } 129 return nil, false, errors.Newf("%q has no charm url set", s.tag) 130 } 131 132 // TODO(dimitern) bug #1270795 2014-01-20 133 // Add a doc comment here. 134 func (s *Service) GetOwnerTag() (string, error) { 135 var result params.StringResult 136 args := params.Entities{ 137 Entities: []params.Entity{{Tag: s.tag}}, 138 } 139 err := s.st.caller.Call("Uniter", "", "GetOwnerTag", args, &result) 140 if err != nil { 141 return "", base.WrapError(err) 142 } 143 if result.Error != nil { 144 return "", result.Error 145 } 146 return result.Result, nil 147 }