launchpad.net/~rogpeppe/juju-core/500-errgo-fix@v0.0.0-20140213181702-000000002356/state/api/uniter/relation.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/names" 11 "launchpad.net/juju-core/state/api/base" 12 "launchpad.net/juju-core/state/api/params" 13 ) 14 15 // This module implements a subset of the interface provided by 16 // state.Relation, as needed by the uniter API. 17 18 // Relation represents a relation between one or two service 19 // endpoints. 20 type Relation struct { 21 st *State 22 tag string 23 id int 24 life params.Life 25 } 26 27 // String returns the relation as a string. 28 func (r *Relation) String() string { 29 _, relId, err := names.ParseTag(r.tag, names.RelationTagKind) 30 if err != nil { 31 panic(fmt.Sprintf("%q is not a valid relation tag", r.tag)) 32 } 33 return relId 34 } 35 36 // Id returns the integer internal relation key. This is exposed 37 // because the unit agent needs to expose a value derived from this 38 // (as JUJU_RELATION_ID) to allow relation hooks to differentiate 39 // between relations with different services. 40 func (r *Relation) Id() int { 41 return r.id 42 } 43 44 // Life returns the relation's current life state. 45 func (r *Relation) Life() params.Life { 46 return r.life 47 } 48 49 // Refresh refreshes the contents of the relation from the underlying 50 // state. It returns an error that satisfies IsNotFound if the relation has been 51 // removed. 52 func (r *Relation) Refresh() error { 53 result, err := r.st.relation(r.tag, r.st.unitTag) 54 if err != nil { 55 // NOTE: The life cycle information is the only 56 // thing that can change - id, tag and endpoint 57 // information are static. 58 return base.WrapError(err) 59 } 60 61 r.life = result.Life 62 63 return nil 64 } 65 66 // Endpoint returns the endpoint of the relation for the service the 67 // uniter's managed unit belongs to. 68 func (r *Relation) Endpoint() (*Endpoint, error) { 69 // NOTE: This differs from state.Relation.Endpoint(), because when 70 // talking to the API, there's already an authenticated entity - the 71 // unit, and we can find out its service name. 72 result, err := r.st.relation(r.tag, r.st.unitTag) 73 if err != nil { 74 return nil, base.WrapError(err) 75 } 76 return &Endpoint{result.Endpoint.Relation}, nil 77 } 78 79 // Unit returns a RelationUnit for the supplied unit. 80 func (r *Relation) Unit(u *Unit) (*RelationUnit, error) { 81 if u == nil { 82 return nil, errors.Newf("unit is nil") 83 } 84 result, err := r.st.relation(r.tag, u.tag) 85 if err != nil { 86 return nil, base.WrapError(err) 87 } 88 return &RelationUnit{ 89 relation: r, 90 unit: u, 91 endpoint: Endpoint{result.Endpoint.Relation}, 92 st: r.st, 93 }, nil 94 }