From 4289fa7a67d3eb09df36402a41d9114a28ef62a1 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Franti=C5=A1ek=20Dvo=C5=99=C3=A1k?= <valtri@civ.zcu.cz>
Date: Mon, 4 Nov 2024 21:51:53 +0000
Subject: [PATCH] Ansible and YAML linting

* ansible linting
* ansible block error handling
* YAML linting
* editorconfig file and formatting
---
 .ansible-lint                                 |  1 +
 .editorconfig                                 | 37 ++++++++++++
 cesnet-central/deployments/fullhub.yaml       | 35 ++++--------
 cesnet-central/inventory/99-all.yaml          |  2 +-
 cesnet-central/playbooks/ephemeral.yaml       |  5 +-
 .../playbooks/repository-nexus.yaml           |  5 ++
 cesnet-mcc/inventory/99-all.yaml              |  2 +-
 cesnet-mcc/playbooks/gateway.yaml             |  1 +
 .../accounting-config-production.yaml         |  3 +-
 .../accounting-config-stage.yaml              |  3 +-
 common/deployments/hub-production.yaml        | 35 ++++--------
 common/deployments/hub-staging.yaml           | 35 ++++--------
 common/playbooks/accounting.yaml              |  7 ++-
 common/playbooks/cvmfs.yaml                   | 12 +++-
 common/playbooks/k8s.yaml                     | 57 ++++++++++++-------
 common/playbooks/notebooks.yaml               | 17 ++++--
 common/playbooks/security-logs.yaml           |  5 +-
 common/playbooks/security-scanner.yaml        |  6 +-
 common/playbooks/upgrade.yaml                 |  2 +
 production1/inventory/99-all.yaml             |  7 ++-
 production2/inventory/99-all.yaml             |  2 +-
 requirements.yml                              | 12 ++--
 staging1/inventory/99-all.yaml                |  7 ++-
 staging2/inventory/99-all.yaml                |  2 +-
 testing/deployments/hub.yaml                  | 35 ++++--------
 testing/inventory/99-all.yaml                 |  2 +-
 testing/playbooks/notebooks-redirect.yaml     |  1 +
 27 files changed, 194 insertions(+), 144 deletions(-)
 create mode 100644 .editorconfig

diff --git a/.ansible-lint b/.ansible-lint
index d8cb4a4..7ac061e 100644
--- a/.ansible-lint
+++ b/.ansible-lint
@@ -1,4 +1,5 @@
 skip_list:
   - command-instead-of-module
   - fqcn-builtins
+  - var-naming[no-reserved]
   - yaml[line-length]
diff --git a/.editorconfig b/.editorconfig
new file mode 100644
index 0000000..faab564
--- /dev/null
+++ b/.editorconfig
@@ -0,0 +1,37 @@
+[*]
+charset = utf-8
+end_of_line = lf
+indent_size = 4
+indent_style = tab
+insert_final_newline = true
+max_line_length = off
+trim_trailing_whitespace = true
+
+[*.md]
+indent_style = undef
+
+[*.py]
+indent_style = spaces
+indent_size = 4
+
+[*.{tf,tfvars}]
+indent_style = spaces
+indent_size = 2
+max_line_length = off
+
+[*.{yaml,yml}]
+indent_size = 2
+indent_style = space
+# default from ansible-lint
+max_line_length = 160
+
+[/*/playbooks/{files,templates}/**]
+indent_style = undef
+max_line_length = off
+
+[/*/extra/*]
+max_line_length = off
+
+[.ansible-lint]
+indent_size = 2
+indent_style = space
diff --git a/cesnet-central/deployments/fullhub.yaml b/cesnet-central/deployments/fullhub.yaml
index 6aadf75..47d4748 100644
--- a/cesnet-central/deployments/fullhub.yaml
+++ b/cesnet-central/deployments/fullhub.yaml
@@ -27,22 +27,11 @@ singleuser:
           type: Directory
       - name: owncloud-home
         empty_dir:
-      # - name: scratch
-      #   ephemeral:
-      #     volumeClaimTemplate:
-      #       spec:
-      #         accessModes: [ "ReadWriteOnce" ]
-      #         storageClassName: local-path
-      #         resources:
-      #           requests:
-      #             storage: "10Gi"
     extraVolumeMounts:
       - name: cvmfs-host
         mountPath: "/cvmfs:shared"
       - name: owncloud-home
         mountPath: '/home/jovyan:shared'
-      # - name: scratch
-      #   mountPath: '/scratch'
   memory:
     limit: 4G
     guarantee: 128M
@@ -131,14 +120,14 @@ singleuser:
     singleuser-webdav-wrapper.sh:
       mode: 0755
       mountPath: /usr/local/bin/jupyterhub-singleuser-webdav-wrapper
-      #NotebookNotary.db_file=':memory:' is used due to issues
-      #notebook notary file was causing in ~/.jupyter in ownCloud mount
+      # NotebookNotary.db_file=':memory:' is used due to issues
+      # notebook notary file was causing in ~/.jupyter in ownCloud mount
       #
-      #LabApp.custom_css=True allows to use custom CSS for EOSC style
+      # LabApp.custom_css=True allows to use custom CSS for EOSC style
       #
-      #ResourceUseDisplay.mem_warning_threshold=0.25 sets for resource-usage
-      #extension to warn about used memory when only 25% of memory is available
-      #which is also used by EGI notebooks-resource-warning extension
+      # ResourceUseDisplay.mem_warning_threshold=0.25 sets for resource-usage
+      # extension to warn about used memory when only 25% of memory is available
+      # which is also used by EGI notebooks-resource-warning extension
       stringData: |-
         #! /bin/sh
         #
@@ -264,14 +253,14 @@ hub:
                   return
 
               if type == "home":
-                  #Jupyter side
+                  # Jupyter side
                   subpath = ""
-                  #ownCloud backend side
+                  # ownCloud backend side
                   remote_path = "/notebooks_service"
               else:
-                  #Jupyter side
+                  # Jupyter side
                   subpath = "/" + type.capitalize()
-                  #ownCloud backend side
+                  # ownCloud backend side
                   remote_path = "/"
               env = [
                   {"name": "WEBDAV_URL", "value": owncloud_url},
@@ -294,8 +283,8 @@ hub:
               spawner.extra_containers.append(
                   {
                       "name": "owncloud-" + type,
-                      #To be changed. This is temporary image with 
-                      #rclone fix for ownCloud not yet upstreamed
+                      # To be changed. This is temporary image with
+                      # rclone fix for ownCloud not yet upstreamed
                       "image":"eginotebooks/webdav-rclone-sidecar-forked:1.2",
                       "args": ["bearer_token_command=cat " + self.token_path],
                       "env": env,
diff --git a/cesnet-central/inventory/99-all.yaml b/cesnet-central/inventory/99-all.yaml
index 083e5da..5b1474d 100644
--- a/cesnet-central/inventory/99-all.yaml
+++ b/cesnet-central/inventory/99-all.yaml
@@ -9,7 +9,7 @@ allnodes:
 
 all:
   vars:
-    ansible_become: yes
+    ansible_become: true
     ansible_user: egi
 
     site_name: cesnet-central
diff --git a/cesnet-central/playbooks/ephemeral.yaml b/cesnet-central/playbooks/ephemeral.yaml
index 87dcb15..f80927f 100644
--- a/cesnet-central/playbooks/ephemeral.yaml
+++ b/cesnet-central/playbooks/ephemeral.yaml
@@ -7,8 +7,8 @@
       git:
         repo: https://github.com/rancher/local-path-provisioner.git
         dest: "/root/git-local-path-provisioner"
-        clone: yes
-        update: no
+        clone: true
+        update: false
         version: v0.0.26
     - name: Local path provisioner configuration
       copy:
@@ -40,4 +40,5 @@
       environment:
         KUBECONFIG: /etc/kubernetes/admin.conf
         PATH: /sbin:/bin:/usr/sbin:/usr/bin:/usr/local/bin
+      changed_when: true
       when: true
diff --git a/cesnet-central/playbooks/repository-nexus.yaml b/cesnet-central/playbooks/repository-nexus.yaml
index 34cb18e..470ce7b 100644
--- a/cesnet-central/playbooks/repository-nexus.yaml
+++ b/cesnet-central/playbooks/repository-nexus.yaml
@@ -29,6 +29,7 @@
       environment:
         KUBECONFIG: /etc/kubernetes/admin.conf
         PATH: /sbin:/bin:/usr/sbin:/usr/bin:/usr/local/bin
+      changed_when: true
       when: true
     - name: Wait for Nexus pod ready
       command: kubectl wait pod --all --namespace nexus --for condition=ready --timeout=5m
@@ -76,6 +77,10 @@
             body: "{{ nexus_admin_password }}"
             body_format: raw
             status_code: [200, 204]
+      rescue:
+        - name: Admin Password Setup Fail
+          fail:
+            msg: "Failed admin password setup"
     - name: Check blobstore
       uri:
         url: "{{ nexus_url }}/blobstores/{{ nexus_blobstore_type }}/{{ nexus_blobstore_name }}"
diff --git a/cesnet-mcc/inventory/99-all.yaml b/cesnet-mcc/inventory/99-all.yaml
index 4d8d32c..2eb4505 100644
--- a/cesnet-mcc/inventory/99-all.yaml
+++ b/cesnet-mcc/inventory/99-all.yaml
@@ -9,7 +9,7 @@ allnodes:
 
 all:
   vars:
-    ansible_become: yes
+    ansible_become: true
     ansible_user: egi
 
     site_name: cesnet-mcc
diff --git a/cesnet-mcc/playbooks/gateway.yaml b/cesnet-mcc/playbooks/gateway.yaml
index decd33c..e7a447b 100644
--- a/cesnet-mcc/playbooks/gateway.yaml
+++ b/cesnet-mcc/playbooks/gateway.yaml
@@ -86,4 +86,5 @@
       environment:
         KUBECONFIG: /etc/kubernetes/admin.conf
         PATH: /sbin:/bin:/usr/sbin:/usr/bin:/usr/local/bin
+      changed_when: true
       when: true
diff --git a/common/accounting_deployments/accounting-config-production.yaml b/common/accounting_deployments/accounting-config-production.yaml
index 2fd0e04..d71594c 100644
--- a/common/accounting_deployments/accounting-config-production.yaml
+++ b/common/accounting_deployments/accounting-config-production.yaml
@@ -1,3 +1,4 @@
+---
 eosc:
   schedule: 42 1 * * *
   tokenUrl: "https://{{ secrets['checkin_host'] }}/OIDC/token"
@@ -10,5 +11,3 @@ eosc:
     medium-environment-4-vcpu-8-gb-ram: 66cc84190224445bec163975
     large-environment-8-vcpu-16-gb-ram-gpu: 66cc84266ea4014534e682d7
     large-environment-8-vcpu-16-gb-ram: 66cc84386ea4014534e682d8
-
-
diff --git a/common/accounting_deployments/accounting-config-stage.yaml b/common/accounting_deployments/accounting-config-stage.yaml
index 15d83b2..332595f 100644
--- a/common/accounting_deployments/accounting-config-stage.yaml
+++ b/common/accounting_deployments/accounting-config-stage.yaml
@@ -1,3 +1,4 @@
+---
 eosc:
   schedule: 42 1 * * *
   tokenUrl: "https://{{ secrets['checkin_host'] }}/OIDC/token"
@@ -10,5 +11,3 @@ eosc:
     medium-environment-4-vcpu-8-gb-ram: 668bdd75d1bc0f46a16be8a2
     large-environment-8-vcpu-16-gb-ram-gpu: 668bdd8b88e1d617b217ecba
     large-environment-8-vcpu-16-gb-ram: 6694d9eb744c3c7ae7531917
-
-
diff --git a/common/deployments/hub-production.yaml b/common/deployments/hub-production.yaml
index 20bd3b1..759c511 100644
--- a/common/deployments/hub-production.yaml
+++ b/common/deployments/hub-production.yaml
@@ -27,22 +27,11 @@ singleuser:
           type: Directory
       - name: owncloud-home
         empty_dir:
-      # - name: scratch
-      #   ephemeral:
-      #     volumeClaimTemplate:
-      #       spec:
-      #         accessModes: [ "ReadWriteOnce" ]
-      #         storageClassName: local-path
-      #         resources:
-      #           requests:
-      #             storage: "10Gi"
     extraVolumeMounts:
       - name: cvmfs-host
         mountPath: "/cvmfs:shared"
       - name: owncloud-home
         mountPath: '/home/jovyan:shared'
-      # - name: scratch
-      #   mountPath: '/scratch'
   memory:
     limit: 4G
     guarantee: 512M
@@ -113,14 +102,14 @@ singleuser:
     singleuser-webdav-wrapper.sh:
       mode: 0755
       mountPath: /usr/local/bin/jupyterhub-singleuser-webdav-wrapper
-      #NotebookNotary.db_file=':memory:' is used due to issues
-      #notebook notary file was causing in ~/.jupyter in ownCloud mount
+      # NotebookNotary.db_file=':memory:' is used due to issues
+      # notebook notary file was causing in ~/.jupyter in ownCloud mount
       #
-      #LabApp.custom_css=True allows to use custom CSS for EOSC style
+      # LabApp.custom_css=True allows to use custom CSS for EOSC style
       #
-      #ResourceUseDisplay.mem_warning_threshold=0.25 sets for resource-usage
-      #extension to warn about used memory when only 25% of memory is available
-      #which is also used by EGI notebooks-resource-warning extension
+      # ResourceUseDisplay.mem_warning_threshold=0.25 sets for resource-usage
+      # extension to warn about used memory when only 25% of memory is available
+      # which is also used by EGI notebooks-resource-warning extension
       stringData: |-
         #! /bin/sh
         #
@@ -247,14 +236,14 @@ hub:
                   return
 
               if type == "home":
-                  #Jupyter side
+                  # Jupyter side
                   subpath = ""
-                  #ownCloud backend side
+                  # ownCloud backend side
                   remote_path = "/notebooks_service"
               else:
-                  #Jupyter side
+                  # Jupyter side
                   subpath = "/" + type.capitalize()
-                  #ownCloud backend side
+                  # ownCloud backend side
                   remote_path = "/"
               env = [
                   {"name": "WEBDAV_URL", "value": owncloud_url},
@@ -277,8 +266,8 @@ hub:
               spawner.extra_containers.append(
                   {
                       "name": "owncloud-" + type,
-                      #To be changed. This is temporary image with 
-                      #rclone fix for ownCloud not yet upstreamed
+                      # To be changed. This is temporary image with
+                      # rclone fix for ownCloud not yet upstreamed
                       "image":"eginotebooks/webdav-rclone-sidecar-forked:1.2",
                       "args": ["bearer_token_command=cat " + self.token_path],
                       "env": env,
diff --git a/common/deployments/hub-staging.yaml b/common/deployments/hub-staging.yaml
index f89abcf..1fd09d7 100644
--- a/common/deployments/hub-staging.yaml
+++ b/common/deployments/hub-staging.yaml
@@ -27,22 +27,11 @@ singleuser:
           type: Directory
       - name: owncloud-home
         empty_dir:
-      # - name: scratch
-      #   ephemeral:
-      #     volumeClaimTemplate:
-      #       spec:
-      #         accessModes: [ "ReadWriteOnce" ]
-      #         storageClassName: local-path
-      #         resources:
-      #           requests:
-      #             storage: "10Gi"
     extraVolumeMounts:
       - name: cvmfs-host
         mountPath: "/cvmfs:shared"
       - name: owncloud-home
         mountPath: '/home/jovyan:shared'
-      # - name: scratch
-      #   mountPath: '/scratch'
   memory:
     limit: 4G
     guarantee: 512M
@@ -113,14 +102,14 @@ singleuser:
     singleuser-webdav-wrapper.sh:
       mode: 0755
       mountPath: /usr/local/bin/jupyterhub-singleuser-webdav-wrapper
-      #NotebookNotary.db_file=':memory:' is used due to issues
-      #notebook notary file was causing in ~/.jupyter in ownCloud mount
+      # NotebookNotary.db_file=':memory:' is used due to issues
+      # notebook notary file was causing in ~/.jupyter in ownCloud mount
       #
-      #LabApp.custom_css=True allows to use custom CSS for EOSC style
+      # LabApp.custom_css=True allows to use custom CSS for EOSC style
       #
-      #ResourceUseDisplay.mem_warning_threshold=0.25 sets for resource-usage
-      #extension to warn about used memory when only 25% of memory is available
-      #which is also used by EGI notebooks-resource-warning extension
+      # ResourceUseDisplay.mem_warning_threshold=0.25 sets for resource-usage
+      # extension to warn about used memory when only 25% of memory is available
+      # which is also used by EGI notebooks-resource-warning extension
       stringData: |-
         #! /bin/sh
         #
@@ -245,14 +234,14 @@ hub:
                   return
 
               if type == "home":
-                  #Jupyter side
+                  # Jupyter side
                   subpath = ""
-                  #ownCloud backend side
+                  # ownCloud backend side
                   remote_path = "/notebooks_service"
               else:
-                  #Jupyter side
+                  # Jupyter side
                   subpath = "/" + type.capitalize()
-                  #ownCloud backend side
+                  # ownCloud backend side
                   remote_path = "/"
               env = [
                   {"name": "WEBDAV_URL", "value": owncloud_url},
@@ -275,8 +264,8 @@ hub:
               spawner.extra_containers.append(
                   {
                       "name": "owncloud-" + type,
-                      #To be changed. This is temporary image with 
-                      #rclone fix for ownCloud not yet upstreamed
+                      # To be changed. This is temporary image with
+                      # rclone fix for ownCloud not yet upstreamed
                       "image":"eginotebooks/webdav-rclone-sidecar-forked:1.2",
                       "args": ["bearer_token_command=cat " + self.token_path],
                       "env": env,
diff --git a/common/playbooks/accounting.yaml b/common/playbooks/accounting.yaml
index a835caa..6fec7d0 100644
--- a/common/playbooks/accounting.yaml
+++ b/common/playbooks/accounting.yaml
@@ -1,3 +1,4 @@
+---
 - name: EOSC accounting deployment
   hosts: master[0]
   become: true
@@ -6,6 +7,7 @@
       shell: |-
         helm repo add egi-accounting https://egi-federation.github.io/egi-notebooks-accounting
         helm repo update
+      changed_when: true
       when: "'egi-accounting' not in ansible_local.helm_repos | map(attribute='name') | list"
     - name: Get credentials from Vault for accounting
       set_fact:
@@ -19,7 +21,7 @@
       debug:
         msg: "{{ item.key }} = {{ item.value }}"
       loop: "{{ secrets | dict2items }}"
-    - name: Copy config file to master   
+    - name: Copy config file to master
       template:
         src: "../accounting_deployments/accounting-config.yaml"
         dest: "/tmp/accounting-config.yaml"
@@ -33,7 +35,7 @@
         if [ $? -ne 0 ]; then
             helm install --create-namespace --namespace accounting \
                 -f /tmp/accounting-config.yaml --version {{ version }} \
-                 {{ name }} egi-accounting/notebooks-accounting
+                {{ name }} egi-accounting/notebooks-accounting
         else
             helm upgrade --version {{ version }} -f /tmp/accounting-config.yaml \
                 --namespace accounting {{ name }} egi-accounting/notebooks-accounting
@@ -41,4 +43,5 @@
       environment:
         KUBECONFIG: /etc/kubernetes/admin.conf
         PATH: /sbin:/bin:/usr/sbin:/usr/bin:/usr/local/bin
+      changed_when: true
       when: true
diff --git a/common/playbooks/cvmfs.yaml b/common/playbooks/cvmfs.yaml
index 26eb1a8..9554416 100644
--- a/common/playbooks/cvmfs.yaml
+++ b/common/playbooks/cvmfs.yaml
@@ -2,7 +2,13 @@
 - name: CVMFS deployment
   hosts: ingress, nfs, worker, gpu
   vars:
-    # EGI repositories: gridpp.egi.eu eosc.egi.eu pheno.egi.eu mice.egi.eu ghost.egi.eu wenmr.egi.eu neugrid.egi.eu auger.egi.eu dirac.egi.eu galdyn.egi.eu seadatanet.egi.eu ligo.egi.eu supernemo.egi.eu pravda.egi.eu chipster.egi.eu hyperk.egi.eu snoplus.egi.eu km3net.egi.eu t2k.egi.eu na62.egi.eu biomed.egi.eu eiscat.egi.eu comet.egi.eu notebooks.egi.eu
+    #
+    # EGI repositories:
+    #
+    # gridpp.egi.eu eosc.egi.eu pheno.egi.eu mice.egi.eu ghost.egi.eu wenmr.egi.eu neugrid.egi.eu auger.egi.eu dirac.egi.eu galdyn.egi.eu seadatanet.egi.eu
+    # ligo.egi.eu supernemo.egi.eu pravda.egi.eu chipster.egi.eu hyperk.egi.eu snoplus.egi.eu km3net.egi.eu t2k.egi.eu na62.egi.eu biomed.egi.eu eiscat.egi.eu
+    # comet.egi.eu notebooks.egi.eu
+    #
     cvmfs_repositories:
       - cvmfs-config.cern.ch  # required
       - atlas.cern.ch
@@ -46,6 +52,10 @@
         - name: Update apt cache with cvmfs apt repository
           apt:
             update_cache: true
+      rescue:
+        - name: Setup CVMFS Apt Repository Fail
+          fail:
+            msg: "Failed setup of CVMFS apt repository"
     - name: Install cvmfs
       package:
         name: cvmfs
diff --git a/common/playbooks/k8s.yaml b/common/playbooks/k8s.yaml
index 04eac78..99bac06 100644
--- a/common/playbooks/k8s.yaml
+++ b/common/playbooks/k8s.yaml
@@ -4,7 +4,7 @@
   become: true
   tasks:
     - name: Add SSH keys
-      authorized_key:
+      ansible.posix.authorized_key:
         user: egi
         state: present
         key: '{{ item }}'
@@ -72,11 +72,11 @@
           when: site_name == "cesnet-testing" or site_name == "cesnet-mcc"
         - name: Site-specific postfix settings - mail_fromdomain
           set_fact:
-            main: '{{ main | combine({ "myhostname": mail_fromdomain }) }}'
+            main: '{{ main | combine({"myhostname": mail_fromdomain}) }}'
           when: mail_fromdomain is defined
         - name: Site-specific postfix settings - default_transport
           set_fact:
-            main: '{{ main | combine({ "default_transport": "error: This server sends mail only locally." }) }}'
+            main: '{{ main | combine({"default_transport": "error: This server sends mail only locally."}) }}'
           when: mail_local | default(false) | bool
         - name: Setup postfix
           lineinfile:
@@ -93,6 +93,10 @@
             dest: /etc/mailutils.conf
             mode: 0644
           when: (site_name == "cesnet-testing" or site_name == "cesnet-mcc" or mail_fromdomain is defined) and not (mail_local | default(false))
+      rescue:
+        - name: Mail Settings Fail
+          fail:
+            msg: "Mail settings failed"
     - name: Site touch
       file:
         path: "/EOSC-{{ site_name | upper }}"
@@ -144,6 +148,7 @@
   handlers:
     - name: Reload exports
       command: exportfs -ra
+      changed_when: true
 
 - name: K8s master deployment
   hosts: master
@@ -240,9 +245,9 @@
         - Restart docker
   handlers:
     - name: Reload systemd daemon
-      command:
-        cmd: systemctl daemon-reload
-      ignore_errors: true
+      systemd:
+        daemon_reload: true
+      failed_when: false
     - name: Restart docker
       service:
         name: docker
@@ -261,6 +266,7 @@
       delay: 10
       environment:
         KUBECONFIG: /etc/kubernetes/admin.conf
+      changed_when: false
       when: true
     - name: Create custom fact directory
       file:
@@ -280,11 +286,13 @@
       shell: |-
         helm repo add stable https://charts.helm.sh/stable/
         helm repo update
+      changed_when: true
       when: "'stable' not in ansible_local.helm_repos | map(attribute='name') | list"
     - name: Helm repo add nfs-subdir-external-provisioner
       shell: |-
         helm repo add nfs-subdir-external-provisioner https://kubernetes-sigs.github.io/nfs-subdir-external-provisioner
         helm repo update
+      changed_when: true
       when: "'nfs-subdir-external-provisioner' not in ansible_local.helm_repos | map(attribute='name') | list"
     - name: NFS provisioner
       vars:
@@ -302,13 +310,14 @@
       environment:
         KUBECONFIG: /etc/kubernetes/admin.conf
         PATH: /sbin:/bin:/usr/sbin:/usr/bin:/usr/local/bin
+      changed_when: true
       when: true
     - name: Git clone local-path-provisioner
       git:
         repo: https://github.com/rancher/local-path-provisioner.git
         dest: "/root/git-local-path-provisioner"
-        clone: yes
-        update: no
+        clone: true
+        update: false
         version: v0.0.26
     - name: Local path provisioner configuration
       copy:
@@ -341,11 +350,13 @@
       environment:
         KUBECONFIG: /etc/kubernetes/admin.conf
         PATH: /sbin:/bin:/usr/sbin:/usr/bin:/usr/local/bin
+      changed_when: true
       when: true
     - name: Helm repo add ingress-nginx
       shell: |-
         helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx
         helm repo update
+      changed_when: true
       when: "'ingress-nginx' not in ansible_local.helm_repos | map(attribute='name') | list"
     - name: Ingress
       vars:
@@ -355,7 +366,7 @@
           --set controller.service.externalIPs={{ '{' + hostvars[groups['ingress'][0]].ansible_default_ipv4.address + '}' }}
           --set controller.config.proxy-body-size=0
           --set controller.allowSnippetAnnotations=false
-          --version={{version}}
+          --version={{ version }}
       shell: |-
         helm status --namespace kube-system cluster-ingress
         if [ $? -ne 0 ]; then
@@ -366,6 +377,7 @@
       environment:
         KUBECONFIG: /etc/kubernetes/admin.conf
         PATH: /sbin:/bin:/usr/sbin:/usr/bin:/usr/local/bin
+      changed_when: true
       when: true
     - name: Cert-manager
       vars:
@@ -389,6 +401,7 @@
       environment:
         KUBECONFIG: /etc/kubernetes/admin.conf
         PATH: /sbin:/bin:/usr/sbin:/usr/bin:/usr/local/bin
+      changed_when: true
       when: true
     - name: Cluster issuer file
       copy:
@@ -416,12 +429,14 @@
       environment:
         KUBECONFIG: /etc/kubernetes/admin.conf
         PATH: /sbin:/bin:/usr/sbin:/usr/bin:/usr/local/bin
+      changed_when: true
       when: true
     # Accounting / monitoring needs
     - name: Helm repo add prometheus-community
       shell: |-
         helm repo add prometheus-community https://prometheus-community.github.io/helm-charts
         helm repo update
+      changed_when: true
       when: "'prometheus-community' not in ansible_local.helm_repos | map(attribute='name') | list"
     - name: Prometheus configuration
       vars:
@@ -495,6 +510,7 @@
       environment:
         KUBECONFIG: /etc/kubernetes/admin.conf
         PATH: /sbin:/bin:/usr/sbin:/usr/bin:/usr/local/bin
+      changed_when: true
       when: true
     - name: Grafana configuration
       copy:
@@ -513,17 +529,17 @@
               - "{{ grafana_hostname }}"
               secretName: acme-tls-grafana
           datasources:
-           datasources.yaml:
-             apiVersion: 1
-             datasources:
-              - name: Prometheus
-                type: prometheus
-                access: Server
-                orgId: 1
-                url: http://prometheus-server.prometheus.svc.cluster.local
-                isDefault: true
-                version: 1
-                editable: false
+            datasources.yaml:
+              apiVersion: 1
+              datasources:
+                - name: Prometheus
+                  type: prometheus
+                  access: Server
+                  orgId: 1
+                  url: http://prometheus-server.prometheus.svc.cluster.local
+                  isDefault: true
+                  version: 1
+                  editable: false
           sidecar:
             dashboards:
               enabled: true
@@ -546,4 +562,5 @@
       environment:
         KUBECONFIG: /etc/kubernetes/admin.conf
         PATH: /sbin:/bin:/usr/sbin:/usr/bin:/usr/local/bin
+      changed_when: true
       when: true
diff --git a/common/playbooks/notebooks.yaml b/common/playbooks/notebooks.yaml
index 4c6db4d..c687395 100644
--- a/common/playbooks/notebooks.yaml
+++ b/common/playbooks/notebooks.yaml
@@ -8,14 +8,15 @@
         helm repo add jupyterhub https://jupyterhub.github.io/helm-chart/
         helm repo add eginotebooks https://egi-federation.github.io/egi-notebooks-chart/
         helm repo update
+      changed_when: true
       when: "'jupyterhub' not in ansible_local.helm_repos | map(attribute='name') | list or
-             'eginotebooks' not in ansible_local.helm_repos | map(attribute='name') | list"
+            'eginotebooks' not in ansible_local.helm_repos | map(attribute='name') | list"
     - name: Get Secrets from Vault for notebooks
       vars:
         name: "{{ item | basename | splitext | first }}"
       set_fact:
-        deployment_secrets: "{{ deployment_secrets|default({}) | combine({name: lookup('community.hashi_vault.hashi_vault',
-          (vault_mount_point, 'deployment-' + name)  | join('/'),  token_validate=false)}) }}"
+        deployment_secrets: "{{ deployment_secrets | default({}) | combine({name: lookup('community.hashi_vault.hashi_vault',
+          (vault_mount_point, 'deployment-' + name) | join('/'), token_validate=false)}) }}"
       with_fileglob:
         - "../deployments/*.yaml"
     - name: Debug Deployments Secrets
@@ -41,7 +42,7 @@
         if [ $? -ne 0 ]; then
             helm install --create-namespace --namespace {{ name }} \
                 -f /tmp/{{ item | basename }} --version {{ version }} --timeout 2h \
-                 {{ name }} jupyterhub/jupyterhub
+                {{ name }} jupyterhub/jupyterhub
         else
             helm upgrade --version {{ version }} -f /tmp/{{ item | basename }} --timeout 2h \
                 --namespace {{ name }} {{ name }} jupyterhub/jupyterhub
@@ -49,6 +50,7 @@
       environment:
         KUBECONFIG: /etc/kubernetes/admin.conf
         PATH: /sbin:/bin:/usr/sbin:/usr/bin:/usr/local/bin
+      changed_when: true
       when: true
       with_fileglob:
         - "../deployments/*.yaml"
@@ -70,6 +72,7 @@
       environment:
         KUBECONFIG: /etc/kubernetes/admin.conf
         PATH: /sbin:/bin:/usr/sbin:/usr/bin:/usr/local/bin
+      changed_when: true
       when: true
       with_fileglob:
         - "../deployments/*.yaml"
@@ -106,6 +109,7 @@
       environment:
         KUBECONFIG: /etc/kubernetes/admin.conf
         PATH: /sbin:/bin:/usr/sbin:/usr/bin:/usr/local/bin
+      changed_when: true
       when: true
       with_fileglob:
         - "../deployments/*.yaml"
@@ -123,6 +127,7 @@
       environment:
         KUBECONFIG: /etc/kubernetes/admin.conf
         PATH: /sbin:/bin:/usr/sbin:/usr/bin:/usr/local/bin
+      changed_when: true
       when: true
       with_fileglob:
         - "../deployments/*.yaml"
@@ -144,6 +149,7 @@
         KUBECONFIG: /etc/kubernetes/admin.conf
       with_fileglob:
         - "../extra/*.yaml"
+      changed_when: true
       when: true
     # Workaround for pods stuck in "Terminating" state
     - name: K8s pods cleaner script
@@ -164,7 +170,8 @@
         user: egi
       with_fileglob:
         - "../deployments/*.yaml"
-- hosts: nfs
+- name: Global Quota Settings on NFS
+  hosts: nfs
   become: true
   tasks:
     - name: Quota settings
diff --git a/common/playbooks/security-logs.yaml b/common/playbooks/security-logs.yaml
index e08df25..82c56db 100644
--- a/common/playbooks/security-logs.yaml
+++ b/common/playbooks/security-logs.yaml
@@ -43,6 +43,7 @@
       shell: |-
         helm repo add fluent https://fluent.github.io/helm-charts
         helm repo update
+      changed_when: true
       when: "'fluent' not in ansible_local.helm_repos | map(attribute='name') | list"
     - name: Get Secrets from Vault
       set_fact:
@@ -54,7 +55,7 @@
       loop: "{{ secrets | dict2items }}"
     - name: Set Fluent TLS Fact From Secrets
       set_fact:
-        fluent_has_tls: "{{ 'fluent_secrets_ca' in secrets or 'fluent_secrets_crt' in secrets or 'fluent_secrets_key' in  secrets }}"
+        fluent_has_tls: "{{ 'fluent_secrets_ca' in secrets or 'fluent_secrets_crt' in secrets or 'fluent_secrets_key' in secrets }}"
     - name: Check fluent-bit namespace
       command:
         cmd: kubectl get namespace {{ namespace }}
@@ -78,6 +79,7 @@
       environment:
         KUBECONFIG: /etc/kubernetes/admin.conf
         PATH: /sbin:/bin:/usr/sbin:/usr/bin:/usr/local/bin
+      changed_when: true
       when: fluent_has_tls
     - name: Fluent Bit Configuration
       template:
@@ -99,4 +101,5 @@
       environment:
         KUBECONFIG: /etc/kubernetes/admin.conf
         PATH: /sbin:/bin:/usr/sbin:/usr/bin:/usr/local/bin
+      changed_when: true
       when: true
diff --git a/common/playbooks/security-scanner.yaml b/common/playbooks/security-scanner.yaml
index 0459062..6cd7976 100644
--- a/common/playbooks/security-scanner.yaml
+++ b/common/playbooks/security-scanner.yaml
@@ -15,10 +15,11 @@
       shell: |-
         helm repo add deepfence https://deepfence-helm-charts.s3.amazonaws.com/threatmapper
         helm repo update
+      changed_when: true
       when: "'deepfence' not in ansible_local.helm_repos | map(attribute='name') | list"
     - name: Get Secrets From Vault
       set_fact:
-        secrets: "{{ lookup('community.hashi_vault.hashi_vault', [ vault_mount_point,  'site-' + site_name] | join('/'), token_validate=false) }}"
+        secrets: "{{ lookup('community.hashi_vault.hashi_vault', [vault_mount_point, 'site-' + site_name] | join('/'), token_validate=false) }}"
     - name: Debug Secrets
       debug:
         msg: "{{ item.key }} = {{ item.value }}"
@@ -37,10 +38,11 @@
                 deepfence-agent deepfence/deepfence-agent
         else
             helm upgrade --namespace {{ namespace }} \
-                -f /tmp/deepfence-agent.yaml --version {{ version }}  \
+                -f /tmp/deepfence-agent.yaml --version {{ version }} \
                 deepfence-agent deepfence/deepfence-agent
         fi
       environment:
         KUBECONFIG: /etc/kubernetes/admin.conf
         PATH: /sbin:/bin:/usr/sbin:/usr/bin:/usr/local/bin
+      changed_when: true
       when: true
diff --git a/common/playbooks/upgrade.yaml b/common/playbooks/upgrade.yaml
index ff5546d..f15382e 100644
--- a/common/playbooks/upgrade.yaml
+++ b/common/playbooks/upgrade.yaml
@@ -39,6 +39,7 @@
     - name: Upgrade kubeadm
       command: |
         kubeadm upgrade apply --yes v{{ version }}
+      changed_when: true
       when: true
 
 - name: Upgrade k8s nodes
@@ -48,6 +49,7 @@
     - name: Upgrade kubeadm
       command: |
         kubeadm upgrade node
+      changed_when: true
       when: true
 
 - name: Upgrade and hold packages
diff --git a/production1/inventory/99-all.yaml b/production1/inventory/99-all.yaml
index 7bca22b..3952a20 100644
--- a/production1/inventory/99-all.yaml
+++ b/production1/inventory/99-all.yaml
@@ -9,9 +9,12 @@ allnodes:
 
 all:
   vars:
-    ansible_become: yes
+    ansible_become: true
     ansible_user: egi
-    ansible_ssh_common_args: '-o ProxyCommand="ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -W %h:%p -q egi@{{ groups["fip"][0] }}" -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null'
+    ansible_ssh_common_args: >-
+      -o ProxyCommand="ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -W %h:%p -q egi@{{ groups["fip"][0] }}"
+      -o StrictHostKeyChecking=no
+      -o UserKnownHostsFile=/dev/null
 
     mail_local: true
     site_name: psnc-production1
diff --git a/production2/inventory/99-all.yaml b/production2/inventory/99-all.yaml
index 96c4a6b..459b15c 100644
--- a/production2/inventory/99-all.yaml
+++ b/production2/inventory/99-all.yaml
@@ -9,7 +9,7 @@ allnodes:
 
 all:
   vars:
-    ansible_become: yes
+    ansible_become: true
     ansible_user: egi
 
     mail_local: true
diff --git a/requirements.yml b/requirements.yml
index 9e77ef3..d82ea85 100644
--- a/requirements.yml
+++ b/requirements.yml
@@ -1,9 +1,9 @@
 ---
 collections:
-  - ansible.posix
-  - ansible.utils
-  - community.general
-  - community.hashi_vault
+  - name: ansible.posix
+  - name: ansible.utils
+  - name: community.general
+  - name: community.hashi_vault
 roles:
-  - grycap.kubernetes
-  - ipr-cnrs.glpi_agent
+  - name: grycap.kubernetes
+  - name: ipr-cnrs.glpi_agent
diff --git a/staging1/inventory/99-all.yaml b/staging1/inventory/99-all.yaml
index 2d2dad6..4134f17 100644
--- a/staging1/inventory/99-all.yaml
+++ b/staging1/inventory/99-all.yaml
@@ -9,9 +9,12 @@ allnodes:
 
 all:
   vars:
-    ansible_become: yes
+    ansible_become: true
     ansible_user: egi
-    ansible_ssh_common_args: '-o ProxyCommand="ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -W %h:%p -q egi@{{ groups["fip"][0] }}" -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null'
+    ansible_ssh_common_args: >-
+      -o ProxyCommand="ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -W %h:%p -q egi@{{ groups["fip"][0] }}"
+      -o StrictHostKeyChecking=no
+      -o UserKnownHostsFile=/dev/null
 
     mail_local: true
     site_name: psnc-staging1
diff --git a/staging2/inventory/99-all.yaml b/staging2/inventory/99-all.yaml
index 61561d6..48b8d4d 100644
--- a/staging2/inventory/99-all.yaml
+++ b/staging2/inventory/99-all.yaml
@@ -9,7 +9,7 @@ allnodes:
 
 all:
   vars:
-    ansible_become: yes
+    ansible_become: true
     ansible_user: egi
 
     mail_local: true
diff --git a/testing/deployments/hub.yaml b/testing/deployments/hub.yaml
index f0a8985..4ece284 100644
--- a/testing/deployments/hub.yaml
+++ b/testing/deployments/hub.yaml
@@ -28,22 +28,11 @@ singleuser:
           type: Directory
       - name: owncloud-home
         empty_dir:
-      # - name: scratch
-      #   ephemeral:
-      #     volumeClaimTemplate:
-      #       spec:
-      #         accessModes: [ "ReadWriteOnce" ]
-      #         storageClassName: local-path
-      #         resources:
-      #           requests:
-      #             storage: "10Gi"
     extraVolumeMounts:
       - name: cvmfs-host
         mountPath: "/cvmfs:shared"
       - name: owncloud-home
         mountPath: '/home/jovyan:shared'
-      # - name: scratch
-      #   mountPath: '/scratch'
   memory:
     limit: 4G
     guarantee: 512M
@@ -114,14 +103,14 @@ singleuser:
     singleuser-webdav-wrapper.sh:
       mode: 0755
       mountPath: /usr/local/bin/jupyterhub-singleuser-webdav-wrapper
-      #NotebookNotary.db_file=':memory:' is used due to issues
-      #notebook notary file was causing in ~/.jupyter in ownCloud mount
+      # NotebookNotary.db_file=':memory:' is used due to issues
+      # notebook notary file was causing in ~/.jupyter in ownCloud mount
       #
-      #LabApp.custom_css=True allows to use custom CSS for EOSC style
+      # LabApp.custom_css=True allows to use custom CSS for EOSC style
       #
-      #ResourceUseDisplay.mem_warning_threshold=0.25 sets for resource-usage
-      #extension to warn about used memory when only 25% of memory is available
-      #which is also used by EGI notebooks-resource-warning extension
+      # ResourceUseDisplay.mem_warning_threshold=0.25 sets for resource-usage
+      # extension to warn about used memory when only 25% of memory is available
+      # which is also used by EGI notebooks-resource-warning extension
       stringData: |-
         #! /bin/sh
         #
@@ -246,14 +235,14 @@ hub:
                   return
 
               if type == "home":
-                  #Jupyter side
+                  # Jupyter side
                   subpath = ""
-                  #ownCloud backend side
+                  # ownCloud backend side
                   remote_path = "/notebooks_service"
               else:
-                  #Jupyter side
+                  # Jupyter side
                   subpath = "/" + type.capitalize()
-                  #ownCloud backend side
+                  # ownCloud backend side
                   remote_path = "/"
               env = [
                   {"name": "WEBDAV_URL", "value": owncloud_url},
@@ -276,8 +265,8 @@ hub:
               spawner.extra_containers.append(
                   {
                       "name": "owncloud-" + type,
-                      #To be changed. This is temporary image with 
-                      #rclone fix for ownCloud not yet upstreamed
+                      # To be changed. This is temporary image with
+                      # rclone fix for ownCloud not yet upstreamed
                       "image":"eginotebooks/webdav-rclone-sidecar-forked:1.2",
                       "args": ["bearer_token_command=cat " + self.token_path],
                       "env": env,
diff --git a/testing/inventory/99-all.yaml b/testing/inventory/99-all.yaml
index 6c0e757..438f768 100644
--- a/testing/inventory/99-all.yaml
+++ b/testing/inventory/99-all.yaml
@@ -9,7 +9,7 @@ allnodes:
 
 all:
   vars:
-    ansible_become: yes
+    ansible_become: true
     ansible_user: egi
 
     site_name: cesnet-testing
diff --git a/testing/playbooks/notebooks-redirect.yaml b/testing/playbooks/notebooks-redirect.yaml
index 3253d21..df93ed9 100644
--- a/testing/playbooks/notebooks-redirect.yaml
+++ b/testing/playbooks/notebooks-redirect.yaml
@@ -50,4 +50,5 @@
                 path: /(.*)
                 pathType: Prefix
         EOF
+      changed_when: true
       when: true
-- 
GitLab