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 }