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