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