mirror of
https://github.com/projectatomic/atomic.git
synced 2026-02-05 18:45:01 +01:00
syscontainers: environment variable detection
Add functionality to detect environment variables in template files.
The variables that can be set by the user through --set is displayed
on 'atomic images info'. The variables with overridable default
values will either have their default value displayed, or shown as
{SET_BY_OS} if atomic sets them. Variables without default value
must be set by the user and is listed separately.
Currently install --system already checks for variables that have no
value after install, and will error out.
Signed-off-by: Yu Qi Zhang <jerzhang@redhat.com>
Closes: #752
Approved by: giuseppe
This commit is contained in:
@@ -120,6 +120,16 @@ class Info(Atomic):
|
||||
labels = manifest["Labels"]
|
||||
for label in labels:
|
||||
buf += ('\n{0}: {1}'.format(label, labels[label]))
|
||||
|
||||
template_variables, template_variables_to_set = self.syscontainers.get_template_variables(self.image)
|
||||
buf += ("\n\nEnvironment variables with default value, but overridable with --set:")
|
||||
for variable in template_variables.keys():
|
||||
buf += ('\n{}: {}'.format(variable, template_variables.get(variable)))
|
||||
|
||||
if template_variables_to_set:
|
||||
buf += ("\n\nEnvironment variables that has no default value, and must be set with --set:")
|
||||
for variable in template_variables_to_set.keys():
|
||||
buf += ('\n{}: {}'.format(variable, template_variables_to_set.get(variable)))
|
||||
return buf
|
||||
# Check if the input is an image id associated with more than one
|
||||
# repotag. If so, error out.
|
||||
@@ -141,6 +151,16 @@ class Info(Atomic):
|
||||
labels = manifest["Labels"]
|
||||
for label in labels:
|
||||
buf += ('\n{0}: {1}'.format(label, labels[label]))
|
||||
|
||||
template_variables, template_variables_to_set = self.syscontainers.get_template_variables(self.image)
|
||||
buf += ("\n\nEnvironment variables with default value, but overridable with --set:")
|
||||
for variable in template_variables.keys():
|
||||
buf += ('\n{}: {}'.format(variable, template_variables.get(variable)))
|
||||
|
||||
if template_variables_to_set:
|
||||
buf += ("\n\nEnvironment variables that has no default value, and must be set with --set:")
|
||||
for variable in template_variables_to_set.keys():
|
||||
buf += ('\n{}: {}'.format(variable, template_variables_to_set.get(variable)))
|
||||
return buf
|
||||
else:
|
||||
self._no_such_image()
|
||||
|
||||
@@ -52,6 +52,9 @@ WorkingDirectory=$DESTDIR
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
"""
|
||||
TEMPLATE_FORCED_VARIABLES = ["DESTDIR", "NAME", "EXEC_START", "EXEC_STOP",
|
||||
"HOST_UID", "HOST_GID"]
|
||||
TEMPLATE_OVERRIDABLE_VARIABLES = ["RUN_DIRECTORY", "STATE_DIRECTORY"]
|
||||
|
||||
class SystemContainers(object):
|
||||
|
||||
@@ -624,6 +627,66 @@ class SystemContainers(object):
|
||||
ret.append(container)
|
||||
return ret
|
||||
|
||||
def get_template_variables(self, image):
|
||||
repo = self._get_ostree_repo()
|
||||
_, commit_rev = self._resolve_image(repo, image)
|
||||
if not commit_rev:
|
||||
return
|
||||
|
||||
manifest = self._image_manifest(repo, commit_rev)
|
||||
layers = SystemContainers.get_layers_from_manifest(json.loads(manifest))
|
||||
templates = {}
|
||||
manifest_template = None
|
||||
for i in layers:
|
||||
layer = i.replace("sha256:", "")
|
||||
commit = repo.read_commit(repo.resolve_rev("%s%s" % (OSTREE_OCIIMAGE_PREFIX, layer), True)[1])[1]
|
||||
exports = commit.get_root().get_child("exports")
|
||||
if not exports.query_exists():
|
||||
continue
|
||||
|
||||
children = exports.enumerate_children("", Gio.FileQueryInfoFlags.NONE, None)
|
||||
for child in reversed(list(children)):
|
||||
name = child.get_name()
|
||||
if name == "manifest.json":
|
||||
manifest_template = exports.get_child(name).read()
|
||||
|
||||
if name.endswith(".template"):
|
||||
if name.startswith(".wh"):
|
||||
name = name[4:]
|
||||
templates.pop(name, None)
|
||||
else:
|
||||
templates[name] = exports.get_child(name).read()
|
||||
|
||||
variables = {}
|
||||
for v in templates.values():
|
||||
fd = v.get_fd()
|
||||
with os.fdopen(fd) as f:
|
||||
data = f.read()
|
||||
template = Template(data)
|
||||
for variable in ["".join(x) for x in template.pattern.findall(data)]: # pylint: disable=no-member
|
||||
if variable not in TEMPLATE_FORCED_VARIABLES:
|
||||
variables[variable] = variable
|
||||
|
||||
variables_with_default = {}
|
||||
if manifest_template:
|
||||
fd = manifest_template.get_fd()
|
||||
with os.fdopen(fd) as f:
|
||||
data = json.loads(f.read())
|
||||
for variable in data['defaultValues']:
|
||||
variables_with_default[variable] = data['defaultValues'][variable]
|
||||
|
||||
# Also include variables that are set by the OS
|
||||
# but can be overriden by --set
|
||||
for variable in TEMPLATE_OVERRIDABLE_VARIABLES:
|
||||
variables_with_default[variable] = "{SET_BY_OS}"
|
||||
|
||||
variables_to_set = {}
|
||||
for variable in variables:
|
||||
if variable not in variables_with_default:
|
||||
variables_to_set[variable] = "{DEF_VALUE}"
|
||||
|
||||
return variables_with_default, variables_to_set
|
||||
|
||||
def delete_image(self, image):
|
||||
repo = self._get_ostree_repo()
|
||||
if not repo:
|
||||
|
||||
@@ -26,6 +26,8 @@ atomic images allows the user to view and operate on container images in a docke
|
||||
|
||||
Displays the LABEL fields within an image. By default, it will check first for a local image and then all configured registries.
|
||||
|
||||
For a system container image, this will also display the environment variables a user can set.
|
||||
|
||||
**help**
|
||||
|
||||
Displays a help file associated with a container or image.
|
||||
|
||||
Reference in New Issue
Block a user