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