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

Support Jinja imports with relative paths. Issue #13889 #47490

Merged
merged 16 commits into from
Jun 8, 2018

Conversation

plastikos
Copy link
Contributor

@plastikos plastikos commented May 4, 2018

Jinja imports will be interpreted as originating from the top of each
of the directories in the searchpath when the template name does not
begin with './' or '../'. When a template name begins with './' or
'../' then the import will be relative to the importing file.

Prior practices required the following construct:

{% from tpldir ~ '/foo' import bar %}

This patch supports a more "natural" construct:

{% from './foo' import bar %}

Comparatively when importing from a parent directory - prior practice:

{% from tpldir ~ '/../foo' import bar %}

Construct supported by this patch:

{% from '../foo' import bar %}

What does this PR do?

Supports relative Jinja imports.

What issues does this PR fix or reference?

#13889

Previous Behavior

Unfortunately {% from './foo' import bar %} does not work. This super-secret technique was required: {% from tpldir ~ '/foo' import bar %}

New Behavior

This works: {% from './foo' import bar %}

Tests written?

Yes

Commits signed with GPG?

No

Please review Salt's Contributing Guide for best practices.

See GitHub's page on GPG signing for more information about signing commits with GPG.

Jinja imports will be interpreted as originating from the top of each
of the directories in the searchpath when the template name does not
begin with './' or '../'.  When a template name begins with './' or
'../' then the import will be relative to the importing file.

Prior practices required the following construct:

.. code-block:: yaml

  {% from tpldir ~ '/foo' import bar %}

This patch supports a more "natural" construct:

.. code-block:: yaml

  {% from './foo' import bar %}

Comparatively when importing from a parent directory - prior practice:

.. code-block:: yaml

  {% from tpldir ~ '/../foo' import bar %}

Construct supported by this patch:

.. code-block:: yaml

  {% from '../foo' import bar %}
Copy link
Contributor Author

@plastikos plastikos left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are a few details that should be cleaned-up before this is merged.

the importing file.

'''
# FIXME: somewhere do seprataor replacement: '\\' => '/'
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Translation of \ => / might be broken. Help me, Obi Juan, you're my only hope!

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@dwoz @twangboy When using jinja imports on Windows, are Windows-specific path-separators supported? If so, are they the only ones supported, or are forward slashes also supported? I would assume both are supported, since they are in Python proper, but I don't want to assume without knowing for sure.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I use Windows separators in my Jinja. I don't even have to escape them. Jinja apparently does some escaping for you.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The tpldir = os.path.dirname(template).replace('\\', '/') construct was in the original code and appears to do some path translation on Windows. I'm not sure how to test it to ensure that I haven't broken the functionality. Is there a unit test?

'''
Salt-specific loader to find imported jinja files.

Jinja imports will be interpreted as originating from the top
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This import behavior needs to be in the documentation. Where is the best location for it?

@plastikos
Copy link
Contributor Author

RETEST

@plastikos
Copy link
Contributor Author

Help! Suggestions welcome!

@@ -332,7 +332,7 @@ def parse_args(self, args=None, values=None):
os.path.basename(fpath).startswith('test_'):
self.options.name.append(fpath)
continue
self.exit(status=1, msg='\'{}\' is not a valid test module'.format(fpath))
self.exit(status=1, msg='\'{}\' is not a valid test module\n'.format(fpath))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you help me understand this change? I don't know what adding a newline here fixes.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Without the newline then the error message is not on a line by itself and the command prompt is left on the same line as the error message.

'Relative path "%s" cannot be resolved without an environment',
template
)
print('Relative path "{0}" cannot be resolved without an environment'.format(template))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should not be printing to the CLI here.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well that's embarrassing - that should have been removed.

if _template.split('/', 1)[0] == '..':
log.warning(
'Discarded template path "%s": attempts to'
' ascend outside of file roots', template
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since we have multiple backends, we can't assume people will be using file_roots, so this log message should reference salt:// instead.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay.

the importing file.

'''
# FIXME: somewhere do seprataor replacement: '\\' => '/'
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@dwoz @twangboy When using jinja imports on Windows, are Windows-specific path-separators supported? If so, are they the only ones supported, or are forward slashes also supported? I would assume both are supported, since they are in Python proper, but I don't want to assume without knowing for sure.

@plastikos
Copy link
Contributor Author

@terminalmage - review changes, please.

@rallytime
Copy link
Contributor

@plastikos Is this ready to go from your side?

If so, can you also add a mention of this addition to the Fluorine release notes?

@plastikos
Copy link
Contributor Author

@rallytime - I'll add the mention in the release notes and it will be ready to go.

@plastikos
Copy link
Contributor Author

@rallytime , thanks for the fix-ups.

@rallytime rallytime merged commit 160cdb2 into saltstack:develop Jun 8, 2018
myii added a commit to myii/salt that referenced this pull request Apr 8, 2022
Fix saltstack#61040.

Jinja imports with relative paths was introduced in saltstack#47490.

Unfortunately, relative imports have never been working on Windows.
That's due to backslashes being unhandled by the `cache_file` function:

* https://github.com/saltstack/salt/blob/7275ecf073197faed26f3a571c25fcd59bfbfd60/salt/utils/jinja.py#L114

Instead of getting:

* `salt://packages/map.jinja`

We're ending up with:

* `salt://packages\map.jinja`

Thus, the file isn't cached from the master.

There's actually a `FIXME` note about it:

* https://github.com/saltstack/salt/blob/7275ecf073197faed26f3a571c25fcd59bfbfd60/salt/utils/jinja.py#L136

And the replacement is actually done for setting `tpldir`:

* https://github.com/saltstack/salt/blob/7275ecf073197faed26f3a571c25fcd59bfbfd60/salt/utils/jinja.py#L165

This commit ensures the replacement is also done when caching files.
Ch3LL pushed a commit that referenced this pull request Apr 11, 2022
Fix #61040.

Jinja imports with relative paths was introduced in #47490.

Unfortunately, relative imports have never been working on Windows.
That's due to backslashes being unhandled by the `cache_file` function:

* https://github.com/saltstack/salt/blob/7275ecf073197faed26f3a571c25fcd59bfbfd60/salt/utils/jinja.py#L114

Instead of getting:

* `salt://packages/map.jinja`

We're ending up with:

* `salt://packages\map.jinja`

Thus, the file isn't cached from the master.

There's actually a `FIXME` note about it:

* https://github.com/saltstack/salt/blob/7275ecf073197faed26f3a571c25fcd59bfbfd60/salt/utils/jinja.py#L136

And the replacement is actually done for setting `tpldir`:

* https://github.com/saltstack/salt/blob/7275ecf073197faed26f3a571c25fcd59bfbfd60/salt/utils/jinja.py#L165

This commit ensures the replacement is also done when caching files.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants