diff --git a/site/profiles/manifests/base.pp b/site/profiles/manifests/base.pp index 62b242e..607136b 100644 --- a/site/profiles/manifests/base.pp +++ b/site/profiles/manifests/base.pp @@ -35,6 +35,7 @@ class profiles::base ( include profiles::dns::base include profiles::cloudinit::init include profiles::metrics::default + include profiles::helpers::node_lookup # include the python class class { 'python': diff --git a/site/profiles/manifests/helpers/node_lookup.pp b/site/profiles/manifests/helpers/node_lookup.pp new file mode 100644 index 0000000..b155f6c --- /dev/null +++ b/site/profiles/manifests/helpers/node_lookup.pp @@ -0,0 +1,56 @@ +# profiles::helpers::node_lookup +# +# wrapper class for python, pip and venv +class profiles::helpers::node_lookup ( + String $script_name = 'node_lookup', + Stdlib::AbsolutePath $base_path = "/opt/${script_name}", + Stdlib::AbsolutePath $venv_path = "${base_path}/venv", + String $owner = 'root', + String $group = 'root', + Boolean $systempkgs = false, + String $version = 'system', + Array[String[1]] $packages = ['requests'], +){ + + # ensure the base_path exists + file { $base_path: + ensure => directory, + mode => '0755', + owner => $owner, + group => $group, + } + # create a venv + python::pyvenv { $venv_path : + ensure => present, + version => $version, + systempkgs => $systempkgs, + venv_dir => $venv_path, + owner => $owner, + group => $group, + require => File[$base_path], + } + + # install the required pip packages + $packages.each |String $package| { + python::pip { "${venv_path}_${package}": + ensure => present, + pkgname => $package, + virtualenv => $venv_path, + } + } + + # create the script from a template + file { "${base_path}/${script_name}": + ensure => file, + mode => '0755', + content => template("profiles/helpers/${script_name}.erb"), + require => Python::Pyvenv[$venv_path], + } + + # create symbolic link in $PATH + file { "/usr/local/bin/${script_name}": + ensure => 'link', + target => "${base_path}/${script_name}", + require => File["${base_path}/${script_name}"], + } +} diff --git a/site/profiles/templates/helpers/node_lookup.erb b/site/profiles/templates/helpers/node_lookup.erb new file mode 100644 index 0000000..7596821 --- /dev/null +++ b/site/profiles/templates/helpers/node_lookup.erb @@ -0,0 +1,61 @@ +#!/usr/bin/env <%= @venv_path %>/bin/python +import requests +import sys +import argparse +import json + +def build_query(node=None, fact_name=None, match=None, show_role=False): + query_filters = [] + + if node: + query_filters.append(["=", "certname", node]) + if fact_name: + query_filters.append(["=", "name", fact_name]) + elif show_role: + query_filters.append(["=", "name", "enc_role"]) + + if match: + query_filters.append(["~", "value", match]) + + if not query_filters: + return '["=", "name", "enc_role"]' + else: + return json.dumps(["and"] + query_filters) + +def query_puppetdb(query): + url = 'http://puppetdb:8080/pdb/query/v4/facts' + response = requests.get(url, params={'query': query}) + process_response(response) + +def process_response(response): + if response.status_code == 200: + for fact in response.json(): + print(f"{fact['certname']} {fact['value']}") + else: + print(f"Error querying PuppetDB: HTTP {response.status_code}") + print("Response content:", response.text) + +def parse_stdin(): + for line in sys.stdin: + yield line.split()[0] + +def main(): + parser = argparse.ArgumentParser(description="Query PuppetDB for nodes.") + parser.add_argument("-n", "--node", help="Node name or partial match") + parser.add_argument("-R", "--role", action="store_true", help="Show the role for matched hosts") + parser.add_argument("-F", "--fact", help="Specify a fact name") + parser.add_argument("-m", "--match", help="Simple pattern match for the value") + + args = parser.parse_args() + + if not args.node and not sys.stdin.isatty(): + for node in parse_stdin(): + args.node = node + query = build_query(node=args.node, fact_name=args.fact, match=args.match, show_role=args.role) + query_puppetdb(query) + else: + query = build_query(node=args.node, fact_name=args.fact, match=args.match, show_role=args.role) + query_puppetdb(query) + +if __name__ == "__main__": + main()