using set_fact with until

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.

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

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’

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 ?

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

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

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.

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."?

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.”?

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

Fixed syntax.

With set_fact and until it will not set the variable on each iteration unfortunately.
I don't know of any workaround.

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’

With set_fact and until it will not set the variable on each iteration
unfortunately.

That is what I observe :frowning:

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.

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

That seems overly complex. I would instead wait until the required data is available before running set_fact:

`

`

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

Thank you,

  -vlado

Thank you Vladmir and flowerysong, this solution works just as its needed.