blob: d67c50b5c42ed034c87acc92920a584932af6f12 [file] [log] [blame]
Tri Vo29ac1822016-10-01 17:06:29 -07001#!/usr/bin/env python
2#
3# Copyright 2016 - The Android Open Source Project
4#
5# Licensed under the Apache License, Version 2.0 (the "License");
6# you may not use this file except in compliance with the License.
7# You may obtain a copy of the License at
8#
9# http://www.apache.org/licenses/LICENSE-2.0
10#
11# Unless required by applicable law or agreed to in writing, software
12# distributed under the License is distributed on an "AS IS" BASIS,
13# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14# See the License for the specific language governing permissions and
15# limitations under the License.
Tri Vo29ac1822016-10-01 17:06:29 -070016"""Tests for acloud.internal.lib.gcompute_client."""
Kevin Cheng5c124ec2018-05-16 13:28:51 -070017# pylint: disable=too-many-lines
Tri Vo29ac1822016-10-01 17:06:29 -070018
Kevin Cheng5c124ec2018-05-16 13:28:51 -070019import copy
Tri Vo29ac1822016-10-01 17:06:29 -070020import os
21
Kevin Cheng5c124ec2018-05-16 13:28:51 -070022import unittest
herbertxuece12e232019-10-23 17:40:49 +080023import six
Tri Vo29ac1822016-10-01 17:06:29 -070024import mock
Kevin Cheng5c124ec2018-05-16 13:28:51 -070025
26# pylint: disable=import-error
Kevin Chengda4f07a2018-06-26 10:25:05 -070027import apiclient.http
Tri Vo29ac1822016-10-01 17:06:29 -070028
Sam Chiu7de3b232018-12-06 19:45:52 +080029from acloud import errors
cylanc2f98802019-08-15 17:47:30 +080030from acloud.internal import constants
Tri Vo29ac1822016-10-01 17:06:29 -070031from acloud.internal.lib import driver_test_lib
32from acloud.internal.lib import gcompute_client
33from acloud.internal.lib import utils
Tri Vo29ac1822016-10-01 17:06:29 -070034
herbertxue1512f8a2019-06-27 13:56:23 +080035
Kevin Chengb5963882018-05-09 00:06:27 -070036GS_IMAGE_SOURCE_URI = "https://storage.googleapis.com/fake-bucket/fake.tar.gz"
37GS_IMAGE_SOURCE_DISK = (
38 "https://www.googleapis.com/compute/v1/projects/fake-project/zones/"
39 "us-east1-d/disks/fake-disk")
40PROJECT = "fake-project"
Tri Vo29ac1822016-10-01 17:06:29 -070041
herbertxue1512f8a2019-06-27 13:56:23 +080042
Kevin Cheng5c124ec2018-05-16 13:28:51 -070043# pylint: disable=protected-access, too-many-public-methods
Kevin Cheng070ae5c2018-08-02 16:03:00 -070044class ComputeClientTest(driver_test_lib.BaseDriverTest):
Tri Vo29ac1822016-10-01 17:06:29 -070045 """Test ComputeClient."""
46
Kevin Chengb5963882018-05-09 00:06:27 -070047 PROJECT_OTHER = "fake-project-other"
Tri Vo29ac1822016-10-01 17:06:29 -070048 INSTANCE = "fake-instance"
49 IMAGE = "fake-image"
50 IMAGE_URL = "http://fake-image-url"
Kevin Chengb5963882018-05-09 00:06:27 -070051 IMAGE_OTHER = "fake-image-other"
Tri Vo29ac1822016-10-01 17:06:29 -070052 MACHINE_TYPE = "fake-machine-type"
53 MACHINE_TYPE_URL = "http://fake-machine-type-url"
54 METADATA = ("metadata_key", "metadata_value")
Kevin Chengb5963882018-05-09 00:06:27 -070055 ACCELERATOR_URL = "http://speedy-gpu"
Tri Vo29ac1822016-10-01 17:06:29 -070056 NETWORK = "fake-network"
57 NETWORK_URL = "http://fake-network-url"
Kevin Cheng480e1212018-10-24 00:23:30 -070058 SUBNETWORK_URL = "http://fake-subnetwork-url"
Tri Vo29ac1822016-10-01 17:06:29 -070059 ZONE = "fake-zone"
60 REGION = "fake-region"
61 OPERATION_NAME = "fake-op"
Kevin Chengb5963882018-05-09 00:06:27 -070062 IMAGE_FINGERPRINT = "L_NWHuz7wTY="
63 GPU = "fancy-graphics"
cylan64af2db2019-01-17 15:13:59 +080064 SSHKEY = (
65 "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDBkTOTRze9v2VOqkkf7RG"
66 "jSkg6Z2kb9Q9UHsDGatvend3fmjIw1Tugg0O7nnjlPkskmlgyd4a/j99WOeLL"
67 "CPk6xPyoVjrPUVBU/pAk09ORTC4Zqk6YjlW7LOfzvqmXhmIZfYu6Q4Yt50pZzhl"
68 "lllfu26nYjY7Tg12D019nJi/kqPX5+NKgt0LGXTu8T1r2Gav/q4V7QRWQrB8Eiu"
69 "pxXR7I2YhynqovkEt/OXG4qWgvLEXGsWtSQs0CtCzqEVxz0Y9ECr7er4VdjSQxV"
70 "AaeLAsQsK9ROae8hMBFZ3//8zLVapBwpuffCu+fUoql9qeV9xagZcc9zj8XOUOW"
71 "ApiihqNL1111 test@test1.org")
Kevin Chengc330f6f2019-05-13 09:32:42 -070072 EXTRA_SCOPES = ["scope1"]
Tri Vo29ac1822016-10-01 17:06:29 -070073
74 def setUp(self):
75 """Set up test."""
76 super(ComputeClientTest, self).setUp()
77 self.Patch(gcompute_client.ComputeClient, "InitResourceHandle")
78 fake_cfg = mock.MagicMock()
Kevin Chengb5963882018-05-09 00:06:27 -070079 fake_cfg.project = PROJECT
Kevin Chengc330f6f2019-05-13 09:32:42 -070080 fake_cfg.extra_scopes = self.EXTRA_SCOPES
Kevin Chengb5963882018-05-09 00:06:27 -070081 self.compute_client = gcompute_client.ComputeClient(
82 fake_cfg, mock.MagicMock())
Tri Vo29ac1822016-10-01 17:06:29 -070083 self.compute_client._service = mock.MagicMock()
84
Kevin Cheng5c124ec2018-05-16 13:28:51 -070085 self._disk_args = copy.deepcopy(gcompute_client.BASE_DISK_ARGS)
86 self._disk_args["initializeParams"] = {"diskName": self.INSTANCE,
87 "sourceImage": self.IMAGE_URL}
88
89 # pylint: disable=invalid-name
Tri Vo29ac1822016-10-01 17:06:29 -070090 def _SetupMocksForGetOperationStatus(self, mock_result, operation_scope):
91 """A helper class for setting up mocks for testGetOperationStatus*.
92
Kevin Chengb5963882018-05-09 00:06:27 -070093 Args:
94 mock_result: The result to return by _GetOperationStatus.
95 operation_scope: A value of OperationScope.
Tri Vo29ac1822016-10-01 17:06:29 -070096
Kevin Chengb5963882018-05-09 00:06:27 -070097 Returns:
98 A mock for Resource object.
99 """
Tri Vo29ac1822016-10-01 17:06:29 -0700100 resource_mock = mock.MagicMock()
101 mock_api = mock.MagicMock()
102 if operation_scope == gcompute_client.OperationScope.GLOBAL:
103 self.compute_client._service.globalOperations = mock.MagicMock(
104 return_value=resource_mock)
105 elif operation_scope == gcompute_client.OperationScope.ZONE:
106 self.compute_client._service.zoneOperations = mock.MagicMock(
107 return_value=resource_mock)
108 elif operation_scope == gcompute_client.OperationScope.REGION:
109 self.compute_client._service.regionOperations = mock.MagicMock(
110 return_value=resource_mock)
111 resource_mock.get = mock.MagicMock(return_value=mock_api)
112 mock_api.execute = mock.MagicMock(return_value=mock_result)
113 return resource_mock
114
115 def testGetOperationStatusGlobal(self):
116 """Test _GetOperationStatus for global."""
117 resource_mock = self._SetupMocksForGetOperationStatus(
118 {"status": "GOOD"}, gcompute_client.OperationScope.GLOBAL)
119 status = self.compute_client._GetOperationStatus(
120 {"name": self.OPERATION_NAME},
121 gcompute_client.OperationScope.GLOBAL)
122 self.assertEqual(status, "GOOD")
123 resource_mock.get.assert_called_with(
Kevin Chengb5963882018-05-09 00:06:27 -0700124 project=PROJECT, operation=self.OPERATION_NAME)
Tri Vo29ac1822016-10-01 17:06:29 -0700125
126 def testGetOperationStatusZone(self):
127 """Test _GetOperationStatus for zone."""
128 resource_mock = self._SetupMocksForGetOperationStatus(
129 {"status": "GOOD"}, gcompute_client.OperationScope.ZONE)
130 status = self.compute_client._GetOperationStatus(
131 {"name": self.OPERATION_NAME}, gcompute_client.OperationScope.ZONE,
132 self.ZONE)
133 self.assertEqual(status, "GOOD")
134 resource_mock.get.assert_called_with(
Kevin Chengb5963882018-05-09 00:06:27 -0700135 project=PROJECT,
Tri Vo29ac1822016-10-01 17:06:29 -0700136 operation=self.OPERATION_NAME,
137 zone=self.ZONE)
138
139 def testGetOperationStatusRegion(self):
140 """Test _GetOperationStatus for region."""
141 resource_mock = self._SetupMocksForGetOperationStatus(
142 {"status": "GOOD"}, gcompute_client.OperationScope.REGION)
143 self.compute_client._GetOperationStatus(
144 {"name": self.OPERATION_NAME},
145 gcompute_client.OperationScope.REGION, self.REGION)
146 resource_mock.get.assert_called_with(
Kevin Chengb5963882018-05-09 00:06:27 -0700147 project=PROJECT, operation=self.OPERATION_NAME, region=self.REGION)
Tri Vo29ac1822016-10-01 17:06:29 -0700148
149 def testGetOperationStatusError(self):
150 """Test _GetOperationStatus failed."""
151 self._SetupMocksForGetOperationStatus(
152 {"error": {"errors": ["error1", "error2"]}},
153 gcompute_client.OperationScope.GLOBAL)
herbertxuece12e232019-10-23 17:40:49 +0800154 six.assertRaisesRegex(self,
155 errors.DriverError,
156 "Get operation state failed.*error1.*error2",
157 self.compute_client._GetOperationStatus,
158 {"name": self.OPERATION_NAME},
159 gcompute_client.OperationScope.GLOBAL)
Tri Vo29ac1822016-10-01 17:06:29 -0700160
Kevin Cheng5c124ec2018-05-16 13:28:51 -0700161 @mock.patch.object(errors, "GceOperationTimeoutError")
162 @mock.patch.object(utils, "PollAndWait")
163 def testWaitOnOperation(self, mock_poll, mock_gce_operation_timeout_error):
Tri Vo29ac1822016-10-01 17:06:29 -0700164 """Test WaitOnOperation."""
165 mock_error = mock.MagicMock()
Kevin Cheng5c124ec2018-05-16 13:28:51 -0700166 mock_gce_operation_timeout_error.return_value = mock_error
Tri Vo29ac1822016-10-01 17:06:29 -0700167 self.compute_client.WaitOnOperation(
168 operation={"name": self.OPERATION_NAME},
169 operation_scope=gcompute_client.OperationScope.REGION,
170 scope_name=self.REGION)
Kevin Cheng5c124ec2018-05-16 13:28:51 -0700171 mock_poll.assert_called_with(
Tri Vo29ac1822016-10-01 17:06:29 -0700172 func=self.compute_client._GetOperationStatus,
173 expected_return="DONE",
174 timeout_exception=mock_error,
175 timeout_secs=self.compute_client.OPERATION_TIMEOUT_SECS,
Kevin Chengb5963882018-05-09 00:06:27 -0700176 sleep_interval_secs=self.compute_client.OPERATION_POLL_INTERVAL_SECS,
Tri Vo29ac1822016-10-01 17:06:29 -0700177 operation={"name": self.OPERATION_NAME},
178 operation_scope=gcompute_client.OperationScope.REGION,
179 scope_name=self.REGION)
180
Kevin Chengb5963882018-05-09 00:06:27 -0700181 def testGetImage(self):
182 """Test GetImage."""
183 resource_mock = mock.MagicMock()
184 mock_api = mock.MagicMock()
185 self.compute_client._service.images = mock.MagicMock(
186 return_value=resource_mock)
187 resource_mock.get = mock.MagicMock(return_value=mock_api)
188 mock_api.execute = mock.MagicMock(return_value={"name": self.IMAGE})
189 result = self.compute_client.GetImage(self.IMAGE)
190 self.assertEqual(result, {"name": self.IMAGE})
191 resource_mock.get.assert_called_with(project=PROJECT, image=self.IMAGE)
192
193 def testGetImageOther(self):
194 """Test GetImage with other project."""
195 resource_mock = mock.MagicMock()
196 mock_api = mock.MagicMock()
197 self.compute_client._service.images = mock.MagicMock(
198 return_value=resource_mock)
199 resource_mock.get = mock.MagicMock(return_value=mock_api)
200 mock_api.execute = mock.MagicMock(return_value={"name": self.IMAGE_OTHER})
201 result = self.compute_client.GetImage(
202 image_name=self.IMAGE_OTHER,
203 image_project=self.PROJECT_OTHER)
204 self.assertEqual(result, {"name": self.IMAGE_OTHER})
205 resource_mock.get.assert_called_with(
206 project=self.PROJECT_OTHER, image=self.IMAGE_OTHER)
207
Kevin Cheng070ae5c2018-08-02 16:03:00 -0700208 def testCreateImageWithSourceURI(self):
209 """Test CreateImage with src uri."""
210 source_uri = GS_IMAGE_SOURCE_URI
211 source_disk = None
212 labels = None
213 expected_body = {"name": self.IMAGE,
214 "rawDisk": {"source": GS_IMAGE_SOURCE_URI}}
215 mock_check = self.Patch(gcompute_client.ComputeClient,
216 "CheckImageExists",
217 return_value=False)
218 mock_wait = self.Patch(gcompute_client.ComputeClient, "WaitOnOperation")
219 resource_mock = mock.MagicMock()
220 self.compute_client._service.images = mock.MagicMock(
221 return_value=resource_mock)
222 resource_mock.insert = mock.MagicMock()
223 self.compute_client.CreateImage(
224 image_name=self.IMAGE, source_uri=source_uri,
225 source_disk=source_disk, labels=labels)
226 resource_mock.insert.assert_called_with(
227 project=PROJECT, body=expected_body)
228 mock_wait.assert_called_with(
229 operation=mock.ANY,
230 operation_scope=gcompute_client.OperationScope.GLOBAL)
231 mock_check.assert_called_with(self.IMAGE)
232
233 def testCreateImageWithSourceDisk(self):
234 """Test CreateImage with src disk."""
235 source_uri = None
236 source_disk = GS_IMAGE_SOURCE_DISK
237 labels = None
238 expected_body = {"name": self.IMAGE,
239 "sourceDisk": GS_IMAGE_SOURCE_DISK}
240 mock_check = self.Patch(gcompute_client.ComputeClient,
241 "CheckImageExists",
242 return_value=False)
243 mock_wait = self.Patch(gcompute_client.ComputeClient, "WaitOnOperation")
244 resource_mock = mock.MagicMock()
245 self.compute_client._service.images = mock.MagicMock(
246 return_value=resource_mock)
247 resource_mock.insert = mock.MagicMock()
248 self.compute_client.CreateImage(
249 image_name=self.IMAGE, source_uri=source_uri,
250 source_disk=source_disk, labels=labels)
251 resource_mock.insert.assert_called_with(
252 project=PROJECT, body=expected_body)
253 mock_wait.assert_called_with(
254 operation=mock.ANY,
255 operation_scope=gcompute_client.OperationScope.GLOBAL)
256 mock_check.assert_called_with(self.IMAGE)
257
258 def testCreateImageWithSourceDiskAndLabel(self):
259 """Test CreateImage with src disk and label."""
260 source_uri = None
261 source_disk = GS_IMAGE_SOURCE_DISK
262 labels = {"label1": "xxx"}
263 expected_body = {"name": self.IMAGE,
264 "sourceDisk": GS_IMAGE_SOURCE_DISK,
265 "labels": {"label1": "xxx"}}
herbertxue308f7662018-05-18 03:25:58 +0000266 mock_check = self.Patch(gcompute_client.ComputeClient,
267 "CheckImageExists",
268 return_value=False)
Kevin Cheng5c124ec2018-05-16 13:28:51 -0700269 mock_wait = self.Patch(gcompute_client.ComputeClient, "WaitOnOperation")
Tri Vo29ac1822016-10-01 17:06:29 -0700270 resource_mock = mock.MagicMock()
271 self.compute_client._service.images = mock.MagicMock(
272 return_value=resource_mock)
273 resource_mock.insert = mock.MagicMock()
Tri Vo29ac1822016-10-01 17:06:29 -0700274 self.compute_client.CreateImage(
Kevin Chengb5963882018-05-09 00:06:27 -0700275 image_name=self.IMAGE, source_uri=source_uri,
276 source_disk=source_disk, labels=labels)
Tri Vo29ac1822016-10-01 17:06:29 -0700277 resource_mock.insert.assert_called_with(
Kevin Cheng5c124ec2018-05-16 13:28:51 -0700278 project=PROJECT, body=expected_body)
279 mock_wait.assert_called_with(
Tri Vo29ac1822016-10-01 17:06:29 -0700280 operation=mock.ANY,
281 operation_scope=gcompute_client.OperationScope.GLOBAL)
herbertxue308f7662018-05-18 03:25:58 +0000282 mock_check.assert_called_with(self.IMAGE)
Tri Vo29ac1822016-10-01 17:06:29 -0700283
Kevin Cheng5c124ec2018-05-16 13:28:51 -0700284 @mock.patch.object(gcompute_client.ComputeClient, "GetImage")
285 def testSetImageLabel(self, mock_get_image):
286 """Test SetImageLabel."""
287 with mock.patch.object(self.compute_client._service, "images",
288 return_value=mock.MagicMock(
289 setLabels=mock.MagicMock())) as _:
290 image = {"name": self.IMAGE,
291 "sourceDisk": GS_IMAGE_SOURCE_DISK,
292 "labelFingerprint": self.IMAGE_FINGERPRINT,
293 "labels": {"a": "aaa", "b": "bbb"}}
294 mock_get_image.return_value = image
295 new_labels = {"a": "xxx", "c": "ccc"}
296 # Test
297 self.compute_client.SetImageLabels(
298 self.IMAGE, new_labels)
299 # Check result
300 expected_labels = {"a": "xxx", "b": "bbb", "c": "ccc"}
301 self.compute_client._service.images().setLabels.assert_called_with(
302 project=PROJECT,
303 resource=self.IMAGE,
304 body={
305 "labels": expected_labels,
306 "labelFingerprint": self.IMAGE_FINGERPRINT
307 })
Kevin Chengb5963882018-05-09 00:06:27 -0700308
Kevin Cheng070ae5c2018-08-02 16:03:00 -0700309 def testCreateImageRaiseDriverErrorWithValidInput(self):
310 """Test CreateImage with valid input."""
311 source_uri = GS_IMAGE_SOURCE_URI
312 source_disk = GS_IMAGE_SOURCE_DISK
herbertxue308f7662018-05-18 03:25:58 +0000313 self.Patch(gcompute_client.ComputeClient, "CheckImageExists", return_value=False)
Kevin Chengb5963882018-05-09 00:06:27 -0700314 self.assertRaises(errors.DriverError, self.compute_client.CreateImage,
315 image_name=self.IMAGE, source_uri=source_uri,
316 source_disk=source_disk)
317
Kevin Cheng070ae5c2018-08-02 16:03:00 -0700318 def testCreateImageRaiseDriverErrorWithInvalidInput(self):
319 """Test CreateImage with valid input."""
320 source_uri = None
321 source_disk = None
322 self.Patch(gcompute_client.ComputeClient, "CheckImageExists", return_value=False)
323 self.assertRaises(errors.DriverError, self.compute_client.CreateImage,
324 image_name=self.IMAGE, source_uri=source_uri,
325 source_disk=source_disk)
Tri Vo29ac1822016-10-01 17:06:29 -0700326
Kevin Cheng5c124ec2018-05-16 13:28:51 -0700327 @mock.patch.object(gcompute_client.ComputeClient, "DeleteImage")
328 @mock.patch.object(gcompute_client.ComputeClient, "CheckImageExists",
herbertxue308f7662018-05-18 03:25:58 +0000329 side_effect=[False, True])
Kevin Cheng5c124ec2018-05-16 13:28:51 -0700330 @mock.patch.object(gcompute_client.ComputeClient, "WaitOnOperation",
331 side_effect=errors.DriverError("Expected fake error"))
332 def testCreateImageFail(self, mock_wait, mock_check, mock_delete):
333 """Test CreateImage fails."""
Tri Vo29ac1822016-10-01 17:06:29 -0700334 resource_mock = mock.MagicMock()
335 self.compute_client._service.images = mock.MagicMock(
336 return_value=resource_mock)
337 resource_mock.insert = mock.MagicMock()
338
339 expected_body = {
340 "name": self.IMAGE,
341 "rawDisk": {
Kevin Chengb5963882018-05-09 00:06:27 -0700342 "source": GS_IMAGE_SOURCE_URI,
Tri Vo29ac1822016-10-01 17:06:29 -0700343 },
344 }
herbertxuece12e232019-10-23 17:40:49 +0800345 six.assertRaisesRegex(
346 self,
Tri Vo29ac1822016-10-01 17:06:29 -0700347 errors.DriverError,
348 "Expected fake error",
349 self.compute_client.CreateImage,
350 image_name=self.IMAGE,
Kevin Chengb5963882018-05-09 00:06:27 -0700351 source_uri=GS_IMAGE_SOURCE_URI)
Tri Vo29ac1822016-10-01 17:06:29 -0700352 resource_mock.insert.assert_called_with(
Kevin Chengb5963882018-05-09 00:06:27 -0700353 project=PROJECT, body=expected_body)
Kevin Cheng5c124ec2018-05-16 13:28:51 -0700354 mock_wait.assert_called_with(
Tri Vo29ac1822016-10-01 17:06:29 -0700355 operation=mock.ANY,
356 operation_scope=gcompute_client.OperationScope.GLOBAL)
Kevin Cheng5c124ec2018-05-16 13:28:51 -0700357 mock_check.assert_called_with(self.IMAGE)
358 mock_delete.assert_called_with(self.IMAGE)
Tri Vo29ac1822016-10-01 17:06:29 -0700359
360 def testCheckImageExistsTrue(self):
361 """Test CheckImageExists return True."""
362 resource_mock = mock.MagicMock()
363 mock_api = mock.MagicMock()
364 self.compute_client._service.images = mock.MagicMock(
365 return_value=resource_mock)
366 resource_mock.get = mock.MagicMock(return_value=mock_api)
367 mock_api.execute = mock.MagicMock(return_value={"name": self.IMAGE})
368 self.assertTrue(self.compute_client.CheckImageExists(self.IMAGE))
369
370 def testCheckImageExistsFalse(self):
371 """Test CheckImageExists return False."""
372 resource_mock = mock.MagicMock()
373 mock_api = mock.MagicMock()
374 self.compute_client._service.images = mock.MagicMock(
375 return_value=resource_mock)
376 resource_mock.get = mock.MagicMock(return_value=mock_api)
377 mock_api.execute = mock.MagicMock(
378 side_effect=errors.ResourceNotFoundError(404, "no image"))
379 self.assertFalse(self.compute_client.CheckImageExists(self.IMAGE))
380
Kevin Cheng5c124ec2018-05-16 13:28:51 -0700381 @mock.patch.object(gcompute_client.ComputeClient, "WaitOnOperation")
382 def testDeleteImage(self, mock_wait):
Tri Vo29ac1822016-10-01 17:06:29 -0700383 """Test DeleteImage."""
Tri Vo29ac1822016-10-01 17:06:29 -0700384 resource_mock = mock.MagicMock()
385 self.compute_client._service.images = mock.MagicMock(
386 return_value=resource_mock)
387 resource_mock.delete = mock.MagicMock()
388 self.compute_client.DeleteImage(self.IMAGE)
389 resource_mock.delete.assert_called_with(
Kevin Chengb5963882018-05-09 00:06:27 -0700390 project=PROJECT, image=self.IMAGE)
Kevin Cheng5c124ec2018-05-16 13:28:51 -0700391 self.assertTrue(mock_wait.called)
Tri Vo29ac1822016-10-01 17:06:29 -0700392
393 def _SetupBatchHttpRequestMock(self):
394 """Setup BatchHttpRequest mock."""
395 requests = {}
396
397 def _Add(request, callback, request_id):
398 requests[request_id] = (request, callback)
399
400 def _Execute():
401 for rid in requests:
402 _, callback = requests[rid]
403 callback(
404 request_id=rid, response=mock.MagicMock(), exception=None)
Tri Vo29ac1822016-10-01 17:06:29 -0700405 mock_batch = mock.MagicMock()
406 mock_batch.add = _Add
407 mock_batch.execute = _Execute
408 self.Patch(apiclient.http, "BatchHttpRequest", return_value=mock_batch)
409
Kevin Cheng5c124ec2018-05-16 13:28:51 -0700410 @mock.patch.object(gcompute_client.ComputeClient, "WaitOnOperation")
411 def testDeleteImages(self, mock_wait):
Tri Vo29ac1822016-10-01 17:06:29 -0700412 """Test DeleteImages."""
413 self._SetupBatchHttpRequestMock()
Tri Vo29ac1822016-10-01 17:06:29 -0700414 fake_images = ["fake_image_1", "fake_image_2"]
415 mock_api = mock.MagicMock()
416 resource_mock = mock.MagicMock()
417 self.compute_client._service.images = mock.MagicMock(
418 return_value=resource_mock)
419 resource_mock.delete = mock.MagicMock(return_value=mock_api)
420 # Call the API.
421 deleted, failed, error_msgs = self.compute_client.DeleteImages(
422 fake_images)
423 # Verify
Kevin Chengb5963882018-05-09 00:06:27 -0700424 calls = [
425 mock.call(project=PROJECT, image="fake_image_1"),
426 mock.call(project=PROJECT, image="fake_image_2")
427 ]
Tri Vo29ac1822016-10-01 17:06:29 -0700428 resource_mock.delete.assert_has_calls(calls, any_order=True)
Kevin Cheng5c124ec2018-05-16 13:28:51 -0700429 self.assertEqual(mock_wait.call_count, 2)
Tri Vo29ac1822016-10-01 17:06:29 -0700430 self.assertEqual(error_msgs, [])
431 self.assertEqual(failed, [])
432 self.assertEqual(set(deleted), set(fake_images))
433
434 def testListImages(self):
435 """Test ListImages."""
436 fake_token = "fake_next_page_token"
437 image_1 = "image_1"
438 image_2 = "image_2"
439 response_1 = {"items": [image_1], "nextPageToken": fake_token}
440 response_2 = {"items": [image_2]}
441 self.Patch(
442 gcompute_client.ComputeClient,
443 "Execute",
444 side_effect=[response_1, response_2])
445 resource_mock = mock.MagicMock()
446 self.compute_client._service.images = mock.MagicMock(
447 return_value=resource_mock)
448 resource_mock.list = mock.MagicMock()
449 images = self.compute_client.ListImages()
450 calls = [
Kevin Chengb5963882018-05-09 00:06:27 -0700451 mock.call(project=PROJECT, filter=None, pageToken=None),
452 mock.call(project=PROJECT, filter=None, pageToken=fake_token)
Tri Vo29ac1822016-10-01 17:06:29 -0700453 ]
454 resource_mock.list.assert_has_calls(calls)
455 self.assertEqual(images, [image_1, image_2])
456
Kevin Chengb5963882018-05-09 00:06:27 -0700457 def testListImagesFromExternalProject(self):
458 """Test ListImages which accepts different project."""
459 image = "image_1"
460 response = {"items": [image]}
461 self.Patch(gcompute_client.ComputeClient, "Execute", side_effect=[response])
462 resource_mock = mock.MagicMock()
463 self.compute_client._service.images = mock.MagicMock(
464 return_value=resource_mock)
465 resource_mock.list = mock.MagicMock()
466 images = self.compute_client.ListImages(
467 image_project="fake-project-2")
468 calls = [
469 mock.call(project="fake-project-2", filter=None, pageToken=None)]
470 resource_mock.list.assert_has_calls(calls)
471 self.assertEqual(images, [image])
472
Tri Vo29ac1822016-10-01 17:06:29 -0700473 def testGetInstance(self):
474 """Test GetInstance."""
475 resource_mock = mock.MagicMock()
476 mock_api = mock.MagicMock()
477 self.compute_client._service.instances = mock.MagicMock(
478 return_value=resource_mock)
479 resource_mock.get = mock.MagicMock(return_value=mock_api)
480 mock_api.execute = mock.MagicMock(return_value={"name": self.INSTANCE})
481 result = self.compute_client.GetInstance(self.INSTANCE, self.ZONE)
482 self.assertEqual(result, {"name": self.INSTANCE})
483 resource_mock.get.assert_called_with(
Kevin Chengb5963882018-05-09 00:06:27 -0700484 project=PROJECT, zone=self.ZONE, instance=self.INSTANCE)
Tri Vo29ac1822016-10-01 17:06:29 -0700485
486 def testListInstances(self):
487 """Test ListInstances."""
488 fake_token = "fake_next_page_token"
489 instance_1 = "instance_1"
490 instance_2 = "instance_2"
491 response_1 = {"items": [instance_1], "nextPageToken": fake_token}
492 response_2 = {"items": [instance_2]}
493 self.Patch(
494 gcompute_client.ComputeClient,
495 "Execute",
496 side_effect=[response_1, response_2])
497 resource_mock = mock.MagicMock()
498 self.compute_client._service.instances = mock.MagicMock(
499 return_value=resource_mock)
500 resource_mock.list = mock.MagicMock()
501 instances = self.compute_client.ListInstances(self.ZONE)
502 calls = [
503 mock.call(
Kevin Chengb5963882018-05-09 00:06:27 -0700504 project=PROJECT,
Tri Vo29ac1822016-10-01 17:06:29 -0700505 zone=self.ZONE,
506 filter=None,
507 pageToken=None),
508 mock.call(
Kevin Chengb5963882018-05-09 00:06:27 -0700509 project=PROJECT,
Tri Vo29ac1822016-10-01 17:06:29 -0700510 zone=self.ZONE,
511 filter=None,
512 pageToken=fake_token),
513 ]
514 resource_mock.list.assert_has_calls(calls)
515 self.assertEqual(instances, [instance_1, instance_2])
516
Kevin Cheng5c124ec2018-05-16 13:28:51 -0700517 @mock.patch.object(gcompute_client.ComputeClient, "GetImage")
518 @mock.patch.object(gcompute_client.ComputeClient, "GetNetworkUrl")
Kevin Cheng480e1212018-10-24 00:23:30 -0700519 @mock.patch.object(gcompute_client.ComputeClient, "GetSubnetworkUrl")
Kevin Cheng5c124ec2018-05-16 13:28:51 -0700520 @mock.patch.object(gcompute_client.ComputeClient, "GetMachineType")
521 @mock.patch.object(gcompute_client.ComputeClient, "WaitOnOperation")
cylanc2f98802019-08-15 17:47:30 +0800522 @mock.patch("getpass.getuser", return_value="fake_user")
523 def testCreateInstance(self, _get_user, mock_wait, mock_get_mach_type,
Kevin Cheng480e1212018-10-24 00:23:30 -0700524 mock_get_subnetwork_url, mock_get_network_url,
525 mock_get_image):
Tri Vo29ac1822016-10-01 17:06:29 -0700526 """Test CreateInstance."""
Kevin Cheng5c124ec2018-05-16 13:28:51 -0700527 mock_get_mach_type.return_value = {"selfLink": self.MACHINE_TYPE_URL}
528 mock_get_network_url.return_value = self.NETWORK_URL
Kevin Cheng480e1212018-10-24 00:23:30 -0700529 mock_get_subnetwork_url.return_value = self.SUBNETWORK_URL
Kevin Cheng5c124ec2018-05-16 13:28:51 -0700530 mock_get_image.return_value = {"selfLink": self.IMAGE_URL}
Tri Vo29ac1822016-10-01 17:06:29 -0700531 resource_mock = mock.MagicMock()
532 self.compute_client._service.instances = mock.MagicMock(
533 return_value=resource_mock)
534 resource_mock.insert = mock.MagicMock()
herbertxue308f7662018-05-18 03:25:58 +0000535 self.Patch(
536 self.compute_client,
537 "_GetExtraDiskArgs",
538 return_value=[{"fake_extra_arg": "fake_extra_value"}])
539 extra_disk_name = "gce-x86-userdebug-2345-abcd-data"
540 expected_disk_args = [self._disk_args]
541 expected_disk_args.extend([{"fake_extra_arg": "fake_extra_value"}])
Kevin Chengc330f6f2019-05-13 09:32:42 -0700542 expected_scope = []
543 expected_scope.extend(self.compute_client.DEFAULT_INSTANCE_SCOPE)
544 expected_scope.extend(self.EXTRA_SCOPES)
Tri Vo29ac1822016-10-01 17:06:29 -0700545
546 expected_body = {
547 "machineType": self.MACHINE_TYPE_URL,
548 "name": self.INSTANCE,
549 "networkInterfaces": [
550 {
551 "network": self.NETWORK_URL,
Kevin Cheng480e1212018-10-24 00:23:30 -0700552 "subnetwork": self.SUBNETWORK_URL,
Tri Vo29ac1822016-10-01 17:06:29 -0700553 "accessConfigs": [
554 {"name": "External NAT",
555 "type": "ONE_TO_ONE_NAT"}
556 ],
557 }
558 ],
herbertxue308f7662018-05-18 03:25:58 +0000559 "disks": expected_disk_args,
Tri Vo29ac1822016-10-01 17:06:29 -0700560 "serviceAccounts": [
561 {"email": "default",
Kevin Chengc330f6f2019-05-13 09:32:42 -0700562 "scopes": expected_scope}
Tri Vo29ac1822016-10-01 17:06:29 -0700563 ],
564 "metadata": {
565 "items": [{"key": self.METADATA[0],
566 "value": self.METADATA[1]}],
567 },
cylanc2f98802019-08-15 17:47:30 +0800568 "labels":{constants.LABEL_CREATE_BY: "fake_user"},
Tri Vo29ac1822016-10-01 17:06:29 -0700569 }
570
571 self.compute_client.CreateInstance(
572 instance=self.INSTANCE,
573 image_name=self.IMAGE,
574 machine_type=self.MACHINE_TYPE,
575 metadata={self.METADATA[0]: self.METADATA[1]},
576 network=self.NETWORK,
herbertxue308f7662018-05-18 03:25:58 +0000577 zone=self.ZONE,
Kevin Chengc330f6f2019-05-13 09:32:42 -0700578 extra_disk_name=extra_disk_name,
579 extra_scopes=self.EXTRA_SCOPES)
Tri Vo29ac1822016-10-01 17:06:29 -0700580
581 resource_mock.insert.assert_called_with(
Kevin Chengb5963882018-05-09 00:06:27 -0700582 project=PROJECT, zone=self.ZONE, body=expected_body)
Kevin Cheng5c124ec2018-05-16 13:28:51 -0700583 mock_wait.assert_called_with(
Tri Vo29ac1822016-10-01 17:06:29 -0700584 mock.ANY,
585 operation_scope=gcompute_client.OperationScope.ZONE,
586 scope_name=self.ZONE)
587
Erwin Jansenf39798d2019-05-14 21:06:44 -0700588
589 @mock.patch.object(gcompute_client.ComputeClient, "GetImage")
590 @mock.patch.object(gcompute_client.ComputeClient, "GetNetworkUrl")
591 @mock.patch.object(gcompute_client.ComputeClient, "GetSubnetworkUrl")
592 @mock.patch.object(gcompute_client.ComputeClient, "GetMachineType")
593 @mock.patch.object(gcompute_client.ComputeClient, "WaitOnOperation")
cylanc2f98802019-08-15 17:47:30 +0800594 @mock.patch("getpass.getuser", return_value="fake_user")
herbertxue1512f8a2019-06-27 13:56:23 +0800595 def testCreateInstanceWithTags(self,
cylanc2f98802019-08-15 17:47:30 +0800596 _get_user,
herbertxue1512f8a2019-06-27 13:56:23 +0800597 mock_wait,
598 mock_get_mach_type,
599 mock_get_subnetwork_url,
600 mock_get_network_url,
601 mock_get_image):
Erwin Jansenf39798d2019-05-14 21:06:44 -0700602 """Test CreateInstance."""
603 mock_get_mach_type.return_value = {"selfLink": self.MACHINE_TYPE_URL}
604 mock_get_network_url.return_value = self.NETWORK_URL
605 mock_get_subnetwork_url.return_value = self.SUBNETWORK_URL
606 mock_get_image.return_value = {"selfLink": self.IMAGE_URL}
607 resource_mock = mock.MagicMock()
608 self.compute_client._service.instances = mock.MagicMock(
609 return_value=resource_mock)
610 resource_mock.insert = mock.MagicMock()
611 self.Patch(
612 self.compute_client,
613 "_GetExtraDiskArgs",
614 return_value=[{"fake_extra_arg": "fake_extra_value"}])
615 extra_disk_name = "gce-x86-userdebug-2345-abcd-data"
616 expected_disk_args = [self._disk_args]
617 expected_disk_args.extend([{"fake_extra_arg": "fake_extra_value"}])
618 expected_scope = []
619 expected_scope.extend(self.compute_client.DEFAULT_INSTANCE_SCOPE)
620 expected_scope.extend(self.EXTRA_SCOPES)
621
622 expected_body = {
623 "machineType": self.MACHINE_TYPE_URL,
624 "name": self.INSTANCE,
625 "networkInterfaces": [
626 {
627 "network": self.NETWORK_URL,
628 "subnetwork": self.SUBNETWORK_URL,
629 "accessConfigs": [
630 {"name": "External NAT",
631 "type": "ONE_TO_ONE_NAT"}
632 ],
633 }
634 ],
635 'tags': {'items': ['https-server']},
636 "disks": expected_disk_args,
637 "serviceAccounts": [
638 {"email": "default",
639 "scopes": expected_scope}
640 ],
641 "metadata": {
642 "items": [{"key": self.METADATA[0],
643 "value": self.METADATA[1]}],
644 },
cylanc2f98802019-08-15 17:47:30 +0800645 "labels":{'created_by': "fake_user"},
Erwin Jansenf39798d2019-05-14 21:06:44 -0700646 }
647
648 self.compute_client.CreateInstance(
649 instance=self.INSTANCE,
650 image_name=self.IMAGE,
651 machine_type=self.MACHINE_TYPE,
652 metadata={self.METADATA[0]: self.METADATA[1]},
653 network=self.NETWORK,
654 zone=self.ZONE,
655 extra_disk_name=extra_disk_name,
656 tags=["https-server"],
657 extra_scopes=self.EXTRA_SCOPES)
658
659 resource_mock.insert.assert_called_with(
660 project=PROJECT, zone=self.ZONE, body=expected_body)
661 mock_wait.assert_called_with(
662 mock.ANY,
663 operation_scope=gcompute_client.OperationScope.ZONE,
664 scope_name=self.ZONE)
665
Kevin Cheng5c124ec2018-05-16 13:28:51 -0700666 @mock.patch.object(gcompute_client.ComputeClient, "GetAcceleratorUrl")
667 @mock.patch.object(gcompute_client.ComputeClient, "GetImage")
668 @mock.patch.object(gcompute_client.ComputeClient, "GetNetworkUrl")
Kevin Cheng480e1212018-10-24 00:23:30 -0700669 @mock.patch.object(gcompute_client.ComputeClient, "GetSubnetworkUrl")
Kevin Cheng5c124ec2018-05-16 13:28:51 -0700670 @mock.patch.object(gcompute_client.ComputeClient, "GetMachineType")
671 @mock.patch.object(gcompute_client.ComputeClient, "WaitOnOperation")
cylanc2f98802019-08-15 17:47:30 +0800672 @mock.patch("getpass.getuser", return_value="fake_user")
673 def testCreateInstanceWithGpu(self, _get_user, mock_wait, mock_get_mach,
Kevin Cheng480e1212018-10-24 00:23:30 -0700674 mock_get_subnetwork, mock_get_network,
675 mock_get_image, mock_get_accel):
Kevin Chengb5963882018-05-09 00:06:27 -0700676 """Test CreateInstance with a GPU parameter not set to None."""
Kevin Cheng5c124ec2018-05-16 13:28:51 -0700677 mock_get_mach.return_value = {"selfLink": self.MACHINE_TYPE_URL}
678 mock_get_network.return_value = self.NETWORK_URL
Kevin Cheng480e1212018-10-24 00:23:30 -0700679 mock_get_subnetwork.return_value = self.SUBNETWORK_URL
Kevin Cheng5c124ec2018-05-16 13:28:51 -0700680 mock_get_accel.return_value = self.ACCELERATOR_URL
681 mock_get_image.return_value = {"selfLink": self.IMAGE_URL}
Kevin Chengb5963882018-05-09 00:06:27 -0700682
683 resource_mock = mock.MagicMock()
684 self.compute_client._service.instances = mock.MagicMock(
685 return_value=resource_mock)
686 resource_mock.insert = mock.MagicMock()
687
688 expected_body = {
689 "machineType":
690 self.MACHINE_TYPE_URL,
691 "name":
692 self.INSTANCE,
693 "networkInterfaces": [{
Kevin Cheng480e1212018-10-24 00:23:30 -0700694 "network": self.NETWORK_URL,
695 "subnetwork": self.SUBNETWORK_URL,
Kevin Chengb5963882018-05-09 00:06:27 -0700696 "accessConfigs": [{
697 "name": "External NAT",
698 "type": "ONE_TO_ONE_NAT"
699 }],
700 }],
Kevin Cheng5c124ec2018-05-16 13:28:51 -0700701 "disks": [self._disk_args],
Kevin Chengb5963882018-05-09 00:06:27 -0700702 "serviceAccounts": [{
703 "email": "default",
704 "scopes": self.compute_client.DEFAULT_INSTANCE_SCOPE
705 }],
706 "scheduling": {
707 "onHostMaintenance": "terminate"
708 },
709 "guestAccelerators": [{
710 "acceleratorCount": 1,
711 "acceleratorType": "http://speedy-gpu"
712 }],
713 "metadata": {
714 "items": [{
715 "key": self.METADATA[0],
716 "value": self.METADATA[1]
717 }],
718 },
cylanc2f98802019-08-15 17:47:30 +0800719 "labels":{'created_by': "fake_user"},
Kevin Chengb5963882018-05-09 00:06:27 -0700720 }
721
722 self.compute_client.CreateInstance(
723 instance=self.INSTANCE,
724 image_name=self.IMAGE,
725 machine_type=self.MACHINE_TYPE,
726 metadata={self.METADATA[0]: self.METADATA[1]},
727 network=self.NETWORK,
728 zone=self.ZONE,
Kevin Chengc330f6f2019-05-13 09:32:42 -0700729 gpu=self.GPU,
730 extra_scopes=None)
Kevin Chengb5963882018-05-09 00:06:27 -0700731
732 resource_mock.insert.assert_called_with(
733 project=PROJECT, zone=self.ZONE, body=expected_body)
Kevin Cheng5c124ec2018-05-16 13:28:51 -0700734 mock_wait.assert_called_with(
Kevin Chengb5963882018-05-09 00:06:27 -0700735 mock.ANY, operation_scope=gcompute_client.OperationScope.ZONE,
736 scope_name=self.ZONE)
737
Kevin Cheng5c124ec2018-05-16 13:28:51 -0700738 @mock.patch.object(gcompute_client.ComputeClient, "WaitOnOperation")
739 def testDeleteInstance(self, mock_wait):
Tri Vo29ac1822016-10-01 17:06:29 -0700740 """Test DeleteInstance."""
Tri Vo29ac1822016-10-01 17:06:29 -0700741 resource_mock = mock.MagicMock()
742 self.compute_client._service.instances = mock.MagicMock(
743 return_value=resource_mock)
744 resource_mock.delete = mock.MagicMock()
745 self.compute_client.DeleteInstance(
746 instance=self.INSTANCE, zone=self.ZONE)
747 resource_mock.delete.assert_called_with(
Kevin Chengb5963882018-05-09 00:06:27 -0700748 project=PROJECT, zone=self.ZONE, instance=self.INSTANCE)
Kevin Cheng5c124ec2018-05-16 13:28:51 -0700749 mock_wait.assert_called_with(
Tri Vo29ac1822016-10-01 17:06:29 -0700750 mock.ANY,
751 operation_scope=gcompute_client.OperationScope.ZONE,
752 scope_name=self.ZONE)
753
Kevin Cheng5c124ec2018-05-16 13:28:51 -0700754 @mock.patch.object(gcompute_client.ComputeClient, "WaitOnOperation")
755 def testDeleteInstances(self, mock_wait):
Tri Vo29ac1822016-10-01 17:06:29 -0700756 """Test DeleteInstances."""
757 self._SetupBatchHttpRequestMock()
Tri Vo29ac1822016-10-01 17:06:29 -0700758 fake_instances = ["fake_instance_1", "fake_instance_2"]
759 mock_api = mock.MagicMock()
760 resource_mock = mock.MagicMock()
761 self.compute_client._service.instances = mock.MagicMock(
762 return_value=resource_mock)
763 resource_mock.delete = mock.MagicMock(return_value=mock_api)
764 deleted, failed, error_msgs = self.compute_client.DeleteInstances(
765 fake_instances, self.ZONE)
766 calls = [
767 mock.call(
Kevin Chengb5963882018-05-09 00:06:27 -0700768 project=PROJECT,
Tri Vo29ac1822016-10-01 17:06:29 -0700769 instance="fake_instance_1",
Kevin Chengb5963882018-05-09 00:06:27 -0700770 zone=self.ZONE),
771 mock.call(
772 project=PROJECT,
773 instance="fake_instance_2",
774 zone=self.ZONE)
Tri Vo29ac1822016-10-01 17:06:29 -0700775 ]
776 resource_mock.delete.assert_has_calls(calls, any_order=True)
Kevin Cheng5c124ec2018-05-16 13:28:51 -0700777 self.assertEqual(mock_wait.call_count, 2)
Tri Vo29ac1822016-10-01 17:06:29 -0700778 self.assertEqual(error_msgs, [])
779 self.assertEqual(failed, [])
780 self.assertEqual(set(deleted), set(fake_instances))
781
Kevin Cheng070ae5c2018-08-02 16:03:00 -0700782 def testCreateDiskWithProject(self):
783 """Test CreateDisk with images using a set project."""
784 source_project = "fake-image-project"
785 expected_project_to_use = "fake-image-project"
Kevin Cheng5c124ec2018-05-16 13:28:51 -0700786 mock_wait = self.Patch(gcompute_client.ComputeClient, "WaitOnOperation")
Kevin Chengb5963882018-05-09 00:06:27 -0700787 resource_mock = mock.MagicMock()
788 self.compute_client._service.disks = mock.MagicMock(
789 return_value=resource_mock)
790 resource_mock.insert = mock.MagicMock()
791 self.compute_client.CreateDisk(
792 "fake_disk", "fake_image", 10, self.ZONE, source_project=source_project)
793 resource_mock.insert.assert_called_with(
794 project=PROJECT,
795 zone=self.ZONE,
796 sourceImage="projects/%s/global/images/fake_image" %
797 expected_project_to_use,
798 body={
799 "name":
800 "fake_disk",
801 "sizeGb":
802 10,
803 "type":
804 "projects/%s/zones/%s/diskTypes/pd-standard" % (PROJECT,
805 self.ZONE)
806 })
Kevin Cheng5c124ec2018-05-16 13:28:51 -0700807 self.assertTrue(mock_wait.called)
Kevin Chengb5963882018-05-09 00:06:27 -0700808
Kevin Cheng070ae5c2018-08-02 16:03:00 -0700809 def testCreateDiskWithNoSourceProject(self):
810 """Test CreateDisk with images with no set project."""
811 source_project = None
812 expected_project_to_use = PROJECT
813 mock_wait = self.Patch(gcompute_client.ComputeClient, "WaitOnOperation")
814 resource_mock = mock.MagicMock()
815 self.compute_client._service.disks = mock.MagicMock(
816 return_value=resource_mock)
817 resource_mock.insert = mock.MagicMock()
818 self.compute_client.CreateDisk(
819 "fake_disk", "fake_image", 10, self.ZONE, source_project=source_project)
820 resource_mock.insert.assert_called_with(
821 project=PROJECT,
822 zone=self.ZONE,
823 sourceImage="projects/%s/global/images/fake_image" %
824 expected_project_to_use,
825 body={
826 "name":
827 "fake_disk",
828 "sizeGb":
829 10,
830 "type":
831 "projects/%s/zones/%s/diskTypes/pd-standard" % (PROJECT,
832 self.ZONE)
833 })
834 self.assertTrue(mock_wait.called)
835
836 def testCreateDiskWithTypeStandard(self):
837 """Test CreateDisk with images using standard."""
838 disk_type = gcompute_client.PersistentDiskType.STANDARD
839 expected_disk_type_string = "pd-standard"
840 mock_wait = self.Patch(gcompute_client.ComputeClient, "WaitOnOperation")
841 resource_mock = mock.MagicMock()
842 self.compute_client._service.disks = mock.MagicMock(
843 return_value=resource_mock)
844 resource_mock.insert = mock.MagicMock()
845 self.compute_client.CreateDisk(
846 "fake_disk",
847 "fake_image",
848 10,
849 self.ZONE,
850 source_project="fake-project",
851 disk_type=disk_type)
852 resource_mock.insert.assert_called_with(
853 project=PROJECT,
854 zone=self.ZONE,
855 sourceImage="projects/%s/global/images/fake_image" % "fake-project",
856 body={
857 "name":
858 "fake_disk",
859 "sizeGb":
860 10,
861 "type":
862 "projects/%s/zones/%s/diskTypes/%s" %
863 (PROJECT, self.ZONE, expected_disk_type_string)
864 })
865 self.assertTrue(mock_wait.called)
866
867 def testCreateDiskWithTypeSSD(self):
868 """Test CreateDisk with images using standard."""
869 disk_type = gcompute_client.PersistentDiskType.SSD
870 expected_disk_type_string = "pd-ssd"
Kevin Cheng5c124ec2018-05-16 13:28:51 -0700871 mock_wait = self.Patch(gcompute_client.ComputeClient, "WaitOnOperation")
Kevin Chengb5963882018-05-09 00:06:27 -0700872 resource_mock = mock.MagicMock()
873 self.compute_client._service.disks = mock.MagicMock(
874 return_value=resource_mock)
875 resource_mock.insert = mock.MagicMock()
876 self.compute_client.CreateDisk(
877 "fake_disk",
878 "fake_image",
879 10,
880 self.ZONE,
881 source_project="fake-project",
882 disk_type=disk_type)
883 resource_mock.insert.assert_called_with(
884 project=PROJECT,
885 zone=self.ZONE,
886 sourceImage="projects/%s/global/images/fake_image" % "fake-project",
887 body={
888 "name":
889 "fake_disk",
890 "sizeGb":
891 10,
892 "type":
893 "projects/%s/zones/%s/diskTypes/%s" %
894 (PROJECT, self.ZONE, expected_disk_type_string)
895 })
Kevin Cheng5c124ec2018-05-16 13:28:51 -0700896 self.assertTrue(mock_wait.called)
Kevin Chengb5963882018-05-09 00:06:27 -0700897
Kevin Cheng5c124ec2018-05-16 13:28:51 -0700898 @mock.patch.object(gcompute_client.ComputeClient, "WaitOnOperation")
899 def testAttachDisk(self, mock_wait):
Kevin Chengb5963882018-05-09 00:06:27 -0700900 """Test AttachDisk."""
Kevin Chengb5963882018-05-09 00:06:27 -0700901 resource_mock = mock.MagicMock()
902 self.compute_client._service.instances = mock.MagicMock(
903 return_value=resource_mock)
904 resource_mock.attachDisk = mock.MagicMock()
905 self.compute_client.AttachDisk(
906 "fake_instance_1", self.ZONE, deviceName="fake_disk",
907 source="fake-selfLink")
908 resource_mock.attachDisk.assert_called_with(
909 project=PROJECT,
910 zone=self.ZONE,
911 instance="fake_instance_1",
912 body={
913 "deviceName": "fake_disk",
914 "source": "fake-selfLink"
915 })
Kevin Cheng5c124ec2018-05-16 13:28:51 -0700916 self.assertTrue(mock_wait.called)
Kevin Chengb5963882018-05-09 00:06:27 -0700917
Kevin Cheng5c124ec2018-05-16 13:28:51 -0700918 @mock.patch.object(gcompute_client.ComputeClient, "WaitOnOperation")
919 def testDetachDisk(self, mock_wait):
Kevin Chengb5963882018-05-09 00:06:27 -0700920 """Test DetachDisk."""
Kevin Chengb5963882018-05-09 00:06:27 -0700921 resource_mock = mock.MagicMock()
922 self.compute_client._service.instances = mock.MagicMock(
923 return_value=resource_mock)
924 resource_mock.detachDisk = mock.MagicMock()
925 self.compute_client.DetachDisk("fake_instance_1", self.ZONE, "fake_disk")
926 resource_mock.detachDisk.assert_called_with(
927 project=PROJECT,
928 zone=self.ZONE,
929 instance="fake_instance_1",
930 deviceName="fake_disk")
Kevin Cheng5c124ec2018-05-16 13:28:51 -0700931 self.assertTrue(mock_wait.called)
Kevin Chengb5963882018-05-09 00:06:27 -0700932
Kevin Cheng5c124ec2018-05-16 13:28:51 -0700933 @mock.patch.object(gcompute_client.ComputeClient, "GetAcceleratorUrl")
934 @mock.patch.object(gcompute_client.ComputeClient, "WaitOnOperation")
935 def testAttachAccelerator(self, mock_wait, mock_get_accel):
Kevin Chengb5963882018-05-09 00:06:27 -0700936 """Test AttachAccelerator."""
Kevin Cheng5c124ec2018-05-16 13:28:51 -0700937 mock_get_accel.return_value = self.ACCELERATOR_URL
Kevin Chengb5963882018-05-09 00:06:27 -0700938 resource_mock = mock.MagicMock()
939 self.compute_client._service.instances = mock.MagicMock(
940 return_value=resource_mock)
941 resource_mock.attachAccelerator = mock.MagicMock()
942 self.compute_client.AttachAccelerator("fake_instance_1", self.ZONE, 1,
943 "nvidia-tesla-k80")
944 resource_mock.setMachineResources.assert_called_with(
945 project=PROJECT,
946 zone=self.ZONE,
947 instance="fake_instance_1",
948 body={
949 "guestAccelerators": [{
950 "acceleratorType": self.ACCELERATOR_URL,
951 "acceleratorCount": 1
952 }]
953 })
Kevin Cheng5c124ec2018-05-16 13:28:51 -0700954 self.assertTrue(mock_wait.called)
Kevin Chengb5963882018-05-09 00:06:27 -0700955
Kevin Cheng5c124ec2018-05-16 13:28:51 -0700956 @mock.patch.object(gcompute_client.ComputeClient, "WaitOnOperation")
957 def testBatchExecuteOnInstances(self, mock_wait):
958 """Test BatchExecuteOnInstances."""
Tri Vo29ac1822016-10-01 17:06:29 -0700959 self._SetupBatchHttpRequestMock()
Tri Vo29ac1822016-10-01 17:06:29 -0700960 action = mock.MagicMock(return_value=mock.MagicMock())
961 fake_instances = ["fake_instance_1", "fake_instance_2"]
962 done, failed, error_msgs = self.compute_client._BatchExecuteOnInstances(
963 fake_instances, self.ZONE, action)
964 calls = [mock.call(instance="fake_instance_1"),
965 mock.call(instance="fake_instance_2")]
966 action.assert_has_calls(calls, any_order=True)
Kevin Cheng5c124ec2018-05-16 13:28:51 -0700967 self.assertEqual(mock_wait.call_count, 2)
Tri Vo29ac1822016-10-01 17:06:29 -0700968 self.assertEqual(set(done), set(fake_instances))
969 self.assertEqual(error_msgs, [])
970 self.assertEqual(failed, [])
971
Kevin Cheng5c124ec2018-05-16 13:28:51 -0700972 @mock.patch.object(gcompute_client.ComputeClient, "WaitOnOperation")
973 def testResetInstance(self, mock_wait):
Tri Vo29ac1822016-10-01 17:06:29 -0700974 """Test ResetInstance."""
Tri Vo29ac1822016-10-01 17:06:29 -0700975 resource_mock = mock.MagicMock()
976 self.compute_client._service.instances = mock.MagicMock(
977 return_value=resource_mock)
978 resource_mock.reset = mock.MagicMock()
979 self.compute_client.ResetInstance(
980 instance=self.INSTANCE, zone=self.ZONE)
981 resource_mock.reset.assert_called_with(
Kevin Chengb5963882018-05-09 00:06:27 -0700982 project=PROJECT, zone=self.ZONE, instance=self.INSTANCE)
Kevin Cheng5c124ec2018-05-16 13:28:51 -0700983 mock_wait.assert_called_with(
Tri Vo29ac1822016-10-01 17:06:29 -0700984 mock.ANY,
985 operation_scope=gcompute_client.OperationScope.ZONE,
986 scope_name=self.ZONE)
987
988 def _CompareMachineSizeTestHelper(self,
989 machine_info_1,
990 machine_info_2,
991 expected_result=None,
992 expected_error_type=None):
993 """Helper class for testing CompareMachineSize.
994
Kevin Chengb5963882018-05-09 00:06:27 -0700995 Args:
996 machine_info_1: A dictionary representing the first machine size.
997 machine_info_2: A dictionary representing the second machine size.
998 expected_result: An integer, 0, 1 or -1, or None if not set.
999 expected_error_type: An exception type, if set will check for exception.
1000 """
Kevin Cheng5c124ec2018-05-16 13:28:51 -07001001 mock_get_mach_type = self.Patch(
Tri Vo29ac1822016-10-01 17:06:29 -07001002 gcompute_client.ComputeClient,
1003 "GetMachineType",
1004 side_effect=[machine_info_1, machine_info_2])
1005 if expected_error_type:
1006 self.assertRaises(expected_error_type,
1007 self.compute_client.CompareMachineSize, "name1",
1008 "name2", self.ZONE)
1009 else:
1010 result = self.compute_client.CompareMachineSize("name1", "name2",
1011 self.ZONE)
1012 self.assertEqual(result, expected_result)
1013
Kevin Cheng5c124ec2018-05-16 13:28:51 -07001014 mock_get_mach_type.assert_has_calls(
Tri Vo29ac1822016-10-01 17:06:29 -07001015 [mock.call("name1", self.ZONE), mock.call("name2", self.ZONE)])
1016
1017 def testCompareMachineSizeSmall(self):
1018 """Test CompareMachineSize where the first one is smaller."""
1019 machine_info_1 = {"guestCpus": 10, "memoryMb": 100}
1020 machine_info_2 = {"guestCpus": 10, "memoryMb": 200}
1021 self._CompareMachineSizeTestHelper(machine_info_1, machine_info_2, -1)
1022
Kevin Cheng4ae42772018-10-02 11:39:48 -07001023 def testCompareMachineSizeSmallSmallerOnSecond(self):
1024 """Test CompareMachineSize where the first one is smaller."""
1025 machine_info_1 = {"guestCpus": 11, "memoryMb": 100}
1026 machine_info_2 = {"guestCpus": 10, "memoryMb": 200}
1027 self._CompareMachineSizeTestHelper(machine_info_1, machine_info_2, -1)
1028
Tri Vo29ac1822016-10-01 17:06:29 -07001029 def testCompareMachineSizeLarge(self):
1030 """Test CompareMachineSize where the first one is larger."""
Kevin Cheng4ae42772018-10-02 11:39:48 -07001031 machine_info_1 = {"guestCpus": 11, "memoryMb": 200}
1032 machine_info_2 = {"guestCpus": 10, "memoryMb": 100}
1033 self._CompareMachineSizeTestHelper(machine_info_1, machine_info_2, 1)
1034
1035 def testCompareMachineSizeLargeWithEqualElement(self):
1036 """Test CompareMachineSize where the first one is larger."""
Tri Vo29ac1822016-10-01 17:06:29 -07001037 machine_info_1 = {"guestCpus": 10, "memoryMb": 200}
1038 machine_info_2 = {"guestCpus": 10, "memoryMb": 100}
1039 self._CompareMachineSizeTestHelper(machine_info_1, machine_info_2, 1)
1040
1041 def testCompareMachineSizeEqual(self):
1042 """Test CompareMachineSize where two machine sizes are equal."""
1043 machine_info = {"guestCpus": 10, "memoryMb": 100}
1044 self._CompareMachineSizeTestHelper(machine_info, machine_info, 0)
1045
1046 def testCompareMachineSizeBadMetric(self):
1047 """Test CompareMachineSize with bad metric."""
Kevin Chengb5963882018-05-09 00:06:27 -07001048 machine_info = {"unknown_metric": 10, "memoryMb": 100}
Tri Vo29ac1822016-10-01 17:06:29 -07001049 self._CompareMachineSizeTestHelper(
1050 machine_info, machine_info, expected_error_type=errors.DriverError)
1051
1052 def testGetMachineType(self):
1053 """Test GetMachineType."""
1054 resource_mock = mock.MagicMock()
1055 mock_api = mock.MagicMock()
1056 self.compute_client._service.machineTypes = mock.MagicMock(
1057 return_value=resource_mock)
1058 resource_mock.get = mock.MagicMock(return_value=mock_api)
1059 mock_api.execute = mock.MagicMock(
1060 return_value={"name": self.MACHINE_TYPE})
1061 result = self.compute_client.GetMachineType(self.MACHINE_TYPE,
1062 self.ZONE)
1063 self.assertEqual(result, {"name": self.MACHINE_TYPE})
1064 resource_mock.get.assert_called_with(
Kevin Chengb5963882018-05-09 00:06:27 -07001065 project=PROJECT,
Tri Vo29ac1822016-10-01 17:06:29 -07001066 zone=self.ZONE,
1067 machineType=self.MACHINE_TYPE)
1068
1069 def _GetSerialPortOutputTestHelper(self, response):
1070 """Helper function for testing GetSerialPortOutput.
1071
Kevin Chengb5963882018-05-09 00:06:27 -07001072 Args:
1073 response: A dictionary representing a fake response.
1074 """
Tri Vo29ac1822016-10-01 17:06:29 -07001075 resource_mock = mock.MagicMock()
1076 mock_api = mock.MagicMock()
1077 self.compute_client._service.instances = mock.MagicMock(
1078 return_value=resource_mock)
1079 resource_mock.getSerialPortOutput = mock.MagicMock(
1080 return_value=mock_api)
1081 mock_api.execute = mock.MagicMock(return_value=response)
1082
1083 if "contents" in response:
1084 result = self.compute_client.GetSerialPortOutput(
1085 instance=self.INSTANCE, zone=self.ZONE)
1086 self.assertEqual(result, "fake contents")
1087 else:
herbertxuece12e232019-10-23 17:40:49 +08001088 six.assertRaisesRegex(
1089 self,
Tri Vo29ac1822016-10-01 17:06:29 -07001090 errors.DriverError,
1091 "Malformed response.*",
1092 self.compute_client.GetSerialPortOutput,
1093 instance=self.INSTANCE,
1094 zone=self.ZONE)
1095 resource_mock.getSerialPortOutput.assert_called_with(
Kevin Chengb5963882018-05-09 00:06:27 -07001096 project=PROJECT,
Tri Vo29ac1822016-10-01 17:06:29 -07001097 zone=self.ZONE,
1098 instance=self.INSTANCE,
1099 port=1)
1100
1101 def testGetSerialPortOutput(self):
Kevin Cheng5c124ec2018-05-16 13:28:51 -07001102 """Test GetSerialPortOutput."""
Tri Vo29ac1822016-10-01 17:06:29 -07001103 response = {"contents": "fake contents"}
1104 self._GetSerialPortOutputTestHelper(response)
1105
1106 def testGetSerialPortOutputFail(self):
Kevin Cheng5c124ec2018-05-16 13:28:51 -07001107 """Test GetSerialPortOutputFail."""
Tri Vo29ac1822016-10-01 17:06:29 -07001108 response = {"malformed": "fake contents"}
1109 self._GetSerialPortOutputTestHelper(response)
1110
1111 def testGetInstanceNamesByIPs(self):
1112 """Test GetInstanceNamesByIPs."""
1113 good_instance = {
1114 "name": "instance_1",
1115 "networkInterfaces": [
1116 {
1117 "accessConfigs": [
1118 {"natIP": "172.22.22.22"},
1119 ],
1120 },
1121 ],
1122 }
1123 bad_instance = {"name": "instance_2"}
1124 self.Patch(
1125 gcompute_client.ComputeClient,
1126 "ListInstances",
1127 return_value=[good_instance, bad_instance])
1128 ip_name_map = self.compute_client.GetInstanceNamesByIPs(
1129 ips=["172.22.22.22", "172.22.22.23"], zone=self.ZONE)
1130 self.assertEqual(ip_name_map, {"172.22.22.22": "instance_1",
1131 "172.22.22.23": None})
1132
cylan64af2db2019-01-17 15:13:59 +08001133 def testRsaNotInMetadata(self):
1134 """Test rsa not in metadata."""
Tri Vo29ac1822016-10-01 17:06:29 -07001135 fake_user = "fake_user"
cylan64af2db2019-01-17 15:13:59 +08001136 fake_ssh_key = "fake_ssh"
1137 metadata = {
1138 "kind": "compute#metadata",
1139 "fingerprint": "a-23icsyx4E=",
1140 "items": [
1141 {
1142 "key": "sshKeys",
1143 "value": "%s:%s" % (fake_user, self.SSHKEY)
1144 }
1145 ]
1146 }
1147 # Test rsa doesn't exist in metadata.
1148 new_entry = "%s:%s" % (fake_user, fake_ssh_key)
1149 self.assertEqual(True, gcompute_client.RsaNotInMetadata(metadata, new_entry))
1150
1151 # Test rsa exists in metadata.
1152 exist_entry = "%s:%s" %(fake_user, self.SSHKEY)
1153 self.assertEqual(False, gcompute_client.RsaNotInMetadata(metadata, exist_entry))
1154
1155 def testGetSshKeyFromMetadata(self):
1156 """Test get ssh key from metadata."""
1157 fake_user = "fake_user"
1158 metadata_key_exist_value_is_empty = {
1159 "kind": "compute#metadata",
1160 "fingerprint": "a-23icsyx4E=",
1161 "items": [
1162 {
1163 "key": "sshKeys",
1164 "value": ""
1165 }
1166 ]
1167 }
1168 metadata_key_exist = {
1169 "kind": "compute#metadata",
1170 "fingerprint": "a-23icsyx4E=",
1171 "items": [
1172 {
1173 "key": "sshKeys",
1174 "value": "%s:%s" % (fake_user, self.SSHKEY)
1175 }
1176 ]
1177 }
1178 metadata_key_not_exist = {
1179 "kind": "compute#metadata",
1180 "fingerprint": "a-23icsyx4E=",
1181 "items": [
1182 {
1183 }
1184 ]
1185 }
1186 expected_key_exist_value_is_empty = {
1187 "key": "sshKeys",
1188 "value": ""
1189 }
1190 expected_key_exist = {
1191 "key": "sshKeys",
1192 "value": "%s:%s" % (fake_user, self.SSHKEY)
1193 }
1194 self.assertEqual(expected_key_exist_value_is_empty,
1195 gcompute_client.GetSshKeyFromMetadata(metadata_key_exist_value_is_empty))
1196 self.assertEqual(expected_key_exist,
1197 gcompute_client.GetSshKeyFromMetadata(metadata_key_exist))
1198 self.assertEqual(None,
1199 gcompute_client.GetSshKeyFromMetadata(metadata_key_not_exist))
1200
1201
1202 def testGetRsaKeyPathExistsFalse(self):
1203 """Test the rsa key path not exists."""
1204 fake_ssh_rsa_path = "/path/to/test_rsa.pub"
1205 self.Patch(os.path, "exists", return_value=False)
herbertxuece12e232019-10-23 17:40:49 +08001206 six.assertRaisesRegex(self,
1207 errors.DriverError,
1208 "RSA file %s does not exist." % fake_ssh_rsa_path,
1209 gcompute_client.GetRsaKey,
1210 ssh_rsa_path=fake_ssh_rsa_path)
cylan64af2db2019-01-17 15:13:59 +08001211
1212 def testGetRsaKey(self):
1213 """Test get the rsa key."""
1214 fake_ssh_rsa_path = "/path/to/test_rsa.pub"
1215 self.Patch(os.path, "exists", return_value=True)
1216 m = mock.mock_open(read_data=self.SSHKEY)
1217 with mock.patch("__builtin__.open", m):
1218 result = gcompute_client.GetRsaKey(fake_ssh_rsa_path)
1219 self.assertEqual(self.SSHKEY, result)
1220
1221 def testUpdateRsaInMetadata(self):
1222 """Test update rsa in metadata."""
1223 fake_ssh_key = "fake_ssh"
1224 fake_metadata_sshkeys_not_exist = {
1225 "kind": "compute#metadata",
1226 "fingerprint": "a-23icsyx4E=",
1227 "items": [
1228 {
1229 "key": "not_sshKeys",
1230 "value": ""
1231 }
1232 ]
1233 }
1234 new_entry = "new_user:%s" % fake_ssh_key
1235 expected = {
1236 "kind": "compute#metadata",
1237 "fingerprint": "a-23icsyx4E=",
1238 "items": [
1239 {
1240 "key": "not_sshKeys",
1241 "value": ""
1242 },
1243 {
1244 "key": "sshKeys",
1245 "value": new_entry
1246 }
1247 ]
1248 }
1249 self.Patch(os.path, "exists", return_value=True)
1250 self.Patch(gcompute_client.ComputeClient, "WaitOnOperation")
1251 resource_mock = mock.MagicMock()
1252 self.compute_client.SetInstanceMetadata = mock.MagicMock(
1253 return_value=resource_mock)
1254 # Test the key item not exists in the metadata.
1255 self.compute_client.UpdateRsaInMetadata(
1256 "fake_zone",
1257 "fake_instance",
1258 fake_metadata_sshkeys_not_exist,
1259 new_entry)
1260 self.compute_client.SetInstanceMetadata.assert_called_with(
1261 "fake_zone",
1262 "fake_instance",
1263 expected)
1264
1265 # Test the key item exists in the metadata.
1266 fake_metadata_ssh_keys_exists = {
1267 "kind": "compute#metadata",
1268 "fingerprint": "a-23icsyx4E=",
1269 "items": [
1270 {
1271 "key": "sshKeys",
1272 "value": "old_user:%s" % self.SSHKEY
1273 }
1274 ]
1275 }
1276 expected_ssh_keys_exists = {
1277 "kind": "compute#metadata",
1278 "fingerprint": "a-23icsyx4E=",
1279 "items": [
1280 {
1281 "key": "sshKeys",
1282 "value": "old_user:%s\n%s" % (self.SSHKEY, new_entry)
1283 }
1284 ]
1285 }
1286
1287 self.compute_client.UpdateRsaInMetadata(
1288 "fake_zone",
1289 "fake_instance",
1290 fake_metadata_ssh_keys_exists,
1291 new_entry)
1292 self.compute_client.SetInstanceMetadata.assert_called_with(
1293 "fake_zone",
1294 "fake_instance",
1295 expected_ssh_keys_exists)
1296
1297 def testAddSshRsaToInstance(self):
1298 """Test add ssh rsa key to instance."""
1299 fake_user = "fake_user"
1300 instance_metadata_key_not_exist = {
1301 "metadata": {
Tri Vo29ac1822016-10-01 17:06:29 -07001302 "kind": "compute#metadata",
1303 "fingerprint": "a-23icsyx4E=",
1304 "items": [
1305 {
1306 "key": "sshKeys",
cylan64af2db2019-01-17 15:13:59 +08001307 "value": ""
1308 }
1309 ]
1310 }
1311 }
1312 instance_metadata_key_exist = {
1313 "metadata": {
1314 "kind": "compute#metadata",
1315 "fingerprint": "a-23icsyx4E=",
1316 "items": [
1317 {
1318 "key": "sshKeys",
1319 "value": "%s:%s" % (fake_user, self.SSHKEY)
Tri Vo29ac1822016-10-01 17:06:29 -07001320 }
1321 ]
1322 }
1323 }
1324 expected = {
1325 "kind": "compute#metadata",
1326 "fingerprint": "a-23icsyx4E=",
1327 "items": [
1328 {
1329 "key": "sshKeys",
cylan64af2db2019-01-17 15:13:59 +08001330 "value": "%s:%s" % (fake_user, self.SSHKEY)
Tri Vo29ac1822016-10-01 17:06:29 -07001331 }
1332 ]
1333 }
1334
1335 self.Patch(os.path, "exists", return_value=True)
cylan64af2db2019-01-17 15:13:59 +08001336 m = mock.mock_open(read_data=self.SSHKEY)
Tri Vo29ac1822016-10-01 17:06:29 -07001337 self.Patch(gcompute_client.ComputeClient, "WaitOnOperation")
Tri Vo29ac1822016-10-01 17:06:29 -07001338 resource_mock = mock.MagicMock()
cylan64af2db2019-01-17 15:13:59 +08001339 self.compute_client._service.instances = mock.MagicMock(
Tri Vo29ac1822016-10-01 17:06:29 -07001340 return_value=resource_mock)
cylan64af2db2019-01-17 15:13:59 +08001341 resource_mock.setMetadata = mock.MagicMock()
Tri Vo29ac1822016-10-01 17:06:29 -07001342
cylan64af2db2019-01-17 15:13:59 +08001343 # Test the key not exists in the metadata.
Tri Vo29ac1822016-10-01 17:06:29 -07001344 self.Patch(
cylan64af2db2019-01-17 15:13:59 +08001345 gcompute_client.ComputeClient, "GetInstance",
1346 return_value=instance_metadata_key_not_exist)
Kevin Chengda4f07a2018-06-26 10:25:05 -07001347 with mock.patch("__builtin__.open", m):
cylan64af2db2019-01-17 15:13:59 +08001348 self.compute_client.AddSshRsaInstanceMetadata(
1349 "fake_zone",
1350 fake_user,
1351 "/path/to/test_rsa.pub",
1352 "fake_instance")
1353 resource_mock.setMetadata.assert_called_with(
1354 project=PROJECT,
1355 zone="fake_zone",
1356 instance="fake_instance",
1357 body=expected)
1358
1359 # Test the key already exists in the metadata.
1360 resource_mock.setMetadata.call_count = 0
1361 self.Patch(
1362 gcompute_client.ComputeClient, "GetInstance",
1363 return_value=instance_metadata_key_exist)
1364 with mock.patch("__builtin__.open", m):
1365 self.compute_client.AddSshRsaInstanceMetadata(
1366 "fake_zone",
1367 fake_user,
1368 "/path/to/test_rsa.pub",
1369 "fake_instance")
1370 resource_mock.setMetadata.assert_not_called()
Tri Vo29ac1822016-10-01 17:06:29 -07001371
Kevin Cheng5c124ec2018-05-16 13:28:51 -07001372 @mock.patch.object(gcompute_client.ComputeClient, "WaitOnOperation")
1373 def testDeleteDisks(self, mock_wait):
Tri Vo29ac1822016-10-01 17:06:29 -07001374 """Test DeleteDisks."""
1375 self._SetupBatchHttpRequestMock()
Tri Vo29ac1822016-10-01 17:06:29 -07001376 fake_disks = ["fake_disk_1", "fake_disk_2"]
1377 mock_api = mock.MagicMock()
1378 resource_mock = mock.MagicMock()
1379 self.compute_client._service.disks = mock.MagicMock(
1380 return_value=resource_mock)
1381 resource_mock.delete = mock.MagicMock(return_value=mock_api)
1382 # Call the API.
1383 deleted, failed, error_msgs = self.compute_client.DeleteDisks(
1384 fake_disks, zone=self.ZONE)
1385 # Verify
Kevin Chengb5963882018-05-09 00:06:27 -07001386 calls = [
1387 mock.call(project=PROJECT, disk="fake_disk_1", zone=self.ZONE),
1388 mock.call(project=PROJECT, disk="fake_disk_2", zone=self.ZONE)
1389 ]
Tri Vo29ac1822016-10-01 17:06:29 -07001390 resource_mock.delete.assert_has_calls(calls, any_order=True)
Kevin Cheng5c124ec2018-05-16 13:28:51 -07001391 self.assertEqual(mock_wait.call_count, 2)
Tri Vo29ac1822016-10-01 17:06:29 -07001392 self.assertEqual(error_msgs, [])
1393 self.assertEqual(failed, [])
1394 self.assertEqual(set(deleted), set(fake_disks))
1395
Kevin Chengb5963882018-05-09 00:06:27 -07001396 def testRetryOnFingerPrintError(self):
Kevin Cheng5c124ec2018-05-16 13:28:51 -07001397 """Test RetryOnFingerPrintError."""
Kevin Chengb5963882018-05-09 00:06:27 -07001398 @utils.RetryOnException(gcompute_client._IsFingerPrintError, 10)
1399 def Raise412(sentinel):
Kevin Cheng5c124ec2018-05-16 13:28:51 -07001400 """Raise 412 HTTP exception."""
1401 if not sentinel.hitFingerPrintConflict.called:
1402 sentinel.hitFingerPrintConflict()
1403 raise errors.HttpError(412, "resource labels have changed")
1404 return "Passed"
Kevin Chengb5963882018-05-09 00:06:27 -07001405
1406 sentinel = mock.MagicMock()
1407 result = Raise412(sentinel)
1408 self.assertEqual(1, sentinel.hitFingerPrintConflict.call_count)
1409 self.assertEqual("Passed", result)
1410
Tri Vo29ac1822016-10-01 17:06:29 -07001411
1412if __name__ == "__main__":
1413 unittest.main()