github.com/mwhudson/juju@v0.0.0-20160512215208-90ff01f3497f/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  	"github.com/juju/names"
     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(caller base.APICaller) *Facade {
    16  	return &Facade{base.NewFacadeCaller(caller, "SSHClient")}
    17  }
    18  
    19  type Facade struct {
    20  	caller base.FacadeCaller
    21  }
    22  
    23  // PublicAddress returns the public address for the SSH target
    24  // provided. The target may be provided as a machine ID or unit name.
    25  func (facade *Facade) PublicAddress(target string) (string, error) {
    26  	addr, err := facade.addressCall("PublicAddress", target)
    27  	return addr, errors.Trace(err)
    28  }
    29  
    30  // PrivateAddress returns the private address for the SSH target
    31  // provided. The target may be provided as a machine ID or unit name.
    32  func (facade *Facade) PrivateAddress(target string) (string, error) {
    33  	addr, err := facade.addressCall("PrivateAddress", target)
    34  	return addr, errors.Trace(err)
    35  }
    36  
    37  func (facade *Facade) addressCall(callName, target string) (string, error) {
    38  	entities, err := targetToEntities(target)
    39  	if err != nil {
    40  		return "", errors.Trace(err)
    41  	}
    42  	var out params.SSHAddressResults
    43  	err = facade.caller.FacadeCall(callName, entities, &out)
    44  	if err != nil {
    45  		return "", errors.Trace(err)
    46  	}
    47  	if len(out.Results) != 1 {
    48  		return "", countError(len(out.Results))
    49  	}
    50  	if err := out.Results[0].Error; err != nil {
    51  		return "", errors.Trace(err)
    52  	}
    53  	return out.Results[0].Address, nil
    54  }
    55  
    56  // PublicKeys returns the SSH public host keys for the SSH target
    57  // provided. The target may be provided as a machine ID or unit name.
    58  func (facade *Facade) PublicKeys(target string) ([]string, error) {
    59  	entities, err := targetToEntities(target)
    60  	if err != nil {
    61  		return nil, errors.Trace(err)
    62  	}
    63  	var out params.SSHPublicKeysResults
    64  	err = facade.caller.FacadeCall("PublicKeys", entities, &out)
    65  	if err != nil {
    66  		return nil, errors.Trace(err)
    67  	}
    68  	if len(out.Results) != 1 {
    69  		return nil, countError(len(out.Results))
    70  	}
    71  	if err := out.Results[0].Error; err != nil {
    72  		return nil, errors.Trace(err)
    73  	}
    74  	return out.Results[0].PublicKeys, nil
    75  }
    76  
    77  // Proxy returns whether SSH connections should be proxied through the
    78  // controller hosts for the associated model.
    79  func (facade *Facade) Proxy() (bool, error) {
    80  	var out params.SSHProxyResult
    81  	err := facade.caller.FacadeCall("Proxy", nil, &out)
    82  	if err != nil {
    83  		return false, errors.Trace(err)
    84  	}
    85  	return out.UseProxy, nil
    86  }
    87  
    88  func targetToEntities(target string) (params.Entities, error) {
    89  	tag, err := targetToTag(target)
    90  	if err != nil {
    91  		return params.Entities{}, errors.Trace(err)
    92  	}
    93  	return params.Entities{
    94  		Entities: []params.Entity{{Tag: tag.String()}},
    95  	}, nil
    96  }
    97  
    98  func targetToTag(target string) (names.Tag, error) {
    99  	switch {
   100  	case names.IsValidMachine(target):
   101  		return names.NewMachineTag(target), nil
   102  	case names.IsValidUnit(target):
   103  		return names.NewUnitTag(target), nil
   104  	default:
   105  		return nil, errors.NotValidf("target %q", target)
   106  	}
   107  }
   108  
   109  // countError complains about malformed results.
   110  func countError(count int) error {
   111  	return errors.Errorf("expected 1 result, got %d", count)
   112  }