github.com/mattyw/juju@v0.0.0-20140610034352-732aecd63861/state/api/uniter/uniter.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/charm"
    12  	"github.com/juju/juju/state/api/base"
    13  	"github.com/juju/juju/state/api/common"
    14  	"github.com/juju/juju/state/api/params"
    15  )
    16  
    17  const uniterFacade = "Uniter"
    18  
    19  // State provides access to the Uniter API facade.
    20  type State struct {
    21  	*common.EnvironWatcher
    22  	*common.APIAddresser
    23  
    24  	caller base.Caller
    25  	// unitTag contains the authenticated unit's tag.
    26  	unitTag string
    27  }
    28  
    29  // NewState creates a new client-side Uniter facade.
    30  func NewState(caller base.Caller, authTag string) *State {
    31  	return &State{
    32  		EnvironWatcher: common.NewEnvironWatcher(uniterFacade, caller),
    33  		APIAddresser:   common.NewAPIAddresser(uniterFacade, caller),
    34  		caller:         caller,
    35  		unitTag:        authTag,
    36  	}
    37  }
    38  
    39  func (st *State) call(method string, params, results interface{}) error {
    40  	return st.caller.Call(uniterFacade, "", method, params, results)
    41  }
    42  
    43  // life requests the lifecycle of the given entity from the server.
    44  func (st *State) life(tag string) (params.Life, error) {
    45  	return common.Life(st.caller, uniterFacade, tag)
    46  }
    47  
    48  // relation requests relation information from the server.
    49  func (st *State) relation(relationTag, unitTag string) (params.RelationResult, error) {
    50  	nothing := params.RelationResult{}
    51  	var result params.RelationResults
    52  	args := params.RelationUnits{
    53  		RelationUnits: []params.RelationUnit{
    54  			{Relation: relationTag, Unit: unitTag},
    55  		},
    56  	}
    57  	err := st.call("Relation", args, &result)
    58  	if err != nil {
    59  		return nothing, err
    60  	}
    61  	if len(result.Results) != 1 {
    62  		return nothing, fmt.Errorf("expected 1 result, got %d", len(result.Results))
    63  	}
    64  	if err := result.Results[0].Error; err != nil {
    65  		return nothing, err
    66  	}
    67  	return result.Results[0], nil
    68  }
    69  
    70  // Unit provides access to methods of a state.Unit through the facade.
    71  func (st *State) Unit(tag string) (*Unit, error) {
    72  	life, err := st.life(tag)
    73  	if err != nil {
    74  		return nil, err
    75  	}
    76  	return &Unit{
    77  		tag:  tag,
    78  		life: life,
    79  		st:   st,
    80  	}, nil
    81  }
    82  
    83  // Service returns a service state by tag.
    84  func (st *State) Service(tag string) (*Service, error) {
    85  	life, err := st.life(tag)
    86  	if err != nil {
    87  		return nil, err
    88  	}
    89  	return &Service{
    90  		tag:  tag,
    91  		life: life,
    92  		st:   st,
    93  	}, nil
    94  }
    95  
    96  // ProviderType returns a provider type used by the current juju
    97  // environment.
    98  //
    99  // TODO(dimitern): We might be able to drop this, once we have machine
   100  // addresses implemented fully. See also LP bug 1221798.
   101  func (st *State) ProviderType() (string, error) {
   102  	var result params.StringResult
   103  	err := st.call("ProviderType", nil, &result)
   104  	if err != nil {
   105  		return "", err
   106  	}
   107  	if err := result.Error; err != nil {
   108  		return "", err
   109  	}
   110  	return result.Result, nil
   111  }
   112  
   113  // Charm returns the charm with the given URL.
   114  func (st *State) Charm(curl *charm.URL) (*Charm, error) {
   115  	if curl == nil {
   116  		return nil, fmt.Errorf("charm url cannot be nil")
   117  	}
   118  	return &Charm{
   119  		st:  st,
   120  		url: curl.String(),
   121  	}, nil
   122  }
   123  
   124  // Relation returns the existing relation with the given tag.
   125  func (st *State) Relation(tag string) (*Relation, error) {
   126  	result, err := st.relation(tag, st.unitTag)
   127  	if err != nil {
   128  		return nil, err
   129  	}
   130  	return &Relation{
   131  		id:   result.Id,
   132  		tag:  tag,
   133  		life: result.Life,
   134  		st:   st,
   135  	}, nil
   136  }
   137  
   138  // RelationById returns the existing relation with the given id.
   139  func (st *State) RelationById(id int) (*Relation, error) {
   140  	var results params.RelationResults
   141  	args := params.RelationIds{
   142  		RelationIds: []int{id},
   143  	}
   144  	err := st.call("RelationById", args, &results)
   145  	if err != nil {
   146  		return nil, err
   147  	}
   148  	if len(results.Results) != 1 {
   149  		return nil, fmt.Errorf("expected 1 result, got %d", len(results.Results))
   150  	}
   151  	result := results.Results[0]
   152  	if err := result.Error; err != nil {
   153  		return nil, err
   154  	}
   155  	relationTag := names.RelationTag(result.Key)
   156  	return &Relation{
   157  		id:   result.Id,
   158  		tag:  relationTag,
   159  		life: result.Life,
   160  		st:   st,
   161  	}, nil
   162  }
   163  
   164  // Environment returns the environment entity.
   165  func (st *State) Environment() (*Environment, error) {
   166  	var result params.EnvironmentResult
   167  	err := st.call("CurrentEnvironment", nil, &result)
   168  	if params.IsCodeNotImplemented(err) {
   169  		// Fall back to using the 1.16 API.
   170  		return st.environment1dot16()
   171  	}
   172  	if err != nil {
   173  		return nil, err
   174  	}
   175  	if err := result.Error; err != nil {
   176  		return nil, err
   177  	}
   178  	return &Environment{
   179  		name: result.Name,
   180  		uuid: result.UUID,
   181  	}, nil
   182  }
   183  
   184  // environment1dot16 requests just the UUID of the current environment, when
   185  // using an older API server that does not support CurrentEnvironment API call.
   186  func (st *State) environment1dot16() (*Environment, error) {
   187  	var result params.StringResult
   188  	err := st.call("CurrentEnvironUUID", nil, &result)
   189  	if err != nil {
   190  		return nil, err
   191  	}
   192  	if err := result.Error; err != nil {
   193  		return nil, err
   194  	}
   195  	return &Environment{
   196  		uuid: result.Result,
   197  	}, nil
   198  }