Skip to content

Commit

Permalink
CRAYSAT-1917: Fix jinja2 rendering of boot_sets data in sat bootprep
Browse files Browse the repository at this point in the history
Make the following fixes:

- Remove the `boot_set` property from `BaseInputItem`. It is not appropriate
  there, and it is redundant with `boot_sets` property that already exists in
  the `InputSessionTemplate`
- Modify the `jinja_rendered` decorator to recursively render more complex
  objects like lists and dictionaries. I think this is safe, but we should
  consider any edge cases more carefully.
- Remove the now unnecessary code that does a one-off Jinja2 rendering of
  `rootfs_provider_passthrough` in the `boot_sets`.

Could still use unit test enhancements that test this new ability to render
fields in the boot_sets.

Test Description:
Tested on a simple bootprep input file that used a variable in the
`rootfs_provider_passthrough` field of a boot set in a BOS session template.
  • Loading branch information
haasken-hpe committed Oct 3, 2024
1 parent e7b8cda commit dcff8f2
Show file tree
Hide file tree
Showing 2 changed files with 20 additions and 19 deletions.
32 changes: 19 additions & 13 deletions sat/cli/bootprep/input/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -108,14 +108,25 @@ def wrapper(self, *args, **kwargs):
# Default to no additional context if not set
context = getattr(self, 'jinja_context', {})

try:
return self.jinja_env.from_string(unrendered_result).render(context)
except SecurityError as err:
raise error_cls(f'Jinja2 template {unrendered_result} for value '
f'{func.__name__} tried to access unsafe attributes.') from err
except TemplateError as err:
raise error_cls(f'Failed to render Jinja2 template {unrendered_result} '
f'for value {func.__name__}: {err}') from err
def render_object(obj):
"""Render an object with the given context."""
if isinstance(obj, str):
try:
return self.jinja_env.from_string(obj).render(context)
except SecurityError as err:
raise error_cls(f'Jinja2 template {obj} for value '
f'{func.__name__} tried to access unsafe attributes.') from err
except TemplateError as err:
raise error_cls(f'Failed to render Jinja2 template {obj} '
f'for value {func.__name__}: {err}') from err
elif isinstance(obj, dict):
return {key: render_object(value) for key, value in obj.items()}
elif isinstance(obj, list):
return [render_object(item) for item in obj]
else:
return obj

return render_object(unrendered_result)

return wrapper

Expand Down Expand Up @@ -242,11 +253,6 @@ def name(self):
# items that inherit from BaseInputItem.
return self.data['name']

@property
def boot_set(self):
"""Return the full boot_sets dictionary."""
return self.data.get('bos_parameters', {}).get('boot_sets', {})

def __str__(self):
# Since the name can be rendered, and when unrendered, it does not need
# to be unique, just refer to this item by its index in the instance.
Expand Down
7 changes: 1 addition & 6 deletions sat/cli/bootprep/input/session_template.py
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ def configuration(self):
return self.data['configuration']

@property
@jinja_rendered
def boot_sets(self):
"""dict: the boot sets specified for the session template"""
# the 'bos_parameters' property is required, and 'boot_sets' is required within that
Expand Down Expand Up @@ -186,12 +187,6 @@ def get_create_item_data(self):
boot_set_api_data.update(boot_set_data)
api_data['boot_sets'][boot_set_name] = boot_set_api_data

# Fetch full boot sets
boot_sets = self.boot_set
# Render the rootfs_provider_passthrough using Jinja2
rendered_rootfs = self.jinja_env.from_string(
boot_sets[boot_set_name]['rootfs_provider_passthrough']).render(self.data)
api_data['boot_sets'][boot_set_name]['rootfs_provider_passthrough'] = rendered_rootfs
return api_data

def get_image_record_by_id(self, ims_image_id):
Expand Down

0 comments on commit dcff8f2

Please sign in to comment.