github.com/makyo/juju@v0.0.0-20160425123129-2608902037e9/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  	_ = gc.Suite(&remoteFunctionalSuite{})
    21  )
    22  
    23  type remoteSuite struct {
    24  	lxdclient.BaseSuite
    25  }
    26  
    27  const (
    28  	testingCert = `
    29  -----BEGIN CERTIFICATE-----
    30  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
    61  EiFwoj8EbmwqzbNpOTNAOdo=
    62  -----END CERTIFICATE-----
    63  `
    64  
    65  	testingKey = `
    66  -----BEGIN RSA PRIVATE KEY-----
    67  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
   116  -----END RSA PRIVATE KEY-----
   117  `
   118  )
   119  
   120  func (s *remoteSuite) TestWithDefaultsNoop(c *gc.C) {
   121  	remote := lxdclient.Remote{
   122  		Name:     "my-remote",
   123  		Host:     "some-host",
   124  		Protocol: lxdclient.LXDProtocol,
   125  		Cert:     s.Cert,
   126  	}
   127  	updated, err := remote.WithDefaults()
   128  	c.Assert(err, jc.ErrorIsNil)
   129  	err = updated.Validate()
   130  
   131  	c.Check(err, jc.ErrorIsNil)
   132  	c.Check(updated, jc.DeepEquals, remote)
   133  }
   134  
   135  func (s *remoteSuite) TestWithDefaultsMissingName(c *gc.C) {
   136  	remote := lxdclient.Remote{
   137  		Name:     "",
   138  		Host:     "some-host",
   139  		Protocol: lxdclient.LXDProtocol,
   140  		Cert:     s.Cert,
   141  	}
   142  	updated, err := remote.WithDefaults()
   143  	c.Assert(err, jc.ErrorIsNil)
   144  
   145  	c.Check(updated, jc.DeepEquals, remote) // Name is not updated.
   146  }
   147  
   148  // TODO(ericsnow) Move this test to a functional suite.
   149  func (s *remoteSuite) TestWithDefaultsMissingCert(c *gc.C) {
   150  	lxdclient.PatchGenerateCertificate(&s.CleanupSuite, testingCert, testingKey)
   151  	remote := lxdclient.Remote{
   152  		Name:     "my-remote",
   153  		Host:     "some-host",
   154  		Protocol: lxdclient.LXDProtocol,
   155  		Cert:     nil,
   156  	}
   157  	updated, err := remote.WithDefaults()
   158  	c.Assert(err, jc.ErrorIsNil)
   159  	err = updated.Validate()
   160  
   161  	c.Check(err, jc.ErrorIsNil)
   162  	c.Assert(updated.Cert, gc.NotNil)
   163  	c.Check(updated.Cert.Validate(), jc.ErrorIsNil)
   164  	updated.Cert = nil // Validate ensured that the cert was okay.
   165  	c.Check(updated, jc.DeepEquals, lxdclient.Remote{
   166  		Name:     "my-remote",
   167  		Host:     "some-host",
   168  		Protocol: lxdclient.LXDProtocol,
   169  		Cert:     nil,
   170  	})
   171  }
   172  
   173  func (s *remoteSuite) TestWithDefaultsMissingProtocol(c *gc.C) {
   174  	remote := lxdclient.Remote{
   175  		Name: "my-remote",
   176  		Host: "some-host",
   177  		Cert: s.Cert,
   178  	}
   179  	updated, err := remote.WithDefaults()
   180  	c.Assert(err, jc.ErrorIsNil)
   181  	err = updated.Validate()
   182  
   183  	c.Check(err, jc.ErrorIsNil)
   184  	c.Assert(updated.Cert, gc.NotNil)
   185  	c.Check(updated.Cert.Validate(), jc.ErrorIsNil)
   186  	updated.Cert = nil // Validate ensured that the cert was okay.
   187  	c.Check(updated, jc.DeepEquals, lxdclient.Remote{
   188  		Name:     "my-remote",
   189  		Host:     "some-host",
   190  		Protocol: lxdclient.LXDProtocol,
   191  		Cert:     nil,
   192  	})
   193  }
   194  
   195  func (s *remoteSuite) TestWithDefaultsZeroValue(c *gc.C) {
   196  	var remote lxdclient.Remote
   197  	updated, err := remote.WithDefaults()
   198  	c.Assert(err, jc.ErrorIsNil)
   199  	err = updated.Validate()
   200  
   201  	c.Check(err, jc.ErrorIsNil)
   202  	c.Check(updated, jc.DeepEquals, lxdclient.Remote{
   203  		Name:     "local",
   204  		Host:     "",
   205  		Protocol: lxdclient.LXDProtocol,
   206  		Cert:     nil,
   207  	})
   208  }
   209  
   210  func (s *remoteSuite) TestWithDefaultsLocalNoop(c *gc.C) {
   211  	remote := lxdclient.Remote{
   212  		Name: "my-local",
   213  		Host: "",
   214  		Cert: nil,
   215  	}
   216  	updated, err := remote.WithDefaults()
   217  	c.Assert(err, jc.ErrorIsNil)
   218  	err = updated.Validate()
   219  
   220  	c.Check(err, jc.ErrorIsNil)
   221  	c.Check(updated, jc.DeepEquals, lxdclient.Remote{
   222  		Name:     "my-local",
   223  		Host:     "",
   224  		Protocol: lxdclient.LXDProtocol,
   225  		Cert:     nil,
   226  	})
   227  }
   228  
   229  func (s *remoteSuite) TestWithDefaultsLocalMissingName(c *gc.C) {
   230  	remote := lxdclient.Remote{
   231  		Name: "",
   232  		Host: "",
   233  		Cert: nil,
   234  	}
   235  	updated, err := remote.WithDefaults()
   236  	c.Assert(err, jc.ErrorIsNil)
   237  	err = updated.Validate()
   238  
   239  	c.Check(err, jc.ErrorIsNil)
   240  	c.Check(updated, jc.DeepEquals, lxdclient.Remote{
   241  		Name:     "local",
   242  		Host:     "",
   243  		Cert:     nil,
   244  		Protocol: lxdclient.LXDProtocol,
   245  	})
   246  }
   247  
   248  func (s *remoteSuite) TestValidateOkay(c *gc.C) {
   249  	remote := lxdclient.Remote{
   250  		Name:     "my-remote",
   251  		Host:     "some-host",
   252  		Protocol: lxdclient.LXDProtocol,
   253  		Cert:     s.Cert,
   254  	}
   255  	err := remote.Validate()
   256  
   257  	c.Check(err, jc.ErrorIsNil)
   258  }
   259  
   260  func (s *remoteSuite) TestValidateZeroValue(c *gc.C) {
   261  	var remote lxdclient.Remote
   262  	err := remote.Validate()
   263  
   264  	c.Check(err, jc.Satisfies, errors.IsNotValid)
   265  }
   266  
   267  func (s *remoteSuite) TestValidateMissingName(c *gc.C) {
   268  	remote := lxdclient.Remote{
   269  		Name:     "",
   270  		Host:     "some-host",
   271  		Protocol: lxdclient.LXDProtocol,
   272  		Cert:     s.Cert,
   273  	}
   274  	err := remote.Validate()
   275  
   276  	c.Check(err, jc.Satisfies, errors.IsNotValid)
   277  }
   278  
   279  func (s *remoteSuite) TestValidateMissingCert(c *gc.C) {
   280  	// We can have "public" remotes that don't require a client certificate
   281  	// to connect to and get images from.
   282  	remote := lxdclient.Remote{
   283  		Name:     "my-remote",
   284  		Host:     "some-host",
   285  		Protocol: lxdclient.LXDProtocol,
   286  		Cert:     nil,
   287  	}
   288  	err := remote.Validate()
   289  
   290  	c.Check(err, jc.ErrorIsNil)
   291  }
   292  
   293  func (s *remoteSuite) TestValidateBadCert(c *gc.C) {
   294  	remote := lxdclient.Remote{
   295  		Name:     "my-remote",
   296  		Host:     "some-host",
   297  		Protocol: lxdclient.LXDProtocol,
   298  		Cert:     &lxdclient.Cert{},
   299  	}
   300  	err := remote.Validate()
   301  
   302  	c.Check(err, jc.Satisfies, errors.IsNotValid)
   303  }
   304  
   305  func (s *remoteSuite) TestValidateLocalOkay(c *gc.C) {
   306  	remote := lxdclient.Remote{
   307  		Name:     "my-local",
   308  		Host:     "",
   309  		Protocol: lxdclient.LXDProtocol,
   310  		Cert:     nil,
   311  	}
   312  	err := remote.Validate()
   313  
   314  	c.Check(err, jc.ErrorIsNil)
   315  }
   316  
   317  func (s *remoteSuite) TestValidateLocalMissingName(c *gc.C) {
   318  	remote := lxdclient.Remote{
   319  		Name:     "",
   320  		Host:     "",
   321  		Protocol: lxdclient.LXDProtocol,
   322  		Cert:     nil,
   323  	}
   324  	err := remote.Validate()
   325  
   326  	c.Check(err, jc.Satisfies, errors.IsNotValid)
   327  }
   328  
   329  func (s *remoteSuite) TestValidateLocalSimplestreamsInvalid(c *gc.C) {
   330  	remote := lxdclient.Remote{
   331  		Name:     "",
   332  		Host:     "",
   333  		Protocol: lxdclient.SimplestreamsProtocol,
   334  		Cert:     nil,
   335  	}
   336  	err := remote.Validate()
   337  
   338  	c.Check(err, jc.Satisfies, errors.IsNotValid)
   339  }
   340  
   341  func (s *remoteSuite) TestValidateLocalWithCert(c *gc.C) {
   342  	remote := lxdclient.Remote{
   343  		Name:     "my-local",
   344  		Host:     "",
   345  		Protocol: lxdclient.LXDProtocol,
   346  		Cert:     &lxdclient.Cert{},
   347  	}
   348  	err := remote.Validate()
   349  
   350  	c.Check(err, jc.Satisfies, errors.IsNotValid)
   351  }
   352  
   353  func (s *remoteSuite) TestValidateSimplestreamsOkay(c *gc.C) {
   354  	remote := lxdclient.Remote{
   355  		Name:     "remote",
   356  		Host:     "http://somewhere/else",
   357  		Protocol: lxdclient.SimplestreamsProtocol,
   358  		Cert:     nil,
   359  	}
   360  	err := remote.Validate()
   361  
   362  	c.Check(err, jc.ErrorIsNil)
   363  }
   364  
   365  func (s *remoteSuite) TestValidateUnknownProtocol(c *gc.C) {
   366  	remote := lxdclient.Remote{
   367  		Name:     "remote",
   368  		Host:     "http://somewhere/else",
   369  		Protocol: "bogus-protocol",
   370  		Cert:     nil,
   371  	}
   372  	err := remote.Validate()
   373  
   374  	c.Check(err, jc.Satisfies, errors.IsNotValid)
   375  }
   376  
   377  func (s *remoteSuite) TestLocal(c *gc.C) {
   378  	expected := lxdclient.Remote{
   379  		Name:     "local",
   380  		Host:     "",
   381  		Protocol: lxdclient.LXDProtocol,
   382  		Cert:     nil,
   383  	}
   384  	c.Check(lxdclient.Local, jc.DeepEquals, expected)
   385  }
   386  
   387  func (s *remoteSuite) TestIDOkay(c *gc.C) {
   388  	remote := lxdclient.Remote{
   389  		Name: "my-remote",
   390  		Host: "some-host",
   391  		Cert: s.Cert,
   392  	}
   393  	id := remote.ID()
   394  
   395  	c.Check(id, gc.Equals, "my-remote")
   396  }
   397  
   398  func (s *remoteSuite) TestIDLocal(c *gc.C) {
   399  	remote := lxdclient.Remote{
   400  		Name: "my-remote",
   401  		Host: "",
   402  		Cert: s.Cert,
   403  	}
   404  	id := remote.ID()
   405  
   406  	c.Check(id, gc.Equals, "local")
   407  }
   408  
   409  func (s *remoteSuite) TestUsingTCPOkay(c *gc.C) {
   410  	c.Skip("not implemented yet")
   411  	// TODO(ericsnow) Finish this!
   412  }
   413  
   414  func (s *remoteSuite) TestUsingTCPNoop(c *gc.C) {
   415  	remote := lxdclient.Remote{
   416  		Name:     "my-remote",
   417  		Host:     "some-host",
   418  		Protocol: lxdclient.LXDProtocol,
   419  		Cert:     s.Cert,
   420  	}
   421  	nonlocal, err := remote.UsingTCP()
   422  	c.Assert(err, jc.ErrorIsNil)
   423  
   424  	c.Check(nonlocal, jc.DeepEquals, remote)
   425  }
   426  
   427  type remoteFunctionalSuite struct {
   428  	lxdclient.BaseSuite
   429  }
   430  
   431  func (s *remoteFunctionalSuite) TestUsingTCP(c *gc.C) {
   432  	if _, err := net.InterfaceByName(lxdclient.DefaultLXDBridge); err != nil {
   433  		c.Skip("network bridge interface not found")
   434  	}
   435  	lxdclient.PatchGenerateCertificate(&s.CleanupSuite, testingCert, testingKey)
   436  
   437  	remote := lxdclient.Remote{
   438  		Name: "my-remote",
   439  		Host: "",
   440  		Cert: nil,
   441  	}
   442  	nonlocal, err := remote.UsingTCP()
   443  	c.Assert(err, jc.ErrorIsNil)
   444  
   445  	checkValidRemote(c, &nonlocal)
   446  	c.Check(nonlocal, jc.DeepEquals, lxdclient.Remote{
   447  		Name:     "my-remote",
   448  		Host:     nonlocal.Host,
   449  		Protocol: lxdclient.LXDProtocol,
   450  		Cert:     nonlocal.Cert,
   451  	})
   452  }
   453  
   454  func checkValidRemote(c *gc.C, remote *lxdclient.Remote) {
   455  	c.Check(remote.Host, jc.Satisfies, isValidAddr)
   456  	checkValidCert(c, remote.Cert)
   457  }
   458  
   459  func isValidAddr(value interface{}) bool {
   460  	addr, ok := value.(string)
   461  	if !ok {
   462  		return false
   463  	}
   464  	return net.ParseIP(addr) != nil
   465  }