github.com/makyo/juju@v0.0.0-20160425123129-2608902037e9/state/constraintsvalidation_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 jc "github.com/juju/testing/checkers" 8 gc "gopkg.in/check.v1" 9 10 "github.com/juju/juju/constraints" 11 "github.com/juju/juju/environs/config" 12 "github.com/juju/juju/state" 13 ) 14 15 type constraintsValidationSuite struct { 16 ConnSuite 17 } 18 19 var _ = gc.Suite(&constraintsValidationSuite{}) 20 21 func (s *constraintsValidationSuite) SetUpTest(c *gc.C) { 22 s.ConnSuite.SetUpTest(c) 23 s.policy.GetConstraintsValidator = func(*config.Config, state.SupportedArchitecturesQuerier) (constraints.Validator, error) { 24 validator := constraints.NewValidator() 25 validator.RegisterConflicts( 26 []string{constraints.InstanceType}, 27 []string{constraints.Mem, constraints.Arch}, 28 ) 29 validator.RegisterUnsupported([]string{constraints.CpuPower}) 30 return validator, nil 31 } 32 } 33 34 func (s *constraintsValidationSuite) addOneMachine(c *gc.C, cons constraints.Value) (*state.Machine, error) { 35 return s.State.AddOneMachine(state.MachineTemplate{ 36 Series: "quantal", 37 Jobs: []state.MachineJob{state.JobHostUnits}, 38 Constraints: cons, 39 }) 40 } 41 42 var setConstraintsTests = []struct { 43 about string 44 consToSet string 45 consFallback string 46 47 effectiveModelCons string // model constraints after setting consFallback 48 effectiveServiceCons string // service constraints after setting consToSet 49 effectiveUnitCons string // unit constraints after setting consToSet on the service 50 effectiveMachineCons string // machine constraints after setting consToSet 51 }{{ 52 about: "(implictly) empty constraints are OK and stored as empty", 53 consToSet: "", 54 consFallback: "", 55 56 effectiveModelCons: "", 57 effectiveServiceCons: "", 58 effectiveUnitCons: "", 59 effectiveMachineCons: "", 60 }, { 61 about: "(implicitly) empty fallback constraints never override set constraints", 62 consToSet: "instance-type=foo-42 cpu-power=9001 spaces=bar", 63 consFallback: "", 64 65 effectiveModelCons: "", // model constraints are stored as empty. 66 // i.e. there are no fallbacks and all the following cases are the same. 67 effectiveServiceCons: "instance-type=foo-42 cpu-power=9001 spaces=bar", 68 effectiveUnitCons: "instance-type=foo-42 cpu-power=9001 spaces=bar", 69 effectiveMachineCons: "instance-type=foo-42 cpu-power=9001 spaces=bar", 70 }, { 71 about: "(implicitly) empty constraints never override explictly set fallbacks", 72 consToSet: "", 73 consFallback: "arch=amd64 cpu-cores=42 mem=2G tags=foo", 74 75 effectiveModelCons: "arch=amd64 cpu-cores=42 mem=2G tags=foo", 76 effectiveServiceCons: "", // set as given. 77 effectiveUnitCons: "arch=amd64 cpu-cores=42 mem=2G tags=foo", 78 // set as given, then merged with fallbacks; since consToSet is 79 // empty, the effective values inherit everything from fallbacks; 80 // like the unit, but only because the service constraints are 81 // also empty. 82 effectiveMachineCons: "arch=amd64 cpu-cores=42 mem=2G tags=foo", 83 }, { 84 about: "(explicitly) empty constraints are OK and stored as given", 85 consToSet: "cpu-cores= cpu-power= root-disk= instance-type= container= tags= spaces=", 86 consFallback: "", 87 88 effectiveModelCons: "", 89 effectiveServiceCons: "cpu-cores= cpu-power= root-disk= instance-type= container= tags= spaces=", 90 effectiveUnitCons: "cpu-cores= cpu-power= root-disk= instance-type= container= tags= spaces=", 91 effectiveMachineCons: "cpu-cores= cpu-power= instance-type= root-disk= tags= spaces=", // container= is dropped 92 }, { 93 about: "(explicitly) empty fallback constraints are OK and stored as given", 94 consToSet: "", 95 consFallback: "cpu-cores= cpu-power= root-disk= instance-type= container= tags= spaces=", 96 97 effectiveModelCons: "cpu-cores= cpu-power= root-disk= instance-type= container= tags= spaces=", 98 effectiveServiceCons: "", 99 effectiveUnitCons: "cpu-cores= cpu-power= root-disk= instance-type= container= tags= spaces=", 100 effectiveMachineCons: "cpu-cores= cpu-power= instance-type= root-disk= tags= spaces=", // container= is dropped 101 }, { 102 about: "(explicitly) empty constraints and fallbacks are OK and stored as given", 103 consToSet: "arch= mem= cpu-cores= container=", 104 consFallback: "cpu-cores= cpu-power= root-disk= instance-type= container= tags= spaces=", 105 effectiveModelCons: "cpu-cores= cpu-power= root-disk= instance-type= container= tags= spaces=", 106 effectiveServiceCons: "arch= mem= cpu-cores= container=", 107 effectiveUnitCons: "arch= container= cpu-cores= cpu-power= mem= root-disk= tags= spaces=", 108 effectiveMachineCons: "arch= cpu-cores= cpu-power= mem= root-disk= tags= spaces=", // container= is dropped 109 }, { 110 about: "(explicitly) empty constraints override set fallbacks for deployment and provisioning", 111 consToSet: "cpu-cores= arch= spaces= cpu-power=", 112 consFallback: "cpu-cores=42 arch=amd64 tags=foo spaces=default,^dmz mem=4G", 113 114 effectiveModelCons: "cpu-cores=42 arch=amd64 tags=foo spaces=default,^dmz mem=4G", 115 effectiveServiceCons: "cpu-cores= arch= spaces= cpu-power=", 116 effectiveUnitCons: "arch= cpu-cores= cpu-power= mem=4G tags=foo spaces=", 117 effectiveMachineCons: "arch= cpu-cores= cpu-power= mem=4G tags=foo spaces=", 118 // we're also checking if m.SetConstraints() does the same with 119 // regards to the effective constraints as AddMachine(), because 120 // some of these tests proved they had different behavior (i.e. 121 // container= was not set to empty) 122 }, { 123 about: "non-empty constraints always override empty or unset fallbacks", 124 consToSet: "cpu-cores=42 root-disk=20G arch=amd64 tags=foo,bar", 125 consFallback: "cpu-cores= arch= tags=", 126 127 effectiveModelCons: "cpu-cores= arch= tags=", 128 effectiveServiceCons: "cpu-cores=42 root-disk=20G arch=amd64 tags=foo,bar", 129 effectiveUnitCons: "cpu-cores=42 root-disk=20G arch=amd64 tags=foo,bar", 130 effectiveMachineCons: "cpu-cores=42 root-disk=20G arch=amd64 tags=foo,bar", 131 }, { 132 about: "non-empty constraints always override set fallbacks", 133 consToSet: "cpu-cores=42 root-disk=20G arch=amd64 tags=foo,bar", 134 consFallback: "cpu-cores=12 root-disk=10G arch=i386 tags=bar", 135 136 effectiveModelCons: "cpu-cores=12 root-disk=10G arch=i386 tags=bar", 137 effectiveServiceCons: "cpu-cores=42 root-disk=20G arch=amd64 tags=foo,bar", 138 effectiveUnitCons: "cpu-cores=42 root-disk=20G arch=amd64 tags=foo,bar", 139 effectiveMachineCons: "cpu-cores=42 root-disk=20G arch=amd64 tags=foo,bar", 140 }, { 141 about: "non-empty constraints override conflicting set fallbacks", 142 consToSet: "mem=8G arch=amd64 cpu-cores=4 tags=bar", 143 consFallback: "instance-type=small cpu-power=1000", // instance-type conflicts mem, arch 144 145 effectiveModelCons: "instance-type=small cpu-power=1000", 146 effectiveServiceCons: "mem=8G arch=amd64 cpu-cores=4 tags=bar", 147 // both of the following contain the explicitly set constraints after 148 // resolving any conflicts with fallbacks (by dropping them). 149 effectiveUnitCons: "mem=8G arch=amd64 cpu-cores=4 tags=bar cpu-power=1000", 150 effectiveMachineCons: "mem=8G arch=amd64 cpu-cores=4 tags=bar cpu-power=1000", 151 }, { 152 about: "set fallbacks are overriden the same way for provisioning and deployment", 153 consToSet: "tags= cpu-power= spaces=bar", 154 consFallback: "tags=foo cpu-power=42", 155 156 // a variation of the above case showing there's no difference 157 // between deployment (service, unit) and provisioning (machine) 158 // constraints when it comes to effective values. 159 effectiveModelCons: "tags=foo cpu-power=42", 160 effectiveServiceCons: "cpu-power= tags= spaces=bar", 161 effectiveUnitCons: "cpu-power= tags= spaces=bar", 162 effectiveMachineCons: "cpu-power= tags= spaces=bar", 163 }, { 164 about: "container type can only be used for deployment, not provisioning", 165 consToSet: "container=kvm arch=amd64", 166 consFallback: "container=lxc mem=8G", 167 168 // service deployment constraints are transformed into machine 169 // provisioning constraints, and the container type only makes 170 // sense currently as a deployment constraint, so it's cleared 171 // when merging service/model deployment constraints into 172 // effective machine provisioning constraints. 173 effectiveModelCons: "container=lxc mem=8G", 174 effectiveServiceCons: "container=kvm arch=amd64", 175 effectiveUnitCons: "container=kvm mem=8G arch=amd64", 176 effectiveMachineCons: "mem=8G arch=amd64", 177 }} 178 179 func (s *constraintsValidationSuite) TestMachineConstraints(c *gc.C) { 180 for i, t := range setConstraintsTests { 181 c.Logf( 182 "test %d: %s\nconsToSet: %q\nconsFallback: %q\n", 183 i, t.about, t.consToSet, t.consFallback, 184 ) 185 // Set fallbacks as model constraints and verify them. 186 err := s.State.SetModelConstraints(constraints.MustParse(t.consFallback)) 187 c.Check(err, jc.ErrorIsNil) 188 econs, err := s.State.ModelConstraints() 189 c.Check(econs, jc.DeepEquals, constraints.MustParse(t.effectiveModelCons)) 190 // Set the machine provisioning constraints. 191 m, err := s.addOneMachine(c, constraints.MustParse(t.consToSet)) 192 c.Check(err, jc.ErrorIsNil) 193 // New machine provisioning constraints get merged with the fallbacks. 194 cons, err := m.Constraints() 195 c.Check(err, jc.ErrorIsNil) 196 c.Check(cons, jc.DeepEquals, constraints.MustParse(t.effectiveMachineCons)) 197 // Changing them should result in the same result before provisioning. 198 err = m.SetConstraints(constraints.MustParse(t.consToSet)) 199 c.Check(err, jc.ErrorIsNil) 200 cons, err = m.Constraints() 201 c.Check(err, jc.ErrorIsNil) 202 c.Check(cons, jc.DeepEquals, constraints.MustParse(t.effectiveMachineCons)) 203 } 204 } 205 206 func (s *constraintsValidationSuite) TestServiceConstraints(c *gc.C) { 207 charm := s.AddTestingCharm(c, "wordpress") 208 service := s.AddTestingService(c, "wordpress", charm) 209 for i, t := range setConstraintsTests { 210 c.Logf( 211 "test %d: %s\nconsToSet: %q\nconsFallback: %q\n", 212 i, t.about, t.consToSet, t.consFallback, 213 ) 214 // Set fallbacks as model constraints and verify them. 215 err := s.State.SetModelConstraints(constraints.MustParse(t.consFallback)) 216 c.Check(err, jc.ErrorIsNil) 217 econs, err := s.State.ModelConstraints() 218 c.Check(econs, jc.DeepEquals, constraints.MustParse(t.effectiveModelCons)) 219 // Set the service deployment constraints. 220 err = service.SetConstraints(constraints.MustParse(t.consToSet)) 221 c.Check(err, jc.ErrorIsNil) 222 u, err := service.AddUnit() 223 c.Check(err, jc.ErrorIsNil) 224 // New unit deployment constraints get merged with the fallbacks. 225 ucons, err := u.Constraints() 226 c.Check(err, jc.ErrorIsNil) 227 c.Check(*ucons, jc.DeepEquals, constraints.MustParse(t.effectiveUnitCons)) 228 // Service constraints remain as set. 229 scons, err := service.Constraints() 230 c.Check(err, jc.ErrorIsNil) 231 c.Check(scons, jc.DeepEquals, constraints.MustParse(t.effectiveServiceCons)) 232 } 233 }