github.com/niedbalski/juju@v0.0.0-20190215020005-8ff100488e47/apiserver/facades/client/sshclient/facade_test.go (about)

     1  // Copyright 2016 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package sshclient_test
     5  
     6  import (
     7  	"github.com/juju/errors"
     8  	jujutesting "github.com/juju/testing"
     9  	jc "github.com/juju/testing/checkers"
    10  	gc "gopkg.in/check.v1"
    11  	"gopkg.in/juju/names.v2"
    12  
    13  	"github.com/juju/juju/apiserver/common"
    14  	"github.com/juju/juju/apiserver/facades/client/sshclient"
    15  	"github.com/juju/juju/apiserver/params"
    16  	apiservertesting "github.com/juju/juju/apiserver/testing"
    17  	"github.com/juju/juju/environs"
    18  	"github.com/juju/juju/environs/config"
    19  	"github.com/juju/juju/environs/context"
    20  	"github.com/juju/juju/network"
    21  	"github.com/juju/juju/provider/dummy"
    22  	"github.com/juju/juju/state"
    23  	"github.com/juju/juju/testing"
    24  )
    25  
    26  type facadeSuite struct {
    27  	testing.BaseSuite
    28  	backend          *mockBackend
    29  	authorizer       *apiservertesting.FakeAuthorizer
    30  	facade           *sshclient.Facade
    31  	m0, uFoo, uOther string
    32  
    33  	callContext context.ProviderCallContext
    34  }
    35  
    36  var _ = gc.Suite(&facadeSuite{})
    37  
    38  func (s *facadeSuite) SetUpSuite(c *gc.C) {
    39  	s.BaseSuite.SetUpSuite(c)
    40  	s.m0 = names.NewMachineTag("0").String()
    41  	s.uFoo = names.NewUnitTag("foo/0").String()
    42  	s.uOther = names.NewUnitTag("other/1").String()
    43  }
    44  
    45  func (s *facadeSuite) SetUpTest(c *gc.C) {
    46  	s.BaseSuite.SetUpTest(c)
    47  
    48  	s.backend = new(mockBackend)
    49  	s.authorizer = new(apiservertesting.FakeAuthorizer)
    50  	s.authorizer.Tag = names.NewUserTag("igor")
    51  	s.authorizer.AdminTag = names.NewUserTag("igor")
    52  
    53  	s.callContext = context.NewCloudCallContext()
    54  	facade, err := sshclient.InternalFacade(s.backend, s.authorizer, s.callContext)
    55  	c.Assert(err, jc.ErrorIsNil)
    56  	s.facade = facade
    57  }
    58  
    59  func (s *facadeSuite) TestMachineAuthNotAllowed(c *gc.C) {
    60  	s.authorizer.Tag = names.NewMachineTag("0")
    61  	_, err := sshclient.InternalFacade(s.backend, s.authorizer, s.callContext)
    62  	c.Assert(err, gc.Equals, common.ErrPerm)
    63  }
    64  
    65  func (s *facadeSuite) TestUnitAuthNotAllowed(c *gc.C) {
    66  	s.authorizer.Tag = names.NewUnitTag("foo/0")
    67  	_, err := sshclient.InternalFacade(s.backend, s.authorizer, s.callContext)
    68  	c.Assert(err, gc.Equals, common.ErrPerm)
    69  }
    70  
    71  func (s *facadeSuite) TestPublicAddress(c *gc.C) {
    72  	args := params.Entities{
    73  		Entities: []params.Entity{{s.m0}, {s.uFoo}, {s.uOther}},
    74  	}
    75  	results, err := s.facade.PublicAddress(args)
    76  
    77  	c.Assert(err, jc.ErrorIsNil)
    78  	c.Check(results, gc.DeepEquals, params.SSHAddressResults{
    79  		Results: []params.SSHAddressResult{
    80  			{Address: "1.1.1.1"},
    81  			{Address: "3.3.3.3"},
    82  			{Error: apiservertesting.NotFoundError("entity")},
    83  		},
    84  	})
    85  	s.backend.stub.CheckCalls(c, []jujutesting.StubCall{
    86  		{"GetMachineForEntity", []interface{}{s.m0}},
    87  		{"GetMachineForEntity", []interface{}{s.uFoo}},
    88  		{"GetMachineForEntity", []interface{}{s.uOther}},
    89  	})
    90  }
    91  
    92  func (s *facadeSuite) TestPrivateAddress(c *gc.C) {
    93  	args := params.Entities{
    94  		Entities: []params.Entity{{s.uOther}, {s.m0}, {s.uFoo}},
    95  	}
    96  	results, err := s.facade.PrivateAddress(args)
    97  
    98  	c.Assert(err, jc.ErrorIsNil)
    99  	c.Check(results, gc.DeepEquals, params.SSHAddressResults{
   100  		Results: []params.SSHAddressResult{
   101  			{Error: apiservertesting.NotFoundError("entity")},
   102  			{Address: "2.2.2.2"},
   103  			{Address: "4.4.4.4"},
   104  		},
   105  	})
   106  	s.backend.stub.CheckCalls(c, []jujutesting.StubCall{
   107  		{"GetMachineForEntity", []interface{}{s.uOther}},
   108  		{"GetMachineForEntity", []interface{}{s.m0}},
   109  		{"GetMachineForEntity", []interface{}{s.uFoo}},
   110  	})
   111  }
   112  
   113  func (s *facadeSuite) TestAllAddresses(c *gc.C) {
   114  	args := params.Entities{
   115  		Entities: []params.Entity{{s.uOther}, {s.m0}, {s.uFoo}},
   116  	}
   117  	results, err := s.facade.AllAddresses(args)
   118  
   119  	c.Assert(err, jc.ErrorIsNil)
   120  	c.Check(results, gc.DeepEquals, params.SSHAddressesResults{
   121  		Results: []params.SSHAddressesResult{
   122  			{Error: apiservertesting.NotFoundError("entity")},
   123  			{Addresses: []string{
   124  				"0.1.2.3", "1.1.1.1", "2.2.2.2", // From AllNetworkAddresses()
   125  				"9.9.9.9", // From Addresses()
   126  			}},
   127  			{Addresses: []string{
   128  				"0.3.2.1", "3.3.3.3", "4.4.4.4", // From AllNetworkAddresses()
   129  				"10.10.10.10", // From Addresses()
   130  			}},
   131  		},
   132  	})
   133  	s.backend.stub.CheckCalls(c, []jujutesting.StubCall{
   134  		{"ModelConfig", nil},
   135  		{"CloudSpec", nil},
   136  		{"GetMachineForEntity", []interface{}{s.uOther}},
   137  		{"GetMachineForEntity", []interface{}{s.m0}},
   138  		{"GetMachineForEntity", []interface{}{s.uFoo}},
   139  	})
   140  }
   141  
   142  func (s *facadeSuite) TestPublicKeys(c *gc.C) {
   143  	args := params.Entities{
   144  		Entities: []params.Entity{{s.m0}, {s.uOther}, {s.uFoo}},
   145  	}
   146  	results, err := s.facade.PublicKeys(args)
   147  
   148  	c.Assert(err, jc.ErrorIsNil)
   149  	c.Check(results, gc.DeepEquals, params.SSHPublicKeysResults{
   150  		Results: []params.SSHPublicKeysResult{
   151  			{PublicKeys: []string{"rsa0", "dsa0"}},
   152  			{Error: apiservertesting.NotFoundError("entity")},
   153  			{PublicKeys: []string{"rsa1", "dsa1"}},
   154  		},
   155  	})
   156  	s.backend.stub.CheckCalls(c, []jujutesting.StubCall{
   157  		{"GetMachineForEntity", []interface{}{s.m0}},
   158  		{"GetSSHHostKeys", []interface{}{names.NewMachineTag("0")}},
   159  		{"GetMachineForEntity", []interface{}{s.uOther}},
   160  		{"GetMachineForEntity", []interface{}{s.uFoo}},
   161  		{"GetSSHHostKeys", []interface{}{names.NewMachineTag("1")}},
   162  	})
   163  }
   164  
   165  func (s *facadeSuite) TestProxyTrue(c *gc.C) {
   166  	s.backend.proxySSH = true
   167  	result, err := s.facade.Proxy()
   168  	c.Assert(err, jc.ErrorIsNil)
   169  	c.Check(result.UseProxy, jc.IsTrue)
   170  	s.backend.stub.CheckCalls(c, []jujutesting.StubCall{
   171  		{"ModelConfig", []interface{}{}},
   172  	})
   173  }
   174  
   175  func (s *facadeSuite) TestProxyFalse(c *gc.C) {
   176  	s.backend.proxySSH = false
   177  	result, err := s.facade.Proxy()
   178  	c.Assert(err, jc.ErrorIsNil)
   179  	c.Check(result.UseProxy, jc.IsFalse)
   180  	s.backend.stub.CheckCalls(c, []jujutesting.StubCall{
   181  		{"ModelConfig", []interface{}{}},
   182  	})
   183  }
   184  
   185  type mockBackend struct {
   186  	stub     jujutesting.Stub
   187  	proxySSH bool
   188  }
   189  
   190  func (backend *mockBackend) ModelTag() names.ModelTag {
   191  	return names.NewModelTag("deadbeef-2f18-4fd2-967d-db9663db7bea")
   192  }
   193  
   194  func (backend *mockBackend) ModelConfig() (*config.Config, error) {
   195  	backend.stub.AddCall("ModelConfig")
   196  	attrs := testing.FakeConfig()
   197  	attrs["proxy-ssh"] = backend.proxySSH
   198  	conf, err := config.New(config.NoDefaults, attrs)
   199  	if err != nil {
   200  		return nil, errors.Trace(err)
   201  	}
   202  	return conf, nil
   203  }
   204  
   205  func (backend *mockBackend) GetMachineForEntity(tagString string) (sshclient.SSHMachine, error) {
   206  	backend.stub.AddCall("GetMachineForEntity", tagString)
   207  	switch tagString {
   208  	case names.NewMachineTag("0").String():
   209  		return &mockMachine{
   210  			tag:            names.NewMachineTag("0"),
   211  			publicAddress:  "1.1.1.1",
   212  			privateAddress: "2.2.2.2",
   213  			addresses:      network.NewAddresses("9.9.9.9"),
   214  			allNetworkAddresses: network.NewAddresses("0.1.2.3", "1.1.1.1", "2.2.2.2",
   215  				"100.100.100.100", // This one will be filtered by provider
   216  			),
   217  		}, nil
   218  	case names.NewUnitTag("foo/0").String():
   219  		return &mockMachine{
   220  			tag:            names.NewMachineTag("1"),
   221  			publicAddress:  "3.3.3.3",
   222  			privateAddress: "4.4.4.4",
   223  			addresses: network.NewAddresses("10.10.10.10",
   224  				"100.100.100.100", // This one will be filtered by provider
   225  			),
   226  			allNetworkAddresses: network.NewAddresses("0.3.2.1", "3.3.3.3", "4.4.4.4"),
   227  		}, nil
   228  	}
   229  	return nil, errors.NotFoundf("entity")
   230  }
   231  
   232  func (backend *mockBackend) GetSSHHostKeys(tag names.MachineTag) (state.SSHHostKeys, error) {
   233  	backend.stub.AddCall("GetSSHHostKeys", tag)
   234  	switch tag {
   235  	case names.NewMachineTag("0"):
   236  		return state.SSHHostKeys{"rsa0", "dsa0"}, nil
   237  	case names.NewMachineTag("1"):
   238  		return state.SSHHostKeys{"rsa1", "dsa1"}, nil
   239  	}
   240  	return nil, errors.New("machine not found")
   241  }
   242  
   243  func (backend *mockBackend) CloudSpec() (environs.CloudSpec, error) {
   244  	backend.stub.AddCall("CloudSpec")
   245  	return dummy.SampleCloudSpec(), nil
   246  }
   247  
   248  type mockMachine struct {
   249  	tag            names.MachineTag
   250  	publicAddress  string
   251  	privateAddress string
   252  
   253  	addresses           []network.Address
   254  	allNetworkAddresses []network.Address
   255  }
   256  
   257  func (m *mockMachine) MachineTag() names.MachineTag {
   258  	return m.tag
   259  }
   260  
   261  func (m *mockMachine) PublicAddress() (network.Address, error) {
   262  	return network.Address{
   263  		Value: m.publicAddress,
   264  	}, nil
   265  }
   266  
   267  func (m *mockMachine) PrivateAddress() (network.Address, error) {
   268  	return network.Address{
   269  		Value: m.privateAddress,
   270  	}, nil
   271  }
   272  
   273  func (m *mockMachine) AllNetworkAddresses() ([]network.Address, error) {
   274  	return m.allNetworkAddresses, nil
   275  }
   276  
   277  func (m *mockMachine) Addresses() []network.Address {
   278  	return m.addresses
   279  }