How to loop over an array inside a dictionary

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 ?

Hi

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 ?

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

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 :wink:

Thomas

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

`

a slight change can make the structure a lot more usable:

oracle_db_homes:

  • orahome: dbhome_1
    version: 12.1.0

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?

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"

`