From 50ce976e0cac2f6e49bae9082ce26cf853c82a0b Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?J=C3=B6rg=20Sachse?= <Joerg.Sachse@slub-dresden.de>
Date: Wed, 10 Aug 2022 09:26:54 +0200
Subject: [PATCH] test: introduce GitLab-CI functionality

---
 .ansible-lint                                 | 84 +++++++++++++++++++
 .config/molecule/config.yml                   |  2 +
 .gitignore                                    |  2 +
 .gitlab-ci.yml                                | 33 ++++++++
 ansible.cfg                                   |  3 +-
 handlers/main.yml                             |  2 +-
 meta/main.yml                                 | 75 ++++++-----------
 molecule/default                              |  1 +
 molecule/default/converge.yml                 |  7 --
 molecule/default/molecule.yml                 | 11 ---
 .../playbooks}/INSTALL.rst                    |  0
 molecule/resources/playbooks/README.md        |  3 +
 molecule/resources/playbooks/converge.yml     | 17 ++++
 molecule/resources/playbooks/prepare.yml      | 22 +++++
 .../playbooks}/verify.yml                     |  2 +-
 molecule/virtualbox/molecule.yml              | 41 +++++++++
 tasks/configure_nfs_mounts.yml                |  2 +-
 tasks/configure_ssh_keys.yml                  | 10 ++-
 tasks/install_ibmsp_client.yml                | 22 ++---
 tasks/main.yml                                |  9 +-
 20 files changed, 260 insertions(+), 88 deletions(-)
 create mode 100644 .ansible-lint
 create mode 100644 .config/molecule/config.yml
 create mode 100644 .gitlab-ci.yml
 create mode 120000 molecule/default
 delete mode 100644 molecule/default/converge.yml
 delete mode 100644 molecule/default/molecule.yml
 rename molecule/{default => resources/playbooks}/INSTALL.rst (100%)
 create mode 100644 molecule/resources/playbooks/README.md
 create mode 100644 molecule/resources/playbooks/converge.yml
 create mode 100644 molecule/resources/playbooks/prepare.yml
 rename molecule/{default => resources/playbooks}/verify.yml (85%)
 create mode 100644 molecule/virtualbox/molecule.yml

diff --git a/.ansible-lint b/.ansible-lint
new file mode 100644
index 0000000..f18a647
--- /dev/null
+++ b/.ansible-lint
@@ -0,0 +1,84 @@
+---
+# based on documentation available at
+# https://ansible-lint.readthedocs.io/en/latest/configuring/
+
+# exclude_paths included in this file are parsed relative to this file's location
+# and not relative to the CWD of execution. CLI arguments passed to the --exclude
+# option will be parsed relative to the CWD of execution.
+exclude_paths:
+  - .cache/    # implicit unless exclude_paths is defined in config
+  - .git/
+  - .githooks/
+  - backups/
+# parseable: true
+# quiet: true
+# verbosity: 1
+
+# Mock modules or roles in order to pass ansible-playbook --syntax-check
+# mock_modules:
+#   - zuul_return
+#   # note the foo.bar is invalid as being neither a module or a collection
+#   - fake_namespace.fake_collection.fake_module
+#   - fake_namespace.fake_collection.fake_module.fake_submodule
+# mock_roles:
+#   - mocked_role
+#   - author.role_name # old standalone galaxy role
+#   - fake_namespace.fake_collection.fake_role # role within a collection
+
+# Enable checking of loop variable prefixes in roles
+loop_var_prefix: "{role}_"
+
+use_default_rules: true
+# Load custom rules from this specific folder
+# rulesdir:
+#   - ./rule/directory/
+
+# This makes linter to fully ignore rules/tags listed below
+skip_list:
+  - skip_this_tag
+  - git-latest
+
+# Any rule that has the 'opt-in' tag will not be loaded unless its 'id' is
+# mentioned in the enable_list:
+enable_list:
+  - empty-string-compare    # opt-in
+  - no-log-password         # opt-in
+  - no-same-owner           # opt-in
+  # add yaml here if you want to avoid ignoring yaml checks when yamllint
+  # library is missing. Normally its absence just skips using that rule.
+  - yaml
+# Report only a subset of tags and fully ignore any others
+# tags:
+#   - var-spacing
+
+# This makes the linter display but not fail for rules/tags listed below:
+warn_list:
+  - skip_this_tag
+  - git-latest
+  - experimental    # experimental is included in the implicit list
+  # - role-name
+
+# Offline mode disables installation of requirements.yml
+offline: false
+
+# Define required Ansible's variables to satisfy syntax check
+# extra_vars:
+#   foo: bar
+#   multiline_string_variable: |
+#     line1
+#     line2
+#   complex_variable: ":{;\t$()"
+
+# Uncomment to enforce action validation with tasks, usually is not
+# needed as Ansible syntax check also covers it.
+# skip_action_validation: false
+
+# List of additional kind:pattern to be added at the top of the default
+# match list, first match determines the file kind.
+kinds:
+  # - playbook: "**/examples/*.{yml,yaml}"
+  # - galaxy: "**/folder/galaxy.yml"
+  # - tasks: "**/tasks/*.yml"
+  # - vars: "**/vars/*.yml"
+  # - meta: "**/meta/main.yml"
+  - yaml: "**/*.yaml-too"
diff --git a/.config/molecule/config.yml b/.config/molecule/config.yml
new file mode 100644
index 0000000..ece7ff6
--- /dev/null
+++ b/.config/molecule/config.yml
@@ -0,0 +1,2 @@
+---
+prerun: false
diff --git a/.gitignore b/.gitignore
index c6bb39d..ed78332 100644
--- a/.gitignore
+++ b/.gitignore
@@ -51,6 +51,8 @@ Thumbs.db
 
 *.retry
 *.vault
+inventory.*
+inv.*
 
 # Vim #
 #######
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
new file mode 100644
index 0000000..35eb914
--- /dev/null
+++ b/.gitlab-ci.yml
@@ -0,0 +1,33 @@
+---
+# A pipeline is composed of independent jobs that run scripts, grouped into stages.
+# Stages run in sequential order, but jobs within stages run in parallel.
+#
+# For more information, see: https://docs.gitlab.com/ee/ci/yaml/index.html#stages
+
+stages:          # List of stages for jobs, and their order of execution
+  - test
+
+default:
+  before_script:
+    - source /opt/molecule/bin/activate
+    - ansible --version
+    - molecule --version
+
+test-job:
+  stage: test
+  tags:
+    - "shell"
+  script:
+    # make sure that Ansible Vaults are present and can be decrypted
+    - echo "${VAULT_LZA_BACKUP_PROXY}" > ../lza_backup_proxy.pass
+    - export ANSIBLE_VAULT_IDENTITY_LIST="../lza_backup_proxy.pass"
+    - rm -rf ../ansible_vaults/
+    - git clone https://gitlab+deploy-token-25:${VAULT_ACCESS_TOKEN}@git.slub-dresden.de/slub-referat-2-3/ansible_vaults.git ../ansible_vaults/; \
+    # run Molecule tests
+    - molecule syntax --scenario-name default
+    - molecule lint --scenario-name default
+    - molecule create --scenario-name default
+    - molecule converge --scenario-name default
+    - molecule idempotence --scenario-name default
+    # - molecule verify --scenario-name default
+    - molecule destroy --scenario-name default
diff --git a/ansible.cfg b/ansible.cfg
index 841e765..9b809d3 100644
--- a/ansible.cfg
+++ b/ansible.cfg
@@ -1,7 +1,8 @@
 [defaults]
 # If set, configures the path to the Vault password file as an alternative to
 # specifying --vault-password-file on the command line.
-vault_identity_list = ../lza_install_common.pass, ../lza_server_hardening.pass, ../slub_osquery.pass, ../lza_backup_proxy.pass
+# vault_identity_list = ../lza_install_common.pass, ../lza_server_hardening.pass, ../slub_osquery.pass, ../lza_backup_proxy.pass
+vault_identity_list = ../lza_backup_proxy.pass
 
 # Path to default inventory file
 # Administrators can override this by using the "-i <inventoryfile>" CLI
diff --git a/handlers/main.yml b/handlers/main.yml
index caea2eb..4cf3e08 100644
--- a/handlers/main.yml
+++ b/handlers/main.yml
@@ -1,5 +1,5 @@
 ---
 - name: restart dsmcad
-  systemd:
+  ansible.builtin.systemd:
     name: "dsmcad.service"
     state: restarted
diff --git a/meta/main.yml b/meta/main.yml
index 7fd92e2..48dce70 100644
--- a/meta/main.yml
+++ b/meta/main.yml
@@ -1,57 +1,32 @@
+---
 galaxy_info:
   author: Jörg Sachse
-  description: IT administrator
-  company: SLUBArchiv.digital
-
-  # If the issue tracker for your role is not on github, uncomment the
-  # next line and provide a value
-  # issue_tracker_url: http://example.com/issue/tracker
-
-  # Choose a valid license ID from https://spdx.org - some suggested licenses:
-  # - BSD-3-Clause (default)
-  # - MIT
-  # - GPL-2.0-or-later
-  # - GPL-3.0-only
-  # - Apache-2.0
-  # - CC-BY-4.0
-  license: license (GPL-2.0-or-later, MIT, etc)
-
-  min_ansible_version: 2.2
-
-  # If this a Container Enabled role, provide the minimum Ansible Container version.
-  # min_ansible_container_version:
-
-  #
-  # Provide a list of supported platforms, and for each platform a list of versions.
-  # If you don't wish to enumerate all versions for a particular platform, use 'all'.
-  # To view available platforms and versions (or releases), visit:
-  # https://galaxy.ansible.com/api/v1/platforms/
-  #
-  # platforms:
-  # - name: Fedora
-  #   versions:
-  #   - all
-  #   - 25
-  # - name: SomePlatform
-  #   versions:
-  #   - all
-  #   - 1.0
-  #   - 7
-  #   - 99.99
-  platforms:
-  - name: Debian
-    versions:
-    - 10
-    - 11
-
+  company: SLUB Dresden
+  description: This role can be used to install a backup proxy server that can be used to gather backups from servers and route them to the IBM Spectrum Protect Server.
   galaxy_tags: []
-    # List tags for your role here, one per line. A tag is a keyword that describes
-    # and categorizes the role. Users find roles by searching for tags. Be sure to
-    # remove the '[]' above, if you add tags to this list.
+    # List tags for your role here, one per line. A tag is a keyword that describes and categorizes the role. Users find roles by searching for tags. Be sure to remove the '[]' above, if you
+    # add tags to this list.
     #
     # NOTE: A tag is limited to a single word comprised of alphanumeric characters.
     #       Maximum 20 tags per role.
-
+  # issue_tracker_url: "https://example.com/"
+    # If the issue tracker for your role is not on github, uncomment the next line and provide a value issue_tracker_url: http://example.com/issue/tracker
+  license: GPLv3
+    # Some suggested licenses: - BSD
+    # (default) - MIT - GPLv2 - GPLv3 - Apache - CC-BY
+  min_ansible_version: "2.5"
+    # If this a Container Enabled role, provide the minimum Ansible Container version. min_ansible_container_version: Optionally specify the branch Galaxy will use when accessing the GitHub repo
+    # for this role. During role install, if no tags are available, Galaxy will use this branch. During import Galaxy will access files on this branch. If Travis integration is configured, only
+    # notifications for this branch will be accepted. Otherwise, in all cases, the repo's default branch (usually master) will be used. github_branch:
+  namespace: "slub"
+  # Provide a list of supported platforms, and for each platform a list of versions. If you don't wish to enumerate all versions for a particular platform, use 'all'. To view available
+  # platforms and versions (or releases), visit: https://galaxy.ansible.com/api/v1/platforms/
+  #
+  # platforms: - name: Fedora
+  #   versions: - all - 25 - name: SomePlatform versions: - all - 1.0 - 7 - 99.99
+  platforms:
+    - name: Debian
+      versions:
+        - "buster"
+        - "bullseye"
 dependencies: []
-  # List your role dependencies here, one per line. Be sure to remove the '[]' above,
-  # if you add dependencies to this list.
diff --git a/molecule/default b/molecule/default
new file mode 120000
index 0000000..3841ab1
--- /dev/null
+++ b/molecule/default
@@ -0,0 +1 @@
+./virtualbox
\ No newline at end of file
diff --git a/molecule/default/converge.yml b/molecule/default/converge.yml
deleted file mode 100644
index 0be27a1..0000000
--- a/molecule/default/converge.yml
+++ /dev/null
@@ -1,7 +0,0 @@
----
-- name: Converge
-  hosts: all
-  tasks:
-    - name: "Include ansible_lza_backup_proxy"
-      include_role:
-        name: "ansible_lza_backup_proxy"
diff --git a/molecule/default/molecule.yml b/molecule/default/molecule.yml
deleted file mode 100644
index 69bc10b..0000000
--- a/molecule/default/molecule.yml
+++ /dev/null
@@ -1,11 +0,0 @@
----
-dependency:
-  name: galaxy
-driver:
-  name: vagrant
-platforms:
-  - name: instance
-provisioner:
-  name: ansible
-verifier:
-  name: ansible
diff --git a/molecule/default/INSTALL.rst b/molecule/resources/playbooks/INSTALL.rst
similarity index 100%
rename from molecule/default/INSTALL.rst
rename to molecule/resources/playbooks/INSTALL.rst
diff --git a/molecule/resources/playbooks/README.md b/molecule/resources/playbooks/README.md
new file mode 100644
index 0000000..0c91883
--- /dev/null
+++ b/molecule/resources/playbooks/README.md
@@ -0,0 +1,3 @@
+This drectory contains shared playbooks and a shared Dockerfile.
+
+Visit https://molecule.readthedocs.io/en/latest/examples.html#sharing-across-scenarios for details on sharing playbooks, tests etc. across multiple scenarios.
diff --git a/molecule/resources/playbooks/converge.yml b/molecule/resources/playbooks/converge.yml
new file mode 100644
index 0000000..9a22439
--- /dev/null
+++ b/molecule/resources/playbooks/converge.yml
@@ -0,0 +1,17 @@
+---
+- name: Converge
+  hosts: all
+  pre_tasks:
+    - name: update apt cache
+      ansible.builtin.apt:
+        update_cache: true
+        upgrade: dist
+      become: true
+      when: ansible_os_family == "Debian"
+    - name: update yum cache
+      ansible.builtin.yum:
+        update_cache: true
+      become: true
+      when: ansible_os_family == "RedHat"
+  roles:
+    - {role: "ansible_lza_backup_proxy", become: true}
diff --git a/molecule/resources/playbooks/prepare.yml b/molecule/resources/playbooks/prepare.yml
new file mode 100644
index 0000000..a20ecff
--- /dev/null
+++ b/molecule/resources/playbooks/prepare.yml
@@ -0,0 +1,22 @@
+---
+- name: Prepare
+  hosts: "*"
+  tasks:
+    - name: install GPG
+      ansible.builtin.apt:
+        name: "gnupg"
+        state: latest
+        update_cache: true
+      become: true
+    - name: add GPG key for SLUB Debian repository
+      ansible.builtin.apt_key:
+        url: "https://sdvdebianrepo.slub-dresden.de/deb-repository/pub.gpg.key"
+        state: present
+      become: true
+    - name: add repo URL to sources.list
+      ansible.builtin.apt_repository:
+        repo: "deb https://sdvdebianrepo.slub-dresden.de/deb-repository bullseye main"
+        state: present
+        update_cache: true
+        mode: "0644"
+      become: true
diff --git a/molecule/default/verify.yml b/molecule/resources/playbooks/verify.yml
similarity index 85%
rename from molecule/default/verify.yml
rename to molecule/resources/playbooks/verify.yml
index 79044cd..e707420 100644
--- a/molecule/default/verify.yml
+++ b/molecule/resources/playbooks/verify.yml
@@ -6,5 +6,5 @@
   gather_facts: false
   tasks:
   - name: Example assertion
-    assert:
+    ansible.builtin.assert:
       that: true
diff --git a/molecule/virtualbox/molecule.yml b/molecule/virtualbox/molecule.yml
new file mode 100644
index 0000000..62d3860
--- /dev/null
+++ b/molecule/virtualbox/molecule.yml
@@ -0,0 +1,41 @@
+---
+dependency:
+  name: galaxy
+  enabled: false
+driver:
+  name: vagrant
+lint: |
+  set -e
+  yamllint .
+  ansible-lint -x no-loop-var-prefix,command-instead-of-module,package-latest
+platforms:
+  # Check out the documentation at
+  # https://github.com/ansible-community/molecule-vagrant#documentation
+  # for more platform parameters.
+  - name: vm-runner
+    box: debian/bullseye64
+    memory: 1024
+    # List of raw Vagrant `config` options.
+    # provider_raw_config_args:
+    #   - "customize [ 'modifyvm', :id, '--natdnshostresolver1', 'on' ]"
+    # Dictionary of `config` options.
+    config_options:
+      ssh.keep_alive: yes
+      ssh.remote_user: "'lza'"
+provisioner:
+  name: ansible
+  log: true
+  config_options:
+    defaults:
+      # https://stackoverflow.com/questions/57435811/ansible-molecule-pass-multiple-vault-ids
+      # vault_identity_list: "@$HOME/.ansible/roles/lza_install_common.pass, @$HOME/.ansible/roles/passfile_1.pass"
+      vault_identity_list: "../lza_backup_proxy.pass"
+  vvv: false
+  playbooks:
+    # create: ../resources/playbooks/create.yml
+    # destroy: ../resources/playbooks/destroy.yml
+    converge: ../resources/playbooks/converge.yml
+    prepare: ../resources/playbooks/prepare.yml
+    verify: ../resources/playbooks/verify.yml
+verifier:
+  name: ansible
diff --git a/tasks/configure_nfs_mounts.yml b/tasks/configure_nfs_mounts.yml
index bd1ffd3..c6c0aeb 100644
--- a/tasks/configure_nfs_mounts.yml
+++ b/tasks/configure_nfs_mounts.yml
@@ -1,6 +1,6 @@
 ---
 - name: Mounts für SubApp-Shares & Logs
-  mount:
+  ansible.posix.mount:
     path: "{{ item.path }}"
     src: "{{ item.src }}"
     state: "{{ item.state | default('mounted') }}"
diff --git a/tasks/configure_ssh_keys.yml b/tasks/configure_ssh_keys.yml
index 38050bb..f025221 100644
--- a/tasks/configure_ssh_keys.yml
+++ b/tasks/configure_ssh_keys.yml
@@ -1,11 +1,17 @@
 ---
+- name: mkdir ~/.ssh/
+  ansible.builtin.file:
+    path: "~/.ssh/"
+    state: directory
+    mode: "0600"
+
 - name: copy deploykey files to managed servers
-  copy:
+  ansible.builtin.copy:
     src: "{{ role_path }}/../ansible_vaults/{{ role_name }}/{{ item }}"
     dest: "~/.ssh/{{ item }}"
     owner: "root"
     group: "root"
-    mode: 0400
+    mode: "0400"
   loop:
     - "id_ed25519_deploykey"
     - "id_ed25519_deploykey.pub"
diff --git a/tasks/install_ibmsp_client.yml b/tasks/install_ibmsp_client.yml
index 204c50e..fdae0fb 100644
--- a/tasks/install_ibmsp_client.yml
+++ b/tasks/install_ibmsp_client.yml
@@ -1,6 +1,6 @@
 ---
 - name: IBMSP-Client Pakete installieren
-  apt:
+  ansible.builtin.apt:
     name: [
       # GSKit Packages
       'gskcrypt64',
@@ -20,7 +20,7 @@
     state: latest
 
 - name: link IBMSP Client kernel modules
-  file:
+  ansible.builtin.file:
     src: "/usr/local/ibm/gsk8_64/lib64/{{ item }}"
     path: "/usr/lib/{{ item }}"
     state: link
@@ -40,9 +40,10 @@
     - "libgsk8valn_64.so"
 
 - name: write IBMSP config files
-  template:
+  ansible.builtin.template:
     src: "opt/tivoli/tsm/client/ba/bin/{{ item }}.j2"
     dest: "/opt/tivoli/tsm/client/ba/bin/{{ item }}"
+    mode: "0644"
   loop:
     - "dsm.opt"
     - "dsm.sys"
@@ -53,16 +54,17 @@
 # - dsmc CLI arg ducumentation can be found at:
 #   https://publib.boulder.ibm.com/tividd/td/TSMC/GC32-0789-01/en_US/HTML/ans5000016.htm#HDRCMD6036
 - name: write password file
-  command:
+  ansible.builtin.command:
     #use: dsmc set password       <Old PW>               <New PW>
     cmd: "dsmc set password {{ ansible_hostname }} {{ ansible_hostname }}"
     creates: "/etc/adsm/TSM.sth"
   register: dsmc_result
   failed_when: (dsmc_result.rc != 0) and (dsmc_result.rc != 8)
   notify: restart dsmcad
+  tags: [molecule-notest]
 
 - name: Start dsmcad service. This service triggers regular checks for backup schedules on the IBMSP server.
-  systemd:
+  ansible.builtin.systemd:
     name: "dsmcad.service"
     state: started
 
@@ -70,22 +72,22 @@
 - name: install check-backup scripts
   block:
     - name: install Git (required by Ansible builtin Git module)
-      apt:
+      ansible.builtin.apt:
         name: "git"
         state: latest
     - name: install logrotate (required by check-backup script)
-      apt:
+      ansible.builtin.apt:
         name: "logrotate"
         state: latest
     - name: check out check-backup Git repo
-      git:
+      ansible.builtin.git:
         repo: "git@git.slub-dresden.de:slub-referat-2-3/check-backup.git"
         dest: "/tmp/check-backup/"
         key_file: "~/.ssh/id_ed25519_deploykey"
         accept_hostkey: true
         force: true
     - name: copy binaries and config to the system
-      copy:
+      ansible.builtin.copy:
         src: "/tmp/check-backup/Linux{{ item.name }}"
         dest: "{{ item.name }}"
         mode: "{{ item.mode }}"
@@ -98,7 +100,7 @@
         - name: "/usr/local/bin/check-backup.sh"
           mode: "0555"
     - name: template script config
-      template:
+      ansible.builtin.template:
         src: "etc/check-backup.cfg.j2"
         dest: "/etc/check-backup.cfg"
         owner: "root"
diff --git a/tasks/main.yml b/tasks/main.yml
index f7331bd..c8eacb9 100644
--- a/tasks/main.yml
+++ b/tasks/main.yml
@@ -1,14 +1,15 @@
 ---
 # tasks file for ansible_lza_backup_proxy
-- include_vars: "{{ role_path }}/../ansible_vaults/{{ role_name }}/{{ item }}"
+- name: include var files
+  ansible.builtin.include_vars: "{{ role_path }}/../ansible_vaults/{{ role_name }}/{{ item }}"
   loop:
     - "ibmsp.vault"
     - "nfs_mounts.vault"
   tags: [always]
 
-- import_tasks: "configure_ssh_keys.yml"
+- ansible.builtin.import_tasks: "configure_ssh_keys.yml"
   tags: [ssh, deploykey]
-- import_tasks: "install_ibmsp_client.yml"
+- ansible.builtin.import_tasks: "install_ibmsp_client.yml"
   tags: [ibmsp, tsm, backup]
-- import_tasks: "configure_nfs_mounts.yml"
+- ansible.builtin.import_tasks: "configure_nfs_mounts.yml"
   tags: [nfs]
-- 
GitLab