github.com/axw/juju@v0.0.0-20161005053422-4bd6544d08d4/state/prechecker_test.go (about)

     1  // Copyright 2014 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package state_test
     5  
     6  import (
     7  	"fmt"
     8  
     9  	"github.com/juju/errors"
    10  	jc "github.com/juju/testing/checkers"
    11  	gc "gopkg.in/check.v1"
    12  
    13  	"github.com/juju/juju/agent"
    14  	"github.com/juju/juju/constraints"
    15  	"github.com/juju/juju/instance"
    16  	"github.com/juju/juju/state"
    17  )
    18  
    19  type PrecheckerSuite struct {
    20  	ConnSuite
    21  	prechecker mockPrechecker
    22  }
    23  
    24  var _ = gc.Suite(&PrecheckerSuite{})
    25  
    26  type mockPrechecker struct {
    27  	precheckInstanceError       error
    28  	precheckInstanceSeries      string
    29  	precheckInstanceConstraints constraints.Value
    30  	precheckInstancePlacement   string
    31  }
    32  
    33  func (p *mockPrechecker) PrecheckInstance(series string, cons constraints.Value, placement string) error {
    34  	p.precheckInstanceSeries = series
    35  	p.precheckInstanceConstraints = cons
    36  	p.precheckInstancePlacement = placement
    37  	return p.precheckInstanceError
    38  }
    39  
    40  func (s *PrecheckerSuite) SetUpTest(c *gc.C) {
    41  	s.ConnSuite.SetUpTest(c)
    42  	s.prechecker = mockPrechecker{}
    43  	s.policy.GetPrechecker = func() (state.Prechecker, error) {
    44  		return &s.prechecker, nil
    45  	}
    46  }
    47  
    48  func (s *PrecheckerSuite) TestPrecheckInstance(c *gc.C) {
    49  	// PrecheckInstance should be called with the specified
    50  	// series and placement, and the specified constraints
    51  	// merged with the model constraints, when attempting
    52  	// to create an instance.
    53  	envCons := constraints.MustParse("mem=4G")
    54  	placement := "abc123"
    55  	template, err := s.addOneMachine(c, envCons, placement)
    56  	c.Assert(err, jc.ErrorIsNil)
    57  	c.Assert(s.prechecker.precheckInstanceSeries, gc.Equals, template.Series)
    58  	c.Assert(s.prechecker.precheckInstancePlacement, gc.Equals, placement)
    59  	validator := constraints.NewValidator()
    60  	cons, err := validator.Merge(envCons, template.Constraints)
    61  	c.Assert(err, jc.ErrorIsNil)
    62  	c.Assert(s.prechecker.precheckInstanceConstraints, gc.DeepEquals, cons)
    63  }
    64  
    65  func (s *PrecheckerSuite) TestPrecheckErrors(c *gc.C) {
    66  	// Ensure that AddOneMachine fails when PrecheckInstance returns an error.
    67  	s.prechecker.precheckInstanceError = fmt.Errorf("no instance for you")
    68  	_, err := s.addOneMachine(c, constraints.Value{}, "placement")
    69  	c.Assert(err, gc.ErrorMatches, ".*no instance for you")
    70  
    71  	// If the policy's Prechecker method fails, that will be returned first.
    72  	s.policy.GetPrechecker = func() (state.Prechecker, error) {
    73  		return nil, fmt.Errorf("no prechecker for you")
    74  	}
    75  	_, err = s.addOneMachine(c, constraints.Value{}, "placement")
    76  	c.Assert(err, gc.ErrorMatches, ".*no prechecker for you")
    77  }
    78  
    79  func (s *PrecheckerSuite) TestPrecheckPrecheckerUnimplemented(c *gc.C) {
    80  	var precheckerErr error
    81  	s.policy.GetPrechecker = func() (state.Prechecker, error) {
    82  		return nil, precheckerErr
    83  	}
    84  	_, err := s.addOneMachine(c, constraints.Value{}, "placement")
    85  	c.Assert(err, gc.ErrorMatches, "cannot add a new machine: policy returned nil prechecker without an error")
    86  	precheckerErr = errors.NotImplementedf("Prechecker")
    87  	_, err = s.addOneMachine(c, constraints.Value{}, "placement")
    88  	c.Assert(err, jc.ErrorIsNil)
    89  }
    90  
    91  func (s *PrecheckerSuite) TestPrecheckNoPolicy(c *gc.C) {
    92  	s.policy.GetPrechecker = func() (state.Prechecker, error) {
    93  		c.Errorf("should not have been invoked")
    94  		return nil, nil
    95  	}
    96  	state.SetPolicy(s.State, nil)
    97  	_, err := s.addOneMachine(c, constraints.Value{}, "placement")
    98  	c.Assert(err, jc.ErrorIsNil)
    99  }
   100  
   101  func (s *PrecheckerSuite) addOneMachine(c *gc.C, envCons constraints.Value, placement string) (state.MachineTemplate, error) {
   102  	err := s.State.SetModelConstraints(envCons)
   103  	c.Assert(err, jc.ErrorIsNil)
   104  	oneJob := []state.MachineJob{state.JobHostUnits}
   105  	extraCons := constraints.MustParse("cores=4")
   106  	template := state.MachineTemplate{
   107  		Series:      "precise",
   108  		Constraints: extraCons,
   109  		Jobs:        oneJob,
   110  		Placement:   placement,
   111  	}
   112  	_, err = s.State.AddOneMachine(template)
   113  	return template, err
   114  }
   115  
   116  func (s *PrecheckerSuite) TestPrecheckInstanceInjectMachine(c *gc.C) {
   117  	template := state.MachineTemplate{
   118  		InstanceId: instance.Id("bootstrap"),
   119  		Series:     "precise",
   120  		Nonce:      agent.BootstrapNonce,
   121  		Jobs:       []state.MachineJob{state.JobManageModel},
   122  		Placement:  "anyoldthing",
   123  	}
   124  	_, err := s.State.AddOneMachine(template)
   125  	c.Assert(err, jc.ErrorIsNil)
   126  	// PrecheckInstance should not have been called, as we've
   127  	// injected a machine with an existing instance.
   128  	c.Assert(s.prechecker.precheckInstanceSeries, gc.Equals, "")
   129  	c.Assert(s.prechecker.precheckInstancePlacement, gc.Equals, "")
   130  }
   131  
   132  func (s *PrecheckerSuite) TestPrecheckContainerNewMachine(c *gc.C) {
   133  	// Attempting to add a container to a new machine should cause
   134  	// PrecheckInstance to be called.
   135  	template := state.MachineTemplate{
   136  		Series:    "precise",
   137  		Jobs:      []state.MachineJob{state.JobHostUnits},
   138  		Placement: "intertubes",
   139  	}
   140  	_, err := s.State.AddMachineInsideNewMachine(template, template, instance.LXD)
   141  	c.Assert(err, jc.ErrorIsNil)
   142  	c.Assert(s.prechecker.precheckInstanceSeries, gc.Equals, template.Series)
   143  	c.Assert(s.prechecker.precheckInstancePlacement, gc.Equals, template.Placement)
   144  }