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