-
-
Notifications
You must be signed in to change notification settings - Fork 163
/
Copy pathfallback_parser.py
98 lines (70 loc) · 2.87 KB
/
fallback_parser.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
"""
Fallback parsing for hcl files
We only need limited information from Terraform Modules:
- The required_version constraint
- The backend type
- A list of sensitive variable names
- The backend configuration for remote backends and cloud blocks
The easiest way to get this information is to parse the HCL files directly.
This doesn't always work if our parser fails, or the files are malformed.
This fallback 'parser' does the stupidest thing that might work to get the information we need.
TODO: The backend configuration is not yet implemented.
"""
import re
from pathlib import Path
from typing import Optional
from github_actions.debug import debug
def get_required_version(body: str) -> Optional[str]:
"""Get the required_version constraint string from a tf file"""
if version := re.search(r'required_version\s*=\s*"(.+)"', body):
return version.group(1)
def get_backend_type(body: str) -> Optional[str]:
"""Get the backend type from a tf file"""
if backend := re.search(r'backend\s*"(.+)"', body):
return backend.group(1)
if backend := re.search(r'backend\s+(.*)\s*{', body):
return backend.group(1).strip()
if re.search(r'cloud\s+\{', body):
return 'cloud'
def get_sensitive_variables(body: str) -> list[str]:
"""Get the sensitive variable names from a tf file"""
variables = []
found = False
for line in reversed(body.splitlines()):
if re.search(r'sensitive\s*=\s*true', line, re.IGNORECASE) or re.search(r'sensitive\s*=\s*"true"', line, re.IGNORECASE):
found = True
continue
if found and (variable := re.search(r'variable\s*"(.+)"', line)):
variables.append(variable.group(1))
found = False
if found and (variable := re.search(r'variable\s+(.+)\{', line)):
variables.append(variable.group(1))
found = False
return variables
def parse(path: Path) -> dict:
debug(f'Attempting to parse {path} with fallback parser')
body = path.read_text()
module = {}
if constraint := get_required_version(body):
module['terraform'] = [{
'required_version': constraint
}]
if backend_type := get_backend_type(body):
if 'terraform' not in module:
module['terraform'] = []
if backend_type == 'cloud':
module['terraform'].append({'cloud': [{}]})
else:
module['terraform'].append({'backend': [{backend_type:{}}]})
if sensitive_variables := get_sensitive_variables(body):
module['variable'] = []
for variable in sensitive_variables:
module['variable'].append({
variable: {
'sensitive': True
}
})
return module
if __name__ == '__main__':
from pprint import pprint
pprint(parse(Path('tests/workflows/test-validate/hard-parse/main.tf')))