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