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  }