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  }