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

Allow to force data types in YAML after jinja expansion #72

Closed
yajo opened this issue Sep 19, 2017 · 6 comments
Closed

Allow to force data types in YAML after jinja expansion #72

yajo opened this issue Sep 19, 2017 · 6 comments
Labels

Comments

@yajo
Copy link

yajo commented Sep 19, 2017

Proposal: Allow to force data types in YAML after jinja expansion

Author: Jairo Llopis <@yajo>

Date: 2017-09-19

  • Status: New
  • Proposal type: (core design, process, ?)
  • Targeted Release: <future release #, ex. 2.2>
  • Associated PR: <link to GH PR in ansible/proposals if PR was submitted>
  • Estimated time to implement: <X days, weeks, etc.>

Motivation

Sometimes you cannot use all of ansible+jinja power if the module did not define the right data type.

Problems

What problems exist that this proposal will solve?

Solution proposal

As explained in ansible/ansible#15249 (comment), Ansible should allow and parse YAML application-specific local tags that force a type cast after the value has been jinja2-evaluated

YAML itself has already type casters such as !!int or !!float (double !!), but those happen before jinja2, and thus they produce an error.

Basically one should be able to add !str, !int or !float (notice the single !) to any variable, either with or without jinja2 expansion, and it should get correctly type-casted after processing the jinja2 filters.

For instance, this should then be a valid workaround for ansible/ansible#30548:

- docker_service:
    pull: true
    state: present
    project_name: test
    definition:
      version: "2.2"
      services:
        dind:
          image: docker:dind
          cpus: !float "{{ ansible_processor_cores / 2 }}"

Testing (optional)

A simple debug task would be enough to test it IMHO.

Documentation (optional)

Of course, this should be documented.

@bcoca
Copy link
Member

bcoca commented Sep 19, 2017

This assumes templating happens before or during the YAML processing, it happens well after, so the YAML type would error out as templates are always strings, by definition.

Type management is then done either in Jinja2 via filters |int or |float and/or in the module option definitions themselves (we call this argspec) name=<option name>, type='integer', which should cast to the correct type if possible.

for your case it would look like this:

 cpus:  "{{ (ansible_processor_cores / 2)|float }}"

Sadly this can be 'lost' when templating again, so you always want to use it on 'consumption' and not on 'definition', we have a PR to jinja2 itself to be better about preserving type but that will take time.

@dagwieers
Copy link
Contributor

The PR to preserve type in Jinja2 is pallets/jinja#708

@yajo
Copy link
Author

yajo commented Sep 20, 2017

Well, the YAML tag (what @bcoca calls type) errors out when it is a built-in one (2 !!), but YAML allows applications to define local tags (1 !). Ansible can map those tags to classes/functions that perform lazy type transform (after jinja evaluation), so the type conversion happens in the correct time.

As an example, you can check out how Odoo implements this.

@sivel
Copy link
Member

sivel commented Sep 20, 2017

The problem as @bcoca mentioned with your specific implementation proposal, is that YAML and jinja parsing happen at different times. So trying to use YAML tags, doesn't work as expected.

What happens is that when YAML is parsed the !float tries to run on a value of "{{ ansible_processor_cores / 2 }}"

The above in your example tries to turn the literal string "{{ ansible_processor_cores / 2 }}" into a float at YAML parsing time which fails.

The PR that @dagwieers mentions is the appropriate solution.

@yajo
Copy link
Author

yajo commented Sep 21, 2017

Well, I said lazy type transform for some reason. But indeed, pallets/jinja#708 is the best bet.

@bcoca
Copy link
Member

bcoca commented Oct 19, 2017

@yajo, closing this proposal as per above. The real place to implement this is in Jinja2 itself.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

4 participants