-
Notifications
You must be signed in to change notification settings - Fork 4
/
dependencies.py
133 lines (115 loc) · 3.61 KB
/
dependencies.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
import glob
import tarfile
import os.path
import yaml
import sys
def scandeps(chartsdir, verbose=False):
cor = {}
incor = {}
ver = {}
nover = []
doubles = []
res = {}
charts = glob.glob("{}/*.tgz".format(chartsdir))
for chart in sorted(charts):
if verbose:
print(chart)
tar = tarfile.open(chart)
for entry in tar:
entryname = entry.name
chartname = entryname.split("/")[0]
if entryname.endswith("Chart.yaml"):
if verbose:
print(entryname)
if entryname.count("/") == 3:
# correct dependency (e.g. cert-manager/charts/webhook/Chart.yaml)
depname = entryname.split("/")[2]
cor[chartname] = cor.get(chartname, []) + [depname]
f = tar.extractfile(entry)
y = yaml.load(f)
if "appVersion" in y:
ver[depname] = ver.get(depname, []) + [chartname + ":" + str(y["appVersion"])]
else:
nover.append(chartname)
elif entryname.count("/") == 2:
# incorrect dependency (e.g. cert-manager/webhook/Chart.yaml)
incor[chartname] = incor.get(chartname, 0) + 1
elif entryname.count("/") == 1:
# main chart file
f = tar.extractfile(entry)
y = yaml.load(f)
if "appVersion" in y:
ver[chartname] = ver.get(chartname, []) + ["chart:" + str(y["appVersion"])]
else:
pass
# TODO register into stats
else:
if entryname.count("charts") > 1:
if verbose:
print("double-dependency!", entryname)
doubles.append(entryname)
if verbose:
print("--")
cor_ratio = 100 * len(cor) / len(charts)
incor_ratio = 100 * len(incor) / len(charts)
nover_ratio = 100 * len(nover) / len(cor)
depsdist = {}
for chart in cor:
depsdist[len(cor[chart])] = depsdist.get(len(cor[chart]), 0) + 1
res["cor_ratio"] = cor_ratio
res["incor_ratio"] = incor_ratio
res["cor"] = cor
res["incor"] = incor
res["depsdist"] = depsdist
res["nover"] = nover
res["nover_ratio"] = nover_ratio
res["ver"] = ver
total = 0
found = []
for verentry in sorted(ver):
if len(ver[verentry]) > 1:
found.append((verentry, ver[verentry]))
total += len(ver[verentry])
count = 0
notfound = []
for verentry in sorted(ver):
if len(ver[verentry]) > 1:
for v1 in ver[verentry]:
if not v1.startswith("chart:"):
chartname, v2 = v1.split(":")
if not "chart:" + v2 in ver[verentry]:
notfound.append((chartname, verentry, v2))
count += 1
res["found"] = found
res["notfound"] = notfound
res["totalnotfound"] = 100 * count / total
depcount = {}
for chartname in cor:
for dep in cor[chartname]:
depcount[dep] = depcount.get(dep, 0) + 1
topdeps = sorted(((v, k) for k, v in depcount.items()), reverse=True)
res["topdeps"] = topdeps
res["doubles"] = doubles
return res
def output(res):
print("Correct deps among all charts: {:.1f}%".format(res["cor_ratio"]), res["cor"])
print("Incorrect deps among all charts: {:.1f}%".format(res["incor_ratio"]), res["incor"])
print("#deps distribution:", res["depsdist"])
print("Incorrect dep versions among all charts with deps: {:.1f}%".format(res["nover_ratio"]), res["nover"])
print("dep versions:", res["ver"])
for verentry, ver in res["found"]:
print("{:30s}: {}".format(verentry, ver))
for chartname, verentry, v2 in res["notfound"]:
print("* notfound", chartname, "=>", verentry, v2)
print("Total notfound: {:.1f}%".format(res["totalnotfound"]))
print("Most popular dependencies:")
print(res["topdeps"])
print("Double dependencies:", len(res["doubles"]))
print(res["doubles"])
if __name__ == "__main__":
if len(sys.argv) == 2:
chartsdir = sys.argv[1]
res = scandeps(chartsdir)
output(res)
else:
print("Syntax: {} <chartsdir>".format(sys.argv[0]), file=sys.stderr)