Happy new year! I’ll continue with Ansible topic with one more post as it has helped our small operations team quite a lot lately.
We still run Oracle e-Business Suite 12.1.3 and the amount of customizations we have is really high(No surprise there!). Due to some historical reasons initially we were loading custom objects to eBS via shell scripts. As time passed this was changed so we used concurrent requests to install those custom objects.
Basically what happens is the concurrent looks for specific named zip object from installation directory and if it exists it executes the shell script. This method is no way perfect but it has worked for us and nobody really had time to improve the script.
In addition to this we always had to go to version control system, checkout the zips for specific tag/release and then upload them to installation directory. Lot of manual and quite static tasks!
So Ansible to the rescue. Using Ansible we found really simple way to reduce manual tasks without touching (yet) the actual installation method. As of now we still use subversion but are already in process on switching to Gitlab and making some changes on deploying the code.
If I break the tasks what Ansible does on high level:
Once again as there is lot of passwords involved we have used ansible-vault as well for variables.
Here we first define the startdate if we would like to schedule the requests but next step is to install subversion & rsync via yum. Really basic but I think it is best to have these here because otherwise you would always need to check if they exist or not.
--- - include: define_startdate.yml when: sch_date is defined - name: Install subversion and rsync to Server yum: name="{{item}}" state=latest update_cache=yes with_items: - subversion - rsync
Again really basic things. Remove directory and export the tag defined in the playbook.
- name: Delete tag folder {{tag}} if exists file: path: "/tmp/{{tag}}" state: absent - name: Export Subversion tag {{tag}} subversion: repo: svn://{{testsvn}}/{{tag}} dest: /tmp/{{tag}}
Here I look the earlier created tag which contains zip files, look all of them and register them into variable.
- name: Register zips to a variable find: paths: "/tmp/{{tag}}/" patterns: "*.zip" register: install_zip
As I want only to copy the zip files from subversion export directory to the installation directory I found rsync to be good for that purpose. With rsync you need to use delegate_to parameter so it is done on destination server.
- name: Copy files from tag to installation folder synchronize: mode: push src: /tmp/{{tag}}/ dest: "{{ricef_dir}}" rsync_opts: - "--include=*.zip" delegate_to: "{{ inventory_hostname }}"
As I don’t want to login with apps user and instead use become_user this was one way to get the user home variable registered. This is needed for the concurrent request execution to have environment variables loaded.
- name: grep and register shell: > egrep "^{{ ap_user }}:" /etc/passwd | awk -F: '{ print $6 }' changed_when: false register: user_home
I have changed the three different types of customizations to TYPE1, TYPE2 and TYPE3 but we have three different customization areas and zip files always contain their respective type in the name.
Each type loops now through (with_items) the files we earlier registered in the variable install_zip. When the item matches to specific type it submits the CONCSUB (when part).
Also we submit this using the application owner user (ap_user) and source the shell when submitting the CONCSUB. All other variables are defined in the group_vars file.
- name: Install TYPE1 zips shell: source "{{user_home.stdout}}"/.bash_profile && CONCSUB apps/"{{apps_pass}}" SYSADMIN "System Administrator" "{{apps_user}}" \ WAIT=N CONCURRENT XBOL XBOCOD "{{run_date|default ('')}}" '$TYPE1_TOP/install' "{{item.path | basename}}" "{{type1_pass}}" '"{{db_host}}"' '"{{db_port}}"' \ '"{{db_sid}}"' with_items: "{{install_zip.files}}" when: item.path | search("type1") become: true become_user: "{{ap_user}}" - name: Install TYPE2 zips shell: source "{{user_home.stdout}}"/.bash_profile && CONCSUB apps/"{{apps_pass}}" SYSADMIN "System Administrator" "{{apps_user}}" \ WAIT=N CONCURRENT XBOL XBOCOD "{{run_date|default ('')}}" '$TYPE2_TOP/install' "{{item.path | basename}}" "{{type2_pass}}" '"{{db_host}}"' '"{{db_port}}"' \ '"{{db_sid}}"' with_items: "{{install_zip.files}}" when: item.path | search("type2") become: true become_user: "{{ap_user}}" - name: Install TYPE3 zips shell: source "{{user_home.stdout}}"/.bash_profile && CONCSUB apps/"{{apps_pass}}" SYSADMIN "System Administrator" "{{apps_user}}" \ WAIT=N CONCURRENT XBOL XBOCOD "{{run_date|default ('')}}" '$TYPE3_TOP/install' "{{item.path | basename}}" "{{type3_pass}}" '"{{db_host}}"' '"{{db_port}}"' \ '"{{db_sid}}"' with_items: "{{install_zip.files}}" when: item.path | search("type3") become: true become_user: "{{ap_user}}"
This is just for cleanup.
- name: Removing temporary files file: path: "/tmp/{{tag}}" state: absent
We have another playbook when installing single customization but it follows the same logic. This one is used to load all customizations for specific release and is called using ansible-playbook:
ansible-playbook tag2UAT.yml –ask-vault-pass –extra-vars “tag=REL_2017_12_1 apps_user=MY_APPS_USER”
So the only variables I pass are tag and my own username. All passwords and other environment variables are defined in ansible-vault file group_vars/UAT and so on. If I would want to schedule the concurrents I would pass one more variable for the date.
Even though this is just basic level scripting it has helped us a lot to reduce manual tasks and automate tasks which are error prone.
Last time I showed how to provision Autonomous Database Serverless (ADB-S) on Google Cloud. This…
I bet few years back folks didn't expect that by 2024 we would be able…
This will NOT be a technical walkthrough on Oracle Database@Azure but rather my opinions and…
Recently OCI announced small but VERY useful service, IP Address Insights. Why this matters? I've…