-1

I'm trying to build certain software on each machine locally. The playbook would download the source tarball (using get_url), configure and build it.

I'd like to define the list of items to build as something like the below:

srcpkg:
  python:
    ver:    "3.7.0"
    sha:    "0382996d1ee6aafe59763426cf0139ffebe36984474d0ec4126dd1c40a8b3549"
    url:    "https://www.python.org/ftp/python/{{ srcpkg.python.ver }}/python/Python-{{ srcpkg.python.pyver }}.tar.xz"

Unfortunately, such references to itself (the url refers to ver in the above example) cause Ansible to throw a "recursive loop detected" error at runtime.

Is there a way -- either in Ansible or, maybe, simply in Yaml -- to define things so that I wouldn't have to repeat the version in more than one place?

Update: tried to use anchor/reference:

srcpkg:
  python:
    ver:    &ver "3.7.0"
    sha:    "0382996d1ee6aafe59763426cf0139ffebe36984474d0ec4126dd1c40a8b3549"
    url:    "https://www.python.org/ftp/python/{{ *ver }}/python/Python-{{ *ver }}.tar.xz"

to no avail: Ansible complains of "unexpected '*'".

Mikhail T.
  • 3,043
  • 3
  • 29
  • 46

1 Answers1

3

When you write the following in YAML:

url: "https://www.python.org/ftp/python/{{ *ver }}/python/Python-{{ *ver }}.tar.xz"

the right side of the :  specifies a scalar value. YAML aliases are not resolved in parts of a scalar.

Ansible thus creates a string variable with the value: https://www.python.org/ftp/python/{{ *ver }}/python/Python-{{ *ver }}.tar.xz.

And for Jinja2 *ver is a syntax error.


What you can do is to use a helper Ansible variable (YAML uses eager evaluation for aliases, Jinja2 uses lazy evaluation for variables):

srcpkg:
  python:
    ver: &ver "3.7.0"
    sha: "0382996d1ee6aafe59763426cf0139ffebe36984474d0ec4126dd1c40a8b3549"
    url: "https://www.python.org/ftp/python/{{ python_version }}/python/Python-{{ python_version }}.tar.xz"
  python_version: *ver
techraf
  • 64,883
  • 27
  • 193
  • 198
  • Thanks, but that's not suitable for the task :( Different software has version embedded in different places of the download URLs, and this way I'll need a _separate_ variable for every package... Unfortunately, something like `Python-*ver.tar.xz` is not expanded at all... – Mikhail T. Aug 14 '18 at 21:30
  • Well, you asked a question, posted some code, and I answered your question. I have no knowledge of what tasks you have in your mind. I also don't understand what you mean by "*`Python-*ver.tar.xz` is not expanded at all*", because such string does not occur in the example I posted. If you did not define the anchor, YAML parser would give you an error `found undefined alias` on the `python_version: *ver` line. – techraf Aug 14 '18 at 21:36
  • The task is described in the question. The goal is to have a single data-structure describing, where to get the sources for each package. – Mikhail T. Aug 14 '18 at 21:39
  • Unfortunately SO does not allow the answer as short as "you cannot". And it seems you already figured out you can't. – techraf Aug 14 '18 at 21:42
  • That line doesn't define a string. It specifies **two** *nodes*: the key and value for a mapping. The nodes are separated by a mapping indicator (`:`) The key is a plain style scalar node, the value is a double quoted style scalar node (those quotes are superfluous). The OP obviously skimmed the YAML documentation (if he bothered to read the documentation for the tools he is using at all), as that very clearly indicates that *anchors and aliases work on the node level*. – Anthon Aug 15 '18 at 11:33
  • @Anthon If it is a scalar and not a string, then is `foo: !!int bar` valid in YAML? (`yamllint` accepts it, but the web one changes it to `foo: bar`, so it is not very helpful) Obviously it is not a correct representation of an integer, but is it an incorrect YAML, or is it passed to the consumer for "judgement"? Likewise, for `foo: 123` and `foo: bar` the matching to a [generic string](http://yaml.org/spec/1.2/2009-07-21/spec.html#id2601957) and an [integer](http://yaml.org/spec/1.2/2009-07-21/spec.html#id2602943) is outside of YAML? – techraf Aug 22 '18 at 20:20
  • @techraf According to the spec the secondary tag handle `!!` is short-hand for `tag:yaml.org,2002:` and the spec refers to the type repository for details (for int to http://yaml.org/type/int.html). So yes it is outside, but it also official by the reference. That info is actually only used during compositing of the objects, not during parsing or composing. And if you use e.g. ruamel.yaml/PyYAML BaseLoader everything loads as as string and the composer never fails because it doesn't try to make an int out of `bar`. Unfortunately YAML 1.2 refers to the type repository, but then defines e.g. – Anthon Aug 22 '18 at 21:31
  • `!!bool` much narrower than the repository does in its core schema. I would have preferred a more active and explicit revocal "Off" as a boolean myself. I would expect your example to generate an error when trying to appy the core/normal schema, but not when using a minimal schema (which AFAIK still allows you to use ``!!int` tags, just not necessarily interpret them). – Anthon Aug 22 '18 at 21:36