-
Notifications
You must be signed in to change notification settings - Fork 57
/
fix_tfvars_symlinks.py
197 lines (167 loc) · 8.39 KB
/
fix_tfvars_symlinks.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
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
import os
import re
import sys
import shutil
# Problem : when git cloning from github symlinks become text in files
# e.g. 3-networks-hub-and-spoke\envs\development\common.auto.tfvars : ../../common.auto.tfvars
# not only .auto.tfvars but also .tfvars
# to find them use regex r'^[\./]+[^\W\./]+\.auto\.tfvars' or better r'^[\./]+[^\n]+\.tfvars'
# this should have been a symlink. If on Windows symlinks not available
# if the referenced file does not exist most likely because we have examples something like
# access_context.auto.example.tfvars, common.auto.example.tfvars, etc
# however if git-cloned on Linux the symlinks remain symlinks and the script will only fix the broken ones
# the fix consists in creating thje missing file referenced by the symlink with a text ### fill-me-in with tfvars definitions
# list of extensions to replace
# DEFAULT_REPLACE_EXTENSIONS = None
# example: uncomment next line to only replace *.c, *.h, and/or *.txt
# DEFAULT_REPLACE_EXTENSIONS = (".c", ".h", ".txt")
DEFAULT_TFVAR_EXTENSIONS = (".tfvars")
regex_find_symlink = r'^[\./]+([^\n/]+)\.tfvars'
regex_find_mod_tfvars = r'^([^\n\./]+(\.auto|))\.mod(\.tfvars)'
re_repl_mod_tfvars = r'\1\3'
regex_find_tfvars = r'^([^\n\./]+(\.auto|))\.tfvars'
fixed_fake_symlinked_count = 0
fixed_tfvars_symlinked_count = 0
fix_symlink_error_count = 0
# pat_replace = list( ([re.compile(one_re_find_repl[0]),one_re_find_repl[1]] for one_re_find_repl in regex_find_replace))
pat_find_symlink = re.compile(regex_find_symlink)
pat_find_mod_tfvars = re.compile(regex_find_mod_tfvars)
pat_find_tfvars = re.compile(regex_find_tfvars)
def check_file_type(fname, tfvar_extensions=DEFAULT_TFVAR_EXTENSIONS):
if tfvar_extensions:
return fname.lower().endswith(tfvar_extensions)
return False
## do not overwrite destination if exists
def create_symlink_or_hardcopy(src_file_path, dst_file_path):
if os.path.exists(dst_file_path):
return (dst_file_path,"exists")
try:
os.symlink(src_file_path, dst_file_path)
return (dst_file_path,"symlink")
except:
print("Could not symlink {} to {}".format(src_file_path,dst_file_path))
try:
shutil.copy2(src_file_path,dst_file_path)
return (dst_file_path,"hardlink")
except:
print("Could not copy {} to {}".format(src_file_path,dst_file_path))
return None
# if a <fname>.mod.tfvars file exists but not a <fname>.tfvars file, a symlink or hardcopy is created
# first a symlink creation attempted, if it fails a hardcopy is created
def create_mod_tfvars_symlink_or_hardcopy(fname, dirpath):
tfvars_full_path = None
tfvars_mod_full_path = None
if re.search(pat_find_mod_tfvars,fname):
tfvars_fname = re.sub(pat_find_mod_tfvars,re_repl_mod_tfvars,fname)
tfvars_full_path = os.path.join(dirpath,tfvars_fname)
tfvars_mod_full_path = os.path.join(dirpath,fname)
if (tfvars_full_path is None):
return None
result = create_symlink_or_hardcopy(tfvars_mod_full_path,tfvars_full_path)
return result
## looks for <name>.mod.tfvars files and checks if a symlink exists to them in same folder
## if no symlink, will either create one or (Windows non-admin) will simply copy the file
##
def fix_mod_tfvars_symlinks(src_fname, dirpath):
global fixed_tfvars_symlinked_count
global fix_symlink_error_count
# normalize just in case if src_fname is a path
fname = os.path.basename(src_fname)
fname_abs_path = os.path.join(dirpath,fname)
# first create symlink to a .mod.tfvars in same folder
if re.match(pat_find_mod_tfvars,fname):
result = create_mod_tfvars_symlink_or_hardcopy(fname,dirpath)
if result is None:
print("error symlinking {} in {}".format(fname,dirpath))
fix_symlink_error_count += 1
elif re.match(r'exists',result[1]):
## for some reason called twice on same file
print("error symlinking {} in {}, destination {} already exists".format(fname,dirpath,result[0]))
## silently ignore if dest file already exists
return
elif re.match(r'symlink',result[1]):
print("symlinked {} in {} to {}".format(fname,dirpath,result[0]))
fixed_tfvars_symlinked_count += 1
elif re.match(r'hardlink',result[1]):
print("copied {} in {} to {}".format(fname,dirpath,result[0]))
fixed_tfvars_symlinked_count += 1
def fix_tfvars_symlinks(src_fname, dirpath):
global fixed_fake_symlinked_count
global fix_symlink_error_count
global pat_find_symlink
# normalize just in case if src_fname is a path
fname = os.path.basename(src_fname)
fname_abs_path = os.path.join(dirpath,fname)
if re.match(pat_find_tfvars,fname):
if not os.path.islink(fname_abs_path):
tfvars_path_above = None
symlink_path = None
lines = None
try:
with open(fname_abs_path,'r') as f:
lines = f.readlines()
f.close()
except:
print("can't open file {}".format(fname_abs_path))
fix_symlink_error_count += 1
return
if len(lines) == 1 and re.match(pat_find_symlink, lines[0]):
symlink_path = lines[0]
tfvars_path_above = os.path.join(dirpath,symlink_path)
else:
return
# exit if error
if tfvars_path_above is None or not os.path.exists(tfvars_path_above):
print("missing source tfvars file" + "" if tfvars_path_above is None else tfvars_path_above)
fix_symlink_error_count += 1
return
# rename source file and try to create symlink, otherwise hard copy
print("renaming " + fname_abs_path + "\n to " + fname_abs_path + ".delete_me")
os.rename(fname_abs_path, fname_abs_path +'.delete_me')
if create_symlink_or_hardcopy(tfvars_path_above,fname_abs_path) is not None:
print("symlinked " + tfvars_path_above + "\n to " + fname_abs_path)
fixed_fake_symlinked_count += 1
else:
fix_symlink_error_count += 1
print("error symlinking " + tfvars_path_above + "\n to " + fname_abs_path)
else:
try:
tfvars_path_above = os.readlink(fname_abs_path)
if not os.path.isabs(tfvars_path_above):
tfvars_path_above = os.path.join(dirpath,tfvars_path_above)
if tfvars_path_above is not None and os.path.exists(tfvars_path_above):
return
print("Broken symlink {} to {}".format(fname_abs_path,tfvars_path_above) if tfvars_path_above is not None else "" )
print("Broken symlink in {}".format(fname_abs_path) if tfvars_path_above is None else "")
except:
print("can't get symlink from file {}".format( fname_abs_path))
fix_symlink_error_count += 1
def get_relative_dir_string(root_dir, current_dir):
abs_root_dir = os.path.abspath(root_dir)
abs_current_dir = os.path.abspath(current_dir)
rel_path = os.path.relpath(abs_current_dir, start=abs_root_dir).replace(os.sep,'/')
return rel_path
def mass_fix_mod_tfvars(root_dir, crt_dir, replace_extensions=DEFAULT_TFVAR_EXTENSIONS):
for dirpath, dirnames, filenames in os.walk(os.path.abspath(crt_dir)):
for fname in filenames:
if check_file_type(fname, replace_extensions):
fullname = os.path.join(dirpath, fname)
fix_mod_tfvars_symlinks(fullname, dirpath)
def mass_fix_symlinks(root_dir, crt_dir, replace_extensions=DEFAULT_TFVAR_EXTENSIONS):
## print("crt_dir="+crt_dir+"\n")
for dirpath, dirnames, filenames in os.walk(os.path.abspath(crt_dir)):
for fname in filenames:
if check_file_type(fname, replace_extensions):
fullname = os.path.join(dirpath, fname)
fix_tfvars_symlinks(fullname, dirpath)
def main(root_dir):
mass_fix_mod_tfvars(root_dir,root_dir)
mass_fix_symlinks(root_dir,root_dir)
if __name__ == "__main__":
if len(sys.argv) != 2:
print("Usage: fix_fake_symlinks.py <root_dir>\n")
sys.exit()
main(sys.argv[1])
print("fixed " + str(fixed_fake_symlinked_count) + " fake symlinks and " + str(fixed_tfvars_symlinked_count) + " fixed_tfvars_symlinked_count " + str(fix_symlink_error_count) + " errors" )
## sys.exit(1)
##mass_replace(sys.argv[1])