summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ansible-practice/02-playbook-list-files.yml2
-rw-r--r--ansible-practice/04-playbook-create-file.yml2
-rw-r--r--ansible-practice/05-playbook-add-content-to-created-file.yml2
-rw-r--r--ansible-practice/system/12-replace-text.yml42
-rw-r--r--ansible-practice/system/12-replace-text.yml~15
-rw-r--r--ansible-practice/system/13-create-update-user.yml42
-rw-r--r--ansible-practice/system/13-create-update-user.yml~8
-rw-r--r--ansible-practice/system/14-verify-user.yml28
-rw-r--r--ansible-practice/system/14-verify-user.yml~19
-rw-r--r--ansible_stuff.org287
-rw-r--r--regex_test.py41
-rw-r--r--regex_test.py~12
12 files changed, 473 insertions, 27 deletions
diff --git a/ansible-practice/02-playbook-list-files.yml b/ansible-practice/02-playbook-list-files.yml
index 1163a2d..9240059 100644
--- a/ansible-practice/02-playbook-list-files.yml
+++ b/ansible-practice/02-playbook-list-files.yml
@@ -8,7 +8,7 @@
# connection: local
tasks:
- name: "just execute a ls -lrt command"
- shell: "ls -lrt"
+ ansible.builtin.shell: "ls -lrt"
register: "output"
- debug: var=output.stdout_lines
diff --git a/ansible-practice/04-playbook-create-file.yml b/ansible-practice/04-playbook-create-file.yml
index d9676e9..19afb03 100644
--- a/ansible-practice/04-playbook-create-file.yml
+++ b/ansible-practice/04-playbook-create-file.yml
@@ -9,7 +9,7 @@
# connection: local
tasks:
- name: Creating an empty file
- file:
+ ansible.builtin.file:
path: "~/ansible_created_file-01.txt"
state: touch
... \ No newline at end of file
diff --git a/ansible-practice/05-playbook-add-content-to-created-file.yml b/ansible-practice/05-playbook-add-content-to-created-file.yml
index 60b1c05..decf848 100644
--- a/ansible-practice/05-playbook-add-content-to-created-file.yml
+++ b/ansible-practice/05-playbook-add-content-to-created-file.yml
@@ -8,7 +8,7 @@
connection: local
tasks:
- name: Creating a file with content
- copy:
+ ansible.builtin.copy:
dest: "~/tmp/temp_files/ansible_created_file-02.txt"
content: |
line 01
diff --git a/ansible-practice/system/12-replace-text.yml b/ansible-practice/system/12-replace-text.yml
new file mode 100644
index 0000000..4ae07a6
--- /dev/null
+++ b/ansible-practice/system/12-replace-text.yml
@@ -0,0 +1,42 @@
+#
+# https://docs.ansible.com/ansible/latest/collections/ansible/builtin/replace_module.html
+#
+---
+- name: "12 - custom ansible - replace text"
+ hosts: dev
+ tasks:
+ - name: update slackpg blacklist - blacklist kernels
+ ansible.builtin.replace:
+ path: "{{ backup_etc_dir }}/blacklist"
+ regexp: '#kernel'
+ replace: 'kernel'
+ tags: ['slackpkg_blacklist_kernels']
+
+ - name: update slackpg blacklist - blacklist SBo packages
+ ansible.builtin.replace:
+ path: "{{ backup_etc_dir }}/blacklist"
+ regexp: '#\[0-9\]'
+ replace: '[0-9]'
+ tags: ['slackpkg_blacklist_sbo']
+
+ # this will add a line to a file if it does not exist !!
+ - name: update slackpg blacklist - blacklist alienbob packages
+ ansible.builtin.lineinfile:
+ path: "{{ backup_etc_dir }}/blacklist"
+ search_string: '\[0-9\]\+alien'
+ line: '[0-9]+alien'
+ tags: ['slackpkg_blacklist_alien']
+
+ - name: update slackpg blacklist - blacklist sbopkg packages
+ ansible.builtin.lineinfile:
+ path: "{{ backup_etc_dir }}/blacklist"
+ search_string: 'sbopkg'
+ line: 'sbopkg'
+ tags: ['slackpkg_blacklist_sbopkg']
+
+ - name: update slackpg blacklist - blacklist kde packages
+ ansible.builtin.lineinfile:
+ path: "{{ backup_etc_dir }}/blacklist"
+ search_string: 'kde\/'
+ line: 'kde/'
+ tags: ['slackpkg_blacklist_kde']
diff --git a/ansible-practice/system/12-replace-text.yml~ b/ansible-practice/system/12-replace-text.yml~
new file mode 100644
index 0000000..1848ea6
--- /dev/null
+++ b/ansible-practice/system/12-replace-text.yml~
@@ -0,0 +1,15 @@
+---
+- name: "12 - custom ansible - replace text"
+ hosts: dev
+ tasks:
+ - name: update slackpg blacklist
+ ansible.builtin.replace:
+ path: "{{ backup_etc_dir }}/blacklist"
+ # regexp: '^#(kernel-.+)$'
+ # replace: '\1'
+ regexp: "kernel"
+ replace: "kerneldaryll"
+ owner: root
+ group: root
+ backup: yes
+ tags: ['slackpkg_blacklist']
diff --git a/ansible-practice/system/13-create-update-user.yml b/ansible-practice/system/13-create-update-user.yml
new file mode 100644
index 0000000..b00af34
--- /dev/null
+++ b/ansible-practice/system/13-create-update-user.yml
@@ -0,0 +1,42 @@
+#
+# https://www.howtouselinux.com/post/create-user-with-ansible
+# https://docs.ansible.com/ansible/latest/collections/ansible/builtin/user_module.html
+# https://docs.ansible.com/ansible/latest/playbook_guide/playbooks_variables.html
+# https://docs.ansible.com/ansible/latest/collections/community/crypto/openssh_keypair_module.html
+# https://www.codesandnotes.be/2020/01/13/generate-ssh-keys-using-ansible/
+#
+---
+- name: "13 - custom ansible - create/update user"
+ hosts: dev
+ become: yes # Run tasks with root/sudo privileges
+ vars:
+ username: testuser1
+ password: mypassword
+ passphrase: one two three
+
+ tasks:
+ - name: create user
+ ansible.builtin.user:
+ name: "{{ username }}"
+ password: "{{ password | password_hash('sha512') }}" # encrypted password
+ state: present # ensure the user is present
+ createhome: true # create the users home directory
+ shell: /bin/bash
+ group: users # slackware default
+ groups: audio,cdrom,floppy,input,lp,netdev,plugdev,power,scanner,video,wheel
+ generate_ssh_key: true
+ ssh_key_type: ed25519
+ ssh_key_passphrase: "{{ passphrase }}"
+
+#
+# received the following when running this playbook:
+#
+# TASK [create user] *************************************************
+#
+# [DEPRECATION WARNING]: Encryption using the Python crypt module is
+# deprecated. The Python crypt module is deprecated and will be removed
+# from Python 3.13. Install the passlib library for continued encryption
+# functionality. This feature will be removed in version
+# 2.17. Deprecation warnings can be disabled by setting
+# deprecation_warnings=False in ansible.cfg.
+#
diff --git a/ansible-practice/system/13-create-update-user.yml~ b/ansible-practice/system/13-create-update-user.yml~
new file mode 100644
index 0000000..d7fc422
--- /dev/null
+++ b/ansible-practice/system/13-create-update-user.yml~
@@ -0,0 +1,8 @@
+#
+# https://www.howtouselinux.com/post/create-user-with-ansible
+#
+---
+- name: "13 - custom ansible - create/update user"
+ hosts: dev
+ become: yes # Run tasks with root/sudo privileges
+ tasks:
diff --git a/ansible-practice/system/14-verify-user.yml b/ansible-practice/system/14-verify-user.yml
new file mode 100644
index 0000000..8b785b1
--- /dev/null
+++ b/ansible-practice/system/14-verify-user.yml
@@ -0,0 +1,28 @@
+#
+# https://www.howtouselinux.com/post/create-user-with-ansible
+# https://docs.ansible.com/ansible/latest/collections/ansible/builtin/user_module.html
+# https://docs.ansible.com/ansible/latest/playbook_guide/playbooks_variables.html
+#
+---
+- name: "14 - custom ansible - verifyl user"
+ hosts: dev
+ become: yes # Run tasks with root/sudo privileges
+ vars:
+ username: testuser1
+
+ tasks:
+ - name: check if user exists
+ ansible.builtin.command: id {{ username }}
+# ansible.builtin.shell: id {{ username }}
+ register: user_check
+ ignore_errors: true
+
+ - name: display user information
+ ansible.builtin.debug:
+ msg: user '{{ username }}' exists !
+ when: user_check.rc == 0
+
+ - name: display error message if user does not exist
+ ansible.builtin.debug:
+ msg: user '{{ username }}' does not exist !
+ when: user_check.rc != 0
diff --git a/ansible-practice/system/14-verify-user.yml~ b/ansible-practice/system/14-verify-user.yml~
new file mode 100644
index 0000000..4be4c36
--- /dev/null
+++ b/ansible-practice/system/14-verify-user.yml~
@@ -0,0 +1,19 @@
+#
+# https://www.howtouselinux.com/post/create-user-with-ansible
+#
+---
+- name: "14 - custom ansible - verifyl user"
+ hosts: dev
+ become: yes # Run tasks with root/sudo privileges
+
+ tasks:
+ - name: check if user exists
+ ansible.builtin.shell:
+ register: user_check
+ ignore_errors: true
+
+ - name: display user information
+ ansible.builtin.debug:
+ msg: "user '{{ username }}' exists !"
+ when: user_check.rc == 0
+
diff --git a/ansible_stuff.org b/ansible_stuff.org
index 3b161ab..f427ae8 100644
--- a/ansible_stuff.org
+++ b/ansible_stuff.org
@@ -1,7 +1,10 @@
-* notes on ansible
+#+STARTUP: overview
+#+TITLE: my scrappy ansible notes
+#+AUTHOR: blizzack
-* installing ansible via pip
-** <2023-10-23 Mon>
+* <2023-10-23 Mon>
+
+- installing ansible via pip
bash-5.2$ python3 -m pip install --user ansible
Collecting ansible
@@ -300,7 +303,7 @@ bash-5.2$
bash-5.2$
bash-5.2$
-** <2023-10-24 Tue>
+* <2023-10-24 Tue>
decided it would be nice to have another host to play around with so
i dusted off 'bbox' and logged into it from 'boom2'
@@ -388,7 +391,7 @@ Connection to 192.168.0.220 closed.
https://www.educba.com/ansible-hosts-file/
-** <2023-10-29 Sun>
+* <2023-10-29 Sun>
- created '~/.ansible/hosts' file like so:
@@ -444,7 +447,7 @@ ansible dev -m ping
msg: Hello Ansible World
#+end_src
-** <2023-10-30 Mon>
+* <2023-10-30 Mon>
- make sure to setup my path correctly so that the ansible executable
can be found
@@ -488,14 +491,14 @@ bash-5.2$ echo $PATH
- seems i dont understand YAML well enuf
https://docs.ansible.com/ansible/latest/reference_appendices/YAMLSyntax.html
-** <2023-11-02 Thu>
+* <2023-11-02 Thu>
some definitions of things:
- control node = my ansible server
- managed node(s) = target systems
-** <2023-11-22 Wed>
+* <2023-11-22 Wed>
did a lil research on more resources
@@ -627,7 +630,7 @@ playbook: 12-playbook-copy-directory.yml
ansible-playbook -l dev-stations 12-playbook-copy-directory.yml
-** <2023-11-30 Thu>
+* <2023-11-30 Thu>
researching 'roles' and how to use them.
@@ -693,7 +696,7 @@ https://docs.ansible.com/ansible/latest/playbook_guide/playbooks_reuse_roles.htm
- localhost.yml
- other_hosts.yml
-** <2023-12-04 Mon>
+* <2023-12-04 Mon>
- experimented w/ using the 'inventory_hostname' above by using an
example from here:
@@ -708,7 +711,7 @@ https://docs.ansible.com/ansible/latest/playbook_guide/playbooks_reuse_roles.htm
https://github.com/cesarvr/ansible-role-hello-world
- the inet needs more simple examples like this !!
-** <2023-12-05 Tue>
+* <2023-12-05 Tue>
- How to Use Ansible Roles to Abstract your Infrastructure Environment
https://www.digitalocean.com/community/tutorials/how-to-use-ansible-roles-to-abstract-your-infrastructure-environment
@@ -730,7 +733,7 @@ https://docs.ansible.com/ansible/latest/playbook_guide/playbooks_reuse_roles.htm
https://stackoverflow.com/questions/53253879/ansible-vars-files-vs-include-vars
https://stackoverflow.com/questions/36134552/use-multiple-var-files-in-ansible-role
-** <2023-12-07 Thu>
+* <2023-12-07 Thu>
- worked w/ 'var_files' and that did not do what i expected
- playing w/ 'group_vars' directory
@@ -772,7 +775,7 @@ https://docs.ansible.com/ansible/latest/playbook_guide/playbooks_reuse_roles.htm
- so...this explains why trying to add different variablse for the
hosts in roles was painful...its bcuz its in the wrong place
-** <2023-12-08 Fri>
+* <2023-12-08 Fri>
- continued my tests of copying files and found the correct way is to
use hosts and/or group vars that can be kept in the playbook or w/
@@ -817,15 +820,14 @@ https://docs.ansible.com/ansible/latest/playbook_guide/playbooks_reuse_roles.htm
'ansible.builtin.command'
https://stackoverflow.com/questions/56663332/difference-between-shell-and-command-in-ansible
-
-** <2023-12-12 Tue>
+* <2023-12-12 Tue>
today i learned that ansible makes it a lil difficult to copy/move
files around on the controller node. they make it very apparent that
ansible is for contolling managed nodes not necessarily controlling
the control node.
-** <2023-12-13 Wed>
+* <2023-12-13 Wed>
looking at examples to update a file on a managed host
@@ -838,7 +840,7 @@ https://docs.ansible.com/ansible/latest/collections/ansible/builtin/lineinfile_m
- an online python regex syntax checker
https://pythex.org/
-** <2023-12-14 Thu>
+* <2023-12-14 Thu>
copy 'rc.firewall' from bbox to boom2:
@@ -846,11 +848,248 @@ rsync --progress -avzhr --delete -e 'ssh -i ~/.ssh/20231024bbox' dpierre@192.168
https://chmod-calculator.com/
----
-- name: "09 - custom ansible - backup system files"
- hosts: localhost
+* <2023-12-15 Fri>
+
+lol..learned of a lil abnormality w/ ansible today. while testing
+replacing contents of a file w/ the 'ansible.builtin.replace' module
+it was just not working as i expected. it seemed that the task
+completed ok but no changes took place. i was testing on a particular
+task w/in a playbook. i was calling the task like so:
+
+#+begin_example
+ ansible-playbook 11-playbook-herd-new-host.yml -b -K --tags=slackpkg_blacklist
+
+ BECOME password:
+
+ PLAY [11 - custom ansible - herd new host] ********************************************
+
+ TASK [Gathering Facts] ****************************************************************
+ ok: [192.168.0.220]
+
+ PLAY RECAP ****************************************************************************
+ 192.168.0.220 : ok=1 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
+#+end_example
+
+
+the following looks okay...but you really need to look at the above
+closely. i called the 'slackpkg_blacklist' task to be run but the
+above output does not state that the task has run.....grrr!!
+
+to debug i had to move the separate task into its own playbook and the
+error showed up like so:
+
+#+begin_example
+ $ ansible-playbook system/12-replace-text.yml -b -K
+ BECOME password:
+
+ PLAY [12 - custom ansible - replace text] ***********************************************
+
+ TASK [Gathering Facts] ******************************************************************
+ ok: [192.168.0.220]
+
+ TASK [update slackpg blacklist] *********************************************************
+ fatal: [192.168.0.220]: FAILED! => {"changed": false, "msg": "Unsupported parameters for (ansible.builtin.replace) module: tags. Supported parameters include: after, attributes, backup, before, encoding, group, mode, owner, path, regexp, replace, selevel, serole, setype, seuser, unsafe_writes, validate (attr, dest, destfile, name)."}
+
+ PLAY RECAP ******************************************************************************
+ 192.168.0.220 : ok=1 changed=0 unreachable=0 failed=1 skipped=0 rescued=0 ignored=0
+#+end_example
+
+when i looked closer at my playbook the 'tags:' directive was indented
+too much and ansible complained w/ the running playbook. which is
+nice! but... it did not complain when the task was called directly as
+part of a playbook w/ many tasks.
+
+ #+name: BAD EXAMPLE !!!!
+ #+begin_example
+ - name: update slackpg blacklist
+ ansible.builtin.replace:
+ path: "{{ backup_etc_dir }}/blacklist-list"
+ regexp: '#kernel'
+ replace: 'kernel'
+ backup: yes
+ tags: ['slackpkg_blacklist']
+ #+end_example
+
+ #+name: GOOD EXAMPLE !!!!
+ #+begin_example
+ - name: update slackpg blacklist
+ ansible.builtin.replace:
+ path: "{{ backup_etc_dir }}/blacklist-list"
+ regexp: '#kernel'
+ replace: 'kernel'
+ backup: yes
+ tags: ['slackpkg_blacklist']
+ #+end_example
+
+another crazy thing i noticed w/ the first example output above was
+that i purposed placed errors in the task to see if i'd get an error
+and still no feedback from ansible that anything went wrong.
+
+the lesson learned here:
+- looking at the CLI for awhile can make anyone skip over text on the
+ screen. when calling a task explicitly from a playbook you'll want
+ to make sure that task is explictly listed in the output !!!!
+
+** python backtrace
+
+i thought i was gonna need to use pythons regex backtrace construct
+but realized i did not need it. the following are decent resources on
+backtrace.
+
+https://www.howtouselinux.com/post/modify-files-with-ansible-lineinfile-replace-and-blockinfile
+https://www.programiz.com/python-programming/regex
+https://www.pythontutorial.net/python-regex/python-regex-backreferences/
+
+ansible replace examples:
+- https://www.linuxtechi.com/replace-strings-lines-with-ansible/
+
+* <2023-12-16 Sat>
+
+just pointing out another case of weirdness that occured as a result
+of the 'command' vs. 'shell' in a playbook.
+
+this is an example of the playbook tested:
+
+ #+name: using command module
+ #+begin_example
tasks:
- - name: backup '/etc/fstab'
- ansible.builtin.debug:
- msg: backup_etc_dir variable = {{ backup_etc_dir }}
- tags: ['fstab']
+ - name: check if user exists
+ ansible.builtin.command: id {{ username }}
+ register: user_check
+ ignore_errors: true
+
+ - name: display user information
+ ansible.builtin.debug:
+ msg: user '{{ username }}' exists !
+ when: user_check.rc == 0
+
+ - name: display error message if user does not exist
+ ansible.builtin.debug:
+ msg: user '{{ username }}' does not exist !
+ when: user_check.rc != 0
+ #+end_example
+
+ #+name: using shell module
+ #+begin_example
+ tasks:
+ - name: check if user exists
+ ansible.builtin.shell: id {{ username }}
+ register: user_check
+ ignore_errors: true
+
+ - name: display user information
+ ansible.builtin.debug:
+ msg: user '{{ username }}' exists !
+ when: user_check.rc == 0
+
+ - name: display error message if user does not exist
+ ansible.builtin.debug:
+ msg: user '{{ username }}' does not exist !
+ when: user_check.rc != 0
+ #+end_example
+
+for the ignored test that failed i noticed that the "cmd" object
+from the command module returns an array, like so:
+
+ #+name: shell module result
+ #+begin_example
+ ...
+ ...
+ TASK [check if user exists] ************************************************************
+ fatal: [192.168.0.220]: FAILED! => {"changed": true, "cmd": ["id", "testuser1"], "delta": "0:00:00.011568", "end": "2023-12-17 09:04:06.919370", "msg": "non-zero return code", "rc": 1, "start": "2023-12-17 09:04:06.907802", "stderr": "id: ‘testuser1’: no such user", "stderr_lines": ["id: ‘testuser1’: no such user"], "stdout": "", "stdout_lines": []}
+ ...ignoring
+ ...
+ ...
+ #+end_example
+
+while the same object under the shell command returns a string, like so:
+
+ #+name: shell module result
+ #+begin_example
+ ...
+ ...
+ TASK [check if user exists] ************************************************************
+ fatal: [192.168.0.220]: FAILED! => {"changed": true, "cmd": "id testuser1", "delta": "0:00:00.025297", "end": "2023-12-17 08:08:40.530399", "msg": "non-zero return code", "rc": 1, "start": "2023-12-17 08:08:40.505102", "stderr": "id: ‘testuser1’: no such user", "stderr_lines": ["id: ‘testuser1’: no such user"], "stdout": "", "stdout_lines": []}
+ ...ignoring
+ ...
+ ...
+ #+end_example
+
+just documenting this fact here cuz i have a feeling this weirdness
+will bite me in the ass someday.
+
+
+* references
+2023-12-16 -- the following is a lists of ansible related URLs compiled so far.
+
+http://mywiki.wooledge.org/BashFAQ/088
+https://assets.digitalocean.com/books/how-to-manage-remote-servers-with-ansible.pdf
+https://chmod-calculator.com/
+https://cyb.org.uk/2021/05/03/bash-productivity.html
+https://docs.ansible.com/ansible-core/2.15/reference_appendices/interpreter_discovery.html
+https://docs.ansible.com/ansible/2.7/user_guide/playbooks_variables.html#variable-precedence-where-should-i-put-a-variable
+https://docs.ansible.com/ansible/2.9/user_guide/playbooks_reuse.html
+https://docs.ansible.com/ansible/2.9/user_guide/playbooks_reuse_includes.html#including-and-importing-task-files
+https://docs.ansible.com/ansible/latest/cli/ansible-config.html
+https://docs.ansible.com/ansible/latest/collections/ansible/builtin/command_module.html
+https://docs.ansible.com/ansible/latest/collections/ansible/builtin/copy_module.html
+https://docs.ansible.com/ansible/latest/collections/ansible/builtin/debug_module.html
+https://docs.ansible.com/ansible/latest/collections/ansible/builtin/file_module.html
+https://docs.ansible.com/ansible/latest/collections/ansible/builtin/import_playbook_module.html
+https://docs.ansible.com/ansible/latest/collections/ansible/builtin/lineinfile_module.html
+https://docs.ansible.com/ansible/latest/collections/ansible/builtin/reboot_module.html
+https://docs.ansible.com/ansible/latest/collections/ansible/builtin/replace_module.html
+https://docs.ansible.com/ansible/latest/collections/ansible/builtin/shell_module.html
+https://docs.ansible.com/ansible/latest/collections/ansible/builtin/stat_module.html
+https://docs.ansible.com/ansible/latest/collections/community/general/shutdown_module.html
+https://docs.ansible.com/ansible/latest/collections/community/general/slackpkg_module.html
+https://docs.ansible.com/ansible/latest/command_guide/intro_adhoc.html
+https://docs.ansible.com/ansible/latest/installation_guide/intro_configuration.html#getting-the-latest-configuration
+https://docs.ansible.com/ansible/latest/inventory/implicit_localhost.html
+https://docs.ansible.com/ansible/latest/inventory_guide/connection_details.html
+https://docs.ansible.com/ansible/latest/inventory_guide/intro_inventory.html
+https://docs.ansible.com/ansible/latest/playbook_guide/playbooks_conditionals.html
+https://docs.ansible.com/ansible/latest/playbook_guide/playbooks_delegation.html
+https://docs.ansible.com/ansible/latest/playbook_guide/playbooks_delegation.html#delegating-facts
+https://docs.ansible.com/ansible/latest/playbook_guide/playbooks_privilege_escalation.html
+https://docs.ansible.com/ansible/latest/playbook_guide/playbooks_reuse_roles.html
+https://docs.ansible.com/ansible/latest/playbook_guide/playbooks_variables.html#id44
+https://docs.ansible.com/ansible/latest/playbook_guide/playbooks_variables.html#registering-variables
+https://docs.ansible.com/ansible/latest/playbook_guide/playbooks_vars_facts.html
+https://docs.ansible.com/ansible/latest/playbook_guide/playbooks_vars_facts.html#information-about-ansible-magic-variables
+https://docs.ansible.com/ansible/latest/plugins/become.html
+https://docs.ansible.com/ansible/latest/reference_appendices/YAMLSyntax.html
+https://docs.ansible.com/ansible/latest/reference_appendices/config.html
+https://docs.ansible.com/ansible/latest/reference_appendices/faq.html#how-do-i-handle-different-machines-needing-different-user-accounts-or-ports-to-log-in-with
+https://docs.python.org/3/library/re.html
+https://docs.slackware.com/howtos:slackware_admin:slackware_automation_using_ansible
+https://github.com/cesarvr/ansible-role-hello-world
+https://gitlab.com/mmlj4/ansible_slackware_bootstrap
+https://nixzie.com/run-ansible-playbook-locally/#Run_Ansible_Playbook_Locally_Using_Local_Action
+https://phoenixnap.com/kb/ansible-check-if-file-exists
+https://phoenixnap.com/kb/ansible-create-file
+https://pythex.org/
+https://serverfault.com/questions/589734/ansible-can-i-use-vars-files-when-some-files-do-not-exist
+https://stackoverflow.com/questions/18839509/where-can-i-get-a-list-of-ansible-pre-defined-variables
+https://stackoverflow.com/questions/24162996/how-to-move-rename-a-file-using-an-ansible-task-on-a-remote-system
+https://stackoverflow.com/questions/32101001/ansible-playbooks-vs-roles
+https://stackoverflow.com/questions/36134552/use-multiple-var-files-in-ansible-role
+https://stackoverflow.com/questions/53253879/ansible-vars-files-vs-include-vars
+https://stackoverflow.com/questions/56663332/difference-between-shell-and-command-in-ansible
+https://www.digitalocean.com/community/cheatsheets/how-to-manage-multiple-servers-with-ansible-ad-hoc-commands
+https://www.digitalocean.com/community/cheatsheets/how-to-use-ansible-cheat-sheet-guide
+https://www.digitalocean.com/community/tutorial-series/how-to-write-ansible-playbooks
+https://www.digitalocean.com/community/tutorials/how-to-use-ansible-roles-to-abstract-your-infrastructure-environment
+https://www.educba.com/ansible-hosts-file/
+https://www.freekb.net/Article?id=2395
+https://www.freekb.net/Article?id=3078
+https://www.freekb.net/Article?id=573
+https://www.freekb.net/Article?id=759
+https://www.howtouselinux.com/post/ansible-copy-module-examples-to-copy-file-to-remote-server
+https://www.howtouselinux.com/post/modify-files-with-ansible-lineinfile-replace-and-blockinfile
+https://www.lifewire.com/download-free-books-3482754
+https://www.linuxtechi.com/replace-strings-lines-with-ansible/
+https://www.middlewareinventory.com/blog/ansible-update-etc-hosts-file-across-all-hosts/
+https://www.middlewareinventory.com/blog/run-ansible-playbook-locally/
+https://www.programiz.com/python-programming/regex
+https://www.pythontutorial.net/python-regex/python-regex-backreferences/
diff --git a/regex_test.py b/regex_test.py
new file mode 100644
index 0000000..d7891ac
--- /dev/null
+++ b/regex_test.py
@@ -0,0 +1,41 @@
+import re
+
+# multiline string
+string = '#kernel-generic.*\n#kernel-huge.*\n#kernel-modules.*\n#kernel-source'
+
+# matches all whitespace characters
+## from pythex.org --> ^#(kernel-.+)$
+#pattern = r'^#(kernel-.+)$\1'
+#replace = r'\1'
+
+#pattern = r'^#(kernel)\1'
+#replace = r'\1'
+
+## works
+#pattern = r'#(kernel)'
+#replace = r'kernel'
+
+## works
+pattern = r'#kernel'
+replace = r'kernel'
+
+#pattern = r'(#kernel)\1'
+#replace = r'ola'
+
+
+new_string = re.sub(pattern, replace, string)
+print(string)
+print('')
+print(new_string)
+
+
+##########
+##s = 'Python Python is awesome'
+##
+##pattern = r'(\w+)\s+\1'
+##replace = r'\1'
+##
+###new_s = re.sub(r'(\w+)\s+\1', r'\1', s)
+##new_s = re.sub(pattern, replace, s)
+##
+##print(new_s)
diff --git a/regex_test.py~ b/regex_test.py~
new file mode 100644
index 0000000..4468629
--- /dev/null
+++ b/regex_test.py~
@@ -0,0 +1,12 @@
+import re
+
+# multiline string
+string = 'abc 12\
+de 23 \n f45 6'
+
+# matches all whitespace characters
+pattern = '\s+'
+replace = ''
+
+new_string = re.sub(r'\s+', replace, string, 1)
+print(new_string)