github.com/cloudbase/juju-core@v0.0.0-20140504232958-a7271ac7912f/state/api/uniter/uniter.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/juju-core/charm" 10 "launchpad.net/juju-core/names" 11 "launchpad.net/juju-core/state/api/base" 12 "launchpad.net/juju-core/state/api/common" 13 "launchpad.net/juju-core/state/api/params" 14 ) 15 16 const uniter = "Uniter" 17 18 // State provides access to the Uniter API facade. 19 type State struct { 20 *common.EnvironWatcher 21 22 caller base.Caller 23 // unitTag contains the authenticated unit's tag. 24 unitTag string 25 } 26 27 // NewState creates a new client-side Uniter facade. 28 func NewState(caller base.Caller, authTag string) *State { 29 return &State{ 30 EnvironWatcher: common.NewEnvironWatcher(uniter, caller), 31 caller: caller, 32 unitTag: authTag} 33 } 34 35 // life requests the lifecycle of the given entity from the server. 36 func (st *State) life(tag string) (params.Life, error) { 37 return common.Life(st.caller, uniter, tag) 38 } 39 40 // relation requests relation information from the server. 41 func (st *State) relation(relationTag, unitTag string) (params.RelationResult, error) { 42 nothing := params.RelationResult{} 43 var result params.RelationResults 44 args := params.RelationUnits{ 45 RelationUnits: []params.RelationUnit{ 46 {Relation: relationTag, Unit: unitTag}, 47 }, 48 } 49 err := st.caller.Call(uniter, "", "Relation", args, &result) 50 if err != nil { 51 return nothing, err 52 } 53 if len(result.Results) != 1 { 54 return nothing, fmt.Errorf("expected one result, got %d", len(result.Results)) 55 } 56 if err := result.Results[0].Error; err != nil { 57 return nothing, err 58 } 59 return result.Results[0], nil 60 } 61 62 // Unit provides access to methods of a state.Unit through the facade. 63 func (st *State) Unit(tag string) (*Unit, error) { 64 life, err := st.life(tag) 65 if err != nil { 66 return nil, err 67 } 68 return &Unit{ 69 tag: tag, 70 life: life, 71 st: st, 72 }, nil 73 } 74 75 // Service returns a service state by tag. 76 func (st *State) Service(tag string) (*Service, error) { 77 life, err := st.life(tag) 78 if err != nil { 79 return nil, err 80 } 81 return &Service{ 82 tag: tag, 83 life: life, 84 st: st, 85 }, nil 86 } 87 88 // ProviderType returns a provider type used by the current juju 89 // environment. 90 // 91 // TODO(dimitern): We might be able to drop this, once we have machine 92 // addresses implemented fully. See also LP bug 1221798. 93 func (st *State) ProviderType() (string, error) { 94 var result params.StringResult 95 err := st.caller.Call(uniter, "", "ProviderType", nil, &result) 96 if err != nil { 97 return "", err 98 } 99 if err := result.Error; err != nil { 100 return "", err 101 } 102 return result.Result, nil 103 } 104 105 // Charm returns the charm with the given URL. 106 func (st *State) Charm(curl *charm.URL) (*Charm, error) { 107 if curl == nil { 108 return nil, fmt.Errorf("charm url cannot be nil") 109 } 110 return &Charm{ 111 st: st, 112 url: curl.String(), 113 }, nil 114 } 115 116 // Relation returns the existing relation with the given tag. 117 func (st *State) Relation(tag string) (*Relation, error) { 118 result, err := st.relation(tag, st.unitTag) 119 if err != nil { 120 return nil, err 121 } 122 return &Relation{ 123 id: result.Id, 124 tag: tag, 125 life: result.Life, 126 st: st, 127 }, nil 128 } 129 130 // Relation returns the existing relation with the given tag. 131 func (st *State) RelationById(id int) (*Relation, error) { 132 var results params.RelationResults 133 args := params.RelationIds{ 134 RelationIds: []int{id}, 135 } 136 err := st.caller.Call(uniter, "", "RelationById", args, &results) 137 if err != nil { 138 return nil, err 139 } 140 if len(results.Results) != 1 { 141 return nil, fmt.Errorf("expected one result, got %d", len(results.Results)) 142 } 143 result := results.Results[0] 144 if err := result.Error; err != nil { 145 return nil, err 146 } 147 relationTag := names.RelationTag(result.Key) 148 return &Relation{ 149 id: result.Id, 150 tag: relationTag, 151 life: result.Life, 152 st: st, 153 }, nil 154 } 155 156 // Environment returns the environment entity. 157 func (st *State) Environment() (*Environment, error) { 158 var result params.EnvironmentResult 159 err := st.caller.Call("Uniter", "", "CurrentEnvironment", nil, &result) 160 if params.IsCodeNotImplemented(err) { 161 // Fall back to using the 1.16 API. 162 return st.environment1dot16() 163 } 164 if err != nil { 165 return nil, err 166 } 167 if err := result.Error; err != nil { 168 return nil, err 169 } 170 return &Environment{ 171 name: result.Name, 172 uuid: result.UUID, 173 }, nil 174 } 175 176 // environment1dot16 requests just the UUID of the current environment, when 177 // using an older API server that does not support CurrentEnvironment API call. 178 func (st *State) environment1dot16() (*Environment, error) { 179 var result params.StringResult 180 err := st.caller.Call("Uniter", "", "CurrentEnvironUUID", nil, &result) 181 if err != nil { 182 return nil, err 183 } 184 if err := result.Error; err != nil { 185 return nil, err 186 } 187 return &Environment{ 188 uuid: result.Result, 189 }, nil 190 } 191 192 // APIAddresses returns the list of addresses used to connect to the API. 193 func (st *State) APIAddresses() ([]string, error) { 194 var result params.StringsResult 195 err := st.caller.Call(uniter, "", "APIAddresses", nil, &result) 196 if err != nil { 197 return nil, err 198 } 199 if err := result.Error; err != nil { 200 return nil, err 201 } 202 return result.Result, nil 203 }