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