blob: f4697400dbf99e0f5396e8a9c143bb746bf4ddee [file] [log] [blame]
herbertxue34776bb2018-07-03 21:57:48 +08001#!/usr/bin/env python
2#
3# Copyright 2018 - 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.
16"""Tests for acloud.setup.gcp_setup_runner."""
17
18import unittest
19import os
20import mock
21
chojoyce13cb0c52019-07-01 17:24:52 +080022# pylint: disable=no-name-in-module,import-error,no-member
23from acloud import errors
24from acloud.internal.lib import utils
herbertxue34776bb2018-07-03 21:57:48 +080025from acloud.internal.proto import user_config_pb2
26from acloud.public import config
27from acloud.setup import gcp_setup_runner
28
29_GCP_USER_CONFIG = """
30[compute]
31region = new_region
32zone = new_zone
33[core]
34account = new@google.com
35disable_usage_reporting = False
36project = new_project
37"""
38
39
40def _CreateCfgFile():
41 """A helper method that creates a mock configuration object."""
42 default_cfg = """
43project: "fake_project"
44zone: "fake_zone"
45storage_bucket_name: "fake_bucket"
46client_id: "fake_client_id"
47client_secret: "fake_client_secret"
48"""
49 return default_cfg
50
51
52# pylint: disable=protected-access
53class AcloudGCPSetupTest(unittest.TestCase):
54 """Test GCP Setup steps."""
55
56 def setUp(self):
57 """Create config and gcp_env_runner."""
58 self.cfg_path = "acloud_unittest.config"
59 file_write = open(self.cfg_path, 'w')
60 file_write.write(_CreateCfgFile().strip())
61 file_write.close()
62 self.gcp_env_runner = gcp_setup_runner.GcpTaskRunner(self.cfg_path)
63 self.gcloud_runner = gcp_setup_runner.GoogleSDKBins("")
64
65 def tearDown(self):
66 """Remove temp file."""
67 if os.path.isfile(self.cfg_path):
68 os.remove(self.cfg_path)
69
70 def testUpdateConfigFile(self):
71 """Test update config file."""
72 # Test update project field.
73 gcp_setup_runner.UpdateConfigFile(self.cfg_path, "project",
74 "test_project")
75 cfg = config.AcloudConfigManager.LoadConfigFromProtocolBuffer(
76 open(self.cfg_path, "r"), user_config_pb2.UserConfig)
77 self.assertEqual(cfg.project, "test_project")
78 self.assertEqual(cfg.ssh_private_key_path, "")
chojoyce13cb0c52019-07-01 17:24:52 +080079 # Test add ssh key path in config.
herbertxue34776bb2018-07-03 21:57:48 +080080 gcp_setup_runner.UpdateConfigFile(self.cfg_path,
81 "ssh_private_key_path", "test_path")
82 cfg = config.AcloudConfigManager.LoadConfigFromProtocolBuffer(
83 open(self.cfg_path, "r"), user_config_pb2.UserConfig)
84 self.assertEqual(cfg.project, "test_project")
85 self.assertEqual(cfg.ssh_private_key_path, "test_path")
chojoyce13cb0c52019-07-01 17:24:52 +080086 # Test config is not a file
87 with mock.patch("os.path.isfile") as chkfile:
88 chkfile.return_value = False
89 gcp_setup_runner.UpdateConfigFile(self.cfg_path, "project",
90 "test_project")
91 cfg = config.AcloudConfigManager.LoadConfigFromProtocolBuffer(
92 open(self.cfg_path, "r"), user_config_pb2.UserConfig)
93 self.assertEqual(cfg.project, "test_project")
herbertxue34776bb2018-07-03 21:57:48 +080094
herbertxue34776bb2018-07-03 21:57:48 +080095 @mock.patch("os.path.dirname", return_value="")
96 @mock.patch("subprocess.check_output")
97 def testSeupProjectZone(self, mock_runner, mock_path):
98 """Test setup project and zone."""
99 gcloud_runner = gcp_setup_runner.GoogleSDKBins(mock_path)
100 self.gcp_env_runner.project = "fake_project"
101 self.gcp_env_runner.zone = "fake_zone"
102 mock_runner.side_effect = [0, _GCP_USER_CONFIG]
103 self.gcp_env_runner._UpdateProject(gcloud_runner)
104 self.assertEqual(self.gcp_env_runner.project, "new_project")
105 self.assertEqual(self.gcp_env_runner.zone, "new_zone")
106
107 @mock.patch("__builtin__.raw_input")
108 def testSetupClientIDSecret(self, mock_id):
109 """Test setup client ID and client secret."""
110 self.gcp_env_runner.client_id = "fake_client_id"
111 self.gcp_env_runner.client_secret = "fake_client_secret"
112 mock_id.side_effect = ["new_id", "new_secret"]
113 self.gcp_env_runner._SetupClientIDSecret()
114 self.assertEqual(self.gcp_env_runner.client_id, "new_id")
115 self.assertEqual(self.gcp_env_runner.client_secret, "new_secret")
116
chojoyce13cb0c52019-07-01 17:24:52 +0800117 @mock.patch.object(gcp_setup_runner, "UpdateConfigFile")
118 @mock.patch.object(utils, "CreateSshKeyPairIfNotExist")
119 def testSetupSSHKeys(self, mock_check, mock_update):
120 """Test setup the pair of the ssh key for acloud.config."""
121 # Test ssh key has already setup
122 gcp_setup_runner.SetupSSHKeys(self.cfg_path,
123 "fake_private_key_path",
124 "fake_public_key_path")
125 self.assertEqual(mock_update.call_count, 0)
126 # Test if private_key_path is empty string
127 with mock.patch('os.path.expanduser') as ssh_path:
128 ssh_path.return_value = ""
129 gcp_setup_runner.SetupSSHKeys(self.cfg_path,
130 "fake_private_key_path",
131 "fake_public_key_path")
132 mock_check.assert_called_once_with(
133 gcp_setup_runner._DEFAULT_SSH_PRIVATE_KEY,
134 gcp_setup_runner._DEFAULT_SSH_PUBLIC_KEY)
135
136 mock_update.assert_has_calls([
137 mock.call(self.cfg_path, "ssh_private_key_path",
138 gcp_setup_runner._DEFAULT_SSH_PRIVATE_KEY),
139 mock.call(self.cfg_path, "ssh_public_key_path",
140 gcp_setup_runner._DEFAULT_SSH_PUBLIC_KEY)])
141
142 @mock.patch.object(gcp_setup_runner.GcpTaskRunner, "_CreateStableHostImage")
143 @mock.patch.object(gcp_setup_runner.GcpTaskRunner, "_EnableGcloudServices")
144 @mock.patch.object(gcp_setup_runner.GcpTaskRunner, "_SetupProject")
145 @mock.patch.object(gcp_setup_runner, "GoogleSDKBins")
146 def testSetupGcloudInfo(self, mock_sdk, mock_set, mock_run, mock_create):
147 """test setup gcloud info"""
148 with mock.patch("google_sdk.GoogleSDK"):
149 self.gcp_env_runner._SetupGcloudInfo()
150 mock_sdk.assert_called_once()
151 mock_set.assert_called_once()
152 mock_run.assert_called_once()
153 mock_create.assert_called_once()
154
155 @mock.patch.object(gcp_setup_runner, "UpdateConfigFile")
156 def testCreateStableHostImage(self, mock_update):
157 """test create stable hostimage."""
158 # Test no need to create stable hose image name.
159 self.gcp_env_runner.stable_host_image_name = "fake_host_image_name"
160 self.gcp_env_runner._CreateStableHostImage()
161 self.assertEqual(mock_update.call_count, 0)
162 # Test need to reset stable hose image name.
163 self.gcp_env_runner.stable_host_image_name = ""
164 self.gcp_env_runner._CreateStableHostImage()
165 self.assertEqual(mock_update.call_count, 1)
166
herbertxueed577e82019-08-26 18:19:09 +0800167 @mock.patch.object(gcp_setup_runner.GcpTaskRunner, "_CheckBillingEnable")
chojoyce13cb0c52019-07-01 17:24:52 +0800168 @mock.patch.object(gcp_setup_runner.GcpTaskRunner, "_NeedProjectSetup")
chojoyce13cb0c52019-07-01 17:24:52 +0800169 @mock.patch.object(gcp_setup_runner.GcpTaskRunner, "_SetupClientIDSecret")
170 @mock.patch.object(gcp_setup_runner.GcpTaskRunner, "_UpdateProject")
171 def testSetupProjectNoChange(self, mock_setproj, mock_setid,
herbertxuea6a953a2019-06-25 18:29:00 +0800172 mock_chkproj, mock_check_billing):
chojoyce13cb0c52019-07-01 17:24:52 +0800173 """test setup project and project not be changed."""
174 # Test project didn't change, and no need to setup client id/secret
175 mock_chkproj.return_value = False
176 self.gcp_env_runner.client_id = "test_client_id"
177 self.gcp_env_runner._SetupProject(self.gcloud_runner)
178 self.assertEqual(mock_setproj.call_count, 0)
179 self.assertEqual(mock_setid.call_count, 0)
herbertxueed577e82019-08-26 18:19:09 +0800180 mock_check_billing.assert_called_once()
chojoyce13cb0c52019-07-01 17:24:52 +0800181 # Test project didn't change, but client_id is empty
182 self.gcp_env_runner.client_id = ""
183 self.gcp_env_runner._SetupProject(self.gcloud_runner)
184 self.assertEqual(mock_setproj.call_count, 0)
185 mock_setid.assert_called_once()
herbertxueed577e82019-08-26 18:19:09 +0800186 self.assertEqual(mock_check_billing.call_count, 2)
chojoyce13cb0c52019-07-01 17:24:52 +0800187
herbertxueed577e82019-08-26 18:19:09 +0800188 @mock.patch.object(gcp_setup_runner.GcpTaskRunner, "_CheckBillingEnable")
chojoyce13cb0c52019-07-01 17:24:52 +0800189 @mock.patch.object(gcp_setup_runner.GcpTaskRunner, "_NeedProjectSetup")
chojoyce13cb0c52019-07-01 17:24:52 +0800190 @mock.patch.object(gcp_setup_runner.GcpTaskRunner, "_SetupClientIDSecret")
191 @mock.patch.object(gcp_setup_runner.GcpTaskRunner, "_UpdateProject")
192 def testSetupProjectChanged(self, mock_setproj, mock_setid,
herbertxuea6a953a2019-06-25 18:29:00 +0800193 mock_chkproj, mock_check_billing):
chojoyce13cb0c52019-07-01 17:24:52 +0800194 """test setup project when project changed."""
195 mock_chkproj.return_value = True
196 mock_setproj.return_value = True
197 self.gcp_env_runner._SetupProject(self.gcloud_runner)
198 mock_setproj.assert_called_once()
199 mock_setid.assert_called_once()
herbertxueed577e82019-08-26 18:19:09 +0800200 mock_check_billing.assert_called_once()
chojoyce13cb0c52019-07-01 17:24:52 +0800201
202 @mock.patch.object(utils, "GetUserAnswerYes")
203 def testNeedProjectSetup(self, mock_ans):
204 """test need project setup."""
205 # Test need project setup.
206 self.gcp_env_runner.project = ""
207 self.gcp_env_runner.zone = ""
208 self.assertTrue(self.gcp_env_runner._NeedProjectSetup())
209 # Test no need project setup and get user's answer.
210 self.gcp_env_runner.project = "test_project"
211 self.gcp_env_runner.zone = "test_zone"
212 self.gcp_env_runner._NeedProjectSetup()
213 mock_ans.assert_called_once()
214
215 def testNeedClientIDSetup(self):
216 """test need client_id setup."""
217 # Test project changed.
218 self.assertTrue(self.gcp_env_runner._NeedClientIDSetup(True))
219 # Test project is not changed but client_id or client_secret is empty.
220 self.gcp_env_runner.client_id = ""
221 self.gcp_env_runner.client_secret = ""
222 self.assertTrue(self.gcp_env_runner._NeedClientIDSetup(False))
223 # Test no need client_id setup.
224 self.gcp_env_runner.client_id = "test_client_id"
225 self.gcp_env_runner.client_secret = "test_client_secret"
226 self.assertFalse(self.gcp_env_runner._NeedClientIDSetup(False))
227
228 @mock.patch("subprocess.check_output")
chojoyce13cb0c52019-07-01 17:24:52 +0800229 def testEnableGcloudServices(self, mock_run):
230 """test enable Gcloud services."""
herbertxue2160dd92019-10-07 17:34:37 +0800231 mock_run.return_value = ""
chojoyce13cb0c52019-07-01 17:24:52 +0800232 self.gcp_env_runner._EnableGcloudServices(self.gcloud_runner)
233 mock_run.assert_has_calls([
234 mock.call(["gcloud", "services", "enable",
herbertxue2160dd92019-10-07 17:34:37 +0800235 gcp_setup_runner._ANDROID_BUILD_SERVICE], stderr=-2),
chojoyce13cb0c52019-07-01 17:24:52 +0800236 mock.call(["gcloud", "services", "enable",
herbertxue2160dd92019-10-07 17:34:37 +0800237 gcp_setup_runner._COMPUTE_ENGINE_SERVICE], stderr=-2)])
238
239 @mock.patch("subprocess.check_output")
240 def testGoogleAPIService(self, mock_run):
241 """Test GoogleAPIService"""
242 api_service = gcp_setup_runner.GoogleAPIService("service_name",
243 "error_message")
244 api_service.EnableService(self.gcloud_runner)
245 mock_run.assert_has_calls([
246 mock.call(["gcloud", "services", "enable", "service_name"], stderr=-2)])
247
248 @mock.patch("subprocess.check_output")
249 def testCheckBillingEnable(self, mock_run):
250 """Test CheckBillingEnable"""
251 # Test billing account in gcp project already enabled.
252 mock_run.return_value = "billingEnabled: true"
253 self.gcp_env_runner._CheckBillingEnable(self.gcloud_runner)
254 mock_run.assert_has_calls([
255 mock.call(["gcloud", "alpha", "billing", "projects", "describe",
256 self.gcp_env_runner.project])])
257
258 # Test billing account in gcp project was not enabled.
259 mock_run.return_value = "billingEnabled: false"
260 with self.assertRaises(errors.NoBillingError):
261 self.gcp_env_runner._CheckBillingEnable(self.gcloud_runner)
herbertxue34776bb2018-07-03 21:57:48 +0800262
263
264if __name__ == "__main__":
265 unittest.main()