Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add validation for paths in config #166

Merged
merged 2 commits into from
Nov 26, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,10 @@ with key suffixes as follows:
* `_required`: `true` means that the key must be set
* `_values`: the value, if set, must be within the space-separated list
of values here
* `_type`: `path` means the value, if set, must be the path to a file which
exists
* `_type`: `paths` means the value, if set, must be a space-separated list of
path to files which exist

Merged options
--------------
Expand Down
10 changes: 10 additions & 0 deletions config/schema.ini
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,20 @@
# _required = true means that the key must be set
# _values means the value, if set, must be within the space-separated list of
# values here
# _type = path means the value, if set, must be the path to a file which exists
# _type = paths means the value, if set, must be a space-separated list of
# path to files which exist

[image]
compression_required = true
compression_values = gz
xz
partition_table_values = gpt
dos
branding_fbe_config_type = path
icon_grid_type = paths
initramfs_plymouth_watermark = path
chromium_policies_managed = path
chromium_policies_recommended = path
settings = paths
settings_locks = paths
20 changes: 20 additions & 0 deletions run-build
Original file line number Diff line number Diff line change
Expand Up @@ -515,6 +515,26 @@ class ImageBuilder(object):
raise eib.ImageBuildError(
'Configuration key [%s] %s has invalid value: %s'
% (section, option, self.config[section][option]))
elif option.endswith('_type'):
real_option = option[:-len('_type')]
if real_option in self.config[section]:
real_value = self.config[section][real_option].strip()
if value == "path":
paths = [real_value] if real_value else []
elif value == "paths":
paths = real_value.split()
else:
raise eib.ImageBuildError(
f'Schema key [{section}] {option} has invalid value: '
f'{value}'
)

for path in paths:
if not os.path.exists(path):
raise eib.ImageBuildError(
f'Configuration key [{section}] {real_option} refers to '
f'nonexistent path: {path}'
)

def check_config(self):
"""Check loaded configuration against schema for validity."""
Expand Down
49 changes: 49 additions & 0 deletions tests/test_image_builder.py
Original file line number Diff line number Diff line change
Expand Up @@ -327,3 +327,52 @@ def test_localdir(make_builder, tmp_path, tmp_builder_paths, caplog):
assert (builder.config['image']['branding_desktop_logo'] ==
str(localdir / 'data' / 'desktop.png'))
assert builder.config['image']['signing_key'] == 'foobar'


def test_path_validation(make_builder, tmp_path):
configdir = tmp_path / 'config'
configdir.mkdir()

# Schema
schema = configdir / 'schema.ini'
schema.write_text(dedent("""\
[image]
singular_type = path
plural_type = paths
"""))

# Some config
defaults = configdir / 'defaults.ini'
defaults.write_text(dedent("""\
[image]
singular = ${build:localdatadir}/a.txt
plural = ${build:localdatadir}/b.txt ${build:localdatadir}/c.txt
"""))

localdir = tmp_path / 'local'
localdatadir = localdir / 'data'
localdatadir.mkdir(parents=True)

a = localdatadir / 'a.txt'
a.touch()

b = localdatadir / 'b.txt'
b.touch()

c = localdatadir / 'c.txt'
c.touch()

builder = make_builder(configdir=str(configdir), localdir=str(localdir))
builder.configure()

# All paths exist
builder.check_config()

b.unlink()
with pytest.raises(eib.ImageBuildError, match=r'plural.*b.txt'):
builder.check_config()

b.touch()
a.unlink()
with pytest.raises(eib.ImageBuildError, match=r'singular.*a.txt'):
builder.check_config()