|
15 | 15 | from __future__ import absolute_import |
16 | 16 |
|
17 | 17 | import os |
| 18 | +import re |
18 | 19 | import signal |
19 | 20 | import subprocess |
20 | 21 | import sys |
21 | 22 |
|
| 23 | +import boto3 |
22 | 24 | import pkg_resources |
23 | 25 | import psutil |
24 | 26 | from retrying import retry |
@@ -199,14 +201,67 @@ def _terminate(signo, frame): # pylint: disable=unused-argument |
199 | 201 | def _install_requirements(): |
200 | 202 | logger.info("installing packages from requirements.txt...") |
201 | 203 | pip_install_cmd = [sys.executable, "-m", "pip", "install", "-r", REQUIREMENTS_PATH] |
202 | | - |
| 204 | + if os.getenv("CA_REPOSITORY_ARN"): |
| 205 | + index = _get_codeartifact_index() |
| 206 | + pip_install_cmd.append("-i") |
| 207 | + pip_install_cmd.append(index) |
203 | 208 | try: |
204 | 209 | subprocess.check_call(pip_install_cmd) |
205 | 210 | except subprocess.CalledProcessError: |
206 | 211 | logger.error("failed to install required packages, exiting") |
207 | 212 | raise ValueError("failed to install required packages") |
208 | 213 |
|
209 | 214 |
|
| 215 | +def _get_codeartifact_index(): |
| 216 | + """ |
| 217 | + Build the authenticated codeartifact index url |
| 218 | + https://docs.aws.amazon.com/codeartifact/latest/ug/python-configure-pip.html |
| 219 | + https://docs.aws.amazon.com/service-authorization/latest/reference/list_awscodeartifact.html#awscodeartifact-resources-for-iam-policies |
| 220 | + :return: authenticated codeartifact index url |
| 221 | + """ |
| 222 | + repository_arn = os.getenv("CA_REPOSITORY_ARN") |
| 223 | + arn_regex = ( |
| 224 | + "arn:(?P<partition>[^:]+):codeartifact:(?P<region>[^:]+):(?P<account>[^:]+)" |
| 225 | + ":repository/(?P<domain>[^/]+)/(?P<repository>.+)" |
| 226 | + ) |
| 227 | + m = re.match(arn_regex, repository_arn) |
| 228 | + if not m: |
| 229 | + raise Exception("invalid CodeArtifact repository arn {}".format(repository_arn)) |
| 230 | + domain = m.group("domain") |
| 231 | + owner = m.group("account") |
| 232 | + repository = m.group("repository") |
| 233 | + region = m.group("region") |
| 234 | + |
| 235 | + logger.info( |
| 236 | + "configuring pip to use codeartifact " |
| 237 | + "(domain: %s, domain owner: %s, repository: %s, region: %s)", |
| 238 | + domain, |
| 239 | + owner, |
| 240 | + repository, |
| 241 | + region, |
| 242 | + ) |
| 243 | + try: |
| 244 | + client = boto3.client("codeartifact", region_name=region) |
| 245 | + auth_token_response = client.get_authorization_token(domain=domain, domainOwner=owner) |
| 246 | + token = auth_token_response["authorizationToken"] |
| 247 | + endpoint_response = client.get_repository_endpoint( |
| 248 | + domain=domain, domainOwner=owner, repository=repository, format="pypi" |
| 249 | + ) |
| 250 | + unauthenticated_index = endpoint_response["repositoryEndpoint"] |
| 251 | + return re.sub( |
| 252 | + "https://", |
| 253 | + "https://aws:{}@".format(token), |
| 254 | + re.sub( |
| 255 | + "{}/?$".format(repository), |
| 256 | + "{}/simple/".format(repository), |
| 257 | + unauthenticated_index, |
| 258 | + ), |
| 259 | + ) |
| 260 | + except Exception: |
| 261 | + logger.error("failed to configure pip to use codeartifact") |
| 262 | + raise Exception("failed to configure pip to use codeartifact") |
| 263 | + |
| 264 | + |
210 | 265 | def _retry_retrieve_mms_server_process(startup_timeout): |
211 | 266 | retrieve_mms_server_process = retry(wait_fixed=1000, stop_max_delay=startup_timeout * 1000)( |
212 | 267 | _retrieve_mms_server_process |
|
0 commit comments