Update cipd.py with changes from downstream
Change-Id: I88cabc042b5907d4b8a7693d1d502fba37e941e5
Reviewed-on: https://fuchsia-review.googlesource.com/c/infra/prebuilt/+/561135
Reviewed-by: Oliver Newman <olivernewman@google.com>
diff --git a/cipd.py b/cipd.py
index c2ef723..5c45101 100755
--- a/cipd.py
+++ b/cipd.py
@@ -18,16 +18,42 @@
import ssl
import subprocess
import sys
+import base64
try:
- import httplib
+ import httplib # Python 2
except ImportError:
- import http.client as httplib # type: ignore
+ import http.client as httplib
try:
- import urlparse # Python 2.
+ import urlparse # Python 2
except ImportError:
- import urllib.parse as urlparse # type: ignore
+ import urllib.parse as urlparse
+
+# Generated from the following command. May need to be periodically rerun.
+# $ cipd ls infra/tools/cipd | perl -pe "s[.*/][];s/^/ '/;s/\s*$/',\n/;"
+SUPPORTED_PLATFORMS = (
+ "aix-ppc64",
+ "linux-386",
+ "linux-amd64",
+ "linux-arm64",
+ "linux-armv6l",
+ "linux-mips64",
+ "linux-mips64le",
+ "linux-mipsle",
+ "linux-ppc64",
+ "linux-ppc64le",
+ "linux-s390x",
+ "mac-amd64",
+ "mac-arm64",
+ "windows-386",
+ "windows-amd64",
+)
+
+
+class UnsupportedPlatform(Exception):
+ pass
+
SCRIPT_DIR = os.path.dirname(__file__)
VERSION_FILE = os.path.join(SCRIPT_DIR, ".cipd_version")
@@ -43,9 +69,12 @@
try:
os_name = platform.system().lower()
- return {"linux": "linux", "mac": "mac", "darwin": "mac", "windows": "windows",}[
- os_name
- ]
+ return {
+ "linux": "linux",
+ "mac": "mac",
+ "darwin": "mac",
+ "windows": "windows",
+ }[os_name]
except KeyError:
raise Exception("unrecognized os: {}".format(os_name))
@@ -104,6 +133,30 @@
raise Exception("platform {} not in {}".format(expected_plat, DIGESTS_FILE))
+def https_connect_with_proxy(target_url):
+ """Create HTTPSConnection with proxy support."""
+
+ proxy_env = os.environ.get("HTTPS_PROXY") or os.environ.get("https_proxy")
+ if proxy_env in (None, ""):
+ conn = httplib.HTTPSConnection(target_url)
+ return conn
+
+ url = urlparse.urlparse(proxy_env)
+ conn = httplib.HTTPSConnection(url.hostname, url.port)
+ headers = {}
+ if url.username and url.password:
+ auth = "%s:%s" % (url.username, url.password)
+ py_version = sys.version_info.major
+ if py_version >= 3:
+ headers["Proxy-Authorization"] = "Basic " + str(
+ base64.b64encode(auth.encode()).decode()
+ )
+ else:
+ headers["Proxy-Authorization"] = "Basic " + base64.b64encode(auth)
+ conn.set_tunnel(target_url, 443, headers)
+ return conn
+
+
def client_bytes():
"""Pull down the CIPD client and return it as a bytes object.
@@ -116,7 +169,7 @@
version = ins.read().strip()
try:
- conn = httplib.HTTPSConnection(CIPD_HOST)
+ conn = https_connect_with_proxy(CIPD_HOST)
except AttributeError:
print("=" * 70)
print(
@@ -132,9 +185,11 @@
print("=" * 70)
raise
- path = "/client?platform={platform}-{arch}&version={version}".format(
- platform=platform_normalized(), arch=arch_normalized(), version=version
- )
+ full_platform = "{}-{}".format(platform_normalized(), arch_normalized())
+ if full_platform not in SUPPORTED_PLATFORMS:
+ raise UnsupportedPlatform(full_platform)
+
+ path = "/client?platform={}&version={}".format(full_platform, version)
for _ in range(10):
try:
@@ -151,12 +206,21 @@
"\n"
" sudo pip install certifi\n"
"\n"
+ "And if on the system Python on a Mac try\n"
+ "\n"
+ " /Applications/Python 3.6/Install Certificates.command\n"
+ "\n"
"If using Homebrew Python try\n"
"\n"
" brew install openssl\n"
" brew uninstall python\n"
" brew install python\n"
"\n"
+ "If those don't work, address all the potential issues shown \n"
+ "by the following command.\n"
+ "\n"
+ " brew doctor\n"
+ "\n"
"Otherwise, check that your machine's Python can use SSL, "
"testing with the httplib module on Python 2 or http.client on "
"Python 3.",
@@ -173,14 +237,16 @@
location = res.getheader("location")
url = urlparse.urlparse(location)
if url.netloc != conn.host:
- conn = httplib.HTTPSConnection(url.netloc)
+ conn = https_connect_with_proxy(url.netloc)
path = "{}?{}".format(url.path, url.query)
# Some kind of error in this response.
else:
break
- raise Exception("failed to download client")
+ raise Exception(
+ "failed to download client from https://{}{}".format(CIPD_HOST, path)
+ )
def bootstrap(client, silent=False):
@@ -233,19 +299,28 @@
os.environ["CIPD_HTTP_USER_AGENT_PREFIX"] = user_agent()
- try:
- if not os.path.isfile(client):
- bootstrap(client, silent)
+ if not os.path.isfile(client):
+ bootstrap(client, silent)
- try:
- selfupdate(client)
- except subprocess.CalledProcessError:
- print(
- "CIPD selfupdate failed. Bootstrapping then retrying...",
- file=sys.stderr,
- )
- bootstrap(client)
- selfupdate(client)
+ try:
+ selfupdate(client)
+ except subprocess.CalledProcessError:
+ print("CIPD selfupdate failed. Bootstrapping then retrying...", file=sys.stderr)
+ bootstrap(client)
+ selfupdate(client)
+
+ return client
+
+
+def main(client=CLIENT, silent=False):
+ """Install/update cipd client."""
+
+ try:
+ init(client=client, silent=silent)
+
+ except UnsupportedPlatform:
+ # Don't show help message below for this exception.
+ raise
except Exception:
print(
@@ -253,7 +328,9 @@
"`CIPD_HTTP_USER_AGENT_PREFIX={user_agent}/manual {client} "
"selfupdate -version-file '{version_file}'` "
"to diagnose if this is persistent.".format(
- user_agent=user_agent(), client=client, version_file=VERSION_FILE,
+ user_agent=user_agent(),
+ client=client,
+ version_file=VERSION_FILE,
),
file=sys.stderr,
)
@@ -263,5 +340,5 @@
if __name__ == "__main__":
- client_exe = init()
+ client_exe = main()
subprocess.check_call([client_exe] + sys.argv[1:])