xref: /aosp_15_r20/tools/acloud/setup/gcp_setup_runner_test.py (revision 800a58d989c669b8eb8a71d8df53b1ba3d411444)
1*800a58d9SAndroid Build Coastguard Worker#!/usr/bin/env python
2*800a58d9SAndroid Build Coastguard Worker#
3*800a58d9SAndroid Build Coastguard Worker# Copyright 2018 - The Android Open Source Project
4*800a58d9SAndroid Build Coastguard Worker#
5*800a58d9SAndroid Build Coastguard Worker# Licensed under the Apache License, Version 2.0 (the "License");
6*800a58d9SAndroid Build Coastguard Worker# you may not use this file except in compliance with the License.
7*800a58d9SAndroid Build Coastguard Worker# You may obtain a copy of the License at
8*800a58d9SAndroid Build Coastguard Worker#
9*800a58d9SAndroid Build Coastguard Worker#     http://www.apache.org/licenses/LICENSE-2.0
10*800a58d9SAndroid Build Coastguard Worker#
11*800a58d9SAndroid Build Coastguard Worker# Unless required by applicable law or agreed to in writing, software
12*800a58d9SAndroid Build Coastguard Worker# distributed under the License is distributed on an "AS IS" BASIS,
13*800a58d9SAndroid Build Coastguard Worker# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14*800a58d9SAndroid Build Coastguard Worker# See the License for the specific language governing permissions and
15*800a58d9SAndroid Build Coastguard Worker# limitations under the License.
16*800a58d9SAndroid Build Coastguard Worker"""Tests for acloud.setup.gcp_setup_runner."""
17*800a58d9SAndroid Build Coastguard Worker
18*800a58d9SAndroid Build Coastguard Workerimport unittest
19*800a58d9SAndroid Build Coastguard Workerimport os
20*800a58d9SAndroid Build Coastguard Worker
21*800a58d9SAndroid Build Coastguard Workerfrom unittest import mock
22*800a58d9SAndroid Build Coastguard Workerimport six
23*800a58d9SAndroid Build Coastguard Worker
24*800a58d9SAndroid Build Coastguard Worker# pylint: disable=no-name-in-module,import-error,no-member
25*800a58d9SAndroid Build Coastguard Workerfrom acloud import errors
26*800a58d9SAndroid Build Coastguard Workerfrom acloud.internal.lib import utils
27*800a58d9SAndroid Build Coastguard Workerfrom acloud.internal.proto import user_config_pb2
28*800a58d9SAndroid Build Coastguard Workerfrom acloud.public import config
29*800a58d9SAndroid Build Coastguard Workerfrom acloud.setup import gcp_setup_runner
30*800a58d9SAndroid Build Coastguard Worker
31*800a58d9SAndroid Build Coastguard Worker_GCP_USER_CONFIG = """
32*800a58d9SAndroid Build Coastguard Worker[compute]
33*800a58d9SAndroid Build Coastguard Workerregion = new_region
34*800a58d9SAndroid Build Coastguard Workerzone = new_zone
35*800a58d9SAndroid Build Coastguard Worker[core]
36*800a58d9SAndroid Build Coastguard Workeraccount = [email protected]
37*800a58d9SAndroid Build Coastguard Workerdisable_usage_reporting = False
38*800a58d9SAndroid Build Coastguard Workerproject = new_project
39*800a58d9SAndroid Build Coastguard Worker"""
40*800a58d9SAndroid Build Coastguard Worker
41*800a58d9SAndroid Build Coastguard Workerdef _CreateCfgFile():
42*800a58d9SAndroid Build Coastguard Worker    """A helper method that creates a mock configuration object."""
43*800a58d9SAndroid Build Coastguard Worker    default_cfg = """
44*800a58d9SAndroid Build Coastguard Workerproject: "fake_project"
45*800a58d9SAndroid Build Coastguard Workerzone: "fake_zone"
46*800a58d9SAndroid Build Coastguard Workerstorage_bucket_name: "fake_bucket"
47*800a58d9SAndroid Build Coastguard Workerclient_id: "fake_client_id"
48*800a58d9SAndroid Build Coastguard Workerclient_secret: "fake_client_secret"
49*800a58d9SAndroid Build Coastguard Worker"""
50*800a58d9SAndroid Build Coastguard Worker    return default_cfg
51*800a58d9SAndroid Build Coastguard Worker
52*800a58d9SAndroid Build Coastguard Worker
53*800a58d9SAndroid Build Coastguard Worker# pylint: disable=protected-access
54*800a58d9SAndroid Build Coastguard Workerclass AcloudGCPSetupTest(unittest.TestCase):
55*800a58d9SAndroid Build Coastguard Worker    """Test GCP Setup steps."""
56*800a58d9SAndroid Build Coastguard Worker
57*800a58d9SAndroid Build Coastguard Worker    def setUp(self):
58*800a58d9SAndroid Build Coastguard Worker        """Create config and gcp_env_runner."""
59*800a58d9SAndroid Build Coastguard Worker        self.cfg_path = "acloud_unittest.config"
60*800a58d9SAndroid Build Coastguard Worker        file_write = open(self.cfg_path, 'w')
61*800a58d9SAndroid Build Coastguard Worker        file_write.write(_CreateCfgFile().strip())
62*800a58d9SAndroid Build Coastguard Worker        file_write.close()
63*800a58d9SAndroid Build Coastguard Worker        self.gcp_env_runner = gcp_setup_runner.GcpTaskRunner(self.cfg_path)
64*800a58d9SAndroid Build Coastguard Worker        self.gcloud_runner = gcp_setup_runner.GoogleSDKBins("")
65*800a58d9SAndroid Build Coastguard Worker
66*800a58d9SAndroid Build Coastguard Worker    def tearDown(self):
67*800a58d9SAndroid Build Coastguard Worker        """Remove temp file."""
68*800a58d9SAndroid Build Coastguard Worker        if os.path.isfile(self.cfg_path):
69*800a58d9SAndroid Build Coastguard Worker            os.remove(self.cfg_path)
70*800a58d9SAndroid Build Coastguard Worker
71*800a58d9SAndroid Build Coastguard Worker    def testUpdateConfigFile(self):
72*800a58d9SAndroid Build Coastguard Worker        """Test update config file."""
73*800a58d9SAndroid Build Coastguard Worker        # Test update project field.
74*800a58d9SAndroid Build Coastguard Worker        gcp_setup_runner.UpdateConfigFile(self.cfg_path, "project",
75*800a58d9SAndroid Build Coastguard Worker                                          "test_project")
76*800a58d9SAndroid Build Coastguard Worker        cfg = config.AcloudConfigManager.LoadConfigFromProtocolBuffer(
77*800a58d9SAndroid Build Coastguard Worker            open(self.cfg_path, "r"), user_config_pb2.UserConfig)
78*800a58d9SAndroid Build Coastguard Worker        self.assertEqual(cfg.project, "test_project")
79*800a58d9SAndroid Build Coastguard Worker        self.assertEqual(cfg.ssh_private_key_path, "")
80*800a58d9SAndroid Build Coastguard Worker        # Test add ssh key path in config.
81*800a58d9SAndroid Build Coastguard Worker        gcp_setup_runner.UpdateConfigFile(self.cfg_path,
82*800a58d9SAndroid Build Coastguard Worker                                          "ssh_private_key_path", "test_path")
83*800a58d9SAndroid Build Coastguard Worker        cfg = config.AcloudConfigManager.LoadConfigFromProtocolBuffer(
84*800a58d9SAndroid Build Coastguard Worker            open(self.cfg_path, "r"), user_config_pb2.UserConfig)
85*800a58d9SAndroid Build Coastguard Worker        self.assertEqual(cfg.project, "test_project")
86*800a58d9SAndroid Build Coastguard Worker        self.assertEqual(cfg.ssh_private_key_path, "test_path")
87*800a58d9SAndroid Build Coastguard Worker        # Test config is not a file
88*800a58d9SAndroid Build Coastguard Worker        with mock.patch("os.path.isfile") as chkfile:
89*800a58d9SAndroid Build Coastguard Worker            chkfile.return_value = False
90*800a58d9SAndroid Build Coastguard Worker            gcp_setup_runner.UpdateConfigFile(self.cfg_path, "project",
91*800a58d9SAndroid Build Coastguard Worker                                              "test_project")
92*800a58d9SAndroid Build Coastguard Worker            cfg = config.AcloudConfigManager.LoadConfigFromProtocolBuffer(
93*800a58d9SAndroid Build Coastguard Worker                open(self.cfg_path, "r"), user_config_pb2.UserConfig)
94*800a58d9SAndroid Build Coastguard Worker            self.assertEqual(cfg.project, "test_project")
95*800a58d9SAndroid Build Coastguard Worker
96*800a58d9SAndroid Build Coastguard Worker    @mock.patch("os.path.dirname", return_value="")
97*800a58d9SAndroid Build Coastguard Worker    @mock.patch.object(utils, "CheckOutput")
98*800a58d9SAndroid Build Coastguard Worker    def testSeupProjectZone(self, mock_runner, mock_path):
99*800a58d9SAndroid Build Coastguard Worker        """Test setup project and zone."""
100*800a58d9SAndroid Build Coastguard Worker        gcloud_runner = gcp_setup_runner.GoogleSDKBins(mock_path)
101*800a58d9SAndroid Build Coastguard Worker        self.gcp_env_runner.project = "fake_project"
102*800a58d9SAndroid Build Coastguard Worker        self.gcp_env_runner.zone = "fake_zone"
103*800a58d9SAndroid Build Coastguard Worker        mock_runner.side_effect = [0, _GCP_USER_CONFIG]
104*800a58d9SAndroid Build Coastguard Worker        self.gcp_env_runner._UpdateProject(gcloud_runner)
105*800a58d9SAndroid Build Coastguard Worker        self.assertEqual(self.gcp_env_runner.project, "new_project")
106*800a58d9SAndroid Build Coastguard Worker        self.assertEqual(self.gcp_env_runner.zone, "new_zone")
107*800a58d9SAndroid Build Coastguard Worker
108*800a58d9SAndroid Build Coastguard Worker    @mock.patch.object(six.moves, "input")
109*800a58d9SAndroid Build Coastguard Worker    def testSetupClientIDSecret(self, mock_id):
110*800a58d9SAndroid Build Coastguard Worker        """Test setup client ID and client secret."""
111*800a58d9SAndroid Build Coastguard Worker        self.gcp_env_runner.client_id = "fake_client_id"
112*800a58d9SAndroid Build Coastguard Worker        self.gcp_env_runner.client_secret = "fake_client_secret"
113*800a58d9SAndroid Build Coastguard Worker        mock_id.side_effect = ["new_id", "new_secret"]
114*800a58d9SAndroid Build Coastguard Worker        self.gcp_env_runner._SetupClientIDSecret()
115*800a58d9SAndroid Build Coastguard Worker        self.assertEqual(self.gcp_env_runner.client_id, "new_id")
116*800a58d9SAndroid Build Coastguard Worker        self.assertEqual(self.gcp_env_runner.client_secret, "new_secret")
117*800a58d9SAndroid Build Coastguard Worker
118*800a58d9SAndroid Build Coastguard Worker    @mock.patch.object(gcp_setup_runner, "UpdateConfigFile")
119*800a58d9SAndroid Build Coastguard Worker    @mock.patch.object(utils, "CreateSshKeyPairIfNotExist")
120*800a58d9SAndroid Build Coastguard Worker    def testSetupSSHKeys(self, mock_check, mock_update):
121*800a58d9SAndroid Build Coastguard Worker        """Test setup the pair of the ssh key for acloud.config."""
122*800a58d9SAndroid Build Coastguard Worker        # Test ssh key has already setup
123*800a58d9SAndroid Build Coastguard Worker        gcp_setup_runner.SetupSSHKeys(self.cfg_path,
124*800a58d9SAndroid Build Coastguard Worker                                      "fake_private_key_path",
125*800a58d9SAndroid Build Coastguard Worker                                      "fake_public_key_path")
126*800a58d9SAndroid Build Coastguard Worker        self.assertEqual(mock_update.call_count, 0)
127*800a58d9SAndroid Build Coastguard Worker        # Test if private_key_path is empty string
128*800a58d9SAndroid Build Coastguard Worker        with mock.patch('os.path.expanduser') as ssh_path:
129*800a58d9SAndroid Build Coastguard Worker            ssh_path.return_value = ""
130*800a58d9SAndroid Build Coastguard Worker            gcp_setup_runner.SetupSSHKeys(self.cfg_path,
131*800a58d9SAndroid Build Coastguard Worker                                          "fake_private_key_path",
132*800a58d9SAndroid Build Coastguard Worker                                          "fake_public_key_path")
133*800a58d9SAndroid Build Coastguard Worker            mock_check.assert_called_once_with(
134*800a58d9SAndroid Build Coastguard Worker                gcp_setup_runner._DEFAULT_SSH_PRIVATE_KEY,
135*800a58d9SAndroid Build Coastguard Worker                gcp_setup_runner._DEFAULT_SSH_PUBLIC_KEY)
136*800a58d9SAndroid Build Coastguard Worker
137*800a58d9SAndroid Build Coastguard Worker            mock_update.assert_has_calls([
138*800a58d9SAndroid Build Coastguard Worker                mock.call(self.cfg_path, "ssh_private_key_path",
139*800a58d9SAndroid Build Coastguard Worker                          gcp_setup_runner._DEFAULT_SSH_PRIVATE_KEY),
140*800a58d9SAndroid Build Coastguard Worker                mock.call(self.cfg_path, "ssh_public_key_path",
141*800a58d9SAndroid Build Coastguard Worker                          gcp_setup_runner._DEFAULT_SSH_PUBLIC_KEY)])
142*800a58d9SAndroid Build Coastguard Worker
143*800a58d9SAndroid Build Coastguard Worker    @mock.patch.object(gcp_setup_runner.GcpTaskRunner, "_CreateStableHostImage")
144*800a58d9SAndroid Build Coastguard Worker    @mock.patch.object(gcp_setup_runner.GcpTaskRunner, "_EnableGcloudServices")
145*800a58d9SAndroid Build Coastguard Worker    @mock.patch.object(gcp_setup_runner.GcpTaskRunner, "_SetupProject")
146*800a58d9SAndroid Build Coastguard Worker    @mock.patch.object(gcp_setup_runner, "GoogleSDKBins")
147*800a58d9SAndroid Build Coastguard Worker    def testSetupGcloudInfo(self, mock_sdk, mock_set, mock_run, mock_create):
148*800a58d9SAndroid Build Coastguard Worker        """test setup gcloud info"""
149*800a58d9SAndroid Build Coastguard Worker        with mock.patch("acloud.setup.google_sdk.GoogleSDK"):
150*800a58d9SAndroid Build Coastguard Worker            self.gcp_env_runner._SetupGcloudInfo()
151*800a58d9SAndroid Build Coastguard Worker            mock_sdk.assert_called_once()
152*800a58d9SAndroid Build Coastguard Worker            mock_set.assert_called_once()
153*800a58d9SAndroid Build Coastguard Worker            mock_run.assert_called_once()
154*800a58d9SAndroid Build Coastguard Worker            mock_create.assert_called_once()
155*800a58d9SAndroid Build Coastguard Worker
156*800a58d9SAndroid Build Coastguard Worker    @mock.patch.object(gcp_setup_runner, "UpdateConfigFile")
157*800a58d9SAndroid Build Coastguard Worker    def testCreateStableHostImage(self, mock_update):
158*800a58d9SAndroid Build Coastguard Worker        """test create stable hostimage."""
159*800a58d9SAndroid Build Coastguard Worker        # Test no need to create stable hose image name.
160*800a58d9SAndroid Build Coastguard Worker        self.gcp_env_runner.stable_host_image_name = "fake_host_image_name"
161*800a58d9SAndroid Build Coastguard Worker        self.gcp_env_runner._CreateStableHostImage()
162*800a58d9SAndroid Build Coastguard Worker        self.assertEqual(mock_update.call_count, 0)
163*800a58d9SAndroid Build Coastguard Worker        # Test need to reset stable hose image name.
164*800a58d9SAndroid Build Coastguard Worker        self.gcp_env_runner.stable_host_image_name = ""
165*800a58d9SAndroid Build Coastguard Worker        self.gcp_env_runner._CreateStableHostImage()
166*800a58d9SAndroid Build Coastguard Worker        self.assertEqual(mock_update.call_count, 1)
167*800a58d9SAndroid Build Coastguard Worker
168*800a58d9SAndroid Build Coastguard Worker    @mock.patch.object(gcp_setup_runner.GcpTaskRunner, "_CheckBillingEnable")
169*800a58d9SAndroid Build Coastguard Worker    @mock.patch.object(gcp_setup_runner.GcpTaskRunner, "_NeedProjectSetup")
170*800a58d9SAndroid Build Coastguard Worker    @mock.patch.object(gcp_setup_runner.GcpTaskRunner, "_SetupClientIDSecret")
171*800a58d9SAndroid Build Coastguard Worker    @mock.patch.object(gcp_setup_runner.GcpTaskRunner, "_UpdateProject")
172*800a58d9SAndroid Build Coastguard Worker    def testSetupProjectNoChange(self, mock_setproj, mock_setid,
173*800a58d9SAndroid Build Coastguard Worker                                 mock_chkproj, mock_check_billing):
174*800a58d9SAndroid Build Coastguard Worker        """test setup project and project not be changed."""
175*800a58d9SAndroid Build Coastguard Worker        # Test project didn't change, and no need to setup client id/secret
176*800a58d9SAndroid Build Coastguard Worker        mock_chkproj.return_value = False
177*800a58d9SAndroid Build Coastguard Worker        self.gcp_env_runner.client_id = "test_client_id"
178*800a58d9SAndroid Build Coastguard Worker        self.gcp_env_runner._SetupProject(self.gcloud_runner)
179*800a58d9SAndroid Build Coastguard Worker        self.assertEqual(mock_setproj.call_count, 0)
180*800a58d9SAndroid Build Coastguard Worker        self.assertEqual(mock_setid.call_count, 0)
181*800a58d9SAndroid Build Coastguard Worker        mock_check_billing.assert_called_once()
182*800a58d9SAndroid Build Coastguard Worker        # Test project didn't change, but client_id is empty
183*800a58d9SAndroid Build Coastguard Worker        self.gcp_env_runner.client_id = ""
184*800a58d9SAndroid Build Coastguard Worker        self.gcp_env_runner._SetupProject(self.gcloud_runner)
185*800a58d9SAndroid Build Coastguard Worker        self.assertEqual(mock_setproj.call_count, 0)
186*800a58d9SAndroid Build Coastguard Worker        mock_setid.assert_called_once()
187*800a58d9SAndroid Build Coastguard Worker        self.assertEqual(mock_check_billing.call_count, 2)
188*800a58d9SAndroid Build Coastguard Worker
189*800a58d9SAndroid Build Coastguard Worker    @mock.patch.object(gcp_setup_runner.GcpTaskRunner, "_CheckBillingEnable")
190*800a58d9SAndroid Build Coastguard Worker    @mock.patch.object(gcp_setup_runner.GcpTaskRunner, "_NeedProjectSetup")
191*800a58d9SAndroid Build Coastguard Worker    @mock.patch.object(gcp_setup_runner.GcpTaskRunner, "_SetupClientIDSecret")
192*800a58d9SAndroid Build Coastguard Worker    @mock.patch.object(gcp_setup_runner.GcpTaskRunner, "_UpdateProject")
193*800a58d9SAndroid Build Coastguard Worker    def testSetupProjectChanged(self, mock_setproj, mock_setid,
194*800a58d9SAndroid Build Coastguard Worker                                mock_chkproj, mock_check_billing):
195*800a58d9SAndroid Build Coastguard Worker        """test setup project when project changed."""
196*800a58d9SAndroid Build Coastguard Worker        mock_chkproj.return_value = True
197*800a58d9SAndroid Build Coastguard Worker        mock_setproj.return_value = True
198*800a58d9SAndroid Build Coastguard Worker        self.gcp_env_runner._SetupProject(self.gcloud_runner)
199*800a58d9SAndroid Build Coastguard Worker        mock_setproj.assert_called_once()
200*800a58d9SAndroid Build Coastguard Worker        mock_setid.assert_called_once()
201*800a58d9SAndroid Build Coastguard Worker        mock_check_billing.assert_called_once()
202*800a58d9SAndroid Build Coastguard Worker
203*800a58d9SAndroid Build Coastguard Worker    @mock.patch.object(utils, "GetUserAnswerYes")
204*800a58d9SAndroid Build Coastguard Worker    def testNeedProjectSetup(self, mock_ans):
205*800a58d9SAndroid Build Coastguard Worker        """test need project setup."""
206*800a58d9SAndroid Build Coastguard Worker        # Test need project setup.
207*800a58d9SAndroid Build Coastguard Worker        self.gcp_env_runner.project = ""
208*800a58d9SAndroid Build Coastguard Worker        self.gcp_env_runner.zone = ""
209*800a58d9SAndroid Build Coastguard Worker        self.assertTrue(self.gcp_env_runner._NeedProjectSetup())
210*800a58d9SAndroid Build Coastguard Worker        # Test no need project setup and get user's answer.
211*800a58d9SAndroid Build Coastguard Worker        self.gcp_env_runner.project = "test_project"
212*800a58d9SAndroid Build Coastguard Worker        self.gcp_env_runner.zone = "test_zone"
213*800a58d9SAndroid Build Coastguard Worker        self.gcp_env_runner._NeedProjectSetup()
214*800a58d9SAndroid Build Coastguard Worker        mock_ans.assert_called_once()
215*800a58d9SAndroid Build Coastguard Worker
216*800a58d9SAndroid Build Coastguard Worker    def testNeedClientIDSetup(self):
217*800a58d9SAndroid Build Coastguard Worker        """test need client_id setup."""
218*800a58d9SAndroid Build Coastguard Worker        # Test project changed.
219*800a58d9SAndroid Build Coastguard Worker        self.assertTrue(self.gcp_env_runner._NeedClientIDSetup(True))
220*800a58d9SAndroid Build Coastguard Worker        # Test project is not changed but client_id or client_secret is empty.
221*800a58d9SAndroid Build Coastguard Worker        self.gcp_env_runner.client_id = ""
222*800a58d9SAndroid Build Coastguard Worker        self.gcp_env_runner.client_secret = ""
223*800a58d9SAndroid Build Coastguard Worker        self.assertTrue(self.gcp_env_runner._NeedClientIDSetup(False))
224*800a58d9SAndroid Build Coastguard Worker        # Test no need client_id setup.
225*800a58d9SAndroid Build Coastguard Worker        self.gcp_env_runner.client_id = "test_client_id"
226*800a58d9SAndroid Build Coastguard Worker        self.gcp_env_runner.client_secret = "test_client_secret"
227*800a58d9SAndroid Build Coastguard Worker        self.assertFalse(self.gcp_env_runner._NeedClientIDSetup(False))
228*800a58d9SAndroid Build Coastguard Worker
229*800a58d9SAndroid Build Coastguard Worker    @mock.patch.object(utils, "CheckOutput")
230*800a58d9SAndroid Build Coastguard Worker    def testEnableGcloudServices(self, mock_run):
231*800a58d9SAndroid Build Coastguard Worker        """test enable Gcloud services."""
232*800a58d9SAndroid Build Coastguard Worker        mock_run.return_value = ""
233*800a58d9SAndroid Build Coastguard Worker        self.gcp_env_runner._EnableGcloudServices(self.gcloud_runner)
234*800a58d9SAndroid Build Coastguard Worker        mock_run.assert_has_calls([
235*800a58d9SAndroid Build Coastguard Worker            mock.call(["gcloud", "services", "enable",
236*800a58d9SAndroid Build Coastguard Worker                       gcp_setup_runner._ANDROID_BUILD_SERVICE],
237*800a58d9SAndroid Build Coastguard Worker                      env=self.gcloud_runner._env, stderr=-2),
238*800a58d9SAndroid Build Coastguard Worker            mock.call(["gcloud", "services", "enable",
239*800a58d9SAndroid Build Coastguard Worker                       gcp_setup_runner._COMPUTE_ENGINE_SERVICE],
240*800a58d9SAndroid Build Coastguard Worker                      env=self.gcloud_runner._env, stderr=-2)])
241*800a58d9SAndroid Build Coastguard Worker
242*800a58d9SAndroid Build Coastguard Worker    @mock.patch.object(utils, "CheckOutput")
243*800a58d9SAndroid Build Coastguard Worker    def testGoogleAPIService(self, mock_run):
244*800a58d9SAndroid Build Coastguard Worker        """Test GoogleAPIService"""
245*800a58d9SAndroid Build Coastguard Worker        api_service = gcp_setup_runner.GoogleAPIService("service_name",
246*800a58d9SAndroid Build Coastguard Worker                                                        "error_message")
247*800a58d9SAndroid Build Coastguard Worker        api_service.EnableService(self.gcloud_runner)
248*800a58d9SAndroid Build Coastguard Worker        mock_run.assert_has_calls([
249*800a58d9SAndroid Build Coastguard Worker            mock.call(["gcloud", "services", "enable", "service_name"],
250*800a58d9SAndroid Build Coastguard Worker                      env=self.gcloud_runner._env, stderr=-2)])
251*800a58d9SAndroid Build Coastguard Worker
252*800a58d9SAndroid Build Coastguard Worker    @mock.patch.object(utils, "CheckOutput")
253*800a58d9SAndroid Build Coastguard Worker    def testCheckBillingEnable(self, mock_run):
254*800a58d9SAndroid Build Coastguard Worker        """Test CheckBillingEnable"""
255*800a58d9SAndroid Build Coastguard Worker        # Test billing account in gcp project already enabled.
256*800a58d9SAndroid Build Coastguard Worker        mock_run.return_value = "billingEnabled: true"
257*800a58d9SAndroid Build Coastguard Worker        self.gcp_env_runner._CheckBillingEnable(self.gcloud_runner)
258*800a58d9SAndroid Build Coastguard Worker        mock_run.assert_has_calls([
259*800a58d9SAndroid Build Coastguard Worker            mock.call(
260*800a58d9SAndroid Build Coastguard Worker                [
261*800a58d9SAndroid Build Coastguard Worker                    "gcloud", "alpha", "billing", "projects", "describe",
262*800a58d9SAndroid Build Coastguard Worker                    self.gcp_env_runner.project
263*800a58d9SAndroid Build Coastguard Worker                ],
264*800a58d9SAndroid Build Coastguard Worker                env=self.gcloud_runner._env)
265*800a58d9SAndroid Build Coastguard Worker        ])
266*800a58d9SAndroid Build Coastguard Worker
267*800a58d9SAndroid Build Coastguard Worker        # Test billing account in gcp project was not enabled.
268*800a58d9SAndroid Build Coastguard Worker        mock_run.return_value = "billingEnabled: false"
269*800a58d9SAndroid Build Coastguard Worker        with self.assertRaises(errors.NoBillingError):
270*800a58d9SAndroid Build Coastguard Worker            self.gcp_env_runner._CheckBillingEnable(self.gcloud_runner)
271*800a58d9SAndroid Build Coastguard Worker
272*800a58d9SAndroid Build Coastguard Worker
273*800a58d9SAndroid Build Coastguard Workerif __name__ == "__main__":
274*800a58d9SAndroid Build Coastguard Worker    unittest.main()
275