blob: 7d0c2dcdf90652f2f32dfea02866ca1b27465b69 [file] [log] [blame]
# Copyright 2018 The ChromiumOS Authors
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
"""Boto compatibility functions for cbuildbot.
This module provides compatibility functions to help manage old versions of
boto/gsutil.
NOTE: This should eventually be removed as part of crbug.com/845304.
"""
import configparser
import contextlib
import logging
import os
import tempfile
from chromite.lib import constants
from chromite.lib import osutils
# Path to an updated cacerts.txt file, which will override the cacerts.txt file
# embedded in boto in the wrapped FixBotoCerts context. Relative to chromite/.
BOTO_CACERTS_PATH = "third_party/boto/boto/cacerts/cacerts.txt"
BOTO_CACERTS_ABS_PATH = str(
constants.CHROMITE_DIR / os.path.normpath(BOTO_CACERTS_PATH)
)
@contextlib.contextmanager
def FixBotoCerts(activate=True, strict=False):
"""Fix for outdated cacerts.txt file in old versions of boto/gsutil."""
if not activate:
logging.info("FixBotoCerts skipped")
yield
return
logging.info("FixBotoCerts started")
orig_env = os.environ.copy()
boto_cfg_path = None
try:
config = configparser.ConfigParser()
# Read existing boto config file(s); this mimics what boto itself does.
if "BOTO_CONFIG" in os.environ:
config.read(os.environ["BOTO_CONFIG"])
else:
boto_path = os.environ.get("BOTO_PATH", "/etc/boto.cfg:~/.boto")
config.read(boto_path.split(":"))
# Set [Boto] ca_certificates_file = <path to cacerts.txt>.
if not config.has_section("Boto"):
config.add_section("Boto")
config.set("Boto", "ca_certificates_file", BOTO_CACERTS_ABS_PATH)
# Write updated boto config to a tempfile.
fd, boto_cfg_path = tempfile.mkstemp(
prefix="fix_certs", suffix="boto.cfg"
)
os.close(fd)
with open(boto_cfg_path, "w", encoding="utf-8") as f:
config.write(f)
os.chmod(boto_cfg_path, 0o644)
# Update env to use only our generated boto config.
os.environ["BOTO_CONFIG"] = boto_cfg_path
os.environ.pop("BOTO_PATH", None)
except Exception as e:
if strict:
raise e
logging.warning("FixBotoCerts init failed: %s", e)
# Don't make things worse; let the build continue.
try:
yield
finally:
# Restore env.
osutils.SetEnvironment(orig_env)
# Clean up the boto.cfg file.
if boto_cfg_path:
try:
os.remove(boto_cfg_path)
except Exception as e:
if strict:
raise e
logging.warning(
"FixBotoCerts failed removing %s: %s", boto_cfg_path, e
)