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 }