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
|
diff --git a/dockerfile_parse/parser.py b/dockerfile_parse/parser.py
index 615d7a8..25b6536 100644
--- a/dockerfile_parse/parser.py
+++ b/dockerfile_parse/parser.py
@@ -66,11 +66,12 @@ class Envs(dict):
class DockerfileParser(object):
- def __init__(self, path=None, cache_content=False, env_replace=True):
+ def __init__(self, path=None, cache_content=False, env_replace=True, parent_env=None):
"""
Initialize path to Dockerfile
:param path: path to (directory with) Dockerfile
:param cache_content: cache Dockerfile content inside DockerfileParser
+ :param parent_env: python dict of inherited env vars from parent image
"""
path = path or '.'
if path.endswith(DOCKERFILE_FILENAME):
@@ -91,6 +92,14 @@ class DockerfileParser(object):
self.env_replace = env_replace
+ if isinstance(parent_env, dict):
+ logger.debug("Setting inherited parent image ENV vars: %s", parent_env)
+ self.parent_env = parent_env
+ elif parent_env != None:
+ assert isinstance(parent_env, dict)
+ else:
+ self.parent_env = {}
+
@property
def lines(self):
"""
@@ -106,7 +115,7 @@ class DockerfileParser(object):
self.cached_content = ''.join(lines)
return lines
except (IOError, OSError) as ex:
- logger.error("Couldn't retrieve lines from dockerfile: %s" % repr(ex))
+ logger.error("Couldn't retrieve lines from dockerfile: %r", ex)
raise
@lines.setter
@@ -122,7 +131,7 @@ class DockerfileParser(object):
with open(self.dockerfile_path, 'w') as dockerfile:
dockerfile.writelines([u2b(l) for l in lines])
except (IOError, OSError) as ex:
- logger.error("Couldn't write lines to dockerfile: %s" % repr(ex))
+ logger.error("Couldn't write lines to dockerfile: %r", ex)
raise
@property
@@ -140,7 +149,7 @@ class DockerfileParser(object):
self.cached_content = content
return content
except (IOError, OSError) as ex:
- logger.error("Couldn't retrieve content of dockerfile: %s" % repr(ex))
+ logger.error("Couldn't retrieve content of dockerfile: %r", ex)
raise
@content.setter
@@ -156,7 +165,7 @@ class DockerfileParser(object):
with open(self.dockerfile_path, 'w') as dockerfile:
dockerfile.write(u2b(content))
except (IOError, OSError) as ex:
- logger.error("Couldn't write content to dockerfile: %s" % repr(ex))
+ logger.error("Couldn't write content to dockerfile: %r", ex)
raise
@property
@@ -290,7 +299,7 @@ class DockerfileParser(object):
if name != 'LABEL' and name != 'ENV':
raise ValueError("Unsupported instruction '%s'", name)
instructions = {}
- envs = {}
+ envs = self.parent_env.copy()
for insndesc in self.structure:
this_insn = insndesc['instruction']
if this_insn in (name, 'ENV'):
@@ -354,7 +363,7 @@ class DockerfileParser(object):
elif name == 'ENV':
existing = self.envs
- logger.debug("setting %s instructions: %r" % (name, instructions))
+ logger.debug("setting %s instructions: %r", name, instructions)
to_delete = [k for k in existing if k not in instructions]
for key in to_delete:
diff --git a/tests/test_parser.py b/tests/test_parser.py
index 8f63a04..e47fefe 100644
--- a/tests/test_parser.py
+++ b/tests/test_parser.py
@@ -86,6 +86,35 @@ USER {0}""".format(NON_ASCII)
base_img = dfparser.baseimage
assert base_img.startswith('fedora')
+ def test_get_parent_env(self, tmpdir):
+ tmpdir_path = str(tmpdir.realpath())
+ p_env = {"bar": "baz"}
+ df1 = DockerfileParser(tmpdir_path, env_replace=True, parent_env=p_env)
+ df1.lines = [
+ "FROM parent\n",
+ "ENV foo=\"$bar\"\n",
+ "LABEL label=\"$foo $bar\"\n"
+ ]
+
+ # Even though we inherit an ENV, this .envs count should only be for the
+ # ENVs defined in *this* Dockerfile as we're parsing the Dockerfile and
+ # the parent_env is only to satisfy use of inhereted ENVs.
+ assert len(df1.envs) == 1
+ assert df1.envs.get('foo') == 'baz'
+ assert len(df1.labels) == 1
+ assert df1.labels.get('label') == 'baz baz'
+
+ def test_get_parent_env_from_scratch(self, tmpdir):
+ tmpdir_path = str(tmpdir.realpath())
+ p_env = {"bar": "baz"}
+ df1 = DockerfileParser(tmpdir_path, env_replace=True, parent_env=p_env)
+ df1.lines = [
+ "FROM scratch\n",
+ ]
+
+ assert not df1.envs
+
+
def test_get_instructions_from_df(self, dfparser, instruction):
dfparser.content = ""
lines = []
|