From: Alexander Barton Date: Wed, 19 Apr 2023 10:24:13 +0000 (+0200) Subject: Initial commit X-Git-Tag: rel-1-0-0~12 X-Git-Url: https://arthur.barton.de/gitweb/?p=ansible-collection-boilerplate.git;a=commitdiff_plain;h=c942cbb65d957b0b32d8915ea0855b2a3ecf1c14 Initial commit This implements the core functionality, including the "ansible-boilerplate" script, Ansible wrapper scripts "a", "ap" and "aps", the Makefile, and boilerplate configuration files for Ansible, ansible-lint, yamllint, etc. --- c942cbb65d957b0b32d8915ea0855b2a3ecf1c14 diff --git a/.ansible-lint b/.ansible-lint new file mode 100644 index 0000000..627e059 --- /dev/null +++ b/.ansible-lint @@ -0,0 +1,14 @@ +--- +# ansible-lint configuration. +# See . + +exclude_paths: + - .git/ + - .venv/ + - ansible_galaxy/ansible_collections/ + - ansible_galaxy/ansible_roles/ + - bin/ + - requirements.yml + +skip_list: + - galaxy[version-incorrect] diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..36f06c5 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,33 @@ +# .editorconfig: Editor settings, see . + +# top-most EditorConfig file +root = true + +# Defaults for all file types: + +[*] +# Use UTF-8 encoding. +charset = utf-8 +# Unix-style newlines. +end_of_line = lf +# Files should end with a newline. +insert_final_newline = true +# Remove whitespace characters preceding newline characters. +trim_trailing_whitespace = true + +# File type specific settings follow: + +[{bin/*,Makefile*,*.sh}] +# Tab indentation (8 characters wide). +indent_style = tab +indent_size = 8 + +[*.{json,md}] +# 4 space indentation. +indent_style = space +indent_size = 4 + +[*.{yaml,yml}] +# 2 space indentation. +indent_style = space +indent_size = 2 diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..d76a635 --- /dev/null +++ b/.gitignore @@ -0,0 +1,14 @@ +# Intentionally untracked files to ignore. See gitignore(5). + +.DS_Store +*.bak +*.new +*~ +/.cache +/.venv +/ansible_galaxy/ansible_collections/ +/ansible_galaxy/ansible_roles/ +/bin/a +/bin/ap +/bin/aps +/dist/ diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..efb96e6 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,14 @@ +{ + "ansible.ansible.path": ".venv/bin/ansible", + "ansible.python.interpreterPath": ".venv/bin/python", + "ansible.validation.lint.path": ".venv/bin/ansible-lint", + "files.associations": { + "**/ansible/**/*.yml": "ansible", + "**/group_vars/*": "ansible", + "**/host_vars/*": "ansible", + "**/playbooks/**/*.yml": "ansible", + "**/roles/**/*.yml": "ansible", + "Makefile*": "makefile" + }, + "python.defaultInterpreterPath": ".venv/bin/python" +} diff --git a/.yamllint.yml b/.yamllint.yml new file mode 100644 index 0000000..d61e11d --- /dev/null +++ b/.yamllint.yml @@ -0,0 +1,16 @@ +--- +# yamllint configuration. +# See . + +extends: default + +rules: + line-length: + max: 100 + level: warning + +ignore: | + .trunk/ + .venv/ + ansible_galaxy/ansible_collections/ + ansible_galaxy/ansible_roles/ diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..e69de29 diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..197ab10 --- /dev/null +++ b/LICENSE @@ -0,0 +1,18 @@ +Copyright 2023 Alexander Barton + +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. diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..df66180 --- /dev/null +++ b/Makefile @@ -0,0 +1,38 @@ +# +# Ansible Boilerplate Collection: Makefile for the project itself. +# + +DIST_D = $(CURDIR)/dist + +default: all + +# Include the "real" boilerplate Makefile into this "wrapper" Makefile: +include Makefile.boilerplate + +check: check-ansible + +install: + +clean: + +distclean: clean distclean-ansible +# Remove distribution directory + rm -fr "$(DIST_D)" + +maintainer-clean: distclean + +dist: all $(VENV_BIN)/ansible-galaxy +# Create distribution archive ... + mkdir -p "$(DIST_D)" + "$(VENV_BIN)"/ansible-galaxy collection build --force --output-path "$(DIST_D)" + +distcheck: dist +# Run tests on distribution archive ... + mkdir -p "$(DIST_D)/check" + tar -C "$(DIST_D)/check" -xzf "$(DIST_D)"/*.tar.gz + test -e "$(VENV_D)" && ln -fs "$(VENV_D)" "$(DIST_D)/check/.venv" + make -C "$(DIST_D)/check" check +# Clean up ... + rm -fr "$(DIST_D)/check" + +.PHONY: default all check install clean distclean maintainer-clean dist distcheck diff --git a/Makefile.boilerplate b/Makefile.boilerplate new file mode 100644 index 0000000..4c4c6d5 --- /dev/null +++ b/Makefile.boilerplate @@ -0,0 +1,67 @@ +# +# Ansible Boilerplate Collection: Makefile for inclusion into projects using it. +# + +PYTHON ?= python3 +SOURCE_ROOT ?= $(CURDIR) +VENV_D = $(SOURCE_ROOT)/.venv +VENV_BIN = $(VENV_D)/bin + +this_makefile_path:=$(word $(words $(MAKEFILE_LIST)),$(MAKEFILE_LIST)) +this_dir:=$(shell cd $(dir $(this_makefile_path));pwd) + +check-ansible: $(VENV_BIN)/ansible-lint +# Check Ansible executable ... + "$(VENV_BIN)"/ansible --version +# Check YAML files ... + "$(VENV_BIN)"/yamllint . +# Run ansible-playbook syntax check, when a "site play" is found ... +ifneq ("$(wildcard playbooks/site.yml)","") + "$(VENV_BIN)"/ansible-playbook --syntax-check playbooks/site.yml +endif +ifneq ("$(wildcard site.yml)","") + "$(VENV_BIN)"/ansible-playbook --syntax-check site.yml +endif +# Run ansible-lint ... + "$(VENV_BIN)"/ansible-lint --offline --project-dir "$(SOURCE_ROOT)" --show-relpath + +distclean-ansible: +# Remove Python "virtual environment" ... + rm -fr "$(SOURCE_ROOT)"/.venv +# Remove Ansible Galaxy collections and roles + rm -fr "$(SOURCE_ROOT)"/ansible_galaxy/ansible_collections "$(SOURCE_ROOT)"/ansible_galaxy/ansible_roles +# Remove cache directory, used by the Ansible "facts cache" for example ... + rm -fr "$(SOURCE_ROOT)"/.cache +# Clean up symlinked commands in dependant projects ... + for cmd in "$(SOURCE_ROOT)"/bin/a "$(SOURCE_ROOT)"/bin/ap "$(SOURCE_ROOT)"/bin/aps; do \ + test -h "$$cmd" && rm -f "$$cmd" || true; \ + done + +$(VENV_BIN)/ansible $(VENV_BIN)/ansible-galaxy $(VENV_BIN)/ansible-lint venv: $(VENV_BIN)/pip +# Install/upgrade Python package manager + "$(VENV_BIN)"/pip install --upgrade pip wheel + touch "$(VENV_BIN)/pip" "$(VENV_BIN)/wheel" +# Install/upgrade Python dependencies ... + "$(VENV_BIN)"/pip install --upgrade --requirement $(this_dir)/requirements.txt + touch "$(VENV_BIN)/ansible" "$(VENV_BIN)/ansible-galaxy" "$(VENV_BIN)/ansible-lint" + +$(VENV_BIN)/pip: +# Create/upgrade Python "virtual environment" + "$(PYTHON)" -m venv "$(SOURCE_ROOT)"/.venv + +.PHONY: venv + +ifneq ($(patsubst %..,,$(lastword $(SOURCE_ROOT))),) +# SOURCE_ROOT does not end in "..", so looks like this Makefile fragment is +# included in the top-level Makefile. So add some proprietary targets to the +# "common" toplevel targets: + +all: $(VENV_BIN)/ansible $(VENV_BIN)/ansible-galaxy $(VENV_BIN)/ansible-lint +check: check-ansible +distclean: distclean-ansible + +upgrade: $(SOURCE_ROOT)/bin/ansible-boilerplate + $(SOURCE_ROOT)/bin/ansible-boilerplate upgrade + +.PHONY: check distclean +endif diff --git a/README.md b/README.md new file mode 100644 index 0000000..12f35bd --- /dev/null +++ b/README.md @@ -0,0 +1,99 @@ +# Ansible Boilerplate Collection - alexbarton.boilerplate + +This Ansible collection provides boilerplate files, plays, roles, scripts etc. +on which new projects that will use Ansible can be based on. + +## Installation + +### Prerequisites + +To install this Ansible collection, you need the `ansible-galaxy` command. If +it is not provided by your operating system installation by default, best is +to create a new Python "virtual environment" inside of your project directory +and install Ansible into it, like this: + +```bash +cd ~/src/my-ansible-project +python3 -m venv .venv +./.venv/bin/pip install -U pip setuptools +./.venv/bin/pip install ansible +``` + +#### Location of the Ansible Boilerplate Collection codebase + +By default, the commands here in the README file as well as the scripts of the +Ansible Boilerplate Collection assume that the code of this collection can be +found on the Ansible Galaxy repository with the name "alexbarton.boilerplate". + +If you want to override this, you can set the `BOILERPLATE_COLLECTION_SRC` +environment variable to: + +* a file name (including path) to a local archive file (e. g. + `/tmp/ansible/alexbarton-boilerplate-0.0.1.tar.gz`) +* a path name to a local Git repository (e. g. + `/usr/local/src/ansible-collection-boilerplate.git`) +* a URL to a remote Git repository (e. g. + `git+https://my.git.server/ansible-collection-boilerplate.git`) +* the name of an Collection stored on the Ansible Galaxy (e. g. + `alexbarton.boilerplate`) + +Example: + +```bash +export BOILERPLATE_COLLECTION_SRC=/tmp/ansible/alexbarton-boilerplate-0.0.1.tar.gz +``` + +### Installing the Ansible Boilerplate Collection + +The following command will install the Ansible Boilerplate Collection from the +location given in the `BOILERPLATE_COLLECTION_SRC` environment variable (see +above) or from the Ansible Galaxy repository with its default name of +"alexbarton.boilerplate", when the environment variable is not set: + +```bash +./.venv/bin/ansible-galaxy collection install -p ansible_galaxy \ + "${BOILERPLATE_COLLECTION_SRC:-alexbarton.boilerplate}" +``` + +## Initializing a New Project + +Once the Ansible Boilerplate Collection is available in the local +`ansible_galaxy/ansible_collections` sub-directory, you can use the +`ansible-boilerplate` command to initialize a new project: + +```bash +./ansible_galaxy/ansible_collections/alexbarton/boilerplate/bin/ansible-boilerplate init +``` + +This initializes an Ansible-based project with some template files, links some +scripts into the local `./bin/` directory (which is created as needed) and +copies the `ansible-boilerplate` command into the `./bin/` directory, too, to +make it available even when the "alexbarton.boilerplate" Ansible Collection is +not yet installed on the local machine (for example, after freshly checking +out the project or running `make distclean`). + +It is a good idea to commit this initial state of your new project to your +code repository. For Git, something like this: + +```bash +git init +git add . +git commit -m "Initial commit" +``` + +## Initializing/Upgrading an Existing Project + +In an existing and already initialized project the `ansible-boilerplate` +command is available in the `./bin/` directory. You can use it to initialize +the project "from scratch" and to upgrade it like this: + +```bash +./bin/ansible-boilerplate upgrade +``` + +Or, when you use a Python virtual environment and stick to using the Makefile +system provided by this project, you can just use the `make` command itself: + +```bash +make upgrade +``` diff --git a/ansible.cfg b/ansible.cfg new file mode 100644 index 0000000..96aa4d0 --- /dev/null +++ b/ansible.cfg @@ -0,0 +1,30 @@ +# Ansible configuration. +# See . + +[defaults] +ansible_managed = Managed by Ansible, DO NOT MODIFY, changes will be overwritten! +collections_paths = ansible_galaxy +fact_caching = jsonfile +fact_caching_connection = .cache +fact_caching_timeout = 3600 +gathering = smart +interpreter_python = auto_silent +inventory = hosts.ini +roles_path = ansible_galaxy/ansible_roles:roles +stdout_callback = yaml + +[colors] +changed = bright yellow +error = bright red +ok = bright green + +[diff] +always = True + +[privilege_escalation] +become = True +become_ask_pass = True + +[ssh_connection] +control_path = %(directory)s/%%h-%%p-%%r +pipelining = True diff --git a/bin/a b/bin/a new file mode 100755 index 0000000..cf1eab0 --- /dev/null +++ b/bin/a @@ -0,0 +1,22 @@ +#!/bin/sh +# +# Ansible Collection Boilerplate: +# "a": ansible(1) wrapper script. +# + +# Change working directory to the base directory ... +cd "$(dirname "$0")/.." || exit 1 + +# Prepare environment ... +set -e +pwd +test -x "${PWD}/.venv/bin/ansible" || make "${PWD}/.venv/bin/ansible" + +# Options ... +options=("$@") + +[[ -r .ansible-vault-secret ]] && options+=("--vault-password-file=.ansible-vault-secret") + +# Run ansible(1): +set -x +"${PWD}/.venv/bin/ansible" "${options[@]}" diff --git a/bin/ansible-boilerplate b/bin/ansible-boilerplate new file mode 100755 index 0000000..3af1566 --- /dev/null +++ b/bin/ansible-boilerplate @@ -0,0 +1,290 @@ +#!/bin/sh -e +# +# Ansible Boilerplate Collection: Setup & Maintenance Script. +# + +# Detect commands to use: +PYTHON="${PYTHON:-$(command -v python3 2>/dev/null || echo "python3")}" +PIP="${PIP:-$(command -v pip 2>/dev/null || echo "pip")}" +ANSIBLE_GALAXY="${ANSIBLE_GALAXY:-$(command -v ansible-galaxy 2>/dev/null || echo "ansible-galaxy")}" + +BASE_D="ansible_galaxy/ansible_collections/alexbarton/boilerplate" + +# +# Show usage information on stderr. +# +Usage() { + { + echo "$0 " + echo + echo " help Show this help text and exit." + echo " init Initialize project and boilerplate code." + echo " upgrade Upgrade boilerplate code and dependencies. [Alias: update, up]" + echo " --force Force overwriting an existing role or collection." + echo + } >&2 +} + +# +# Initialize a new project. +# +# Create some default files and call Upgrade() afterwards. This function does not +# overwrite any already existing file. +# +Init() { + if [ $# -ne 0 ]; then + Usage + exit 1 + fi + if [ -e Makefile.boilerplate ]; then + echo "This is the upstream project! Don't call \"init\" on it!" >&2 + exit 1 + fi + echo "Initialize project:" + + for file in \ + README.md \ + LICENSE \ + ; do + test -e "${file}" || touch "${file}" + done + mkdir -p .vscode playbooks roles + test -e "hosts.ini" || Init_HostsIni + test -e "Makefile" || Init_Makefile + test -e "requirements.yml" || Init_RequirementsYml + + Upgrade --init +} + +# +# Create a Makefile template file. +# +Init_Makefile() { + echo "Creating \"Makefile\" ..." + cat >Makefile <&2) + +default: all + +# Include the Ansible Boilerplate Collection Makefile fragment: +include ansible_galaxy/ansible_collections/alexbarton/boilerplate/Makefile.boilerplate + +all: + +check: + +install: + +clean: + +distclean: clean + +maintainer-clean: distclean + +.PHONY: default all check install clean distclean maintainer-clean +EOF +} + +# +# Create a hosts.ini template file. +# +Init_HostsIni() { + echo "Creating \"hosts.ini\" ..." + cat >hosts.ini <requirements.yml </dev/null; then + # Either an existing ".venv" folder was found or the + # ansible-galaxy(1) command was not found on the system, so + # let's use a Python virtual environment! + echo "Using a Python virtual environment." + PIP="./.venv/bin/pip" + ANSIBLE_GALAXY="./.venv/bin/ansible-galaxy" + if ! [ -x .venv/bin/pip ]; then + echo "Initializing Python virtual environment ..." + "${PYTHON}" -m venv .venv + "${PIP}" install -U pip setuptools + fi + fi + for var in PYTHON PIP ANSIBLE_GALAXY; do + eval 'echo " - ${var} is \"$'"${var}"'\"."' + done + + if ! [ -x "${ANSIBLE_GALAXY}" ]; then + echo "Installing Ansible ..." + "${PIP}" install -U ansible + fi + + # Are we running in a dependent project? If so, perform specific upgrade tasks! + # shellcheck disable=SC2086 + [ -e Makefile.boilerplate ] || Upgrade_Dependent ${is_init} + + if [ -r requirements.txt ]; then + echo "Installing Python dependencies ..." + "${PIP}" install -U -r requirements.txt + fi + + if [ -r requirements.yml ]; then + echo "Upgrading Ansible Galaxy dependencies ..." + # shellcheck disable=SC2248 + "${ANSIBLE_GALAXY}" collection install -U -r requirements.yml ${do_force} + # shellcheck disable=SC2248 + "${ANSIBLE_GALAXY}" role install -r requirements.yml ${do_force} + fi +} + +# +# Upgrade steps for dependent projects only. +# +# --init: Upgrade() is called by the Init() function. +# +Upgrade_Dependent() { + collection="${BOILERPLATE_COLLECTION_SRC:-alexbarton.boilerplate}" + echo "Installing/upgrading \"${collection}\" ..." + "${ANSIBLE_GALAXY}" collection install -U -p ansible_galaxy "${collection}" + + echo "Copying \"boilerplate\" script into bin/ directory ..." + mkdir -p bin + cp -av "${BASE_D}/bin/ansible-boilerplate" "bin/ansible-boilerplate" + + echo "Creating symbolic links to files inside of the Boilerplate Collection ..." + for file in \ + bin/a \ + bin/ap \ + bin/aps \ + ; do + # Create (new) symbolic links, when the target already is a symbolic link or + # does not yet exists. Don't overwrite existing regular files etc.! + test -L "${file}" && ln -fsv "../${BASE_D}/${file}" "${file}" + test -e "${file}" || ln -fsv "../${BASE_D}/${file}" "${file}" + done + + echo "Upgrading template files from the Boilerplate Collection ..." + for file in \ + .ansible-lint \ + .editorconfig \ + .gitignore \ + .vscode/settings.json \ + .yamllint.yml \ + ansible.cfg \ + requirements.txt \ + ; do + # shellcheck disable=SC2086 + Upgrade_Template "${file}" ${is_init} + done + + # Verify that the Boilerplate Collection is available now! + "${ANSIBLE_GALAXY}" collection verify --offline alexbarton.boilerplate +} + +# +# Upgrade a template file. +# +# --init: Initialize a new project, therefore create the template file if it +# does not yet exist. +# +Upgrade_Template() { + # Does the target directory exist? Skip this template file if not! + [ -d "$(dirname "$1")" ] || return 0 + + # Return when the target file does not exist and not in "init mode": + [ ! -e "$1" ] && [ "$2" != "--init" ] && return 0 + + # Remove the target when it is a symbolic link. + [ -L "$1" ] && rm -v "$1" + + # Do not override the target when it exists already! + if [ -e "$1" ]; then + # Target already exists. Is it different? + if ! cmp "$1" "${BASE_D}/$1"; then + # Files are not the same! Install new version in parallel: + install -b -m 0644 -p -v "${BASE_D}/$1" "$1.new" + fi + else + # Target does not yet exist: + install -b -m 0644 -p -v "${BASE_D}/$1" "$1" + fi +} + +cmd="$1" +[ $# -gt 0 ] && shift + +case "${cmd}" in + "init") + Init "$@" + ;; + "upgrade"|"update"|"up") + Upgrade "$@" + ;; + "help"|"--help") + Usage + ;; + *) + Usage + exit 1 +esac +exit 0 diff --git a/bin/ap b/bin/ap new file mode 100755 index 0000000..c3bbdb4 --- /dev/null +++ b/bin/ap @@ -0,0 +1,39 @@ +#!/bin/bash +# +# Ansible Collection Boilerplate: +# "ap": ansible-playbook(1) wrapper script. +# + +# Change working directory to the base directory ... +cd "$(dirname "$0")/.." || exit 1 + +# Prepare environment ... +set -e +pwd +test -x "${PWD}/.venv/bin/ansible-playbook" || make "${PWD}/.venv/bin/ansible" + +# Get playbook name: +play="$1" +shift + +# Search playbook ... +unset playbook +for dir in \ + . \ + playbooks{,/deploy,/site} \ + ansible_galaxy/ansible_collections/*/*/playbooks \ +; do + playbook="${dir}/${play}.yml" + test -r "${playbook}" && break + unset playbook +done +[[ -n "${playbook}" ]] || playbook="${play}" + +# Options ... +options=("$@") + +[[ -r .ansible-vault-secret ]] && options+=("--vault-password-file=.ansible-vault-secret") + +# Run ansible-playbook(1): +set -x +"${PWD}/.venv/bin/ansible-playbook" "${playbook}" "${options[@]}" diff --git a/bin/aps b/bin/aps new file mode 100755 index 0000000..e866dbd --- /dev/null +++ b/bin/aps @@ -0,0 +1,9 @@ +#!/bin/sh +# +# Ansible Collection Boilerplate: +# "aps": ansible-playbook(1) "site" wrapper script. +# + +# Change working directory to the base directory ... +cd "$(dirname "$0")/.." || exit 1 +./bin/ap site "$@" diff --git a/galaxy.yml b/galaxy.yml new file mode 100644 index 0000000..6db0bf4 --- /dev/null +++ b/galaxy.yml @@ -0,0 +1,32 @@ +--- +namespace: alexbarton +name: boilerplate +# NOTE: Remove "galaxy[version-incorrect]" from the "skip_list" in +# .ansible-lint once you bump the version to 1.0.0 (or higher)! +version: 0.0.1 + +authors: + - Alexander Barton + +description: Collection of boilerplate files, plays, roles and scripts for projects using Ansible. +readme: README.md + +license_file: LICENSE + +tags: + - boilerplate + - common + - tools + +dependencies: + "community.general": ">=6.1.0" + +homepage: https://github.com/alexbarton/ansible-collection-boilerplate +documentation: https://github.com/alexbarton/ansible-collection-boilerplate +issues: https://github.com/alexbarton/ansible-collection-boilerplate/issues +repository: https://github.com/alexbarton/ansible-collection-boilerplate + +build_ignore: + - .DS_Store + - .trunk + - .venv diff --git a/meta/runtime.yml b/meta/runtime.yml new file mode 100644 index 0000000..74fa9e7 --- /dev/null +++ b/meta/runtime.yml @@ -0,0 +1,3 @@ +--- + +requires_ansible: '>=2.14.0' diff --git a/playbooks/ping.yml b/playbooks/ping.yml new file mode 100644 index 0000000..241346b --- /dev/null +++ b/playbooks/ping.yml @@ -0,0 +1,15 @@ +--- +# Connect to a system and run the Ansible "ping" module on it. +# +# Example: +# ./bin/ap ping -l example.host.name +# + +- name: Ping system + any_errors_fatal: true + hosts: '{{target|default("all")}}' + + tasks: + + - name: Run the Ansible "ping" module + ansible.builtin.ping: diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..70fe5a0 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,6 @@ +# Python dependencies + +ansible>=7.4 +ansible-core>=2.14 +ansible-lint>=6.14 +yamllint>=1.30