github.com/axw/juju@v0.0.0-20161005053422-4bd6544d08d4/worker/instancepoller/worker_test.go (about) 1 // Copyright 2013 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 // TODO(wallyworld) - move to instancepoller_test 5 package instancepoller 6 7 import ( 8 "fmt" 9 "reflect" 10 "time" 11 12 jc "github.com/juju/testing/checkers" 13 "github.com/juju/utils/clock" 14 gc "gopkg.in/check.v1" 15 "gopkg.in/juju/names.v2" 16 17 "github.com/juju/juju/api" 18 apiinstancepoller "github.com/juju/juju/api/instancepoller" 19 "github.com/juju/juju/apiserver/params" 20 "github.com/juju/juju/instance" 21 "github.com/juju/juju/juju/testing" 22 "github.com/juju/juju/network" 23 "github.com/juju/juju/provider/dummy" 24 "github.com/juju/juju/state" 25 "github.com/juju/juju/status" 26 coretesting "github.com/juju/juju/testing" 27 "github.com/juju/juju/worker" 28 ) 29 30 var _ = gc.Suite(&workerSuite{}) 31 32 type workerSuite struct { 33 testing.JujuConnSuite 34 35 apiSt api.Connection 36 api *apiinstancepoller.API 37 } 38 39 func (s *workerSuite) SetUpTest(c *gc.C) { 40 s.JujuConnSuite.SetUpTest(c) 41 s.apiSt, _ = s.OpenAPIAsNewMachine(c, state.JobManageModel) 42 s.api = s.apiSt.InstancePoller() 43 } 44 45 func (*workerSuite) instId(i int) instance.Id { 46 return instance.Id(fmt.Sprint(i)) 47 } 48 49 func (*workerSuite) addressesForIndex(i int) []network.Address { 50 return network.NewAddresses(fmt.Sprintf("127.0.0.%d", i)) 51 } 52 53 func (s *workerSuite) TestWorker(c *gc.C) { 54 // Most functionality is already tested in detail - we 55 // just need to test that things are wired together 56 // correctly. 57 58 // TODO(redir): per fwereade these should be in the worker config. 59 s.PatchValue(&ShortPoll, 10*time.Millisecond) 60 s.PatchValue(&LongPoll, 10*time.Millisecond) 61 62 machines, insts := s.setupScenario(c) 63 s.State.StartSync() 64 w, err := NewWorker(Config{ 65 Delay: time.Millisecond * 10, 66 Clock: clock.WallClock, 67 Facade: s.api, 68 Environ: s.Environ, 69 }) 70 c.Assert(err, jc.ErrorIsNil) 71 defer func() { 72 c.Assert(worker.Stop(w), gc.IsNil) 73 }() 74 75 // TODO(perrito666) make this dependent on a juju status 76 checkInstanceInfo := func(index int, m machine, expectedStatus string) bool { 77 isProvisioned := true 78 instanceStatus, err := m.InstanceStatus() 79 if params.IsCodeNotProvisioned(err) { 80 isProvisioned = false 81 } else { 82 c.Assert(err, jc.ErrorIsNil) 83 } 84 providerAddresses, err := m.ProviderAddresses() 85 c.Assert(err, jc.ErrorIsNil) 86 // TODO(perrito666) all providers should use juju statuses instead of message. 87 return reflect.DeepEqual(providerAddresses, s.addressesForIndex(index)) && (!isProvisioned || instanceStatus.Info == expectedStatus) 88 } 89 90 // Wait for the odd numbered machines in the 91 // first half of the machine slice to be given their 92 // addresses and status. 93 for a := coretesting.LongAttempt.Start(); a.Next(); { 94 if !a.HasNext() { 95 c.Fatalf("timed out waiting for instance info") 96 } 97 98 if machinesSatisfy(c, machines, func(i int, m *apiinstancepoller.Machine) bool { 99 if i < len(machines)/2 && i%2 == 1 { 100 return checkInstanceInfo(i, m, "running") 101 } 102 instanceStatus, err := m.InstanceStatus() 103 c.Logf("instance message is: %q", instanceStatus.Info) 104 c.Assert(instanceStatus.Status, gc.Equals, status.Pending.String()) 105 stm, err := s.State.Machine(m.Id()) 106 c.Assert(err, jc.ErrorIsNil) 107 return len(stm.Addresses()) == 0 108 }) { 109 break 110 } 111 } 112 // Now provision the even machines in the first half and watch them get addresses. 113 for i := 0; i < len(insts)/2; i += 2 { 114 m, err := s.State.Machine(machines[i].Id()) 115 c.Assert(err, jc.ErrorIsNil) 116 err = m.SetProvisioned(insts[i].Id(), "nonce", nil) 117 c.Assert(err, jc.ErrorIsNil) 118 dummy.SetInstanceAddresses(insts[i], s.addressesForIndex(i)) 119 dummy.SetInstanceStatus(insts[i], "running") 120 } 121 for a := coretesting.LongAttempt.Start(); a.Next(); { 122 if !a.HasNext() { 123 c.Fatalf("timed out waiting for machine instance info") 124 } 125 if machinesSatisfy(c, machines, func(i int, m *apiinstancepoller.Machine) bool { 126 if i < len(machines)/2 { 127 return checkInstanceInfo(i, m, "running") 128 } 129 // Machines in second half still have no addresses, nor status. 130 instanceStatus, err := m.InstanceStatus() 131 c.Assert(instanceStatus.Status, gc.Equals, status.Pending.String()) 132 stm, err := s.State.Machine(m.Id()) 133 c.Assert(err, jc.ErrorIsNil) 134 return len(stm.Addresses()) == 0 135 }) { 136 break 137 } 138 } 139 140 // Provision the remaining machines and check the address and status. 141 for i := len(insts) / 2; i < len(insts); i++ { 142 if i%2 == 0 { 143 m, err := s.State.Machine(machines[i].Id()) 144 c.Assert(err, jc.ErrorIsNil) 145 err = m.SetProvisioned(insts[i].Id(), "nonce", nil) 146 c.Assert(err, jc.ErrorIsNil) 147 } 148 dummy.SetInstanceAddresses(insts[i], s.addressesForIndex(i)) 149 dummy.SetInstanceStatus(insts[i], "running") 150 } 151 for a := coretesting.LongAttempt.Start(); a.Next(); { 152 if !a.HasNext() { 153 c.Fatalf("timed out waiting for machine instance info") 154 } 155 if machinesSatisfy(c, machines, func(i int, m *apiinstancepoller.Machine) bool { 156 return checkInstanceInfo(i, m, "running") 157 }) { 158 break 159 } 160 } 161 } 162 163 // TODO(rog) 164 // - check that the environment observer is actually hooked up. 165 // - check that the environment observer is stopped. 166 // - check that the errors propagate correctly. 167 168 func machinesSatisfy(c *gc.C, machines []*apiinstancepoller.Machine, f func(i int, m *apiinstancepoller.Machine) bool) bool { 169 for i, m := range machines { 170 err := m.Refresh() 171 c.Assert(err, jc.ErrorIsNil) 172 if !f(i, m) { 173 return false 174 } 175 } 176 return true 177 } 178 179 func (s *workerSuite) setupScenario(c *gc.C) ([]*apiinstancepoller.Machine, []instance.Instance) { 180 var machines []*apiinstancepoller.Machine 181 var insts []instance.Instance 182 for i := 0; i < 10; i++ { 183 m, err := s.State.AddMachine("series", state.JobHostUnits) 184 c.Assert(err, jc.ErrorIsNil) 185 apiMachine, err := s.api.Machine(names.NewMachineTag(m.Id())) 186 c.Assert(err, jc.ErrorIsNil) 187 machines = append(machines, apiMachine) 188 inst, _ := testing.AssertStartInstance(c, s.Environ, s.ControllerConfig.ControllerUUID(), m.Id()) 189 insts = append(insts, inst) 190 } 191 // Associate the odd-numbered machines with an instance. 192 for i := 1; i < len(machines); i += 2 { 193 apiMachine := machines[i] 194 m, err := s.State.Machine(apiMachine.Id()) 195 c.Assert(err, jc.ErrorIsNil) 196 err = m.SetProvisioned(insts[i].Id(), "nonce", nil) 197 c.Assert(err, jc.ErrorIsNil) 198 } 199 // Associate the first half of the instances with an address and status. 200 for i := 0; i < len(machines)/2; i++ { 201 dummy.SetInstanceAddresses(insts[i], s.addressesForIndex(i)) 202 dummy.SetInstanceStatus(insts[i], "running") 203 } 204 // Make sure the second half of the instances have no addresses. 205 for i := len(machines) / 2; i < len(machines); i++ { 206 dummy.SetInstanceAddresses(insts[i], nil) 207 } 208 return machines, insts 209 }