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  }