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