github.com/cloudbase/juju-core@v0.0.0-20140504232958-a7271ac7912f/state/apiserver/server_test.go (about)

     1  // Copyright 2012, 2013 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package apiserver_test
     5  
     6  import (
     7  	"io"
     8  	stdtesting "testing"
     9  	"time"
    10  
    11  	gc "launchpad.net/gocheck"
    12  
    13  	jujutesting "launchpad.net/juju-core/juju/testing"
    14  	"launchpad.net/juju-core/rpc"
    15  	"launchpad.net/juju-core/state"
    16  	"launchpad.net/juju-core/state/api"
    17  	"launchpad.net/juju-core/state/api/params"
    18  	"launchpad.net/juju-core/state/apiserver"
    19  	coretesting "launchpad.net/juju-core/testing"
    20  	jc "launchpad.net/juju-core/testing/checkers"
    21  	"launchpad.net/juju-core/utils"
    22  )
    23  
    24  func TestAll(t *stdtesting.T) {
    25  	coretesting.MgoTestPackage(t)
    26  }
    27  
    28  var fastDialOpts = api.DialOpts{}
    29  
    30  type serverSuite struct {
    31  	jujutesting.JujuConnSuite
    32  }
    33  
    34  var _ = gc.Suite(&serverSuite{})
    35  
    36  func (s *serverSuite) TestStop(c *gc.C) {
    37  	// Start our own instance of the server so we have
    38  	// a handle on it to stop it.
    39  	srv, err := apiserver.NewServer(s.State, "localhost:0", []byte(coretesting.ServerCert), []byte(coretesting.ServerKey), "")
    40  	c.Assert(err, gc.IsNil)
    41  	defer srv.Stop()
    42  
    43  	stm, err := s.State.AddMachine("quantal", state.JobHostUnits)
    44  	c.Assert(err, gc.IsNil)
    45  	err = stm.SetProvisioned("foo", "fake_nonce", nil)
    46  	c.Assert(err, gc.IsNil)
    47  	password, err := utils.RandomPassword()
    48  	c.Assert(err, gc.IsNil)
    49  	err = stm.SetPassword(password)
    50  	c.Assert(err, gc.IsNil)
    51  
    52  	// Note we can't use openAs because we're not connecting to
    53  	// s.APIConn.
    54  	apiInfo := &api.Info{
    55  		Tag:      stm.Tag(),
    56  		Password: password,
    57  		Nonce:    "fake_nonce",
    58  		Addrs:    []string{srv.Addr()},
    59  		CACert:   []byte(coretesting.CACert),
    60  	}
    61  	st, err := api.Open(apiInfo, fastDialOpts)
    62  	c.Assert(err, gc.IsNil)
    63  	defer st.Close()
    64  
    65  	_, err = st.Machiner().Machine(stm.Tag())
    66  	c.Assert(err, gc.IsNil)
    67  
    68  	err = srv.Stop()
    69  	c.Assert(err, gc.IsNil)
    70  
    71  	_, err = st.Machiner().Machine(stm.Tag())
    72  	// The client has not necessarily seen the server shutdown yet,
    73  	// so there are two possible errors.
    74  	if err != rpc.ErrShutdown && err != io.ErrUnexpectedEOF {
    75  		c.Fatalf("unexpected error from request: %v", err)
    76  	}
    77  
    78  	// Check it can be stopped twice.
    79  	err = srv.Stop()
    80  	c.Assert(err, gc.IsNil)
    81  }
    82  
    83  func (s *serverSuite) TestOpenAsMachineErrors(c *gc.C) {
    84  	assertNotProvisioned := func(err error) {
    85  		c.Assert(err, gc.NotNil)
    86  		c.Assert(err, jc.Satisfies, params.IsCodeNotProvisioned)
    87  		c.Assert(err, gc.ErrorMatches, `machine \d+ is not provisioned`)
    88  	}
    89  	stm, err := s.State.AddMachine("quantal", state.JobHostUnits)
    90  	c.Assert(err, gc.IsNil)
    91  	err = stm.SetProvisioned("foo", "fake_nonce", nil)
    92  	c.Assert(err, gc.IsNil)
    93  	password, err := utils.RandomPassword()
    94  	c.Assert(err, gc.IsNil)
    95  	err = stm.SetPassword(password)
    96  	c.Assert(err, gc.IsNil)
    97  
    98  	// This does almost exactly the same as OpenAPIAsMachine but checks
    99  	// for failures instead.
   100  	_, info, err := s.APIConn.Environ.StateInfo()
   101  	info.Tag = stm.Tag()
   102  	info.Password = password
   103  	info.Nonce = "invalid-nonce"
   104  	st, err := api.Open(info, fastDialOpts)
   105  	assertNotProvisioned(err)
   106  	c.Assert(st, gc.IsNil)
   107  
   108  	// Try with empty nonce as well.
   109  	info.Nonce = ""
   110  	st, err = api.Open(info, fastDialOpts)
   111  	assertNotProvisioned(err)
   112  	c.Assert(st, gc.IsNil)
   113  
   114  	// Finally, with the correct one succeeds.
   115  	info.Nonce = "fake_nonce"
   116  	st, err = api.Open(info, fastDialOpts)
   117  	c.Assert(err, gc.IsNil)
   118  	c.Assert(st, gc.NotNil)
   119  	st.Close()
   120  
   121  	// Now add another machine, intentionally unprovisioned.
   122  	stm1, err := s.State.AddMachine("quantal", state.JobHostUnits)
   123  	c.Assert(err, gc.IsNil)
   124  	err = stm1.SetPassword(password)
   125  	c.Assert(err, gc.IsNil)
   126  
   127  	// Try connecting, it will fail.
   128  	info.Tag = stm1.Tag()
   129  	info.Nonce = ""
   130  	st, err = api.Open(info, fastDialOpts)
   131  	assertNotProvisioned(err)
   132  	c.Assert(st, gc.IsNil)
   133  }
   134  
   135  func (s *serverSuite) TestMachineLoginStartsPinger(c *gc.C) {
   136  	// This is the same steps as OpenAPIAsNewMachine but we need to assert
   137  	// the agent is not alive before we actually open the API.
   138  	// Create a new machine to verify "agent alive" behavior.
   139  	machine, err := s.State.AddMachine("quantal", state.JobHostUnits)
   140  	c.Assert(err, gc.IsNil)
   141  	err = machine.SetProvisioned("foo", "fake_nonce", nil)
   142  	c.Assert(err, gc.IsNil)
   143  	password, err := utils.RandomPassword()
   144  	c.Assert(err, gc.IsNil)
   145  	err = machine.SetPassword(password)
   146  	c.Assert(err, gc.IsNil)
   147  
   148  	// Not alive yet.
   149  	s.assertAlive(c, machine, false)
   150  
   151  	// Login as the machine agent of the created machine.
   152  	st := s.OpenAPIAsMachine(c, machine.Tag(), password, "fake_nonce")
   153  
   154  	// Make sure the pinger has started.
   155  	s.assertAlive(c, machine, true)
   156  
   157  	// Now make sure it stops when connection is closed.
   158  	c.Assert(st.Close(), gc.IsNil)
   159  
   160  	// Sync, then wait for a bit to make sure the state is updated.
   161  	s.State.StartSync()
   162  	<-time.After(coretesting.ShortWait)
   163  	s.State.StartSync()
   164  
   165  	s.assertAlive(c, machine, false)
   166  }
   167  
   168  func (s *serverSuite) TestUnitLoginStartsPinger(c *gc.C) {
   169  	// Create a new service and unit to verify "agent alive" behavior.
   170  	service := s.AddTestingService(c, "wordpress", s.AddTestingCharm(c, "wordpress"))
   171  	unit, err := service.AddUnit()
   172  	c.Assert(err, gc.IsNil)
   173  	password, err := utils.RandomPassword()
   174  	c.Assert(err, gc.IsNil)
   175  	err = unit.SetPassword(password)
   176  	c.Assert(err, gc.IsNil)
   177  
   178  	// Not alive yet.
   179  	s.assertAlive(c, unit, false)
   180  
   181  	// Login as the unit agent of the created unit.
   182  	st := s.OpenAPIAs(c, unit.Tag(), password)
   183  
   184  	// Make sure the pinger has started.
   185  	s.assertAlive(c, unit, true)
   186  
   187  	// Now make sure it stops when connection is closed.
   188  	c.Assert(st.Close(), gc.IsNil)
   189  
   190  	// Sync, then wait for a bit to make sure the state is updated.
   191  	s.State.StartSync()
   192  	<-time.After(coretesting.ShortWait)
   193  	s.State.StartSync()
   194  
   195  	s.assertAlive(c, unit, false)
   196  }
   197  
   198  type agentAliver interface {
   199  	AgentAlive() (bool, error)
   200  }
   201  
   202  func (s *serverSuite) assertAlive(c *gc.C, entity agentAliver, isAlive bool) {
   203  	s.State.StartSync()
   204  	alive, err := entity.AgentAlive()
   205  	c.Assert(err, gc.IsNil)
   206  	c.Assert(alive, gc.Equals, isAlive)
   207  }