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