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