import files

This commit is contained in:
Yann Autissier
2021-02-09 17:05:00 +01:00
parent f5c4576411
commit 44a6d37ba5
425 changed files with 23195 additions and 0 deletions
+1
View File
@@ -0,0 +1 @@
vars/local.yml
+12
View File
@@ -0,0 +1,12 @@
; DO NOT EDIT (unless you know what you are doing)
;
; This subdirectory is a git "subrepo", and this file is maintained by the
; git-subrepo command. See https://github.com/git-commands/git-subrepo#readme
;
[subrepo]
remote = ssh://git@github.com/1001Pharmacies/ansible-hosts
branch = master
commit = a495a6dbfae1f3c32f8e968c1ff2b3596ab42f27
parent = 85a259e1f4db43a63c58b4c8fe39b5d5e3b54053
method = merge
cmdver = 0.4.0
+4
View File
@@ -0,0 +1,4 @@
# Authors
* **Yann Autissier** - *Initial work* - [aya](https://github.com/aya)
+5
View File
@@ -0,0 +1,5 @@
# Changelog
## v1.0.0 (December 20, 2016)
* Initial release
+20
View File
@@ -0,0 +1,20 @@
MIT License
Copyright (c) 2016 Yann Autissier
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+110
View File
@@ -0,0 +1,110 @@
# Ansible role to customize servers
An ansible role to customize your servers after a fresh install
## Role Variables
* `hosts_ssh_users` - A list of github usernames. We will fetch ssh keys from their github account and add it to the authorized_keys of the ansible user.
``` yaml
# a list of github usernames to get public keys
hosts_ssh_users: []
```
* `hosts_enable_zram` - Activate zram swap devices. This option allows to create virtual swap devices compressed in RAM. It can increase hosts performances, specially on hosts without physical swap.
``` yaml
# Activate zram swap devices
hosts_enable_zram: false
```
* `hosts_enable_rc` - Run user specific functions on ssh connection. This allow a user to customize his session when connecting to a server, like attaching automaticaly a screen session for example.
``` yaml
# run user specific rc functions on ssh connection
hosts_enable_rc: false
```
* `hosts_rc_functions` - List of user specific functions to run on ssh connection. Here you can add any function to be called when you connect to the host. Default functions are available in the /etc/profile.d/rc_functions.sh file.
``` yaml
# list of rc functions to call at user connection
hosts_rc_functions:
# customize PS1 variable
- 01_custom_ps1
# customize PROMPT variable
# - 02_custom_prompt
# launch a ssh agent and load all private keys located in ~/.ssh
# - 03_ssh_agent
# create and/or attach a tmux session
# - 04_attach_tmux
# create and/or attach a screen session
- 05_attach_screen
```
* `hosts_rc_cleanup` - List of rc functions you do not want to run anymore. If you had previously activated a rc function in `hosts_rc_functions`, you can add it to `hosts_rc_cleanup` to disable it.
``` yaml
# list of rc functions to cleanup (remove files)
# hosts_rc_cleanup:
# - 03_ssh_agent
# - 04_attach_tmux
```
* `hosts_etc_bashrc` - The location of the /etc/bashrc file on the current distro
``` yaml
# location of /etc/bashrc
hosts_etc_bashrc: /etc/bashrc
```
* `hosts_packages` - A list of packages to install on your servers. This list should be overrided for a specific distro.
``` yaml
# packages specific to a distribution
hosts_packages: []
```
* `hosts_packages_common` - A common list of packages to install on your servers. This list should be common to all distros.
``` yaml
# packages common to all distributions
hosts_packages_common:
- { "name": "bash", "state": "present" }
- { "name": "ca-certificates", "state": "present" }
- { "name": "rsync", "state": "present" }
- { "name": "screen", "state": "present" }
- { "name": "tzdata", "state": "present" }
```
## Example
To launch this role on your `hosts` servers, run the default playbook.
``` bash
$ ansible-playbook playbook.yml
```
It will install the following packages : bash, ca-certificates, rsync, screen, tzdata and vim (plus libselinux-python on redhat).
## Common configurations
This example configuration will add the [ssh keys from aya's github user](https://github.com/aya.keys) to your remote ~/.ssh/authorized_keys.
It will create a ~/.rc.d and touch 01_custom_ps1 and 02_attach_screen files into this directory, resulting in a customized PS1 and automaticaly attaching a screen on (re)connection on the remote server.
``` yaml
hosts_ssh_users:
- aya
hosts_enable_rc: true
hosts_rc_functions:
- 01_custom_ps1
- 02_attach_screen
```
## Tests
To test this role on your `hosts` servers, run the tests/playbook.yml playbook.
``` bash
$ ansible-playbook tests/playbook.yml
```
+142
View File
@@ -0,0 +1,142 @@
---
# file: defaults/main.yml
# enable cloud-init
hosts_enable_cloudinit: false
# enable rc.local script
hosts_enable_local: false
# run user specific rc functions on ssh connection
hosts_enable_rc: false
# Activate zram swap devices on host
hosts_enable_zram: false
# git repositories to clone
hosts_git_repositories: []
# - { "repo": "ssh://git@github.com/aya/infra", "dest": "/src" }
# list of rc functions to call at user connection
hosts_rc_functions:
# customize PS1 variable
- 01_custom_ps1
# customize PROMPT variable
- 02_custom_prompt
# launch a ssh agent and load all private keys located in ~/.ssh
- 03_ssh_agent
# create and/or attach a tmux session
# - 04_attach_tmux
# create and/or attach a screen session
- 05_attach_screen
# display system information
- 06_pfetch
# list of rc functions to cleanup (remove files)
# hosts_rc_cleanup:
# - 03_ssh_agent
# - 04_attach_tmux
# packages to install
hosts_packages: []
# packages specific to a distribution
hosts_packages_distro: []
# packages common to all distributions
hosts_packages_common:
- { "name": "bash", "state": "present" }
- { "name": "ca-certificates", "state": "present" }
- { "name": "rsync", "state": "present" }
- { "name": "screen", "state": "present" }
- { "name": "tzdata", "state": "present" }
# a list of SSH private keys to copy
hosts_ssh_private_keys: []
# - ~/.ssh/id_rsa
# a list of public hosts keys to add to known_hosts
hosts_ssh_public_hosts_keys:
- { "name": "github.com", "key": "files/etc/ssh/github.com.pub" }
# a list of github usernames to get public keys
hosts_ssh_users: []
# - aya
# a list of environment variables to write to user ~/.env
hosts_user_env: []
# - SHELL
hosts_cloudinit_config:
users:
- default
disable_root: true
mount_default_fields: [~, ~, 'auto', 'defaults,nofail', '0', '2']
resize_rootfs_tmp: /dev
ssh_pwauth: 0
preserve_hostname: false
datasource_list:
- Ec2
datasource:
Ec2:
metadata_urls:
- 'http://169.254.169.254'
timeout: 5
max_wait: 10
cloud_init_modules:
- migrator
- seed_random
- bootcmd
- write-files
- growpart
- resizefs
- disk_setup
- mounts
- set_hostname
- update_hostname
- update_etc_hosts
- resolv_conf
- ca-certs
- rsyslog
- users-groups
- ssh
cloud_config_modules:
- ssh-import-id
- locale
- set-passwords
- apk-configure
- ntp
- timezone
- disable-ec2-metadata
- runcmd
cloud_final_modules:
- package-update-upgrade-install
- puppet
- chef
- mcollective
- salt-minion
- rightscale_userdata
- scripts-vendor
- scripts-per-once
- scripts-per-boot
- scripts-per-instance
- scripts-user
- ssh-authkey-fingerprints
- keys-to-console
- phone-home
- final-message
- power-state-change
system_info:
distro: alpine
default_user:
name: alpine
lock_passwd: True
gecos: alpine Cloud User
groups: [adm, sudo]
sudo: ["ALL=(ALL) NOPASSWD:ALL"]
shell: /bin/ash
paths:
cloud_dir: /var/lib/cloud/
templates_dir: /etc/cloud/templates/
ssh_svcname: sshd
+105
View File
@@ -0,0 +1,105 @@
#!/bin/bash
### BEGIN INIT INFO
# Provides: zram
# Required-Start:
# Required-Stop:
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: Increased Performance In Linux With zRam (Virtual Swap Compressed in RAM)
# Description: Adapted from systemd scripts at https://github.com/mystilleef/FedoraZram
### END INIT INFO
# percent of RAM assigned to zRam swap devices
RATIO=33
# priority of zRam swap devices
PRIORITY=1024
# load system specific configurations
[ -r /etc/default/zram ] && . /etc/default/zram
[ -r /etc/sysconfig/zram ] && . /etc/sysconfig/zram
start() {
# get number of CPUs
num_cpus=$(grep -c ^processor /proc/cpuinfo 2>/dev/null)
# if something goes wrong, assume we have 1
[ $? -eq 0 ] && [ "${num_cpus:-0}" != 0 ] || num_cpus=1
# load kernel module
if /sbin/modinfo zram 2>/dev/null | grep -q ' zram_num_devices:' 2>/dev/null; then
/sbin/modprobe zram zram_num_devices=$num_cpus
elif /sbin/modinfo zram 2>/dev/null | grep -q ' num_devices:' 2>/dev/null; then
/sbin/modprobe zram num_devices=$num_cpus
else
/bin/echo "Unable to load zram kernel module." && exit 1
fi
# get amount of memory
mem_total_kb=$(awk '$1 == "MemTotal:" {print $2}' /proc/meminfo)
# assign RATIO% of system memory to zram
mem_total_zram=$((mem_total_kb * ${RATIO:-33} / 100 * 1024))
# create one zram swap device per cpu
for i in $(seq 0 $((num_cpus - 1))); do
# enable lz4 if supported
/bin/grep -q lz4 /sys/block/zram$i/comp_algorithm 2>/dev/null && /bin/echo lz4 > /sys/block/zram$i/comp_algorithm 2>/dev/null
# initialize the device
/bin/echo $((mem_total_zram / num_cpus)) > /sys/block/zram$i/disksize 2>/dev/null
# create a swap filesystem
/sbin/mkswap /dev/zram$i >/dev/null 2>&1
# activate zram swap device
/bin/echo -n "Adding swap device /dev/zram$i... "
/sbin/swapon -p ${PRIORITY:-1024} /dev/zram$i >/dev/null 2>&1
result=$? && [ ${result} -eq 0 ] && /bin/echo "OK" || /bin/echo "ERROR"
done
[ ${result:-0} -ge ${return:-0} ] && return=${result}
}
stop() {
# remove swap devices
for dev in $(awk '$1 ~ /^\/dev\/zram/ {print $1}' /proc/swaps); do
/bin/echo -n "Removing swap device $dev... "
/sbin/swapoff $dev >/dev/null 2>&1
result=$? && [ ${result} -eq 0 ] && /bin/echo "OK" || /bin/echo "ERROR"
done
[ ${result:-0} -ge ${return:-0} ] && return=${result}
# remove zram kernel module
if grep -q "^zram " /proc/modules; then
sleep 1
/sbin/rmmod zram
fi
}
status() {
for block in /sys/block/zram*; do
[ -d "$block" ] && /bin/echo -n "/dev/${block/*\/}: " || continue
[ $(<$block/compr_data_size) -gt 0 ] \
&& compr_ratio=$(awk "BEGIN { printf \"%.2f\", "$(<$block/orig_data_size)/$(<$block/compr_data_size)" }") \
|| compr_ratio=0
[ -r $block/stat ] && [ -r $block/mm_stat ] \
&& /usr/bin/awk 'NF==11 {printf("read: %8d, write: %8d, wait: %8d", $1, $5, $11)}' $block/stat && /bin/echo -n ", " \
&& /usr/bin/awk 'NF==7 {printf("orig_data_size: %12d, compr_data_size: %12d", $1, $2)}' $block/mm_stat && /bin/echo -n ", " \
&& /bin/echo "compr_ratio: $compr_ratio" \
|| /bin/echo "read: $(<$block/num_reads), write: $(<$block/num_writes), orig_data_size: $(<$block/orig_data_size), compr_data_size: $(<$block/compr_data_size), compr_ratio: $compr_ratio"
done
}
case "$1" in
start)
start
;;
stop)
stop
;;
restart)
stop
start
;;
status)
status
;;
*)
/bin/echo "Usage: $0 {start|stop|restart|status}"
esac
exit ${return:-1}
+18
View File
@@ -0,0 +1,18 @@
#!/sbin/openrc-run
depend() {
need localmount swap
after bootmisc modules
}
start() {
/etc/init.d/zram start
}
stop() {
/etc/init.d/zram stop
}
status() {
/etc/init.d/zram status
}
+6
View File
@@ -0,0 +1,6 @@
UNAUTHORIZED ACCESS TO THIS DEVICE IS PROHIBITED
You must have explicit, authorized permission to access or configure this device.
Unauthorized attempts and actions to access or use this system may result in civil and/or criminal penalties.
All activities performed on this device are logged and monitored.
@@ -0,0 +1,2 @@
#!/bin/sh
cd /root && ( make ansible-pull > /var/log/ansible.log || reboot ) &
@@ -0,0 +1,39 @@
# shellcheck shell=sh
# test current shell flags
case $- in
# if we are in an interactive shell
*i*)
# load user stuff from files ~/.rc.d/*
for file in "${HOME}"/.rc.d/*; do
# read files only
if [ -f "${file}" ]; then
func_name=$(basename "${file}")
func_args=$(cat "${file}")
# at this stage, func_name can start with numbers to allow ordering function calls with file names starting with numbers
# func_name must start with a letter, remove all other characters at the beginning of func_name until a letter is found
while [ "${func_name}" != "" ] && [ "${func_name#[a-z]}" = "${func_name}" ]; do
# remove first char of func_name
func_name="${func_name#?}"
done
# call user function with args passed from the content of the file
command -v "${func_name}" >/dev/null 2>&1 && "${func_name}" "${func_args}"
fi
done
# load user stuff from env vars RC_*
IFS="$(printf '%b_' '\n')"; IFS="${IFS%_}"; for line in $(printenv 2>/dev/null |awk '$0 ~ /^RC_[1-9A-Z_]*=/'); do
func_name=$(printf '%s\n' "${line%%=*}" |awk '{print tolower(substr($0,4))}')
eval func_args=\$"${line%%=*}"
[ "${func_args}" = "false" ] && continue
[ "${func_args}" = "true" ] && unset func_args
# at this stage, func_name can start with numbers to allow ordering function calls with file names starting with numbers
# func_name must start with a letter, remove all other characters at the beginning of func_name until a letter is found
while [ "${func_name}" != "" ] && [ "${func_name#[a-z]}" = "${func_name}" ]; do
# remove first char of func_name
func_name="${func_name#?}"
done
# call user function with args passed from the value of the env var
command -v "${func_name}" >/dev/null 2>&1 && "${func_name}" "${func_args}"
done
unset IFS
;;
esac
@@ -0,0 +1,218 @@
# shellcheck shell=sh
## force() runs a command sine die
force() {
if [ $# -gt 0 ]; then
while true; do
"$@"
sleep 1
done
fi
}
## force8() runs a command sine die if not already running
force8() {
if [ $# -gt 0 ]; then
while true; do
# awk expression to match $@
[ "$(ps wwx -o args 2>/dev/null |awk -v field="${PS_X_FIELD:-1}" '
BEGIN {nargs=split("'"$*"'",args)}
# if match first field
$field == args[1] {
matched=1;
# match following fields
for (i=1;i<=NF-field;i++) {
if ($(i+field) == args[i+1]) {matched++}
}
# all fields matched
if (matched == nargs) {found++}
}
END {print found+0}'
)" = 0 ] && "$@"
sleep 1
done
fi
}
## load_average() prints the current load average
load_average() {
awk '{printf "%.1f\n" $1}' /proc/loadavg 2>/dev/null \
|| uptime 2>/dev/null |awk '{printf "%.1f\n", $(NF-2)}'
}
## process_count() prints number of "processes"/"running processes"/"D-state"
process_count() {
ps ax -o stat 2>/dev/null |awk '
$1 ~ /R/ {process_running++};
$1 ~ /D/ {process_dstate++};
END {
print NR-1"/"process_running+0"/"process_dstate+0;
}'
}
## prompt_set() exports custom PROMPT_COMMAND
prompt_set() {
case "${TERM}" in
screen*)
ESCAPE_CODE_DCS="\033k"
ESCAPE_CODE_ST="\033\\"
;;
linux*|xterm*|rxvt*)
ESCAPE_CODE_DCS="\033]0;"
ESCAPE_CODE_ST="\007"
;;
*)
;;
esac
# in a screen
if [ -n "${STY}" ]; then
export PROMPT_COMMAND='printf "${ESCAPE_CODE_DCS:-\033]0;}%s${ESCAPE_CODE_ST:-\007}" "${PWD##*/}"'
else
export PROMPT_COMMAND='printf "${ESCAPE_CODE_DCS:-\033]0;}%s@%s:%s${ESCAPE_CODE_ST:-\007}" "${USER}" "${HOSTNAME%%.*}" "${PWD##*/}"'
fi
unset ESCAPE_CODE_DCS ESCAPE_CODE_ST
}
## ps1_set() exports custom PS1
ps1_set() {
case "$0" in
*sh)
COLOR_DGRAY="\[\033[1;30m\]"
COLOR_RED="\[\033[01;31m\]"
COLOR_GREEN="\[\033[01;32m\]"
COLOR_BROWN="\[\033[0;33m\]"
COLOR_YELLOW="\[\033[01;33m\]"
COLOR_BLUE="\[\033[01;34m\]"
COLOR_CYAN="\[\033[0;36m\]"
COLOR_GRAY="\[\033[0;37m\]"
COLOR_NC="\[\033[0m\]"
;;
*)
;;
esac
PS1_COUNT="${COLOR_DGRAY}[${COLOR_BLUE}\$(process_count 2>/dev/null)${COLOR_DGRAY}|${COLOR_BLUE}\$(user_count 2>/dev/null)${COLOR_DGRAY}|${COLOR_BLUE}\$(load_average 2>/dev/null)${COLOR_DGRAY}]${COLOR_NC}"
PS1_END="${COLOR_DGRAY}\$(if [ \"\$(id -u)\" = 0 ]; then printf \"#\"; else printf \"\$\"; fi)${COLOR_NC}"
if type __git_ps1 >/dev/null 2>&1; then
PS1_GIT="\$(__git_ps1 2>/dev/null \" (%s)\")"
else
PS1_GIT="\$(BRANCH=\$(git rev-parse --abbrev-ref HEAD 2>/dev/null); [ -n \"\${BRANCH}\" ] && printf \" (\${BRANCH})\")"
fi
PS1_GIT="${COLOR_CYAN}${PS1_GIT}${COLOR_NC}"
PS1_HOSTNAME_COLOR="\`case \"\${ENV}\" in [Pp][Rr][0Oo][Dd]*) printf \"${COLOR_RED}\";; *) if [ -n \"\${ENV}\" ]; then printf \"${COLOR_YELLOW}\"; else printf \"${COLOR_GREEN}\"; fi;; esac\`"
PS1_HOSTNAME="${PS1_HOSTNAME_COLOR}\$(hostname |sed 's/\..*//')${COLOR_NC}"
PS1_USER_COLOR="\$(if [ \"\$(id -u)\" = 0 ]; then printf \"${COLOR_RED}\"; else printf \"${COLOR_BROWN}\"; fi)"
PS1_USER="${PS1_USER_COLOR}\$(id -nu)${COLOR_NC}"
PS1_WORKDIR="${COLOR_GRAY}\$(pwd |sed 's|^'\${HOME}'\(/.*\)*$|~\1|')${COLOR_NC}"
export PS1="${PS1_COUNT}${PS1_USER}${COLOR_DGRAY}@${PS1_HOSTNAME}${COLOR_DGRAY}:${PS1_WORKDIR}${PS1_GIT}${PS1_END} "
unset PS1_COUNT PS1_END PS1_GIT PS1_HOSTNAME PS1_HOSTNAME_COLOR PS1_USER PS1_USER_COLOR PS1_WORKDIR
}
## screen_attach() attaches existing screen session or creates a new one
screen_attach() {
command -v screen >/dev/null 2>&1 || return
SCREEN_SESSION="$(id -nu)@$(hostname |sed 's/\..*//')"
if [ -z "${STY}" ]; then
# attach screen in tmux window 0 only ;)
[ -n "${TMUX}" ] && [ "$(tmux list-window 2>/dev/null |awk '$NF == "(active)" {print $1}' |sed 's/:$//')" != "0" ] && return
printf 'Attaching screen.' && sleep 1 && printf '.' && sleep 1 && printf '.' && sleep 1
exec screen -xRR -S "${SCREEN_SESSION}"
fi
unset SCREEN_SESSION
}
## screen_detach() detaches current screen session
screen_detach() {
screen -d
}
## ssh_add() loads all private keys in ~/.ssh/ to ssh agent
ssh_add() {
command -v ssh-agent >/dev/null 2>&1 && command -v ssh-add >/dev/null 2>&1 || return
SSH_AGENT_DIR="/tmp/ssh-$(id -u)"
SSH_AGENT_SOCK="${SSH_AGENT_DIR}/agent@$(hostname |sed 's/\..*//')"
# launch a new agent
if [ -z "${SSH_AUTH_SOCK}" ]; then
[ ! -d "${SSH_AGENT_DIR}" ] && mkdir -p "${SSH_AGENT_DIR}" 2>/dev/null && chmod 0700 "${SSH_AGENT_DIR}"
# search for an already running agent
if ps wwx -o args |awk '$1 ~ "ssh-agent$" && $3 == "'"${SSH_AGENT_SOCK}"'"' |wc -l |grep -q 0; then
rm -f "${SSH_AGENT_SOCK}"
ssh-agent -a "${SSH_AGENT_SOCK}" >/dev/null 2>&1
fi
fi
# attach to agent
export SSH_AUTH_SOCK="${SSH_AUTH_SOCK:-${SSH_AGENT_SOCK}}"
# list private keys to add
# shellcheck disable=SC2068
for dir in ${@:-${HOME}/.ssh}; do
if [ "${SSH_ADD_RECURSIVE:-}" = true ]; then
GREP_RECURSIVE_FLAG="r"
else
GREP_RECURSIVE_CHAR="*"
fi
SSH_PRIVATE_KEYS="${SSH_PRIVATE_KEYS:-} ${dir}/id_rsa $(grep -l${GREP_RECURSIVE_FLAG:-} 'PRIVATE KEY' "${dir}"/"${GREP_RECURSIVE_CHAR:-}" 2>/dev/null |grep -vw "${dir}"/id_rsa)"
done
# shellcheck disable=SC2086
printf '%s\n' ${SSH_PRIVATE_KEYS} |while read -r file; do
[ -r "${file}" ] || continue
# add private key to agent
ssh-add -l |grep -q "$(ssh-keygen -lf "${file}" 2>/dev/null |awk '{print $2}')" 2>/dev/null || ssh-add "${file}"
done
unset GREP_RECURSIVE_CHAR GREP_RECURSIVE_FLAG SSH_AGENT_DIR SSH_AGENT_SOCK SSH_PRIVATE_KEYS
}
## ssh_del() removes all private keys in ~/.ssh/ from ssh agent
ssh_del() {
command -v ssh-add >/dev/null 2>&1 || return
# attach to agent
if [ -z "${SSH_AUTH_SOCK}" ]; then
return
fi
# list private keys to del
# shellcheck disable=SC2068
for dir in ${@:-${HOME}/.ssh}; do
if [ "${SSH_DEL_RECURSIVE:-}" = true ]; then
GREP_RECURSIVE_FLAG="r"
else
GREP_RECURSIVE_CHAR="*"
fi
SSH_PRIVATE_KEYS="${SSH_PRIVATE_KEYS:-} ${dir}/id_rsa $(grep -l${GREP_RECURSIVE_FLAG:-} 'PRIVATE KEY' "${dir}"/"${GREP_RECURSIVE_CHAR:-}" 2>/dev/null |grep -vw "${dir}"/id_rsa)"
done
# shellcheck disable=SC2086
printf '%s\n' ${SSH_PRIVATE_KEYS} |while read -r file; do
[ -r "${file}" ] || continue
# remove private key from agent
ssh-add -l |grep -q "$(ssh-keygen -lf "${file}" 2>/dev/null |awk '{print $2}')" 2>/dev/null && ssh-add -d "${file}"
done
unset GREP_RECURSIVE_CHAR GREP_RECURSIVE_FLAG SSH_PRIVATE_KEYS
}
## tmux_attach() attaches existing tmux session or creates a new one
tmux_attach() {
command -v tmux >/dev/null 2>&1 || return
TMUX_SESSION="$(id -nu)@$(hostname |sed 's/\..*//')"
if [ -z "${TMUX}" ]; then
printf 'Attaching tmux.' && sleep 1 && printf '.' && sleep 1 && printf '.' && sleep 1
exec tmux -L"${TMUX_SESSION}" new-session -A -s"${TMUX_SESSION}"
fi
unset TMUX_SESSION
}
## tmux_detach() detaches current tmux session
tmux_detach() {
tmux detach
}
## user_count() prints number of "users sessions"/"users"/"logged users"
user_count() {
ps ax -o user,tty 2>/dev/null |awk '
$2 ~ /^(pts|tty)/ {users_session++; logged[$1]++;};
{count[$1]++;}
END {
for (uc in count) {c = c" "uc;}; users_count=split(c,v," ")-1;
for (ul in logged) {l = l" "ul;}; users_logged=split(l,v," ")-1;
print users_session+0"/"users_count"/"users_logged;
}'
}
@@ -0,0 +1 @@
github.com ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAq2A7hRGmdnm9tUDbO9IDSwBK6TbQa+PXYPCPy6rbTrTtw7PHkccKrpp0yVhp5HdEIcKr6pLlVDBfOLX9QUsyCOV0wzfjIJNlGEYsdlLJizHhbn2mUjvSAHQqZETYP81eFzLQNnPHt4EVVUh7VfDESU84KezmD5QlWpXLmvU31/yMf+Se8xhHTvKSCZIFImWwoG6mbUoWf9nzpIoaSjB+weqqUUmpaaasXVal72J+UX2B+2RPW3RcT0eOzQgqlJL3RKrTJvdsjE3JEAvGq3lGHSZXy28G3skua2SmVi/w4yCE6gbODqnTWlg7+wC604ydGXA8VJiS5ap43JXiUFFAaQ==
@@ -0,0 +1,12 @@
[Unit]
Description=Increased Performance In Linux With zRam (Virtual Swap Compressed in RAM)
[Service]
Type=oneshot
RemainAfterExit=yes
EnvironmentFile=-/etc/sysconfig/zram
ExecStart=/etc/init.d/zram start
ExecStop=/etc/init.d/zram stop
[Install]
WantedBy=sysinit.target
+11
View File
@@ -0,0 +1,11 @@
---
# file: handlers/main.yml
- name: update boot config
environment:
PATH: "{{ ansible_env.PATH }}:/usr/sbin:/sbin"
with_together:
- '{{ boot_config }}'
- '{{ boot_config_handler_notify.results }}'
command: "update-extlinux"
when: item.1.changed and item.0.dest == "/etc/update-extlinux.conf"
+46
View File
@@ -0,0 +1,46 @@
# Copyright (c) 2016 Centile
#
# MIT License
# Permission is hereby granted, free of charge, to any person obtaining a
# copy of this software and associated documentation files (the
# "Software"), to deal in the Software without restriction, including
# without limitation the rights to use, copy, modify, merge, publish,
# distribute, sublicense, and/or sell copies of the Software, and to
# permit persons to whom the Software is furnished to do so, subject to
# the following conditions:
#
# The above copyright notice and this permission notice shall be included
# in all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
# IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
# CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#
---
galaxy_info:
author: Yann Autissier
description: An ansible role to customize servers
company: Centile
license: MIT
platforms:
- name: EL
versions:
- all
- name: Fedora
versions:
- all
- name: Debian
versions:
- all
- name: Ubuntu
versions:
- all
- name: Alpine
versions:
- all
dependencies: []
+7
View File
@@ -0,0 +1,7 @@
---
# file: playbook.yml
- hosts: hosts
roles:
- .
+32
View File
@@ -0,0 +1,32 @@
---
# file: tasks/boot.yml
- name: boot - define config
set_fact:
boot_config:
# set clocksource at boot
- dest: /etc/update-extlinux.conf
line: 'default_kernel_opts="\1 clocksource=tsc tsc=reliable"'
regex: '^default_kernel_opts="((?!.*clocksource=tsc tsc=reliable).*)"$'
- name: boot - stat config file
changed_when: false
register: boot_config_stat
stat:
path: '{{item.dest}}'
with_items: '{{boot_config|default([])}}'
- name: boot - update config
become: yes
lineinfile:
backrefs: true
dest: '{{item.0.dest}}'
line: '{{item.0.line}}'
regex: '{{item.0.regex}}'
with_together:
- '{{boot_config|default([])}}'
- '{{boot_config_stat.results}}'
when: item.1.stat.exists
register: boot_config_handler_notify
notify:
- update boot config
+48
View File
@@ -0,0 +1,48 @@
---
# file: tasks/cloudinit.yml
- name: cloudinit - install cloud-init packages
package: name="cloud-init" state="present"
become: yes
when: hosts_enable_cloudinit|default(false) and ansible_os_family|lower != "alpine"
- name: cloudinit - install cloud-init packages
apk: name="{{item.name}}" state="{{item.state}}"
apk:
name: cloud-init
state: present
repository:
- http://dl-cdn.alpinelinux.org/alpine/edge/main
- http://dl-cdn.alpinelinux.org/alpine/edge/testing
- http://dl-cdn.alpinelinux.org/alpine/edge/community
- http://dl-cdn.alpinelinux.org/alpine/latest-stable/main
- http://dl-cdn.alpinelinux.org/alpine/latest-stable/community
with_items:
- { "name": "cloud-init", "state": "present" }
- { "name": "cloud-init-openrc", "state": "present" }
become: yes
when: hosts_enable_cloudinit|default(false) and ansible_os_family|lower == "alpine"
- name: cloudinit - update /etc/cloud/cloud.cfg
template:
src: etc/cloud/cloud.cfg.j2
dest: /etc/cloud/cloud.cfg
force: yes
when: hosts_enable_cloudinit|default(false)
- name: cloudinit - activate service
service:
name: cloud-init
state: started
enabled: yes
when: hosts_enable_cloudinit|default(false) and ansible_service_mgr|lower != "openrc"
become: yes
- name: cloudinit - activate service (openrc)
service:
name: cloud-init
state: started
enabled: yes
runlevel: boot
when: hosts_enable_cloudinit|default(false) and ansible_service_mgr|lower == "openrc"
become: yes
+37
View File
@@ -0,0 +1,37 @@
---
# file: tasks/files.yml
- name: files - copy files
with_items:
- /etc/issue.net
- /etc/profile.d/rc.sh
- /etc/profile.d/rc_functions.sh
copy: src=../files/{{item}} dest={{item}} owner=root group=root mode=0644
become: yes
- name: files - copy binary files
with_items:
- /etc/init.d/zram
copy: src=../files/{{item}} dest={{item}} owner=root group=root mode=0755
become: yes
- name: files - copy systemd files
with_items:
- /etc/systemd/system/zram.service
copy: src=../files/{{item}} dest={{item}} owner=root group=root mode=0644
when: ansible_service_mgr|lower == "systemd"
become: yes
- name: files - copy openrc files
with_items:
- /etc/init.d/zram-openrc
- /etc/local.d/ansible.start
copy: src=../files/{{item}} dest={{item}} owner=root group=root mode=0755
when: ansible_service_mgr|lower == "openrc"
become: yes
- name: files - get remote binary files
with_items:
- https://raw.githubusercontent.com/dylanaraps/pfetch/master/pfetch
get_url: url={{item}} dest=/usr/local/bin owner=root group=root mode=0755
become: yes
+10
View File
@@ -0,0 +1,10 @@
---
# file: tasks/git.yml
- name: git - clone repositories
with_items: "{{ hosts_git_repositories|default([]) }}"
git:
repo: "{{ item.repo }}"
dest: "{{ item.dest|default('/src') }}"
key_file: "{{ item.key_file|default('~/.ssh/id_rsa') }}"
version: "{{ item.version|default('HEAD') }}"
+30
View File
@@ -0,0 +1,30 @@
---
# file: tasks/main.yml
- import_tasks: vars.yml
tags:
- vars
- import_tasks: boot.yml
tags:
- boot
- import_tasks: cloudinit.yml
tags:
- cloudinit
- import_tasks: packages.yml
tags:
- packages
- import_tasks: ssh.yml
tags:
- ssh
- import_tasks: files.yml
tags:
- files
- import_tasks: git.yml
tags:
- git
- import_tasks: service.yml
tags:
- service
- import_tasks: user.yml
tags:
- user
+7
View File
@@ -0,0 +1,7 @@
---
# file: tasks/packages.yml
- name: packages - install/remove packages
package: name="{{item.name}}" state="{{item.state}}"
with_items: "{{hosts_packages_common|default([]) + hosts_packages_distro|default([]) + hosts_packages|default([])}}"
become: yes
+26
View File
@@ -0,0 +1,26 @@
---
# file: tasks/service.yml
- name: service - activate local (openrc)
service:
name: local
enabled: yes
when: hosts_enable_local|default(false) and ansible_service_mgr|lower == "openrc"
become: yes
- name: service - activate zram
service:
name: zram
state: started
enabled: yes
when: hosts_enable_zram|default(false) and ansible_service_mgr|lower != "openrc"
become: yes
- name: service - activate zram (openrc)
service:
name: zram-openrc
state: started
enabled: yes
runlevel: boot
when: hosts_enable_zram|default(false) and ansible_service_mgr|lower == "openrc"
become: yes
+48
View File
@@ -0,0 +1,48 @@
---
# file: tasks/ssh.yml
- name: ssh - add keys to file ~/.ssh/authorized_keys
authorized_key: user="root" key=https://github.com/{{item}}.keys
with_items: "{{hosts_ssh_users|default([])}}"
become: yes
- name: ssh - copy ssh private keys
with_items: "{{hosts_ssh_private_keys|default([])}}"
copy: src={{item}} dest=~/.ssh/ mode=0400
become: yes
- name: ssh - add public hosts keys to known_hosts
with_items: "{{hosts_ssh_public_hosts_keys|default([])}}"
known_hosts:
name: "{{item.name}}"
key: "{{ lookup('file', '{{item.key}}') }}"
become: yes
- name: ssh - define configuration
set_fact:
sshd_config:
- dest: /etc/conf.d/dropbear
line: 'DROPBEAR_OPTS="\1 -b /etc/issue.net"'
regex: '^DROPBEAR_OPTS="((?!.*-b /etc/issue.net).*)"$'
- dest: /etc/ssh/sshd_config
line: Banner /etc/issue.net
regex: ^#?Banner
- name: ssh - stat configuration file
changed_when: false
register: sshd_config_stat
stat:
path: '{{item.dest}}'
with_items: '{{sshd_config|default([])}}'
- name: ssh - configure sshd
become: yes
lineinfile:
backrefs: true
dest: '{{item.0.dest}}'
line: '{{item.0.line}}'
regex: '{{item.0.regex}}'
with_together:
- '{{sshd_config|default([])}}'
- '{{sshd_config_stat.results}}'
when: item.1.stat.exists
+66
View File
@@ -0,0 +1,66 @@
---
# file: tasks/user.yml
- name: user - create ~/.env
template:
src: .env.j2
dest: ~/.env
force: no
mode: 0400
- name: user - create ~/.rc.d
file: path=~/.rc.d/ state={{hosts_enable_rc|default(false)|ternary('directory', 'absent')}} mode="0700"
- name: user - activate rc functions
with_items: "{{hosts_rc_functions|default([])}}"
file: path="~/.rc.d/{{item}}" state="touch" mode="0600"
when: hosts_enable_rc|default(false)
- name: user - disable rc functions
with_items: "{{hosts_rc_cleanup|default([])}}"
file: path="~/.rc.d/{{item}}" state="absent" mode="0600"
when: hosts_enable_rc|default(false)
- name: user - create directories
with_items:
- ~/.config
- ~/.config/git
file:
path: "{{item}}"
state: directory
- name: user - update ~/.config/git/ignore
with_items:
- '.nfs*'
- '*~'
- '*.log'
- '*.swp'
lineinfile: dest=~/.config/git/ignore create=yes line='{{item}}'
- name: user - update ~/.profile
with_items:
- alias ctop='docker run --rm -ti --volume /var/run/docker.sock:/var/run/docker.sock:ro quay.io/vektorlab/ctop:latest'
- alias vi='vim'
- export EDITOR='vim'
- export PAGER='less'
lineinfile: dest=~/.profile create=yes line='{{item}}'
- name: user - update ~/.screenrc
with_items:
- defscrollback 1024
- hardstatus alwayslastline "%{= kw}[%{G}$USER@%H%{-}] \# %?%-Lw%?[%{G}%n%f %t%{-}]%?%+Lw%?%?%=%-17< [%{B}%l%{-}]"
- shell -$SHELL
lineinfile: dest=~/.screenrc create=yes line='{{item}}'
- name: user - update ~/.vimrc
with_items:
- :set et ai bg=dark sw=4 ts=4 encoding=utf-8 mouse=""
- :syn on
- :filetype plugin indent on
lineinfile: dest=~/.vimrc create=yes line='{{item}}'
- name: user - update ~/Makefile
template:
src: Makefile.j2
dest: ~/Makefile
force: yes
+34
View File
@@ -0,0 +1,34 @@
---
# file: tasks/vars.yml
- name: vars - load per operating system variables
include_vars: "{{item}}"
with_first_found:
- paths:
- "vars/"
- files:
- "{{ansible_distribution|lower}}-{{ansible_distribution_version|lower}}-{{ansible_machine}}.yml" # centos-6.4-i386.yml ubuntu-16.04-x86_64.yml
- "{{ansible_distribution|lower}}-{{ansible_distribution_version|lower}}.yml" # centos-6.4.yml ubuntu-16.04.yml
- "{{ansible_distribution|lower}}-{{ansible_distribution_major_version|lower}}-{{ansible_machine}}.yml" # centos-6-i386.yml ubuntu-16-x86_64.yml
- "{{ansible_distribution|lower}}-{{ansible_distribution_major_version|lower}}.yml" # centos-6.yml ubuntu-16.yml
- "{{ansible_os_family|lower}}-{{ansible_distribution_version|lower}}-{{ansible_machine}}.yml" # redhat-6.4-i386.yml debian-8.5-x86_64.yml
- "{{ansible_os_family|lower}}-{{ansible_distribution_version|lower}}.yml" # redhat-6.4.yml debian-8.5.yml
- "{{ansible_os_family|lower}}-{{ansible_distribution_major_version|lower}}-{{ansible_machine}}.yml" # redhat-6-i386.yml debian-8-x86_64.yml
- "{{ansible_os_family|lower}}-{{ansible_distribution_major_version|lower}}.yml" # redhat-6.yml debian-8.yml
- "{{ansible_distribution|lower}}-{{ansible_machine}}.yml" # centos-i386.yml ubuntu-x86_64.yml
- "{{ansible_distribution|lower}}.yml" # centos.yml ubuntu.yml
- "{{ansible_os_family|lower}}-{{ansible_machine}}.yml" # redhat-i386.yml debian-x86_64.yml
- "{{ansible_os_family|lower}}.yml" # redhat.yml debian.yml
- "{{ansible_system|lower}}-{{ansible_machine}}.yml" # linux-i386.yml linux-x86_64.yml
- "{{ansible_system|lower}}.yml" # linux.yml
- "default.yml" # default.yml
skip: true
- name: vars - override with local variables
include_vars: "{{item}}"
with_first_found:
- paths:
- "vars/"
- files:
- "local.yml"
skip: true
+5
View File
@@ -0,0 +1,5 @@
{% for var in hosts_user_env|default([]) %}
{{var}}={{ lookup('env',var) }}
{% endfor %}
ENV_USER_VARS={{hosts_user_env |default([]) |join(' ')}} DOCKER
DOCKER=false
+35
View File
@@ -0,0 +1,35 @@
USER := 1001pharmacies
APP ?= $(shell hostname -s)
CMDS := exec
SERVICE ?= php
-include .env
ansible:
@make -C $(ANSIBLE_GIT_DIRECTORY) ansible-run-localhost $(foreach var,$(ENV_USER_VARS),$(if $($(var)),$(var)='$($(var))'))
ansible-%:
@make -C $(ANSIBLE_GIT_DIRECTORY) ansible-run-localhost $(foreach var,$(ENV_USER_VARS),$(if $($(var)),$(var)='$($(var))')) ANSIBLE_TAGS=$*
ansible-pull:
@$(foreach var,$(ENV_USER_VARS),$(if $($(var)),$(var)='$($(var))')) $(if $(ANSIBLE_CONFIG),ANSIBLE_CONFIG=$(ANSIBLE_GIT_DIRECTORY)/$(ANSIBLE_CONFIG)) ansible-pull --url $(ANSIBLE_GIT_REPOSITORY) $(if $(ANSIBLE_GIT_KEY_FILE),--key-file $(ANSIBLE_GIT_KEY_FILE)) $(if $(ANSIBLE_GIT_VERSION),--checkout $(ANSIBLE_GIT_VERSION)) $(if $(ANSIBLE_GIT_DIRECTORY),--directory $(ANSIBLE_GIT_DIRECTORY)) $(if $(ANSIBLE_TAGS),--tags $(ANSIBLE_TAGS)) $(if $(ANSIBLE_EXTRA_VARS),--extra-vars '$(ANSIBLE_EXTRA_VARS)') $(if $(findstring true,$(FORCE)),--force) $(if $(findstring true,$(DRYRUN)),--check) --full $(if $(ANSIBLE_INVENTORY),--inventory $(ANSIBLE_INVENTORY)) $(ANSIBLE_VERBOSE) $(ANSIBLE_PLAYBOOK)
exec:
@make -C $(ANSIBLE_GIT_DIRECTORY) exec ARGS='$(ARGS)' DOCKER_NAME=$(USER)_$(ENV)_$(APP)_$(SERVICE) ENV=$(ENV) DOCKER_RUN_WORKDIR=
connect:
@docker exec -it $(USER)_$(ENV)_$(APP)_$(SERVICE) /bin/bash || true
logs:
@docker logs --follow --tail 100 $(USER)_$(ENV)_$(APP)_$(SERVICE) || true
logs-nofollow:
@docker logs --tail 100 $(USER)_$(ENV)_$(APP)_$(SERVICE) || true
run:
@$(ARGS)
ifneq ($(filter $(CMDS),$(firstword $(MAKECMDGOALS))),)
ARGS := $(wordlist 2,$(words $(MAKECMDGOALS)),$(MAKECMDGOALS))
ARGS := $(subst :,\:,$(ARGS))
$(eval $(ARGS):;@:)
endif
@@ -0,0 +1,3 @@
{{ ansible_managed|comment }}
{{ hosts_cloudinit_config|to_nice_yaml }}
+43
View File
@@ -0,0 +1,43 @@
---
# file: tests/goss.yml
- name: tests - create temporary directory
command: mktemp -d
register: tests_mktemp
- name: tests - register goss installation
environment:
PATH: "/usr/local/bin:{{ansible_env.PATH}}"
command: which goss
register: tests_goss_installed
- name: tests - register specific OS goss files
set_fact:
goss_file:
- "goss/main_{{ansible_distribution|lower}}-{{ansible_distribution_major_version|lower}}.yml" # main_centos-6.yml main_centos-7.yml
- "goss/main_{{ansible_distribution|lower}}.yml" # main_centos.yml main_ubuntu.yml
- "goss/main_{{ansible_os_family|lower}}.yml" # main_redhat.yml main_debian.yml
- "goss/main_{{ansible_system|lower}}.yml" # main_linux.yml
- "goss/main.yml" # main.yml
- name: tests - register goss file
set_fact:
tests_goss_file: "{{lookup('first_found', goss_file)}}"
- name: tests - copy test files
copy: src=goss/ dest="{{tests_mktemp.stdout}}"
- name: tests - launch tests
environment:
PATH: "/usr/local/bin:{{ansible_env.PATH}}"
goss: path="{{tests_mktemp.stdout}}/{{tests_goss_file|basename}}" format=rspecish
register: tests_goss_results
ignore_errors: true
become: yes
- name: tests - remove temporary directory
file: path="{{tests_mktemp.stdout}}" state=absent
- name: tests - failure message
fail: msg="{{tests_goss_results.msg}}"
when: tests_goss_results|failed
+10
View File
@@ -0,0 +1,10 @@
file:
/etc/bashrc:
exists: true
mode: "0644"
owner: root
group: root
filetype: file
contains:
- "source /etc/profile.d/bashrc.sh"
@@ -0,0 +1,12 @@
file:
/etc/profile.d/bashrc.sh:
exists: true
mode: "0644"
owner: root
group: root
filetype: file
contains:
- /^function git_branch/
- /^function process_count/
- /^function load_average/
@@ -0,0 +1,13 @@
file:
/etc/bash.bashrc:
exists: true
mode: "0644"
owner: root
group: root
filetype: file
contains:
- "source /etc/profile.d/bashrc.sh"
gossfile:
bash_common.yml: {}
+5
View File
@@ -0,0 +1,5 @@
gossfile:
package.yml: {}
bash.yml: {}
root.yml: {}
# ssh.yml: {}
@@ -0,0 +1,5 @@
gossfile:
package_debian.yml: {}
bash_debian.yml: {}
root.yml: {}
# ssh.yml: {}
@@ -0,0 +1,5 @@
gossfile:
package_redhat.yml: {}
bash.yml: {}
root.yml: {}
# ssh.yml: {}
@@ -0,0 +1,5 @@
gossfile:
package_common.yml: {}
package:
vim:
installed: true
@@ -0,0 +1,11 @@
package:
bash:
installed: true
ca-certificates:
installed: true
screen:
installed: true
rsync:
installed: true
tzdata:
installed: true
@@ -0,0 +1,5 @@
gossfile:
package_common.yml: {}
package:
vim-nox:
installed: true
@@ -0,0 +1,5 @@
gossfile:
package_common.yml: {}
package:
vim-minimal:
installed: true
+9
View File
@@ -0,0 +1,9 @@
file:
/root/.screenrc:
exists: true
mode: "0644"
owner: root
group: root
filetype: file
contains:
- /^hardstatus alwayslastline/
+17
View File
@@ -0,0 +1,17 @@
file:
/etc/ssh/sshd_config:
exists: true
mode: "0644"
owner: root
group: root
filetype: file
contains:
- /^PermitRootLogin prohibit-password/
/root/.ssh/authorized_keys:
exists: true
mode: "0600"
owner: root
group: root
filetype: file
contains:
- "Jpb0EeFEebgvi7Kpp6gpIXKFEeuuE"
+118
View File
@@ -0,0 +1,118 @@
#!/usr/bin/env python
import os
from ansible.module_utils.basic import *
DOCUMENTATION = '''
---
module: goss
author: Mathieu Corbin
short_description: Launch goss (https://github.com/aelsabbahy/goss) test
description:
- Launch goss test. Always changed = False if success.
options:
path:
required: true
description:
- Test file to validate. Must be on the remote machine.
format:
required: false
description:
- change the output goss format.
- Goss format list : goss v --format => [documentation json junit nagios rspecish tap].
- Default: rspecish
output_file:
required: false
description:
- save the result of the goss command in a file whose path is output_file
examples:
- name: test goss file
goss:
path: "/path/to/file.yml"
- name: test goss files
goss:
path: "{{ item }}"
format: json
output_file : /my/output/file-{{ item }}
with_items: "{{ goss_files }}"
'''
# launch goss validate command on the file
def check(module, test_file_path, output_format):
cmd = ""
if output_format is not None:
cmd = "goss -g {0} v --format {1}".format(test_file_path, output_format)
else:
cmd = "goss -g {0} v".format(test_file_path)
return module.run_command(cmd)
# write goss result to output_file_path
def output_file(output_file_path, out):
if output_file_path is not None:
with open(output_file_path, 'w') as output_file:
output_file.write(out)
def main():
module = AnsibleModule(
argument_spec=dict(
path=dict(required=True, type='str'),
format=dict(required=False, type='str'),
output_file=dict(required=False, type='str'),
),
supports_check_mode=False
)
test_file_path = module.params['path'] # test file path
output_format = module.params['format'] # goss output format
output_file_path = module.params['output_file']
if test_file_path is None:
module.fail_json(msg="test file path is null")
test_file_path = os.path.expanduser(test_file_path)
# test if access to test file is ok
if not os.access(test_file_path, os.R_OK):
module.fail_json(msg="Test file %s not readable" % (test_file_path))
# test if test file is not a dir
if os.path.isdir(test_file_path):
module.fail_json(msg="Test file must be a file ! : %s" % (test_file_path))
(rc, out, err) = check(module, test_file_path, output_format)
if output_file_path is not None:
output_file_path = os.path.expanduser(output_file_path)
# check if output_file is a file
if output_file_path.endswith(os.sep):
module.fail_json(msg="output_file must be a file. Actually : %s "
% (output_file_path))
output_dirname = os.path.dirname(output_file_path)
# check if output directory exists
if not os.path.exists(output_dirname):
module.fail_json(msg="directory %s does not exists" % (output_dirname))
# check if writable
if not os.access(os.path.dirname(output_file_path), os.W_OK):
module.fail_json(msg="Destination %s not writable" % (os.path.dirname(output_file_path)))
# write goss result on the output file
output_file(output_file_path, out)
if rc is not None and rc != 0:
error_msg = "err : {0} ; out : {1}".format(err, out)
module.fail_json(msg=error_msg)
result = {}
result['stdout'] = out
result['changed'] = False
module.exit_json(**result)
if __name__ == '__main__':
main()
+6
View File
@@ -0,0 +1,6 @@
---
# file: tests/main.yml
- include: goss.yml
tags:
- tests
+6
View File
@@ -0,0 +1,6 @@
---
# file: tests/playbook.yml
- hosts: '{{ target | default("all") }}'
tasks:
- import_tasks: main.yml
+6
View File
@@ -0,0 +1,6 @@
---
# file vars/debian.yml
hosts_packages_distro:
- { "name": "vim-nox", "state": "present" }
+4
View File
@@ -0,0 +1,4 @@
hosts_packages_distro: []
hosts_packages_common: []
hosts_ssh_users: []
+7
View File
@@ -0,0 +1,7 @@
---
# file vars/redhat.yml
hosts_packages_distro:
- { "name": "vim", "state": "present" }
- { "name": "libselinux-python", "state": "present" }