-
Notifications
You must be signed in to change notification settings - Fork 2
/
parser.py
137 lines (110 loc) · 3.33 KB
/
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
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
################### Parser Dockerfile #####################
import json
import crawler
import filter
import collections, logging, itertools
import bashlex.parser
import bashlex.ast
from json import dumps
from dockerfile_parser import parser
# major function
# paras "dockerfile": return from crawler.resolve_images_info(image)
def dockerfile2bash(dockerfile):
cmds = []
commands = dockerfile2cmds(dockerfile)
if len(commands) == 0:
return cmds
for command in commands["RUN"]:
# get beshlex AST
try:
parts = bashlex.parse(command)
except:
return cmds
for ast in parts:
cmd = []
try:
for i in range(len(ast.parts)):
word = ast.parts[i].word
cmd.append(word)
cmds.append(cmd)
except:
continue
return cmds
def dockerfile2cmds(dockerfile):
commands = {}
if dockerfile == None or dockerfile == "":
print ("[ERR] dockerfile format error...")
return commands
# resolve the dockerfile
try:
dockerfile = parse_dockerfile(dockerfile)
except:
print ("[ERR] Dockerfile parsing failed...")
return commands
commands["RUN"] = parse_cmds_from_dockerfile(dockerfile)
commands["CMD"] = parse_exe_from_dockerfile(dockerfile)
commands["ADD"] = parse_add_from_dockerfile(dockerfile)
return commands
def parse_dockerfile(path):
parsed = parser.parse(path)
dockerfile = dumps(parsed, indent=2, separators=(',', ': '))
dockerfile = json.loads(dockerfile)
return dockerfile
# parsing "CMD" and "ENTRYPOINT"
def parse_exe_from_dockerfile(dockerfile):
entrypoints = []
try:
entrypoint = dockerfile['workdir']['/']['root']['entrypoint']
except:
entrypoint = []
try:
cmd = dockerfile['workdir']['/']['root']['cmd']
except:
cmd = []
# list to str
for entry in entrypoint:
if type(entry) is list:
for e in entry:
entrypoints.append(e)
else:
entrypoints.append(entry)
for entry in cmd:
if type(entry) is list:
for e in entry:
entrypoints.append(e)
else:
entrypoints.append(entry)
return entrypoints
def split_bash_cmds(commands):
# store the function in bash
commands = commands.replace("&&", ";")
command = commands.split(";")
return command
# parsing "RUN" commnads
def parse_cmds_from_dockerfile(dockerfile):
commands = []
try:
for item in dockerfile['workdir']['/']['root']['run']:
if filter.exsit(item, None, "or"):
continue
command = split_bash_cmds(item)
commands = commands + command
except:
return commands
return commands
# parsing "ADD" and "COPY" commnads
def parse_add_from_dockerfile(dockerfile):
copy = []
try:
for item in dockerfile['workdir']['/']['root']['copy']:
command = "COPY " + item['src'] + " " + item['dest']
copy.append(command)
except:
pass
try:
for item in dockerfile['workdir']['/']['root']['add']:
command = "ADD " + item['src'] + " " + item['dest']
copy.append(command)
except:
pass
return copy