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  }