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