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