Combining 2 lists of strings with a separator

hello guys,
I need to build filenames based on 3 parts: basename, version and trailing ‘.x86_64.rpm’.
Let’s focus on the first 2 parts:
The first one is:

“installed_mtx_packages_name”: [
“mtx-device”,
“mtx-grpc-agent”,
“mtx-infra”,

]

The second one is:

“installed_mtx_packages_version”: [
“1.0.0-r1705191346”,
“1.0.1-r1705191346”,
“1.0.0-r1705170158”,

]

the goal is to obtain this:
“installed_mtx_packages_partialname”: [
“mtx-device-1.0.0-r1705191346”,
“mtx-grpc-agent-1.0.0-r1705191346”,
“mtx-infra-1.0.0-r1705170158”,

]

I’ve tried several strategies, including:

  • name: Building partial name of installed MTX packages
    set_fact:
    installed_mtx_packages_partialname: “{{ installed_mtx_packages_name | map(‘regex_replace’, ‘(.*)’, ‘\1-item’) | list }}”
    with_items: installed_mtx_packages_version

But of course the item is considered as a string here instead of a variable.

If I move the ’ just before item, I get the error:
"template error while templating string: expected token ‘,’, got ‘string’ "

Any suggestion?

hello guys,
I need to build filenames based on 3 parts: basename, version and
trailing '.x86_64.rpm'.
Let's focus on the first 2 parts:
The first one is:
        "installed_mtx_packages_name": [
            "mtx-device",
            "mtx-grpc-agent",
            "mtx-infra",
...
        ]

The second one is:
        "installed_mtx_packages_version": [
            "1.0.0-r1705191346",
            "1.0.1-r1705191346",
            "1.0.0-r1705170158",
...
        ]

the goal is to obtain this:
         "installed_mtx_packages_partialname": [
            "mtx-device-1.0.0-r1705191346",
            "mtx-grpc-agent-1.0.0-r1705191346",

Should this line be "mtx-grpc-agent-1.0.1-r1705191346" by any chance?
Just checking if the example might be a typo :slight_smile:

            "mtx-infra-1.0.0-r1705170158",
...
        ]

This is not an answer for your question, but maybe a nudge to rethink
it if possible - do you absolutely have to form these as two separate
lists? Where do the installed_mtx_packages_name and
installed_mtx_packages_version variables come from? Command, some
external file?

Otherwise, you may want to look at this (if I understood your
requirements well):

https://docs.ansible.com/ansible/latest/playbooks_loops.html#looping-over-parallel-sets-of-data

I've tried several strategies, including:
- name: Building partial name of installed MTX packages
  set_fact:
        installed_mtx_packages_partialname:
"{{ installed_mtx_packages_name | map('regex_replace', '(.*)',
'\\1-item') | list }}" with_items: installed_mtx_packages_version

But of course the item is considered as a string here instead of a
variable.

If I move the ' just before item, I get the error:
"template error while templating string: expected token ',', got
'string' "

Not 100% sure what you mean by "just before item", but I'm assuming
you'd want (e.g. note the "'\\1-' + item" part - you can concatenate
strings this way):

"{{ installed_mtx_packages_name | map('regex_replace', '(.*)', '\\1-' + item) | list }}"

Additionally, you should switch to using (I think without moustaches
this would iterate over an item literal
"installed_mtx_packages_version" otherwise):

with_items: "{{ installed_mtx_packages_version }}"

To top it off - I'm pretty sure this particular loop would not produce
the list you desire.

Best regards

@branko

  • you’re right about the typo.
  • your “‘\1-’ + item” solution works beautifully :slight_smile:

The solution hence is:

  • name: Building partial name of installed MTX packages
    set_fact:
    installed_mtx_packages_partial_name: “{{ installed_mtx_packages_name | map(‘regex_replace’, ‘(.*)’, ‘\1-’ + item) | list }}”
    with_items: “{{ installed_mtx_packages_version }}”

The result is:

“installed_mtx_packages_partial_name”: [
“mtx-device-1.0.1-r1705191346”,
“mtx-grpc-agent-1.0.1-r1705191346”,
“mtx-infra-1.0.1-r1705191346”,

]

Thanks!

@branko

Sorry for the false positive, actually your solution does not work: it loops over all versions as expected, but it puts each item at the end of each name for each iteration, so the final list is (as shown in previous post):

“installed_mtx_packages_partial_name”: [
“mtx-device-1.0.1-r1705191346”,
“mtx-grpc-agent-1.0.1-r1705191346”,
“mtx-infra-1.0.1-r1705191346”,

]

As you can see (and I missed it the first time), all the elements have the same version, instead of its own.

The true solution is tricky:

  • name: Building partial name of installed MTX packages
    set_fact:
    installed_mtx_packages_partial_name_item: “{{ item.0 }}-{{ item.1 }}”
    with_together:

  • “{{ installed_mtx_packages_name }}”

  • “{{ installed_mtx_packages_version }}”
    register: installed_mtx_packages_partial_name_result

  • name: Building partial list of name of installed MTX packages
    set_fact:
    installed_mtx_packages_partial_name: “{{ installed_mtx_packages_partial_name_result.results | map(attribute=‘ansible_facts.installed_mtx_packages_partial_name_item’) | list }}”

leads to the true list:

“installed_mtx_packages_partial_name”: [
“mtx-infra-1.0.0-r1705191346”,
“mtx-device-1.0.0-r1705191346”,
“mtx-grpc-agent-1.0.1-r1705191346”,

]

There might be a more elegant solution.