Skip to content

Commit

Permalink
initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
hille721 committed Apr 13, 2023
0 parents commit 27fd22e
Show file tree
Hide file tree
Showing 22 changed files with 1,224 additions and 0 deletions.
55 changes: 55 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
# build products...
*.py[co]
build
AUTHORS.TXT
# Emacs backup and autosave files...
*~
.\#*
\#*
# RPM stuff...
MANIFEST
dist
rpm-build
# Eclipse/PyDev stuff...
.project
.pydevproject
# PyCharm stuff...
.idea
#IntelliJ IDEA stuff..
*.iml
#VSCode stuff..
.vscode/
# Mac OS X stuff...
.DS_Store
# Vim swap files
*.swp
*.swo
[._]*.un~
credentials.yml
# test output
*.retry
*.out
.pytest_cache/
.tox
.cache
.pytest_cache
results.xml
coverage.xml
# Development
/test/develop
lib/ansible_variables.egg-info
# Environments
.env
.venv
env/
venv/
ENV/
env.bak/
venv.bak/
venv
env
/.cache/
# default 'coverage html' results
htmlcov/
# default 'coverage' tool data
.coverage
29 changes: 29 additions & 0 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
---
exclude: '.bumpversion.cfg'
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks.git
rev: v4.4.0
hooks:
- id: end-of-file-fixer
- id: trailing-whitespace
- id: mixed-line-ending
- id: fix-byte-order-marker
- id: check-executables-have-shebangs
- id: check-merge-conflict
- id: check-added-large-files
- id: debug-statements
language_version: python3
- repo: https://github.com/psf/black
rev: 22.12.0
hooks:
- id: black
exclude: ".ci/hack"

- repo: https://github.com/pycqa/flake8.git
rev: 6.0.0
hooks:
- id: flake8
- repo: https://github.com/PyCQA/doc8
rev: v1.1.1
hooks:
- id: doc8
674 changes: 674 additions & 0 deletions LICENSE

Large diffs are not rendered by default.

39 changes: 39 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# Ansible variables

## Installation

```bash
pip install ansible-variables
```

## Usage

```bash
$ ansible-variables -h
usage: ansible-variables [-h] [--version] [-v] [-i INVENTORY] [--vault-id VAULT_IDS]
[--ask-vault-password | --vault-password-file VAULT_PASSWORD_FILES] [--playbook-dir BASEDIR] [--var VARIABLE]
host

positional arguments:
host Ansible hostname for which variable sources should be printed

optional arguments:
--ask-vault-password, --ask-vault-pass
ask for vault password
--playbook-dir BASEDIR
Since this tool does not use playbooks, use this as a substitute playbook directory. This sets the relative path for
many features including roles/ group_vars/ etc.
--var VARIABLE Only check for specific variable
--vault-id VAULT_IDS the vault identity to use
--vault-password-file VAULT_PASSWORD_FILES, --vault-pass-file VAULT_PASSWORD_FILES
vault password file
--version show program's version number, config file location, configured module search path, module location, executable
location and exit
-h, --help show this help message and exit
-i INVENTORY, --inventory INVENTORY, --inventory-file INVENTORY
specify inventory host path or comma separated host list. --inventory-file is deprecated
-v, --verbose Causes Ansible to print more debug messages. Adding multiple -v will increase the verbosity, the builtin plugins
currently evaluate up to -vvvvvv. A reasonable level to start is -vvv, connection debugging might require -vvvv.
Show variable sources for a host.
```
Empty file.
Empty file.
119 changes: 119 additions & 0 deletions lib/ansible_variables/cli/variables.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
import argparse

import rich

from ansible import context
from ansible.cli import CLI
from ansible.cli.arguments import option_helpers as opt_help
from ansible.errors import AnsibleOptionsError
from ansible.utils.display import Display

from ansible_variables.utils.vars import variable_sources, source_mapping

display = Display()

# Internal vars same as defined for ansible-inventory
# (https://github.com/ansible/ansible/blob/d081ed36169f4f74512d1707909185281a30e29b/lib/ansible/cli/inventory.py#L28-L46)
INTERNAL_VARS = frozenset(
[
"ansible_diff_mode",
"ansible_config_file",
"ansible_facts",
"ansible_forks",
"ansible_inventory_sources",
"ansible_limit",
"ansible_playbook_python",
"ansible_run_tags",
"ansible_skip_tags",
"ansible_verbosity",
"ansible_version",
"inventory_dir",
"inventory_file",
"inventory_hostname",
"inventory_hostname_short",
"groups",
"group_names",
"omit",
"playbook_dir",
]
)


class VariablesCLI(CLI):
"""used to display from where a variable value is comming from"""

name = "ansible-variables"

def __init__(self, args):
super(VariablesCLI, self).__init__(args)
self.loader = None
self.inventory = None
self.vm = None

def init_parser(self):
super(VariablesCLI, self).init_parser(
usage="usage: %prog [options] [host]",
epilog="Show variable sources for a host.",
)

opt_help.add_inventory_options(self.parser)
opt_help.add_vault_options(self.parser)
opt_help.add_basedir_options(self.parser)

# remove unused default options
self.parser.add_argument("--list-hosts", help=argparse.SUPPRESS, action=opt_help.UnrecognizedArgument)
self.parser.add_argument(
"-l",
"--limit",
help=argparse.SUPPRESS,
action=opt_help.UnrecognizedArgument,
)

self.parser.add_argument(
"host",
action="store",
help="Ansible hostname for which variable sources should be printed",
)

self.parser.add_argument(
"--var",
action="store",
default=None,
dest="variable",
help="Only check for specific variable",
)

def post_process_args(self, options):
options = super(VariablesCLI, self).post_process_args(options)

display.verbosity = options.verbosity
self.validate_conflicts(options)

return options

def run(self):
super(VariablesCLI, self).run()

# Initialize needed objects
self.loader, self.inventory, self.vm = self._play_prereqs()

host = self.inventory.get_host(context.CLIARGS["host"])
if not host:
raise AnsibleOptionsError("You must pass a single valid host to ansible-variables")

for var, value, source in variable_sources(
vm=self.vm,
host=host,
var=context.CLIARGS["variable"],
verbosity=context.CLIARGS["verbosity"],
):
if var not in INTERNAL_VARS:
rich.print(f"[bold]{var}[/bold]: {value} - [italic]{source_mapping(source)}[/italic]")


def main(args=None):
VariablesCLI.cli_executor(args)


if __name__ == "__main__":
main()
Empty file.
61 changes: 61 additions & 0 deletions lib/ansible_variables/utils/vars.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import contextlib
import io

from ansible import constants as C
from ansible.utils.display import Display

display = Display()


def variable_sources(vm, host, var=None, verbosity=0):
"""get vars with sources
Returns
[(name, value, source)]
"""

C.DEFAULT_DEBUG = True
# we are catching the debug messages here
f = io.StringIO()
with contextlib.redirect_stdout(f):
hostvars = vm.get_vars(host=host)
output = f.getvalue()
# let's print the output again if the verbosity is high enough
if verbosity >= 3:
display.debug(output)
C.DEFAULT_DEBUG = False

if not var:
return [(var, hostvars.data.get(var), source) for var, source in hostvars.sources.items()]

return [(var, hostvars.data.get(var), hostvars.sources.get(var))]


def source_mapping(source):
"""Better wording of sources
Args:
source (str): original source str out of `vm.get_vars`
"""

source_map = {
# host variable in inventory
"host vars for": "host variable defined in inventory",
# group variable in inventory
"group vars, precedence entry 'groups_inventory'": "group variable defined in inventory",
# group variable all in inventory
"group vars, precedence entry 'all_inventory'": "group variable definined in inventory (all)",
# host_vars
"inventory host_vars for": "host_vars",
# group_vars
"group vars, precedence entry 'groups_plugins_inventory'": "group_vars",
# group_vars all
"group vars, precedence entry 'all_plugins_inventory'": "group_vars (all)",
}

for key, value in source_map.items():
if source.startswith(key):
return value

return source
4 changes: 4 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# for now only be used for black config
# maybe in the future we will use it instead of setup.py / setup.cfg
[tool.black]
line-length = 120
7 changes: 7 additions & 0 deletions requirements-dev.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
-e .

tox
black
pylint
flake8
pytest
54 changes: 54 additions & 0 deletions setup.cfg
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
[metadata]
name = ansible-variables
version = 0.3.0
description = Variables for Ansible
long_description = file: README.md
long_description_content_type = text/markdown
author = Christoph Hille
author_email = [email protected]
url = https://github.com/hille721/ansible-variables
project_urls =
Bug Tracker=https://github.com/hille721/ansible-variables/issues
Documentation=https://github.com/hille721/ansible-variables
license = GPLv3+
classifiers =
Development Status :: 2 - Pre-Alpha
Environment :: Console
Intended Audience :: Developers
Intended Audience :: Information Technology
Intended Audience :: System Administrators
License :: OSI Approved :: GNU General Public License v3 or later (GPLv3+)
Natural Language :: English
Operating System :: POSIX
Programming Language :: Python :: 3
Programming Language :: Python :: 3.8
Programming Language :: Python :: 3.9
Programming Language :: Python :: 3.10
Programming Language :: Python :: 3.11
Programming Language :: Python :: 3 :: Only
Topic :: System :: Installation/Setup
Topic :: System :: Systems Administration
Topic :: Utilities

[options]
zip_safe = False
python_requires = >=3.8
include_package_data = True
package_dir =
=lib
packages = find:
install_requires =
ansible-core
rich

[options.packages.find]
where = lib
exclude =
tests

[options.entry_points]
console_scripts =
ansible-variables = ansible_variables.cli.variables:main

[flake8]
max-line-length = 120
14 changes: 14 additions & 0 deletions setup.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import sys

from pkg_resources import VersionConflict, require
from setuptools import setup

try:
require("setuptools>=38.3")
except VersionConflict:
print("Error: version of setuptools is too old (<38.3)!")
sys.exit(1)


if __name__ == "__main__":
setup()
Loading

0 comments on commit 27fd22e

Please sign in to comment.