Composability: is there a way to implement a module as a series of ansible tasks?

51 views
Skip to first unread message

Ben Cohen

unread,
Aug 15, 2015, 1:00:14 AM8/15/15
to ansible...@googlegroups.com
I really like the ansible module interface: pure functions are powerful, super simple and really great.  The with_items syntax adds a lot of power on top with very low cognitive overhead that helps keep you laser focused on describing your objectives in ways that tend to be very declarative.

Sometimes though, I've got a task that I need to do multiple times but can't express as a single module call -- or I might find myself needing to do something somewhat tricky in multiple different places and I'd like to avoid repeating the complexity.  I use the the roles/ system heavily to try and reduce repetition, however some things just aren't easily refactored into roles or its very awkward to do so and increases the cognitive overhead of understanding the overall objective.

Does a mechanism exist which makes it possible to basically package up a sequence of tasks as a module?

It would be (really really) cool if I could package up a sequence of tasks as a custom module.  I imagine a syntax like this:

inside library/copyAndDecrypt.yml

---

- defineModule: "copyAndDecrypt"
  arguments:
    src:
      type: string
      required: yes
    dest: 
      type: string
      required: yes
    owner:
      type: string
      default: None
    mode:
      type: string
      default: None
    secret:
      type: string
      required: yes
  local_vars:
    some_local_var: "just convenient suguar for re-use within the module"
  tasks:
    
    - name: Decrypt contents of src and capture into a variable
      local_action: shell openssl aes-256-cbc -salt -a -d -in {{ src }} -k {{ secret }}
      register: decryptedContents

    - name: Ensure decrypted key is copied to expected location
      copy:
      args:
        content: "{{ decryptedContents }}"
        dest: /etc/nginx/ssl/sts_ssl_private.key
        owner: {{ owner }}
        mode: {{ mode }}


Usage would then be like using a module:

---

- name: "Ensure decrypted ssl private key is deployed where webserver will look for it"
  copyAndDecrypt: src=path_on_control_node/to/encrypted_file dest=/path/where/decrypted/file/should/live owner=root mode=0600

- name: "Ensure all these secret files are decrypted and in place"
  copyAndDecrypt: src={{item.src}} dest={{item.dest}} owner=accountingDepartment mode=0600
  with_items:
    - src: accounting/owed_money
      dest: "{{ secret_base }}/"
    - src: accounting/stolen_money
      dest: "{{ secret_base }}/"
    - src: accounting/lost_money
      dest: "{{ secret_base }}/""
    
Not entirely sure what the module would return, perhaps the value of the first task with an error or the value of the last task with successful exit ... (ansible 2 handlers could be relevant though i'm not all that familiar with what ansible2 is bringing to the table)...  I understand that ansible2 has block scope and other features coming -- though I don't know the details, but I imagine it will make it significantly simpler to implement a scope mechanism?  The idea being that the module has its own scope with only passed in parameters and local_vars being accessible within and with any registered variables referenced on tasks being accessible from only the module scope ...

it seems like it would be relatively straightforward to implement something like this in ansible2?  Would people be interested?

(or if I'm just missing that this feature exists already in some form, please let me know as I'd love to use it!)

Brian Coca

unread,
Aug 15, 2015, 1:06:49 AM8/15/15
to Ansible Project
that is what includes and roles are for.



--
Brian Coca

Ben Cohen

unread,
Aug 15, 2015, 1:40:55 AM8/15/15
to ansible...@googlegroups.com
Ok -- I see that include: supports with_items in ansible v2 -- I think I see that include: + blocks: get me most of what I want.  Will (does already?) include: have an option in v2 to limit the scope of the included tasks to only the values passed in and to not leak variables registered within out to the caller?  It seems like include: and with_items: could become confusing without this ...





--
Brian Coca

--
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 post to this group, send email to ansible...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/ansible-project/CAJ5XC8kHB9YT9VhwuKU%2BXFWHoG45cEaaAuRk_WoVih5nvXt1Nw%40mail.gmail.com.
For more options, visit https://groups.google.com/d/optout.

Brian Coca

unread,
Aug 15, 2015, 9:53:56 AM8/15/15
to Ansible Project
no var scoping, but just using simple naming conventions should deal with that.
> https://groups.google.com/d/msgid/ansible-project/CABUBibtQ6wuny-E1fQU1eLEXP31kH0WGowF6-DVzC%2B7-zNJy5A%40mail.gmail.com.
>
> For more options, visit https://groups.google.com/d/optout.



--
Brian Coca

Ben Cohen

unread,
Aug 16, 2015, 2:56:12 AM8/16/15
to ansible...@googlegroups.com
It works in the example I gave yes -- but it seems like any task with both when: and register: becomes basically impossible to reason about within an include ... (the registered value could come from a previous include: invocation in the case of when: evaluating to false) ...
Reply all
Reply to author
Forward
0 new messages