github.com/niedbalski/juju@v0.0.0-20190215020005-8ff100488e47/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  // AllAddresses returns all addresses for the SSH target provided. The target
    43  // may be provided as a machine ID or unit name.
    44  func (facade *Facade) AllAddresses(target string) ([]string, error) {
    45  	entities, err := targetToEntities(target)
    46  	if err != nil {
    47  		return nil, errors.Trace(err)
    48  	}
    49  	var out params.SSHAddressesResults
    50  	err = facade.caller.FacadeCall("AllAddresses", entities, &out)
    51  	if err != nil {
    52  		return nil, errors.Trace(err)
    53  	}
    54  	if len(out.Results) != 1 {
    55  		return nil, countError(len(out.Results))
    56  	}
    57  	if err := out.Results[0].Error; err != nil {
    58  		return nil, errors.Trace(err)
    59  	}
    60  	return out.Results[0].Addresses, nil
    61  }
    62  
    63  func (facade *Facade) addressCall(callName, target string) (string, error) {
    64  	entities, err := targetToEntities(target)
    65  	if err != nil {
    66  		return "", errors.Trace(err)
    67  	}
    68  	var out params.SSHAddressResults
    69  	err = facade.caller.FacadeCall(callName, entities, &out)
    70  	if err != nil {
    71  		return "", errors.Trace(err)
    72  	}
    73  	if len(out.Results) != 1 {
    74  		return "", countError(len(out.Results))
    75  	}
    76  	if err := out.Results[0].Error; err != nil {
    77  		return "", errors.Trace(err)
    78  	}
    79  	return out.Results[0].Address, nil
    80  }
    81  
    82  // PublicKeys returns the SSH public host keys for the SSH target
    83  // provided. The target may be provided as a machine ID or unit name.
    84  func (facade *Facade) PublicKeys(target string) ([]string, error) {
    85  	entities, err := targetToEntities(target)
    86  	if err != nil {
    87  		return nil, errors.Trace(err)
    88  	}
    89  	var out params.SSHPublicKeysResults
    90  	err = facade.caller.FacadeCall("PublicKeys", entities, &out)
    91  	if err != nil {
    92  		return nil, errors.Trace(err)
    93  	}
    94  	if len(out.Results) != 1 {
    95  		return nil, countError(len(out.Results))
    96  	}
    97  	if err := out.Results[0].Error; err != nil {
    98  		return nil, errors.Trace(err)
    99  	}
   100  	return out.Results[0].PublicKeys, nil
   101  }
   102  
   103  // Proxy returns whether SSH connections should be proxied through the
   104  // controller hosts for the associated model.
   105  func (facade *Facade) Proxy() (bool, error) {
   106  	var out params.SSHProxyResult
   107  	err := facade.caller.FacadeCall("Proxy", nil, &out)
   108  	if err != nil {
   109  		return false, errors.Trace(err)
   110  	}
   111  	return out.UseProxy, nil
   112  }
   113  
   114  func targetToEntities(target string) (params.Entities, error) {
   115  	tag, err := targetToTag(target)
   116  	if err != nil {
   117  		return params.Entities{}, errors.Trace(err)
   118  	}
   119  	return params.Entities{
   120  		Entities: []params.Entity{{Tag: tag.String()}},
   121  	}, nil
   122  }
   123  
   124  func targetToTag(target string) (names.Tag, error) {
   125  	switch {
   126  	case names.IsValidMachine(target):
   127  		return names.NewMachineTag(target), nil
   128  	case names.IsValidUnit(target):
   129  		return names.NewUnitTag(target), nil
   130  	default:
   131  		return nil, errors.NotValidf("target %q", target)
   132  	}
   133  }
   134  
   135  // countError complains about malformed results.
   136  func countError(count int) error {
   137  	return errors.Errorf("expected 1 result, got %d", count)
   138  }