Changeset - d1387069c3c9
[Not reviewed]
0 7 0
Branko Majic (branko) - 5 months ago 2025-07-20 09:56:21
branko@majic.rs
MAR-244: Update copyright notices.
7 files changed with 12 insertions and 12 deletions:
0 comments (0 inline, 0 general)
LICENSE
Show inline comments
 
Copyright (c) 2018, Branko Majic
 
Copyright (c) 2018, 2025, Branko Majic
 
All rights reserved.
 

	
 
Redistribution and use in source and binary forms, with or without modification,
 
are permitted provided that the following conditions are met:
 

	
 
  Redistributions of source code must retain the above copyright notice, this
 
  list of conditions and the following disclaimer.
 

	
 
  Redistributions in binary form must reproduce the above copyright notice, this
 
  list of conditions and the following disclaimer in the documentation and/or
 
  other materials provided with the distribution.
 

	
 
  Neither the name of Branko Majic nor the names of any other
 
  contributors may be used to endorse or promote products derived from
 
  this software without specific prior written permission.
 

	
 
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
 
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
 
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
docs/about.rst
Show inline comments
 
About Majic Ansible Roles
 
=========================
 

	
 
Majic Ansible Roles is a collection of Ansible roles that are used on regular
 
basis for deployment and maintenance of Majic infrastructure.
 

	
 
The roles are kept as a separate project in hope of making them potentially
 
useful to wider audience, and for reference purposes.
 

	
 
Roles cover different aspects of infrastructure, such as mail servers, web
 
servers, web applications etc. The roles are mainly well-suited for smaller
 
installations.
 

	
 
Roles are written for use with *Debian GNU/Linux*. For more details on
 
supported releases, see :ref:`rolereference`.
 

	
 
At the moment, the roles have been written for and tested against **Ansible
 
11.5.x**.
 

	
 
The roles also utilise the ``ipv4/ipv6`` lookup plugins which require
 
``netaddr`` package to be installed. The ``passlib`` package is used
 
for hashing the operating system passwords. Make sure you have the
 
packages available on controller machine.
 

	
 

	
 
Why were these roles created?
 
-----------------------------
 

	
 
For a long time I have had a couple of Internet-facing servers where I hosted
 
all the IT infrastructure I needed for my day-to-day life.
 

	
 
This started off with some basic services, like mail and XMPP server, and in
 
time extended to include a web server, code repository etc.
 

	
 
As the number of services I used grew, I found it more difficult to track
 
updates and upgrades, let alone test them in reliable way. The biggest problem
 
in particular was lack of time to properly document all the different things
 
I've set-up.
 

	
 
Being familiar with some Puppet-based deployments, I've started looking into the
 
possibility of using a configuration management system. Ansible emerged as
 
something that I thought would be easy to use, due to its agent-less nature.
 

	
 
Once I passed some basic tutorials and got to know the system a bit, I decided
 
to start my journey on implementing the different roles, in the way I want them,
 
that would let me easily set-up my servers (and reinstall them, amongst other
 
things).
 

	
 
The roles you see within this repository are the fruit of this labour. I hope
 
you find them useful.
 

	
 

	
 
Features
 
--------
 

	
 
*Majic Ansible Roles* have the following features:
 

	
 
.. warning::
 

	
 
   Of course, you may want to take some statements with a pinch of salt, and
 
   possibly attribute them to either delusions of grandeur, or bragging :)
 

	
 
* Emphasis on small, self-hosted deployments.
 
* Modular role design where possible and where necessary.
 
* A number of roles covering common set-up of servers, databases, web server,
 
  XMPP server, mail server, and LDAP server.
 
* Streamlined integration with LDAP server for most of the services.
 
* Well-documented, with role reference documentation, examples, and test/sample
 
  site.
 
* Balanced implementation allowing both configurability and ease of deployment.
 
* Free Software, released under liberal BSD license.
 

	
 
Available roles:
 

	
 
* ``bootstrap`` (for setting-up servers for Ansible use)
 
* ``common`` (for setting-up basic security, accounts, and configuration on
 
  servers)
 
* ``database`` (for creating databases to be used for applications)
 
* ``database_server`` (for deploying a database server, MariaDB)
 
* ``ldap_client`` (for setting-up LDAP client configuration)
 
* ``ldap_server`` (for deploying an LDAP server, OpenLDAP)
 
* ``mail_forwarder`` (for setting-up forwarding of local mails to smart host,
 
  Postfix)
 
* ``mail_server`` (for deploying Postfix, Dovecot, ClamAV)
 
* ``php_website`` (for deploying PHP websites)
 
* ``preseed`` (for preparing Debian preseed files)
 
* ``prosody`` (for deploying XMPP server, Prosody)
 
* ``web_server`` (for deploying web server, Nginx)
 
* ``wsgi_website`` (for deploying WSGI/Python applications)
 

	
 

	
 
Support
 
-------
 

	
 
In case of problems with the roles or provided code, please do not hestitate to
 
contact the author at **majic-ansible-roles (at) majic.rs**. The project can be
 
found at:
 

	
 
* https://code.majic.rs/majic-ansible-roles
 
* https://projects.majic.rs/majic-ansible-roles
 

	
 

	
 
License
 
-------
 

	
 
Majic Ansible Roles is released under terms of *BSD (3-Clause) License*::
 

	
 
  Copyright (c) 2018, Branko Majic
 
  Copyright (c) 2018, 2025, Branko Majic
 
  All rights reserved.
 

	
 
  Redistribution and use in source and binary forms, with or without modification,
 
  are permitted provided that the following conditions are met:
 

	
 
    Redistributions of source code must retain the above copyright notice, this
 
    list of conditions and the following disclaimer.
 

	
 
    Redistributions in binary form must reproduce the above copyright notice, this
 
    list of conditions and the following disclaimer in the documentation and/or
 
    other materials provided with the distribution.
 

	
 
    Neither the name of Branko Majic nor the names of any other
 
    contributors may be used to endorse or promote products derived from
 
    this software without specific prior written permission.
 

	
 
  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 
  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 
  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 
  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
 
  ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 
  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 
  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
 
  ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 
  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 
  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
roles/common/files/check_certificate.sh
Show inline comments
 
#!/bin/bash
 
#
 
# check_certificate.sh
 
#
 
# Copyright (C) 2017, Branko Majic <branko@majic.rs>
 
# Copyright (C) 2017, 2025, Branko Majic <branko@majic.rs>
 
#
 
# This program is free software: you can redistribute it and/or modify
 
# it under the terms of the GNU General Public License as published by
 
# the Free Software Foundation, either version 3 of the License, or
 
# (at your option) any later version.
 
#
 
# This program is distributed in the hope that it will be useful,
 
# but WITHOUT ANY WARRANTY; without even the implied warranty of
 
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
# GNU General Public License for more details.
 
#
 
# You should have received a copy of the GNU General Public License
 
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
#
 

	
 
program="check_certificate.sh"
 

	
 
function usage() {
 
    cat <<EOF
 
$program, a non-interactive utility for checking certificates
 

	
 
Usage: $program [OPTIONS] check_type...
 

	
 
$program is a non-interactive utility for checking certificates. Utility
 
supports a number of different checks which are passed in as positional
 
arguments. The following checks are currently implemented:
 

	
 
expiration
 
  Checks if certificate expires within designated time. Expiration period can be
 
  specified via options (see below).
 

	
 
List of certificate files to check can be passed through two mutually exclusive
 
mechanisms - via options or through configuration files. If certificates are
 
specified through options, configuration files are not read.
 

	
 
Configuration files are by default read from directory
 
/etc/check_certificate/. Each configuration file is expected to end with
 
".conf". All other files will be ignored. A different configuration directory
 
can be also specified via an option.
 

	
 
Configuration files themselves should contain one certificate per line. Blank
 
lines will be ignored.
 

	
 

	
 
$program accepts the following options:
 

	
 
    -e period
 
        Number of days before certificate expires after which the certificate
 
        should be considered as about to expire. Value is used in the following
 
        check types: expiration.
 

	
 
    -c certificate_file
 
        Path to certificate file for which the checks should be run. This option
 
        can be specified multiple times on the command line in order to verify
 
        multiple certificates.
 

	
 
    -q
 
        Enable quiet mode. Output only warnings and errors.
 

	
 
    -d
 
        Enable debug output.
 

	
 
    -v
 
        Show script version and licensing information.
 

	
 
    -h
 
        Show usage help.
 

	
 

	
 
Please report bugs and send feature requests to <branko@majic.rs>.
 
EOF
 
}
 

	
 
function version() {
 
        cat <<EOF
 
$program
 

	
 
+-----------------------------------------------------------------------+
 
| Copyright (C) 2017, Branko Majic <branko@majic.rs>                    |
 
| Copyright (C) 2017, 2025, Branko Majic <branko@majic.rs>              |
 
|                                                                       |
 
| This program is free software: you can redistribute it and/or modify  |
 
| it under the terms of the GNU General Public License as published by  |
 
| the Free Software Foundation, either version 3 of the License, or     |
 
| (at your option) any later version.                                   |
 
|                                                                       |
 
| This program is distributed in the hope that it will be useful,       |
 
| but WITHOUT ANY WARRANTY; without even the implied warranty of        |
 
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         |
 
| GNU General Public License for more details.                          |
 
|                                                                       |
 
| You should have received a copy of the GNU General Public License     |
 
| along with this program.  If not, see <http://www.gnu.org/licenses/>. |
 
+-----------------------------------------------------------------------+
 

	
 
EOF
 
}
 

	
 
# Set-up colours for message printing if we're not piping and terminal is
 
# capable of outputting the colors.
 
_color_terminal=$(tput colors 2>&1)
 
if [[ -t 1 ]] && (( ${_color_terminal} > 0 )); then
 
    _text_bold=$(tput bold)
 
    _text_white=$(tput setaf 7)
 
    _text_blue=$(tput setaf 6)
 
    _text_green=$(tput setaf 2)
 
    _text_yellow=$(tput setaf 3)
 
    _text_red=$(tput setaf 1)
 
    _text_reset=$(tput sgr0)
 
else
 
    _text_bold=""
 
    _text_white=""
 
    _text_blue=""
 
    _text_green=""
 
    _text_yellow=""
 
    _text_red=""
 
    _text_reset=""
 
fi
 

	
 
# Set-up functions for printing coloured messages.
 
function debug() {
 
    [[ $DEBUG != 0 ]] && echo "${_text_bold}${_text_blue}[DEBUG]${_text_reset}" "$@"
 
}
 

	
 
function info() {
 
    [[ $QUIET == 0 ]] && echo "${_text_bold}${_text_white}[INFO] ${_text_reset}" "$@"
 
}
 

	
 
function success() {
 
    [[ $QUIET == 0 ]] && echo "${_text_bold}${_text_green}[OK]   ${_text_reset}" "$@"
 
}
 

	
 
function warning() {
 
    echo "${_text_bold}${_text_yellow}[WARN] ${_text_reset}" "$@"
 
}
 

	
 
function error() {
 
    echo "${_text_bold}${_text_red}[ERROR]${_text_reset}" "$@" >&2
 
}
 

	
 
#
 
# Checks expiration of passed-in certificate file.
 
#
 
# Arguments:
 
#
 
#   $1 - Path to certificate file to check
 
#
 
# Returns:
 
#
 
#   0 if check has passed, 1 if check has not passed.
 
#
 
function check_expiration() {
 
    local certificate_file="$1"
 
    local certificate_expiration_date certificate_expiration_date_in_seconds certificate_expires_in
 
    local current_date_in_seconds
 
    local expiration_period_seconds
 
    local status
 

	
 
    let expiration_period_seconds="$expiration_period"*24*60*60
 

	
 
    debug "Running expiration check for file: $certificate_file"
 
    debug "Expiration period set to: $expiration_period"
 

	
 
    certificate_expiration_date=$(openssl x509 -enddate -noout -in "$certificate_file" | sed -e 's/^notAfter=//')
 
    certificate_expiration_date_in_seconds=$(date -d "$certificate_expiration_date" "+%s")
 
    current_date_in_seconds=$(date "+%s")
 
    let certificate_expires_in="$certificate_expiration_date_in_seconds-$current_date_in_seconds"
 

	
 
    if (( $certificate_expires_in >= 0 )); then
 
        status="expires"
 
    else
 
        status="expired"
 
    fi
 

	
 
    if openssl x509 -noout -in "$certificate_file" -checkend "$expiration_period_seconds" > /dev/null; then
 
        success "Certificate $certificate_file $status on $certificate_expiration_date, $(print_relative_period "$certificate_expires_in")."
 
	return 0
 
    else
 
        error "Certificate $certificate_file $status on $certificate_expiration_date, $(print_relative_period "$certificate_expires_in")."
 
	return 1
 
    fi
 
}
 

	
 
#
 
# Outputs period relative to current time in human-readable format
 
# with granularity in days.
 
#
 
# Arguments:
 
#
 
#   $1 - Time period in seconds. Can be negative to denote past.
 
#
 
function print_relative_period() {
 
    local seconds="$1"
 
    local days leftover
 

	
 
    let days="$seconds/(60*60*24)"
 

	
 
    if (( $days == 1 )); then
 
        echo "in $days day"
 
    elif (( $days > 1 )); then
 
        echo "in $days days"
 
    elif (( $days == 0 && $seconds > 0 )); then
 
        echo "in less than a day"
 
    elif (( $days == 0 && $seconds < 0 )); then
 
        echo "less than a day ago"
 
    elif (( $days == -1 )); then
 
        echo "one day ago"
 
    elif (( $days < -1 )); then
 
        echo "${days#-} days ago"
 
    fi
 
}
 

	
 
# Exit codes
 
ERROR_SUCCESS=0
 
ERROR_PARAMETERS=1
 
ERROR_FAILED_CHECK=2
 

	
 
# If no arguments were given, just show usage help.
 
if [[ -z $1 ]]; then
 
    usage
 
    exit $ERROR_SUCCESS
 
fi
 

	
 
# Disable debug by default.
 
DEBUG=0
 
QUIET=0
 

	
 
# Set-up default option values.
 
let expiration_period=30
 

	
 
# List of certificate files to check.
 
certificate_files=()
 
configuration_directory="/etc/check_certificate"
 

	
 
# Parse the arguments
 
while getopts "e:c:C:xqdvh" opt; do
 
    case "$opt" in
 
	e) let expiration_period="$OPTARG";;
 
	c) certificate_files+=("$OPTARG");;
 
	C) configuration_directory="$OPTARG";;
 
        q) QUIET=1;;
 
	d) DEBUG=1;;
 
        v) version
 
           exit $ERROR_SUCCESS;;
 
        h) usage
 
           exit $ERROR_SUCCESS;;
 
        *) usage
 
           exit $ERROR_PARAMETERS;;
 
    esac
 
done
 
i=$OPTIND
 
shift $(($i-1))
 

	
 
# Verify parameters.
 
if [[ $# == 0 ]]; then
 
    error "At least one valid check type must be specified."
 
    exit $ERROR_PARAMETERS
 
fi
 
for check in "$@"; do
 
    if [[ $check != expiration ]]; then
 
	error "Unsupported check type specified: $check"
 
	exit $ERROR_PARAMETERS
 
    fi
 
done
 

	
 
# Load list of certificate files from configuration files if none were specified
 
# via options.
 
if [[ ${#certificate_files[@]} == 0 ]]; then
 
    for configuration_file in "$configuration_directory"/*.conf; do
 
	if [[ -f $configuration_file ]]; then
 
	    DONE=false
 
	    until "$DONE"; do
roles/common/files/legacy_iptables_rules.sh
Show inline comments
 
#!/bin/bash
 
#
 
# legacy_iptables_rules.sh
 
#
 
# Copyright (C) 2023, Branko Majic <branko@majic.rs>
 
# Copyright (C) 2023, 2025, Branko Majic <branko@majic.rs>
 
#
 
# This program is free software: you can redistribute it and/or modify
 
# it under the terms of the GNU General Public License as published by
 
# the Free Software Foundation, either version 3 of the License, or
 
# (at your option) any later version.
 
#
 
# This program is distributed in the hope that it will be useful,
 
# but WITHOUT ANY WARRANTY; without even the implied warranty of
 
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
# GNU General Public License for more details.
 
#
 
# You should have received a copy of the GNU General Public License
 
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
#
 

	
 
# Treat unset variables as errors.
 
set -u
 

	
 
PROGRAM="legacy_iptables_rules.sh"
 

	
 
function usage() {
 
    cat <<EOF
 
$PROGRAM, helper tool for removing legacy iptables rules
 

	
 
Usage:
 
  $PROGRAM [OPTIONS] remove
 
EOF
 
}
 

	
 
function short_help() {
 
    cat <<EOF
 
$(usage)
 

	
 
For more details see $PROGRAM -h.
 
EOF
 
}
 

	
 
function long_help() {
 
    cat <<EOF
 
$(usage)
 

	
 
$PROGRAM is a helper tool that can be used to remove the legacy
 
iptables rules.
 

	
 
The tool works by resetting the default policies on all the relevant
 
chains and tables, flushing the rules, as well as unloading the
 
related kernel modules.
 

	
 
Tool implements multiple commands, as documented below.
 

	
 
  remove
 

	
 
    Removes the legacy iptables rules.
 

	
 
$PROGRAM accepts the following options:
 

	
 
    -q
 
        Quiet mode.
 
    -d
 
        Enable debug mode.
 
    -v
 
        Show script version and licensing information.
 
    -h
 
        Show full help.
 

	
 
Please report bugs and send feature requests to <branko@majic.rs>.
 
EOF
 
}
 

	
 
function version() {
 
    cat <<EOF
 
$PROGRAM
 

	
 
+-----------------------------------------------------------------------+
 
| Copyright (C) 2023, Branko Majic <branko@majic.rs>                    |
 
| Copyright (C) 2023, 2025, Branko Majic <branko@majic.rs>              |
 
|                                                                       |
 
| This program is free software: you can redistribute it and/or modify  |
 
| it under the terms of the GNU General Public License as published by  |
 
| the Free Software Foundation, either version 3 of the License, or     |
 
| (at your option) any later version.                                   |
 
|                                                                       |
 
| This program is distributed in the hope that it will be useful,       |
 
| but WITHOUT ANY WARRANTY; without even the implied warranty of        |
 
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         |
 
| GNU General Public License for more details.                          |
 
|                                                                       |
 
| You should have received a copy of the GNU General Public License     |
 
| along with this program.  If not, see <http://www.gnu.org/licenses/>. |
 
+-----------------------------------------------------------------------+
 

	
 
EOF
 
}
 

	
 
# Set-up colours for message printing if we're not piping and terminal is
 
# capable of outputting the colors.
 
_COLOR_TERMINAL=$(tput colors 2>&1)
 
if [[ -t 1 ]] && (( _COLOR_TERMINAL > 0 )); then
 
    _TEXT_BOLD=$(tput bold)
 
    _TEXT_WHITE=$(tput setaf 7)
 
    _TEXT_BLUE=$(tput setaf 6)
 
    _TEXT_GREEN=$(tput setaf 2)
 
    _TEXT_YELLOW=$(tput setaf 3)
 
    _TEXT_RED=$(tput setaf 1)
 
    _TEXT_RESET=$(tput sgr0)
 
else
 
    _TEXT_BOLD=""
 
    _TEXT_WHITE=""
 
    _TEXT_BLUE=""
 
    _TEXT_GREEN=""
 
    _TEXT_YELLOW=""
 
    _TEXT_RED=""
 
    _TEXT_RESET=""
 
fi
 

	
 
# Set-up functions for printing coloured messages.
 
function debug() {
 
    if [[ $DEBUG != 0 ]]; then
 
        echo "${_TEXT_BOLD}${_TEXT_BLUE}[DEBUG]${_TEXT_RESET}" "$@"
 
    fi
 
}
 

	
 
function info() {
 
    if [[ $QUIET == 0 ]]; then
 
        echo "${_TEXT_BOLD}${_TEXT_WHITE}[INFO] ${_TEXT_RESET}" "$@"
 
    fi
 
}
 

	
 
function success() {
 
    if [[ $QUIET == 0 ]]; then
 
        echo "${_TEXT_BOLD}${_TEXT_GREEN}[OK]   ${_TEXT_RESET}" "$@"
 
    fi
 
}
 

	
 
function warning() {
 
    echo "${_TEXT_BOLD}${_TEXT_YELLOW}[WARN] ${_TEXT_RESET}" "$@" >&2
 
}
 

	
 
function error() {
 
    echo "${_TEXT_BOLD}${_TEXT_RED}[ERROR]${_TEXT_RESET}" "$@" >&2
 
}
 

	
 
#
 
# Removes legacy iptables (both IPv4 and IPv6) rules.
 
#
 
# Returns:
 
#
 
#   0 in case of success, 1 otherwise.
 
#
 
function remove_legacy_iptables() {
 
    local family table tables chain iptables_save iptables_legacy module
 
    declare -a removed_families=()
 

	
 
    family=(ip ip6)
 
    tables=(filter nat mangle raw security)
 

	
 
    for family in "${family[@]}"; do
 

	
 
        iptables_save="${family}tables-save"
 
        iptables_legacy="${family}tables-legacy"
 
        iptables_legacy_save="${family}tables-legacy-save"
 

	
 
        if "$iptables_save" 2>&1 | grep -q "Warning: ${family}tables-legacy tables present"; then
 
            info "Legacy iptables detected for IP family: $family"
 

	
 
            for table in "${tables[@]}"; do
 

	
 
                info "Processing table: $family/$table"
 

	
 
                # Iterate over all chains with default policy.
 
                for chain in $("$iptables_legacy_save" -t "$table" | grep -E '^:.*(ACCEPT|DROP)' | sed -e 's/^://;s/ .*//'); do
 

	
 
                    info "Setting default policy for chain: $family/$table/$chain"
 
                    if ! "$iptables_legacy" -t "$table" -P "$chain" ACCEPT; then
 
                        error "Failed to set policy for chain: $chain ($table)"
 
                        return 1
 
                    fi
 

	
 
                done
 

	
 
                info "Flushing table: $family/$table"
 
                if ! "$iptables_legacy" -t "$table" -F; then
 
                    error "Failed to flush the table: $table"
 
                    return 1
 
                fi
 

	
 
                info "Removing user chains: $family/$table"
 
                if ! "$iptables_legacy" -t "$table" -X; then
 
                    error "Failed to remove user chains: $family/$table"
 
                    return 1
 
                fi
 

	
 
            done
 

	
 
            # Modules are named after a table.
 
            for table in "${tables[@]}"; do
 
                module="${family}table_${table}"
 

	
 
                info "Unloading module: $module"
 
                if ! rmmod "$module"; then
 
                    error "Failed to unload module: $module"
 
                    return 1
 
                fi
 
            done
 

	
 
            removed_families+=("$family")
 

	
 
        fi
 

	
 
    done
 

	
 
    if (( ${#removed_families[@]} > 0 )); then
 
        success "Removed legacy iptables for families: ${removed_families[*]}"
 
    else
 
        success "No legacy iptables are present on the system."
 
    fi
 

	
 
    return 0
 
}
 

	
 
# Define error codes.
 
SUCCESS=0
 
ERROR_ARGUMENTS=1
 
ERROR_GENERAL=2
 

	
 
# Disable debug and quiet modes by default.
 
DEBUG=0
 
QUIET=0
 

	
 
# If no arguments were given, just show usage help.
 
if [[ -z ${1-} ]]; then
 
    short_help
 
    exit "$ERROR_ARGUMENTS"
 
fi
 

	
 
# Parse the arguments
 
while getopts "qdvh" opt; do
 
    case "$opt" in
 
	q) QUIET=1;;
 
	d) DEBUG=1;;
 
        v) version
 
           exit "$SUCCESS";;
 
        h) long_help
 
           exit "$SUCCESS";;
 
        *) short_help
 
           exit "$ERROR_ARGUMENTS";;
 
    esac
 
done
 
i=$OPTIND
 
shift $(( i-1 ))
 

	
 
# Quiet and debug are mutually exclusive.
 
if [[ $QUIET != 0 && $DEBUG != 0 ]]; then
 
    error "Quiet and debug options are mutually exclusive."
 
    exit "$ERROR_ARGUMENTS"
 
fi
 

	
 
COMMAND="${1-}"
 

	
 
if [[ $COMMAND == remove ]]; then
 

	
 
    if ! remove_legacy_iptables; then
 
        error "Failed to remove legacy iptables."
 
        exit "$ERROR_GENERAL"
 
    fi
 

	
 
else
 

	
roles/common/files/pip_check_requirements_upgrades.sh
Show inline comments
 
#!/bin/bash
 
#
 
# pip_check_requirements_upgrades.sh
 
#
 
# Copyright (C) 2017, Branko Majic <branko@majic.rs>
 
# Copyright (C) 2017, 2025, Branko Majic <branko@majic.rs>
 
#
 
# This program is free software: you can redistribute it and/or modify
 
# it under the terms of the GNU General Public License as published by
 
# the Free Software Foundation, either version 3 of the License, or
 
# (at your option) any later version.
 
#
 
# This program is distributed in the hope that it will be useful,
 
# but WITHOUT ANY WARRANTY; without even the implied warranty of
 
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
# GNU General Public License for more details.
 
#
 
# You should have received a copy of the GNU General Public License
 
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
#
 

	
 
program="pip_check_requirements_upgrades.sh"
 

	
 
function usage() {
 
    cat <<EOF
 
$program, a non-interactive utility for checking for available upgrades in
 
Python pip requirements files based on pip-tools
 

	
 
Usage: $program [OPTIONS] configuration_directory
 

	
 
$program a non-interactive utility for checking for available upgrades in Python
 
pip requirements files based on pip-tools. Utility is written specifically with
 
pip-tools in mind, and pip-tools must be available when running the utility.
 

	
 
If you are unfamiliar with pip-tools, please read its documentation first, and
 
make sure you fully understand how it works.
 

	
 
Utility accepts a single positionl argument - path to configuration
 
directory. Configuration directory should contain one or more sub-directories
 
where each sub-directory is treated as describing a separate Python virtual
 
environment. This allows the checks to be run for multiple virtual environments
 
in a modular manner.
 

	
 
Each sub-directory should contain one or more .in files with corresponding .txt
 
file. Base names must match (i.e. if you have production.in, the requirements
 
file must be called production.txt).
 

	
 
Utility iterates over each .in/.txt pair, calculates new requirements
 
based on the .in file, and diffs this against existing .txt file. If a
 
.in file does not have a corresponding .txt file, it is ignored
 
(making it possible to use the '-r base.in' syntax for including base
 
requirements etc).
 

	
 
Utility creates copy of existing requirements file, stripping it from all
 
comments, then calculates new requirements file (storing result in temporary
 
location as well), and runs a diff between them.
 

	
 
If newer pacakges are available that would satisfiy the provided .in file, a
 
diff is shown on standard output in addition to a warning message.
 

	
 
$program accepts the following options:
 

	
 
    -V virtualenv
 
        Path to virtual environment with pre-installed pip-tools. If specified,
 
        the virtual environment will be activated prior to running the utility.
 

	
 
    -q
 
        Quiet mode. Output a message only if newer packages are available.
 
    -d
 
        Enable debug mode.
 
    -v
 
        Show script licensing information.
 
    -h
 
        Show usage help.
 

	
 

	
 
Please report bugs and send feature requests to <branko@majic.rs>.
 
EOF
 
}
 

	
 
function version() {
 
    cat <<EOF
 
$program
 

	
 
+-----------------------------------------------------------------------+
 
| Copyright (C) 2017, Branko Majic <branko@majic.rs>                    |
 
| Copyright (C) 2017, 2025, Branko Majic <branko@majic.rs>              |
 
|                                                                       |
 
| This program is free software: you can redistribute it and/or modify  |
 
| it under the terms of the GNU General Public License as published by  |
 
| the Free Software Foundation, either version 3 of the License, or     |
 
| (at your option) any later version.                                   |
 
|                                                                       |
 
| This program is distributed in the hope that it will be useful,       |
 
| but WITHOUT ANY WARRANTY; without even the implied warranty of        |
 
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         |
 
| GNU General Public License for more details.                          |
 
|                                                                       |
 
| You should have received a copy of the GNU General Public License     |
 
| along with this program.  If not, see <http://www.gnu.org/licenses/>. |
 
+-----------------------------------------------------------------------+
 

	
 
EOF
 
}
 

	
 
# Set-up colours for message printing if we're not piping and terminal is
 
# capable of outputting the colors.
 
_color_terminal=$(tput colors 2>&1)
 
if [[ -t 1 ]] && (( _color_terminal > 0 )); then
 
    _text_bold=$(tput bold)
 
    _text_white=$(tput setaf 7)
 
    _text_blue=$(tput setaf 6)
 
    _text_green=$(tput setaf 2)
 
    _text_yellow=$(tput setaf 3)
 
    _text_red=$(tput setaf 1)
 
    _text_reset=$(tput sgr0)
 
else
 
    _text_bold=""
 
    _text_white=""
 
    _text_blue=""
 
    _text_green=""
 
    _text_yellow=""
 
    _text_red=""
 
    _text_reset=""
 
fi
 

	
 
# Set-up functions for printing coloured messages.
 
function debug() {
 
    if [[ $debug != 0 ]]; then
 
        echo -e "${_text_bold}${_text_blue}[DEBUG]${_text_reset}" "$@"
 
    fi
 
}
 

	
 
function info() {
 
    echo -e "${_text_bold}${_text_white}[INFO] ${_text_reset}" "$@"
 
}
 

	
 
function success() {
 
    echo -e "${_text_bold}${_text_green}[OK]   ${_text_reset}" "$@"
 
}
 

	
 
function warning() {
 
    echo -e "${_text_bold}${_text_yellow}[WARN] ${_text_reset}" "$@"
 
}
 

	
 
function error() {
 
    echo -e "${_text_bold}${_text_red}[ERROR]${_text_reset}" "$@" >&2
 
}
 

	
 
# Define error codes.
 
SUCCESS=0
 
ERROR_ARGUMENTS=1
 
ERROR_CONFIG_DIR=2
 
ERROR_PIP_TOOLS_MISSING=3
 

	
 
# Disable debug and quiet modes by default.
 
debug=0
 
quiet=0
 

	
 
# Set-up defaults.
 
virtualenv=""
 

	
 
# If no arguments were given, just show usage help.
 
if [[ -z $1 ]]; then
 
    usage
 
    exit "$SUCCESS"
 
fi
 

	
 
# Parse the arguments
 
while getopts "V:qdvh" opt; do
 
    case "$opt" in
 
        V) virtualenv="$OPTARG";;
 
        q) quiet=1;;
 
        d) debug=1;;
 
        v) version
 
           exit "$SUCCESS";;
 
        h) usage
 
           exit "$SUCCESS";;
 
        *) usage
 
           exit "$ERROR_ARGUMENTS";;
 
    esac
 
done
 
i=$OPTIND
 
shift $(( i-1 ))
 

	
 

	
 
if [[ ${#@} == 0 ]]; then
 
    error "Must pass configuration directory."
 
    usage
 
    exit "$ERROR_ARGUMENTS"
 
fi
 

	
 
# Verify positional arguments.
 
config_dir="$1"
 
if [[ ! -d $config_dir ]]; then
 
    error "No such directory: $config_dir"
 
    exit "$ERROR_ARGUMENTS"
 
fi
 

	
 
# Make sure virtual environment exists.
 
if [[ -n $virtualenv && ! -f $virtualenv/bin/activate ]]; then
 
    error "Invalid virtual environment specified: $virtualenv"
 
    exit "$ERROR_ARGUMENTS"
 
fi
 

	
 
# Activate the virtual environment if it was specified.
 
# shellcheck disable=SC1090 # no point in validating external script
 
[[ -n $virtualenv ]] && source "$virtualenv/bin/activate"
 

	
 
# Verify pip-compile is available.
 
if ! which pip-compile >/dev/null 2>&1; then
 
    error "Could not find command pip-compile from packagep pip-tools. Package might not be available in the virtual environment."
 
    exit "$ERROR_PIP_TOOLS_MISSING"
 
fi
 

	
 
# Process each environment.
 
for environment in "$config_dir"/*; do
 
    # Empty directory.
 
    if [[ ! -e $environment ]]; then
 
        error "Configuration directory is empty: $config_dir"
 
        exit "$ERROR_CONFIG_DIR"
 
    fi
 

	
 
    # Process each .in file.
 
    for req_in in "$environment"/*.in; do
 
        # Directory without .in files.
 
        if [[ ! -e $req_in ]]; then
 
            error "No .in files in directory, skipping: $environment"
 
            continue
 
        fi
 

	
 
        # Figure out if .txt file exists.
 
        req_txt="${req_in%.in}.txt"
 
        if [[ ! -f $req_txt ]]; then
 
            [[ $quiet == 0 ]] && info "Skipping input file with missing .txt file: $req_in"
 
            continue
 
        fi
 

	
 
        # Clean up the existing requirements file to contain only
 
        # package versioning information.
 
        current=$(sed -e 's/[[:blank:]]*#.*//' "$req_txt" | grep -v "^$" | sort -u)
 

	
 
        # Set-up pip-compile invocation based on available options,
 
        # partially in order to get rid of the warnings.
 
        pip_compile_invocation=(
 
            "pip-compile"
 
            "--quiet"
 
            "--allow-unsafe"
 
            "--no-header"
 
            "--no-annotate"
 
            "--no-emit-index-url"
 
        )
 

	
 
        if pip-compile --help | grep -q -- --resolver; then
 
            pip_compile_invocation+=("--resolver=backtracking")
 
        fi
 

	
 
        if pip-compile --help | grep -q -- --strip-extras; then
 
            pip_compile_invocation+=("--strip-extras")
 
        fi
 

	
 
        pip_compile_invocation+=(
 
            "--output-file" "-"
 
            "--upgrade" "$req_in"
 
        )
 

	
 
        # Calculate up-to-date requirements.
 
        if ! new=$("${pip_compile_invocation[@]}"); then
 
            error "Failed while running pip-compile command against (see error stack trace above): $req_in"
 
            continue
 
        fi
 

	
 
        # Clean up the new requirements to contain only package
 
        # versioning information.
 
        new=$(echo "$new" | sed -e 's/[[:blank:]]*#.*//' | grep -v "^$" | sort -u)
 

	
 
        debug "Current requirements:\n$current\n"
 
        debug "New requirements:\n$new\n"
 

	
roles/web_server/files/nginx_verify_site.sh
Show inline comments
 
#!/bin/bash
 
#
 
# nginx_verify_site.sh
 
#
 
# Copyright (C) 2016, Branko Majic <branko@majic.rs>
 
# Copyright (C) 2016, 2025, Branko Majic <branko@majic.rs>
 
#
 
# This program is free software: you can redistribute it and/or modify
 
# it under the terms of the GNU General Public License as published by
 
# the Free Software Foundation, either version 3 of the License, or
 
# (at your option) any later version.
 
#
 
# This program is distributed in the hope that it will be useful,
 
# but WITHOUT ANY WARRANTY; without even the implied warranty of
 
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
# GNU General Public License for more details.
 
#
 
# You should have received a copy of the GNU General Public License
 
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
#
 

	
 
program="nginx_verify_site.sh"
 
version="0.1"
 

	
 
function usage() {
 
    cat <<EOF
 
$program $version, a non-interactive utility for testing a new nginx site configuration file
 

	
 
Usage: $program [OPTIONS] site_configuration_file
 

	
 
$program is a non-interactive utility for testing a new nginx site configuration
 
file. The utility works by copying the existing nginx configuration to a
 
temporary path, deploying the passed-in site configuration file to the temporary
 
location, and running the nginx -t command on temporary configuration
 
copy. During this process the utility will also fix the paths in temporary
 
configuration files on the fly.
 

	
 
A single positional argument is accepted:
 

	
 
site_configuration_file
 
  Path to the (new) file containing the site configuration that should be
 
  tested.
 

	
 
$program accepts the following options:
 

	
 
    -n name   Name to use for site configuration file. Useful when combined with
 
              Ansible's validate command (modules copy/template) which does not
 
              preserve filenames when executed. Defaults to original filename
 
              for site_configuration_file.
 

	
 
    -v        show script version and licensing information
 
    -h        show usage help
 

	
 

	
 
Please report bugs and send feature requests to <branko@majic.rs>.
 
EOF
 
}
 

	
 
function version() {
 
        cat <<EOF
 
$program, version $version
 

	
 
+-----------------------------------------------------------------------+
 
| Copyright (C) 2016, Branko Majic <branko@majic.rs>                    |
 
| Copyright (C) 2016, 2025, Branko Majic <branko@majic.rs>              |
 
|                                                                       |
 
| This program is free software: you can redistribute it and/or modify  |
 
| it under the terms of the GNU General Public License as published by  |
 
| the Free Software Foundation, either version 3 of the License, or     |
 
| (at your option) any later version.                                   |
 
|                                                                       |
 
| This program is distributed in the hope that it will be useful,       |
 
| but WITHOUT ANY WARRANTY; without even the implied warranty of        |
 
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         |
 
| GNU General Public License for more details.                          |
 
|                                                                       |
 
| You should have received a copy of the GNU General Public License     |
 
| along with this program.  If not, see <http://www.gnu.org/licenses/>. |
 
+-----------------------------------------------------------------------+
 

	
 
EOF
 
}
 

	
 
# Set-up colours for message printing if we're not piping and terminal is
 
# capable of outputting the colors.
 
_color_terminal=$(tput colors 2>&1)
 
if [[ -t 1 ]] && (( ${_color_terminal} > 0 )); then
 
    _text_bold=$(tput bold)
 
    _text_white=$(tput setaf 7)
 
    _text_blue=$(tput setaf 6)
 
    _text_green=$(tput setaf 2)
 
    _text_yellow=$(tput setaf 3)
 
    _text_red=$(tput setaf 1)
 
    _text_reset=$(tput sgr0)
 
else
 
    _text_bold=""
 
    _text_white=""
 
    _text_blue=""
 
    _text_green=""
 
    _text_yellow=""
 
    _text_red=""
 
    _text_reset=""
 
fi
 

	
 
# Set-up functions for printing coloured messages.
 
function debug() {
 
    echo "${_text_bold}${_text_blue}[DEBUG]${_text_reset}" "$@"
 
}
 

	
 
function info() {
 
    echo "${_text_bold}${_text_white}[INFO] ${_text_reset}" "$@"
 
}
 

	
 
function success() {
 
    echo "${_text_bold}${_text_green}[OK]   ${_text_reset}" "$@"
 
}
 

	
 
function warning() {
 
    echo "${_text_bold}${_text_yellow}[WARN] ${_text_reset}" "$@"
 
}
 

	
 
function error() {
 
    echo "${_text_bold}${_text_red}[ERROR]${_text_reset}" "$@" >&2
 
}
 

	
 
# Helper function for removing temporary directory.
 
function remove_temp_config() {
 
    [[ -e $temp_config ]] && rm -rf "$temp_config"
 
}
 

	
 
# If no arguments were given, just show usage help.
 
if [[ -z $1 ]]; then
 
    usage
 
    exit 0
 
fi
 

	
 
# Parse the arguments
 
while getopts "n:vh" opt; do
 
    case "$opt" in
 
        n) name="$OPTARG";;
 
        v) version
 
           exit 0;;
 
        h) usage
 
           exit 0;;
 
        *) usage
 
           exit 1;;
 
    esac
 
done
 
i=$OPTIND
 
shift $(($i-1))
 

	
 
# Read the site configuration.
 
site_configuration_file="$1"
 

	
 
# Verify positional arguments.
 
if [[ ! -f $site_configuration_file ]]; then
 
    error "Could not open site configuration file: $site_configuration_file"
 
    exit 1
 
fi
 

	
 
# Determine what the file should be called like in temporary directory. Sanitise
 
# the name if it was passed in, just in case.
 
if [[ -z $name ]]; then
 
    name=$(basename "$site_configuration_file")
 
else
 
    name=$(basename "$name")
 
fi
 

	
 
# Set-up paths where original and temporary configurations can be found.
 
original_config="/etc/nginx"
 
temp_config=$(mktemp -d)
 

	
 
# Remove the temporary directory on exit.
 
trap remove_temp_config EXIT
 

	
 
# Prepare temporary copy for verification.
 
cp -a "$original_config" "$temp_config/"
 
find "$temp_config" -type f -print0 | xargs -0 sed -i -e "s#$original_config#$temp_config/nginx#g"
 

	
 
# Enable the new site configuration in temporary copy.
 
rm -f "$temp_config/nginx/sites-enabled/$name"
 
cp "$site_configuration_file" "$temp_config/nginx/sites-enabled/$name"
 

	
 
# Finally, run the test.
 
nginx -t -c "$temp_config/nginx/nginx.conf"
scripts/run_tests.sh
Show inline comments
 
#!/bin/bash
 
#
 
# run_tests.sh
 
#
 
# Copyright (C) 2017, Branko Majic <branko@majic.rs>
 
# Copyright (C) 2017, 2025, Branko Majic <branko@majic.rs>
 
#
 
# This program is free software: you can redistribute it and/or modify
 
# it under the terms of the GNU General Public License as published by
 
# the Free Software Foundation, either version 3 of the License, or
 
# (at your option) any later version.
 
#
 
# This program is distributed in the hope that it will be useful,
 
# but WITHOUT ANY WARRANTY; without even the implied warranty of
 
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
# GNU General Public License for more details.
 
#
 
# You should have received a copy of the GNU General Public License
 
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
#
 

	
 
program="run_tests.sh"
 

	
 
function usage() {
 
    cat <<EOF
 
$program, a non-interactive utility for running role tests for Majic Ansible
 
Roles
 

	
 
Usage: $program [OPTIONS] (all|role1 ... roleN)
 

	
 
$program is a non-interactive utility for running role tests for Majic Ansible
 
Roles.
 

	
 
The script iterates over all roles within sub-directory "roles" (relative to
 
working directory) that have a valid Molecule configuration, runs the tests, and
 
optionally writes report for all tested roles (see option -r).
 

	
 
Only the default scenario is tested at the moment.
 

	
 
$program accepts the following options:
 

	
 
    -r
 
        Generate report for all roles under sub-directory of current
 
        directory "test_report-YYYY_MM_DD-hh_mm". Within the
 
        sub-directory each role will have its own file named
 
        "role-ROLENAME.txt". In addition, a summary file (summary.txt)
 
        is produced with overview of which roles have passed, failed,
 
        and which roles were skipped.
 

	
 
    -l all|lint
 
        Limit what type of tests should be run. Currently supported
 
        values are:
 

	
 
        all
 
            Runs all the available tests. This is the default.
 

	
 
        lint
 
            Runs only the linting tests. This is useful for performing
 
            a quick check on syntax prior to running more extensive
 
            testing.
 

	
 
    -d
 
        Enable debug mode.
 
    -v
 
        Show script licensing information.
 
    -h
 
        Show usage help.
 

	
 

	
 
Please report bugs and send feature requests to <branko@majic.rs>.
 
EOF
 
}
 

	
 
function version() {
 
    cat <<EOF
 
$program
 

	
 
+-----------------------------------------------------------------------+
 
| Copyright (C) 2017, Branko Majic <branko@majic.rs>                    |
 
| Copyright (C) 2017, 2025, Branko Majic <branko@majic.rs>              |
 
|                                                                       |
 
| This program is free software: you can redistribute it and/or modify  |
 
| it under the terms of the GNU General Public License as published by  |
 
| the Free Software Foundation, either version 3 of the License, or     |
 
| (at your option) any later version.                                   |
 
|                                                                       |
 
| This program is distributed in the hope that it will be useful,       |
 
| but WITHOUT ANY WARRANTY; without even the implied warranty of        |
 
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         |
 
| GNU General Public License for more details.                          |
 
|                                                                       |
 
| You should have received a copy of the GNU General Public License     |
 
| along with this program.  If not, see <http://www.gnu.org/licenses/>. |
 
+-----------------------------------------------------------------------+
 

	
 
EOF
 
}
 

	
 
# Set-up colours for message printing if we're not piping and terminal is
 
# capable of outputting the colors.
 
_color_terminal=$(tput colors 2>&1)
 
if [[ -t 1 ]] && (( _color_terminal > 0 )); then
 
    _text_bold=$(tput bold)
 
    _text_white=$(tput setaf 7)
 
    _text_blue=$(tput setaf 6)
 
    _text_green=$(tput setaf 2)
 
    _text_yellow=$(tput setaf 3)
 
    _text_red=$(tput setaf 1)
 
    _text_reset=$(tput sgr0)
 
else
 
    _text_bold=""
 
    _text_white=""
 
    _text_blue=""
 
    _text_green=""
 
    _text_yellow=""
 
    _text_red=""
 
    _text_reset=""
 
fi
 

	
 
# Set-up functions for printing coloured messages.
 
function debug() {
 
    if [[ $debug != 0 ]]; then
 
        echo "${_text_bold}${_text_blue}[DEBUG]${_text_reset}" "$@"
 
    fi
 
}
 

	
 
function info() {
 
    echo "${_text_bold}${_text_white}[INFO] ${_text_reset}" "$@"
 
}
 

	
 
function success() {
 
    echo "${_text_bold}${_text_green}[OK]   ${_text_reset}" "$@"
 
}
 

	
 
function warning() {
 
    echo "${_text_bold}${_text_yellow}[WARN] ${_text_reset}" "$@"
 
}
 

	
 
function error() {
 
    echo "${_text_bold}${_text_red}[ERROR]${_text_reset}" "$@" >&2
 
}
 

	
 
# Define error codes.
 
SUCCESS=0
 
ERROR_ARGUMENTS=1
 
ERROR_NO_ROLES=2
 
ERROR_MISSING_BINARY=3
 
ERROR_FAILED_ROLES=4
 
ERROR_REPORT=5
 

	
 
# Disable debug mode by default.
 
debug=0
 

	
 
# Default values.
 
report=0
 
tests=all
 

	
 
# If no arguments were given, just show usage help.
 
if [[ -z $1 ]]; then
 
    usage
 
    exit "$SUCCESS"
 
fi
 

	
 
# Parse the arguments
 
while getopts "rl:qdvh" opt; do
 
    case "$opt" in
 
        r) report=1;;
 
        l) tests="$OPTARG";;
 
	d) debug=1;;
 
        v) version
 
           exit "$SUCCESS";;
 
        h) usage
 
           exit "$SUCCESS";;
 
        *) usage
 
           exit "$ERROR_ARGUMENTS";;
 
    esac
 
done
 
i=$OPTIND
 
shift $(( i-1 ))
 

	
 
# Test if the necessary binaries are available.
 
if ! type molecule > /dev/null 2>&1; then
 
    error "Could not locate binary: molecule. Please ensure you are running the script from within correctly set-up Python virtual environment."
 
    exit $ERROR_MISSING_BINARY
 
fi
 

	
 
# Assume success.
 
test_result=0
 

	
 
# Verify arguments.
 
if [[ $tests != "all" && $tests != "lint" ]]; then
 
    error "Unsupported type of tests requested: $tests"
 
    exit $ERROR_ARGUMENTS
 
fi
 

	
 
# Assemble list of roles to run against.
 
roles=()
 
roles_to_test=()
 
roles_to_skip=()
 

	
 
# Assemble list of roles to test.
 
if [[ $1 == "all" ]]; then
 
    debug "Testing of all roles was requested, assembling role list."
 

	
 
    # Traverse directory.
 
    for role_dir in roles/*; do
 
        if [[ -d $role_dir ]]; then
 
            debug "Located candiate role in directory $role_dir"
 
            roles+=("${role_dir#roles/}")
 
        else
 
            debug "Ignoring non-directory $role_dir"
 
        fi
 
    done
 
else
 
    while [[ -n $1 ]]; do
 
        roles+=("$1")
 
        shift 1
 
    done
 
fi
 

	
 
if [[ ${#roles[@]} == 0 ]]; then
 
    error "No role has been specified for testing."
 
    exit $ERROR_ARGUMENTS
 
fi
 

	
 
# Determine which roles have available tests.
 
for role in "${roles[@]}"; do
 
    role_dir="roles/$role"
 
    if [[ ! -d "roles/$role" ]]; then
 
        warning "Could not locate role $role in directory $role_dir"
 
        roles_to_skip+=("$role")
 
    elif [[ -f "$role_dir/molecule/default/molecule.yml" ]]; then
 
        debug "Role $role contains Molecule configuration."
 
         roles_to_test+=("$role")
 
    else
 
        warning "Role $role cannot be tested - missing Molecule configuration."
 
        roles_to_skip+=("$role")
 
    fi
 
done
 

	
 
# Output some helpful info, and ensure we can actually run tests against
 
# something.
 
info "Testing requested for roles: ${roles[*]}"
 
[[ ${#roles_to_skip[@]} != 0 ]] && info "The following roles will not be tested: ${roles_to_skip[*]}"
 
if [[ ${#roles_to_test[@]} == 0 ]]; then
 
    error "No roles can be tested."
 
    exit $ERROR_NO_ROLES
 
fi
 
info "The following roles will be tested: ${roles_to_test[*]}"
 

	
 
# Prepare directory for storing reports.
 
if [[ $report == 1 ]]; then
 
    report_directory="$(pwd)/test_report-$(date +%Y_%m_%d-%H_%M_%S)"
 
    report_summary="${report_directory}/summary.txt"
 
    if ! mkdir "$report_directory"; then
 
        error "Failed to create report directory $report_directory"
 
        exit $ERROR_REPORT
 
    fi
 
    touch "$report_summary"
 
    debug "Created report directory $report_directory."
 

	
 
    # Output skipped roles to summary immediatelly.
 
    for role in "${roles_to_skip[@]}"; do
 
        echo "[SKIP] $role" >> "$report_summary"
 
    done
 
else
 
    debug "No report directory will be created."
 
fi
 

	
 
# Test the roles.
 
passed_roles=()
 
failed_roles=()
0 comments (0 inline, 0 general)