xref: /aosp_15_r20/tools/acloud/setup/google_sdk.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"""google SDK tools installer.
17*800a58d9SAndroid Build Coastguard Worker
18*800a58d9SAndroid Build Coastguard WorkerThis class will return the path to the google sdk tools and download them into
19*800a58d9SAndroid Build Coastguard Workera temporary dir if they don't exist. The caller is expected to call cleanup
20*800a58d9SAndroid Build Coastguard Workerwhen they're done.
21*800a58d9SAndroid Build Coastguard Worker
22*800a58d9SAndroid Build Coastguard WorkerExample usage:
23*800a58d9SAndroid Build Coastguard Workergoogle_sdk = GoogleSDK()
24*800a58d9SAndroid Build Coastguard Workergoogle_sdk_bin_path = google_sdk.GetSDKBinPath()
25*800a58d9SAndroid Build Coastguard Worker
26*800a58d9SAndroid Build Coastguard Worker# Caller is done.
27*800a58d9SAndroid Build Coastguard Workergoogle_sdk.CleanUp()
28*800a58d9SAndroid Build Coastguard Worker"""
29*800a58d9SAndroid Build Coastguard Worker
30*800a58d9SAndroid Build Coastguard Workerimport logging
31*800a58d9SAndroid Build Coastguard Workerimport os
32*800a58d9SAndroid Build Coastguard Workerimport platform
33*800a58d9SAndroid Build Coastguard Workerimport shutil
34*800a58d9SAndroid Build Coastguard Workerimport sys
35*800a58d9SAndroid Build Coastguard Workerimport tempfile
36*800a58d9SAndroid Build Coastguard Workerfrom six.moves import urllib
37*800a58d9SAndroid Build Coastguard Worker
38*800a58d9SAndroid Build Coastguard Workerfrom acloud import errors
39*800a58d9SAndroid Build Coastguard Workerfrom acloud.internal.lib import utils
40*800a58d9SAndroid Build Coastguard Worker
41*800a58d9SAndroid Build Coastguard Worker
42*800a58d9SAndroid Build Coastguard Workerlogger = logging.getLogger(__name__)
43*800a58d9SAndroid Build Coastguard Worker
44*800a58d9SAndroid Build Coastguard WorkerSDK_BIN_PATH = os.path.join("google-cloud-sdk", "bin")
45*800a58d9SAndroid Build Coastguard WorkerGCLOUD_BIN = "gcloud"
46*800a58d9SAndroid Build Coastguard WorkerGCLOUD_COMPONENT_NOT_INSTALLED = "Not Installed"
47*800a58d9SAndroid Build Coastguard WorkerGCP_SDK_VERSION = "209.0.0"
48*800a58d9SAndroid Build Coastguard WorkerGCP_SDK_TOOLS_URL = "https://dl.google.com/dl/cloudsdk/channels/rapid/downloads"
49*800a58d9SAndroid Build Coastguard WorkerLINUX_GCP_SDK_64_URL = "%s/google-cloud-sdk-%s-linux-x86_64.tar.gz" % (
50*800a58d9SAndroid Build Coastguard Worker    GCP_SDK_TOOLS_URL, GCP_SDK_VERSION)
51*800a58d9SAndroid Build Coastguard WorkerLINUX_GCP_SDK_32_URL = "%s/google-cloud-sdk-%s-linux-x86.tar.gz" % (
52*800a58d9SAndroid Build Coastguard Worker    GCP_SDK_TOOLS_URL, GCP_SDK_VERSION)
53*800a58d9SAndroid Build Coastguard WorkerWIN_GCP_SDK_64_URL = "%s/google-cloud-sdk-%s-windows-x86_64.zip" % (
54*800a58d9SAndroid Build Coastguard Worker    GCP_SDK_TOOLS_URL, GCP_SDK_VERSION)
55*800a58d9SAndroid Build Coastguard WorkerWIN_GCP_SDK_32_URL = "%s/google-cloud-sdk-%s-windows-x86.zip" % (
56*800a58d9SAndroid Build Coastguard Worker    GCP_SDK_TOOLS_URL, GCP_SDK_VERSION)
57*800a58d9SAndroid Build Coastguard WorkerMAC_GCP_SDK_64_URL = "%s/google-cloud-sdk-%s-darwin-x86_64.tar.gz" % (
58*800a58d9SAndroid Build Coastguard Worker    GCP_SDK_TOOLS_URL, GCP_SDK_VERSION)
59*800a58d9SAndroid Build Coastguard WorkerMAC_GCP_SDK_32_URL = "%s/google-cloud-sdk-%s-darwin-x86.tar.gz" % (
60*800a58d9SAndroid Build Coastguard Worker    GCP_SDK_TOOLS_URL, GCP_SDK_VERSION)
61*800a58d9SAndroid Build Coastguard WorkerLINUX = "linux"
62*800a58d9SAndroid Build Coastguard WorkerWIN = "windows"
63*800a58d9SAndroid Build Coastguard WorkerMAC = "darwin"
64*800a58d9SAndroid Build Coastguard Worker
65*800a58d9SAndroid Build Coastguard Worker
66*800a58d9SAndroid Build Coastguard Workerdef GetSdkUrl():
67*800a58d9SAndroid Build Coastguard Worker    """Get google SDK tool url.
68*800a58d9SAndroid Build Coastguard Worker
69*800a58d9SAndroid Build Coastguard Worker    Return:
70*800a58d9SAndroid Build Coastguard Worker        String, a URL of google SDK tools.
71*800a58d9SAndroid Build Coastguard Worker
72*800a58d9SAndroid Build Coastguard Worker    Raises:
73*800a58d9SAndroid Build Coastguard Worker        OSTypeError when OS type is neither linux, mac, or windows.
74*800a58d9SAndroid Build Coastguard Worker    """
75*800a58d9SAndroid Build Coastguard Worker    is_64bits = sys.maxsize > 2**32
76*800a58d9SAndroid Build Coastguard Worker    os_type = platform.system().lower()
77*800a58d9SAndroid Build Coastguard Worker    if is_64bits:
78*800a58d9SAndroid Build Coastguard Worker        if os_type == LINUX:
79*800a58d9SAndroid Build Coastguard Worker            return LINUX_GCP_SDK_64_URL
80*800a58d9SAndroid Build Coastguard Worker        if os_type == MAC:
81*800a58d9SAndroid Build Coastguard Worker            return MAC_GCP_SDK_64_URL
82*800a58d9SAndroid Build Coastguard Worker        if os_type == WIN:
83*800a58d9SAndroid Build Coastguard Worker            return WIN_GCP_SDK_64_URL
84*800a58d9SAndroid Build Coastguard Worker    else:
85*800a58d9SAndroid Build Coastguard Worker        if os_type == LINUX:
86*800a58d9SAndroid Build Coastguard Worker            return LINUX_GCP_SDK_32_URL
87*800a58d9SAndroid Build Coastguard Worker        if os_type == MAC:
88*800a58d9SAndroid Build Coastguard Worker            return MAC_GCP_SDK_32_URL
89*800a58d9SAndroid Build Coastguard Worker        if os_type == WIN:
90*800a58d9SAndroid Build Coastguard Worker            return WIN_GCP_SDK_32_URL
91*800a58d9SAndroid Build Coastguard Worker    raise errors.OSTypeError("no gcloud for os type: %s" % (os_type))
92*800a58d9SAndroid Build Coastguard Worker
93*800a58d9SAndroid Build Coastguard Worker
94*800a58d9SAndroid Build Coastguard Workerdef SDKInstalled():
95*800a58d9SAndroid Build Coastguard Worker    """Check google SDK tools installed.
96*800a58d9SAndroid Build Coastguard Worker
97*800a58d9SAndroid Build Coastguard Worker    We'll try to find where gcloud is and assume the other google sdk tools
98*800a58d9SAndroid Build Coastguard Worker    live in the same location.
99*800a58d9SAndroid Build Coastguard Worker
100*800a58d9SAndroid Build Coastguard Worker    Return:
101*800a58d9SAndroid Build Coastguard Worker        Boolean, return True if gcloud is installed, False otherwise.
102*800a58d9SAndroid Build Coastguard Worker    """
103*800a58d9SAndroid Build Coastguard Worker    if utils.FindExecutable(GCLOUD_BIN):
104*800a58d9SAndroid Build Coastguard Worker        return True
105*800a58d9SAndroid Build Coastguard Worker    return False
106*800a58d9SAndroid Build Coastguard Worker
107*800a58d9SAndroid Build Coastguard Worker
108*800a58d9SAndroid Build Coastguard Workerclass GoogleSDK():
109*800a58d9SAndroid Build Coastguard Worker    """Google SDK tools installer."""
110*800a58d9SAndroid Build Coastguard Worker
111*800a58d9SAndroid Build Coastguard Worker    def __init__(self):
112*800a58d9SAndroid Build Coastguard Worker        """GoogleSDKInstaller initialize.
113*800a58d9SAndroid Build Coastguard Worker
114*800a58d9SAndroid Build Coastguard Worker        Make sure the GCloud SDK is installed. If not, this function will assist
115*800a58d9SAndroid Build Coastguard Worker        users to install.
116*800a58d9SAndroid Build Coastguard Worker        """
117*800a58d9SAndroid Build Coastguard Worker        self._tmp_path = None
118*800a58d9SAndroid Build Coastguard Worker        self._tmp_sdk_path = None
119*800a58d9SAndroid Build Coastguard Worker        if not SDKInstalled():
120*800a58d9SAndroid Build Coastguard Worker            self.DownloadGcloudSDKAndExtract()
121*800a58d9SAndroid Build Coastguard Worker
122*800a58d9SAndroid Build Coastguard Worker    @staticmethod
123*800a58d9SAndroid Build Coastguard Worker    def InstallGcloudComponent(gcloud_runner, component):
124*800a58d9SAndroid Build Coastguard Worker        """Install gcloud component.
125*800a58d9SAndroid Build Coastguard Worker
126*800a58d9SAndroid Build Coastguard Worker        Args:
127*800a58d9SAndroid Build Coastguard Worker            gcloud_runner: A GcloudRunner class to run "gcloud" command.
128*800a58d9SAndroid Build Coastguard Worker            component: String, name of gcloud component.
129*800a58d9SAndroid Build Coastguard Worker        """
130*800a58d9SAndroid Build Coastguard Worker        result = gcloud_runner.RunGcloud([
131*800a58d9SAndroid Build Coastguard Worker            "components", "list", "--format", "get(state.name)", "--filter",
132*800a58d9SAndroid Build Coastguard Worker            "ID=%s" % component
133*800a58d9SAndroid Build Coastguard Worker        ])
134*800a58d9SAndroid Build Coastguard Worker        if result.strip() == GCLOUD_COMPONENT_NOT_INSTALLED:
135*800a58d9SAndroid Build Coastguard Worker            gcloud_runner.RunGcloud(
136*800a58d9SAndroid Build Coastguard Worker                ["components", "install", "--quiet", component])
137*800a58d9SAndroid Build Coastguard Worker
138*800a58d9SAndroid Build Coastguard Worker    def GetSDKBinPath(self):
139*800a58d9SAndroid Build Coastguard Worker        """Get google SDK tools bin path.
140*800a58d9SAndroid Build Coastguard Worker
141*800a58d9SAndroid Build Coastguard Worker        We assumed there are google sdk tools somewhere and will raise if we
142*800a58d9SAndroid Build Coastguard Worker        can't find it. The order we're looking for is:
143*800a58d9SAndroid Build Coastguard Worker        1. Builtin gcloud (usually /usr/bin), we'll return /usr/bin with the
144*800a58d9SAndroid Build Coastguard Worker           assumption other sdk tools live there.
145*800a58d9SAndroid Build Coastguard Worker        2. Downloaded google sdk (self._tmp_dir), we assumed the caller already
146*800a58d9SAndroid Build Coastguard Worker           downloaded/extracted and set the self._tmp_sdk_path for us to return.
147*800a58d9SAndroid Build Coastguard Worker           We'll make sure it exists prior to returning it.
148*800a58d9SAndroid Build Coastguard Worker
149*800a58d9SAndroid Build Coastguard Worker        Return:
150*800a58d9SAndroid Build Coastguard Worker            String, return google SDK tools bin path.
151*800a58d9SAndroid Build Coastguard Worker
152*800a58d9SAndroid Build Coastguard Worker        Raise:
153*800a58d9SAndroid Build Coastguard Worker            NoGoogleSDKDetected if we can't find the sdk path.
154*800a58d9SAndroid Build Coastguard Worker        """
155*800a58d9SAndroid Build Coastguard Worker        builtin_gcloud = utils.FindExecutable(GCLOUD_BIN)
156*800a58d9SAndroid Build Coastguard Worker        if builtin_gcloud:
157*800a58d9SAndroid Build Coastguard Worker            return os.path.dirname(builtin_gcloud)
158*800a58d9SAndroid Build Coastguard Worker        if os.path.exists(self._tmp_sdk_path):
159*800a58d9SAndroid Build Coastguard Worker            return self._tmp_sdk_path
160*800a58d9SAndroid Build Coastguard Worker        raise errors.NoGoogleSDKDetected("no sdk path.")
161*800a58d9SAndroid Build Coastguard Worker
162*800a58d9SAndroid Build Coastguard Worker    def DownloadGcloudSDKAndExtract(self):
163*800a58d9SAndroid Build Coastguard Worker        """Download the google SDK tools and decompress it.
164*800a58d9SAndroid Build Coastguard Worker
165*800a58d9SAndroid Build Coastguard Worker        Download the google SDK from the GCP web.
166*800a58d9SAndroid Build Coastguard Worker        Reference https://cloud.google.com/sdk/docs/downloads-versioned-archives.
167*800a58d9SAndroid Build Coastguard Worker        """
168*800a58d9SAndroid Build Coastguard Worker        self._tmp_path = tempfile.mkdtemp(prefix="gcloud")
169*800a58d9SAndroid Build Coastguard Worker        url = GetSdkUrl()
170*800a58d9SAndroid Build Coastguard Worker        filename = url[url.rfind("/") + 1:]
171*800a58d9SAndroid Build Coastguard Worker        file_path = os.path.join(self._tmp_path, filename)
172*800a58d9SAndroid Build Coastguard Worker        logger.info("Download file from: %s", url)
173*800a58d9SAndroid Build Coastguard Worker        logger.info("Save the file to: %s", file_path)
174*800a58d9SAndroid Build Coastguard Worker        url_stream = urllib.request.urlopen(url)
175*800a58d9SAndroid Build Coastguard Worker        metadata = url_stream.info()
176*800a58d9SAndroid Build Coastguard Worker        file_size = int(metadata.get("Content-Length"))
177*800a58d9SAndroid Build Coastguard Worker        logger.info("Downloading google SDK: %s bytes.", file_size)
178*800a58d9SAndroid Build Coastguard Worker        with open(file_path, 'wb') as output:
179*800a58d9SAndroid Build Coastguard Worker            output.write(url_stream.read())
180*800a58d9SAndroid Build Coastguard Worker        utils.Decompress(file_path, self._tmp_path)
181*800a58d9SAndroid Build Coastguard Worker        self._tmp_sdk_path = os.path.join(self._tmp_path, SDK_BIN_PATH)
182*800a58d9SAndroid Build Coastguard Worker
183*800a58d9SAndroid Build Coastguard Worker    def CleanUp(self):
184*800a58d9SAndroid Build Coastguard Worker        """Clean google sdk tools install folder."""
185*800a58d9SAndroid Build Coastguard Worker        if self._tmp_path and os.path.exists(self._tmp_path):
186*800a58d9SAndroid Build Coastguard Worker            shutil.rmtree(self._tmp_path)
187