github.com/altoros/juju-vmware@v0.0.0-20150312064031-f19ae857ccca/api/apiclient_test.go (about)

     1  // Copyright 2014 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package api_test
     5  
     6  import (
     7  	"fmt"
     8  	"io"
     9  	"net"
    10  	"strconv"
    11  
    12  	"github.com/juju/names"
    13  	jc "github.com/juju/testing/checkers"
    14  	"github.com/juju/utils/parallel"
    15  	gc "gopkg.in/check.v1"
    16  
    17  	"github.com/juju/juju/api"
    18  	"github.com/juju/juju/apiserver/params"
    19  	jujutesting "github.com/juju/juju/juju/testing"
    20  	coretesting "github.com/juju/juju/testing"
    21  )
    22  
    23  type apiclientSuite struct {
    24  	jujutesting.JujuConnSuite
    25  }
    26  
    27  var _ = gc.Suite(&apiclientSuite{})
    28  
    29  type websocketSuite struct {
    30  	coretesting.BaseSuite
    31  }
    32  
    33  var _ = gc.Suite(&websocketSuite{})
    34  
    35  func (s *apiclientSuite) TestOpenPrefersLocalhostIfPresent(c *gc.C) {
    36  	// Create a socket that proxies to the API server though our localhost address.
    37  	info := s.APIInfo(c)
    38  	serverAddr := info.Addrs[0]
    39  	server, err := net.Dial("tcp", serverAddr)
    40  	c.Assert(err, jc.ErrorIsNil)
    41  	defer server.Close()
    42  	listener, err := net.Listen("tcp", "localhost:0")
    43  	c.Assert(err, jc.ErrorIsNil)
    44  	defer listener.Close()
    45  	go func() {
    46  		for {
    47  			client, err := listener.Accept()
    48  			if err != nil {
    49  				return
    50  			}
    51  			go io.Copy(client, server)
    52  			go io.Copy(server, client)
    53  		}
    54  	}()
    55  
    56  	// Check that we are using our working address to connect
    57  	listenerAddress := listener.Addr().String()
    58  	// listenAddress contains the actual IP address, but APIHostPorts
    59  	// is going to report localhost, so just find the port
    60  	_, port, err := net.SplitHostPort(listenerAddress)
    61  	c.Check(err, jc.ErrorIsNil)
    62  	portNum, err := strconv.Atoi(port)
    63  	c.Check(err, jc.ErrorIsNil)
    64  	expectedHostPort := fmt.Sprintf("localhost:%d", portNum)
    65  	info.Addrs = []string{"fakeAddress:1", "fakeAddress:1", expectedHostPort}
    66  	st, err := api.Open(info, api.DialOpts{})
    67  	c.Assert(err, jc.ErrorIsNil)
    68  	defer st.Close()
    69  	c.Assert(st.Addr(), gc.Equals, expectedHostPort)
    70  }
    71  
    72  func (s *apiclientSuite) TestOpenMultiple(c *gc.C) {
    73  	// Create a socket that proxies to the API server.
    74  	info := s.APIInfo(c)
    75  	serverAddr := info.Addrs[0]
    76  	server, err := net.Dial("tcp", serverAddr)
    77  	c.Assert(err, jc.ErrorIsNil)
    78  	defer server.Close()
    79  	listener, err := net.Listen("tcp", "127.0.0.1:0")
    80  	c.Assert(err, jc.ErrorIsNil)
    81  	defer listener.Close()
    82  	go func() {
    83  		for {
    84  			client, err := listener.Accept()
    85  			if err != nil {
    86  				return
    87  			}
    88  			go io.Copy(client, server)
    89  			go io.Copy(server, client)
    90  		}
    91  	}()
    92  
    93  	// Check that we can use the proxy to connect.
    94  	proxyAddr := listener.Addr().String()
    95  	info.Addrs = []string{proxyAddr}
    96  	st, err := api.Open(info, api.DialOpts{})
    97  	c.Assert(err, jc.ErrorIsNil)
    98  	defer st.Close()
    99  	c.Assert(st.Addr(), gc.Equals, proxyAddr)
   100  
   101  	// Now break Addrs[0], and ensure that Addrs[1]
   102  	// is successfully connected to.
   103  	info.Addrs = []string{proxyAddr, serverAddr}
   104  	listener.Close()
   105  	st, err = api.Open(info, api.DialOpts{})
   106  	c.Assert(err, jc.ErrorIsNil)
   107  	defer st.Close()
   108  	c.Assert(st.Addr(), gc.Equals, serverAddr)
   109  }
   110  
   111  func (s *apiclientSuite) TestOpenMultipleError(c *gc.C) {
   112  	listener, err := net.Listen("tcp", "127.0.0.1:0")
   113  	c.Assert(err, jc.ErrorIsNil)
   114  	defer listener.Close()
   115  	go func() {
   116  		for {
   117  			client, err := listener.Accept()
   118  			if err != nil {
   119  				return
   120  			}
   121  			client.Close()
   122  		}
   123  	}()
   124  	info := s.APIInfo(c)
   125  	addr := listener.Addr().String()
   126  	info.Addrs = []string{addr, addr, addr}
   127  	_, err = api.Open(info, api.DialOpts{})
   128  	c.Assert(err, gc.ErrorMatches, `unable to connect to "wss://.*/environment/[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}/api"`)
   129  }
   130  
   131  func (s *apiclientSuite) TestOpenPassesEnvironTag(c *gc.C) {
   132  	info := s.APIInfo(c)
   133  	env, err := s.State.Environment()
   134  	c.Assert(err, jc.ErrorIsNil)
   135  	// TODO(jam): 2014-06-05 http://pad.lv/1326802
   136  	// we want to test this eventually, but for now s.APIInfo uses
   137  	// conn.StateInfo() which doesn't know about EnvironTag.
   138  	// c.Check(info.EnvironTag, gc.Equals, env.Tag())
   139  	// c.Assert(info.EnvironTag, gc.Not(gc.Equals), "")
   140  	// We start by ensuring we have an invalid tag, and Open should fail.
   141  	info.EnvironTag = names.NewEnvironTag("bad-tag")
   142  	_, err = api.Open(info, api.DialOpts{})
   143  	c.Check(err, gc.ErrorMatches, `unknown environment: "bad-tag"`)
   144  	c.Check(params.ErrCode(err), gc.Equals, params.CodeNotFound)
   145  	// Now set it to the right tag, and we should succeed.
   146  	info.EnvironTag = env.EnvironTag()
   147  	st, err := api.Open(info, api.DialOpts{})
   148  	c.Assert(err, jc.ErrorIsNil)
   149  	st.Close()
   150  	// Backwards compatibility, we should succeed if we do not set an
   151  	// environ tag
   152  	info.EnvironTag = names.NewEnvironTag("")
   153  	st, err = api.Open(info, api.DialOpts{})
   154  	c.Assert(err, jc.ErrorIsNil)
   155  	st.Close()
   156  }
   157  
   158  func (s *apiclientSuite) TestDialWebsocketStopped(c *gc.C) {
   159  	stopped := make(chan struct{})
   160  	f := api.NewWebsocketDialer(nil, api.DialOpts{})
   161  	close(stopped)
   162  	result, err := f(stopped)
   163  	c.Assert(err, gc.Equals, parallel.ErrStopped)
   164  	c.Assert(result, gc.IsNil)
   165  }
   166  
   167  func (*websocketSuite) TestSetUpWebsocketConfig(c *gc.C) {
   168  	conf, err := api.SetUpWebsocket("0.1.2.3:1234", "", nil)
   169  	c.Assert(err, jc.ErrorIsNil)
   170  	c.Check(conf.Location.String(), gc.Equals, "wss://0.1.2.3:1234/")
   171  	c.Check(conf.Origin.String(), gc.Equals, "http://localhost/")
   172  }
   173  
   174  func (*websocketSuite) TestSetUpWebsocketConfigHandlesEnvironUUID(c *gc.C) {
   175  	conf, err := api.SetUpWebsocket("0.1.2.3:1234", "dead-beef-1234", nil)
   176  	c.Assert(err, jc.ErrorIsNil)
   177  	c.Check(conf.Location.String(), gc.Equals, "wss://0.1.2.3:1234/environment/dead-beef-1234/api")
   178  	c.Check(conf.Origin.String(), gc.Equals, "http://localhost/")
   179  }