github.com/wallyworld/juju@v0.0.0-20161013125918-6cf1bc9d917a/api/sshclient/facade.go (about)

     1  // Copyright 2016 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package sshclient
     5  
     6  import (
     7  	"github.com/juju/errors"
     8  	"gopkg.in/juju/names.v2"
     9  
    10  	"github.com/juju/juju/api/base"
    11  	"github.com/juju/juju/apiserver/params"
    12  )
    13  
    14  // NewFacade returns a new Facade based on an existing API connection.
    15  func NewFacade(callCloser base.APICallCloser) *Facade {
    16  	clientFacade, caller := base.NewClientFacade(callCloser, "SSHClient")
    17  	return &Facade{
    18  		ClientFacade: clientFacade,
    19  		caller:       caller,
    20  	}
    21  }
    22  
    23  type Facade struct {
    24  	base.ClientFacade
    25  	caller base.FacadeCaller
    26  }
    27  
    28  // PublicAddress returns the public address for the SSH target
    29  // provided. The target may be provided as a machine ID or unit name.
    30  func (facade *Facade) PublicAddress(target string) (string, error) {
    31  	addr, err := facade.addressCall("PublicAddress", target)
    32  	return addr, errors.Trace(err)
    33  }
    34  
    35  // PrivateAddress returns the private address for the SSH target
    36  // provided. The target may be provided as a machine ID or unit name.
    37  func (facade *Facade) PrivateAddress(target string) (string, error) {
    38  	addr, err := facade.addressCall("PrivateAddress", target)
    39  	return addr, errors.Trace(err)
    40  }
    41  
    42  func (facade *Facade) addressCall(callName, target string) (string, error) {
    43  	entities, err := targetToEntities(target)
    44  	if err != nil {
    45  		return "", errors.Trace(err)
    46  	}
    47  	var out params.SSHAddressResults
    48  	err = facade.caller.FacadeCall(callName, entities, &out)
    49  	if err != nil {
    50  		return "", errors.Trace(err)
    51  	}
    52  	if len(out.Results) != 1 {
    53  		return "", countError(len(out.Results))
    54  	}
    55  	if err := out.Results[0].Error; err != nil {
    56  		return "", errors.Trace(err)
    57  	}
    58  	return out.Results[0].Address, nil
    59  }
    60  
    61  // PublicKeys returns the SSH public host keys for the SSH target
    62  // provided. The target may be provided as a machine ID or unit name.
    63  func (facade *Facade) PublicKeys(target string) ([]string, error) {
    64  	entities, err := targetToEntities(target)
    65  	if err != nil {
    66  		return nil, errors.Trace(err)
    67  	}
    68  	var out params.SSHPublicKeysResults
    69  	err = facade.caller.FacadeCall("PublicKeys", entities, &out)
    70  	if err != nil {
    71  		return nil, errors.Trace(err)
    72  	}
    73  	if len(out.Results) != 1 {
    74  		return nil, countError(len(out.Results))
    75  	}
    76  	if err := out.Results[0].Error; err != nil {
    77  		return nil, errors.Trace(err)
    78  	}
    79  	return out.Results[0].PublicKeys, nil
    80  }
    81  
    82  // Proxy returns whether SSH connections should be proxied through the
    83  // controller hosts for the associated model.
    84  func (facade *Facade) Proxy() (bool, error) {
    85  	var out params.SSHProxyResult
    86  	err := facade.caller.FacadeCall("Proxy", nil, &out)
    87  	if err != nil {
    88  		return false, errors.Trace(err)
    89  	}
    90  	return out.UseProxy, nil
    91  }
    92  
    93  func targetToEntities(target string) (params.Entities, error) {
    94  	tag, err := targetToTag(target)
    95  	if err != nil {
    96  		return params.Entities{}, errors.Trace(err)
    97  	}
    98  	return params.Entities{
    99  		Entities: []params.Entity{{Tag: tag.String()}},
   100  	}, nil
   101  }
   102  
   103  func targetToTag(target string) (names.Tag, error) {
   104  	switch {
   105  	case names.IsValidMachine(target):
   106  		return names.NewMachineTag(target), nil
   107  	case names.IsValidUnit(target):
   108  		return names.NewUnitTag(target), nil
   109  	default:
   110  		return nil, errors.NotValidf("target %q", target)
   111  	}
   112  }
   113  
   114  // countError complains about malformed results.
   115  func countError(count int) error {
   116  	return errors.Errorf("expected 1 result, got %d", count)
   117  }