|
1 |
| -import errno |
2 | 1 | import os
|
| 2 | +import re |
| 3 | +import requests |
3 | 4 | import shutil
|
4 | 5 | import subprocess
|
5 | 6 | import sys
|
6 | 7 | import yaml
|
7 |
| -import requests |
8 |
| -import re |
9 | 8 |
|
10 | 9 |
|
11 |
| -REGISTRY_BASE_URL = 'https://registry.terraform.io/v1/modules/' |
| 10 | +REGISTRY_BASE_URL = 'https://registry.terraform.io/v1/modules' |
| 11 | +GITHUB_DOWNLOAD_URL_RE = re.compile('https://[^/]+/repos/([^/]+)/([^/]+)/tarball/([^/]+)/.*') |
| 12 | + |
| 13 | + |
| 14 | +def get_source_from_registry(source, version): |
| 15 | + namespace, name, provider = source.split('/') |
| 16 | + registry_download_url = '{base_url}/{namespace}/{name}/{provider}/{version}/download'.format( |
| 17 | + base_url=REGISTRY_BASE_URL, |
| 18 | + namespace=namespace, |
| 19 | + name=name, |
| 20 | + provider=provider, |
| 21 | + version=version, |
| 22 | + ) |
| 23 | + response = requests.get(registry_download_url) |
| 24 | + if response.status_code == 204: |
| 25 | + github_download_url = response.headers.get('X-Terraform-Get') or '' |
| 26 | + match = GITHUB_DOWNLOAD_URL_RE.match(github_download_url) |
| 27 | + if match: |
| 28 | + user, repo, version = match.groups() |
| 29 | + source = 'https://github.com/{}/{}.git'.format(user, repo) |
| 30 | + return source, version |
| 31 | + sys.stderr.write('Error looking up module in Terraform Registry: {}\n'.format(response.content)) |
| 32 | + sys.exit(1) |
12 | 33 |
|
13 |
| -def get_source_from_registry(module_name): |
14 |
| - response = requests.get('{}{}'.format(REGISTRY_BASE_URL, module_name)) |
15 |
| - data = response.json() |
16 |
| - if 'errors' not in data.keys(): |
17 |
| - return data['source'] |
18 |
| - else: |
19 |
| - sys.stderr.write('Error looking up module in Terraform Registry: {}\n'.format(data['errors'])) |
20 |
| - sys.exit(1) |
21 | 34 |
|
22 | 35 | def run(*args, **kwargs):
|
23 | 36 | proc = subprocess.Popen(args, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, **kwargs)
|
@@ -76,27 +89,31 @@ def update_modules(path):
|
76 | 89 |
|
77 | 90 | for name, repository_details in sorted(terrafile.items()):
|
78 | 91 | target = os.path.join(module_path, name)
|
79 |
| - raw_source = repository_details['source'] |
80 |
| - if is_valid_registry_source(raw_source): |
81 |
| - source = get_source_from_registry(raw_source) |
82 |
| - elif os.path.isdir(raw_source): |
83 |
| - source = os.path.abspath(raw_source) |
| 92 | + source = repository_details['source'] |
| 93 | + |
| 94 | + # Support modules on the local filesystem. |
| 95 | + if source.startswith('./') or source.startswith('../') or source.startswith('/'): |
| 96 | + print('Copying {}/{}'.format(module_path_name, name)) |
| 97 | + # Paths must be relative to the Terrafile directory. |
| 98 | + source = os.path.join(module_path, source) |
84 | 99 | shutil.rmtree(target, ignore_errors=True)
|
85 |
| - print('Fetching {}/{}'.format(module_path_name, name)) |
86 | 100 | shutil.copytree(source, target)
|
87 | 101 | continue
|
88 |
| - else: |
89 |
| - source = raw_source |
| 102 | + |
90 | 103 | version = repository_details['version']
|
91 | 104 |
|
| 105 | + # Support Terraform Registry sources. |
| 106 | + if is_valid_registry_source(source): |
| 107 | + print('Checking {}/{}'.format(module_path_name, name)) |
| 108 | + source, version = get_source_from_registry(source, version) |
| 109 | + |
92 | 110 | # Skip this module if it has already been checked out.
|
93 | 111 | if has_git_tag(path=target, tag=version):
|
94 | 112 | print('Fetched {}/{}'.format(module_path_name, name))
|
95 | 113 | continue
|
96 | 114 |
|
97 |
| - print('Fetching {}/{}'.format(module_path_name, name)) |
98 |
| - |
99 | 115 | # Delete the old directory and clone it from scratch.
|
| 116 | + print('Fetching {}/{}'.format(module_path_name, name)) |
100 | 117 | shutil.rmtree(target, ignore_errors=True)
|
101 | 118 | output, returncode = run('git', 'clone', '--branch={}'.format(version), source, target)
|
102 | 119 | if returncode != 0:
|
|
0 commit comments