How to loop over an array inside a dictionary

1,546 views
Skip to first unread message

Thomas Krahn

unread,
Nov 18, 2014, 1:55:42 PM11/18/14
to ansible...@googlegroups.com
Hi All

i'm trying to migrate my Oracle installation from Puppet to Ansible. As i need severyl ORACLE_HOME on one server i have defned the following dictionary variable:

oracle_app_directory=/app
oracle_db_homes:
  dbhome_1:
    version: 12.1.0
    path: "{{ oracle_app_directory }}/oracle/product/12.1.0/dbhome_1"
    installation_files_directory: /share/oracle/12.1.0/patches
    installation_files:
    - linuxamd64_12c_database_1of2.zip
    - linuxamd64_12c_database_2of2.zip
    unpack_directory: /share/oracle/12.1.0/unpacked
  dbhome_2:
    version: 11.2.0
    path: "{{ oracle_app_directory }}/oracle/product/11.2.0/dbhome_1"
    installation_files_directory: /share/oracle/11.2.0/patches
    installation_files:
    - linuxamd64_11g_database_1of2.zip
    - linuxamd64_11g_database_2of2.zip
    unpack_directory: /share/oracle/11.2.0/unpacked

I need to loop over the dictionary (oracle_db_homes) to unpack the files (installation_files) for each defined ORACLE_HOME into a directory (unpack_directory). 

How can i do that with Ansible ?

Karl E. Jorgensen

unread,
Nov 18, 2014, 4:29:58 PM11/18/14
to ansible...@googlegroups.com
Hi
http://docs.ansible.com/playbooks_loops.html#looping-over-hashes

should help. For example:

tasks:
- name: Do clever stuff
command: echo {{item.key}}: Oracle version {{item.value.version}} goes into {{item.value.path}}
with_dict: oracle_db_homes

But your data structure looks a bit odd to me: Does each entry in
oracle_db_homes need to have a name? If not, you can define it as an
array rather than a dict/hash:

oracle_db_homes:
- version: 12.1.0
path: "{{oracle_app_directory}}/oracle/somewhere/here"
- version: 11.2.0
path: "{{oracle_app_directory}}/oracle/somewhere/else"


Hope this helps

--
Karl E. Jorgensen

Thomas Krahn

unread,
Nov 19, 2014, 8:25:14 AM11/19/14
to ansible...@googlegroups.com
Hi Karl,

Thanks for your answer. The name is needed as I need to reference it from another data structure. My problem is really not how to loop over a dict. My problem is the array installation_files where I need to loop additionally.

I need to unpack the installation files for every home ;-)

Thomas

James Martin

unread,
Nov 19, 2014, 10:06:43 AM11/19/14
to ansible...@googlegroups.com
Karl is correct.  Your data structure is making things difficult.  If you make your datastructure a list of dictionaries, you can use the with_subelements function, described here:  http://docs.ansible.com/playbooks_loops.html#looping-over-subelements

- hosts: localhost
  vars
:
    oracle_app_directory
: /app
    oracle_db_homes:
    - version: 12.1.0
      path: "{{ oracle_app_directory }}/
oracle/product/12.1.0/dbhome_1"

      installation_files_directory: /share/oracle/12.1.0/patches
      installation_files:
      - linuxamd64_12c_database_1of2.zip
      - linuxamd64_12c_database_2of2.zip
      unpack_directory: /share/oracle/12.1.0/unpacked
    - version: 11.2.0
      path: "
{{ oracle_app_directory }}/oracle/product/11.2.0/dbhome_1"

      installation_files_directory: /share/oracle/11.2.0/patches
      installation_files:
      - linuxamd64_11g_database_1of2.zip
      - linuxamd64_11g_database_2of2.zip
    unpack_directory: /share/oracle/11.2.0/unpacked
  tasks:
  - debug: msg="
{{ item.0.version }} -- {{ item.1 }}"
    with_subelements:
    - oracle_db_homes
    - installation_files

Brian Coca

unread,
Nov 19, 2014, 10:40:22 AM11/19/14
to ansible...@googlegroups.com
a slight change can make the structure a lot more usable:

oracle_db_homes:
  - orahome: dbhome_1
    version: 12.1.0
....


--
Brian Coca

Thomas Krahn

unread,
Nov 19, 2014, 11:28:34 AM11/19/14
to ansible...@googlegroups.com
Hi James

thanks a lot for you help. My first problem is solved :-).

Let me try to explain why i think i need the "dbhome_1" and "dbhome_2". If one of you guys has a solution for this also than my migration to Ansible can go one.

Second Problem:

I have several databases on one host so i wanted to define another variable like this:

oracle_databases:
  DB1:
    dbhome: dbhome_1
    ... some other stuff...
  DB2:
    dbhome: dbhome_1
  DB3:
    dbhome: dbhome_2

So my idea (like i do it in Puppet) is to use the value of oracle_database.dbhome to reference to oracle_db_home[dbhome].path.

Any idea?

James Martin

unread,
Nov 19, 2014, 1:06:50 PM11/19/14
to ansible...@googlegroups.com
I stand corrected, it does seem you can use with_subelements with a dictionary.  The following (on ansible 1.8-devel) will loop through all the installation_files

- hosts: localhost
  vars
:
    oracle_app_directory
:
/app
    oracle_db_homes:
      DB1:
        path: "{{ oracle_app_directory }}/
oracle/product/12.1.0/dbhome_1"

        installation_files_directory: /share/oracle/12.1.0/patches
        installation_files:
        - linuxamd64_12c_database_1of2.zip
        - linuxamd64_12c_database_2of2.zip
        unpack_directory: /share/oracle/12.1.0/unpacked
      DB2:
        path: "
{{ oracle_app_directory }}/oracle/product/11.2.0/dbhome_1"

        installation_files_directory: /share/oracle/11.2.0/patches
        installation_files:
        - linuxamd64_11g_database_1of2.zip
        - linuxamd64_11g_database_2of2.zip
        unpack_directory: /share/oracle/11.2.0/unpacked
  tasks:
  - debug: msg="
{{ item.1 }}"

    with_subelements:
    - oracle_db_homes
    - installation_files

ansible-playbook -i hosts test.yml |grep msg
TASK: [debug msg=" {{ item.1 }}"] *********************************************
    "msg": " linuxamd64_12c_database_1of2.zip"
    "msg": " linuxamd64_12c_database_2of2.zip"
    "msg": " linuxamd64_11g_database_1of2.zip"
    "msg": " linuxamd64_11g_database_2of2.zip"

Reply all
Reply to author
Forward
0 new messages