#
# RedHat ubi9 (with init) docker image:
#
kaau@OCLT71159526 ~ $ docker images
                                                                                  i Info →   U  In Use
IMAGE                                                 ID             DISK USAGE   CONTENT SIZE   EXTRA
registry.access.redhat.com/ubi9/ubi-init:latest       78a0a01dac2e        337MB         84.6MB

kaau@OCLT71159526 ~ $ mkdir -p ${HOME}/demo/mnt
kaau@OCLT71159526 ~ $ tree ${HOME}/demo
/home/kaau/demo
└── mnt
2 directories, 0 files

#
# docker-compose.yml:
#
kaau@OCLT71159526 ~ $ cd demo
kaau@OCLT71159526 ~/demo $ vi docker-compose.yml 
::
::

kaau@OCLT71159526 ~/demo $ cat docker-compose.yml 
[[blue:services:]]
[[blue:  ansible-ctrl:]]
[[blue:    image: registry.access.redhat.com/ubi9/ubi:latest]]
[[blue:    container_name: ansible-ctrl]]
[[blue:    hostname: ansible-ctrl.srv.bmogc.net]]
[[blue:    privileged: true]]
[[blue:    tmpfs:]]
[[blue:      - /run]]
[[blue:    volumes:]]
[[blue:      - ./mnt:/mnt]]
[[blue:    command: /sbin/init]]
[[blue:    post_start:]]
[[blue:      - command: ['subscription-manager', 'register', '--username', 'kianming.aau@bmo.com', '--password', 'myRedHatpassw0rd' ]]]
[[blue:      - command: ['dnf', 'update', '--assumeyes']]]
[[blue:      - command: ['dnf', 'install', '--assumeyes', 'python3-pip']]]
[[blue:      - command: ['pip3', 'install', '--upgrade', 'pip', 'setuptools', 'wheel']]]
[[blue:      - command: ['pip3', 'install', 'ansible']]]
[[blue:      - command: ['ansible-playbook', '/mnt/ansible-ctrl-playbook.yml']]]
[[blue:    environment:]]
[[blue:      HTTPS_PROXY: http://kaau:Airp0rt2025_@ebcswg.bmogc.net:8080]]
[[blue:    networks:]]
[[blue:      backend:]]
[[blue:        ipv4_address: 172.20.0.2]]
[[blue:  ansible-tgt:]]
[[blue:    image: registry.access.redhat.com/ubi9/ubi-init:latest]]
[[blue:    container_name: ansible-tgt]]
[[blue:    hostname: ansible-tgt.srv.bmogc.net]]
[[blue:    privileged: true]]
[[blue:    tmpfs:]]
[[blue:      - /run]]
[[blue:    volumes:]]
[[blue:      - ./mnt:/mnt]]
[[blue:    command: /sbin/init]]
[[blue:    post_start:]]
[[blue:      - command: ['subscription-manager', 'register', '--username', 'kianming.aau@bmo.com', '--password', 'myRedHatpassw0rd' ]]]
[[blue:      - command: ['dnf', 'update', '--assumeyes']]]
[[blue:      - command: ['dnf', 'install', '--assumeyes', 'python3-pip']]]
[[blue:      - command: ['pip3', 'install', '--upgrade', 'pip', 'setuptools', 'wheel']]]
[[blue:      - command: ['pip3', 'install', 'ansible']     # install it just to run the ansible-tgt-playbook.yml]]
[[blue:      - command: ['ansible-playbook', '/mnt/ansible-tgt-playbook.yml']]]
[[blue:    environment:]]
[[blue:      HTTPS_PROXY: http://kaau:Airp0rt2025_@ebcswg.bmogc.net:8080]]
[[blue:    networks:]]
[[blue:      backend:]]
[[blue:        ipv4_address: 172.20.0.3]]
[[blue:networks:]]
[[blue:  backend:]]
[[blue:    driver: bridge]]
[[blue:    ipam:]]
[[blue:      driver: default]]
[[blue:      config:]]
[[blue:        - subnet: 172.20.0.0/28]]
[[blue:          gateway: 172.20.0.1]]

#
# populate repos and files:
#
kaau@OCLT71159526 ~ $ cd ${HOME}/demo/mnt
kaau@OCLT71159526 ~/demo/mnt $ git clone https://github.com/BMO-Prod/NACBSRE_sre_cac_86039.git
Cloning into 'NACBSRE_sre_cac_86039'...
remote: Enumerating objects: 13731, done.
remote: Counting objects: 100% (1421/1421), done.
remote: Compressing objects: 100% (412/412), done.
remote: Total 13731 (delta 1216), reused 1009 (delta 1009), pack-reused 12310 (from 3)
Receiving objects: 100% (13731/13731), 4.65 MiB | 1.64 MiB/s, done.
Resolving deltas: 100% (7770/7770), done.

kaau@OCLT71159526 ~/demo/mnt $ git clone https://github.com/BMO-Prod/NACBSRE_sre_client_app_86039.git
Cloning into 'NACBSRE_sre_client_app_86039'...
remote: Enumerating objects: 1718, done.
remote: Counting objects: 100% (226/226), done.
remote: Compressing objects: 100% (66/66), done.
remote: Total 1718 (delta 193), reused 161 (delta 159), pack-reused 1492 (from 2)
Receiving objects: 100% (1718/1718), 621.77 KiB | 1.30 MiB/s, done.
Resolving deltas: 100% (850/850), done.

kaau@OCLT71159526 ~/demo/mnt $ ls -l
drwxr-xr-x 13 kaau kaau 4096 May 10 16:47 NACBSRE_sre_cac_86039
drwxr-xr-x 14 kaau kaau 4096 May 11 00:11 NACBSRE_sre_client_app_86039
-rw-r--r--  1 kaau kaau 3107 May 11 00:46 ansible-ctrl-playbook.yml
-rw-r--r--  1 kaau kaau  996 May 10 15:35 ansible-tgt-playbook.yml
-rw-r--r--  1 kaau kaau  427 May 10 16:49 ansible.cfg
-rw-------  1 kaau kaau  411 May 10 13:13 ansible_id_ed25519.key
-rw-------  1 kaau kaau  102 May 10 13:13 ansible_id_ed25519.pub
lrwxrwxrwx  1 kaau kaau   22 May 10 14:44 authorized_keys -> ansible_id_ed25519.pub
-rw-r--r--  1 kaau kaau  263 May 11 00:16 requirements.yml

kaau@OCLT71159526 ~/demo/mnt $ cat ansible-ctrl-playbook.yml 
[[blue:---]]
[[blue:  - name: dummy.dummy.com]]
[[blue:    hosts: localhost]]
[[blue:    remote_user: root]]
[[blue:    vars:]]
[[blue:      USER: ansible]]
[[blue:    tasks:]]
[[blue:      - name: dnf install -y utilities]]
[[blue:        dnf: ]]
[[blue:          name: []]
[[blue:            procps-ng, unzip, git, xz, cpio, sudo, wget, vim-enhanced, net-tools, bind-utils, hostname,]]
[[blue:            lsof, sudo, rsync, gettext, ncurses, dnf-utils, make]]
[[blue:          ]]]
[[blue:          state: present]]
[[blue:      - name: pip3 install jsonschema                                                    # for sre_data_validation]]
[[blue:        pip: ]]
[[blue:          name: jsonschema]]
[[blue:          executable: pip3]]
[[blue:      - name: create user {{ USER }}]]
[[blue:        user: name={{USER}} home=/home/{{USER}} shell=/bin/bash]]
[[blue:      - name: copy /mnt/ansible_id_ed25519.key /tmp/ansible_id_ed25519.key              # SSH private key]]
[[blue:        copy: src=/mnt/ansible_id_ed25519.key dest=/tmp/ansible_id_ed25519.key owner={{USER}} group={{USER}} mode=0600]]
[[blue:      - name: /home/{{USER}}/vault.nfo]]
[[blue:        lineinfile: path=/home/{{USER}}/vault.nfo line='vaultPassw0rd' create=yes]]
[[blue:      - name: /home/{{USER}}/.bash_profile]]
[[blue:        lineinfile: path=/home/{{USER}}/.bash_profile line='export ANSIBLE_VAULT_PASSWORD_FILE=/home/{{USER}}/vault.nfo' create=yes]]
[[blue:]]
[[blue:      - name: ln -nfs /mnt/NACBSRE_sre_cac_86039 /home/{{USER}}/NACBSRE_sre_cac_86039]]
[[blue:        file: path=/home/{{USER}}/NACBSRE_sre_cac_86039 src=/mnt/NACBSRE_sre_cac_86039 force=yes owner={{USER}} group={{USER}} follow=false state=link]]
[[blue:      - name: mkdir /mnt/NACBSRE_sre_cac_86039/ansible_collections]]
[[blue:        file: path=/mnt/NACBSRE_sre_cac_86039/ansible_collections owner={{USER}} group={{USER}} mode='0755' state=directory]]
[[blue:      - name: symlink nacbsre in /mnt/NACBSRE_sre_cac_86039/ansible_collections]]
[[blue:        file: src=../nacbsre dest=/mnt/NACBSRE_sre_cac_86039/ansible_collections/nacbsre owner={{USER}} group={{USER}} state=link ]]
[[blue:]]
[[blue:      - name: ln -nfs /mnt/NACBSRE_sre_client_app_86039 /home/{{USER}}/NACBSRE_sre_client_app_86039]]
[[blue:        file: path=/home/{{USER}}/NACBSRE_sre_client_app_86039 src=/mnt/NACBSRE_sre_client_app_86039 force=yes owner={{USER}} group={{USER}} follow=false state=link]]
[[blue:      - name: Assign ansible-tgt IP address in NACBSRE_sre_client_app_86039/inventories/containers]]
[[blue:        replace:]]
[[blue:          path: /mnt/NACBSRE_sre_client_app_86039/inventories/containers]]
[[blue:          regexp: 'ansible_host=([0-9]{1,3}\.){3}[0-9]{1,3} ansible_port=2222 ansible_user=ansible']]
[[blue:          replace: 'ansible_host=172.20.0.3 ansible_port=22 ansible_user=root']]
[[blue:      - name: copy /mnt/ansible.cfg /mnt/NACBSRE_sre_client_app_86039/.ansible.cfg]]
[[blue:        copy: src=/mnt/ansible.cfg dest=/mnt/NACBSRE_sre_client_app_86039/ansible.cfg owner={{USER}} group={{USER}} mode=0644]]
[[blue:      - name: copy /mnt/requirements.yml /mnt/NACBSRE_sre_client_app_86039/collections/requirements.yml]]
[[blue:        copy: src=/mnt/requirements.yml dest=/mnt/NACBSRE_sre_client_app_86039/collections/requirements.yml owner={{USER}} group={{USER}} mode=0644]]

kaau@OCLT71159526 ~/demo/mnt $ cat ansible-tgt-playbook.yml 
[[blue:---]]
[[blue:  - name: dummy.dummy.com]]
[[blue:    hosts: localhost]]
[[blue:    remote_user: root]]
[[blue:    tasks:]]
[[blue:      - name: dnf install -y openssh-server]]
[[blue:        dnf: name=openssh-server state=present]]
[[blue:      - name: /etc/ssh/sshd_config]]
[[blue:        lineinfile: path=/etc/ssh/sshd_config regexp="^#PermitRootLogin prohibit-password" line="PermitRootLogin yes"]]
[[blue:      - name: systemctl restart sshd.service]]
[[blue:        ansible.builtin.service: name=sshd state=restarted]]
[[blue:      - name: dnf install -y utilities]]
[[blue:        dnf: ]]
[[blue:          name: [ ]]
[[blue:            procps-ng, unzip, xz, cpio, sudo, wget, vim-enhanced, net-tools, bind-utils,]]
[[blue:            hostname, lsof, rsync, gettext, ncurses, dnf-utils, git, which, psmisc ]]
[[blue:          ]]]
[[blue:          state: present]]
[[blue:      - name: mkdir /root/.ssh]]
[[blue:        file: path=/root/.ssh owner=root group=root mode='0700' state=directory]]
[[blue:      - name: copy /mnt/authorized_keys /root/.ssh/authorized_keys]]
[[blue:        copy: src=/mnt/authorized_keys dest=/root/.ssh/authorized_keys owner=root group=root mode='0600']]

kaau@OCLT71159526 ~/demo/mnt $ cat ansible.cfg 
[[blue:[defaults]]]
[[blue:collections_paths = /home/ansible/NACBSRE_sre_cac_86039:~/.ansible/collections:/usr/share/ansible/collections]]
[[blue:roles_path = ../requirements_roles/Products_Linux_Automation/roles:roles/Products_Linux_Automation/roles]]
[[blue:filter_plugins = ../requirements_roles/Products_Linux_Automation/filter_plugins:roles/Products_Linux_Automation/filter_plugins]]
[[blue:]]
[[blue:[ssh_connection]]]
[[blue:ssh_args = -o ControlMaster=auto -o ControlPersist=600s]]

kaau@OCLT71159526 ~/demo/mnt $ cat requirements.yml 
[[blue:---]]
[[blue:## for local developer testing]]
[[blue:collections:]]
[[blue:  - source: /home/ansible/NACBSRE_sre_cac_86039/nacbsre/cac_collection]]
[[blue:    type: dir]]

[[blue:#collections:]]
[[blue:##  - name: https://github.com/BMO-Prod/NACBSRE_sre_cac_86039.git#/nacbsre]]
[[blue:##    type: git]]
[[blue:##    #version: v7.0.0]]
...
Spin up the containers:
```bash
kaau@OCLT71159526 ~/demo/mnt $ cd ..
kaau@OCLT71159526 ~/demo $ docker compose up --detach
 ✔ Network demo_backend Created                                                                                                0.3s
 ✔ Container controller Started                                                                                              138.5s
 ✔ Container target     Started                                                                                              214.5s

kaau@OCLT71159526 ~/demo $ docker compose ps --all
NAME           IMAGE                                             COMMAND        SERVICE        CREATED         STATUS         PORTS
ansible-ctrl   registry.access.redhat.com/ubi9/ubi:latest        "/sbin/init"   ansible-ctrl   3 minutes ago   Up 3 minutes   
ansible-tgt    registry.access.redhat.com/ubi8/ubi-init:latest   "/sbin/init"   ansible-tgt    3 minutes ago   Up 3 minutes   

Login into the ansible-ctrl:

kaau@OCLT71159526 ~/demo $ docker compose exec --interactive --tty ansible-ctrl bash                         ---or docker exec -it ansible-ctrl bash

[root@ansible-ctrl /]# hostname --fqdn; hostname --ip-address
ansible-ctrl.srv.bmogc.net
172.20.0.2

[root@ansible-ctrl /]# host ansible-tgt.srv.bmogc.net                                                        ---hostname lookup: works
ansible-tgt.srv.bmogc.net has address 172.20.0.3

[root@ansible-ctrl /]# id -a ansible
uid=1000(ansible) gid=1000(ansible) groups=1000(ansible)

#
# user "ansible":
#
[root@ansible-ctrl /]# su - ansible

[ansible@ansible-ctrl ~]$ ls -la
drwx------ 2 ansible ansible 4096 May 11 03:53 .
drwxr-xr-x 1 root    root    4096 May 11 03:53 ..
-rw-r--r-- 1 ansible ansible   18 Feb 15  2024 .bash_logout
-rw-r--r-- 1 ansible ansible  200 May 11 03:53 .bash_profile
-rw-r--r-- 1 ansible ansible  492 Feb 15  2024 .bashrc
lrwxrwxrwx 1 ansible ansible   26 May 11 03:53 NACBSRE_sre_cac_86039 -> /mnt/NACBSRE_sre_cac_86039
lrwxrwxrwx 1 ansible ansible   33 May 11 03:53 NACBSRE_sre_client_app_86039 -> /mnt/NACBSRE_sre_client_app_86039
-rw-r--r-- 1 root    root      14 May 11 03:53 vault.nfo

[ansible@ansible-ctrl ~]$ env | grep ^ANSIBLE_VAULT_PASSWORD_FILE
ANSIBLE_VAULT_PASSWORD_FILE=/home/ansible/vault.nfo
[ansible@ansible-ctrl ~]$ ls -l ${ANSIBLE_VAULT_PASSWORD_FILE}
-rw-r--r-- 1 root root 14 May 10 19:43 /home/ansible/vault.nfo

[ansible@ansible-ctrl ~]$ ls -l /tmp/ansible_id_ed25519.key 
-rw------- 1 ansible ansible 411 May 10 20:10 /tmp/ansible_id_ed25519.key                                    ---SSH private key

[ansible@ansible-ctrl ~]$ cd NACBSRE_sre_client_app_86039
[ansible@ansible-ctrl NACBSRE_sre_client_app_86039]$ ls -l
-rw-r--r--  1 ansible ansible  291 May 10 17:07 ICM_inventorylist.json
-rw-r--r--  1 ansible ansible 2136 May 10 17:07 ICM_joblist.json
-rw-r--r--  1 ansible ansible 5377 May 10 17:07 README_product-lifecycle-guide.md
-rw-r--r--  1 ansible ansible  266 May 10 17:07 SSP_inventorylist.json
-rw-r--r--  1 ansible ansible 1033 May 10 17:07 SSP_joblist.json
-rw-r--r--  1 ansible ansible  427 May 10 20:41 ansible.cfg
drwxr-xr-x  3 ansible ansible 4096 May 10 17:07 artifacts
drwxr-xr-x  2 ansible ansible 4096 May 10 20:46 collections
-rw-r--r--  1 ansible ansible  318 May 10 17:07 config_report_generation.yml
-rw-r--r--  1 ansible ansible 5839 May 10 17:07 devtools_setup.yml
drwxr-xr-x  4 ansible ansible 4096 May 10 17:07 docs
-rw-r--r--  1 ansible ansible 1303 May 10 17:07 driftdetector_report.yml
-rw-r--r--  1 ansible ansible  271 May 10 17:07 driftdetector_update.yml
drwxr-xr-x  2 ansible ansible 4096 May 10 17:07 files
drwxr-xr-x  9 ansible ansible 4096 May 10 17:07 group_vars
drwxr-xr-x  2 ansible ansible 4096 May 10 17:07 host_vars
-rw-r--r--  1 ansible ansible  385 May 10 17:07 ihs_config.yml
-rw-r--r--  1 ansible ansible  311 May 10 17:07 ihs_install.yml
-rw-r--r--  1 ansible ansible  330 May 10 17:07 ihs_operation.yml
drwxr-xr-x  2 ansible ansible 4096 May 11 04:02 inventories
-rw-r--r--  1 ansible ansible  440 May 10 17:07 linux_config.yml
-rw-r--r--  1 ansible ansible  681 May 10 17:07 managed_files_deploy.yml
-rw-r--r--  1 ansible ansible  302 May 10 17:07 mq_install.yml
-rw-r--r--  1 ansible ansible  322 May 10 17:07 mqclient_install.yml
-rw-r--r--  1 ansible ansible  482 May 10 17:07 oracle_client.yml
-rw-r--r--  1 ansible ansible  486 May 10 17:07 oracle_server.yml
-rw-r--r--  1 ansible ansible  273 May 10 17:07 os_hardening.yml
-rw-r--r--  1 ansible ansible  405 May 10 17:07 pkg_deploy.yml
-rw-r--r--  1 ansible ansible  272 May 10 17:07 pkg_download.yml
drwxr-xr-x 13 ansible ansible 4096 May 10 17:07 powerbi_reports
-rw-r--r--  1 ansible ansible  443 May 10 17:07 qmgrs_deploy.yml
-rw-r--r--  1 ansible ansible  343 May 10 17:07 qmgrs_operation.yml
-rw-r--r--  1 ansible ansible  305 May 10 17:07 report_generation.yml
drwxr-xr-x  2 ansible ansible 4096 May 10 17:07 roles
-rw-r--r--  1 ansible ansible  464 May 10 17:07 service_operation.yml
drwxr-xr-x  5 ansible ansible 4096 May 10 17:07 srefiles
-rw-r--r--  1 ansible ansible 1135 May 10 17:07 tomcat_build.yml
-rw-r--r--  1 ansible ansible 1580 May 10 17:07 was_config.yml
-rw-r--r--  1 ansible ansible  309 May 10 17:07 was_extract_pfbc.yml
-rw-r--r--  1 ansible ansible  492 May 10 17:07 was_install.yml
-rw-r--r--  1 ansible ansible  352 May 10 17:07 was_operation.yml
-rw-r--r--  1 ansible ansible 1264 May 10 17:07 was_operation_example1.yml
-rw-r--r--  1 ansible ansible  434 May 10 17:07 was_patch_example.yml

[ansible@ansible-ctrl NACBSRE_sre_client_app_86039]$ cat ansible.cfg 
[[blue:[defaults]]]
[[blue:collections_paths = /home/ansible/NACBSRE_sre_cac_86039:~/.ansible/collections:/usr/share/ansible/collections]]
[[blue:roles_path = ../requirements_roles/Products_Linux_Automation/roles:roles/Products_Linux_Automation/roles]]
[[blue:filter_plugins = ../requirements_roles/Products_Linux_Automation/filter_plugins:roles/Products_Linux_Automation/filter_plugins]]
[[blue:[ssh_connection]]]
[[blue:ssh_args = -o ControlMaster=auto -o ControlPersist=600s]]
[[blue:]]
[[blue:[ansible@ansible-ctrl NACBSRE_sre_client_app_86039]$ cat collections/requirements.yml ]]
[[blue:---]]
[[blue:## for local developer testing]]
[[blue:collections:]]
[[blue:  - source: /home/ansible/NACBSRE_sre_cac_86039/nacbsre/cac_collection]]
[[blue:    type: dir]]
[[blue:#collections:]]
[[blue:##  - name: https://github.com/BMO-Prod/NACBSRE_sre_cac_86039.git#/nacbsre]]
[[blue:##    type: git]]
[[blue:##    #version: v7.0.0]]
[[blue:...]]

[ansible@ansible-ctrl NACBSRE_sre_client_app_86039]$ grep ansible-tgt inventories/containers 
ansible-tgt ansible_host=172.20.0.3 ansible_port=22 ansible_user=root ansible_ssh_private_key_file=/tmp/ansible_id_ed25519.key
ansible-tgt ansible_host=172.20.0.3 ansible_port=22 ansible_user=root ansible_ssh_private_key_file=/tmp/ansible_id_ed25519.key

[ansible@ansible-ctrl NACBSRE_sre_client_app_86039]$ which ansible ansible-playbook ansible-galaxy 
/usr/local/bin/ansible
/usr/local/bin/ansible-playbook
/usr/local/bin/ansible-galaxy

[ansible@ansible-ctrl NACBSRE_sre_client_app_86039]$ ansible-galaxy collection list | grep -B1 nacbsre
----------------------------- -------
nacbsre.cac_collection        8.1.0  

#
# run:
#
[ansible@ansible-ctrl NACBSRE_sre_client_app_86039]$ ansible-playbook driftdetector_update.yml -i inventories/containers \
                                                     [[yellow:-e "GROUP_LIMIT=rhel9 sre_pkg_download_no_log=false"]]                \
                                                     [[yellow:--skip-tags sendemail -vv --diff --check]]
  ansible collection location = /home/ansible/NACBSRE_sre_cac_86039:/home/ansible/.ansible/collections:/usr/share/ansible/collections
  executable location = /usr/local/bin/ansible-playbook
  python version = 3.9.25 (main, Apr 17 2026, 00:00:00) [GCC 11.5.0 20240719 (Red Hat 11.5.0-11)] (/usr/bin/python3)
  jinja version = 3.1.6
  libyaml = True
Using /mnt/NACBSRE_sre_client_app_86039/ansible.cfg as config file
Skipping callback 'default', as we already have a stdout callback.
Skipping callback 'minimal', as we already have a stdout callback.
Skipping callback 'oneline', as we already have a stdout callback.
PLAYBOOK: driftdetector_update.yml *************************************************************************************************
1 plays in driftdetector_update.yml
PLAY [Driftdetector Update] ********************************************************************************************************
::
::
::
::
TASK [nacbsre.cac_collection.sre_driftdetector : mark driftdetector update as completed] *******************************************
task path: /home/ansible/NACBSRE_sre_cac_86039/ansible_collections/nacbsre/cac_collection/roles/sre_driftdetector/tasks/main.yml:128
ok: [ansible-tgt] => {"ansible_facts": {"sre_driftdetector_completed": true}, "changed": false}

PLAY RECAP **************************************************************************************************************************
ansible-tgt                : ok=81   changed=24   unreachable=0    failed=0    skipped=63   rescued=0    ignored=0