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