github.com/niedbalski/juju@v0.0.0-20190215020005-8ff100488e47/apiserver/common/machine_test.go (about) 1 // Copyright 2015 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package common_test 5 6 import ( 7 "github.com/juju/errors" 8 "github.com/juju/naturalsort" 9 jc "github.com/juju/testing/checkers" 10 gc "gopkg.in/check.v1" 11 12 "github.com/juju/juju/apiserver/common" 13 "github.com/juju/juju/apiserver/params" 14 "github.com/juju/juju/core/instance" 15 "github.com/juju/juju/core/status" 16 "github.com/juju/juju/state" 17 "github.com/juju/juju/state/multiwatcher" 18 ) 19 20 type machineSuite struct{} 21 22 var _ = gc.Suite(&machineSuite{}) 23 24 func (s *machineSuite) TestMachineJobFromParams(c *gc.C) { 25 var tests = []struct { 26 name multiwatcher.MachineJob 27 want state.MachineJob 28 err string 29 }{{ 30 name: multiwatcher.JobHostUnits, 31 want: state.JobHostUnits, 32 }, { 33 name: multiwatcher.JobManageModel, 34 want: state.JobManageModel, 35 }, { 36 name: "invalid", 37 want: -1, 38 err: `invalid machine job "invalid"`, 39 }} 40 for _, test := range tests { 41 got, err := common.MachineJobFromParams(test.name) 42 if err != nil { 43 c.Check(err, gc.ErrorMatches, test.err) 44 } 45 c.Check(got, gc.Equals, test.want) 46 } 47 } 48 49 func (s *machineSuite) TestDestroyMachines(c *gc.C) { 50 st := mockState{ 51 machines: map[string]*mockMachine{ 52 "1": {}, 53 "2": {destroyErr: errors.New("unit exists error")}, 54 "3": {life: state.Dying}, 55 }, 56 } 57 err := common.MockableDestroyMachines(&st, false, "1", "2", "3", "4") 58 59 c.Assert(st.machines["1"].Life(), gc.Equals, state.Dying) 60 c.Assert(st.machines["1"].forceDestroyCalled, jc.IsFalse) 61 62 c.Assert(st.machines["2"].Life(), gc.Equals, state.Alive) 63 c.Assert(st.machines["2"].forceDestroyCalled, jc.IsFalse) 64 65 c.Assert(st.machines["3"].forceDestroyCalled, jc.IsFalse) 66 c.Assert(st.machines["3"].destroyCalled, jc.IsFalse) 67 68 c.Assert(err, gc.ErrorMatches, "some machines were not destroyed: unit exists error; machine 4 does not exist") 69 } 70 71 func (s *machineSuite) TestForceDestroyMachines(c *gc.C) { 72 st := mockState{ 73 machines: map[string]*mockMachine{ 74 "1": {}, 75 "2": {life: state.Dying}, 76 }, 77 } 78 err := common.MockableDestroyMachines(&st, true, "1", "2") 79 80 c.Assert(st.machines["1"].Life(), gc.Equals, state.Dying) 81 c.Assert(st.machines["1"].forceDestroyCalled, jc.IsTrue) 82 c.Assert(st.machines["2"].forceDestroyCalled, jc.IsTrue) 83 84 c.Assert(err, jc.ErrorIsNil) 85 } 86 87 func (s *machineSuite) TestMachineHardwareInfo(c *gc.C) { 88 one := uint64(1) 89 amd64 := "amd64" 90 gig := uint64(1024) 91 st := mockState{ 92 machines: map[string]*mockMachine{ 93 "1": {id: "1", life: state.Alive, containerType: instance.NONE, 94 hw: &instance.HardwareCharacteristics{ 95 Arch: &amd64, 96 Mem: &gig, 97 CpuCores: &one, 98 CpuPower: &one, 99 }}, 100 "2": {id: "2", life: state.Alive, containerType: instance.LXD}, 101 "3": {life: state.Dying}, 102 }, 103 } 104 info, err := common.ModelMachineInfo(&st) 105 c.Assert(err, jc.ErrorIsNil) 106 c.Assert(info, jc.DeepEquals, []params.ModelMachineInfo{ 107 { 108 Id: "1", 109 DisplayName: "", 110 Hardware: ¶ms.MachineHardware{ 111 Arch: &amd64, 112 Mem: &gig, 113 Cores: &one, 114 CpuPower: &one, 115 }, 116 }, { 117 Id: "2", 118 DisplayName: "", 119 }, 120 }) 121 } 122 123 func (s *machineSuite) TestMachineInstanceInfo(c *gc.C) { 124 st := mockState{ 125 machines: map[string]*mockMachine{ 126 "1": { 127 id: "1", 128 instId: "123", 129 status: status.Down, 130 hasVote: true, 131 wantsVote: true, 132 }, 133 "2": { 134 id: "2", 135 instId: "456", 136 displayName: "two", 137 status: status.Allocating, 138 hasVote: false, 139 wantsVote: true, 140 }, 141 }, 142 } 143 info, err := common.ModelMachineInfo(&st) 144 c.Assert(err, jc.ErrorIsNil) 145 c.Assert(info, jc.DeepEquals, []params.ModelMachineInfo{ 146 { 147 Id: "1", 148 InstanceId: "123", 149 Status: "down", 150 HasVote: true, 151 WantsVote: true, 152 }, 153 { 154 Id: "2", 155 InstanceId: "456", 156 DisplayName: "two", 157 Status: "allocating", 158 HasVote: false, 159 WantsVote: true, 160 }, 161 }) 162 } 163 164 func (s *machineSuite) TestMachineInstanceInfoWithEmptyDisplayName(c *gc.C) { 165 st := mockState{ 166 machines: map[string]*mockMachine{ 167 "1": { 168 id: "1", 169 instId: "123", 170 displayName: "", 171 status: status.Down, 172 hasVote: true, 173 wantsVote: true, 174 }, 175 }, 176 } 177 info, err := common.ModelMachineInfo(&st) 178 c.Assert(err, jc.ErrorIsNil) 179 c.Assert(info, jc.DeepEquals, []params.ModelMachineInfo{ 180 { 181 Id: "1", 182 InstanceId: "123", 183 DisplayName: "", 184 Status: "down", 185 HasVote: true, 186 WantsVote: true, 187 }, 188 }) 189 } 190 191 func (s *machineSuite) TestMachineInstanceInfoWithSetDisplayName(c *gc.C) { 192 st := mockState{ 193 machines: map[string]*mockMachine{ 194 "1": { 195 id: "1", 196 instId: "123", 197 displayName: "snowflake", 198 status: status.Down, 199 hasVote: true, 200 wantsVote: true, 201 }, 202 }, 203 } 204 info, err := common.ModelMachineInfo(&st) 205 c.Assert(err, jc.ErrorIsNil) 206 c.Assert(info, jc.DeepEquals, []params.ModelMachineInfo{ 207 { 208 Id: "1", 209 InstanceId: "123", 210 DisplayName: "snowflake", 211 Status: "down", 212 HasVote: true, 213 WantsVote: true, 214 }, 215 }) 216 } 217 218 type mockState struct { 219 common.ModelManagerBackend 220 machines map[string]*mockMachine 221 } 222 223 func (st *mockState) Machine(id string) (common.Machine, error) { 224 if m, ok := st.machines[id]; ok { 225 return m, nil 226 } 227 return nil, errors.Errorf("machine %s does not exist", id) 228 } 229 230 func (st *mockState) AllMachines() (machines []common.Machine, _ error) { 231 // Ensure we get machines in id order. 232 var ids []string 233 for id := range st.machines { 234 ids = append(ids, id) 235 } 236 naturalsort.Sort(ids) 237 for _, id := range ids { 238 machines = append(machines, st.machines[id]) 239 } 240 return machines, nil 241 } 242 243 type mockMachine struct { 244 state.Machine 245 id string 246 life state.Life 247 containerType instance.ContainerType 248 hw *instance.HardwareCharacteristics 249 instId instance.Id 250 displayName string 251 hasVote, wantsVote bool 252 status status.Status 253 statusErr error 254 destroyErr error 255 forceDestroyErr error 256 forceDestroyCalled bool 257 destroyCalled bool 258 agentDead bool 259 presenceErr error 260 } 261 262 func (m *mockMachine) Id() string { 263 return m.id 264 } 265 266 func (m *mockMachine) Life() state.Life { 267 return m.life 268 } 269 270 func (m *mockMachine) InstanceId() (instance.Id, error) { 271 return m.instId, nil 272 } 273 274 func (m *mockMachine) InstanceNames() (instance.Id, string, error) { 275 instId, err := m.InstanceId() 276 return instId, m.displayName, err 277 } 278 279 func (m *mockMachine) WantsVote() bool { 280 return m.wantsVote 281 } 282 283 func (m *mockMachine) HasVote() bool { 284 return m.hasVote 285 } 286 287 func (m *mockMachine) Status() (status.StatusInfo, error) { 288 return status.StatusInfo{ 289 Status: m.status, 290 }, m.statusErr 291 } 292 293 func (m *mockMachine) HardwareCharacteristics() (*instance.HardwareCharacteristics, error) { 294 return m.hw, nil 295 } 296 297 func (m *mockMachine) AgentPresence() (bool, error) { 298 return !m.agentDead, m.presenceErr 299 } 300 301 func (m *mockMachine) ForceDestroy() error { 302 m.forceDestroyCalled = true 303 if m.forceDestroyErr != nil { 304 return m.forceDestroyErr 305 } 306 m.life = state.Dying 307 return nil 308 } 309 310 func (m *mockMachine) Destroy() error { 311 m.destroyCalled = true 312 if m.destroyErr != nil { 313 return m.destroyErr 314 } 315 m.life = state.Dying 316 return nil 317 }