github.com/axw/juju@v0.0.0-20161005053422-4bd6544d08d4/tools/lxdclient/remote_test.go (about) 1 // Copyright 2015 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 // +build go1.3 5 6 package lxdclient_test 7 8 import ( 9 "net" 10 11 "github.com/juju/errors" 12 jc "github.com/juju/testing/checkers" 13 gc "gopkg.in/check.v1" 14 15 "github.com/juju/juju/tools/lxdclient" 16 ) 17 18 var ( 19 _ = gc.Suite(&remoteSuite{}) 20 ) 21 22 type remoteSuite struct { 23 lxdclient.BaseSuite 24 } 25 26 const ( 27 testingCert = ` 28 -----BEGIN CERTIFICATE----- 29 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 60 EiFwoj8EbmwqzbNpOTNAOdo= 61 -----END CERTIFICATE----- 62 ` 63 64 testingKey = ` 65 -----BEGIN RSA PRIVATE KEY----- 66 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 115 -----END RSA PRIVATE KEY----- 116 ` 117 ) 118 119 func (s *remoteSuite) TestWithDefaultsNoop(c *gc.C) { 120 remote := lxdclient.Remote{ 121 Name: "my-remote", 122 Host: "some-host", 123 Protocol: lxdclient.LXDProtocol, 124 Cert: s.Cert, 125 } 126 updated, err := remote.WithDefaults() 127 c.Assert(err, jc.ErrorIsNil) 128 err = updated.Validate() 129 130 c.Check(err, jc.ErrorIsNil) 131 c.Check(updated, jc.DeepEquals, remote) 132 } 133 134 func (s *remoteSuite) TestWithDefaultsMissingName(c *gc.C) { 135 remote := lxdclient.Remote{ 136 Name: "", 137 Host: "some-host", 138 Protocol: lxdclient.LXDProtocol, 139 Cert: s.Cert, 140 } 141 updated, err := remote.WithDefaults() 142 c.Assert(err, jc.ErrorIsNil) 143 144 c.Check(updated, jc.DeepEquals, remote) // Name is not updated. 145 } 146 147 // TODO(ericsnow) Move this test to a functional suite. 148 func (s *remoteSuite) TestWithDefaultsMissingCert(c *gc.C) { 149 lxdclient.PatchGenerateCertificate(&s.CleanupSuite, testingCert, testingKey) 150 remote := lxdclient.Remote{ 151 Name: "my-remote", 152 Host: "some-host", 153 Protocol: lxdclient.LXDProtocol, 154 Cert: nil, 155 } 156 updated, err := remote.WithDefaults() 157 c.Assert(err, jc.ErrorIsNil) 158 err = updated.Validate() 159 160 c.Check(err, jc.ErrorIsNil) 161 c.Assert(updated.Cert, gc.NotNil) 162 c.Check(updated.Cert.Validate(), jc.ErrorIsNil) 163 updated.Cert = nil // Validate ensured that the cert was okay. 164 c.Check(updated, jc.DeepEquals, lxdclient.Remote{ 165 Name: "my-remote", 166 Host: "some-host", 167 Protocol: lxdclient.LXDProtocol, 168 Cert: nil, 169 }) 170 } 171 172 func (s *remoteSuite) TestWithDefaultsMissingProtocol(c *gc.C) { 173 remote := lxdclient.Remote{ 174 Name: "my-remote", 175 Host: "some-host", 176 Cert: s.Cert, 177 } 178 updated, err := remote.WithDefaults() 179 c.Assert(err, jc.ErrorIsNil) 180 err = updated.Validate() 181 182 c.Check(err, jc.ErrorIsNil) 183 c.Assert(updated.Cert, gc.NotNil) 184 c.Check(updated.Cert.Validate(), jc.ErrorIsNil) 185 updated.Cert = nil // Validate ensured that the cert was okay. 186 c.Check(updated, jc.DeepEquals, lxdclient.Remote{ 187 Name: "my-remote", 188 Host: "some-host", 189 Protocol: lxdclient.LXDProtocol, 190 Cert: nil, 191 }) 192 } 193 194 func (s *remoteSuite) TestWithDefaultsZeroValue(c *gc.C) { 195 var remote lxdclient.Remote 196 updated, err := remote.WithDefaults() 197 c.Assert(err, jc.ErrorIsNil) 198 err = updated.Validate() 199 200 c.Check(err, jc.ErrorIsNil) 201 c.Check(updated, jc.DeepEquals, lxdclient.Remote{ 202 Name: "local", 203 Host: "", 204 Protocol: lxdclient.LXDProtocol, 205 Cert: nil, 206 }) 207 } 208 209 func (s *remoteSuite) TestWithDefaultsLocalNoop(c *gc.C) { 210 remote := lxdclient.Remote{ 211 Name: "my-local", 212 Host: "", 213 Cert: nil, 214 } 215 updated, err := remote.WithDefaults() 216 c.Assert(err, jc.ErrorIsNil) 217 err = updated.Validate() 218 219 c.Check(err, jc.ErrorIsNil) 220 c.Check(updated, jc.DeepEquals, lxdclient.Remote{ 221 Name: "my-local", 222 Host: "", 223 Protocol: lxdclient.LXDProtocol, 224 Cert: nil, 225 }) 226 } 227 228 func (s *remoteSuite) TestWithDefaultsLocalMissingName(c *gc.C) { 229 remote := lxdclient.Remote{ 230 Name: "", 231 Host: "", 232 Cert: nil, 233 } 234 updated, err := remote.WithDefaults() 235 c.Assert(err, jc.ErrorIsNil) 236 err = updated.Validate() 237 238 c.Check(err, jc.ErrorIsNil) 239 c.Check(updated, jc.DeepEquals, lxdclient.Remote{ 240 Name: "local", 241 Host: "", 242 Cert: nil, 243 Protocol: lxdclient.LXDProtocol, 244 }) 245 } 246 247 func (s *remoteSuite) TestValidateOkay(c *gc.C) { 248 remote := lxdclient.Remote{ 249 Name: "my-remote", 250 Host: "some-host", 251 Protocol: lxdclient.LXDProtocol, 252 Cert: s.Cert, 253 } 254 err := remote.Validate() 255 256 c.Check(err, jc.ErrorIsNil) 257 } 258 259 func (s *remoteSuite) TestValidateZeroValue(c *gc.C) { 260 var remote lxdclient.Remote 261 err := remote.Validate() 262 263 c.Check(err, jc.Satisfies, errors.IsNotValid) 264 } 265 266 func (s *remoteSuite) TestValidateMissingName(c *gc.C) { 267 remote := lxdclient.Remote{ 268 Name: "", 269 Host: "some-host", 270 Protocol: lxdclient.LXDProtocol, 271 Cert: s.Cert, 272 } 273 err := remote.Validate() 274 275 c.Check(err, jc.Satisfies, errors.IsNotValid) 276 } 277 278 func (s *remoteSuite) TestValidateMissingCert(c *gc.C) { 279 // We can have "public" remotes that don't require a client certificate 280 // to connect to and get images from. 281 remote := lxdclient.Remote{ 282 Name: "my-remote", 283 Host: "some-host", 284 Protocol: lxdclient.LXDProtocol, 285 Cert: nil, 286 } 287 err := remote.Validate() 288 289 c.Check(err, jc.ErrorIsNil) 290 } 291 292 func (s *remoteSuite) TestValidateBadCert(c *gc.C) { 293 remote := lxdclient.Remote{ 294 Name: "my-remote", 295 Host: "some-host", 296 Protocol: lxdclient.LXDProtocol, 297 Cert: &lxdclient.Cert{}, 298 } 299 err := remote.Validate() 300 301 c.Check(err, jc.Satisfies, errors.IsNotValid) 302 } 303 304 func (s *remoteSuite) TestValidateLocalOkay(c *gc.C) { 305 remote := lxdclient.Remote{ 306 Name: "my-local", 307 Host: "", 308 Protocol: lxdclient.LXDProtocol, 309 Cert: nil, 310 } 311 err := remote.Validate() 312 313 c.Check(err, jc.ErrorIsNil) 314 } 315 316 func (s *remoteSuite) TestValidateLocalMissingName(c *gc.C) { 317 remote := lxdclient.Remote{ 318 Name: "", 319 Host: "", 320 Protocol: lxdclient.LXDProtocol, 321 Cert: nil, 322 } 323 err := remote.Validate() 324 325 c.Check(err, jc.Satisfies, errors.IsNotValid) 326 } 327 328 func (s *remoteSuite) TestValidateLocalSimplestreamsInvalid(c *gc.C) { 329 remote := lxdclient.Remote{ 330 Name: "", 331 Host: "", 332 Protocol: lxdclient.SimplestreamsProtocol, 333 Cert: nil, 334 } 335 err := remote.Validate() 336 337 c.Check(err, jc.Satisfies, errors.IsNotValid) 338 } 339 340 func (s *remoteSuite) TestValidateLocalWithCert(c *gc.C) { 341 remote := lxdclient.Remote{ 342 Name: "my-local", 343 Host: "", 344 Protocol: lxdclient.LXDProtocol, 345 Cert: &lxdclient.Cert{}, 346 } 347 err := remote.Validate() 348 349 c.Check(err, jc.Satisfies, errors.IsNotValid) 350 } 351 352 func (s *remoteSuite) TestValidateSimplestreamsOkay(c *gc.C) { 353 remote := lxdclient.Remote{ 354 Name: "remote", 355 Host: "http://somewhere/else", 356 Protocol: lxdclient.SimplestreamsProtocol, 357 Cert: nil, 358 } 359 err := remote.Validate() 360 361 c.Check(err, jc.ErrorIsNil) 362 } 363 364 func (s *remoteSuite) TestValidateUnknownProtocol(c *gc.C) { 365 remote := lxdclient.Remote{ 366 Name: "remote", 367 Host: "http://somewhere/else", 368 Protocol: "bogus-protocol", 369 Cert: nil, 370 } 371 err := remote.Validate() 372 373 c.Check(err, jc.Satisfies, errors.IsNotValid) 374 } 375 376 func (s *remoteSuite) TestLocal(c *gc.C) { 377 expected := lxdclient.Remote{ 378 Name: "local", 379 Host: "", 380 Protocol: lxdclient.LXDProtocol, 381 Cert: nil, 382 } 383 c.Check(lxdclient.Local, jc.DeepEquals, expected) 384 } 385 386 func (s *remoteSuite) TestIDOkay(c *gc.C) { 387 remote := lxdclient.Remote{ 388 Name: "my-remote", 389 Host: "some-host", 390 Cert: s.Cert, 391 } 392 id := remote.ID() 393 394 c.Check(id, gc.Equals, "my-remote") 395 } 396 397 func (s *remoteSuite) TestIDLocal(c *gc.C) { 398 remote := lxdclient.Remote{ 399 Name: "my-remote", 400 Host: "", 401 Cert: s.Cert, 402 } 403 id := remote.ID() 404 405 c.Check(id, gc.Equals, "local") 406 } 407 408 func isValidAddr(value interface{}) bool { 409 addr, ok := value.(string) 410 if !ok { 411 return false 412 } 413 return net.ParseIP(addr) != nil 414 }