Ansible and Satellite 6.4 - Waiting for Promote To Finish

44 views
Skip to first unread message

Cade Lambert

unread,
Aug 20, 2019, 1:29:26 PM8/20/19
to Ansible Project
I created a playbook to connect to Satellite via API, publish new content views, and promote the various lifecycle environments to these new Content View versions, looping through a list of Lifecycle Environments.  The issue I'm having is I can't figure out a way for my task to wait until the promotion of one Lifecycle Environment is completed before attempting to promote the next.  If it tries to promote while a promotion is already in progress, the task fails.  I've added a delay to the task to try to wait it out but that doesn't always work and was hoping for a more clever solution.  Here's my task:

  - name: Promote new RHEL7 version to Lifecycle Environments
    uri:
      url: "https://satelliteserver/katello/api/v2/content_view_versions/{{ (content_views7.json.results[0].id | int) }}/promote"
      method: POST
      body:
        description: "Promoted by Tower"
        environment_id: "{{ item }}"
        organization_id: 3
        force: true
      user: "{{ satellite_user }}"
      password: "{{ satellite_pass }}"
      force_basic_auth: yes
      validate_certs: no
      body_format: json
      status_code: 202
    loop:
      - 3
      - 4
      - 5
      - 6
      - 7
      - 8
    loop_control:
      pause: 180

Any input on a way to wait for the promotion to finish, or a cleaner way of doing the same thing?

Jonathan Lozada De La Matta

unread,
Aug 20, 2019, 1:54:48 PM8/20/19
to ansible...@googlegroups.com
Cade,

Check out https://docs.ansible.com/ansible/latest/user_guide/playbooks_loops.html There's delays, retries etc. You can use any of this to accomplish what you want.

--
You received this message because you are subscribed to the Google Groups "Ansible Project" group.
To unsubscribe from this group and stop receiving emails from it, send an email to ansible-proje...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/ansible-project/60b7d8f5-fad5-47c6-bb22-91c47ae0da1c%40googlegroups.com.


--

Jonathan Cha'gara Lozada De La Matta

He / Him / His

Red Hat

Senior Automation Practice Consultant & Automation CoP Manager

Join the Automation CoP! https://red.ht/autocop

 

Cade Lambert

unread,
Sep 5, 2019, 10:16:26 AM9/5/19
to Ansible Project
So I'm still having trouble with this.  Here's my task:

  - name: Promote new RHEL7 version to Lifecycle Environments
   uri:
     url: "https://satellite/katello/api/v2/content_view_versions/{{ (content_views7.json.results[0].id | int) }}/promote"
     method: POST
     body:
       description: "Promoted by Tower"
       environment_id: "{{ item }}"
       organization_id: 3
       force: true
     user: "{{ satellite_user }}"
     password: "{{ satellite_pass }}"
     force_basic_auth: yes
     validate_certs: no
     body_format: json
     status_code: 202
   register: promote_rhel7
   loop:
     - 3
     - 4
     - 5
     - 6
     - 7
     - 8
   until: promote_rhel7.json.result == 'success'
   retries: 10
   delay: 20


I tried this but it error'd out with:

fatal: [localhost]: FAILED! => {"msg": "The conditional check 'promote_rhel7.json.result == 'success'' failed. The error was: error while evaluating conditional (promote_rhel7.json.result == 'success'): 'dict object' has no attribute 'result'"}


Which I kind of expected because it doesn't seem like it's returning anything.  I'm trying to loop through all the lifecycle environments in one task, but I also need to check the tasks from satellite to ensure the promotion is done before it attempts to promote to the next lifecycle environment, or it'll throw a lock error.  I know I could ditch the loop and create a task for each lifecycle environment, and check satellite tasks prior to each promotion, but I was hoping there was a sleeker way to do it.

I've used loop_control and pause previously, but I'd like to know for certain a promote is complete before attempting the next one.

Kai Stian Olstad

unread,
Sep 6, 2019, 2:27:26 AM9/6/19
to ansible...@googlegroups.com
On 05.09.2019 16:16, Cade Lambert wrote:
> until: promote_rhel7.json.result == 'success'
> retries: 10
> delay: 20
>
>
> I tried this but it error'd out with:
>
> fatal: [localhost]: FAILED! => {"msg": "The conditional check
> 'promote_rhel7.json.result == 'success'' failed. The error was: error
> while
> evaluating conditional (promote_rhel7.json.result == 'success'): 'dict
> object' has no attribute 'result'"}

I don't know anything about the api you are using so I can't comment on
that, but this type of error can be solved by checking if the variable
is defined first.

until: promote_rhel7.json.result is defined and
promote_rhel7.json.result == 'success'



--
Kai Stian Olstad

Cade Lambert

unread,
Sep 6, 2019, 10:52:18 AM9/6/19
to Ansible Project
Yeah, it's not defined because it's not a value that's returned when the API call is sent.  I'm not sure there's a way to do what I'm trying to do with a loop.

Zolvaring

unread,
Sep 6, 2019, 11:28:46 AM9/6/19
to ansible...@googlegroups.com
I think Kai's suggestion is correct, don't know much about your specific use case, but I've had similar issues looping with return values. The reason is on there first check the call hasn't been made yet and "results" won't exist you're right, but on subsequent calls within that loop it will, so that extra clause should fix that error.

On Fri, Sep 6, 2019, 7:52 AM Cade Lambert <crl...@gmail.com> wrote:
Yeah, it's not defined because it's not a value that's returned when the API call is sent.  I'm not sure there's a way to do what I'm trying to do with a loop.

--
You received this message because you are subscribed to the Google Groups "Ansible Project" group.
To unsubscribe from this group and stop receiving emails from it, send an email to ansible-proje...@googlegroups.com.

Cade Lambert

unread,
Sep 6, 2019, 1:14:32 PM9/6/19
to Ansible Project
I tested that just now.  It doesn't work. The API doesn't send a response about the status of the promote task.  When I make the call to promote, it immediately responds with info that it started, and that's all.  So the solution Kai provided really just keeps sending the same API request using the same loop item, because it never gets a response back from the API about result.

root@tower /etc/ansible/playbooks $ ansible-playbook test.yml

PLAY [localhost] ********************************************************************************************************************************************************************************************************************************

TASK [Gathering Facts] **************************************************************************************************************************************************************************************************************************
ok: [localhost]

TASK [Promote new RHEL7 version to Lifecycle Environments] **************************************************************************************************************************************************************************************
FAILED - RETRYING: Promote new RHEL7 version to Lifecycle Environments (10 retries left).
FAILED - RETRYING: Promote new RHEL7 version to Lifecycle Environments (9 retries left).
FAILED - RETRYING: Promote new RHEL7 version to Lifecycle Environments (8 retries left).
FAILED - RETRYING: Promote new RHEL7 version to Lifecycle Environments (7 retries left).
FAILED - RETRYING: Promote new RHEL7 version to Lifecycle Environments (6 retries left).
FAILED - RETRYING: Promote new RHEL7 version to Lifecycle Environments (5 retries left).
FAILED - RETRYING: Promote new RHEL7 version to Lifecycle Environments (4 retries left).
FAILED - RETRYING: Promote new RHEL7 version to Lifecycle Environments (3 retries left).


Zolvaring

unread,
Sep 7, 2019, 2:56:08 AM9/7/19
to ansible...@googlegroups.com
Okay, looking more closely I think I see. I don't believe "results" becomes populated in a loop object until the end of the first iteration and with a retry technically you have never ended that first iteration. What I would do then is this:

include_tasks: register_environment
loop:
  - 3
  - 4
  etc


---
# file: register_environment.yml

- task:
  your whole task as you wrote it with retries

This will bring the task out of a loop by using the file include and I believe it will handle register normally (as in "result" will be available for retry for initial iteration)


--
You received this message because you are subscribed to the Google Groups "Ansible Project" group.
To unsubscribe from this group and stop receiving emails from it, send an email to ansible-proje...@googlegroups.com.

Cade Lambert

unread,
Sep 9, 2019, 9:10:39 AM9/9/19
to Ansible Project
Interesting, I'll try that later. For now, I just went ahead and created the role with each lifecycle environment having it's own register task and then importing a separate task file that contains the tasks to query the task queue in satellite and wait until the task is finished..   I think if I combined that with your idea, it'd probably work and have less code.
Reply all
Reply to author
Forward
0 new messages