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