From 39f57f14879a2fc2809602e86c037b6642b08957 Mon Sep 17 00:00:00 2001 From: mmetc <92726601+mmetc@users.noreply.github.com> Date: Tue, 26 Jul 2022 13:09:13 +0200 Subject: [PATCH] functional tests instrumented by ansible/vagrant (#1682) --- tests/README.md | 10 +- tests/ansible/.gitignore | 2 + tests/ansible/README.md | 157 ++++++++++++++++++ tests/ansible/ansible.cfg | 14 ++ tests/ansible/env/example.sh | 51 ++++++ tests/ansible/env/pkg-sqlite.sh | 17 ++ tests/ansible/env/source-mysql.sh | 14 ++ tests/ansible/env/source-pgx.sh | 14 ++ tests/ansible/env/source-postgres.sh | 14 ++ tests/ansible/env/source-sqlite.sh | 14 ++ tests/ansible/prepare-run | 37 +++++ tests/ansible/prepare_tests.yml | 20 +++ tests/ansible/provision_dependencies.yml | 53 ++++++ tests/ansible/provision_test_suite.yml | 5 + tests/ansible/requirements.yml | 4 + .../roles/bats_requirements/defaults/main.yml | 4 + .../roles/bats_requirements/tasks/bash.yml | 51 ++++++ .../bats_requirements/tasks/daemonize.yml | 35 ++++ .../roles/bats_requirements/tasks/main.yml | 80 +++++++++ .../roles/bats_requirements/tasks/netcat.yml | 25 +++ tests/ansible/roles/common/tasks/main.yml | 39 +++++ .../tasks/install_from_deb.yml | 19 +++ .../tasks/install_from_deb_repo.yml | 33 ++++ .../tasks/install_from_rpm.yml | 20 +++ .../tasks/install_from_rpm_repo.yml | 30 ++++ .../install_crowdsec_package/tasks/main.yml | 33 ++++ .../install_crowdsec_package/vars/main.yml | 16 ++ .../install_crowdsec_tests/defaults/main.yml | 3 + .../install_crowdsec_tests/tasks/main.yml | 68 ++++++++ .../roles/machine_id/defaults/main.yml | 2 + tests/ansible/roles/machine_id/tasks/main.yml | 18 ++ .../ansible/roles/make_fixture/tasks/main.yml | 55 ++++++ .../ansible/roles/make_fixture/vars/main.yml | 2 + .../roles/run_func_tests/tasks/main.yml | 89 ++++++++++ .../roles/run_func_tests/vars/main.yml | 3 + tests/ansible/run_all.yml | 5 + tests/ansible/run_tests.yml | 18 ++ tests/ansible/vagrant/Vagrantfile.common | 34 ++++ tests/ansible/vagrant/centos-7/Vagrantfile | 6 + tests/ansible/vagrant/centos-8/Vagrantfile | 6 + .../vagrant/debian-10-buster/Vagrantfile | 6 + .../vagrant/debian-11-bullseye/Vagrantfile | 6 + .../vagrant/debian-9-stretch/Vagrantfile | 6 + .../vagrant/debian-testing/Vagrantfile | 6 + tests/ansible/vagrant/fedora-33/Vagrantfile | 8 + tests/ansible/vagrant/fedora-34/Vagrantfile | 8 + tests/ansible/vagrant/fedora-35/Vagrantfile | 8 + tests/ansible/vagrant/fedora-36/Vagrantfile | 8 + tests/ansible/vagrant/freebsd-12/Vagrantfile | 6 + tests/ansible/vagrant/freebsd-13/Vagrantfile | 6 + tests/ansible/vagrant/oracle-7/Vagrantfile | 6 + tests/ansible/vagrant/oracle-8/Vagrantfile | 6 + .../vagrant/ubuntu-16.04-xenial/Vagrantfile | 7 + .../vagrant/ubuntu-18.04-bionic/Vagrantfile | 7 + .../vagrant/ubuntu-20.04-focal/Vagrantfile | 7 + .../vagrant/ubuntu-22.04-jammy/Vagrantfile | 7 + .../vagrant/zz-amazon-linux-2/Vagrantfile | 6 + tests/ansible/vars/go.yml | 2 + tests/ansible/vars/mysql.yml | 4 + tests/ansible/vars/postgres.yml | 29 ++++ 60 files changed, 1263 insertions(+), 6 deletions(-) create mode 100644 tests/ansible/.gitignore create mode 100644 tests/ansible/README.md create mode 100644 tests/ansible/ansible.cfg create mode 100755 tests/ansible/env/example.sh create mode 100755 tests/ansible/env/pkg-sqlite.sh create mode 100755 tests/ansible/env/source-mysql.sh create mode 100755 tests/ansible/env/source-pgx.sh create mode 100755 tests/ansible/env/source-postgres.sh create mode 100755 tests/ansible/env/source-sqlite.sh create mode 100755 tests/ansible/prepare-run create mode 100644 tests/ansible/prepare_tests.yml create mode 100644 tests/ansible/provision_dependencies.yml create mode 100644 tests/ansible/provision_test_suite.yml create mode 100644 tests/ansible/requirements.yml create mode 100644 tests/ansible/roles/bats_requirements/defaults/main.yml create mode 100644 tests/ansible/roles/bats_requirements/tasks/bash.yml create mode 100644 tests/ansible/roles/bats_requirements/tasks/daemonize.yml create mode 100644 tests/ansible/roles/bats_requirements/tasks/main.yml create mode 100644 tests/ansible/roles/bats_requirements/tasks/netcat.yml create mode 100644 tests/ansible/roles/common/tasks/main.yml create mode 100644 tests/ansible/roles/install_crowdsec_package/tasks/install_from_deb.yml create mode 100644 tests/ansible/roles/install_crowdsec_package/tasks/install_from_deb_repo.yml create mode 100644 tests/ansible/roles/install_crowdsec_package/tasks/install_from_rpm.yml create mode 100644 tests/ansible/roles/install_crowdsec_package/tasks/install_from_rpm_repo.yml create mode 100644 tests/ansible/roles/install_crowdsec_package/tasks/main.yml create mode 100644 tests/ansible/roles/install_crowdsec_package/vars/main.yml create mode 100644 tests/ansible/roles/install_crowdsec_tests/defaults/main.yml create mode 100644 tests/ansible/roles/install_crowdsec_tests/tasks/main.yml create mode 100644 tests/ansible/roles/machine_id/defaults/main.yml create mode 100644 tests/ansible/roles/machine_id/tasks/main.yml create mode 100644 tests/ansible/roles/make_fixture/tasks/main.yml create mode 100644 tests/ansible/roles/make_fixture/vars/main.yml create mode 100644 tests/ansible/roles/run_func_tests/tasks/main.yml create mode 100644 tests/ansible/roles/run_func_tests/vars/main.yml create mode 100644 tests/ansible/run_all.yml create mode 100644 tests/ansible/run_tests.yml create mode 100644 tests/ansible/vagrant/Vagrantfile.common create mode 100644 tests/ansible/vagrant/centos-7/Vagrantfile create mode 100644 tests/ansible/vagrant/centos-8/Vagrantfile create mode 100644 tests/ansible/vagrant/debian-10-buster/Vagrantfile create mode 100644 tests/ansible/vagrant/debian-11-bullseye/Vagrantfile create mode 100644 tests/ansible/vagrant/debian-9-stretch/Vagrantfile create mode 100644 tests/ansible/vagrant/debian-testing/Vagrantfile create mode 100644 tests/ansible/vagrant/fedora-33/Vagrantfile create mode 100644 tests/ansible/vagrant/fedora-34/Vagrantfile create mode 100644 tests/ansible/vagrant/fedora-35/Vagrantfile create mode 100644 tests/ansible/vagrant/fedora-36/Vagrantfile create mode 100644 tests/ansible/vagrant/freebsd-12/Vagrantfile create mode 100644 tests/ansible/vagrant/freebsd-13/Vagrantfile create mode 100644 tests/ansible/vagrant/oracle-7/Vagrantfile create mode 100644 tests/ansible/vagrant/oracle-8/Vagrantfile create mode 100644 tests/ansible/vagrant/ubuntu-16.04-xenial/Vagrantfile create mode 100644 tests/ansible/vagrant/ubuntu-18.04-bionic/Vagrantfile create mode 100644 tests/ansible/vagrant/ubuntu-20.04-focal/Vagrantfile create mode 100644 tests/ansible/vagrant/ubuntu-22.04-jammy/Vagrantfile create mode 100644 tests/ansible/vagrant/zz-amazon-linux-2/Vagrantfile create mode 100644 tests/ansible/vars/go.yml create mode 100644 tests/ansible/vars/mysql.yml create mode 100644 tests/ansible/vars/postgres.yml diff --git a/tests/README.md b/tests/README.md index 2d1af960f..783cc5abf 100644 --- a/tests/README.md +++ b/tests/README.md @@ -5,10 +5,9 @@ This directory contains scripts for functional testing. The tests are run with the [bats-core](https://github.com/bats-core/bats-core) framework, which is an active fork of the older BATS (Bash Automated Testing System). -The goal is to be cross-platform but not explicitly test the packaging system -or service management. Those parts are specific to each distribution and are -tested separately (triggered by crowdsec releases, but they run in other -repositories). +With the addition of [the ansible playbooks](ansible/README.md) it is possible +to use VMs to test the binary packages, service management and other CPU +architectures. ### cscli @@ -52,13 +51,12 @@ repositories). | stream mode | `99_lapi-stream-mode | | - # How to use it ## pre-requisites - `git submodule init; git submodule update` - - `daemonize (linux) or daemon (freebsd), bash, python3, openbsd-netcat` + - `daemonize (linux) or daemon (freebsd), bash>=4.4, python3, openbsd-netcat` - `go install github.com/cloudflare/cfssl/cmd/cfssl@latest` - `go install github.com/cloudflare/cfssl/cmd/cfssljson@latest` - `go install github.com/mikefarah/yq/v4@latest` diff --git a/tests/ansible/.gitignore b/tests/ansible/.gitignore new file mode 100644 index 000000000..a5bc4e84f --- /dev/null +++ b/tests/ansible/.gitignore @@ -0,0 +1,2 @@ +.vagrant +vagrant/*/*.out diff --git a/tests/ansible/README.md b/tests/ansible/README.md new file mode 100644 index 000000000..c7ab21840 --- /dev/null +++ b/tests/ansible/README.md @@ -0,0 +1,157 @@ +# Ansible playbooks for functional testing + +These playbooks allow you to test crowdsec in a real environment, where the +application is running as root, deployed with the OS package manager, and +uses the standard init system for the distribution (systemd or other). + +This way, you can test not only the application's feature but also the packaging +boilerplate, integration scripts, and compatibility with new distribution releases, +operating systems, or architectures. + +The ansible hosts should be expendable machines with at least 1GB RAM, do not +expect them to be stable if you use them for anything else after the tests. + +Install the requirements with `ansible-galaxy install -r requiements.yml`. + +There are several Ansible playbooks. You can use `run-all.yml` to configure the +installation and run the tests, or run the playbooks separately to iterate while developing. + +- run-all.yml: run the other playbooks in the correct order. + +- provision-dependencies.yml: install the bats requirements (bash, netcat, cfssl, etc.), compilers, and database. + +- provision-test-suite.yml: install the tests scripts and bats environment. + +- prepare-tests.yml: install the package under test, and create the test fixture data. + +- run-tests.yml: run the functional tests. This is not idempotent and can be run multiple times. + +The tasks use the following environment variables. They must be exported or +ansible won't be able to see them. + +- `TEST_SUITE_GIT` (default "https://github.com/crowdsecurity/crowdsec"), + `TEST_SUITE_VERSION` (default "master"): repo URL and branch/tag/commit of + the crowdsec sources containing the test fixture and scripts. + +- `TEST_SUITE_ZIP`: optional, archive of a `crowdsecurity/crowdsec` repository + containing the test fixture and scripts. Overrides `TEST_SUITE_GIT` and + `TEST_SUITE_VERSION`. It can be created with `zip -r crowdsec.zip .` from + the root directory of the repository. + +- `DB_BACKEND`: Required. Set to "sqlite", "pgx", "mysql", "postgres". + Postgres is automatically provisioned when required. There is no + provisioning code for mysql/mariadb yet, but it can be added. + +- `PACKAGE_TESTING`: when set to false or not defined, the crowdsec binaries + to be tested are built from the sources that come from `TEST_SUITE_GIT` or + `TEST_SUITE_ZIP`. Crowdsec is then run as non-root, in a local directory. + This is basically a fancy wrapper to run `make bats-test` in a vm. + When `PACKAGE_TESTING` is set to true, however, crowdsec is installed from + a binary package (see variables below), it is run as root from systemd (or + equivalent) and uses the system-wide `/etc/crowdsec` and `/var/lib` + directories to store the test data. + +- `TEST_PACKAGE_VERSION_DEB`, `TEST_PACKAGE_VERSION_RPM`: Optional, the + version of the package under test (ex. "1.4.0-rc5"), can be in the + packagecloud "stable" or "testing" repository. Requires + `PACKAGE_TESTING=true`. You must set both variables to reuse the same set of + variables for Debian and RedHat-based distributions, because stable releases + require a package version suffix in the RPM file names. + +- `TEST_PACKAGE_FILE`: optional, file pointing to the package under test + (.deb, .rpm, .pkg...). If both `TEST_PACKAGE_VERSION_*` and + `TEST_PACKAGE_FILE` are provided, both are be installed (to test upgrades + for example). Requires `PACKAGE_TESTING=true` + +- `TEST_PACKAGE_DIR`: optional (but conflicts with `TEST_PACKAGE_FILE`), the path + to a directory containing packages with the following layout: + + For DEB: `{{ package_dir }}/{{ ansible_distribution_release }}_{{ ansible_architecture.replace('x86_64', 'amd64) }}/{{ ansible_distribution_release }}/{{ ansible_architecture.replace('x86_64', 'amd64' }}/crowdsec_*.deb` + For RPM: `{{ package_dir }}/{{ releasever }}/RPMS/{{ ansible_architecture }}/crowdsec-{{ testing_file_version }}*.{{ releasever }}.{{ ansible_architecture }}.rpm` + +- `TEST_SKIP`: optional, comma-separated list of scripts that won't be executed. + Example: `TEST_SKIP=02_nolapi.bats,03_noagent.bats` + +## Running tests with Vagrant + Ansible + +You don't need Vagrant to run the ansible tests, if you can manage your own +vm creation and inventory. + +However, to avoid relying on (and paying for..) a public cloud, we wrote vagrant +configuration files for the most common distributions we support. + +To test with Vagrant, you need to: + +- have a working libvirt environment (if you can use virt-manager to create VMs, you're golden) + +- install the vagrant-libvirt plugin (`vagrant plugin install vagrant-libvirt`. + If it complains about gem versions, blame Ruby and see if you can remove some + other conflicting plugin). + +- copy one of the `./env/*.sh` scripts to `environment.sh`, edit to your + needs, and execute it with "source environment.sh" + +- `cd vagrant/` + +- `vagrant up --no-provision; vagrant provision`. The first command creates + the VM, the second installs all the dependencies, test suite and package + under test, then runs the tests. If you run a plain `vagrant up`, it does + everything with a single command, but also destroys the VM in case of test + failure so you are left with nothing to debug. + +- `vagrant destroy` when you want to remove the VM. If you want to free up the + space taken by the base VM images, they are in + `/var/lib/libvirt/images/*VAGRANT*` + +The above steps are automated in the script `./prepare-run` (requires bash >=4.4). +It takes an enviroment file, and optionally a list of directories with vagrant +configurations. With a single parameter, it loops over all the directories in +alphabetical order. Watch out for leftover VMs if you break the loop by hand. + +After this, you will find up to 30GB of base images in `/var/lib/libvirt/images`, +which you need to remove by hand when you have finished testing or leave them +around for the next time. + +You can give more memory or CPU juice to the VMs by editing [Vagrantfile.common](vagrant/Vagrantfile.common). + +## Test Matrix + +Tests fail with unsupported configurations or when the environment is not prepared correctly +due to missing setup/teardown parts in Ansible or functional tests. False positives +are also possible due to timing issues or flaky network connections. + +If you have a result that deviates from the following matrix, that's probably a genuine bug or regression. +The data was created with crowdsec v1.4.1. + +| | source/sqlite | pkg/sqlite | source/postgres | source/pgx | source/mysql (0) | +| ------------------------- | ------------- | ---------- | --------------- | ---------- | ---------------- | +| AmazonLinux 2 | ✓ (1) | ✓ (1) | old-db | old-db | wip | +| CentOS 7 | ✓ | ✓ | old-db | old-db | ✓ | +| CentOS 8 | ✓ | ✓ | ✓ | ✓ | ✓ | +| Debian 9 (stretch) | ✓ | ✓ | old-db | old-db | wip | +| Debian 10 (buster) | ✓ | ✓ | ✓ | ✓ | ✓ | +| Debian 11 (bullseye) | ✓ | ✓ | ✓ | ✓ | ✓ | +| Debian (testing/bookworm) | ✓ | ✓ | wip | wip | wip | +| Fedora 33 | ✓ | ✓ | wip | wip | wip | +| Fedora 34 | ✓ | ✓ | ✓ | ✓ | wip | +| Fedora 35 | ✓ | ✓ | ✓ | ✓ | wip | +| Fedora 36 | ✓ | ✓ | ✓ | ✓ | wip | +| FreeBSD 12 | ✓ | wip | wip | wip | wip | +| FreeBSD 13 | ✓ | wip | wip | wip | wip | +| Oracle 7 | ✓ | ✓ | wip | wip | ✓ | +| Oracle 8 | ✓ | ✓ | ✓ | ✓ | ✓ | +| Ubuntu 16.04 (xenial) | ✓ | ✓ | wip | wip | ✓ | +| Ubuntu 18.04 (bionic) | ✓ | ✓ | ✓ | ✓ | ✓ | +| Ubuntu 20.04 (focal) | ✓ | ✓ | ✓ | ✓ | ✓ | +| Ubuntu 22.04 (jammy) | ✓ | ✓ | ✓ | ✓ | ✓ | +| | | | | | | + +Note: all tests with `local/` are expected to pass for `pkg/` as well. + +wip - missing ansible or bats parts, working on it + +old-db - the database that ships with the distribution is not supported (Postgres < 10) + +0 - MySQL or MariaDB, depending on distribution defaults + +1 - ansible may hang, passes all tests if run by hand diff --git a/tests/ansible/ansible.cfg b/tests/ansible/ansible.cfg new file mode 100644 index 000000000..fce8cb99c --- /dev/null +++ b/tests/ansible/ansible.cfg @@ -0,0 +1,14 @@ +[defaults] +pipelining = True +force_color = True + +# inventory = inventory.yml +callbacks_enabled = timer + +# more compact and readable output +stdout_callback = debug +display_skipped_hosts = no +display_ok_hosts = yes + +[ssh_connection] +ssh_args = -o ControlMaster=auto -o ControlPersist=60s diff --git a/tests/ansible/env/example.sh b/tests/ansible/env/example.sh new file mode 100755 index 000000000..f86ee3ea5 --- /dev/null +++ b/tests/ansible/env/example.sh @@ -0,0 +1,51 @@ +#!/bin/sh + +## DB_BACKEND is required, because even if it has a sensible default (sqlite) +## all other variables can have an empty value. So if DB_BACKEND is missing you +## may have forgot to set the environment for the test run. +## One of "sqlite", "postgres", "pgx", "mysql" +DB_BACKEND=sqlite + +## Set this to test a binary package (deb, rpm..). If missing or false, +## crowdsec will be built from sources and tested an non-root without installation. +# PACKAGE_TESTING=true + +## The URL of a crowdsec repository with the test scripts. +# TEST_SUITE_GIT="https://github.com/crowdsecurity/crowdsec" + +## The branch, tag or commit of the test scripts. +# TEST_SUITE_VERSION="master" + +## The path to a crowdsec.zip file containing the crowdsec sources with test scripts. +## Overrides TEST_SUITE_GIT and TEST_SUITE_VERSION. +# TEST_SUITE_ZIP="/tmp/crowdsec.zip" + +## TEST_PACKAGE_VERSION_DEB is the version of the package under test. +## Can be different from TEST_PACKAGE_VERSION_RPM in case of stable releases (no '-1' suffix). +# TEST_PACKAGE_VERSION_DEB=1.4.1 + +## TEST_PACKAGE_VERSION_RPM is the version of the package under test. +## Can be different from TEST_PACKAGE_VERSION_DEB in case of stable releases (rpm requires a '-1' suffix). +# TEST_PACKAGE_VERSION_RPM=1.4.1-1 + +## The path to a crowdsec binary package (.deb, .rpm..). If both this and TEST_PACKAGE_VERSION_* are set, +## the package from TEST_PACKAGE_VERSION_* will be installed first, then replaced by the package in the +## provided file. This is a way to test upgrades. +# TEST_PACKAGE_FILE="/tmp/crowdsec.deb" + +## The path to a bundle with all the .deb and .rpm packages, split by architecture, distribution and version (see README). +# TEST_PACKAGE_DIR=/path/to/packages/1.4.1-rc1 + +## A comma-separated list of test scripts to skip. Example: "02_nolapi.bats,03_noagent.bats" +# TEST_SKIP= + +export DB_BACKEND +export PACKAGE_TESTING +export TEST_SUITE_GIT +export TEST_SUITE_VERSION +export TEST_SUITE_ZIP +export TEST_PACKAGE_VERSION_DEB +export TEST_PACKAGE_VERSION_RPM +export TEST_PACKAGE_FILE +export TEST_PACKAGE_DIR +export TEST_SKIP diff --git a/tests/ansible/env/pkg-sqlite.sh b/tests/ansible/env/pkg-sqlite.sh new file mode 100755 index 000000000..a161260ef --- /dev/null +++ b/tests/ansible/env/pkg-sqlite.sh @@ -0,0 +1,17 @@ +#!/bin/sh + +DB_BACKEND=sqlite +PACKAGE_TESTING=true +TEST_PACKAGE_VERSION_DEB=1.4.1 +TEST_PACKAGE_VERSION_RPM=1.4.1-1 + +export DB_BACKEND +export PACKAGE_TESTING +export TEST_SUITE_GIT +export TEST_SUITE_VERSION +export TEST_SUITE_ZIP +export TEST_PACKAGE_VERSION_DEB +export TEST_PACKAGE_VERSION_RPM +export TEST_PACKAGE_FILE +export TEST_PACKAGE_DIR +export TEST_SKIP diff --git a/tests/ansible/env/source-mysql.sh b/tests/ansible/env/source-mysql.sh new file mode 100755 index 000000000..599e522bf --- /dev/null +++ b/tests/ansible/env/source-mysql.sh @@ -0,0 +1,14 @@ +#!/bin/sh + +DB_BACKEND=mysql + +export DB_BACKEND +export PACKAGE_TESTING +export TEST_SUITE_GIT +export TEST_SUITE_VERSION +export TEST_SUITE_ZIP +export TEST_PACKAGE_VERSION_DEB +export TEST_PACKAGE_VERSION_RPM +export TEST_PACKAGE_FILE +export TEST_PACKAGE_DIR +export TEST_SKIP diff --git a/tests/ansible/env/source-pgx.sh b/tests/ansible/env/source-pgx.sh new file mode 100755 index 000000000..b23771fc7 --- /dev/null +++ b/tests/ansible/env/source-pgx.sh @@ -0,0 +1,14 @@ +#!/bin/sh + +DB_BACKEND=pgx + +export DB_BACKEND +export PACKAGE_TESTING +export TEST_SUITE_GIT +export TEST_SUITE_VERSION +export TEST_SUITE_ZIP +export TEST_PACKAGE_VERSION_DEB +export TEST_PACKAGE_VERSION_RPM +export TEST_PACKAGE_FILE +export TEST_PACKAGE_DIR +export TEST_SKIP diff --git a/tests/ansible/env/source-postgres.sh b/tests/ansible/env/source-postgres.sh new file mode 100755 index 000000000..7f76f4e37 --- /dev/null +++ b/tests/ansible/env/source-postgres.sh @@ -0,0 +1,14 @@ +#!/bin/sh + +DB_BACKEND=postgres + +export DB_BACKEND +export PACKAGE_TESTING +export TEST_SUITE_GIT +export TEST_SUITE_VERSION +export TEST_SUITE_ZIP +export TEST_PACKAGE_VERSION_DEB +export TEST_PACKAGE_VERSION_RPM +export TEST_PACKAGE_FILE +export TEST_PACKAGE_DIR +export TEST_SKIP diff --git a/tests/ansible/env/source-sqlite.sh b/tests/ansible/env/source-sqlite.sh new file mode 100755 index 000000000..d1d585ac9 --- /dev/null +++ b/tests/ansible/env/source-sqlite.sh @@ -0,0 +1,14 @@ +#!/bin/sh + +DB_BACKEND=sqlite + +export DB_BACKEND +export PACKAGE_TESTING +export TEST_SUITE_GIT +export TEST_SUITE_VERSION +export TEST_SUITE_ZIP +export TEST_PACKAGE_VERSION_DEB +export TEST_PACKAGE_VERSION_RPM +export TEST_PACKAGE_FILE +export TEST_PACKAGE_DIR +export TEST_SKIP diff --git a/tests/ansible/prepare-run b/tests/ansible/prepare-run new file mode 100755 index 000000000..d37823e78 --- /dev/null +++ b/tests/ansible/prepare-run @@ -0,0 +1,37 @@ +#!/usr/bin/env bash + +# This loops over all the available boxes, running the test suite on each one. +# The results are collected in a file. If the file already exists, tests are not run again. + +env=$1 + +if [[ -z "${env}" ]]; then + echo "Usage: $0 [vagrant-dir]..." + exit 1 +fi + +shift + +vagrant_dirs=("$@") +if [[ $# -eq 0 ]]; then + readarray -d '' vagrant_dirs < <(find vagrant -mindepth 1 -maxdepth 1 -type d -print0 | sort -z) +fi + +#shellcheck disable=SC1090 +. "${env}" + +VAGRANT_FORCE_COLOR=true +export VAGRANT_FORCE_COLOR + +for vm in "${vagrant_dirs[@]}"; do + outfile="$(basename "${env}").out" + pushd "${vm}" >/dev/null || exit + if [[ ! -f "${outfile}" ]]; then + vagrant up --no-provision + vagrant provision 2>&1 | tee "${outfile}" + vagrant destroy -f + else + echo "Skipping: ${vm}, file ${outfile} already exists." >&2 + fi + popd >/dev/null || exit +done diff --git a/tests/ansible/prepare_tests.yml b/tests/ansible/prepare_tests.yml new file mode 100644 index 000000000..78c9ecbbc --- /dev/null +++ b/tests/ansible/prepare_tests.yml @@ -0,0 +1,20 @@ +--- +- name: "prepare functional tests" + hosts: all + gather_facts: true + vars_files: + - vars/go.yml + - vars/mysql.yml + - vars/postgres.yml + environment: + PGHOST: 127.0.0.1 + PGPORT: 5432 + PGPASSWORD: "{{ postgresql_users[0].password }}" + PGUSER: postgres + MYSQL_HOST: localhost + MYSQL_PORT: 3306 + MYSQL_PASSWORD: "{{ mysql_root_password }}" + MYSQL_USER: "root" + roles: + - role: install_crowdsec_package + - role: make_fixture diff --git a/tests/ansible/provision_dependencies.yml b/tests/ansible/provision_dependencies.yml new file mode 100644 index 000000000..cdec8afc1 --- /dev/null +++ b/tests/ansible/provision_dependencies.yml @@ -0,0 +1,53 @@ +--- +- name: "install Go (!freebsd)" + hosts: all + gather_facts: true + vars_files: + - vars/go.yml + tasks: + - ansible.builtin.include_role: + name: gantsign.golang + when: + - ansible_os_family != "FreeBSD" + +- name: "install Go (freebsd)" + hosts: all + gather_facts: true + become: true + tasks: + - ansible.builtin.package: + name: go + state: present + when: + - ansible_os_family == "FreeBSD" + +- name: "apply common configuration to all nodes" + hosts: all + vars_files: + - vars/go.yml + roles: + - common + - machine_id + - bats_requirements + +- name: "install Postgres" + hosts: all + become: true + vars_files: + - vars/postgres.yml + tasks: + - ansible.builtin.include_role: + name: geerlingguy.postgresql + when: + - lookup('ansible.builtin.env', 'DB_BACKEND') in ['pgx', 'postgres'] + +- name: "install MySQL" + hosts: all + become: true + vars_files: + - vars/mysql.yml + tasks: + - ansible.builtin.include_role: + name: geerlingguy.mysql + when: + - lookup('ansible.builtin.env', 'DB_BACKEND') == 'mysql' diff --git a/tests/ansible/provision_test_suite.yml b/tests/ansible/provision_test_suite.yml new file mode 100644 index 000000000..3229a5ca1 --- /dev/null +++ b/tests/ansible/provision_test_suite.yml @@ -0,0 +1,5 @@ +--- +- name: "install the test scripts" + hosts: all + roles: + - install_crowdsec_tests diff --git a/tests/ansible/requirements.yml b/tests/ansible/requirements.yml new file mode 100644 index 000000000..e20812ebf --- /dev/null +++ b/tests/ansible/requirements.yml @@ -0,0 +1,4 @@ +--- +- src: geerlingguy.postgresql +- src: geerlingguy.mysql +- src: gantsign.golang diff --git a/tests/ansible/roles/bats_requirements/defaults/main.yml b/tests/ansible/roles/bats_requirements/defaults/main.yml new file mode 100644 index 000000000..e18ee3032 --- /dev/null +++ b/tests/ansible/roles/bats_requirements/defaults/main.yml @@ -0,0 +1,4 @@ +--- +build_bash: false + +build_daemonize: (ansible_distribution == "Ubuntu" and ansible_distribution_version == '16.04') or ansible_distribution == 'Amazon' diff --git a/tests/ansible/roles/bats_requirements/tasks/bash.yml b/tests/ansible/roles/bats_requirements/tasks/bash.yml new file mode 100644 index 000000000..ff0c92469 --- /dev/null +++ b/tests/ansible/roles/bats_requirements/tasks/bash.yml @@ -0,0 +1,51 @@ +--- +- name: "look up bash version" + become: false + ansible.builtin.package_facts: + +- name: "bash version found" + become: false + ansible.builtin.debug: + var: ansible_facts.packages['bash'][0].version + +- name: "check if bash needs building (<4.4)" + become: false + ansible.builtin.set_fact: + build_bash: "{{ ansible_facts.packages['bash'][0].version is version('4.4', '<') }}" + +- name: "build bash: download" + become: false + ansible.builtin.unarchive: + src: http://ftp.gnu.org/gnu/bash/bash-5.1.16.tar.gz + dest: "{{ ansible_env.HOME }}" + remote_src: true + creates: "{{ ansible_env.HOME }}/bash-5.1.16" + when: + - build_bash + +- name: "build bash: configure" + become: false + ansible.builtin.command: + cmd: "./configure --prefix=/opt/bash" + creates: ./Makefile + chdir: "{{ ansible_env.HOME }}/bash-5.1.16" + when: + - build_bash + +- name: "build bash: create /opt/bash" + become: true + ansible.builtin.file: + path: /opt/bash + state: directory + mode: 0o755 + when: + - build_bash + +- name: "build bash: make install" + become: true + ansible.builtin.command: + cmd: "make install" + creates: /opt/bash/bin/bash + chdir: "{{ ansible_env.HOME }}/bash-5.1.16" + when: + - build_bash diff --git a/tests/ansible/roles/bats_requirements/tasks/daemonize.yml b/tests/ansible/roles/bats_requirements/tasks/daemonize.yml new file mode 100644 index 000000000..59326f1ea --- /dev/null +++ b/tests/ansible/roles/bats_requirements/tasks/daemonize.yml @@ -0,0 +1,35 @@ +--- +- name: "install daemonize package" + become: true + ansible.builtin.package: + name: + - daemonize + when: + - not build_daemonize + +- name: "build daemonize: git checkout" + become: false + ansible.builtin.git: + repo: https://github.com/bmc/daemonize + dest: "{{ ansible_env.HOME }}/daemonize" + version: release-1.7.8 + when: + - build_daemonize + +- name: "build daemonize: configure" + become: false + ansible.builtin.command: + cmd: "./configure --prefix=/usr/local" + creates: ./Makefile + chdir: "{{ ansible_env.HOME }}/daemonize" + when: + - build_daemonize + +- name: "build daemonize: make install" + become: true + ansible.builtin.command: + cmd: "make all install" + creates: /usr/local/sbin/daemonize + chdir: "{{ ansible_env.HOME }}/daemonize" + when: + - build_daemonize diff --git a/tests/ansible/roles/bats_requirements/tasks/main.yml b/tests/ansible/roles/bats_requirements/tasks/main.yml new file mode 100644 index 000000000..0a2c6b9c5 --- /dev/null +++ b/tests/ansible/roles/bats_requirements/tasks/main.yml @@ -0,0 +1,80 @@ +--- +- name: "install bash" + ansible.builtin.import_tasks: bash.yml + +- name: "Install daemonize" + ansible.builtin.import_tasks: daemonize.yml + when: + - ansible_os_family != 'FreeBSD' + +- name: "install netcat" + ansible.builtin.import_tasks: netcat.yml + +- name: "Install curl, jq, openssl, python3" + become: true + ansible.builtin.package: + name: + - curl + - jq + - openssl + - python3 + +- name: "install bc (!freebsd)" + become: true + ansible.builtin.package: + name: + - bc + when: + - ansible_os_family != 'FreeBSD' + +- name: "install base64(freebsd)" + become: true + ansible.builtin.package: + name: + - base64 + when: + - ansible_os_family == 'FreeBSD' + +- name: "install pidof (Amazon)" + become: true + ansible.builtin.package: + name: + - procps-ng + when: + - ansible_distribution == 'Amazon' + +- name: "install gcc (for go-sqlite, needs cgo)" + become: true + ansible.builtin.package: + name: + - gcc + +- name: "install cfssl" + become: true + ansible.builtin.command: + cmd: "go install github.com/cloudflare/cfssl/cmd/cfssl@latest" + creates: /usr/bin/cfssl + environment: + GOBIN: /usr/bin + # make sure we use the built version of go, if there is one + PATH: "{{ golang_install_dir }}/bin:{{ ansible_env.PATH }}" + +- name: "install cfssljson" + become: true + ansible.builtin.command: + cmd: "go install github.com/cloudflare/cfssl/cmd/cfssljson@latest" + creates: /usr/bin/cfssljson + environment: + GOBIN: /usr/bin + # make sure we use the built version of go, if there is one + PATH: "{{ golang_install_dir }}/bin:{{ ansible_env.PATH }}" + +- name: "install yq" + become: true + ansible.builtin.command: + cmd: "go install github.com/mikefarah/yq/v4@latest" + creates: /usr/bin/yq + environment: + GOBIN: /usr/bin + # make sure we use the built version of go, if there is one + PATH: "{{ golang_install_dir }}/bin:{{ ansible_env.PATH }}" diff --git a/tests/ansible/roles/bats_requirements/tasks/netcat.yml b/tests/ansible/roles/bats_requirements/tasks/netcat.yml new file mode 100644 index 000000000..feb417448 --- /dev/null +++ b/tests/ansible/roles/bats_requirements/tasks/netcat.yml @@ -0,0 +1,25 @@ +--- +- name: "install netcat (Amazon, Fedora, CentOS)" + become: true + ansible.builtin.package: + name: + - nmap-ncat + when: + - ansible_facts['distribution'] in ['Amazon', 'Fedora', 'CentOS', 'OracleLinux'] + +- name: "install netcat (RedHat)" + become: true + ansible.builtin.package: + name: + - netcat + when: + - ansible_facts['distribution'] == 'RedHat' + +# "netcat" does not exist in some versions (only -traditional or -openbsd) +- name: "install netcat (Debian)" + become: true + ansible.builtin.package: + name: + - netcat-traditional + when: + - ansible_os_family == "Debian" diff --git a/tests/ansible/roles/common/tasks/main.yml b/tests/ansible/roles/common/tasks/main.yml new file mode 100644 index 000000000..b7a14a7c2 --- /dev/null +++ b/tests/ansible/roles/common/tasks/main.yml @@ -0,0 +1,39 @@ +--- +# required for (at least) jq +- name: "enable EPEL" + become: true + ansible.builtin.package: + name: epel-release + when: + - ansible_distribution == 'CentOS' + +- name: "update package cache (Debian)" + become: true + ansible.builtin.apt: + upgrade: false + update_cache: true + when: + - ansible_os_family == "Debian" + +- name: "install gcc, git" + become: true + ansible.builtin.package: + name: + - gcc + - git + +- name: "install make (Linux)" + become: true + ansible.builtin.package: + name: + - make + when: + - ansible_os_family != "FreeBSD" + +- name: "install gmake (FreeBSD)" + become: true + ansible.builtin.package: + name: + - gmake + when: + - ansible_os_family == "FreeBSD" diff --git a/tests/ansible/roles/install_crowdsec_package/tasks/install_from_deb.yml b/tests/ansible/roles/install_crowdsec_package/tasks/install_from_deb.yml new file mode 100644 index 000000000..a8b341843 --- /dev/null +++ b/tests/ansible/roles/install_crowdsec_package/tasks/install_from_deb.yml @@ -0,0 +1,19 @@ +--- +- name: "set package_file from package_dir" + ansible.builtin.set_fact: + package_file: "{{ package_dir }}/{{ ansible_distribution_release }}_{{ ansible_architecture.replace('x86_64', 'amd64) }}/{{ ansible_distribution_release }}/{{ ansible_architecture.replace('x86_64', 'amd64' }}/crowdsec_*.deb" + when: + - (package_dir is defined) and (package_dir | length > 0) + +- name: "copy built file for deb-like" + become: false + ansible.builtin.copy: + src: "{{ package_file }}" + dest: "{{ ansible_env.HOME }}/crowdsec.deb" + mode: 0o644 + +- name: "install crowdsec on deb-like" + become: true + ansible.builtin.apt: + name: "{{ ansible_env.HOME }}/crowdsec.deb" + allow_downgrade: true diff --git a/tests/ansible/roles/install_crowdsec_package/tasks/install_from_deb_repo.yml b/tests/ansible/roles/install_crowdsec_package/tasks/install_from_deb_repo.yml new file mode 100644 index 000000000..624603b3c --- /dev/null +++ b/tests/ansible/roles/install_crowdsec_package/tasks/install_from_deb_repo.yml @@ -0,0 +1,33 @@ +--- +- name: "install stuff" + become: true + ansible.builtin.package: + name: + - apt-transport-https + - gnupg + +- name: "install crowdsec repo [1/2] (*.deb)" + become: true + ansible.builtin.apt_key: + url: https://packagecloud.io/crowdsec/crowdsec/gpgkey + +- name: "add crowdsec repo [2/2] (*.deb)" + become: true + ansible.builtin.apt_repository: + repo: deb https://packagecloud.io/crowdsec/crowdsec/{{ ansible_distribution | lower }}/ {{ ansible_distribution_release }} main + +- name: "install crowdsec testing repo [1/2] (*.deb)" + become: true + ansible.builtin.apt_key: + url: https://packagecloud.io/crowdsec/crowdsec-testing/gpgkey + +- name: "add crowdsec testing repo [1/2] (*.deb)" + become: true + ansible.builtin.apt_repository: + repo: deb https://packagecloud.io/crowdsec/crowdsec-testing/{{ ansible_distribution | lower }}/ {{ ansible_distribution_release }} main + +- name: "install crowdsec" + become: true + ansible.builtin.package: + name: + - crowdsec={{ package_version_deb }} diff --git a/tests/ansible/roles/install_crowdsec_package/tasks/install_from_rpm.yml b/tests/ansible/roles/install_crowdsec_package/tasks/install_from_rpm.yml new file mode 100644 index 000000000..a96ab8387 --- /dev/null +++ b/tests/ansible/roles/install_crowdsec_package/tasks/install_from_rpm.yml @@ -0,0 +1,20 @@ +--- +- name: "set package_file from package_dir" + ansible.builtin.set_fact: + package_file: "{{ package_dir }}/{{ releasever }}/RPMS/{{ ansible_architecture }}/crowdsec-{{ testing_file_version }}*.{{ releasever }}.{{ ansible_architecture }}.rpm" + when: + - (package_dir is defined) and (package_dir | length > 0) + +- name: "copy built file for rpm-like" + become: false + ansible.builtin.copy: + src: "{{ package_file }}" + dest: "{{ ansible_env.HOME }}/crowdsec.rpm" + mode: 0o644 + +- name: "install crowdsec on rpm-like" + become: true + ansible.builtin.yum: + name: "{{ ansible_env.HOME }}/crowdsec.rpm" + disable_gpg_check: true + allow_downgrade: true diff --git a/tests/ansible/roles/install_crowdsec_package/tasks/install_from_rpm_repo.yml b/tests/ansible/roles/install_crowdsec_package/tasks/install_from_rpm_repo.yml new file mode 100644 index 000000000..27b5a6485 --- /dev/null +++ b/tests/ansible/roles/install_crowdsec_package/tasks/install_from_rpm_repo.yml @@ -0,0 +1,30 @@ +--- +- name: "download the rpm script" + ansible.builtin.get_url: + url: https://packagecloud.io/install/repositories/crowdsec/crowdsec/script.rpm.sh + dest: "{{ ansible_env.HOME }}/rpm.sh" + mode: 0o775 + +- name: "install crowdsec rpm repo" + become: true + ansible.builtin.command: + cmd: "{{ ansible_env.HOME }}/rpm.sh" + changed_when: false + +- name: "download the (testing) rpm script" + ansible.builtin.get_url: + url: https://packagecloud.io/install/repositories/crowdsec/crowdsec-testing/script.rpm.sh + dest: "{{ ansible_env.HOME }}/rpm-testing.sh" + mode: 0o775 + +- name: "install crowdsec (testing) rpm repo" + become: true + ansible.builtin.command: + cmd: "{{ ansible_env.HOME }}/rpm-testing.sh" + changed_when: false + +- name: "install crowdsec" + become: true + ansible.builtin.package: + name: + - crowdsec-{{ package_version_rpm }}.{{ releasever.replace('amzn2', 'el7').replace('ol7', 'el7').replace('ol8', 'el8') }} diff --git a/tests/ansible/roles/install_crowdsec_package/tasks/main.yml b/tests/ansible/roles/install_crowdsec_package/tasks/main.yml new file mode 100644 index 000000000..da22a598e --- /dev/null +++ b/tests/ansible/roles/install_crowdsec_package/tasks/main.yml @@ -0,0 +1,33 @@ +--- +- name: "system details" + ansible.builtin.debug: + msg: | + Distribution: {{ ansible_distribution }} + Version: {{ ansible_distribution_version }} + Major: {{ ansible_distribution_major_version }} + Release: {{ ansible_distribution_release }} + Releasever: {{ releasever }} + +- name: "install from binary repository (RedHat)" + ansible.builtin.import_tasks: install_from_rpm_repo.yml + when: + - (package_version_rpm is defined) and (package_version_rpm|length > 0) + - ansible_os_family == "RedHat" + +- name: "install from binary repository (Debian)" + ansible.builtin.import_tasks: install_from_deb_repo.yml + when: + - (package_version_deb is defined) and (package_version_deb|length > 0) + - ansible_os_family == "Debian" + +- name: "install from *.rpm package file" + ansible.builtin.import_tasks: install_from_rpm.yml + when: + - (package_file is defined) and (package_file|length > 0) + - ansible_os_family == "RedHat" + +- name: "install from *.deb package file" + ansible.builtin.import_tasks: install_from_deb.yml + when: + - (package_file is defined) and (package_file|length > 0) + - ansible_os_family == "Debian" diff --git a/tests/ansible/roles/install_crowdsec_package/vars/main.yml b/tests/ansible/roles/install_crowdsec_package/vars/main.yml new file mode 100644 index 000000000..90654b74c --- /dev/null +++ b/tests/ansible/roles/install_crowdsec_package/vars/main.yml @@ -0,0 +1,16 @@ +--- +release: + CentOS: el + Fedora: fc + Amazon: amzn + Debian: debian + Ubuntu: ubuntu + FreeBSD: freebsd + OracleLinux: ol + +releasever: "{{ release[ansible_distribution] + ansible_distribution_major_version }}" + +package_version_deb: "{{ lookup('ansible.builtin.env', 'TEST_PACKAGE_VERSION_DEB') }}" +package_version_rpm: "{{ lookup('ansible.builtin.env', 'TEST_PACKAGE_VERSION_RPM') }}" +package_file: "{{ lookup('ansible.builtin.env', 'TEST_PACKAGE_FILE') }}" +package_dir: "{{ lookup('ansible.builtin.env', 'TEST_PACKAGE_DIR') }}" diff --git a/tests/ansible/roles/install_crowdsec_tests/defaults/main.yml b/tests/ansible/roles/install_crowdsec_tests/defaults/main.yml new file mode 100644 index 000000000..e02d71b58 --- /dev/null +++ b/tests/ansible/roles/install_crowdsec_tests/defaults/main.yml @@ -0,0 +1,3 @@ +--- +suite_git: "https://github.com/crowdsecurity/crowdsec" +suite_version: "master" diff --git a/tests/ansible/roles/install_crowdsec_tests/tasks/main.yml b/tests/ansible/roles/install_crowdsec_tests/tasks/main.yml new file mode 100644 index 000000000..b728a9be5 --- /dev/null +++ b/tests/ansible/roles/install_crowdsec_tests/tasks/main.yml @@ -0,0 +1,68 @@ +--- +- name: "lookup $TEST_SUITE_GIT" + ansible.builtin.set_fact: + suite_git: "{{ lookup('ansible.builtin.env', 'TEST_SUITE_GIT') }}" + when: lookup('ansible.builtin.env', 'TEST_SUITE_GIT') | length>0 + +- name: "lookup $TEST_SUITE_VERSION" + ansible.builtin.set_fact: + suite_version: "{{ lookup('ansible.builtin.env', 'TEST_SUITE_VERSION') }}" + when: lookup('ansible.builtin.env', 'TEST_SUITE_VERSION') | length>0 + +- name: "lookup $TEST_SUITE_ZIP" + ansible.builtin.set_fact: + suite_zip: "{{ lookup('ansible.builtin.env', 'TEST_SUITE_ZIP') }}" + when: lookup('ansible.builtin.env', 'TEST_SUITE_ZIP') | length>0 + +- name: "install unzip" + become: true + ansible.builtin.package: + name: + - unzip + when: + - (suite_zip is defined) and (suite_zip|length > 0) + +- name: "install tests: create crowdsec dir" + become: false + ansible.builtin.file: + path: "{{ ansible_env.HOME }}/crowdsec" + state: directory + mode: 0o700 + when: + - (suite_zip is defined) and (suite_zip|length > 0) + +- name: "install tests: extract crowdsec" + become: false + ansible.builtin.unarchive: + src: "{{ suite_zip }}" + dest: "{{ ansible_env.HOME }}/crowdsec" + when: + - (suite_zip is defined) and (suite_zip|length > 0) + +- name: "install tests: git submodules for bats" + become: false + ansible.builtin.command: + cmd: "{{ item }}" + chdir: "{{ ansible_env.HOME }}/crowdsec" + with_items: + - git submodule init + - git submodule update + when: + - (suite_zip is defined) and (suite_zip|length > 0) + +- name: "install tests: checkout crowdsec" + become: false + ansible.builtin.git: + repo: "{{ suite_git }}" + dest: "{{ ansible_env.HOME }}/crowdsec" + single_branch: true + version: "{{ suite_version }}" + when: + - (suite_zip is not defined) or (suite_zip|length == 0) + +- name: "install tests: create crowdsec tests/local dir" + become: false + ansible.builtin.file: + path: "{{ ansible_env.HOME }}/crowdsec/tests/local" + state: directory + mode: 0o755 diff --git a/tests/ansible/roles/machine_id/defaults/main.yml b/tests/ansible/roles/machine_id/defaults/main.yml new file mode 100644 index 000000000..5093c5a0d --- /dev/null +++ b/tests/ansible/roles/machine_id/defaults/main.yml @@ -0,0 +1,2 @@ +--- +machine_id: "githubciXXXXXXXXXXXXXXXXXXXXXXXX\n" diff --git a/tests/ansible/roles/machine_id/tasks/main.yml b/tests/ansible/roles/machine_id/tasks/main.yml new file mode 100644 index 000000000..30eee41e5 --- /dev/null +++ b/tests/ansible/roles/machine_id/tasks/main.yml @@ -0,0 +1,18 @@ +--- +- name: "set /etc/machine-id" + become: true + ansible.builtin.copy: + dest: /etc/machine-id + content: "{{ machine_id }}" + mode: 0o444 + +# some distributions use var/lib/dbus, +# but the directory doesn't exists on fedora +- name: "set /var/lib/dbus/machine-id" + become: true + ansible.builtin.copy: + dest: /var/lib/dbus/machine-id + content: "{{ machine_id }}" + mode: 0o444 + when: + - ansible_os_family != 'FreeBSD' and ansible_distribution != "Fedora" diff --git a/tests/ansible/roles/make_fixture/tasks/main.yml b/tests/ansible/roles/make_fixture/tasks/main.yml new file mode 100644 index 000000000..bbf539215 --- /dev/null +++ b/tests/ansible/roles/make_fixture/tasks/main.yml @@ -0,0 +1,55 @@ +--- +- name: "set make_cmd = make (!freebsd)" + ansible.builtin.set_fact: + make_cmd: make + when: + - ansible_os_family != 'FreeBSD' + +- name: "set make_cmd = gmake (freebsd)" + ansible.builtin.set_fact: + make_cmd: gmake + when: + - ansible_os_family == 'FreeBSD' + +- name: "build crowdsec from sources, prepare test environment and fixture" + become: false + ansible.builtin.command: + cmd: "{{ make_cmd }} bats-build bats-fixture" + chdir: "{{ ansible_env.HOME }}/crowdsec" + creates: "{{ ansible_env.HOME }}/crowdsec/tests/local-init/init-config-data.tar" + environment: + DB_BACKEND: "{{ lookup('ansible.builtin.env', 'DB_BACKEND') }}" + # daemonize -> /usr/bin or /usr/local/sbin + # pidof -> /usr/sbin + # bash -> /opt/bash/bin + PATH: "/opt/bash/bin:{{ ansible_env.PATH }}:{{ golang_install_dir }}/bin/:/usr/sbin:/usr/local/sbin" + when: (package_testing is not defined) or (package_testing in ['', 'false', 'False']) + +- name: "prepare test environment and fixture for binary package" + become: true + ansible.builtin.command: + cmd: "{{ make_cmd }} bats-environment bats-check-requirements bats-fixture" + chdir: "{{ ansible_env.HOME }}/crowdsec" + creates: "{{ ansible_env.HOME }}/crowdsec/tests/local-init/init-config-data.tar" + environment: + PACKAGE_TESTING: "{{ package_testing }}" + DB_BACKEND: "{{ lookup('ansible.builtin.env', 'DB_BACKEND') }}" + # daemonize -> /usr/bin or /usr/local/sbin + # pidof -> /usr/sbin + # bash -> /opt/bash/bin + PATH: "/opt/bash/bin:{{ ansible_env.PATH }}:/usr/sbin:/usr/local/sbin" + when: (package_testing is defined) and (package_testing not in ['', 'false', 'False']) + +- name: "read .environment.sh" + ansible.builtin.slurp: + src: "{{ ansible_env.HOME }}/crowdsec/tests/.environment.sh" + changed_when: false + register: envfile + +- name: "show .environment.sh" + ansible.builtin.debug: + msg: "{{ envfile['content'] | b64decode }}" + +- name: "show environment variables" + ansible.builtin.debug: + msg: "{{ ansible_env | to_nice_yaml }}" diff --git a/tests/ansible/roles/make_fixture/vars/main.yml b/tests/ansible/roles/make_fixture/vars/main.yml new file mode 100644 index 000000000..ebf1c8a9a --- /dev/null +++ b/tests/ansible/roles/make_fixture/vars/main.yml @@ -0,0 +1,2 @@ +--- +package_testing: "{{ lookup('ansible.builtin.env', 'PACKAGE_TESTING') }}" diff --git a/tests/ansible/roles/run_func_tests/tasks/main.yml b/tests/ansible/roles/run_func_tests/tasks/main.yml new file mode 100644 index 000000000..9338488f5 --- /dev/null +++ b/tests/ansible/roles/run_func_tests/tasks/main.yml @@ -0,0 +1,89 @@ +--- +- name: "create /lib/systemd/system/crowdsec.service.d" + become: true + ansible.builtin.file: + owner: root + group: root + mode: 0o755 + path: /lib/systemd/system/crowdsec.service.d + state: directory + when: + - (package_testing is defined) and (package_testing not in ['', 'false', 'False']) + - ansible_os_family in ["RedHat", "Debian"] + +- name: "override StartLimitBurst" + become: true + ansible.builtin.ini_file: + dest: /lib/systemd/system/crowdsec.service.d/startlimitburst.conf + owner: root + group: root + mode: 0o644 + section: Service + option: StartLimitBurst + value: 100 + when: + - (package_testing is defined) and (package_testing not in ['', 'false', 'False']) + - ansible_os_family in ["RedHat", "Debian"] + +- name: "systemctl daemon-reload" + become: true + ansible.builtin.systemd: + daemon_reload: true + when: + - (package_testing is defined) and (package_testing not in ['', 'false', 'False']) + - ansible_os_family in ["RedHat", "Debian"] + +- name: "search for test scripts" + become: false + ansible.builtin.find: + paths: "{{ ansible_env.HOME }}/crowdsec/tests/bats" + pattern: "*.bats" + register: testfiles + +- name: "read .environment.sh" + ansible.builtin.slurp: + src: "{{ ansible_env.HOME }}/crowdsec/tests/.environment.sh" + changed_when: false + register: envfile + +- name: "show .environment.sh" + ansible.builtin.debug: + msg: "{{ envfile['content'] | b64decode }}" + +- name: "run BATS tests for source build" + ignore_errors: false + become: false + ansible.builtin.command: + cmd: tests/run-tests {{ item.path }} + chdir: "{{ ansible_env.HOME }}/crowdsec" + with_items: "{{ testfiles.files | sort(attribute='path') }}" + loop_control: + label: "{{ item['path'] }}" + environment: + # daemonize -> /usr/bin or /usr/local/sbin + # pidof -> /usr/sbin + # bash -> /opt/bash/bin + PATH: "/opt/bash/bin:{{ ansible_env.PATH }}:/usr/sbin:/usr/local/sbin" + changed_when: false + when: + - (package_testing is not defined) or (package_testing in ['', 'false', 'False']) + - (item.path | basename) not in skip_tests.split(',') + +- name: "run BATS tests for binary package" + ignore_errors: false + become: true + ansible.builtin.command: + cmd: tests/run-tests {{ item.path }} + chdir: "{{ ansible_env.HOME }}/crowdsec" + with_items: "{{ testfiles.files | sort(attribute='path') }}" + loop_control: + label: "{{ item['path'] }}" + environment: + # daemonize -> /usr/bin or /usr/local/sbin + # pidof -> /usr/sbin + # bash -> /opt/bash/bin + PATH: "/opt/bash/bin:{{ ansible_env.PATH }}:/usr/sbin:/usr/local/sbin" + changed_when: false + when: + - (package_testing is defined) and (package_testing not in ['', 'false', 'False']) + - (item.path | basename) not in skip_tests.split(',') diff --git a/tests/ansible/roles/run_func_tests/vars/main.yml b/tests/ansible/roles/run_func_tests/vars/main.yml new file mode 100644 index 000000000..c12ca5562 --- /dev/null +++ b/tests/ansible/roles/run_func_tests/vars/main.yml @@ -0,0 +1,3 @@ +--- +package_testing: "{{ lookup('ansible.builtin.env', 'PACKAGE_TESTING') }}" +skip_tests: "{{ lookup('ansible.builtin.env', 'TEST_SKIP') }}" diff --git a/tests/ansible/run_all.yml b/tests/ansible/run_all.yml new file mode 100644 index 000000000..3f51227cf --- /dev/null +++ b/tests/ansible/run_all.yml @@ -0,0 +1,5 @@ +--- +- import_playbook: provision_dependencies.yml +- import_playbook: provision_test_suite.yml +- import_playbook: prepare_tests.yml +- import_playbook: run_tests.yml diff --git a/tests/ansible/run_tests.yml b/tests/ansible/run_tests.yml new file mode 100644 index 000000000..5ee42f183 --- /dev/null +++ b/tests/ansible/run_tests.yml @@ -0,0 +1,18 @@ +--- +- name: "run functional tests" + hosts: all + gather_facts: true + vars_files: + - vars/mysql.yml + - vars/postgres.yml + environment: + PGHOST: 127.0.0.1 + PGPORT: 5432 + PGPASSWORD: "{{ postgresql_users[0].password }}" + PGUSER: postgres + MYSQL_HOST: localhost + MYSQL_PORT: 3306 + MYSQL_PASSWORD: "{{ mysql_root_password }}" + MYSQL_USER: "root" + roles: + - role: run_func_tests diff --git a/tests/ansible/vagrant/Vagrantfile.common b/tests/ansible/vagrant/Vagrantfile.common new file mode 100644 index 000000000..535a3016e --- /dev/null +++ b/tests/ansible/vagrant/Vagrantfile.common @@ -0,0 +1,34 @@ +Vagrant.configure("2") do |config| + config.vm.provider :libvirt do |libvirt| + libvirt.cpus = 1 + libvirt.memory = 1024 + end + + config.vm.synced_folder '.', '/vagrant', disabled: true + + config.vm.provision "ansible" do |ansible| + # ansible.verbose = "vvvv" + ansible.config_file = "../../ansible.cfg" + ansible.playbook = "../../run_all.yml" + end + + # same as above, to run the steps separately + + # config.vm.provision "ansible" do |provdep| + # provdep.config_file = "../../ansible-common.cfg" + # provdep.playbook = "../../provision_dependencies.yml" + # end + # config.vm.provision "ansible" do |provtest| + # provtest.config_file = "../../ansible-common.cfg" + # provtest.playbook = "../../provision_test_suite.yml" + # end + # config.vm.provision "ansible" do |preptest| + # preptest.config_file = "../../ansible-common.cfg" + # preptest.playbook = "../../prepare_tests.yml" + # end + # config.vm.provision "ansible" do |runtests| + # runtests.config_file = "../../ansible-common.cfg" + # runtests.playbook = "../../run_tests.yml" + # end + +end diff --git a/tests/ansible/vagrant/centos-7/Vagrantfile b/tests/ansible/vagrant/centos-7/Vagrantfile new file mode 100644 index 000000000..8c9687d92 --- /dev/null +++ b/tests/ansible/vagrant/centos-7/Vagrantfile @@ -0,0 +1,6 @@ +common = '../Vagrantfile.common' +load common if File.exists?(common) + +Vagrant.configure("2") do |config| + config.vm.box = "centos/7" +end diff --git a/tests/ansible/vagrant/centos-8/Vagrantfile b/tests/ansible/vagrant/centos-8/Vagrantfile new file mode 100644 index 000000000..49267201c --- /dev/null +++ b/tests/ansible/vagrant/centos-8/Vagrantfile @@ -0,0 +1,6 @@ +common = '../Vagrantfile.common' +load common if File.exists?(common) + +Vagrant.configure("2") do |config| + config.vm.box = "centos/stream8" +end diff --git a/tests/ansible/vagrant/debian-10-buster/Vagrantfile b/tests/ansible/vagrant/debian-10-buster/Vagrantfile new file mode 100644 index 000000000..49f5803a1 --- /dev/null +++ b/tests/ansible/vagrant/debian-10-buster/Vagrantfile @@ -0,0 +1,6 @@ +common = '../Vagrantfile.common' +load common if File.exists?(common) + +Vagrant.configure("2") do |config| + config.vm.box = "debian/buster64" +end diff --git a/tests/ansible/vagrant/debian-11-bullseye/Vagrantfile b/tests/ansible/vagrant/debian-11-bullseye/Vagrantfile new file mode 100644 index 000000000..0ec8b3515 --- /dev/null +++ b/tests/ansible/vagrant/debian-11-bullseye/Vagrantfile @@ -0,0 +1,6 @@ +common = '../Vagrantfile.common' +load common if File.exists?(common) + +Vagrant.configure("2") do |config| + config.vm.box = "debian/bullseye64" +end diff --git a/tests/ansible/vagrant/debian-9-stretch/Vagrantfile b/tests/ansible/vagrant/debian-9-stretch/Vagrantfile new file mode 100644 index 000000000..4fbc0e3ab --- /dev/null +++ b/tests/ansible/vagrant/debian-9-stretch/Vagrantfile @@ -0,0 +1,6 @@ +common = '../Vagrantfile.common' +load common if File.exists?(common) + +Vagrant.configure("2") do |config| + config.vm.box = "debian/stretch64" +end diff --git a/tests/ansible/vagrant/debian-testing/Vagrantfile b/tests/ansible/vagrant/debian-testing/Vagrantfile new file mode 100644 index 000000000..bfbd5cd0e --- /dev/null +++ b/tests/ansible/vagrant/debian-testing/Vagrantfile @@ -0,0 +1,6 @@ +common = '../Vagrantfile.common' +load common if File.exists?(common) + +Vagrant.configure("2") do |config| + config.vm.box = "debian/testing64" +end diff --git a/tests/ansible/vagrant/fedora-33/Vagrantfile b/tests/ansible/vagrant/fedora-33/Vagrantfile new file mode 100644 index 000000000..f94659907 --- /dev/null +++ b/tests/ansible/vagrant/fedora-33/Vagrantfile @@ -0,0 +1,8 @@ +common = '../Vagrantfile.common' +load common if File.exists?(common) + +Vagrant.configure("2") do |config| + # the official boxes seem to have issues with journalctl + # config.vm.box = "fedora/33-cloud-base" + config.vm.box = "generic/fedora33" +end diff --git a/tests/ansible/vagrant/fedora-34/Vagrantfile b/tests/ansible/vagrant/fedora-34/Vagrantfile new file mode 100644 index 000000000..20c05861b --- /dev/null +++ b/tests/ansible/vagrant/fedora-34/Vagrantfile @@ -0,0 +1,8 @@ +common = '../Vagrantfile.common' +load common if File.exists?(common) + +Vagrant.configure("2") do |config| + # the official boxes seem to have issues with journalctl + # config.vm.box = "fedora/34-cloud-base" + config.vm.box = "generic/fedora34" +end diff --git a/tests/ansible/vagrant/fedora-35/Vagrantfile b/tests/ansible/vagrant/fedora-35/Vagrantfile new file mode 100644 index 000000000..e81271b03 --- /dev/null +++ b/tests/ansible/vagrant/fedora-35/Vagrantfile @@ -0,0 +1,8 @@ +common = '../Vagrantfile.common' +load common if File.exists?(common) + +Vagrant.configure("2") do |config| + # the official boxes seem to have issues with journalctl + # config.vm.box = "fedora/35-cloud-base" + config.vm.box = "generic/fedora35" +end diff --git a/tests/ansible/vagrant/fedora-36/Vagrantfile b/tests/ansible/vagrant/fedora-36/Vagrantfile new file mode 100644 index 000000000..f06f21a27 --- /dev/null +++ b/tests/ansible/vagrant/fedora-36/Vagrantfile @@ -0,0 +1,8 @@ +common = '../Vagrantfile.common' +load common if File.exists?(common) + +Vagrant.configure("2") do |config| + # the official boxes seem to have issues with journalctl + # config.vm.box = "fedora/36-cloud-base" + config.vm.box = "generic/fedora36" +end diff --git a/tests/ansible/vagrant/freebsd-12/Vagrantfile b/tests/ansible/vagrant/freebsd-12/Vagrantfile new file mode 100644 index 000000000..67a5f69ec --- /dev/null +++ b/tests/ansible/vagrant/freebsd-12/Vagrantfile @@ -0,0 +1,6 @@ +common = '../Vagrantfile.common' +load common if File.exists?(common) + +Vagrant.configure("2") do |config| + config.vm.box = "generic/freebsd12" +end diff --git a/tests/ansible/vagrant/freebsd-13/Vagrantfile b/tests/ansible/vagrant/freebsd-13/Vagrantfile new file mode 100644 index 000000000..dd448cecb --- /dev/null +++ b/tests/ansible/vagrant/freebsd-13/Vagrantfile @@ -0,0 +1,6 @@ +common = '../Vagrantfile.common' +load common if File.exists?(common) + +Vagrant.configure("2") do |config| + config.vm.box = "generic/freebsd13" +end diff --git a/tests/ansible/vagrant/oracle-7/Vagrantfile b/tests/ansible/vagrant/oracle-7/Vagrantfile new file mode 100644 index 000000000..d377d9418 --- /dev/null +++ b/tests/ansible/vagrant/oracle-7/Vagrantfile @@ -0,0 +1,6 @@ +common = '../Vagrantfile.common' +load common if File.exists?(common) + +Vagrant.configure("2") do |config| + config.vm.box = "generic/oracle7" +end diff --git a/tests/ansible/vagrant/oracle-8/Vagrantfile b/tests/ansible/vagrant/oracle-8/Vagrantfile new file mode 100644 index 000000000..2f1c75dd9 --- /dev/null +++ b/tests/ansible/vagrant/oracle-8/Vagrantfile @@ -0,0 +1,6 @@ +common = '../Vagrantfile.common' +load common if File.exists?(common) + +Vagrant.configure("2") do |config| + config.vm.box = "generic/oracle8" +end diff --git a/tests/ansible/vagrant/ubuntu-16.04-xenial/Vagrantfile b/tests/ansible/vagrant/ubuntu-16.04-xenial/Vagrantfile new file mode 100644 index 000000000..fb550c494 --- /dev/null +++ b/tests/ansible/vagrant/ubuntu-16.04-xenial/Vagrantfile @@ -0,0 +1,7 @@ +common = '../Vagrantfile.common' +load common if File.exists?(common) + +Vagrant.configure("2") do |config| + # the official boxes only supports virtualbox + config.vm.box = "generic/ubuntu1604" +end diff --git a/tests/ansible/vagrant/ubuntu-18.04-bionic/Vagrantfile b/tests/ansible/vagrant/ubuntu-18.04-bionic/Vagrantfile new file mode 100644 index 000000000..18d3d18d8 --- /dev/null +++ b/tests/ansible/vagrant/ubuntu-18.04-bionic/Vagrantfile @@ -0,0 +1,7 @@ +common = '../Vagrantfile.common' +load common if File.exists?(common) + +Vagrant.configure("2") do |config| + # the official boxes only supports virtualbox + config.vm.box = "generic/ubuntu1804" +end diff --git a/tests/ansible/vagrant/ubuntu-20.04-focal/Vagrantfile b/tests/ansible/vagrant/ubuntu-20.04-focal/Vagrantfile new file mode 100644 index 000000000..bb8bd29b6 --- /dev/null +++ b/tests/ansible/vagrant/ubuntu-20.04-focal/Vagrantfile @@ -0,0 +1,7 @@ +common = '../Vagrantfile.common' +load common if File.exists?(common) + +Vagrant.configure("2") do |config| + # the official boxes only supports virtualbox + config.vm.box = "generic/ubuntu2004" +end diff --git a/tests/ansible/vagrant/ubuntu-22.04-jammy/Vagrantfile b/tests/ansible/vagrant/ubuntu-22.04-jammy/Vagrantfile new file mode 100644 index 000000000..b5e063337 --- /dev/null +++ b/tests/ansible/vagrant/ubuntu-22.04-jammy/Vagrantfile @@ -0,0 +1,7 @@ +common = '../Vagrantfile.common' +load common if File.exists?(common) + +Vagrant.configure("2") do |config| + # the official boxes only supports virtualbox + config.vm.box = "generic/ubuntu2204" +end diff --git a/tests/ansible/vagrant/zz-amazon-linux-2/Vagrantfile b/tests/ansible/vagrant/zz-amazon-linux-2/Vagrantfile new file mode 100644 index 000000000..ab61515a3 --- /dev/null +++ b/tests/ansible/vagrant/zz-amazon-linux-2/Vagrantfile @@ -0,0 +1,6 @@ +common = '../Vagrantfile.common' +load common if File.exists?(common) + +Vagrant.configure("2") do |config| + config.vm.box = "cloudnatives/amazon-linux-2" +end diff --git a/tests/ansible/vars/go.yml b/tests/ansible/vars/go.yml new file mode 100644 index 000000000..1ce34397f --- /dev/null +++ b/tests/ansible/vars/go.yml @@ -0,0 +1,2 @@ +golang_version: "1.18.2" +golang_install_dir: "/opt/go/{{ golang_version }}" diff --git a/tests/ansible/vars/mysql.yml b/tests/ansible/vars/mysql.yml new file mode 100644 index 000000000..c3bd11c0d --- /dev/null +++ b/tests/ansible/vars/mysql.yml @@ -0,0 +1,4 @@ +--- + +# The password is insecure since the db is ephemeral and only listen to localhost. +mysql_root_password: password diff --git a/tests/ansible/vars/postgres.yml b/tests/ansible/vars/postgres.yml new file mode 100644 index 000000000..004dbbb08 --- /dev/null +++ b/tests/ansible/vars/postgres.yml @@ -0,0 +1,29 @@ +--- + +# The password is insecure since the db is ephemeral and only listen to localhost. +postgresql_users: + - name: postgres + password: postgres + +postgresql_hba_entries: + - type: local + database: all + user: postgres + auth_method: peer + + - type: local + database: all + user: all + auth_method: peer + + - type: host + database: all + user: all + address: "127.0.0.1/32" + auth_method: md5 + + - type: host + database: all + user: all + address: "::1/128" + auth_method: md5