github.com/niedbalski/juju@v0.0.0-20190215020005-8ff100488e47/provider/gce/google/conn_instance_test.go (about) 1 // Copyright 2014 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package google_test 5 6 import ( 7 "github.com/juju/errors" 8 jc "github.com/juju/testing/checkers" 9 "google.golang.org/api/compute/v1" 10 gc "gopkg.in/check.v1" 11 12 "github.com/juju/juju/provider/gce/google" 13 ) 14 15 func (s *connSuite) TestConnectionSimpleAddInstance(c *gc.C) { 16 s.FakeConn.Instance = &s.RawInstanceFull 17 18 inst := &s.RawInstance 19 err := google.ConnAddInstance(s.Conn, inst, "mtype", "a-zone") 20 c.Assert(err, jc.ErrorIsNil) 21 22 c.Check(inst, jc.DeepEquals, &s.RawInstanceFull) 23 } 24 25 func (s *connSuite) TestConnectionSimpleAddInstanceAPI(c *gc.C) { 26 s.FakeConn.Instance = &s.RawInstanceFull 27 expected := s.RawInstance 28 expected.MachineType = "zones/a-zone/machineTypes/mtype" 29 30 inst := &s.RawInstance 31 err := google.ConnAddInstance(s.Conn, inst, "mtype", "a-zone") 32 c.Assert(err, jc.ErrorIsNil) 33 34 c.Check(s.FakeConn.Calls, gc.HasLen, 2) 35 c.Check(s.FakeConn.Calls[0].FuncName, gc.Equals, "AddInstance") 36 c.Check(s.FakeConn.Calls[0].ProjectID, gc.Equals, "spam") 37 c.Check(s.FakeConn.Calls[0].ZoneName, gc.Equals, "a-zone") 38 c.Check(s.FakeConn.Calls[0].InstValue, gc.DeepEquals, expected) 39 c.Check(s.FakeConn.Calls[1].FuncName, gc.Equals, "GetInstance") 40 c.Check(s.FakeConn.Calls[1].ProjectID, gc.Equals, "spam") 41 c.Check(s.FakeConn.Calls[1].ZoneName, gc.Equals, "a-zone") 42 c.Check(s.FakeConn.Calls[1].ID, gc.Equals, "spam") 43 } 44 45 func (s *instanceSuite) TestConnectionAddInstance(c *gc.C) { 46 s.FakeConn.Instance = &s.RawInstanceFull 47 48 inst, err := s.Conn.AddInstance(s.InstanceSpec) 49 c.Assert(err, jc.ErrorIsNil) 50 51 c.Check(inst.ID, gc.Equals, "spam") 52 c.Check(inst.ZoneName, gc.Equals, "a-zone") 53 c.Check(inst.Status(), gc.Equals, google.StatusRunning) 54 c.Check(inst.Metadata(), jc.DeepEquals, s.Metadata) 55 c.Check(inst.Addresses(), jc.DeepEquals, s.Addresses) 56 spec := google.GetInstanceSpec(inst) 57 c.Check(spec, gc.DeepEquals, &s.InstanceSpec) 58 } 59 60 func (s *instanceSuite) TestConnectionAddInstanceAPI(c *gc.C) { 61 s.FakeConn.Instance = &s.RawInstanceFull 62 63 _, err := s.Conn.AddInstance(s.InstanceSpec) 64 c.Assert(err, jc.ErrorIsNil) 65 66 c.Check(s.FakeConn.Calls, gc.HasLen, 2) 67 c.Check(s.FakeConn.Calls[0].FuncName, gc.Equals, "AddInstance") 68 c.Check(s.FakeConn.Calls[0].ProjectID, gc.Equals, "spam") 69 // We check s.FakeConn.Calls[0].InstValue below. 70 c.Check(s.FakeConn.Calls[0].ZoneName, gc.Equals, "a-zone") 71 c.Check(s.FakeConn.Calls[1].FuncName, gc.Equals, "GetInstance") 72 c.Check(s.FakeConn.Calls[1].ProjectID, gc.Equals, "spam") 73 c.Check(s.FakeConn.Calls[1].ID, gc.Equals, "spam") 74 c.Check(s.FakeConn.Calls[1].ZoneName, gc.Equals, "a-zone") 75 76 metadata := compute.Metadata{Items: []*compute.MetadataItems{{ 77 Key: "eggs", 78 Value: google.StringPtr("steak"), 79 }}} 80 networkInterfaces := []*compute.NetworkInterface{{ 81 Network: "global/networks/somenetwork", 82 AccessConfigs: []*compute.AccessConfig{{ 83 Name: "somenetif", 84 Type: "ONE_TO_ONE_NAT", 85 }}, 86 }} 87 attachedDisks := []*compute.AttachedDisk{{ 88 Type: "PERSISTENT", 89 Boot: true, 90 Mode: "READ_WRITE", 91 AutoDelete: true, 92 InitializeParams: &compute.AttachedDiskInitializeParams{ 93 DiskSizeGb: 15, 94 SourceImage: "some/image/path", 95 }, 96 }} 97 c.Check(s.FakeConn.Calls[0].InstValue, gc.DeepEquals, compute.Instance{ 98 Name: "spam", 99 MachineType: "zones/a-zone/machineTypes/mtype", 100 Disks: attachedDisks, 101 NetworkInterfaces: networkInterfaces, 102 Metadata: &metadata, 103 Tags: &compute.Tags{Items: []string{"spam"}}, 104 }) 105 } 106 107 func (s *connSuite) TestConnectionAddInstanceFailed(c *gc.C) { 108 s.FakeConn.Instance = &s.RawInstanceFull 109 110 failure := errors.New("unknown") 111 s.FakeConn.Err = failure 112 113 err := google.ConnAddInstance(s.Conn, &s.RawInstance, "mtype", "a-zone") 114 115 c.Check(errors.Cause(err), gc.Equals, failure) 116 } 117 118 func (s *connSuite) TestConnectionAddInstanceWaitFailed(c *gc.C) { 119 s.FakeConn.Instance = &s.RawInstanceFull 120 121 failure := s.NewWaitError(nil, errors.New("unknown")) 122 s.FakeConn.Err = failure 123 124 err := google.ConnAddInstance(s.Conn, &s.RawInstance, "mtype", "a-zone") 125 126 c.Check(errors.Cause(err), gc.Equals, failure) 127 } 128 129 func (s *connSuite) TestConnectionAddInstanceGetFailed(c *gc.C) { 130 s.FakeConn.Instance = &s.RawInstanceFull 131 132 failure := errors.New("unknown") 133 s.FakeConn.Err = failure 134 s.FakeConn.FailOnCall = 1 135 136 err := google.ConnAddInstance(s.Conn, &s.RawInstance, "mtype", "a-zone") 137 138 c.Check(errors.Cause(err), gc.Equals, failure) 139 c.Check(s.FakeConn.Calls, gc.HasLen, 2) 140 } 141 142 func (s *connSuite) TestConnectionInstance(c *gc.C) { 143 s.FakeConn.Instance = &s.RawInstanceFull 144 145 inst, err := s.Conn.Instance("spam", "a-zone") 146 c.Assert(err, jc.ErrorIsNil) 147 148 c.Check(inst.ID, gc.Equals, "spam") 149 c.Check(inst.ZoneName, gc.Equals, "a-zone") 150 c.Check(inst.Status(), gc.Equals, google.StatusRunning) 151 c.Check(inst.Metadata(), jc.DeepEquals, s.Metadata) 152 c.Check(inst.Addresses(), jc.DeepEquals, s.Addresses) 153 spec := google.GetInstanceSpec(&inst) 154 c.Check(spec, gc.IsNil) 155 } 156 157 func (s *connSuite) TestConnectionInstanceAPI(c *gc.C) { 158 s.FakeConn.Instance = &s.RawInstanceFull 159 160 _, err := s.Conn.Instance("ham", "a-zone") 161 c.Assert(err, jc.ErrorIsNil) 162 163 c.Check(s.FakeConn.Calls, gc.HasLen, 1) 164 c.Check(s.FakeConn.Calls[0].FuncName, gc.Equals, "GetInstance") 165 c.Check(s.FakeConn.Calls[0].ProjectID, gc.Equals, "spam") 166 c.Check(s.FakeConn.Calls[0].ID, gc.Equals, "ham") 167 c.Check(s.FakeConn.Calls[0].ZoneName, gc.Equals, "a-zone") 168 } 169 170 func (s *connSuite) TestConnectionInstanceFail(c *gc.C) { 171 failure := errors.New("<unknown>") 172 s.FakeConn.Err = failure 173 174 _, err := s.Conn.Instance("spam", "a-zone") 175 176 c.Check(errors.Cause(err), gc.Equals, failure) 177 } 178 179 func (s *connSuite) TestConnectionInstances(c *gc.C) { 180 s.FakeConn.Instances = []*compute.Instance{&s.RawInstanceFull} 181 182 insts, err := s.Conn.Instances("sp", google.StatusRunning) 183 c.Assert(err, jc.ErrorIsNil) 184 185 google.SetInstanceSpec(&s.Instance, nil) 186 c.Check(insts, jc.DeepEquals, []google.Instance{s.Instance}) 187 } 188 189 func (s *connSuite) TestConnectionInstancesFailure(c *gc.C) { 190 failure := errors.New("<unknown>") 191 s.FakeConn.Err = failure 192 _, err := s.Conn.Instances("sp", google.StatusRunning) 193 194 c.Check(errors.Cause(err), gc.Equals, failure) 195 } 196 197 func (s *connSuite) TestConnectionRemoveInstance(c *gc.C) { 198 err := google.ConnRemoveInstance(s.Conn, "spam", "a-zone") 199 200 c.Check(err, jc.ErrorIsNil) 201 } 202 203 func (s *connSuite) TestConnectionRemoveInstanceAPI(c *gc.C) { 204 err := google.ConnRemoveInstance(s.Conn, "spam", "a-zone") 205 c.Assert(err, jc.ErrorIsNil) 206 207 c.Check(s.FakeConn.Calls, gc.HasLen, 2) 208 c.Check(s.FakeConn.Calls[0].FuncName, gc.Equals, "RemoveInstance") 209 c.Check(s.FakeConn.Calls[0].ProjectID, gc.Equals, "spam") 210 c.Check(s.FakeConn.Calls[0].ZoneName, gc.Equals, "a-zone") 211 c.Check(s.FakeConn.Calls[0].ID, gc.Equals, "spam") 212 c.Check(s.FakeConn.Calls[1].FuncName, gc.Equals, "RemoveFirewall") 213 c.Check(s.FakeConn.Calls[1].ProjectID, gc.Equals, "spam") 214 c.Check(s.FakeConn.Calls[1].Name, gc.Equals, "spam") 215 } 216 217 func (s *connSuite) TestConnectionRemoveInstanceFailed(c *gc.C) { 218 failure := errors.New("<unknown>") 219 s.FakeConn.Err = failure 220 221 err := google.ConnRemoveInstance(s.Conn, "spam", "a-zone") 222 223 c.Check(errors.Cause(err), gc.Equals, failure) 224 } 225 226 func (s *connSuite) TestConnectionRemoveInstanceFirewallFailed(c *gc.C) { 227 failure := errors.New("<unknown>") 228 s.FakeConn.Err = failure 229 s.FakeConn.FailOnCall = 1 230 231 err := google.ConnRemoveInstance(s.Conn, "spam", "a-zone") 232 233 c.Check(errors.Cause(err), gc.Equals, failure) 234 c.Check(s.FakeConn.Calls, gc.HasLen, 2) 235 } 236 237 func (s *connSuite) TestConnectionRemoveInstances(c *gc.C) { 238 s.FakeConn.Instances = []*compute.Instance{&s.RawInstanceFull} 239 240 err := s.Conn.RemoveInstances("sp", "spam") 241 242 c.Check(err, jc.ErrorIsNil) 243 } 244 245 func (s *connSuite) TestConnectionRemoveInstancesAPI(c *gc.C) { 246 s.FakeConn.Instances = []*compute.Instance{&s.RawInstanceFull} 247 248 err := s.Conn.RemoveInstances("sp", "spam") 249 c.Assert(err, jc.ErrorIsNil) 250 251 c.Check(s.FakeConn.Calls, gc.HasLen, 3) 252 c.Check(s.FakeConn.Calls[0].FuncName, gc.Equals, "ListInstances") 253 c.Check(s.FakeConn.Calls[1].FuncName, gc.Equals, "RemoveInstance") 254 c.Check(s.FakeConn.Calls[1].ID, gc.Equals, "spam") 255 c.Check(s.FakeConn.Calls[2].FuncName, gc.Equals, "RemoveFirewall") 256 c.Check(s.FakeConn.Calls[2].Name, gc.Equals, "spam") 257 } 258 259 func (s *connSuite) TestConnectionRemoveInstancesMultiple(c *gc.C) { 260 s.FakeConn.Instances = []*compute.Instance{ 261 &s.RawInstanceFull, 262 { 263 Name: "special", 264 Zone: "a-zone", 265 }, 266 } 267 268 err := s.Conn.RemoveInstances("", "spam", "special") 269 c.Assert(err, jc.ErrorIsNil) 270 271 c.Check(s.FakeConn.Calls, gc.HasLen, 5) 272 c.Check(s.FakeConn.Calls[0].FuncName, gc.Equals, "ListInstances") 273 c.Check(s.FakeConn.Calls[1].FuncName, gc.Equals, "RemoveInstance") 274 c.Check(s.FakeConn.Calls[1].ID, gc.Equals, "spam") 275 c.Check(s.FakeConn.Calls[2].FuncName, gc.Equals, "RemoveFirewall") 276 c.Check(s.FakeConn.Calls[2].Name, gc.Equals, "spam") 277 c.Check(s.FakeConn.Calls[3].FuncName, gc.Equals, "RemoveInstance") 278 c.Check(s.FakeConn.Calls[3].ID, gc.Equals, "special") 279 c.Check(s.FakeConn.Calls[4].FuncName, gc.Equals, "RemoveFirewall") 280 c.Check(s.FakeConn.Calls[4].Name, gc.Equals, "special") 281 } 282 283 func (s *connSuite) TestConnectionRemoveInstancesPartialMatch(c *gc.C) { 284 s.FakeConn.Instances = []*compute.Instance{ 285 &s.RawInstanceFull, 286 { 287 Name: "special", 288 Zone: "a-zone", 289 }, 290 } 291 292 err := s.Conn.RemoveInstances("", "spam") 293 c.Assert(err, jc.ErrorIsNil) 294 295 c.Check(s.FakeConn.Calls, gc.HasLen, 3) 296 c.Check(s.FakeConn.Calls[0].FuncName, gc.Equals, "ListInstances") 297 c.Check(s.FakeConn.Calls[1].FuncName, gc.Equals, "RemoveInstance") 298 c.Check(s.FakeConn.Calls[1].ID, gc.Equals, "spam") 299 c.Check(s.FakeConn.Calls[2].FuncName, gc.Equals, "RemoveFirewall") 300 c.Check(s.FakeConn.Calls[2].Name, gc.Equals, "spam") 301 } 302 303 func (s *connSuite) TestConnectionRemoveInstancesListFailed(c *gc.C) { 304 failure := errors.New("<unknown>") 305 s.FakeConn.Err = failure 306 307 err := s.Conn.RemoveInstances("sp", "spam") 308 309 c.Check(errors.Cause(err), gc.Equals, failure) 310 } 311 312 func (s *connSuite) TestConnectionRemoveInstancesRemoveFailed(c *gc.C) { 313 s.FakeConn.Instances = []*compute.Instance{&s.RawInstanceFull} 314 failure := errors.New("<unknown>") 315 s.FakeConn.Err = failure 316 s.FakeConn.FailOnCall = 2 317 318 err := s.Conn.RemoveInstances("sp", "spam") 319 320 c.Check(err, gc.ErrorMatches, ".*some instance removals failed: .*") 321 } 322 323 func (s *connSuite) TestUpdateMetadataNewAttribute(c *gc.C) { 324 // Ensure we extract the name from the URL we get on the raw instance. 325 s.RawInstanceFull.Zone = "http://eels/lone/wolf/a-zone" 326 s.FakeConn.Instances = []*compute.Instance{&s.RawInstanceFull} 327 328 err := s.Conn.UpdateMetadata("business", "time", s.RawInstanceFull.Name) 329 c.Assert(err, jc.ErrorIsNil) 330 331 c.Check(s.FakeConn.Calls, gc.HasLen, 2) 332 c.Check(s.FakeConn.Calls[0].FuncName, gc.Equals, "ListInstances") 333 334 call := s.FakeConn.Calls[1] 335 c.Check(call.FuncName, gc.Equals, "SetMetadata") 336 c.Check(call.ProjectID, gc.Equals, "spam") 337 c.Check(call.ZoneName, gc.Equals, "a-zone") 338 c.Check(call.InstanceId, gc.Equals, "spam") 339 340 md := call.Metadata 341 c.Check(md.Fingerprint, gc.Equals, "heymumwatchthis") 342 c.Assert(md.Items, gc.HasLen, 2) 343 checkMetadataItems(c, md.Items[0], "eggs", "steak") 344 checkMetadataItems(c, md.Items[1], "business", "time") 345 } 346 347 func (s *connSuite) TestUpdateMetadataExistingAttribute(c *gc.C) { 348 // Ensure we extract the name from the URL we get on the raw instance. 349 s.RawInstanceFull.Zone = "http://eels/lone/wolf/a-zone" 350 s.FakeConn.Instances = []*compute.Instance{&s.RawInstanceFull} 351 352 err := s.Conn.UpdateMetadata("eggs", "beans", s.RawInstanceFull.Name) 353 c.Assert(err, jc.ErrorIsNil) 354 355 c.Check(s.FakeConn.Calls, gc.HasLen, 2) 356 c.Check(s.FakeConn.Calls[0].FuncName, gc.Equals, "ListInstances") 357 358 call := s.FakeConn.Calls[1] 359 c.Check(call.FuncName, gc.Equals, "SetMetadata") 360 c.Check(call.ProjectID, gc.Equals, "spam") 361 c.Check(call.ZoneName, gc.Equals, "a-zone") 362 c.Check(call.InstanceId, gc.Equals, "spam") 363 364 md := call.Metadata 365 c.Check(md.Fingerprint, gc.Equals, "heymumwatchthis") 366 c.Assert(md.Items, gc.HasLen, 1) 367 checkMetadataItems(c, md.Items[0], "eggs", "beans") 368 } 369 370 func (s *connSuite) TestUpdateMetadataMultipleInstances(c *gc.C) { 371 // Ensure we extract the name from the URL we get on the raw instance. 372 s.RawInstanceFull.Zone = "http://eels/lone/wolf/a-zone" 373 374 instance2 := s.RawInstanceFull 375 instance2.Name = "trucks" 376 instance2.Metadata = &compute.Metadata{ 377 Fingerprint: "faroffalienplanet", 378 Items: []*compute.MetadataItems{ 379 makeMetadataItems("eggs", "beans"), 380 makeMetadataItems("rick", "moranis"), 381 }, 382 } 383 384 instance3 := s.RawInstanceFull 385 instance3.Name = "boats" 386 instance3.Metadata = &compute.Metadata{ 387 Fingerprint: "imprisoned", 388 Items: []*compute.MetadataItems{ 389 makeMetadataItems("eggs", "milk"), 390 makeMetadataItems("rick", "moranis"), 391 }, 392 } 393 394 s.FakeConn.Instances = []*compute.Instance{&s.RawInstanceFull, &instance2, &instance3} 395 396 err := s.Conn.UpdateMetadata("rick", "morty", "spam", "boats") 397 c.Assert(err, jc.ErrorIsNil) 398 399 c.Check(s.FakeConn.Calls, gc.HasLen, 3) 400 c.Check(s.FakeConn.Calls[0].FuncName, gc.Equals, "ListInstances") 401 402 call := s.FakeConn.Calls[1] 403 c.Check(call.FuncName, gc.Equals, "SetMetadata") 404 c.Check(call.ProjectID, gc.Equals, "spam") 405 c.Check(call.ZoneName, gc.Equals, "a-zone") 406 c.Check(call.InstanceId, gc.Equals, "spam") 407 408 md := call.Metadata 409 c.Check(md.Fingerprint, gc.Equals, "heymumwatchthis") 410 c.Assert(md.Items, gc.HasLen, 2) 411 checkMetadataItems(c, md.Items[0], "eggs", "steak") 412 checkMetadataItems(c, md.Items[1], "rick", "morty") 413 414 call = s.FakeConn.Calls[2] 415 c.Check(call.FuncName, gc.Equals, "SetMetadata") 416 c.Check(call.ProjectID, gc.Equals, "spam") 417 c.Check(call.ZoneName, gc.Equals, "a-zone") 418 c.Check(call.InstanceId, gc.Equals, "boats") 419 420 md = call.Metadata 421 c.Check(md.Fingerprint, gc.Equals, "imprisoned") 422 c.Assert(md.Items, gc.HasLen, 2) 423 checkMetadataItems(c, md.Items[0], "eggs", "milk") 424 checkMetadataItems(c, md.Items[1], "rick", "morty") 425 } 426 427 func (s *connSuite) TestUpdateMetadataError(c *gc.C) { 428 instance2 := s.RawInstanceFull 429 instance2.Name = "trucks" 430 instance2.Metadata = &compute.Metadata{ 431 Fingerprint: "faroffalienplanet", 432 Items: []*compute.MetadataItems{ 433 makeMetadataItems("eggs", "beans"), 434 makeMetadataItems("rick", "moranis"), 435 }, 436 } 437 s.FakeConn.Instances = []*compute.Instance{&s.RawInstanceFull, &instance2} 438 s.FakeConn.Err = errors.New("kablooey") 439 s.FakeConn.FailOnCall = 1 440 441 err := s.Conn.UpdateMetadata("rick", "morty", "spam", "trucks") 442 c.Assert(err, gc.ErrorMatches, `some metadata updates failed: \[spam\]`) 443 444 c.Assert(s.FakeConn.Calls, gc.HasLen, 3) 445 c.Check(s.FakeConn.Calls[0].FuncName, gc.Equals, "ListInstances") 446 447 call := s.FakeConn.Calls[1] 448 c.Check(call.FuncName, gc.Equals, "SetMetadata") 449 c.Check(call.InstanceId, gc.Equals, "spam") 450 call = s.FakeConn.Calls[2] 451 c.Check(call.FuncName, gc.Equals, "SetMetadata") 452 c.Check(call.InstanceId, gc.Equals, "trucks") 453 } 454 455 func (s *connSuite) TestUpdateMetadataChecksCurrentValue(c *gc.C) { 456 s.FakeConn.Instances = []*compute.Instance{&s.RawInstanceFull} 457 err := s.Conn.UpdateMetadata("eggs", "steak", "spam") 458 c.Assert(err, jc.ErrorIsNil) 459 460 // Since the instance already has the right value we don't issue 461 // the update. 462 c.Assert(s.FakeConn.Calls, gc.HasLen, 1) 463 c.Check(s.FakeConn.Calls[0].FuncName, gc.Equals, "ListInstances") 464 } 465 466 func makeMetadataItems(key, value string) *compute.MetadataItems { 467 return &compute.MetadataItems{Key: key, Value: google.StringPtr(value)} 468 } 469 470 func checkMetadataItems(c *gc.C, item *compute.MetadataItems, key, value string) { 471 c.Assert(item, gc.NotNil) 472 c.Check(item.Key, gc.Equals, key) 473 c.Assert(item.Value, gc.NotNil) 474 c.Check(*item.Value, gc.Equals, value) 475 }