using set_fact with until

108 views
Skip to first unread message

Kamesh Sampath

unread,
Sep 11, 2019, 3:22:50 AM9/11/19
to Ansible Project
I am trying to use `set_fact` with `until` and `retries`, will the fact be evaluated and set during each iteration ? Sometimes I see the value is not being set and I get the failure after the retries. While I see the corresponding lookup returns value using another cli.

name"Get Che Keycloak facts"
  set_fact:
    che_keycloak"{{ lookup('k8s', api_version='route.openshift.io/v1',kind='Route',resource_name='keycloak',namespace='che') }}"
  registerche_keycloak_route_result
  untilche_keycloak.spec is defined
  retries30
  delay10
  whenstate == 'present'

Vladimir Botka

unread,
Sep 11, 2019, 4:40:04 AM9/11/19
to Kamesh Sampath, ansible...@googlegroups.com
Yes. The the fact will be evaluated and set on each iteration. The problem is
that "set_fact" declares the variable "che_keycloak". The condition

until: che_keycloak.spec is defined

can't find the parameter "spec" because there isn't any.

Cheers,

-vlado

Kamesh Sampath

unread,
Sep 11, 2019, 4:44:50 AM9/11/19
to Ansible Project
do you mean to say I should invert the condition for this logic to work ?

Cheers,

        -vlado

Vladimir Botka

unread,
Sep 11, 2019, 4:50:20 AM9/11/19
to Kamesh Sampath, ansible...@googlegroups.com
On Wed, 11 Sep 2019 10:39:49 +0200
Vladimir Botka <vbo...@gmail.com> wrote:

> On Wed, 11 Sep 2019 00:22:50 -0700 (PDT)
> Kamesh Sampath <ksam...@redhat.com> wrote:
>
> > I am trying to use `set_fact` with `until` and `retries`, will the fact be
> > evaluated and set during each iteration ? Sometimes I see the value is not
> > being set and I get the failure after the retries. While I see the
> > corresponding lookup returns value using another cli.
> >
> > - name: "Get Che Keycloak facts"
> > > set_fact:
> > > che_keycloak:
> > > "{{ lookup('k8s', api_version='route.openshift.io/v1',kind='Route',resource_name='keycloak',namespace='che') }}"
> > > register: che_keycloak_route_result
> > > until: che_keycloak.spec is defined
> > > retries: 30
> > > delay: 10
> > > when: state == 'present'

Take a look at the registered variable "che_keycloak_route_result" to see
what's going on

- debug:
var: che_keycloak_route_result

Cheers,

-vlado

Vladimir Botka

unread,
Sep 11, 2019, 5:06:23 AM9/11/19
to Kamesh Sampath, ansible...@googlegroups.com
On Wed, 11 Sep 2019 01:44:50 -0700 (PDT)
Kamesh Sampath <ksam...@redhat.com> wrote:

> > Yes. The the fact will be evaluated and set on each iteration. The problem
> > is
> > that "set_fact" declares the variable "che_keycloak". The condition
> >
> > until: che_keycloak.spec is defined
> >
> > can't find the parameter "spec" because there isn't any.
> >
> do you mean to say I should invert the condition for this logic to work ?

No. I simply mean "spec" is not defined. The question is why? Take a look at
the registered variable. This should provide you with this information.

Cheers,

-vlado

Kamesh Sampath

unread,
Sep 11, 2019, 5:35:13 AM9/11/19
to Vladimir Botka, ansible...@googlegroups.com
the spec becomes available only after few seconds; so I need to keep the lookup run until then. Thats why I had that until checking to see if spec is defined in the fact.


Cheers,

        -vlado
--
Kamesh

Vladimir Botka

unread,
Sep 11, 2019, 5:50:40 AM9/11/19
to Kamesh Sampath, ansible...@googlegroups.com
On Wed, 11 Sep 2019 15:04:44 +0530
Kamesh Sampath <ksam...@redhat.com> wrote:

> > > > that "set_fact" declares the variable "che_keycloak". The condition
> > > >
> > > > until: che_keycloak.spec is defined
> > > >
> > > > can't find the parameter "spec" because there isn't any.
> > > >
> > > do you mean to say I should invert the condition for this logic to work ?
> >
> > No. I simply mean "spec" is not defined. The question is why? Take a look
> > the registered variable. This should provide you with this information.
>
> the spec becomes available only after few seconds; so I need to keep the
> lookup run until then. Thats why I had that until checking to see if spec
> is defined in the fact.

What is the failure (copy&paste) that "Sometimes I see the value is not being
set and I get the failure after the retries."?

Kamesh Sampath

unread,
Sep 11, 2019, 5:57:51 AM9/11/19
to Ansible Project
Exactly I see the value is not being set inspite of that is available after few seconds . The failure throws an error like 
"fatal: [localhost]: FAILED! => {"ansible_facts": {"che_keycloak": []}, "attempts": 30, "changed": false}"
 

Vladimir Botka

unread,
Sep 11, 2019, 6:51:22 AM9/11/19
to Kamesh Sampath, ansible...@googlegroups.com
On Wed, 11 Sep 2019 02:57:51 -0700 (PDT)
Kamesh Sampath <ksam...@redhat.com> wrote:

> > > > > >
> > > > > > until: che_keycloak.spec is defined
> > > > > >
> > > > > > can't find the parameter "spec" because there isn't any.
> > >
> > > the spec becomes available only after few seconds; so I need to keep the
> > > lookup run until then. Thats why I had that until checking to see if
> > > is defined in the fact.
> >
> > What is the failure (copy&paste) that "Sometimes I see the value is not
> > being
> > set and I get the failure after the retries."?
> >
> Exactly I see the value is not being set inspite of that is available after
> few seconds . The failure throws an error like
> "fatal: [localhost]: FAILED! => {"ansible_facts": {"che_keycloak": []},
> "attempts": 30, "changed": false}"

OK. Set "ignore_errors: true", register and print "result". Post it.

- set_fact:
che_keycloak: "{{ lookup('k8s',
api_version='route.openshift.io/v1',
kind='Route',
resource_name='keycloak',
namespace='che') }}"
register: result
until: che_keycloak.spec is
defined retries: 30 delay: 10
ignore_errors: true
when: state == 'present'

- debug:
var: result

Vladimir Botka

unread,
Sep 11, 2019, 6:55:31 AM9/11/19
to Kamesh Sampath, ansible...@googlegroups.com
Fixed syntax.

---

- set_fact:
che_keycloak: "{{ lookup('k8s',
api_version='route.openshift.io/v1',
kind='Route',
resource_name='keycloak',
namespace='che') }}"
register: result
until: che_keycloak.spec is defined
retries: 30
delay: 10
ignore_errors: true
when: state == 'present'

- debug:
var: result

...

Kai Stian Olstad

unread,
Sep 11, 2019, 8:29:42 AM9/11/19
to ansible...@googlegroups.com
With set_fact and until it will not set the variable on each iteration
unfortunately.
I don't know of any workaround.

--
Kai Stian Olstad

Kamesh Sampath

unread,
Sep 11, 2019, 8:32:53 AM9/11/19
to ansible...@googlegroups.com
That is what I observe :(

I don't know of any workaround.
any other better way you think of doing my task?


--
Kai Stian Olstad

--
You received this message because you are subscribed to a topic in the Google Groups "Ansible Project" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/ansible-project/fK2u9_IK48o/unsubscribe.
To unsubscribe from this group and all its topics, send an email to ansible-proje...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/ansible-project/fb9049c270601c5510b3ec2264ba7a32%40olstad.com.
--
Kamesh

Kai Stian Olstad

unread,
Sep 11, 2019, 8:52:47 AM9/11/19
to ansible...@googlegroups.com
On 11.09.2019 14:32, Kamesh Sampath wrote:
> On Wed, 11 Sep 2019 at 17:59, Kai Stian Olstad <
> ansible-pr...@olstad.com> wrote:
>
>> On 11.09.2019 09:22, Kamesh Sampath wrote:
>> > I am trying to use `set_fact` with `until` and `retries`, will the fact
>>
>> With set_fact and until it will not set the variable on each iteration
>> unfortunately.
>
> That is what I observe :(
>
>>
>> I don't know of any workaround.
>
> any other better way you think of doing my task?

You can add the pause module and just wait long enough.

I have not used the Kubernetes, but if it's a k8s module or and API with
URI module that can do the same, that with register would function with
until.


--
Kai Stian Olstad

Vladimir Botka

unread,
Sep 11, 2019, 3:57:30 PM9/11/19
to Kamesh Sampath, ansible...@googlegroups.com
On Wed, 11 Sep 2019 18:02:08 +0530
Kamesh Sampath <ksam...@redhat.com> wrote:

> > >> set_fact:
> > >> che_keycloak:
> > >> "{{ lookup('k8s',
> > >> api_version='route.openshift.io/v1',kind='Route',resource_name='keycloak',namespace='che')
> > >> }}"
> > >> register: che_keycloak_route_result
> > >> until: che_keycloak.spec is defined
> > >> retries: 30
> > >> delay: 10
> > >> when: state == 'present'
> >
> > With set_fact and until it will not set the variable on each iteration
> > unfortunately.
>
> That is what I observe :(
>
> > I don't know of any workaround.
>
> any other better way you think of doing my task?

The "lookup" plugin is evaluated only once before the module starts [1].
Hence it's not possible to get it working with the until/retries construct.

FWIW, it is possible to put it together. The "brute-force" playbook below

- hosts: localhost
vars:
my_continue: true
my_delay: 10
my_retries: 5
tasks:
- include_tasks: include-lookup.yml
loop: "{{ range(0, my_retries)|list }}"

with the included file include-lookup.yml

- name: 'Get data'
set_fact:
my_var: "{{ lookup('pipe', '/scratch/tmp/my_script')|from_yaml }}"
when: my_continue
- name: 'Set continue=false when data OK'
set_fact:
my_continue: false
when:
- my_var.spec is defined
- my_continue
- name: 'Delay next iteration'
wait_for:
timeout: "{{ my_delay }}"
when: my_continue

does the job. The concept works. When the variable "my_var.spec" is defined
then the variable "continue" will be set to False and following tasks will be
skipped.

[1] The "lookup" plugin is evaluated only once before the module starts. From
the log written by "my_script" cat be seen that "lookup" is evaluated
only once.

tasks:
- shell: "echo {{ lookup('pipe', '/scratch/tmp/my_script') }}"
# - shell: "/scratch/tmp/my_script"
ignore_errors: true
register: result
until: result.stdout == 'DUMMY'
retries: 3
delay: 2

$ cat my_script
#!/bin/sh
my_data=/scratch/tmp/my_data
my_log=/scratch/tmp/my_script.log
if [ -e ${my_data} ]; then
cat ${my_data}
fi
date >> ${my_log}

$ cat my_data
spec: 'Specification'

HTH. Cheers,

- vlado

flowerysong

unread,
Sep 11, 2019, 5:50:24 PM9/11/19
to Ansible Project
That seems overly complex. I would instead wait until the required data is available before running set_fact:

- vars:
    che_keycloak_lookup: "{{ lookup('k8s', api_version='route.openshift.io/v1',kind='Route',resource='keycloak',namespace='che') }}"
  block:
    - debug:
        msg: Waiting for data propagation...
      until: "'spec' in che_keycloak_lookup"
      retries: 30
      delay: 10

    - name: Get Che Keycloak facts
      set_fact:
        che_keycloak: "{{ che_keycloak_lookup }}"


Vladimir Botka

unread,
Sep 11, 2019, 10:25:53 PM9/11/19
to flowerysong, ansible...@googlegroups.com
On Wed, 11 Sep 2019 14:50:24 -0700 (PDT)
flowerysong <ezek...@umich.edu> wrote:

> That seems overly complex. I would instead wait until the required data is
> available before running set_fact:
>
> - vars:
> che_keycloak_lookup: "{{ lookup('k8s', ...
> [...]
> - debug:
> msg: Waiting for data propagation...
> until: "'spec' in che_keycloak_lookup"
> retries: 30
> delay: 10

Great! This is the solution how to evaluate "lookup" in each iteration. Just
put the evaluation into "until".

Thank you,

-vlado

Kamesh Sampath

unread,
Sep 11, 2019, 11:29:17 PM9/11/19
to Ansible Project
Thank you Vladmir and flowerysong, this solution works just as its needed. 
Reply all
Reply to author
Forward
0 new messages