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