functional tests instrumented by ansible/vagrant (#1682)

This commit is contained in:
mmetc 2022-07-26 13:09:13 +02:00 committed by GitHub
parent 804b6f4c5d
commit 39f57f1487
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
60 changed files with 1263 additions and 6 deletions

View file

@ -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`

2
tests/ansible/.gitignore vendored Normal file
View file

@ -0,0 +1,2 @@
.vagrant
vagrant/*/*.out

157
tests/ansible/README.md Normal file
View file

@ -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/<distro-of-your-choice>`
- `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/<database>` are expected to pass for `pkg/<database>` 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

14
tests/ansible/ansible.cfg Normal file
View file

@ -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

51
tests/ansible/env/example.sh vendored Executable file
View file

@ -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

17
tests/ansible/env/pkg-sqlite.sh vendored Executable file
View file

@ -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

14
tests/ansible/env/source-mysql.sh vendored Executable file
View file

@ -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

14
tests/ansible/env/source-pgx.sh vendored Executable file
View file

@ -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

14
tests/ansible/env/source-postgres.sh vendored Executable file
View file

@ -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

14
tests/ansible/env/source-sqlite.sh vendored Executable file
View file

@ -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

37
tests/ansible/prepare-run Executable file
View file

@ -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 <env> [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

View file

@ -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

View file

@ -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'

View file

@ -0,0 +1,5 @@
---
- name: "install the test scripts"
hosts: all
roles:
- install_crowdsec_tests

View file

@ -0,0 +1,4 @@
---
- src: geerlingguy.postgresql
- src: geerlingguy.mysql
- src: gantsign.golang

View file

@ -0,0 +1,4 @@
---
build_bash: false
build_daemonize: (ansible_distribution == "Ubuntu" and ansible_distribution_version == '16.04') or ansible_distribution == 'Amazon'

View file

@ -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

View file

@ -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

View file

@ -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 }}"

View file

@ -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"

View file

@ -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"

View file

@ -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

View file

@ -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 }}

View file

@ -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

View file

@ -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') }}

View file

@ -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"

View file

@ -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') }}"

View file

@ -0,0 +1,3 @@
---
suite_git: "https://github.com/crowdsecurity/crowdsec"
suite_version: "master"

View file

@ -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

View file

@ -0,0 +1,2 @@
---
machine_id: "githubciXXXXXXXXXXXXXXXXXXXXXXXX\n"

View file

@ -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"

View file

@ -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 }}"

View file

@ -0,0 +1,2 @@
---
package_testing: "{{ lookup('ansible.builtin.env', 'PACKAGE_TESTING') }}"

View file

@ -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(',')

View file

@ -0,0 +1,3 @@
---
package_testing: "{{ lookup('ansible.builtin.env', 'PACKAGE_TESTING') }}"
skip_tests: "{{ lookup('ansible.builtin.env', 'TEST_SKIP') }}"

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -0,0 +1,6 @@
common = '../Vagrantfile.common'
load common if File.exists?(common)
Vagrant.configure("2") do |config|
config.vm.box = "centos/7"
end

View file

@ -0,0 +1,6 @@
common = '../Vagrantfile.common'
load common if File.exists?(common)
Vagrant.configure("2") do |config|
config.vm.box = "centos/stream8"
end

View file

@ -0,0 +1,6 @@
common = '../Vagrantfile.common'
load common if File.exists?(common)
Vagrant.configure("2") do |config|
config.vm.box = "debian/buster64"
end

View file

@ -0,0 +1,6 @@
common = '../Vagrantfile.common'
load common if File.exists?(common)
Vagrant.configure("2") do |config|
config.vm.box = "debian/bullseye64"
end

View file

@ -0,0 +1,6 @@
common = '../Vagrantfile.common'
load common if File.exists?(common)
Vagrant.configure("2") do |config|
config.vm.box = "debian/stretch64"
end

View file

@ -0,0 +1,6 @@
common = '../Vagrantfile.common'
load common if File.exists?(common)
Vagrant.configure("2") do |config|
config.vm.box = "debian/testing64"
end

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -0,0 +1,6 @@
common = '../Vagrantfile.common'
load common if File.exists?(common)
Vagrant.configure("2") do |config|
config.vm.box = "generic/freebsd12"
end

View file

@ -0,0 +1,6 @@
common = '../Vagrantfile.common'
load common if File.exists?(common)
Vagrant.configure("2") do |config|
config.vm.box = "generic/freebsd13"
end

View file

@ -0,0 +1,6 @@
common = '../Vagrantfile.common'
load common if File.exists?(common)
Vagrant.configure("2") do |config|
config.vm.box = "generic/oracle7"
end

View file

@ -0,0 +1,6 @@
common = '../Vagrantfile.common'
load common if File.exists?(common)
Vagrant.configure("2") do |config|
config.vm.box = "generic/oracle8"
end

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -0,0 +1,2 @@
golang_version: "1.18.2"
golang_install_dir: "/opt/go/{{ golang_version }}"

View file

@ -0,0 +1,4 @@
---
# The password is insecure since the db is ephemeral and only listen to localhost.
mysql_root_password: password

View file

@ -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