facter-3.14.12/0000755005276200011600000000000013702047635013025 5ustar jenkinsjenkinsfacter-3.14.12/CODEOWNERS0000644005276200011600000000003413702047406014411 0ustar jenkinsjenkins* @puppetlabs/night-s-watch facter-3.14.12/CONTRIBUTING.md0000644005276200011600000001305113702047406015252 0ustar jenkinsjenkins# How to contribute Third-party patches are essential for keeping facter great. We simply can't access the huge number of platforms and myriad configurations for running facter. We want to keep it as easy as possible to contribute changes that get things working in your environment. There are a few guidelines that we need contributors to follow so that we can have a chance of keeping on top of things. ## Getting Started * Make sure you have a [Jira account](https://tickets.puppetlabs.com). * Make sure you have a [GitHub account](https://github.com/signup/free). * Submit a Jira ticket for your issue if one does not already exist. * Clearly describe the issue including steps to reproduce when it is a bug. * Make sure you fill in the earliest version that you know has the issue. * A ticket is not necessary for [trivial changes](https://puppet.com/community/trivial-patch-exemption-policy) * Fork the repository on GitHub. ## New Facts All new facts should also be included in `lib/schema/facter.yaml`. Without this facts won't pass acceptance tests. ## Making Changes * Create a topic branch from where you want to base your work. * This is usually the master branch. * Only target release branches if you are certain your fix must be on that branch. * If you use facter as part of the [puppet-agent](https://github.com/puppetlabs/puppet-agent), double-check the base branch to make sure your fix gets in the correct stream. | facter | puppet-agent | |--------|--------------| | 3.11.x | 5.5.x | | 3.12.x | 6.0.x | | 3.13.x | 6.4.x | | master | master | For example, if you use puppet5 you will want to base your work on top of the `3.11.x` branch, so your fix would end up in a subsequent release of puppet-agent `5.5.x`. Once merged, your work will be automatically promoted to the other release streams when our internal CI passes. * To quickly create a topic branch based on master, run `git checkout -b fix/master/my_contribution master`. Please avoid working directly on the `master` branch. * Make commits of logical units. * Check for unnecessary whitespace with `git diff --check` before committing. * If you have python 2 in your path you can run `make cpplint` to ensure your code formatting is clean. The linter runs as part of Travis CI and could fail the CI build. * If you have cppcheck in your path you can run `make cppcheck` to ensure your code passes static analysis. cppcheck runs as part of Travis CI and could fail the CI build. * Make sure your commit messages are in the proper format. If the commit addresses an issue filed in the [Facter Jira project](https://tickets.puppetlabs.com/browse/FACT), start the first line of the commit with the issue number in parentheses. ```` (FACT-1234) Make the example in CONTRIBUTING imperative and concrete Without this patch applied the example commit message in the CONTRIBUTING document is not a concrete example. This is a problem because the contributor is left to imagine what the commit message should look like based on a description rather than an example. This patch fixes the problem by making the example concrete and imperative. The first line is a real life imperative statement with a ticket number from our issue tracker. The body describes the behavior without the patch, why this is a problem, and how the patch fixes the problem when applied. ```` * Make sure you have added the necessary tests for your changes. * Run _all_ the tests to assure nothing else was accidentally broken. ## Making Trivial Changes For [changes of a trivial nature](https://puppet.com/community/trivial-patch-exemption-policy), it is not always necessary to create a new ticket in Jira. In this case, it is appropriate to start the first line of a commit with one of `(docs)`, `(maint)`, or `(packaging)` instead of a ticket number. If a Jira ticket exists for the documentation commit, you can include it after the `(docs)` token. ``` (docs)(DOCUMENT-000) Add docs commit example to CONTRIBUTING There is no example for contributing a documentation commit to the Facter repository. This is a problem because the contributor is left to assume how a commit of this nature may appear. The first line is a real-life imperative statement with '(docs)' in place of what would have been the FACT project ticket number in a non-documentation related commit. The body describes the nature of the new documentation or comments added. ``` For commits that address trivial repository maintenance tasks or packaging issues, start the first line of the commit with `(maint)` or `(packaging)`, respectively. ## Submitting Changes * Sign the [Contributor License Agreement](http://links.puppet.com/cla). * Push your changes to a topic branch in your fork of the repository. * Submit a pull request to the repository in the puppetlabs organization. * Update your ticket to mark that you have submitted code and are ready for it to be reviewed. * Include a link to the pull request in the ticket # Additional Resources * [Puppet community guidelines](https://docs.puppet.com/community/community_guidelines.html) * [Bug tracker (Jira)](https://tickets.puppetlabs.com/browse/FACT) * [Contributor License Agreement](http://links.puppet.com/cla) * [General GitHub documentation](http://help.github.com/) * [GitHub pull request documentation](http://help.github.com/send-pull-requests/) * #puppet-dev IRC channel on freenode.org * [puppet-dev mailing list](https://groups.google.com/forum/#!forum/puppet-dev) facter-3.14.12/Extensibility.md0000644005276200011600000001171613702047406016205 0ustar jenkinsjenkinsExtensibility ============= Native Facter has the following extensibility goals: * Clear guidelines for what facts are supported in-project * Compatibility with 90+% of existing Facter custom facts * Compatibility with 100% of existing Facter external facts * New features for external facts, including depends/requires logic The following sections discuss those goals in more depth. Note that this doc is work-in-progress and should be updated as extensibility features are implemented, refined or ruled out. Built-in facts -------------- These are the criteria for Native Facter pull requests: * Additional resolutions for existing built-in facts (e.g. the operatingsystem facts for new Linux Distros) must conform to the facter.json schema. * New facts must be accompanied by support in the facter.json schema. * For [SemVer](http://semver.org) purposes, a change in fact value is only considered breaking if a) the fact is documented in the schema, and b) the fact is applicable on a platform we test against in [Puppet CI](http://jenkins.puppetlabs.com). Custom Facts Compatibility -------------------------- Ruby Facter supports "custom facts" that are facts implemented using the public Facter API. Native Facter implements a Ruby compatibility layer to support simple and aggregate fact resolutions. Native Facter searches for a MRI Ruby library to load and initializes a Ruby VM as needed to resolve custom facts. The environment variable `LEATHERMAN_RUBY` can be used to explicitly instruct native Facter to use a particular Ruby library (e.g. `LEATHERMAN_RUBY=/usr/local/lib/libruby.so.1.9.3`). If not set, native Facter will search for and load the highest version Ruby library on the system. **Ruby 1.8.x is not supported by native Facter. Please use Ruby 1.9.3 or later.** Native Facter will load custom facts from the following locations: * Any Ruby source file in a `facter` subdirectory on the Ruby load path. * Any Ruby source file in a directory specified by the `FACTERLIB` environment variable (delimited by the platform PATH separator). * Any Ruby source file in a directory specified by the `--custom-dir` option to facter. The following methods from the Facter API are currently supported by native Facter: From the `Facter` module: * [] * add * clear * debug * debugonce * define_fact * each * fact * flush * list * loadfacts * log_exception * reset * search * search_path * search_external * search_external_path * to_hash * value * version * warn * warnonce From the `Facter::Core::Execution` module: * which * exec * execute * ExecutionFailure From the `Facter::Util::Fact` class: * define_resolution * flush * name * resolution * value From the `Facter::Util::Resolution` module: * confine * exec * has_weight * name * on_flush * setcode * which From the `Facter::Core::Aggregate` module: * aggregate * chunk * confine * has_weight * name * on_flush Please note: the timeout option is not currently supported on resolutions. Setting a timeout will result in a warning and the timeout will be ignored. Please see the [Facter Custom Facts Walkthrough](https://docs.puppetlabs.com/facter/2.2/custom_facts.html) for more information on using the Facter API. External Facts Compatiblity --------------------------- Native Facter will support all 4 forms of "external facts" which Ruby Facter supports: * JSON files with the .json extension whose key-value pairs will be mapped to fact-value pairs. * YAML files with the .yaml extension whose key-value pairs will be mapped to fact-value pairs. * Text files with the .txt extension containing `fact=some_value` strings * Executable files returning `fact=some_value` strings New Features for External Facts ------------------------------- Caveat: It is TBD which of these features will be implemented in what releases. * Executable external facts can take a json object on stdin describing all known facts. This will allow logic like the confine/value methods provide in the custom facts API. * To support the use case of facts which depend on other facts: executable external facts can describe what facts they depend on and what facts they provide, via a json schema. (This schema could either be a parallel file distributed with the external fact following some naming convention (e.g. foo.schema for an external fact called foo.sh or foo.py), or the schema could be provided on stdout when executing the external fact with some parameter (e.g. foo.sh --show-schema).) * Native Facter might add a weight indicator for returned facts, to support fact precedence for external facts, along the lines of the `has_weight` functionality. * Native Facter might add a volatility indicator, such as a ttl field, to the json schema provided by external facts. This would allow facter in a long-running process to avoid unnecessary refreshes of non-volatile facts. * Native Facter might include some language-specific shims for its external facts support, most likely for Ruby and Python, to ease writing new external facts (including ports of legacy custom facts). facter-3.14.12/Gemfile0000644005276200011600000000075113702047406014317 0ustar jenkinsjenkinssource ENV['GEM_SOURCE'] || 'https://artifactory.delivery.puppetlabs.net/artifactory/api/gems/rubygems/' def location_for(place, fake_version = nil) if place =~ /^(git[:@][^#]*)#(.*)/ [fake_version, { :git => $1, :branch => $2, :require => false }].compact elsif place =~ /^file:\/\/(.*)/ ['>= 0', { :path => File.expand_path($1), :require => false }] else [place, { :require => false }] end end gem 'packaging', *location_for(ENV['PACKAGING_LOCATION'] || '~> 0.99') facter-3.14.12/LICENSE0000644005276200011600000000126613702047406014033 0ustar jenkinsjenkins facter - Tool for collecting system facts. Copyright (C) 2014 Puppet Labs Inc Puppet Labs can be contacted at: info@puppetlabs.com Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. facter-3.14.12/README.md0000644005276200011600000002230313702047406014300 0ustar jenkinsjenkinsFacter 4 ============ Facter 4 is the newest version of Facter that is written in Ruby and compatible with Facter 3. Currenly Facter 4 is maintained on [4.x branch]( https://github.com/puppetlabs/facter/tree/4.x) Native Facter ============= An implementation of facter functionality in C++11, providing: * a shared library which gather facts about the system * an executable for standalone command line usage * a ruby file to enable `require 'facter'`. Please see our [extensibility document](Extensibility.md) to learn more about extending native facter using custom and external facts. Build Requirements ------------------ * GCC 4.8+ or Clang 5.0+ (OSX) * CMake >= 3.2.2 * Boost C++ Libraries >= 1.54 * yaml-cpp >= 0.5.1 * [leatherman](https://github.com/puppetlabs/leatherman) >= 1.4.3 * [cpp-hocon](https://github.com/puppetlabs/cpp-hocon) >= 0.1.0 Optional Build Libraries ------------------------ * OpenSSL - enables SSH fingerprinting facts. * libblkid (Linux only) - enables the partitions fact. * libcurl >= 7.18.0 - enables facts that perform HTTP requests. Initial Setup ------------- Note: Testing custom facts requires Ruby 1.9+ with libruby built as a dynamic library; that often implies development builds of Ruby. ### Setup on Fedora 23 The following will install all required tools and libraries: dnf install boost-devel openssl-devel yaml-cpp-devel libblkid-devel libcurl-devel gcc-c++ make wget tar cmake ### Setup on Mac OSX El Capitan (homebrew) This assumes Clang is installed and the system OpenSSL libraries will be used. The following will install all required libraries: brew install cmake boost yaml-cpp ### Setup on Ubuntu 15.10 (Trusty) The following will install most required tools and libraries: apt-get install build-essential libboost-all-dev libssl-dev libyaml-cpp-dev libblkid-dev libcurl4-openssl-dev wget tar cmake ### Setup on FreeBSD 10 The following will install most required tools and libraries: pkg install git ruby21 cmake boost-all yaml-cpp gcc49 ### Setup on Windows [MinGW-w64](http://mingw-w64.sourceforge.net/) is used for full C++11 support, and [Chocolatey](https://chocolatey.org) can be used to install. You should have at least 2GB of memory for compilation. * install [CMake](https://chocolatey.org/packages/cmake) * install [MinGW-w64](https://chocolatey.org/packages/mingw) choco install mingw --params "/threads:win32" For the remaining tasks, build commands can be executed in the shell from Start > MinGW-w64 project > Run Terminal * select an install location for dependencies, such as C:\\tools or cmake\\release\\ext; we'll refer to it as $install * build [Boost](http://sourceforge.net/projects/boost/files/latest/download) .\bootstrap mingw .\b2 toolset=gcc --build-type=minimal install --prefix=$install --with-program_options --with-system --with-filesystem --with-date_time --with-thread --with-regex --with-log --with-locale --with-chrono boost.locale.iconv=off * build [yaml-cpp](https://github.com/jbeder/yaml-cpp) cmake -G "MinGW Makefiles" -DCMAKE_PREFIX_PATH=$install -DCMAKE_INSTALL_PREFIX=$install . mingw32-make install * build [libcurl](http://curl.haxx.se/download) mingw32-make mingw32 cp -r include\curl $install\include cp -r lib\libcurl.a $install\lib In Powershell: choco install cmake 7zip.commandline -y $env:PATH = "C:\Program Files\CMake\bin;$env:PATH" choco install mingw --params "/threads:win32" -y $env:PATH = "C:\tools\mingw64\bin;$env:PATH" $install = "C:\tools" (New-Object Net.WebClient).DownloadFile("https://downloads.sourceforge.net/boost/boost_1_54_0.7z", "$pwd/boost_1_54_0.7z") 7za x boost_1_54_0.7z pushd boost_1_54_0 .\bootstrap mingw .\b2 toolset=gcc --build-type=minimal install --prefix=$install --with-program_options --with-system --with-filesystem --with-date_time --with-thread --with-regex --with-log --with-locale --with-chrono boost.locale.iconv=off popd (New-Object Net.WebClient).DownloadFile("https://github.com/jbeder/yaml-cpp/archive/yaml-cpp-0.5.3.tar.gz", "$pwd/yaml-cpp-0.5.3.tar.gz") 7za x yaml-cpp-0.5.3.tar.gz 7za x yaml-cpp-0.5.3.tar pushd yaml-cpp-yaml-cpp-0.5.3 cmake -G "MinGW Makefiles" -DCMAKE_PREFIX_PATH="$install" -DCMAKE_INSTALL_PREFIX="$install" . mingw32-make install popd (New-Object Net.WebClient).DownloadFile("http://curl.haxx.se/download/curl-7.42.1.zip", "$pwd/curl-7.42.1.zip") 7za x curl-7.42.1.zip pushd curl-7.42.1 mingw32-make mingw32 cp -r include\curl $install\include cp -r lib\libcurl.a $install\lib popd Note that OpenSSL isn't needed on Windows. ### Setup on OpenBSD 6.0 The following will install all required tools and libraries: pkg_add boost cmake curl g++ ruby yaml-cpp Optionally `leatherman` can be installed from packages too if not built locally. ### Build and install Leatherman and cpp-hocon [Leatherman](https://github.com/puppetlabs/leatherman) and [cpp-hocon](https://github.com/puppetlabs/cpp-hocon) are built similar to the Pre-Build instructions below. If building on Windows, install to the same `$install` location used for other dependencies. Pre-Build --------- All of the following examples start by assuming the current directory is the root of the repo. On Windows, add `-G "MinGW Makefiles" -DCMAKE_PREFIX_PATH=\ -DBOOST_STATIC=ON` to the `cmake` invocation. Before building facter, use `cmake` to generate build files: $ mkdir release $ cd release $ cmake .. To generate build files with debug information: $ mkdir debug $ cd debug $ cmake -DCMAKE_BUILD_TYPE=Debug .. Build ----- To build facter, use 'make': $ cd release $ make To build facter with debug information: $ cd debug $ make Run --- You can run facter from where it was built: `$ release/bin/facter` For a debug build: `$ debug/bin/facter` Test ---- If a ruby was found during configuration, execute the following command before running tests: $ bundle install --gemfile lib/Gemfile You can run facter tests using the test target: $ cd release $ make test For a debug build: $ cd debug $ make test For verbose test output, run `ctest` instead of using the test target: $ cd release $ ctest -V Install ------- You can install facter into your system: $ cd release $ make && sudo make install By default, facter will install files into `/usr/local/bin`, `/usr/local/lib`, and `/usr/local/include`. If the project is configured with Ruby in the PATH, *facter.rb* will be installed to that Ruby's vendor dir. The install location for *facter.rb* can be overridden using by setting RUBY_LIB_INSTALL. To install to a different location, set the install prefix: $ cd release $ cmake -DCMAKE_INSTALL_PREFIX=~ .. $ make clean install This would install facter into `~/bin`, `~/lib`, and `~/include`. Ruby Usage ---------- Using the Ruby API requires that facter.rb is installed into the Ruby load path, as done in the previous install steps. ```ruby require 'facter' # Use the Facter API... puts "kernel: #{Facter.value(:kernel)}" ``` Configuration ------------- Facter can be configured via a HOCON config file of the following format: ``` global : { external-dir : [ "path1", "path2" ], custom-dir : [ "custom/path" ], no-exernal-facts : false, no-custom-facts : false, no-ruby : false } cli : { debug : false, trace : true, verbose : false, log-level : "warn" } facts : { blocklist : [ "file system", "EC2" ] ttls : [ { "timezone" : 30 days }, ] } ``` All options are respected when running Facter standalone, while calling Facter from Ruby will only load `external-dir`, `custom-dir`, and the fact-specific configuration. The file will be loaded by default from `/etc/puppetlabs/facter/facter.conf` on Unix and `C:\ProgramData\PuppetLabs\facter\etc\facter.conf` on Windows. A different location can be specified using the `--config` command line option. Elements in the blocklist are fact groupings which will not be resolved when Facter runs. Use the `--list-block-group` command line option to see valid blockable groups. Elements in the ttls section are key-value pairs of fact groupings that will be cached with the duration for which to cache them. Cached facts are stored as JSON in `/opt/puppetlabs/facter/cache/cached_facts` on Unix and `C:\ProgramData\PuppetLabs\facter\cache\cached_facts` on Windows. Use the `--list-cache-groups` command line option to see valid cacheable groups. Uninstall --------- Run the following command to remove files that were previously installed: $ sudo xargs rm < release/install_manifest.txt Documentation ------------- To generate API documentation, install doxygen 1.8.7 or later. $ cd lib $ doxygen To view the documentation, open `lib/html/index.html` in a web browser. Debugging --------- If when running the tests you encounter this error message: "could not locate a ruby library" You may need to use a different shared ruby library in Leatherman. To do this, run this command, where the location below is the default for a puppet agent installation: $ export LEATHERMAN_RUBY=/opt/puppetlabs/puppet/lib/libruby.dylib facter-3.14.12/Rakefile0000644005276200011600000000065613702047406014475 0ustar jenkinsjenkinsRAKE_ROOT = File.expand_path(File.dirname(__FILE__)) $LOAD_PATH << File.join(RAKE_ROOT, 'tasks') require 'rake' Dir['tasks/**/*.rake'].each { |t| load t } require 'packaging' Pkg::Util::RakeUtils.load_packaging_tasks namespace :package do task :bootstrap do puts 'Bootstrap is no longer needed, using packaging-as-a-gem' end task :implode do puts 'Implode is no longer needed, using packaging-as-a-gem' end end facter-3.14.12/CMakeLists.txt0000644005276200011600000002113713702047406015565 0ustar jenkinsjenkinscmake_minimum_required(VERSION 3.2.2) project(FACTER VERSION 3.14.12) # Set this early, so it's available. AIX gets weird, man. if("${CMAKE_SYSTEM_NAME}" MATCHES "AIX") set(AIX TRUE) endif() if (NOT CMAKE_BUILD_TYPE) message(STATUS "Defaulting to a release build.") set(CMAKE_BUILD_TYPE "Release" CACHE STRING "Choose the type of build, options are: None Debug Release RelWithDebInfo MinSizeRel." FORCE) endif() include(CheckIncludeFile) CHECK_INCLUDE_FILE(utmpx.h HAVE_UTMPX_H -DHAVE_UTMPX_H) option(YAMLCPP_STATIC "Use yaml-cpp's static libraries" OFF) option(BUILD_SHARED_LIBS "Build libfacter as a shared library" ON) set(FACTER_PATH "" CACHE PATH "Specify the location to look for specific binaries before trying PATH.") if (FACTER_PATH) # Specify a preferred location for binary lookup that will be prioritized over PATH. file(TO_CMAKE_PATH ${FACTER_PATH} FACTER_PATH_FIXED) add_definitions(-DFACTER_PATH="${FACTER_PATH_FIXED}") message(STATUS "Prioritizing binary lookup in ${FACTER_PATH_FIXED}") endif() set(FACTER_RUBY "" CACHE FILEPATH "Specify the location of libruby at compile-time, bypassing dynamic lookup.") if (FACTER_RUBY) file(TO_CMAKE_PATH ${FACTER_RUBY} FACTER_RUBY_PATH) add_definitions(-DFACTER_RUBY="${FACTER_RUBY_PATH}") message(STATUS "Fixing lookup for libruby to ${FACTER_RUBY_PATH}") endif() set(AIO_AGENT_VERSION "" CACHE STRING "Creates an aio_agent_version fact with the specified value.") if (AIO_AGENT_VERSION) add_definitions(-DAIO_AGENT_VERSION="${AIO_AGENT_VERSION}") message(STATUS "Adding fact aio_agent_version=${AIO_AGENT_VERSION}") endif() enable_testing() list(APPEND CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake") if ("${CMAKE_SYSTEM_NAME}" MATCHES "Darwin") # Allow searching in boxen installed homebrew directories # http://stackoverflow.com/questions/1487752/how-do-i-instruct-cmake-to-look-for-libraries-installed-by-macports set(CMAKE_LIBRARY_PATH ${CMAKE_LIBRARY_PATH} /opt/boxen/homebrew/lib) set(CMAKE_INCLUDE_PATH ${CMAKE_INCLUDE_PATH} /opt/boxen/homebrew/include) endif() include(FeatureSummary) SET(LEATHERMAN_COMPONENTS locale catch nowide logging util file_util dynamic_library execution ruby rapidjson) # We look for curl early, because whether or not we link to the leatherman curl library # is dependant on whether or not we find curl on the system. if ((("${CMAKE_SYSTEM_NAME}" MATCHES "FreeBSD|Linux|OpenBSD") OR WIN32) AND NOT WITHOUT_CURL) find_package(CURL) if (CURL_FOUND) add_definitions(-DUSE_CURL) list(APPEND LEATHERMAN_COMPONENTS curl) endif() set_package_properties(CURL PROPERTIES DESCRIPTION "A free and easy-to-use client-side URL transfer library" URL "http://curl.haxx.se/libcurl/") set_package_properties(CURL PROPERTIES TYPE OPTIONAL PURPOSE "Enables facts that require HTTP.") endif() if (WIN32) list(APPEND LEATHERMAN_COMPONENTS windows) endif() find_package(Leatherman REQUIRED COMPONENTS ${LEATHERMAN_COMPONENTS}) # Now that we have leatherman, we can pulll in its options file, which # we need for finding all our other libraries. include(options) if (LEATHERMAN_USE_LOCALES) add_definitions(-DLEATHERMAN_I18N) SET(BOOST_COMPONENTS locale) endif() # We use program_options, system, filesystem, date_time, and regex directly. Testing uses thread and chrono. list(APPEND BOOST_COMPONENTS program_options system filesystem date_time regex thread chrono) find_package(Boost 1.54 REQUIRED COMPONENTS ${BOOST_COMPONENTS}) # date_time and regex need threads on some platforms, and find_package Boost only includes # pthreads if you require the Boost.Thread component. find_package(Threads) find_package(Ruby 1.9) find_package(YAMLCPP REQUIRED) if (NOT WITHOUT_OPENSSL) find_package(OPENSSL) endif() if ("${CMAKE_SYSTEM_NAME}" MATCHES "Linux" AND NOT WITHOUT_BLKID) find_package(BLKID) endif() find_package(CPPHOCON REQUIRED) if ("${CMAKE_SYSTEM_NAME}" MATCHES "Linux") find_package(UDEV) endif() find_package(WHEREAMI) if (WHEREAMI_FOUND) add_definitions(-DUSE_WHEREAMI) endif() if (NOT WITHOUT_JRUBY AND NOT WIN32) find_package(JNI) set_package_properties(JNI PROPERTIES DESCRIPTION "Java Native Interface (JNI) is a programming framework that enables Java code running in a Java Virtual Machine (JVM) to call and be called by native applications.") set_package_properties(JNI PROPERTIES TYPE OPTIONAL PURPOSE "Enables JRuby support in Facter.") if (JNI_FOUND) find_package(Java) set_package_properties(Java PROPERTIES DESCRIPTION "Java compiler for JNI.") set_package_properties(Java PROPERTIES TYPE OPTIONAL PURPOSE "Enables JRuby support in Facter.") if (Java_JAVAC_EXECUTABLE) set(JRUBY_SUPPORT TRUE) set(CMAKE_JAVA_COMPILE_FLAGS -source 1.6 -target 1.6) add_definitions(-DUSE_JRUBY_SUPPORT) endif() endif() endif() # Display a summary of the features include(FeatureSummary) feature_summary(WHAT ALL) # Set RPATH if not installing to a system library directory list(FIND CMAKE_PLATFORM_IMPLICIT_LINK_DIRECTORIES "${CMAKE_INSTALL_PREFIX}/lib" INSTALL_IS_SYSTEM_DIR) if ("${INSTALL_IS_SYSTEM_DIR}" STREQUAL "-1") set(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/lib") endif() # Pull in common cflags setting from leatherman include(cflags) set(FACTER_CXX_FLAGS "${LEATHERMAN_CXX_FLAGS}") add_definitions(${LEATHERMAN_DEFINITIONS}) option(DYNAMICBASE "Add dynamicbase linker option" ON) # Enable DEP/ASLR switches on windows versions if (WIN32) set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--nxcompat") if (DYNAMICBASE) set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--dynamicbase") endif() endif() # # Add cpplint and cppcheck targets # file(GLOB_RECURSE ALL_SOURCES lib/src/*.cc lib/inc/*.hpp lib/inc/*.h exe/*.cc exe/*.hpp exe/*.h) add_cpplint_files(${ALL_SOURCES}) enable_cpplint() add_cppcheck_dirs("${PROJECT_SOURCE_DIR}/lib" "${PROJECT_SOURCE_DIR}/exe") enable_cppcheck() # Pull in helper macros for working with leatherman libraries include(leatherman) set(CMAKE_REQUIRED_FLAGS "-std=c++11") set(CMAKE_REQUIRED_LIBRARIES ${LEATHERMAN_LIBRARIES}) set(CMAKE_REQUIRED_INCLUDES ${LEATHERMAN_INCLUDE_DIRS}) # Guards to make sure we don't compile what we don't have in Leatherman CHECK_CXX_SOURCE_COMPILES(" #include int main() { int a = leatherman::util::environment::get_int(\"A\", 1000); return 0; } " HAS_LTH_GET_INT) if (HAS_LTH_GET_INT) add_definitions(-DHAS_LTH_GET_INT) endif() CHECK_CXX_SOURCE_COMPILES(" #include \"leatherman/execution/execution.hpp\" using namespace leatherman::execution; using namespace std; int main() { vector paths; expand_command(\"command\", paths, false); return 0; } " HAS_LTH_EXPAND) if (HAS_LTH_EXPAND) add_definitions(-DHAS_LTH_EXPAND) endif() if (WIN32) CHECK_CXX_SOURCE_COMPILES(" #include \"leatherman/windows/registry.hpp\" using namespace leatherman::windows; int main() { int test = 0; try { test = registry::get_registry_dword(registry::HKEY::LOCAL_MACHINE, \"RandomSubkey\", \"RandomValue\"); } catch (registry_exception &e) { return test; } } " HAS_LTH_GET_DWORD) if (HAS_LTH_GET_DWORD) add_definitions(-DHAS_LTH_GET_DWORD) endif() endif() add_subdirectory(lib) add_subdirectory(exe) add_subdirectory(locales) # Add test executables for unit testing add_test(NAME "libfacter\\ tests" COMMAND libfacter_test) if (RUBY_FOUND) find_program(BUNDLER_PATH NAMES bundle.bat bundle) if (BUNDLER_PATH) message(STATUS "Bundler found, installing dependencies for Ruby tests...") execute_process(COMMAND ${BUNDLER_PATH} install --retry 2 --path=vendor/bundle WORKING_DIRECTORY "${PROJECT_SOURCE_DIR}/lib") add_test(NAME "libfacter\\ specs" COMMAND ${BUNDLER_PATH} exec rspec WORKING_DIRECTORY "${PROJECT_SOURCE_DIR}/lib") endif() endif() add_test(NAME "facter\\ smoke" COMMAND facter) # Install the man page if ("${CMAKE_SYSTEM_NAME}" MATCHES "OpenBSD|FreeBSD") set(MANDIR man/man8/) else() set(MANDIR share/man/man8/) endif() option(INSTALL_BATCH_FILES "Generate .bat files during installation" ON) install(FILES ${PROJECT_SOURCE_DIR}/man/man8/facter.8 DESTINATION ${MANDIR}) if (WIN32 AND INSTALL_BATCH_FILES) install(FILES ${PROJECT_SOURCE_DIR}/ext/windows/facter.bat DESTINATION ${CMAKE_INSTALL_PREFIX}/bin) install(FILES ${PROJECT_SOURCE_DIR}/ext/windows/facter_interactive.bat DESTINATION ${CMAKE_INSTALL_PREFIX}/bin) install(FILES ${PROJECT_SOURCE_DIR}/ext/windows/run_facter_interactive.bat DESTINATION ${CMAKE_INSTALL_PREFIX}/bin) endif() facter-3.14.12/Gemfile.lock0000644005276200011600000000061413702047634015247 0ustar jenkinsjenkinsGEM remote: https://artifactory.delivery.puppetlabs.net/artifactory/api/gems/rubygems/ specs: artifactory (2.8.2) csv (3.1.5) docopt (0.6.1) packaging (0.99.66) artifactory (~> 2) rake (>= 12.3) release-metrics rake (13.0.1) release-metrics (1.1.0) csv docopt PLATFORMS ruby DEPENDENCIES packaging (~> 0.99) BUNDLED WITH 1.17.3 facter-3.14.12/exe/0000755005276200011600000000000013702047635013606 5ustar jenkinsjenkinsfacter-3.14.12/exe/CMakeLists.txt0000644005276200011600000000156613702047406016352 0ustar jenkinsjenkinscmake_minimum_required(VERSION 3.2.2) set(FACTER_SOURCES facter.cc ) # Set compiler-specific flags set(CMAKE_CXX_FLAGS ${FACTER_CXX_FLAGS}) leatherman_logging_namespace("puppetlabs.facter") include_directories( ../lib/inc # the libfacter headers ${Boost_INCLUDE_DIRS} ${YAMLCPP_INCLUDE_DIRS} ${LEATHERMAN_RUBY_INCLUDE} ${LEATHERMAN_FILE_UTIL_INCLUDE} ${LEATHERMAN_UTIL_INCLUDE} ${LEATHERMAN_NOWIDE_INCLUDE} ${CPPHOCON_INCLUDE_DIRS} ) link_directories( ${CPPHOCON_LIBRARY_DIRS} ) add_executable(facter ${FACTER_SOURCES}) if (${CMAKE_SYSTEM_NAME} MATCHES "Linux") target_link_libraries(facter rt) endif() target_link_libraries(facter libfacter ${CPPHOCON_LIBRARIES} ${LEATHERMAN_LIBRARIES} ${Boost_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} # fix until Leatherman switches to private dependencies ) leatherman_install(facter) facter-3.14.12/exe/facter.cc0000644005276200011600000003663113702047406015366 0ustar jenkinsjenkins#include #include #include #include #include #include #include #include #include // Note the caveats in nowide::cout/cerr; they're not synchronized with stdio. // Thus they can't be relied on to flush before program exit. // Use endl/ends or flush to force synchronization when necessary. #include #include // boost includes are not always warning-clean. Disable warnings that // cause problems before including the headers, then re-enable the warnings. #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wattributes" #include #pragma GCC diagnostic pop #include #include #include #include using namespace std; using namespace hocon; using namespace facter::facts; using namespace facter::logging; using namespace facter::util::config; using leatherman::util::environment; namespace po = boost::program_options; // Mark string for translation (alias for facter::logging::format) using facter::logging::_; void help(po::options_description& desc) { boost::nowide::cout << _("Synopsis\n" "========\n" "\n" "Collect and display facts about the system.\n" "\n" "Usage\n" "=====\n" "\n" " facter [options] [query] [query] [...]\n" "\n" "Options\n" "=======\n\n" "%1%\nDescription\n" "===========\n" "\n" "Collect and display facts about the current system. The library behind\n" "facter is easy to extend, making facter an easy way to collect information\n" "about a system.\n" "\n" "If no queries are given, then all facts will be returned.\n" "\n" "Example Queries\n" "===============\n\n" " facter kernel\n" " facter networking.ip\n" " facter processors.models.0" "\n" "\n" "Config File\n" "===========\n" "\n" "Contains settings for configuring external and custom fact directories,\n" "setting command line options, and blocking and caching facts.\n" "Loaded by default from %2%.\n" "See man page, README, or docs for more details.", desc, default_config_location()) << endl; } void log_command_line(int argc, char** argv) { if (!is_enabled(level::info)) { return; } ostringstream command_line; for (int i = 1; i < argc; ++i) { if (command_line.tellp() != static_cast(0)) { command_line << ' '; } command_line << argv[i]; } log(level::info, "executed with command line: %1%.", command_line.str()); } void log_queries(set const& queries) { if (!is_enabled(level::info)) { return; } if (queries.empty()) { log(level::info, "resolving all facts."); return; } ostringstream output; for (auto const& query : queries) { if (query.empty()) { continue; } if (output.tellp() != static_cast(0)) { output << ' '; } output << query; } log(level::info, "requested queries: %1%.", output.str()); } void print_fact_groups(map> const& fact_groups) { for (auto& group : fact_groups) { boost::nowide::cout << group.first << endl; for (auto& fact : group.second) { boost::nowide::cout << " - " << fact << endl; } } } int main(int argc, char **argv) { try { // Fix args on Windows to be UTF-8 boost::nowide::args arg_utf8(argc, argv); // Setup logging setup_logging(boost::nowide::cerr); vector external_directories; vector custom_directories; unordered_map ttls; // Build a list of options visible on the command line // Keep this list sorted alphabetically // Many of these options also can be specified in the config file, // see facter::util::config. Because of differences between the way // options are specified in the config file and on the command line, // these options need to be specified separately (e.g. on the command // line, flag presence indicates `true`, while in the config file, the // boolean must be specified explicitly). po::options_description visible_options(""); visible_options.add_options() ("color", _("Enable color output.").c_str()) ("config,c", po::value(), _("The location of the config file.").c_str()) ("custom-dir", po::value>(), _("A directory to use for custom facts.").c_str()) ("debug,d", po::bool_switch()->default_value(false), _("Enable debug output.").c_str()) ("external-dir", po::value>(), _("A directory to use for external facts.").c_str()) ("help,h", _("Print this help message.").c_str()) ("json,j", _("Output in JSON format.").c_str()) ("list-block-groups", _("List the names of all blockable fact groups.").c_str()) ("list-cache-groups", _("List the names of all cacheable fact groups.").c_str()) ("log-level,l", po::value()->default_value(level::warning, "warn"), _("Set logging level.\nSupported levels are: none, trace, debug, info, warn, error, and fatal.").c_str()) ("no-block", _("Disable fact blocking.").c_str()) ("no-cache", _("Disable loading and refreshing facts from the cache").c_str()) ("no-color", _("Disable color output.").c_str()) ("no-custom-facts", po::bool_switch()->default_value(false), _("Disable custom facts.").c_str()) ("no-external-facts", po::bool_switch()->default_value(false), _("Disable external facts.").c_str()) ("no-ruby", po::bool_switch()->default_value(false), _("Disable loading Ruby, facts requiring Ruby, and custom facts.").c_str()) ("puppet,p", _("Load the Puppet libraries, thus allowing Facter to load Puppet-specific facts.").c_str()) ("show-legacy", _("Show legacy facts when querying all facts.").c_str()) ("trace", po::bool_switch()->default_value(false), _("Enable backtraces for custom facts.").c_str()) ("verbose", po::bool_switch()->default_value(false), _("Enable verbose (info) output.").c_str()) ("version,v", _("Print the version and exit.").c_str()) ("yaml,y", _("Output in YAML format.").c_str()) ("strict", _("Enable more aggressive error reporting.").c_str()); // Build a list of "hidden" options that are not visible on the command line po::options_description hidden_options(""); hidden_options.add_options() ("query", po::value>()); // Create the supported command line options (visible + hidden) po::options_description command_line_options; command_line_options.add(visible_options).add(hidden_options); // Build a list of positional options (in our case, just queries) po::positional_options_description positional_options; positional_options.add("query", -1); po::variables_map vm; try { po::store(po::command_line_parser(argc, argv). options(command_line_options).positional(positional_options).run(), vm); // Check for non-default config file location hocon::shared_config hocon_conf; if (vm.count("config")) { string conf_dir = vm["config"].as(); hocon_conf = load_config_from(conf_dir); } else { hocon_conf = load_default_config_file(); } if (hocon_conf) { load_global_settings(hocon_conf, vm); load_cli_settings(hocon_conf, vm); load_fact_settings(hocon_conf, vm); load_fact_groups_settings(hocon_conf, vm); ttls = load_ttls(hocon_conf); } // Check for a help option first before notifying if (vm.count("help")) { help(visible_options); return EXIT_SUCCESS; } po::notify(vm); // Check for conflicting options if (vm.count("color") && vm.count("no-color")) { throw po::error(_("color and no-color options conflict: please specify only one.")); } if (vm.count("json") && vm.count("yaml")) { throw po::error(_("json and yaml options conflict: please specify only one.")); } if (vm["no-external-facts"].as() && vm.count("external-dir")) { throw po::error(_("no-external-facts and external-dir options conflict: please specify only one.")); } if (vm["no-custom-facts"].as() && vm.count("custom-dir")) { throw po::error(_("no-custom-facts and custom-dir options conflict: please specify only one.")); } if ((vm["debug"].as() + vm["verbose"].as() + (vm["log-level"].defaulted() ? 0 : 1)) > 1) { throw po::error(_("debug, verbose, and log-level options conflict: please specify only one.")); } if (vm["no-ruby"].as() && vm.count("custom-dir")) { throw po::error(_("no-ruby and custom-dir options conflict: please specify only one.")); } if (vm.count("puppet") && vm["no-custom-facts"].as()) { throw po::error(_("puppet and no-custom-facts options conflict: please specify only one.")); } if (vm.count("puppet") && vm["no-ruby"].as()) { throw po::error(_("puppet and no-ruby options conflict: please specify only one.")); } } catch (exception& ex) { colorize(boost::nowide::cerr, level::error); boost::nowide::cerr << _("error: %1%", ex.what()) << endl; colorize(boost::nowide::cerr); help(visible_options); return EXIT_FAILURE; } // Check for listing fact groups if (vm.count("list-cache-groups")) { collection facts; facts.add_default_facts(!vm.count("no-ruby")); print_fact_groups(facts.get_fact_groups()); if (!vm["no-external-facts"].as()) { vector external_directories; if (vm.count("external-dir")) { external_directories = vm["external-dir"].as>(); } print_fact_groups(facts.get_external_facts_groups(external_directories)); } return EXIT_SUCCESS; } // Check for printing the version if (vm.count("version")) { boost::nowide::cout << LIBFACTER_VERSION_WITH_COMMIT << endl; return EXIT_SUCCESS; } if (vm.count("list-block-groups")) { collection facts; facts.add_default_facts(!vm.count("no-ruby")); print_fact_groups(facts.get_blockable_fact_groups()); return EXIT_SUCCESS; } // Set colorization; if no option was specified, use the default if (vm.count("color")) { set_colorization(true); } else if (vm.count("no-color")) { set_colorization(false); } // Get the logging level auto lvl= vm["log-level"].as(); if (vm["debug"].as()) { lvl = level::debug; } else if (vm["verbose"].as()) { lvl = level::info; } set_level(lvl); log_command_line(argc, argv); // Initialize Ruby in main bool ruby = (!vm["no-ruby"].as()) && facter::ruby::initialize(vm["trace"].as()); leatherman::util::scope_exit ruby_cleanup{[ruby]() { if (ruby) { facter::ruby::uninitialize(); } }}; // Build a set of queries from the command line set queries; if (vm.count("query")) { for (auto const &q : vm["query"].as>()) { // Strip whitespace and query delimiter string query = boost::trim_copy_if(q, boost::is_any_of(".") || boost::is_space()); // Erase any duplicate consecutive delimiters query.erase(unique(query.begin(), query.end(), [](char a, char b) { return a == b && a == '.'; }), query.end()); // Don't insert empty queries if (query.empty()) { continue; } queries.emplace(move(query)); } } log_queries(queries); set blocklist; if (vm.count("blocklist") && !vm.count("no-block")) { auto facts_to_block = vm["blocklist"].as>(); blocklist.insert(facts_to_block.begin(), facts_to_block.end()); } bool ignore_cache = vm.count("no-cache"); collection facts(blocklist, ttls, ignore_cache); facts.add_default_facts(ruby); if (ruby && !vm["no-custom-facts"].as()) { if (vm.count("custom-dir")) { custom_directories = vm["custom-dir"].as>(); } bool redirect_ruby_stdout = vm.count("json") || vm.count("yaml"); facter::ruby::load_custom_facts(facts, vm.count("puppet"), redirect_ruby_stdout, custom_directories); } if (!vm["no-external-facts"].as()) { string inside_facter; environment::get("INSIDE_FACTER", inside_facter); if (inside_facter == "true") { log(level::debug, "Environment variable INSIDE_FACTER is set to 'true'"); log(level::warning, "Facter was called recursively, skipping external facts. Add '--no-external-facts' to silence this warning"); } else { environment::set("INSIDE_FACTER", "true"); if (vm.count("external-dir")) { external_directories = vm["external-dir"].as>(); } facts.add_external_facts(external_directories); } } // Add the environment facts facts.add_environment_facts(); // Output the facts facter::facts::format fmt = facter::facts::format::hash; if (vm.count("json")) { fmt = facter::facts::format::json; } else if (vm.count("yaml")) { fmt = facter::facts::format::yaml; } bool show_legacy = vm.count("show-legacy"); bool strict_errors = vm.count("strict"); facts.write(boost::nowide::cout, fmt, queries, show_legacy, strict_errors); boost::nowide::cout << endl; } catch (locale_error const& e) { boost::nowide::cerr << _("failed to initialize logging system due to a locale error: %1%", e.what()) << endl; return 2; // special error code to indicate we failed harder than normal } catch (exception& ex) { log(level::fatal, "unhandled exception: %1%", ex.what()); } return error_logged() ? EXIT_FAILURE : EXIT_SUCCESS; } facter-3.14.12/ext/0000755005276200011600000000000013702047635013625 5ustar jenkinsjenkinsfacter-3.14.12/ext/build_defaults.yaml0000644005276200011600000000110613702047406017471 0ustar jenkinsjenkins--- deb_build_mirrors: - deb http://pl-build-tools.delivery.puppetlabs.net/debian __DIST__ main packager: 'puppetlabs' gpg_key: '7F438280EF8D349F' # These are the build targets used by the packaging repo. Uncomment to allow use. #final_mocks: 'pl-el-5-x86_64 pl-el-5-i386 pl-el-6-x86_64 pl-el-6-i386 pl-el-7-x86_64' #default_cow: 'base-trusty-i386.cow' #cows: 'base-precise-amd64.cow base-precise-i386.cow base-trusty-amd64.cow base-trusty-i386.cow base-wheezy-amd64.cow base-wheezy-i386.cow' #pbuild_conf: '/etc/pbuilderrc' tar_host: 'downloads.puppetlabs.com' sign_tar: FALSE facter-3.14.12/ext/debian/0000755005276200011600000000000013702047635015047 5ustar jenkinsjenkinsfacter-3.14.12/ext/debian/compat0000644005276200011600000000000213702047406016241 0ustar jenkinsjenkins7 facter-3.14.12/ext/debian/control0000644005276200011600000000164113702047406016450 0ustar jenkinsjenkinsSource: facter Section: devel Priority: optional Maintainer: Puppet Labs Build-Depends: debhelper (>> 7), pl-gcc (>= 4.8.2-1puppetlabs3), pl-cmake (>= 3.2.2-1puppetlabs6), pl-libboost-devel (>= 1.55.0-1puppetlabs3), pl-libboost-static (>= 1.55.0-1puppetlabs3), pl-libyaml-cpp-devel (>= 0.5.1-1puppetlabs4), pl-libyaml-cpp-static (>= 0.5.1-1puppetlabs4), libblkid-dev, libcurl4-openssl-dev, libssl-dev, ruby1.9.1 | ruby (>= 1:1.9.3), ruby1.9.1-dev | ruby-dev (>= 1:1.9.3) Standards-Version: 3.9.1 Homepage: http://www.puppetlabs.com Package: facter Architecture: any Depends: ${shlibs:Depends}, ${misc:Depends}, libblkid1, libcurl3, libssl1.0.0 | libssl0.9.8 Description: A command line tool and library for collecting simple facts about a host operating system Some of the facts are preconfigured, such as the hostname and the operating system. Additional facts can be added through simple Ruby scripts. facter-3.14.12/ext/debian/copyright0000644005276200011600000000070713702047406017002 0ustar jenkinsjenkinsThis package was debianized by Melissa Stone on Thu, 05 Jun 2014 14:07:11 -0800 It was downloaded from https://github.com/puppetlabs/facter Upstream Author: Puppet Labs Copyright: Copyright 2010-2011 Puppet Labs License: ASL-2 http://www.apache.org/licenses/LICENSE-2.0 On a Debian system, the license can be found at /usr/share/common-licenses/Apache-2.0 . facter-3.14.12/ext/debian/docs0000644005276200011600000000002213702047406015710 0ustar jenkinsjenkinsREADME.md LICENSE facter-3.14.12/ext/debian/facter.install0000644005276200011600000000007013702047406017674 0ustar jenkinsjenkinsusr/include/facter usr/lib/ usr/bin/ usr/share/man/man8 facter-3.14.12/ext/debian/lintian-overrides0000644005276200011600000000000013702047406020412 0ustar jenkinsjenkinsfacter-3.14.12/ext/debian/rules0000644005276200011600000000166313702047406016126 0ustar jenkinsjenkins#!/usr/bin/make -f export DH_VERBOSE=1 export VERBOSE=1 PREFIX :=/usr BUILDPREFIX :=/opt/pl-build-tools CPPFLAGS :=$(shell dpkg-buildflags --get CPPFLAGS) CFLAGS :=$(shell dpkg-buildflags --get CFLAGS) CXXFLAGS :=$(shell dpkg-buildflags --get CXXFLAGS) LDFLAGS :=$(shell dpkg-buildflags --get LDFLAGS) # Hard-coded to 2. Our deb builders have a hard-limit at 4GB of memory. NUMPROC :=2 export CPPFLAGS CFLAGS CXXFLAGS LDFLAGS clean: override_dh_auto_configure: $(BUILDPREFIX)/bin/cmake \ -DCMAKE_TOOLCHAIN_FILE=$(BUILDPREFIX)/pl-build-toolchain.cmake \ -DCMAKE_VERBOSE_MAKEFILE=ON \ -DCMAKE_INSTALL_PREFIX=$(PREFIX) \ -DBOOST_STATIC=ON \ -DYAMLCPP_STATIC=ON \ . override_dh_auto_build: $(MAKE) -j$(NUMPROC) DESTDIR=$(CURDIR)/debian/tmp override_dh_auto_install: $(MAKE) -j$(NUMPROC) install DESTDIR=$(CURDIR)/debian/tmp override_dh_auto_test: $(BUILDPREFIX)/bin/ctest -V %: dh $@ --parallel=$(NUMPROC) facter-3.14.12/ext/debian/source/0000755005276200011600000000000013702047635016347 5ustar jenkinsjenkinsfacter-3.14.12/ext/debian/source/format0000644005276200011600000000001413702047406017551 0ustar jenkinsjenkins3.0 (quilt) facter-3.14.12/ext/debian/changelog0000644005276200011600000000060313702047635016720 0ustar jenkinsjenkinsfacter (3.14.12-1puppetlabs1) lucid precise squeeze wheezy trusty; urgency=low * Update to version -- Puppet Labs Release Fri, 10 Jul 2020 11:23:09 +0000 facter (2.4.2-1puppetlabs1) lucid precise squeeze wheezy trusty; urgency=low * Move from Ruby to C++ implementation. -- Michael Smith Fri, 20 Mar 2015 15:12:52 -0700 facter-3.14.12/ext/project_data.yaml0000644005276200011600000000204013702047406017140 0ustar jenkinsjenkins--- project: 'facter' author: 'Puppet Labs' email: 'info@puppetlabs.com' homepage: 'https://github.com/puppetlabs/facter' summary: 'Facter, a system inventory tool' description: 'You can prove anything with facts!' # files to be packaged into a tarball and released with deb/rpm files: - '[A-Z]*' - exe - ext - lib - locales - man - scripts - vendor - cmake # space separated list of files to *exclude* from the tarball # note that each listing in files, above, is recursively copied into the tarball, so # 'tar\_excludes' only needs to include any undesired subdirectories/files of the 'files' # list to exclude tar_excludes: - ext/packaging # Array of templates or globs of templates to evaluate. Note that without this key, the packaging will # default to searching for any files in `ext` with the extension '.erb' and evaluate them. When this # key is supplied, its values override the defaults, and all desired erb files must be specified with a path or glob. templates: - ext/redhat/facter.spec.erb - ext/debian/changelog.erb facter-3.14.12/ext/redhat/0000755005276200011600000000000013702047635015074 5ustar jenkinsjenkinsfacter-3.14.12/ext/redhat/facter.spec0000644005276200011600000000640113702047635017215 0ustar jenkinsjenkins# Only >=el7 and fedora have a sufficient version of ruby available %if 0%{?rhel} >= 7 || 0%{?fedora} %{!?vendor_ruby: %global vendor_ruby %(ruby -rrbconfig -e "puts RbConfig::CONFIG['vendordir']")} %endif # Building debuginfo is pointless, as this has no symbols. %global debug_package %{nil} # VERSION is subbed out during rake srpm process %global realversion 3.14.12 %global rpmversion 3.14.12 %global build_prefix /opt/pl-build-tools %global _prefix /usr %global _libdir %{_prefix}/lib Name: facter Summary: A command line tool and library for collecting simple facts about a host operating system Version: %{rpmversion} Release: 1%{?dist} Epoch: 1 Vendor: %{?_host_vendor} License: ASL 2.0 Group: System Environment/Base URL: http://www.puppetlabs.com/puppet/related-projects/%{name} # Note this URL will only be valid at official tags from Puppet Labs Source0: http://puppetlabs.com/downloads/%{name}/%{name}-%{realversion}.tar.gz BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n) # Only >=el7 and fedora have a sufficient version of ruby available %if 0%{?rhel} >= 7 || 0%{?fedora} BuildRequires: ruby BuildRequires: ruby-devel %endif BuildRequires: pl-gcc >= 4.8.2-4 BuildRequires: pl-cmake >= 3.2.2-1 BuildRequires: pl-libboost-devel >= 1.55.0-4 BuildRequires: pl-libboost-static >= 1.55.0-4 BuildRequires: pl-libyaml-cpp-devel >= 0.5.1-5 BuildRequires: pl-libyaml-cpp-static >= 0.5.1-5 %if 0%{?rhel} > 5 BuildRequires: openssl-devel BuildRequires: libblkid-devel BuildRequires: libcurl-devel %endif Requires: glibc %if 0%{?rhel} > 5 Requires: libblkid Requires: libcurl %endif # If we're linking against openssl, we need to ensure those libraries are available # during runtime. On EL7, those dependency libraries are available via the openssl-libs # package, but we don't have that package on earlier versions. We want to install as # few extra packages as possible, which is why we're installing openssl-libs when available. %if 0%{?rhel} >= 7 Requires: openssl-libs %endif %if 0%{?rhel} == 6 Requires: openssl %endif AutoReq: 0 AutoProv: 0 %description A command line tool and library for collecting simple facts about a host Operating system. Some of the facts are preconfigured, such as the hostname and the operating system. Additional facts can be added through simple Ruby scripts %prep %setup -q -n %{name}-%{realversion} %build rm -rf %{buildroot} %{build_prefix}/bin/cmake \ -DCMAKE_TOOLCHAIN_FILE=%{build_prefix}/pl-build-toolchain.cmake \ -DCMAKE_VERBOSE_MAKEFILE=ON \ -DCMAKE_INSTALL_PREFIX=%{_prefix} \ -DBOOST_STATIC=ON \ -DYAMLCPP_STATIC=ON \ . make %{?_smp_mflags} DESTDIR=%{buildroot} %install make %{?_smp_mflags} install DESTDIR=%{buildroot} %clean rm -rf %{buildroot} %check %{build_prefix}/bin/ctest -V %files %defattr(-,root,root,-) %{_bindir}/facter %{_libdir}/libfacter.so* %{_includedir}/facter %{_mandir}/man8/facter.8.gz %if 0%{?rhel} >= 7 || 0%{?fedora} %{vendor_ruby}/facter.rb %endif %doc LICENSE README.md %changelog * Fri Jul 10 2020 Puppet Labs Release - 1:3.14.12-1 - Build for 3.14.12 * Fri Mar 20 2015 Michael Smith - 2.4.2-1 - Move from Ruby to C++ implementation. facter-3.14.12/ext/windows/0000755005276200011600000000000013702047635015317 5ustar jenkinsjenkinsfacter-3.14.12/ext/windows/facter.bat0000644005276200011600000000021413702047406017244 0ustar jenkinsjenkins@echo off SETLOCAL if exist "%~dp0environment.bat" ( call "%~dp0environment.bat" %0 %* ) else ( SET "PATH=%~dp0;%PATH%" ) facter.exe %* facter-3.14.12/ext/windows/facter_interactive.bat0000644005276200011600000000014113702047406021640 0ustar jenkinsjenkins@echo off SETLOCAL echo Running Facter on demand ... cd "%~dp0" call .\facter.bat %* PAUSE facter-3.14.12/ext/windows/run_facter_interactive.bat0000644005276200011600000000032413702047406022527 0ustar jenkinsjenkins@echo Running facter on demand ... @echo off SETLOCAL if exist "%~dp0environment.bat" ( call "%~dp0environment.bat" %0 %* ) else ( SET "PATH=%~dp0;%PATH%" ) elevate.exe "%~dp0facter_interactive.bat" facter-3.14.12/lib/0000755005276200011600000000000013702047635013573 5ustar jenkinsjenkinsfacter-3.14.12/lib/CMakeLists.txt0000644005276200011600000004074313702047406016337 0ustar jenkinsjenkinscmake_minimum_required(VERSION 3.2.2) # Get the HEAD SHA1 commit message get_commit_string(LIBFACTER_COMMIT) # Generate a file containing the above version numbers configure_file ( "version.h.in" "${CMAKE_CURRENT_LIST_DIR}/inc/facter/version.h" ) # Generate a .gemspec file based on the above version numbers configure_file ( "gemspec.in" "${CMAKE_CURRENT_LIST_DIR}/../.gemspec" ) # Set compiler-specific flags set(CMAKE_CXX_FLAGS ${FACTER_CXX_FLAGS}) if (WIN32) # Disable unused-variable variable for boost ipv6 compilation on windows set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-unused-variable") endif() leatherman_logging_namespace("puppetlabs.facter") # Set the common (platform-independent) sources set(LIBFACTER_COMMON_SOURCES "src/cwrapper.cc" "src/facts/array_value.cc" "src/facts/collection.cc" "src/facts/external_resolvers_factory.cc" "src/facts/external/execution_resolver.cc" "src/facts/external/json_resolver.cc" "src/facts/external/resolver.cc" "src/facts/external/text_resolver.cc" "src/facts/external/yaml_resolver.cc" "src/facts/map_value.cc" "src/facts/resolver.cc" "src/facts/resolvers/augeas_resolver.cc" "src/facts/resolvers/disk_resolver.cc" "src/facts/resolvers/dmi_resolver.cc" "src/facts/resolvers/ec2_resolver.cc" "src/facts/resolvers/filesystem_resolver.cc" "src/facts/resolvers/fips_resolver.cc" "src/facts/resolvers/gce_resolver.cc" "src/facts/resolvers/hypervisors_resolver.cc" "src/facts/resolvers/identity_resolver.cc" "src/facts/resolvers/kernel_resolver.cc" "src/facts/resolvers/ldom_resolver.cc" "src/facts/resolvers/load_average_resolver.cc" "src/facts/resolvers/memory_resolver.cc" "src/facts/resolvers/networking_resolver.cc" "src/facts/resolvers/operating_system_resolver.cc" "src/facts/resolvers/path_resolver.cc" "src/facts/resolvers/processor_resolver.cc" "src/facts/resolvers/ruby_resolver.cc" "src/facts/resolvers/ssh_resolver.cc" "src/facts/resolvers/system_profiler_resolver.cc" "src/facts/resolvers/timezone_resolver.cc" "src/facts/resolvers/uptime_resolver.cc" "src/facts/resolvers/virtualization_resolver.cc" "src/facts/resolvers/xen_resolver.cc" "src/facts/resolvers/zpool_resolver.cc" "src/facts/resolvers/zone_resolver.cc" "src/facts/resolvers/zfs_resolver.cc" "src/facts/cache.cc" "src/facts/scalar_value.cc" "src/logging/logging.cc" "src/ruby/aggregate_resolution.cc" "src/ruby/chunk.cc" "src/ruby/confine.cc" "src/ruby/fact.cc" "src/ruby/module.cc" "src/ruby/resolution.cc" "src/ruby/ruby.cc" "src/ruby/ruby_value.cc" "src/ruby/simple_resolution.cc" "src/util/scoped_file.cc" "src/util/string.cc" "src/util/config/config.cc" "src/util/yaml.cc" ) # Set the POSIX sources if on a POSIX platform if (UNIX) set(LIBFACTER_STANDARD_SOURCES "src/facts/posix/collection.cc" "src/facts/posix/external_resolvers_factory.cc" "src/facts/posix/identity_resolver.cc" "src/facts/posix/networking_resolver.cc" "src/facts/posix/operatingsystem_resolver.cc" "src/facts/posix/processor_resolver.cc" "src/facts/posix/ssh_resolver.cc" "src/facts/posix/timezone_resolver.cc" "src/facts/posix/uptime_resolver.cc" "src/facts/posix/xen_resolver.cc" "src/facts/posix/cache.cc" "src/util/posix/scoped_addrinfo.cc" "src/util/posix/scoped_descriptor.cc" "src/util/config/posix/config.cc" ) if (HAVE_UTMPX_H) set(LIBFACTER_STANDARD_SOURCES ${LIBFACTER_STANDARD_SOURCES} "src/util/posix/utmpx_file.cc") endif() if (NOT AIX) set(LIBFACTER_STANDARD_SOURCES ${LIBFACTER_STANDARD_SOURCES} "src/facts/posix/kernel_resolver.cc" ) endif() endif() if (WIN32) set(LIBFACTER_STANDARD_SOURCES "src/facts/external/windows/powershell_resolver.cc" "src/facts/windows/collection.cc" "src/facts/windows/external_resolvers_factory.cc" "src/util/windows/wsa.cc" ) endif() if (OPENSSL_FOUND) set(LIBFACTER_STANDARD_SOURCES ${LIBFACTER_STANDARD_SOURCES} "src/util/scoped_bio.cc") endif() # Set the platform-specific sources if (AIX) set(LIBFACTER_PLATFORM_SOURCES "src/facts/aix/collection.cc" "src/facts/aix/disk_resolver.cc" "src/facts/aix/filesystem_resolver.cc" "src/facts/aix/kernel_resolver.cc" "src/facts/aix/load_average_resolver.cc" "src/facts/aix/memory_resolver.cc" "src/facts/aix/networking_resolver.cc" "src/facts/aix/nim_resolver.cc" "src/facts/aix/operating_system_resolver.cc" "src/facts/aix/processor_resolver.cc" "src/facts/aix/serial_number_resolver.cc" ) set(LIBFACTER_PLATFORM_LIBRARIES odm lvm ) elseif ("${CMAKE_SYSTEM_NAME}" MATCHES "Darwin") set(LIBFACTER_PLATFORM_SOURCES "src/facts/bsd/filesystem_resolver.cc" "src/facts/bsd/networking_resolver.cc" "src/facts/bsd/uptime_resolver.cc" "src/facts/glib/load_average_resolver.cc" "src/facts/osx/dmi_resolver.cc" "src/facts/osx/networking_resolver.cc" "src/facts/osx/collection.cc" "src/facts/osx/memory_resolver.cc" "src/facts/osx/operating_system_resolver.cc" "src/facts/osx/processor_resolver.cc" "src/facts/osx/system_profiler_resolver.cc" "src/facts/osx/virtualization_resolver.cc" "src/util/bsd/scoped_ifaddrs.cc" ) elseif ("${CMAKE_SYSTEM_NAME}" MATCHES "SunOS") set(LIBFACTER_PLATFORM_SOURCES "src/facts/glib/load_average_resolver.cc" "src/facts/solaris/collection.cc" "src/facts/solaris/disk_resolver.cc" "src/facts/solaris/processor_resolver.cc" "src/facts/solaris/operating_system_resolver.cc" "src/facts/solaris/kernel_resolver.cc" "src/facts/solaris/filesystem_resolver.cc" "src/facts/solaris/dmi_resolver.cc" "src/facts/solaris/virtualization_resolver.cc" "src/facts/solaris/networking_resolver.cc" "src/facts/solaris/memory_resolver.cc" "src/facts/solaris/zfs_resolver.cc" "src/facts/solaris/zone_resolver.cc" "src/facts/solaris/zpool_resolver.cc" "src/facts/solaris/ldom_resolver.cc" "src/util/solaris/k_stat.cc" "src/util/solaris/scoped_kstat.cc" ) set(LIBFACTER_PLATFORM_LIBRARIES kstat socket nsl rt ) elseif ("${CMAKE_SYSTEM_NAME}" MATCHES "Linux") set(LIBFACTER_PLATFORM_SOURCES "src/facts/bsd/networking_resolver.cc" "src/facts/glib/load_average_resolver.cc" "src/facts/linux/disk_resolver.cc" "src/facts/linux/dmi_resolver.cc" "src/facts/linux/filesystem_resolver.cc" "src/facts/linux/fips_resolver.cc" "src/facts/linux/kernel_resolver.cc" "src/facts/linux/memory_resolver.cc" "src/facts/linux/networking_resolver.cc" "src/facts/linux/operating_system_resolver.cc" "src/facts/linux/os_linux.cc" "src/facts/linux/uptime_resolver.cc" "src/facts/linux/collection.cc" "src/facts/linux/processor_resolver.cc" "src/facts/linux/virtualization_resolver.cc" "src/util/bsd/scoped_ifaddrs.cc" ) set(LIBFACTER_PLATFORM_LIBRARIES ${BLKID_LIBRARIES} rt ${UDEV_LIBRARIES} ) elseif ("${CMAKE_SYSTEM_NAME}" MATCHES "FreeBSD") set(LIBFACTER_PLATFORM_SOURCES "src/facts/freebsd/collection.cc" "src/facts/glib/load_average_resolver.cc" "src/facts/bsd/filesystem_resolver.cc" "src/facts/freebsd/filesystem_resolver.cc" "src/facts/bsd/networking_resolver.cc" "src/facts/bsd/uptime_resolver.cc" "src/facts/freebsd/processor_resolver.cc" "src/facts/freebsd/dmi_resolver.cc" "src/facts/freebsd/networking_resolver.cc" "src/util/bsd/scoped_ifaddrs.cc" "src/facts/freebsd/zfs_resolver.cc" "src/facts/freebsd/zpool_resolver.cc" "src/facts/freebsd/virtualization_resolver.cc" "src/facts/freebsd/memory_resolver.cc" "src/facts/freebsd/operating_system_resolver.cc" "src/util/freebsd/geom.cc" "src/facts/freebsd/disk_resolver.cc" ) set(LIBFACTER_PLATFORM_LIBRARIES geom ) elseif ("${CMAKE_SYSTEM_NAME}" MATCHES "OpenBSD") set(LIBFACTER_PLATFORM_SOURCES "src/facts/openbsd/collection.cc" "src/facts/glib/load_average_resolver.cc" "src/facts/bsd/filesystem_resolver.cc" "src/facts/bsd/networking_resolver.cc" "src/facts/bsd/uptime_resolver.cc" "src/facts/openbsd/dmi_resolver.cc" "src/facts/openbsd/networking_resolver.cc" "src/facts/openbsd/processor_resolver.cc" "src/util/bsd/scoped_ifaddrs.cc" "src/facts/openbsd/memory_resolver.cc" "src/facts/openbsd/virtualization_resolver.cc" ) elseif ("${CMAKE_SYSTEM_NAME}" MATCHES "Windows") set(LIBFACTER_PLATFORM_SOURCES "src/facts/windows/dmi_resolver.cc" "src/facts/windows/identity_resolver.cc" "src/facts/windows/kernel_resolver.cc" "src/facts/windows/memory_resolver.cc" "src/facts/windows/networking_resolver.cc" "src/facts/windows/ssh_resolver.cc" "src/facts/windows/operating_system_resolver.cc" "src/facts/windows/processor_resolver.cc" "src/facts/windows/timezone_resolver.cc" "src/facts/windows/uptime_resolver.cc" "src/facts/windows/virtualization_resolver.cc" "src/facts/windows/cache.cc" "src/util/config/windows/config.cc" ) if (HAS_LTH_GET_DWORD) set(LIBFACTER_PLATFORM_SOURCES ${LIBFACTER_PLATFORM_SOURCES} "src/facts/windows/fips_resolver.cc" ) endif() # The GetPerformanceInfo symbol has moved around a lot between Windows versions; # these options tie it to the backwards-compatible version. set(LIBFACTER_PLATFORM_LIBRARIES Psapi.lib Version.lib Wbemuuid.lib Secur32.lib Ws2_32.lib iphlpapi.lib userenv.lib ) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DPSAPI_VERSION=1") endif() if (WIN32) set(LIBFACTER_INSTALL_DESTINATION bin) else() set(LIBFACTER_INSTALL_DESTINATION lib${LIB_SUFFIX}) endif() if (JRUBY_SUPPORT) include_directories(${JNI_INCLUDE_DIRS}) set(LIBFACTER_COMMON_SOURCES ${LIBFACTER_COMMON_SOURCES} src/java/facter.cc) configure_file( Facter.java.in "${CMAKE_BINARY_DIR}/lib/com/puppetlabs/Facter.java" ) include(UseJava) add_jar(facter-jruby-jar "${CMAKE_BINARY_DIR}/lib/com/puppetlabs/Facter.java" OUTPUT_NAME facter OUTPUT_DIR "${CMAKE_BINARY_DIR}/lib" ENTRY_POINT com/puppetlabs/Facter) # javah does not atomically write the header file, so parallel builds can # read it before it finishes writing if not careful. # JDK versions after 9 don't provide javah. Use javac in these cases if(Java_VERSION VERSION_LESS "10") set(JAVAH_COMMAND ${Java_JAVAH_EXECUTABLE}) set(JAVAH_ARG -classpath facter.jar -d "${CMAKE_CURRENT_LIST_DIR}/src/java" com.puppetlabs.Facter) else() set(JAVAH_COMMAND ${Java_JAVAC_EXECUTABLE}) set(JAVAH_ARG -h "${CMAKE_CURRENT_LIST_DIR}/src/java" com/puppetlabs/Facter.java) endif() add_custom_command(OUTPUT "${CMAKE_CURRENT_LIST_DIR}/src/java/com_puppetlabs_Facter.h" COMMAND ${JAVAH_COMMAND} ARGS ${JAVAH_ARG} WORKING_DIRECTORY "${CMAKE_BINARY_DIR}/lib" DEPENDS facter-jruby-jar) # Anything that depends on facter-jruby wants both the jar AND the completely written header. add_custom_target(facter-jruby DEPENDS facter-jruby-jar "${CMAKE_CURRENT_LIST_DIR}/src/java/com_puppetlabs_Facter.h") set(LIBFACTER_COMMON_SOURCES ${LIBFACTER_COMMON_SOURCES} src/java/com_puppetlabs_Facter.h) endif() # Set include directories include_directories( inc ${Boost_INCLUDE_DIRS} ${OPENSSL_INCLUDE_DIRS} ${YAMLCPP_INCLUDE_DIRS} ${CURL_INCLUDE_DIRS} ${LEATHERMAN_INCLUDE_DIRS} ${CPPHOCON_INCLUDE_DIRS} ) link_directories( ${Boost_LIBRARY_DIRS} ${OPENSSL_LIBRARY_DIRS} ${YAMLCPP_LIBRARY_DIRS} ${CURL_LIBRARY_DIRS} ${CPPHOCON_LIBRARY_DIRS} ${WHEREAMI_LIBRARY_DIRS} ) # Add the library target without a prefix (name already has the 'lib') and use '.so' for all platforms (Ruby extension file extension) add_library(libfactersrc OBJECT ${LIBFACTER_COMMON_SOURCES} ${LIBFACTER_STANDARD_SOURCES} ${LIBFACTER_PLATFORM_SOURCES}) set_target_properties(libfactersrc PROPERTIES POSITION_INDEPENDENT_CODE true) add_library(libfacter $) if (BUILD_SHARED_LIBS) set_target_properties(libfacter PROPERTIES PREFIX "" SUFFIX ".so" IMPORT_PREFIX "" IMPORT_SUFFIX ".so.a" VERSION ${PROJECT_VERSION}) endif() if(AIX) # On AIX we need to be built such that we are "dynamically # loadable". This also means specifying an entry point, which for # a ruby module should be our ruby init fn. set_target_properties(libfacter PROPERTIES LINK_FLAGS "-Wl,-G -eInit_libfacter") endif() set(LIBS ${CPPHOCON_LIBRARIES} ${WHEREAMI_LIBRARIES}) # Static libraries should come before shared libraries, or you can end up # with some really annoying link errors. However, we can configure whether # Boost and Leatherman are linked statically or dynamically. if (LEATHERMAN_SHARED) # If Leatherman is shared, Boost should come first because # it's static, or the order doesn't matter. list(APPEND LIBS ${Boost_LIBRARIES} ${LEATHERMAN_LIBRARIES}) else() # If Leatherman is static, it should come first as it depends # on Boost. list(APPEND LIBS ${LEATHERMAN_LIBRARIES} ${Boost_LIBRARIES}) endif() list(APPEND LIBS ${OPENSSL_LIBRARIES} ${YAMLCPP_LIBRARIES} ${CURL_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} ) # Link in additional libraries target_link_libraries(libfacter PRIVATE ${LIBS} ${LIBFACTER_PLATFORM_LIBRARIES}) if (${CMAKE_SYSTEM_NAME} MATCHES "Darwin" AND BOOST_STATIC AND LEATHERMAN_USE_LOCALES) target_link_libraries(libfacter PRIVATE iconv) endif() symbol_exports(libfacter "${CMAKE_CURRENT_LIST_DIR}/inc/facter/export.h") target_compile_definitions(libfactersrc PRIVATE "-Dlibfacter_EXPORTS") leatherman_install(libfacter) install(DIRECTORY inc/facter DESTINATION include) # Always generate spec_helper.rb, as they might be used in packaging # and testing on another machine. # Generate a file for ruby testing configure_file ( "spec_helper.rb.in" "${CMAKE_CURRENT_LIST_DIR}/spec/spec_helper.rb" ) if (APPLE) # Unfortunately the default DLEXT for most rubies on OSX is "bundle" # Ruby calls dlopen for the extension, which doesn't care if the "bundle" really is a dylib # Therefore, workaround this by symlinking "libfacter.bundle" to "libfacter.so" add_custom_command(TARGET libfacter POST_BUILD COMMAND ln -sf libfacter.so libfacter.bundle WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/lib) message(STATUS "\"make install\" will create a symlink from ${CMAKE_INSTALL_PREFIX}/${LIBFACTER_INSTALL_DESTINATION}/libfacter.bundle to ${CMAKE_INSTALL_PREFIX}/${LIBFACTER_INSTALL_DESTINATION}/libfacter.so") install(CODE "EXECUTE_PROCESS(COMMAND ln -sf libfacter.so libfacter.bundle WORKING_DIRECTORY ${CMAKE_INSTALL_PREFIX}/${LIBFACTER_INSTALL_DESTINATION})") endif() set(RUBY_LIB_INSTALL "" CACHE PATH "Specify the location to install facter.rb") if(RUBY_LIB_INSTALL) set(RUBY_VENDORDIR ${RUBY_LIB_INSTALL}) else() # Disable actually installing facter.rb if Ruby is not present and RUBY_LIB_INSTALL not specified. if (RUBY_FOUND) message(STATUS "Ruby ${RUBY_VERSION} found.") execute_process(COMMAND ${RUBY_EXECUTABLE} -rrbconfig -e "puts RbConfig::CONFIG['vendordir']" OUTPUT_VARIABLE RUBY_VENDORDIR_OUT) string(STRIP ${RUBY_VENDORDIR_OUT} RUBY_VENDORDIR) endif() endif() if(RUBY_VENDORDIR) file(RELATIVE_PATH LIBFACTER_INSTALL_RELATIVE ${RUBY_VENDORDIR} ${CMAKE_INSTALL_PREFIX}) configure_file ( "facter.rb.in" "${CMAKE_BINARY_DIR}/lib/facter.rb" ) message(STATUS "\"make install\" will install facter.rb to ${RUBY_VENDORDIR}") install(FILES ${CMAKE_BINARY_DIR}/lib/facter.rb DESTINATION ${RUBY_VENDORDIR}) if (JRUBY_SUPPORT) message(STATUS "\"make install\" will install facter.jar to ${RUBY_VENDORDIR} to support JRuby") install(FILES ${CMAKE_BINARY_DIR}/lib/facter.jar DESTINATION ${RUBY_VENDORDIR}) endif() endif() if (JRUBY_SUPPORT) add_dependencies(libfacter facter-jruby) endif() add_subdirectory(tests) facter-3.14.12/lib/Facter.java.in0000644005276200011600000000577213702047406016256 0ustar jenkinsjenkinspackage com.puppetlabs; import java.util.HashMap; import java.util.TreeSet; /** * The Java shim for libfacter. */ public class Facter { static { // Look for libfacter in the same place as facter.rb does String facterDir = System.getenv("FACTERDIR"); if (facterDir == null) { facterDir = "${CMAKE_INSTALL_PREFIX}"; } // Load the library System.load(facterDir.replaceAll("/$", "") + "/${LIBFACTER_INSTALL_DESTINATION}/libfacter.so"); } /** * Lookup a fact value by name. * @param name The fact name. * @return Returns the fact's value or null if not found. */ public static native Object lookup(String name); /** * Entry point for testing. * Expects one argument which is the fact to lookup. * @param args The program arguments. */ public static void main(String[] args) { if (args.length != 1) { System.out.println("usage: Facter "); return; } print(lookup(args[0]), 1); System.out.println(); } private static void indent(int level) { if (level < 1) { return; } for (int i = 0; i < (level * 2); ++i) { System.out.print(" "); } } @SuppressWarnings("unchecked") private static void print(Object value, int level) { if (value == null) { return; } // Check for arrays if (value instanceof Object[]) { Object[] array = (Object[])value; System.out.print("[\n"); boolean first = true; for (Object element : array) { if (first) { first = false; } else { System.out.print(",\n"); } indent(level); print(element, 0); } System.out.print("\n"); indent(level - 1); System.out.print("]"); return; } // Check for maps if (value instanceof HashMap) { HashMap map = (HashMap)value; System.out.print("{\n"); // Print out the keys in lexicographical order (like a std::map) TreeSet keys = new TreeSet(map.keySet()); boolean first = true; for (String key : keys) { if (first) { first = false; } else { System.out.print(",\n"); } indent(level); System.out.format("%s => ", key); print(map.get(key), level + 1); } System.out.print("\n"); indent(level - 1); System.out.print("}"); return; } // Check for strings (print with quotes) if (value instanceof String) { System.out.format("\"%s\"", value); return; } // Output the value System.out.print(value); } } facter-3.14.12/lib/Gemfile0000644005276200011600000000033513702047406015063 0ustar jenkinsjenkinssource ENV['GEM_SOURCE'] || "https://rubygems.org" group :development, :test do gem 'rake' gem 'rspec' gem 'mocha' end if File.exists? "#{__FILE__}.local" eval(File.read("#{__FILE__}.local"), binding) end facter-3.14.12/lib/Rakefile0000644005276200011600000000017013702047406015232 0ustar jenkinsjenkins# Rakefile for facter require 'rake' Dir['tasks/**/*.rake'].each { |t| load t } task :default do exec 'rake -T' end facter-3.14.12/lib/docs/0000755005276200011600000000000013702047635014523 5ustar jenkinsjenkinsfacter-3.14.12/lib/docs/generate.rb0000644005276200011600000000164613702047406016645 0ustar jenkinsjenkins#!/usr/bin/env ruby # Generates a markdown file containing fact documentation. # usage: ruby generate.rb > facts.md require 'yaml' require 'erb' require 'ostruct' PATH_TO_SCHEMA = File.join(File.dirname(__FILE__), '../schema/facter.yaml') PATH_TO_TEMPLATE = File.join(File.dirname(__FILE__), 'template.erb') schema = YAML.load_file(PATH_TO_SCHEMA) def format_facts(fact_hash) scope = OpenStruct.new({ :facts => fact_hash }) erb = if ERB.instance_method(:initialize).parameters.assoc(:key) # Ruby 2.6+ ERB.new(File.read(PATH_TO_TEMPLATE), trim_mode: '-') else ERB.new(File.read(PATH_TO_TEMPLATE), nil, '-') end erb.result(scope.instance_eval {binding}) end print "## Modern Facts\n\n" print format_facts(schema.reject {|name, info| info['hidden'] == true}) print "## Legacy Facts\n\n" print format_facts(schema.reject {|name, info| info['hidden'].nil? || info['hidden'] == false}) facter-3.14.12/lib/docs/namespaces.dox0000644005276200011600000000423713702047406017360 0ustar jenkinsjenkins/** * The root namespace for facter. */ namespace facter { /** * The namespace for executing commands. */ namespace execution { } /** * The namespace for fact-related types. */ namespace facts { /** * The namespace for BSD-related types and fact resolvers. */ namespace bsd { } /** * The namespace for external types and fact resolvers. */ namespace external { } /** * The namespace for Linux-related types and fact resolvers. */ namespace linux { } /** * The namespace for OSX-related types and fact resolvers. */ namespace osx { } /** * The namespace for POSIX-related types and fact resolvers. */ namespace posix { } /** * The namespace for base resolvers. */ namespace resolvers { } /** * The namespace for Solaris-related types and fact resolvers. */ namespace solaris { } /** * The namespace for Windows-related types and fact resolvers. */ namespace windows { } /** * The namespace for ZFS fact resolvers. */ namespace zfs { } } /** * The namespace for logging functions and macros. */ namespace logging { } /** * The namespace for the Ruby compatibility layer. */ namespace ruby { } /** * The namespace for utilty functions and types. */ namespace util { /** * The namespace for utility types that are BSD-specific. */ namespace bsd { } /** * The namespace for utility types that are POSIX-specific. */ namespace posix { } /** * The namespace for utility types that are Solaris-specific. */ namespace solaris { } /** * The namespace for utility types that are Windows-specific. */ namespace windows { } } } facter-3.14.12/lib/docs/template.erb0000644005276200011600000000211713702047406017025 0ustar jenkinsjenkins<%# This template is used to generate a markdown file documenting facts. -%> <%# Run 'ruby generate.rb > facts.md' to generate the markdown file. -%> <% def format_fact_element(name, info, indent = '') subelements = (info['elements'] || {}).map{|n, i| format_fact_element(n, i, "#{indent} ")}.join('') "#{indent}* `#{name}` (#{info['type']}) --- #{info['description']}\n#{subelements}" end -%> <% facts.each do |name, schema| -%> ### `<%= name %>` <% if schema['hidden'] -%> This legacy fact is hidden by default in Facter's command-line output. <% end -%> **Type:** <%= schema['type'] %> **Purpose:** <%= schema['description'] %> <% if schema['elements'] -%> **Elements:** <%= schema['elements'].map{|name, info| format_fact_element(name, info)}.join('') %> <% end -%> <% if schema['resolution'] -%> **Resolution:** <%= schema['resolution'].split("\n").map { |line| "* " + line }.join("\n") %> <% end -%> <% if schema['caveats'] -%> **Caveats:** <%= schema['caveats'].split("\n").map { |line| "* " + line }.join("\n") %> <% end -%> ([↑ Back to top](#page-nav)) <% end -%> facter-3.14.12/lib/facter.rb.in0000644005276200011600000000323513702047406015770 0ustar jenkinsjenkinsmodule Facter if RUBY_PLATFORM == "java" # For JRuby, require 'facter.jar' begin require 'facter.jar' rescue LoadError raise LoadError.new('libfacter was not built with JRuby support.') end # Pass value call through to JNI interface def self.value(name) Java::ComPuppetlabs::Facter.lookup(name) end def self.search(*paths) # No-op; we don't support custom facts under JRuby end def self.reset() # No-op; we treat facts as immutable under JRuby end def self.version Java::ComPuppetlabs::Facter.lookup("facterversion") end def self.add(*params) raise 'adding facts under JRuby is not implemented.' end else # Simply require libfacter.so; this will define all of the Facter API begin facter_dir = ENV['FACTERDIR'] || File.join(File.expand_path("#{File.dirname(__FILE__)}"), '${LIBFACTER_INSTALL_RELATIVE}') # # This is a cmake pre-processor check. On *nix it will end up '' == '1' # On windows, where we want the changes it will be '1' == '1' # # Facter requires the extra inclusion of puppet/bin as the libfacter.so # lib requires libraries and executables from that directory if '${WIN32}' == '1' ENV['PATH'] = "#{File.join(facter_dir, 'bin')}#{File::PATH_SEPARATOR}#{File.join(facter_dir, '../puppet/bin')}#{File::PATH_SEPARATOR}#{ENV['PATH']}" end require "#{facter_dir}/${LIBFACTER_INSTALL_DESTINATION}/libfacter.so" rescue LoadError raise LoadError, "libfacter was not found. Please make sure it was installed to the expected location.\n" + ($!.message || ''), $!.backtrace end end end facter-3.14.12/lib/gemspec.in0000644005276200011600000000123313702047406015541 0ustar jenkinsjenkins# -*- encoding: utf-8 -*- Gem::Specification.new do |s| s.name = "facter" version = "@PROJECT_VERSION_MAJOR@.@PROJECT_VERSION_MINOR@.@PROJECT_VERSION_PATCH@" mdata = version.match(/(\d+\.\d+\.\d+)/) s.version = mdata ? mdata[1] : version s.required_rubygems_version = Gem::Requirement.new(">= 0") s.authors = ["Puppet Labs"] s.date = "2015-10-22" s.description = "You can prove anything with facts!" s.email = "info@puppetlabs.com" s.files = ["bin/facter"] s.homepage = "https://puppetlabs.com" s.require_paths = ["lib"] s.summary = "Facter, a system inventory tool" s.specification_version = 3 s.required_ruby_version = '~> 2.1' end facter-3.14.12/lib/inc/0000755005276200011600000000000013702047635014344 5ustar jenkinsjenkinsfacter-3.14.12/lib/inc/facter/0000755005276200011600000000000013702047635015610 5ustar jenkinsjenkinsfacter-3.14.12/lib/inc/facter/cwrapper.hpp0000644005276200011600000000062013702047406020136 0ustar jenkinsjenkins#pragma once #include "stdint.h" #ifdef __cplusplus extern "C" { #endif /** * Collects all default facts and store them as a C-string in JSON format. * @param result a pointer to the C-string pointer to the collected facts. * @return Returns EXIT_FAILURE if it fails to retrieve or copy facts; EXIT_SUCCESS otherwise. */ uint8_t get_default_facts(char **result); #ifdef __cplusplus } #endif facter-3.14.12/lib/inc/facter/facts/0000755005276200011600000000000013702047635016710 5ustar jenkinsjenkinsfacter-3.14.12/lib/inc/facter/facts/array_value.hpp0000644005276200011600000000772713702047406021744 0ustar jenkinsjenkins/** * @file * Declares the fact value for arrays. */ #pragma once #include "value.hpp" #include "../export.h" #include #include #include namespace facter { namespace facts { /** * Represents an array of values. * This type can be moved but cannot be copied. */ struct LIBFACTER_EXPORT array_value : value { /** * Constructs an array_value. * @param hidden True if the fact is hidden from output by default or false if not. */ array_value(bool hidden = false) : value(hidden) { } /** * Prevents the array_value from being copied. */ array_value(array_value const&) = delete; /** * Prevents the array_value from being copied. * @returns Returns this array_value. */ array_value& operator=(array_value const&) = delete; /** * Moves the given array_value into this array_value. * @param other The array_value to move into this array_value. */ // Visual Studio 12 still doesn't allow default for move constructor. array_value(array_value&& other); /** * Moves the given array_value into this array_value. * @param other The array_value to move into this array_value. * @return Returns this array_value. */ // Visual Studio 12 still doesn't allow default for move assignment. array_value& operator=(array_value&& other); /** * Adds a value to the array. * @param value The value to add to the array. */ void add(std::unique_ptr value); /** * Checks to see if the array is empty. * @return Returns true if the array is empty or false if it is not. */ bool empty() const; /** * Gets the size of the array. * @return Returns the number of values in the array. */ size_t size() const; /** * Enumerates all facts in the array. * @param func The callback function called for each value in the array. */ void each(std::function func) const; /** * Converts the value to a JSON value. * @param allocator The allocator to use for creating the JSON value. * @param value The returned JSON value. */ virtual void to_json(json_allocator& allocator, json_value& value) const override; /** * Gets the element at the given index. * @tparam T The expected type of the value. * @param i The index in the array to get the element at. * @return Returns the value at the given index or nullptr if the value is not of the expected type. */ template T const* get(size_t i) const { return dynamic_cast(_elements.at(i).get()); } /** * Gets the value at the given index. * @param i The index in the array to get the element at. * @return Returns the value at the given index. */ value const* operator[](size_t i) const; /** * Writes the value to the given stream. * @param os The stream to write to. * @param quoted True if string values should be quoted or false if not. * @param level The current indentation level. * @returns Returns the stream being written to. */ virtual std::ostream& write(std::ostream& os, bool quoted = true, unsigned int level = 1) const override; /** * Writes the value to the given YAML emitter. * @param emitter The YAML emitter to write to. * @returns Returns the given YAML emitter. */ virtual YAML::Emitter& write(YAML::Emitter& emitter) const override; private: std::vector> _elements; }; }} // namespace facter::facts facter-3.14.12/lib/inc/facter/facts/base_resolver.hpp0000644005276200011600000000157713702047406022262 0ustar jenkinsjenkins#ifndef BASE_RESOLVER_H #define BASE_RESOLVER_H #include "../export.h" #include #include namespace facter { namespace facts { struct collection; struct LIBFACTER_EXPORT base_resolver { /** * Gets the name of the fact resolver. * @return Returns the fact resolver's name. */ virtual std::string const& name() const = 0; /** * Gets the fact names the resolver is responsible for resolving. * @return Returns a list of fact names. */ virtual std::vector const& names() const = 0; /** * Called to resolve all facts the resolver is responsible for. * @param facts The fact collection that is resolving facts. */ virtual void resolve(collection& facts) = 0; }; }} // namespace facter::facts #endif // BASE_RESOLVER_H facter-3.14.12/lib/inc/facter/facts/collection.hpp0000644005276200011600000003312213702047406021551 0ustar jenkinsjenkins/** * @file * Declares the fact collection. */ #pragma once #include "resolver.hpp" #include "value.hpp" #include "external/resolver.hpp" #include "../export.h" #include #include #include #include #include #include #include #include #include #include namespace facter { namespace facts { static const std::string cached_custom_facts("cached-custom-facts"); /** * The supported output format for the fact collection. */ enum class format { /** * Use ruby "hash" as the format (default). */ hash, /** * Use JSON as the format. */ json, /** * Use YAML as the format. */ yaml }; namespace { /** * Stream adapter for using with rapidjson */ struct stream_adapter { /** * Constructs an adapter for use with rapidjson around the given stream. * @param stream an output stream to which JSON will be written */ explicit stream_adapter(std::ostream& stream) : _stream(stream) { } /** * Adds a character to the stream. * @param c the char to add */ void Put(char c) { _stream << c; } /** * Flushes the stream. */ void Flush() { _stream.flush(); } private: std::ostream& _stream; }; } /** * Represents the fact collection. * The fact collection is responsible for resolving and storing facts. */ struct LIBFACTER_EXPORT collection { /** * Inherent "has_weight" value for external facts. */ constexpr static size_t external_fact_weight = 10000; /** * Constructs a fact collection. * @param blocklist the names of resolvers that should not be resolved * @param ttls a map of resolver names to cache intervals (times-to-live) * for the facts they resolve * @param ignore_cache true if the cache should not be consulted when resolving facts */ collection(std::set const& blocklist = std::set(), std::unordered_map const& ttls = std::unordered_map{}, bool ignore_cache = false); /** * Destructor for fact collection. */ ~collection(); /** * Prevents the fact collection from being copied. */ collection(collection const&) = delete; /** * Prevents the fact collection from being copied. * @returns Returns this fact collection. */ collection& operator=(collection const&) = delete; /** * Moves the given fact collection into this fact collection. * @param other The fact collection to move into this fact collection. */ // Visual Studio 12 still doesn't allow default for move constructor. collection(collection&& other); /** * Moves the given fact collection into this fact collection. * @param other The fact collection to move into this fact collection. * @return Returns this fact collection. */ // Visual Studio 12 still doesn't allow default for move assignment. collection& operator=(collection&& other); /** * Adds the default facts to the collection. * @param include_ruby_facts Whether or not to include facts which require Ruby in the collection. */ void add_default_facts(bool include_ruby_facts); /** * Adds a resolver to the fact collection. * The last resolver that was added for a particular name or pattern will "win" resolution. * @param res The resolver to add to the fact collection. */ void add(std::shared_ptr const& res); /** * Adds a fact to the fact collection. * @param name The name of the fact. * @param value The value of the fact. */ void add(std::string name, std::unique_ptr value); /** * Adds a custom fact to the fact collection. * @param name The name of the fact. * @param value The value of the fact. * @param weight The weight of the fact. */ void add_custom(std::string name, std::unique_ptr value, size_t weight); /** * Adds an external fact to the fact collection. * @param name The name of the fact. * @param value The value of the fact. */ void add_external(std::string name, std::unique_ptr value); /** * Adds external facts to the fact collection. * @param directories The directories to search for external facts. If empty, the default search paths will be used. */ void add_external_facts(std::vector const& directories = {}); /** * Adds facts defined via "FACTER_xyz" environment variables. * @param callback The callback that is called with the name of each fact added from the environment. */ void add_environment_facts(std::function callback = nullptr); /** * Removes a resolver from the fact collection. * @param res The resolver to remove from the fact collection. */ void remove(std::shared_ptr const& res); /** * Removes a fact by name. * @param name The name of the fact to remove. */ void remove(std::string const& name); /** * Clears the entire fact collection. * This will remove all built-in facts and resolvers from the fact collection. */ void clear(); /** * Checks to see if the fact collection is empty. * All facts will be resolved to determine if the collection is empty. * @return Returns true if the fact collection is empty or false if it is not. */ bool empty(); /** * Gets the count of facts in the fact collection. * All facts will be resolved to determine the size of the collection. * @return Returns the number of facts in the fact collection. */ size_t size(); /** * Gets a fact value by name. * @tparam T The expected type of the value. * @param name The name of the fact to get the value of. * @return Returns a pointer to the fact value or nullptr if the fact is not in the fact collection or the value is not the expected type. */ template T const* get(std::string const& name) { return dynamic_cast(get_value(name)); } /** * Gets a fact value by name without resolving the fact. * @tparam T The expected type of the value. * @param name The name of the fact to get the value of. * @return Returns a pointer to the fact value or nullptr if the fact is not resolved or the value is not the expected type. */ template T const* get_resolved(std::string const& name) const { // Lookup the fact without resolving auto it = _facts.find(name); return dynamic_cast(it == _facts.end() ? nullptr : it->second.get()); } /** * Gets a fact value by name * @param name The name of the fact to get the value of. * @return Returns a pointer to the fact value or nullptr if the fact is not in the fact collection. */ value const* operator[](std::string const& name); /** * Query the collection. * @tparam T The expected type of the value. * @param query The query to run. * @return Returns the result of the query or nullptr if the query returned no value. */ template T const* query(std::string const& query) { return dynamic_cast(query_value(query, false)); } /** * Enumerates all facts in the collection. * All facts will be resolved prior to enumeration. * @param func The callback function called for each fact in the collection. */ void each(std::function func); /** * Writes the contents of the fact collection to the given stream, hiding legacy facts. * All facts will be resolved prior to writing. * @param stream The stream to write the facts to. * @param fmt The output format to use. * @param queries The set of queries to filter the output to. If empty, all facts will be output. * @return Returns the stream being written to. */ std::ostream& write(std::ostream& stream, format fmt = format::hash, std::set const& queries = std::set()); /** * Writes the contents of the fact collection to the given stream. * All facts will be resolved prior to writing. * @param stream The stream to write the facts to. * @param fmt The output format to use. * @param queries The set of queries to filter the output to. If empty, all facts will be output. * @param show_legacy Show legacy facts when querying all facts. * @param strict_errors Report additional error cases * @return Returns the stream being written to. */ std::ostream& write(std::ostream& stream, format fmt, std::set const& queries, bool show_legacy, bool strict_errors); /** * Resolves all facts in the collection. */ void resolve_facts(); /** * Returns the names of all the resolvers currently in the collection, * along with their associated facts. The group names are used to allow * caching of those facts. * @return a map of group names to their associated fact names */ std::map> get_fact_groups(); /** * Returns the time-to-live time for each fact from the facter.conf file * @return a map of fact names to their associated time-to-live value */ const std::unordered_map& get_ttls(); /** * Returns the names of all blockable resolvers currently in the collection, * along with their associated facts. The group names are used to allow * blocking of those facts. * @return a map of blockable group names to their associated fact names */ std::map> get_blockable_fact_groups(); /** * Gets external fact groups (practically files names) * @param directories The directories to search for external facts. If empty, the default search paths will be used. * @return a map of group names to their associated fact names (empty) */ std::map> get_external_facts_groups(std::vector const& directories); protected: /** * Gets external fact directories for the current platform. * @return A list of file paths that will be searched for external facts. */ virtual std::vector get_external_fact_directories() const; private: typedef std::list>> external_files_list; LIBFACTER_NO_EXPORT void resolve_fact(std::string const& name); LIBFACTER_NO_EXPORT value const* get_value(std::string const& name); LIBFACTER_NO_EXPORT value const* query_value(std::string const& query, bool strict_errors); LIBFACTER_NO_EXPORT value const* lookup(value const* value, std::string const& name, bool strict_errors); LIBFACTER_NO_EXPORT void write_hash(std::ostream& stream, std::set const& queries, bool show_legacy, bool strict_errors); LIBFACTER_NO_EXPORT void write_json(std::ostream& stream, std::set const& queries, bool show_legacy, bool strict_errors); LIBFACTER_NO_EXPORT void write_yaml(std::ostream& stream, std::set const& queries, bool show_legacy, bool strict_errors); LIBFACTER_NO_EXPORT void add_common_facts(bool include_ruby_facts); LIBFACTER_NO_EXPORT void get_external_facts_files_from_dir(external_files_list& files, std::string const& directory, bool warn); LIBFACTER_NO_EXPORT external_files_list get_external_facts_files(std::vector const& directories); LIBFACTER_NO_EXPORT bool try_block(std::shared_ptr const& res); LIBFACTER_NO_EXPORT void resolve(std::shared_ptr const& res); // Platform specific members LIBFACTER_NO_EXPORT void add_platform_facts(); std::map> _facts; std::list> _resolvers; std::multimap> _resolver_map; std::list> _pattern_resolvers; std::set _blocklist; std::unordered_map _ttls; bool _ignore_cache; }; }} // namespace facter::facts facter-3.14.12/lib/inc/facter/facts/external/0000755005276200011600000000000013702047635020532 5ustar jenkinsjenkinsfacter-3.14.12/lib/inc/facter/facts/external/resolver.hpp0000644005276200011600000000357013702047406023105 0ustar jenkinsjenkins/** * @file * Declares the base external fact resolver. */ #pragma once #include #include #include "../../export.h" #include "facter/facts/base_resolver.hpp" namespace facter { namespace facts { struct collection; }} // namespace facter::facts namespace facter { namespace facts { namespace external { /** * Thrown when there is an error processing an external fact. */ struct LIBFACTER_EXPORT external_fact_exception : std::runtime_error { /** * Constructs a external_fact_exception. * @param message The exception message. */ explicit external_fact_exception(std::string const& message); }; /** * Thrown when there is no external resolver for a file */ struct LIBFACTER_EXPORT external_fact_no_resolver : std::runtime_error { explicit external_fact_no_resolver(std::string const& message); }; /** * Base class for external resolvers */ struct LIBFACTER_EXPORT resolver : facter::facts::base_resolver { resolver(std::string const &path); /** * Resolves facts from the given file. * @param path The path to the file to resolve facts from. * @param facts The fact collection to populate the external facts into. */ virtual void resolve(collection& facts) = 0; /** * Gets the name of the fact resolver. * @return Returns the fact resolver's name. */ std::string const& name() const; /** * Gets the fact names the resolver is responsible for resolving. * @return Returns a vector of fact names. */ std::vector const& names() const; protected: std::string _path; std::string _name; std::vector _names; }; }}} // namespace facter::facts::external facter-3.14.12/lib/inc/facter/facts/external_resolvers_factory.hpp0000644005276200011600000000150113702047406025067 0ustar jenkinsjenkins#ifndef EXTERNAL_RESOLVERS_FACTORY_H #define EXTERNAL_RESOLVERS_FACTORY_H #include "../export.h" #include "external/resolver.hpp" #include namespace facter { namespace facts { struct LIBFACTER_NO_EXPORT external_resolvers_factory { std::shared_ptr get_resolver(const std::string&); bool text_resolver_can_resolve(std::string const &path); bool json_resolver_can_resolve(std::string const &path); bool yaml_resolver_can_resolve(std::string const &path); bool execution_resolver_can_resolve(std::string const &path); bool powershell_resolver_can_resolve(std::string const &path); std::shared_ptr get_common_resolver(const std::string& path); }; }} // namespace facter::facts #endif // EXTERNAL_RESOLVERS_FACTORY_H facter-3.14.12/lib/inc/facter/facts/fact.hpp0000644005276200011600000005454513702047406020347 0ustar jenkinsjenkins/** * @file * Declares the fact name constants. */ #pragma once #include "../export.h" namespace facter { namespace facts { /** * Stores the constant fact names. */ struct LIBFACTER_EXPORT fact { /** * The fact for kernel name. */ constexpr static char const* kernel = "kernel"; /** * The fact for kernel version. */ constexpr static char const* kernel_version = "kernelversion"; /** * The fact for kernel release. */ constexpr static char const* kernel_release = "kernelrelease"; /** * The fact for kernel major version. */ constexpr static char const* kernel_major_version = "kernelmajversion"; /** * The structured operating system fact. */ constexpr static char const* os = "os"; /** * The fact for operating system name. */ constexpr static char const* operating_system = "operatingsystem"; /** * The fact for operating system family name. */ constexpr static char const* os_family = "osfamily"; /** * The fact for operating system release. */ constexpr static char const* operating_system_release = "operatingsystemrelease"; /** * The fact for operating system major release. */ constexpr static char const* operating_system_major_release = "operatingsystemmajrelease"; /** * The fact for LSB distro id. */ constexpr static char const* lsb_dist_id = "lsbdistid"; /** * The fact for LSB distro release. */ constexpr static char const* lsb_dist_release = "lsbdistrelease"; /** * The fact for LSB distro codename. */ constexpr static char const* lsb_dist_codename = "lsbdistcodename"; /** * The fact for LSB distro description. */ constexpr static char const* lsb_dist_description = "lsbdistdescription"; /** * The fact for LSB distro major release. */ constexpr static char const* lsb_dist_major_release = "lsbmajdistrelease"; /** * The fact for LSB distro minor release. */ constexpr static char const* lsb_dist_minor_release = "lsbminordistrelease"; /** * The fact for LSB release. */ constexpr static char const* lsb_release = "lsbrelease"; /** * The structured fact for networking. */ constexpr static char const* networking = "networking"; /** * The fact for network hostname. */ constexpr static char const* hostname = "hostname"; /** * The fact for IPv4 address. */ constexpr static char const* ipaddress = "ipaddress"; /** * The fact for IPv6 address. */ constexpr static char const* ipaddress6 = "ipaddress6"; /** * The fact for interface MTU. */ constexpr static char const* mtu = "mtu"; /** * The fact for IPv4 netmask. */ constexpr static char const* netmask = "netmask"; /** * The fact for IPv6 netmask. */ constexpr static char const* netmask6 = "netmask6"; /** * The fact for IPv4 network. */ constexpr static char const* network = "network"; /** * The fact for IPv6 network. */ constexpr static char const* network6 = "network6"; /** * The fact for IPv6 scope. */ constexpr static char const* scope6 = "scope6"; /** * The fact for interface MAC address. */ constexpr static char const* macaddress = "macaddress"; /** * The fact for interface names. */ constexpr static char const* interfaces = "interfaces"; /** * The fact for domain name. */ constexpr static char const* domain = "domain"; /** * The fact for fully-qualified domain name (FQDN). */ constexpr static char const* fqdn = "fqdn"; /** * The fact for DHCP servers. */ constexpr static char const* dhcp_servers = "dhcp_servers"; /** * The fact for block device. */ constexpr static char const* block_device = "blockdevice"; /** * The fact for the list of block devices. */ constexpr static char const* block_devices = "blockdevices"; /** * The structured processor fact */ constexpr static char const* processors = "processors"; /** * The fact for processor descriptions. */ constexpr static char const* processor = "processor"; /** * The fact for logical processor count. */ constexpr static char const* processor_count = "processorcount"; /** * The fact for physical processor count. */ constexpr static char const* physical_processor_count = "physicalprocessorcount"; /** * The fact for processor instruction set architecture. */ constexpr static char const* hardware_isa = "hardwareisa"; /** * The fact for processor hardware model. */ constexpr static char const* hardware_model = "hardwaremodel"; /** * The fact for hardware architecture. */ constexpr static char const* architecture = "architecture"; /** * The structured fact for DMI data. */ constexpr static char const* dmi = "dmi"; /** * The fact for BIOS vendor. */ constexpr static char const* bios_vendor = "bios_vendor"; /** * The fact for BIOS version. */ constexpr static char const* bios_version = "bios_version"; /** * The fact for BIOS release date. */ constexpr static char const* bios_release_date = "bios_release_date"; /** * The fact for motherboard asset tag. */ constexpr static char const* board_asset_tag = "boardassettag"; /** * The fact for motherboard manufacturer. */ constexpr static char const* board_manufacturer = "boardmanufacturer"; /** * The fact for motherboard product name. */ constexpr static char const* board_product_name = "boardproductname"; /** * The fact for motherboard serial number. */ constexpr static char const* board_serial_number = "boardserialnumber"; /** * The fact for chassis asset tag. */ constexpr static char const* chassis_asset_tag = "chassisassettag"; /** * The fact for hardware manufacturer. */ constexpr static char const* manufacturer = "manufacturer"; /** * The fact for hardware product name. */ constexpr static char const* product_name = "productname"; /** * The fact for hardware serial number. */ constexpr static char const* serial_number = "serialnumber"; /** * The fact for hardware UUID. */ constexpr static char const* uuid = "uuid"; /** * The fact for hardware chassis type. */ constexpr static char const* chassis_type = "chassistype"; /** * The structured uptime fact */ constexpr static char const* system_uptime = "system_uptime"; /** * The fact for system uptime. */ constexpr static char const* uptime = "uptime"; /** * The fact for system uptime, in days. */ constexpr static char const* uptime_days = "uptime_days"; /** * The fact for system uptime, in hours. */ constexpr static char const* uptime_hours = "uptime_hours"; /** * The fact for system uptime, in seconds. */ constexpr static char const* uptime_seconds = "uptime_seconds"; /** * The fact for selinux state. */ constexpr static char const* selinux = "selinux"; /** * The fact for selinux enforcement state. */ constexpr static char const* selinux_enforced = "selinux_enforced"; /** * The fact for selinux policy version. */ constexpr static char const* selinux_policyversion = "selinux_policyversion"; /** * The fact for current selinux mode. */ constexpr static char const* selinux_current_mode = "selinux_current_mode"; /** * The fact for selinux config mode. */ constexpr static char const* selinux_config_mode = "selinux_config_mode"; /** * The fact for selinux config policy. */ constexpr static char const* selinux_config_policy = "selinux_config_policy"; /** * The structured fact for SSH. */ constexpr static char const* ssh = "ssh"; /** * The fact for SSH DSA public key. */ constexpr static char const* ssh_dsa_key = "sshdsakey"; /** * The fact for SSH RSA public key. */ constexpr static char const* ssh_rsa_key = "sshrsakey"; /** * The fact for SSH ECDSA public key. */ constexpr static char const* ssh_ecdsa_key = "sshecdsakey"; /** * The fact for SSH ED25519 public key. */ constexpr static char const* ssh_ed25519_key = "sshed25519key"; /** * The fact for SSH fingerprint of the DSA public key. */ constexpr static char const* sshfp_dsa = "sshfp_dsa"; /** * The fact for SSH fingerprint of the RSA public key. */ constexpr static char const* sshfp_rsa = "sshfp_rsa"; /** * The fact for SSH fingerprint of the ECDSA public key. */ constexpr static char const* sshfp_ecdsa = "sshfp_ecdsa"; /** * The fact for SSH fingerprint of the ED25519 public key. */ constexpr static char const* sshfp_ed25519 = "sshfp_ed25519"; /** * The structured fact for OSX system profiler facts. */ constexpr static char const* system_profiler = "system_profiler"; /** * The fact for OSX system profiler boot mode. */ constexpr static char const* sp_boot_mode = "sp_boot_mode"; /** * The fact for OSX system profiler boot ROM version. */ constexpr static char const* sp_boot_rom_version = "sp_boot_rom_version"; /** * The fact for OSX system profiler boot volume. */ constexpr static char const* sp_boot_volume = "sp_boot_volume"; /** * The fact for OSX system profiler CPU type (processor name). */ constexpr static char const* sp_cpu_type = "sp_cpu_type"; /** * The fact for OSX system profiler current CPU speed. */ constexpr static char const* sp_current_processor_speed = "sp_current_processor_speed"; /** * The fact for OSX system profiler kernel version. */ constexpr static char const* sp_kernel_version = "sp_kernel_version"; /** * The fact for OSX system profiler L2 cache (per core). */ constexpr static char const* sp_l2_cache_core = "sp_l2_cache_core"; /** * The fact for OSX system profiler L3 cache. */ constexpr static char const* sp_l3_cache = "sp_l3_cache"; /** * The fact for OSX system profiler local host name (computer name). */ constexpr static char const* sp_local_host_name = "sp_local_host_name"; /** * The fact for OSX system profiler machine model (model identifier). */ constexpr static char const* sp_machine_model = "sp_machine_model"; /** * The fact for OSX system profiler machine name (model name). */ constexpr static char const* sp_machine_name = "sp_machine_name"; /** * The fact for OSX system profiler number of processors (total number of cores). */ constexpr static char const* sp_number_processors = "sp_number_processors"; /** * The fact for OSX system profiler OS version (system version). */ constexpr static char const* sp_os_version = "sp_os_version"; /** * The fact for OSX system profiler number of CPU packages (number of physical processors). */ constexpr static char const* sp_packages = "sp_packages"; /** * The fact for OSX system profiler physical memory. */ constexpr static char const* sp_physical_memory = "sp_physical_memory"; /** * The fact for OSX system profiler platform UUID (hardware UUID). */ constexpr static char const* sp_platform_uuid = "sp_platform_uuid"; /** * The fact for OSX system profiler secure virtual memory. */ constexpr static char const* sp_secure_vm = "sp_secure_vm"; /** * The fact for OSX system profiler serial number (system). */ constexpr static char const* sp_serial_number = "sp_serial_number"; /** * The fact for OSX system profiler SMC version (system). */ constexpr static char const* sp_smc_version_system = "sp_smc_version_system"; /** * The fact for OSX system profiler uptime (since boot). */ constexpr static char const* sp_uptime = "sp_uptime"; /** * The fact for OSX system profiler user name. */ constexpr static char const* sp_user_name = "sp_user_name"; /** * The fact for OSX build version. */ constexpr static char const* macosx_buildversion = "macosx_buildversion"; /** * The fact for OSX product name. */ constexpr static char const* macosx_productname = "macosx_productname"; /** * The fact for OSX product version. */ constexpr static char const* macosx_productversion = "macosx_productversion"; /** * The fact for OSX build major version. */ constexpr static char const* macosx_productversion_major = "macosx_productversion_major"; /** * The fact for OSX build minor version. */ constexpr static char const* macosx_productversion_minor = "macosx_productversion_minor"; /** * The fact for Windows to specify if is Server or Desktop Edition variant */ constexpr static char const* windows_edition_id = "windows_edition_id"; /** * The fact for Windows to differentiate Server, Server Core, Client (Desktop) */ constexpr static char const* windows_installation_type = "windows_installation_type"; /** * The fact for Windows textual product name */ constexpr static char const* windows_product_name = "windows_product_name"; /** * The fact for Windows Build Version. */ constexpr static char const* windows_release_id = "windows_release_id"; /** * The fact for Windows native system32 directory. */ constexpr static char const* windows_system32 = "system32"; /** * The fact for virtualization hypervisor. */ constexpr static char const* virtualization = "virtual"; /** * The fact for whether or not the machine is virtual or physical. */ constexpr static char const* is_virtual = "is_virtual"; /** * The fact for all detected hypervisors */ constexpr static char const* hypervisors = "hypervisors"; /** * The fact for the cloud info, including provider, for a node. */ constexpr static char const* cloud = "cloud"; /** * The structured fact for identity information. */ constexpr static char const* identity = "identity"; /** * The fact for the running user ID */ constexpr static char const* id = "id"; /** * The fact for the running group ID */ constexpr static char const* gid = "gid"; /** * The fact for the system timezone */ constexpr static char const* timezone = "timezone"; /** * The fact for mountpoints. */ constexpr static char const* mountpoints = "mountpoints"; /** * The fact for filesystems. */ constexpr static char const* filesystems = "filesystems"; /** * The fact for disks. */ constexpr static char const* disks = "disks"; /** * The fact for partitions. */ constexpr static char const* partitions = "partitions"; /** * The fact for system memory. */ constexpr static char const* memory = "memory"; /** * The fact for free system memory. */ constexpr static char const* memoryfree = "memoryfree"; /** * The fact for free system memory in megabytes. */ constexpr static char const* memoryfree_mb = "memoryfree_mb"; /** * The fact for total system memory. */ constexpr static char const* memorysize = "memorysize"; /** * The fact for total system memory in megabytes. */ constexpr static char const* memorysize_mb = "memorysize_mb"; /** * The fact for free swap. */ constexpr static char const* swapfree = "swapfree"; /** * The fact for free swap in megabytes. */ constexpr static char const* swapfree_mb = "swapfree_mb"; /** * The fact for total swap. */ constexpr static char const* swapsize = "swapsize"; /** * The fact for total swap in megabytes. */ constexpr static char const* swapsize_mb = "swapsize_mb"; /** * The fact for the swap being encrypted or not. */ constexpr static char const* swapencrypted = "swapencrypted"; /** * The ZFS version fact. */ constexpr static char const* zfs_version = "zfs_version"; /** * The ZFS supported version numbers. */ constexpr static char const* zfs_versionnumbers = "zfs_featurenumbers"; /** * The ZFS storage pool (zpool) version fact. */ constexpr static char const* zpool_version = "zpool_version"; /** * The ZFS storage pool supported feature flags. */ constexpr static char const* zpool_featureflags = "zpool_featureflags"; /** * The ZFS storage pool supported version numbers. */ constexpr static char const* zpool_versionnumbers = "zpool_featurenumbers"; /** * The fact for number of Solaris zones. */ constexpr static char const* zones = "zones"; /** * The fact for the current Solaris zone name. */ constexpr static char const* zonename = "zonename"; /** * The fact for Solaris zone brand. */ constexpr static char const* zone_brand = "brand"; /** * The fact for Solaris zone iptype. */ constexpr static char const* zone_iptype = "iptype"; /** * The fact for Solaris zone uuid. */ constexpr static char const* zone_uuid = "uuid"; /** * The fact for Solaris zone id. */ constexpr static char const* zone_id = "id"; /** * The fact for Solaris zone path. */ constexpr static char const* zone_path = "path"; /** * The fact for Solaris zone status. */ constexpr static char const* zone_status = "status"; /** * The fact for Solaris zone name. */ constexpr static char const* zone_name = "name"; /** * The fact for the structured Solaris zone data. */ constexpr static char const* solaris_zones = "solaris_zones"; /** * The fact for EC2 metadata. */ constexpr static char const* ec2_metadata = "ec2_metadata"; /** * The fact for EC2 user data. */ constexpr static char const* ec2_userdata = "ec2_userdata"; /** * The fact for GCE instance metadata. */ constexpr static char const* gce = "gce"; /** * The fact for Ruby metadata. */ constexpr static char const* ruby = "ruby"; /** * The fact for ruby platform. */ constexpr static char const* rubyplatform = "rubyplatform"; /** * The fact for ruby sitedir. */ constexpr static char const* rubysitedir = "rubysitedir"; /** * The fact for ruby version. */ constexpr static char const* rubyversion = "rubyversion"; /** * The fact for the PATH environment variable. */ constexpr static char const* path = "path"; /** * The fact for cpu load average. */ constexpr static char const* load_averages = "load_averages"; /** * The fact for augeas metadata. */ constexpr static char const* augeas = "augeas"; /** * The fact for augeas version. */ constexpr static char const* augeasversion = "augeasversion"; /** * The fact for Xen metadata. */ constexpr static char const* xen = "xen"; /** * The fact for Xen domains. */ constexpr static char const* xendomains = "xendomains"; /** * The structured fact for Solaris LDom facts. */ constexpr static char const* ldom = "ldom"; /** * The fips mode fact for RHEL/Linux* facts. */ constexpr static char const* fips_enabled = "fips_enabled"; /** * The fact for Aix NIM type (master/client) */ constexpr static char const* nim_type = "nim_type"; }; }} // namespace facter::facts facter-3.14.12/lib/inc/facter/facts/map_value.hpp0000644005276200011600000001020613702047406021365 0ustar jenkinsjenkins/** * @file * Declares the fact value for maps (associative array). */ #pragma once #include "value.hpp" #include "../export.h" #include #include #include #include namespace facter { namespace facts { /** * Represents a fact value that maps fact names to values. * This type can be moved but cannot be copied. */ struct LIBFACTER_EXPORT map_value : value { /** * Constructs a map value. * @param hidden True if the fact is hidden from output by default or false if not. */ map_value(bool hidden = false) : value(hidden) { } /** * Prevents the map_value from being copied. */ map_value(map_value const&) = delete; /** * Prevents the map_value from being copied. * @returns Returns this map_value. */ map_value& operator=(map_value const&) = delete; /** * Moves the given map_value into this map_value. * @param other The map_value to move into this map_value. */ // Visual Studio 12 still doesn't allow default for move constructor. map_value(map_value&& other); /** * Moves the given map_value into this map_value. * @param other The map_value to move into this map_value. * @return Returns this map_value. */ // Visual Studio 12 still doesn't allow default for move assignment. map_value& operator=(map_value&& other); /** * Adds a value to the map. * @param name The name of map element. * @param value The value of the map element. */ void add(std::string name, std::unique_ptr value); /** * Checks to see if the map is empty. * @return Returns true if the map is empty or false if it is not. */ bool empty() const; /** * Gets the size of the map. * @return Returns the number of elements in the map. */ size_t size() const; /** * Enumerates all facts in the map. * @param func The callback function called for each element in the map. */ void each(std::function func) const; /** * Converts the value to a JSON value. * @param allocator The allocator to use for creating the JSON value. * @param value The returned JSON value. */ virtual void to_json(json_allocator& allocator, json_value& value) const override; /** * Gets the value in the map of the given name. * @tparam T The expected type of the value. * @param name The name of the value in the map to get. * @return Returns the value in the map or nullptr if the value is not in the map or expected type. */ template T const* get(std::string const& name) const { return dynamic_cast(this->operator [](name)); } /** * Gets the value in the map of the given name. * @param name The name of the value in the map to get. * @return Returns the value in the map or nullptr if the value is not in the map. */ value const* operator[](std::string const& name) const; /** * Writes the value to the given stream. * @param os The stream to write to. * @param quoted True if string values should be quoted or false if not. * @param level The current indentation level. * @returns Returns the stream being written to. */ virtual std::ostream& write(std::ostream& os, bool quoted = true, unsigned int level = 1) const override; /** * Writes the value to the given YAML emitter. * @param emitter The YAML emitter to write to. * @returns Returns the given YAML emitter. */ virtual YAML::Emitter& write(YAML::Emitter& emitter) const override; private: std::map> _elements; }; }} // namespace facter::facts facter-3.14.12/lib/inc/facter/facts/os.hpp0000644005276200011600000001455613702047406020051 0ustar jenkinsjenkins/** * @file * Declares the operating system constants. */ #pragma once #include "../export.h" namespace facter { namespace facts { /** * Stores the constant operating system names. */ struct LIBFACTER_EXPORT os { /** * The RedHat operating system. */ constexpr static char const* redhat = "RedHat"; /** * The Centos operating system. */ constexpr static char const* centos = "CentOS"; /** * The Fedora operating system. */ constexpr static char const* fedora = "Fedora"; /** * The Scientific Linux operating system. */ constexpr static char const* scientific = "Scientific"; /** * The Scientific Linux CERN operating system. */ constexpr static char const* scientific_cern = "SLC"; /** * The Ascendos Linux operating system. */ constexpr static char const* ascendos = "Ascendos"; /** * The Cloud Linux operating system. */ constexpr static char const* cloud_linux = "CloudLinux"; /** * The Virtuozzo Linux operating system. */ constexpr static char const* virtuozzo_linux = "VirtuozzoLinux"; /** * The Parallels Server Bare Metal operating system. */ constexpr static char const* psbm = "PSBM"; /** * The Oracle Linux operating system. */ constexpr static char const* oracle_linux = "OracleLinux"; /** * The Oracle VM Linux operating system. */ constexpr static char const* oracle_vm_linux = "OVS"; /** * The Oracle Enterprise Linux operating system. */ constexpr static char const* oracle_enterprise_linux = "OEL"; /** * The Amazon Linux operating system. */ constexpr static char const* amazon = "Amazon"; /** * The Xen Server Linux operating system. */ constexpr static char const* xen_server = "XenServer"; /** * The XCP-ng Linux operating system. */ constexpr static char const* xcp_ng = "XCP-ng"; /** * The Mint Linux operating system. */ constexpr static char const* linux_mint = "LinuxMint"; /** * The Ubuntu Linux operating system. */ constexpr static char const* ubuntu = "Ubuntu"; /** * The Debian Linux operating system. */ constexpr static char const* debian = "Debian"; /** * The Devuan Linux operating system. */ constexpr static char const* devuan = "Devuan"; /** * The SuSE Linux Enterprise Server operating system. */ constexpr static char const* suse_enterprise_server = "SLES"; /** * The SuSE Linux Enterprise Desktop operating system. */ constexpr static char const* suse_enterprise_desktop = "SLED"; /** * The Open SuSE operating system. */ constexpr static char const* open_suse = "OpenSuSE"; /** * The SuSE operating system. */ constexpr static char const* suse = "SuSE"; /** * The Solaris operating system. */ constexpr static char const* solaris = "Solaris"; /** * The SunOS operating system. */ constexpr static char const* sunos = "SunOS"; /** * The Nexenta operating system. */ constexpr static char const* nexenta = "Nexenta"; /** * The Omni operating system. */ constexpr static char const* omni = "OmniOS"; /** * The Open Indiana operating system. */ constexpr static char const* open_indiana = "OpenIndiana"; /** * The SmartOS operating system. */ constexpr static char const* smart = "SmartOS"; /** * The Gentoo Linux operating system. */ constexpr static char const* gentoo = "Gentoo"; /** * The Archlinux operating system. */ constexpr static char const* archlinux = "Archlinux"; /** * The Manjaro Linux operating system. */ constexpr static char const* manjarolinux = "ManjaroLinux"; /** * The Mandrake Linux operating system. */ constexpr static char const* mandrake = "Mandrake"; /** * The Mandriva Linux operating system. */ constexpr static char const* mandriva = "Mandriva"; /** * The Mageia Linux operating system. */ constexpr static char const* mageia = "Mageia"; /** * The Open WRT operating system. */ constexpr static char const* openwrt = "OpenWrt"; /** * The Meego operating system. */ constexpr static char const* meego = "MeeGo"; /** * The VMWare ESX operating system. */ constexpr static char const* vmware_esx = "VMWareESX"; /** * The Slackware Linux operating system. */ constexpr static char const* slackware = "Slackware"; /** * The Alpine Linux operating system. */ constexpr static char const* alpine = "Alpine"; /** * The CoreOS Linux operating system. */ constexpr static char const* coreos = "CoreOS"; /** * The Cumulus Linux operating system. */ constexpr static char const* cumulus = "CumulusLinux"; /** * The Zen Cloud Platform linux operating system. */ constexpr static char const* zen_cloud_platform = "XCP"; /** * The GNU/kFreeBSD operating system. */ constexpr static char const* kfreebsd = "GNU/kFreeBSD"; /** * The Windows operating system. */ constexpr static char const* windows = "windows"; /** * The AristaEOS operating system. */ constexpr static char const* arista_eos = "AristaEOS"; /** * The HuaweiOS operating system. */ constexpr static char const* huawei = "HuaweiOS"; /** * The PhotonOS operating system. */ constexpr static char const* photon_os = "PhotonOS"; }; }} facter-3.14.12/lib/inc/facter/facts/os_family.hpp0000644005276200011600000000312713702047406021402 0ustar jenkinsjenkins/** * @file * Declares the operating system family constants. */ #pragma once #include "../export.h" namespace facter { namespace facts { /** * Stores the constant operating system family names. */ struct LIBFACTER_EXPORT os_family { /** * The RedHat family of operating systems. */ constexpr static char const* redhat = "RedHat"; /** * The CoreOS family of operating systems. */ constexpr static char const* coreos = "CoreOS"; /** * The Debian family of operating systems. */ constexpr static char const* debian = "Debian"; /** * The SuSE family of operating systems. */ constexpr static char const* suse = "Suse"; /** * The Solaris family of operating systems. */ constexpr static char const* solaris = "Solaris"; /** * The SunOS family of operating systems. */ constexpr static char const* sunos = "SunOS"; /** * The Gentoo family of operating systems. */ constexpr static char const* gentoo = "Gentoo"; /** * The Archlinux family of operating systems. */ constexpr static char const* archlinux = "Archlinux"; /** * The Mandrake family of operating systems. */ constexpr static char const* mandrake = "Mandrake"; /** * The Windows family of operating systems. */ constexpr static char const* windows = "windows"; }; }} // namespace facter::facts facter-3.14.12/lib/inc/facter/facts/resolver.hpp0000644005276200011600000001001413702047406021252 0ustar jenkinsjenkins/** * @file * Declares the base class for fact resolvers. */ #pragma once #include "../export.h" #include #include #include #include #include "facter/facts/base_resolver.hpp" namespace facter { namespace facts { /** * Thrown when a resolver is constructed with an invalid fact name pattern. */ struct LIBFACTER_EXPORT invalid_name_pattern_exception : std::runtime_error { /** * Constructs a invalid_name_pattern_exception. * @param message The exception message. */ explicit invalid_name_pattern_exception(std::string const& message); }; struct collection; /** * Base class for fact resolvers. * A fact resolver is responsible for resolving one or more facts. * This type can be moved but cannot be copied. */ struct LIBFACTER_EXPORT resolver : base_resolver { /** * Constructs a resolver. * @param name The fact resolver name. * @param names The fact names the resolver is responsible for. * @param patterns Regular expression patterns for additional ("dynamic") facts the resolver is responsible for. */ resolver(std::string name, std::vector names, std::vector const& patterns = {}); /** * Destructs the resolver. */ virtual ~resolver(); /** * Prevents the resolver from being copied. */ resolver(resolver const&) = delete; /** * Prevents the resolver from being copied. * @returns Returns this resolver. */ resolver& operator=(resolver const&) = delete; /** * Moves the given resolver into this resolver. * @param other The resolver to move into this resolver. */ // Visual Studio 12 still doesn't allow default for move constructor. resolver(resolver&& other); /** * Moves the given resolver into this resolver. * @param other The resolver to move into this resolver. * @return Returns this resolver. */ // Visual Studio 12 still doesn't allow default for move assignment. resolver& operator=(resolver&& other); /** * Gets the name of the fact resolver. * @return Returns the fact resolver's name. */ std::string const& name() const; /** * Gets the fact names the resolver is responsible for resolving. * @return Returns a vector of fact names. */ std::vector const& names() const; /** * Determines if the resolver has patterns. * @return Returns true if the resolver has patterns or false if it does not. */ bool has_patterns() const; /** * Determines if the given name matches a pattern for the resolver. * @param name The fact name to check. * @return Returns true if the name matches a pattern or returns false if it does not. */ bool is_match(std::string const& name) const; /** * Gets list of languages accepted by the fact resolver for HTTP requests. * @return Returns the fact resolver's accepted languages (comma-separated list of language tags formatted for the HTTP Accept-Language header.) */ std::string const& http_langs(); /** * Called to resolve all facts the resolver is responsible for. * @param facts The fact collection that is resolving facts. */ virtual void resolve(collection& facts) = 0; /** * Determines if this resolver can be blocked from collecting its facts. * @return Returns true if this resolver can be blocked, false otherwise */ virtual bool is_blockable() const; private: std::string _name; std::vector _names; std::vector _regexes; std::string _http_langs; }; }} // namespace facter::facts facter-3.14.12/lib/inc/facter/facts/scalar_value.hpp0000644005276200011600000001173213702047406022062 0ustar jenkinsjenkins/** * @file * Declares the fact value for scalar values like strings and integers. */ #pragma once #include "value.hpp" #include "../export.h" #include #include #include #include namespace facter { namespace facts { /** * Represents a simple scalar value. * This type can be moved but cannot be copied. * @tparam T The underlying scalar type. */ template #if __clang__ || (__GNUC__ >= 5) // Currently limited to Clang and GCC 5 builds until we can minimally target GCC 5 struct LIBFACTER_EXPORT scalar_value : value #else struct scalar_value : value #endif { /** * Constructs a scalar_value. * @param value The scalar value. * @param hidden True if the fact is hidden from output by default or false if not. */ scalar_value(T value, bool hidden = false) : facter::facts::value(hidden), _value(std::move(value)) { } /** * Moves the given scalar_value into this scalar_value. * @param other The scalar_value to move into this scalar_value. */ // Visual Studio 12 still doesn't allow default for move constructor. scalar_value(scalar_value&& other) { *this = std::move(other); } /** * Moves the given scalar_value into this scalar_value. * @param other The scalar_value to move into this scalar_value. * @return Returns this scalar_value. */ // Visual Studio 12 still doesn't allow default for move assignment. scalar_value& operator=(scalar_value&& other) { value::operator=(static_cast(other)); if (this != &other) { _value = std::move(other._value); } return *this; } /** * Converts the value to a JSON value. * @param allocator The allocator to use for creating the JSON value. * @param value The returned JSON value. */ virtual void to_json(json_allocator& allocator, json_value& value) const override; /** * Gets the underlying scalar value. * @return Returns the underlying scalar value. */ T const& value() const { return _value; } /** * Writes the value to the given stream. * @param os The stream to write to. * @param quoted True if string values should be quoted or false if not. * @param level The current indentation level. * @returns Returns the stream being written to. */ virtual std::ostream& write(std::ostream& os, bool quoted = true, unsigned int level = 1) const override { os << _value; return os; } /** * Writes the value to the given YAML emitter. * @param emitter The YAML emitter to write to. * @returns Returns the given YAML emitter. */ virtual YAML::Emitter& write(YAML::Emitter& emitter) const override { emitter << _value; return emitter; } private: scalar_value(scalar_value const&) = delete; scalar_value& operator=(scalar_value const&) = delete; T _value; }; // Declare the specializations for JSON output template <> void scalar_value::to_json(json_allocator& allocator, json_value& value) const; template <> void scalar_value::to_json(json_allocator& allocator, json_value& value) const; template <> void scalar_value::to_json(json_allocator& allocator, json_value& value) const; template <> void scalar_value::to_json(json_allocator& allocator, json_value& value) const; // Declare the specializations for YAML output template <> YAML::Emitter& scalar_value::write(YAML::Emitter& emitter) const; // Declare the specializations for stream output template <> std::ostream& scalar_value::write(std::ostream& os, bool quoted, unsigned int level) const; template <> std::ostream& scalar_value::write(std::ostream& os, bool quoted, unsigned int level) const; // Declare the common instantiations as external; defined in scalar_value.cc extern template struct scalar_value; extern template struct scalar_value; extern template struct scalar_value; extern template struct scalar_value; // Typedef the common instantiation /** * Represents a string fact value. */ typedef scalar_value string_value; /** * Represents an integer fact value. */ typedef scalar_value integer_value; /** * Represents a boolean fact value. */ typedef scalar_value boolean_value; /** * Represents a double fact value. */ typedef scalar_value double_value; }} // namespace facter::facts facter-3.14.12/lib/inc/facter/facts/value.hpp0000644005276200011600000001121113702047406020525 0ustar jenkinsjenkins/** * @file * Declares the base fact value type. */ #pragma once #include "../export.h" #include #include #include #include // Forward declare needed yaml-cpp classes. namespace YAML { class Emitter; } // Forward delcare needed rapidjson classes. namespace rapidjson { class CrtAllocator; template class GenericValue; template class GenericDocument; template struct UTF8; } extern "C" { /** * Simple structure to store enumeration callbacks. */ typedef struct _enumeration_callbacks enumeration_callbacks; } namespace facter { namespace facts { /** * Typedef for RapidJSON allocator. */ typedef typename rapidjson::CrtAllocator json_allocator; /** * Typedef for RapidJSON value. */ typedef typename rapidjson::GenericValue, json_allocator> json_value; /** * Typedef for RapidJSON document. */ typedef typename rapidjson::GenericDocument, json_allocator, json_allocator> json_document; /** * Base class for values. * This type can be moved but cannot be copied. */ struct LIBFACTER_EXPORT value { /** * Constructs a value. * @param hidden True if the fact is hidden from output by default or false if not. */ value(bool hidden = false) : _hidden(hidden), _weight(0) { } /** * Destructs a value. */ virtual ~value() = default; /** * Moves the given value into this value. * @param other The value to move into this value. */ // Visual Studio 12 still doesn't allow default for move constructor. value(value&& other) { _hidden = other._hidden; _weight = other._weight; } /** * Moves the given value into this value. * @param other The value to move into this value. * @return Returns this value. */ // Visual Studio 12 still doesn't allow default for move assignment. value& operator=(value&& other) { _hidden = other._hidden; _weight = other._weight; return *this; } /** * Determines if the value is hidden from output by default. * @return Returns true if the value is hidden from output by default or false if it is not. */ bool hidden() const { return _hidden; } /** * Gets the weight of the fact. * @return Returns the weight of the fact. */ size_t weight() const { return _weight; } /** * Sets the weight of the fact. * @param weight The weight of the fact. */ void weight(size_t weight) { _weight = weight; } /** * Converts the value to a JSON value. * @param allocator The allocator to use for creating the JSON value. * @param value The returned JSON value. */ virtual void to_json(json_allocator& allocator, json_value& value) const = 0; /** * Writes the value to the given stream. * @param os The stream to write to. * @param quoted True if string values should be quoted or false if not. * @param level The current indentation level. * @returns Returns the stream being written to. */ virtual std::ostream& write(std::ostream& os, bool quoted = true, unsigned int level = 1) const = 0; /** * Writes the value to the given YAML emitter. * @param emitter The YAML emitter to write to. * @returns Returns the given YAML emitter. */ virtual YAML::Emitter& write(YAML::Emitter& emitter) const = 0; private: value(value const&) = delete; value& operator=(value const&) = delete; bool _hidden; size_t _weight; }; /** * Utility function for making a value. * @tparam T The type of the value being constructed. * @tparam Args The variadic types for the value's constructor. * @param args The arguments to the value's constructor. * @return Returns a unique pointer to the constructed value. */ template std::unique_ptr make_value(Args&& ...args) { return std::unique_ptr(new T(std::forward(args)...)); } }} // namespace facter::facts facter-3.14.12/lib/inc/facter/facts/vm.hpp0000644005276200011600000001024413702047406020040 0ustar jenkinsjenkins/** * @file * Declares the virtual machine name constants. */ #pragma once #include "../export.h" namespace facter { namespace facts { /** * Stores the constant virtual machine names. */ struct LIBFACTER_EXPORT vm { /** * The name for VMWare virtual machine. */ constexpr static char const* vmware = "vmware"; /** * The name for VirtualBox virtual machine. */ constexpr static char const* virtualbox = "virtualbox"; /** * The name for Parallels virtual machine. */ constexpr static char const* parallels = "parallels"; /** * The name for VMware Server virtual machine. */ constexpr static char const* vmware_server = "vmware_server"; /** * The name for VMware Workstation virtual machine. */ constexpr static char const* vmware_workstation = "vmware_workstation"; /** * The name for Docker virtual machine. */ constexpr static char const* docker = "docker"; /** * The name for LXC virtual machine. */ constexpr static char const* lxc = "lxc"; /** * The name for Google Compute Engine virtual machine. */ constexpr static char const* gce = "gce"; /** * The name for OpenStack-hosted virtual machine, when OpenStack defines the machine type. */ constexpr static char const* openstack = "openstack"; /** * The name for Xen privileged domain virtual machine. */ constexpr static char const* xen_privileged = "xen0"; /** * The name for Xen unprivileged domain virtual machine. */ constexpr static char const* xen_unprivileged = "xenu"; /** * The name for Xen Hardware virtual machine. */ constexpr static char const* xen_hardware = "xenhvm"; /** * The name for Xen virtual machine (on Windows) */ constexpr static char const* xen = "xen"; /** * The name for IBM System Z virtual machine. */ constexpr static char const* zlinux = "zlinux"; /** * The name for Linux-VServer host virtual machine. */ constexpr static char const* vserver_host = "vserver_host"; /** * The name for Linux-VServer virtual machine. */ constexpr static char const* vserver = "vserver"; /** * The name for OpenVZ Hardware Node virtual machine. */ constexpr static char const* openvz_hn = "openvzhn"; /** * The name for OpenVZ Virtual Environment virtual machine. */ constexpr static char const* openvz_ve = "openvzve"; /** * The name for KVM (QEMU) virtual machine. */ constexpr static char const* kvm = "kvm"; /** * The name for AHV (Nutanix) virtual machine. */ constexpr static char const* ahv = "ahv"; /** * The name for Bochs virtual machine. */ constexpr static char const* bochs = "bochs"; /** * The name for Microsoft Hyper-V virtual machine. */ constexpr static char const* hyperv = "hyperv"; /** * The name for Red Hat Enterprise Virtualization virtual machine. */ constexpr static char const* redhat_ev = "rhev"; /** * The name for oVirt virtual machine. */ constexpr static char const* ovirt = "ovirt"; /** * The name for Solaris zones */ constexpr static char const* zone = "zone"; /** * The name for Solaris ldom */ constexpr static char const* ldom = "ldom"; /** * The name of FreeBSD jails */ constexpr static char const* jail = "jail"; /** * The name for OpenBSD vmm */ constexpr static char const* vmm = "vmm"; /** * The name for FreeBSD bhyve */ constexpr static char const* bhyve = "bhyve"; }; }} // namespace facter::facts facter-3.14.12/lib/inc/facter/logging/0000755005276200011600000000000013702047635017236 5ustar jenkinsjenkinsfacter-3.14.12/lib/inc/facter/logging/logging.hpp0000644005276200011600000001247613702047406021403 0ustar jenkinsjenkins/** * @file * Declares the Facter logging functions. */ #pragma once #include #include #include #include #include "../export.h" namespace facter { namespace logging { /** * Represents the supported logging levels. */ enum class level { /** * No logging level. */ none, /** * Trace level. */ trace, /** * Debug level. */ debug, /** * Info level. */ info, /** * Warning level. */ warning, /** * Error level. */ error, /** * Fatal error level. */ fatal }; /** * Reads a logging level from an input stream. * This is used in boost::lexical_cast. * @param in The input stream. * @param lvl The returned logging level. * @returns Returns the input stream. */ LIBFACTER_EXPORT std::istream& operator>>(std::istream& in, level& lvl); /** * Produces the printed representation of a logging level. * @param os The stream to write. * @param lvl The logging level to write. * @return Returns the stream after writing to it. */ LIBFACTER_EXPORT std::ostream& operator<<(std::ostream& os, level lvl); /** * Sets up logging for the given stream. * The logging level is set to warning by default. * @param os The output stream to configure for logging. */ LIBFACTER_EXPORT void setup_logging(std::ostream& os); /** * Sets the current logging level. * @param lvl The new current logging level to set. */ LIBFACTER_EXPORT void set_level(level lvl); /** * Gets the current logging level. * @return Returns the current logging level. */ LIBFACTER_EXPORT level get_level(); /** * Sets whether or not log output is colorized. * @param color Pass true if log output is colorized or false if it is not colorized. */ LIBFACTER_EXPORT void set_colorization(bool color); /** * Gets whether or not the log output is colorized. * @return Returns true if log output is colorized or false if it is not colorized. */ LIBFACTER_EXPORT bool get_colorization(); /** * Determines if the given logging level is enabled. * @param lvl The logging level to check. * @return Returns true if the logging level is enabled or false if it is not. */ LIBFACTER_EXPORT bool is_enabled(level lvl); /** * Determine if an error has been logged. * @return Returns true if an error or critical message has been logged. */ LIBFACTER_EXPORT bool error_logged(); /** * Clears logged errors. */ LIBFACTER_EXPORT void clear_logged_errors(); /** * Translate text using the locale initialized by this library. * @param msg The string to translate. * @return The translated string. */ LIBFACTER_EXPORT std::string translate(std::string const& msg); /** * Format a text message. * @tparam TArgs The format argument types. * @param fmt The format string. * @param args The format arguments. * @return The formatted string. */ template std::string format(std::string const& fmt, TArgs... args) { boost::format msg{translate(fmt)}; (void) std::initializer_list{ ((void)(msg % args), 0)... }; return msg.str(); } /** * Format a text message. * Alias for format(...); Convenience function for adding i18n support. * @tparam TArgs The format argument types. * @param fmt The format string. * @param args The format arguments. * @return The formatted string. */ template inline std::string _(std::string const& fmt, TArgs&&... args) { return format(std::forward(fmt), std::forward(args)...); } /** * Log a message. * @param lvl The logging level to log with. * @param msg The message to log. */ LIBFACTER_EXPORT void log(level lvl, std::string const& msg); /** * Log a formatted message. * @tparam TArgs The format argument types. * @param lvl The logging level to log with. * @param fmt The format string. * @param args The format arguments. */ template inline void log(level lvl, std::string const& fmt, TArgs... args) { log(std::forward(lvl), format(fmt, std::forward(args)...)); } /** * Starts colorizing for the given logging level. * This is a no-op on platforms that don't natively support terminal colors. * @param os The stream to colorize. * @param lvl The logging level to colorize for. Defaults to none, which resets colorization. */ LIBFACTER_EXPORT void colorize(std::ostream &os, level lvl = level::none); /** * Exception to indicate that locale setup was not possible. */ class locale_error : public std::runtime_error { public: /** * Constructs a locale_error exception. * @param msg The exception message. */ explicit locale_error(const std::string& msg) : std::runtime_error(msg) {} }; }} // namespace facter::logging facter-3.14.12/lib/inc/facter/ruby/0000755005276200011600000000000013702047635016571 5ustar jenkinsjenkinsfacter-3.14.12/lib/inc/facter/ruby/ruby.hpp0000644005276200011600000000664713702047406020274 0ustar jenkinsjenkins/** * @file * Declares the Facter Ruby functions. */ #pragma once #include "../facts/collection.hpp" #include "../facts/value.hpp" #include "../export.h" #include #include namespace facter { namespace ruby { /** * Initialize Ruby integration in Facter. * Important: this function must be called in main(). * Calling this function from an arbitrary stack depth may result in segfaults during Ruby GC. * @param include_stack_trace True if Ruby exception messages should include a stack trace or false if not. * @return Returns true if Ruby was initialized or false if Ruby could not be initialized (likely not found). */ LIBFACTER_EXPORT bool initialize(bool include_stack_trace = false); /** * Loads custom facts into the given collection. * Important: this function should be called from main(). * Calling this function from an arbitrary stack depth may result in segfaults during Ruby GC. * @param facts The collection to populate with custom facts. * @param initialize_puppet Whether puppet should be loaded to find additional facts. * @param redirect_stdout Whether Ruby's stdout should be redirected to stderr * @param paths The paths to search for custom facts. */ LIBFACTER_EXPORT void load_custom_facts(facter::facts::collection& facts, bool initialize_puppet, bool redirect_stdout, std::vector const& paths = {}); /** * Loads custom facts into the given collection. * Important: this function should be called from main(). * Calling this function from an arbitrary stack depth may result in segfaults during Ruby GC. * @param facts The collection to populate with custom facts. * @param initialize_puppet Whether puppet should be loaded to find additional facts. * @param paths The paths to search for custom facts. */ LIBFACTER_EXPORT void load_custom_facts(facter::facts::collection& facts, bool initialize_puppet, std::vector const& paths = {}); /** * Loads custom facts into the given collection. * Important: this function should be called from main(). * Calling this function from an arbitrary stack depth may result in segfaults during Ruby GC. * This is provided for backwards compatibility. * @param facts The collection to populate with custom facts. * @param paths The paths to search for custom facts. */ LIBFACTER_EXPORT void load_custom_facts(facter::facts::collection& facts, std::vector const& paths = {}); /** * Traverses a ruby fact and returns a new value based on the * query segments passed in the range. * @param value The original value to query * @param segment The beginning of the query segment range * @param end The end of the query segment range * @return Returns a pointer to the value queried, or nullptr if it does not exist. */ LIBFACTER_EXPORT facts::value const* lookup(facts::value const* value, std::vector::iterator segment, std::vector::iterator end); /** * Uninitialize Ruby integration in Facter. * This is unneeded if libfacter was loaded from Ruby. If libfacter instead loads Ruby's dynamic library * you should call uninitialize before exiting to avoid dynamic library unload ordering issues with * destructors and atexit handlers. */ LIBFACTER_EXPORT void uninitialize(); }} // namespace facter::ruby facter-3.14.12/lib/inc/facter/util/0000755005276200011600000000000013702047635016565 5ustar jenkinsjenkinsfacter-3.14.12/lib/inc/facter/util/config.hpp0000644005276200011600000001017213702047406020540 0ustar jenkinsjenkins/** * @file * Declares methods for interacting with Facter's config file. */ #pragma once #include "../export.h" #include #include namespace facter { namespace util { namespace config { /** * Parses the contents of Facter's config file from its default location * for the current operating system. * @return HOCON config object, or nullptr if no file was found */ LIBFACTER_EXPORT hocon::shared_config load_default_config_file(); /** * Returns the default location of the config file. * @return the absolute path to the default config file */ LIBFACTER_EXPORT std::string default_config_location(); /** * Parses the contents of the config pile at the specified path. * @param config_path the path to the config file * @return HOCON config object, or nullptr if no file was found */ LIBFACTER_EXPORT hocon::shared_config load_config_from(std::string config_path); /** * Loads the "global" section of the config file into the settings map. * @param hocon_config the config object representing the parsed config file * @param vm the key-value map in which to store the settings */ LIBFACTER_EXPORT void load_global_settings(hocon::shared_config hocon_config, boost::program_options::variables_map& vm); /** * Loads the "cli" section of the config file into the settings map. * @param hocon_config the config object representing the parsed config file * @param vm the key-value map in which to store the settings */ LIBFACTER_EXPORT void load_cli_settings(hocon::shared_config hocon_config, boost::program_options::variables_map& vm); /** * Loads the "blocklist" section of the config file into the settings map. * @param hocon_config the config object representing the parsed config file * @param vm the key-value map in which to store the settings */ LIBFACTER_EXPORT void load_fact_settings(hocon::shared_config hocon_config, boost::program_options::variables_map& vm); /** * Loads the "fact-groups" section of the config file into the settings map. * @param hocon_config the config object representing the parsed config file * @param vm the key-value map in which to store the settings */ LIBFACTER_EXPORT void load_fact_groups_settings(hocon::shared_config hocon_config, boost::program_options::variables_map& vm); /** * Returns a schema of the valid global options that can appear in the config file. * @return names, values, and descriptions of global Facter options */ LIBFACTER_EXPORT boost::program_options::options_description global_config_options(); /** * Returns a schema of the valid config file options affecting Facter's command line interface. * @return names, values, and descriptions of command line options */ LIBFACTER_EXPORT boost::program_options::options_description cli_config_options(); /** * Returns a schema for options dealing with block fact collection. * @return names, values, and descriptions of fact blocking config options */ LIBFACTER_EXPORT boost::program_options::options_description fact_config_options(); /** * Returns a schema for options dealing with block fact groups collection. * @return names, values, and descriptions of fact groups config options */ LIBFACTER_EXPORT boost::program_options::options_description fact_groups_config_options(); /** * Returns a map of resolver names and durations (in milliseconds). The listed resolvers will * have their output cached, then re-resolved no more frequently than the given interval. * @param hocon_config the config object representing the parsed config file * @return a map of resolvers to time-to-live durations (in milliseconds) */ LIBFACTER_EXPORT std::unordered_map load_ttls(hocon::shared_config hocon_config); /** * Returns the directory of the fact cache. * @return the absolute path to the fact cache */ LIBFACTER_EXPORT std::string fact_cache_location(); }}} // namespace facter::util::config facter-3.14.12/lib/inc/facter/util/string.hpp0000644005276200011600000000501413702047406020600 0ustar jenkinsjenkins/** * @file * Declares the utility functions for parsing and manipulating strings. */ #pragma once #include "../export.h" #include #include #include #include #include #include #include namespace facter { namespace util { /** * Converts the given bytes to a hexadecimal string. * @param bytes The pointer to the bytes to convert. * @param length The number of bytes to convert. * @param uppercase True if the hexadecimal string should be uppercase or false if it should be lowercase. * @return Returns the hexadecimal string. */ std::string to_hex(uint8_t const* bytes, size_t length, bool uppercase = false); /** * Reads each line from the given string. * @param s The string to read. * @param callback The callback function that is passed each line in the string. */ void each_line(std::string const& s, std::function callback); /** * Converts a size, in bytes, to a corresponding string using SI-prefixed units. * @param size The size in bytes. * @return Returns the size in largest SI unit greater than 1 (e.g. 4.05 GiB, 5.20 MiB, etc). */ std::string si_string(uint64_t size); /** * Converts an amount used to a percentage. * @param used The amount used out of the total. * @param total The total amount. * @return Returns the percentage (e.g. "41.53%"), to two decimal places, as a string. */ std::string percentage(uint64_t used, uint64_t total); /** * Converts the given frequency, in Hz, to a string. * @param freq The frequency to convert, in Hz. * @return Returns the frequency as a string (e.g. "1.24 GHz"). */ std::string frequency(int64_t freq); /** * Checks to see if the given string definitely needs to be quoted for YAML. * This exists as a workaround to yaml-cpp's poor handling of maintaining numerical string types in the output. * @param str The string to check. * @return Returns true if the string needs to be quoted or false if it may not need to be. */ bool needs_quotation(std::string const& str); /** * Converts the given string to an integer, if it is a valid integer. * @param str The string to convert. * @return Returns the converted string if the string is a valid integer, * otherwise it returns "nothing" */ boost::optional maybe_stoi(std::string const& str); }} // namespace facter::util facter-3.14.12/lib/inc/internal/0000755005276200011600000000000013702047635016160 5ustar jenkinsjenkinsfacter-3.14.12/lib/inc/internal/facts/0000755005276200011600000000000013702047635017260 5ustar jenkinsjenkinsfacter-3.14.12/lib/inc/internal/facts/aix/0000755005276200011600000000000013702047635020041 5ustar jenkinsjenkinsfacter-3.14.12/lib/inc/internal/facts/aix/disk_resolver.hpp0000644005276200011600000000111513702047406023417 0ustar jenkinsjenkins/** * @file * Declares the AIX disk fact resolver. */ #pragma once #include "../resolvers/disk_resolver.hpp" namespace facter { namespace facts { namespace aix { /** * Responsible for resolving disk facts. */ struct disk_resolver : resolvers::disk_resolver { protected: /** * Collects the resolver data. * @param facts The fact collection that is resolving facts. * @return Returns the resolver data. */ virtual data collect_data(collection& facts) override; }; }}} // namespace facter::facts::aix facter-3.14.12/lib/inc/internal/facts/aix/filesystem_resolver.hpp0000644005276200011600000000231313702047406024652 0ustar jenkinsjenkins/** * @file * Declares the AIX file system fact resolver. */ #pragma once #include "../resolvers/filesystem_resolver.hpp" #include namespace facter { namespace facts { namespace aix { /** * Responsible for resolving AIX file system facts. */ struct filesystem_resolver : resolvers::filesystem_resolver { protected: /** * Collects the DMI data. * @param facts The fact collection that is resolving facts. * @return Returns the DMI data. */ virtual data collect_data(collection& facts) override; private: void collect_filesystem_data(data& result); void collect_mountpoint_data(data& result); void collect_partition_data(data& result); private: // AIX tracks filesystems as numeric IDs. We need to load up // the human-readable names from /etc before we can print them // out nicely. std::map _filesystems; // This stores which partitions are mounted where, so we don't have // to scan the array of mountpoints when populating partitions. std::map _mounts; }; }}} // namespace facter::facts::aix facter-3.14.12/lib/inc/internal/facts/aix/kernel_resolver.hpp0000644005276200011600000000112713702047406023750 0ustar jenkinsjenkins/** * @file * Declares the AIX kernel fact resolver. */ #pragma once #include "../resolvers/kernel_resolver.hpp" namespace facter { namespace facts { namespace aix { /** * Responsible for resolving kernel facts. */ struct kernel_resolver : resolvers::kernel_resolver { protected: /** * Collects the resolver data. * @param facts The fact collection that is resolving facts. * @return Returns the resolver data. */ virtual data collect_data(collection& facts) override; }; }}} // namespace facter::facts::aix facter-3.14.12/lib/inc/internal/facts/aix/load_average_resolver.hpp0000644005276200011600000000115413702047406025101 0ustar jenkinsjenkins/** * @file * Declares the AIX load average fact resolver. */ #pragma once #include "../resolvers/load_average_resolver.hpp" namespace facter { namespace facts { namespace aix { /** * Responsible for resolving the load average facts. */ struct load_average_resolver : resolvers::load_average_resolver { protected: /** * Gets the load averages (for 1, 5 and 15 minutes period). * @return The load averages. */ virtual boost::optional> get_load_averages() override; }; }}} // namespace facter::facts::aix facter-3.14.12/lib/inc/internal/facts/aix/memory_resolver.hpp0000644005276200011600000000112713702047406024000 0ustar jenkinsjenkins/** * @file * Declares the Aix memory fact resolver. */ #pragma once #include "../resolvers/memory_resolver.hpp" namespace facter { namespace facts { namespace aix { /** * Responsible for resolving memory facts. */ struct memory_resolver : resolvers::memory_resolver { protected: /** * Collects the resolver data. * @param facts The fact collection that is resolving facts. * @return Returns the resolver data. */ virtual data collect_data(collection& facts) override; }; }}} // namespace facter::facts::aix facter-3.14.12/lib/inc/internal/facts/aix/networking_resolver.hpp0000644005276200011600000000346213702047406024663 0ustar jenkinsjenkins/** * @file * Declares the Aix networking fact resolver. */ #pragma once #include "../posix/networking_resolver.hpp" #include struct kinfo_ndd; namespace facter { namespace facts { namespace aix { /** * Responsible for resolving networking facts. */ struct networking_resolver : posix::networking_resolver { protected: /** * Collects the resolver data. * @param facts The fact collection that is resolving facts. * @return Returns the resolver data. */ virtual data collect_data(collection& facts) override; /** * Determines if the given sock address is a link layer address. * @param addr The socket address to check. * @returns Returns true if the socket address is a link layer address or false if it is not. */ virtual bool is_link_address(sockaddr const* addr) const override; /** * Gets the bytes of the link address. * @param addr The socket address representing the link address. * @return Returns a pointer to the address bytes or nullptr if not a link address. */ virtual uint8_t const* get_link_address_bytes(sockaddr const* addr) const override; /** * Gets the length of the link address. * @param addr The socket address representing the link address. * @return Returns the length of the address or 0 if not a link address. */ virtual uint8_t get_link_address_length(sockaddr const* addr) const override; private: using mtu_map = std::unordered_map; std::string get_primary_interface() const; mtu_map get_mtus() const; std::vector get_interfaces() const; }; }}} // namespace facter::facts::aix facter-3.14.12/lib/inc/internal/facts/aix/nim_resolver.hpp0000644005276200011600000000125613702047406023256 0ustar jenkinsjenkins/** * @file * Declares the AIX NIM Type fact resolver. */ #pragma once #include namespace facter { namespace facts { namespace aix { /** * Responsible for resolving NIM Type fact. */ struct nim_resolver : resolver { /* * Constructs the nim_resolver. */ nim_resolver(); /** * Called to resolve all the facts the resolver is responsible for. * @param facts The fact collection that is resolving facts. */ virtual void resolve(collection& facts) override; virtual std::string read_niminfo(); }; }}} // namespace facter::facts::aix facter-3.14.12/lib/inc/internal/facts/aix/operating_system_resolver.hpp0000644005276200011600000000120013702047406026054 0ustar jenkinsjenkins/** * @file * Declares the aix operating system fact resolver. */ #pragma once #include "../posix/operating_system_resolver.hpp" namespace facter { namespace facts { namespace aix { /** * Responsible for resolving operating system facts. */ struct operating_system_resolver : posix::operating_system_resolver { protected: /** * Collects the resolver data. * @param facts The fact collection that is resolving facts. * @return Returns the resolver data. */ virtual data collect_data(collection& facts) override; }; }}} // namespace facter::facts::aix facter-3.14.12/lib/inc/internal/facts/aix/processor_resolver.hpp0000644005276200011600000000114613702047406024510 0ustar jenkinsjenkins/** * @file * Declares the AIX processor fact resolver. */ #pragma once #include "../posix/processor_resolver.hpp" namespace facter { namespace facts { namespace aix { /** * Responsible for resolving processor-related facts. */ struct processor_resolver : posix::processor_resolver { protected: /** * Collects the resolver data. * @param facts The fact collection that is resolving facts. * @return Returns the resolver data. */ virtual data collect_data(collection& facts) override; }; }}} // namespace facter::facts::aix facter-3.14.12/lib/inc/internal/facts/aix/serial_number_resolver.hpp0000644005276200011600000000125013702047406025314 0ustar jenkinsjenkins/** * @file * Declares the AIX serial number fact resolver. */ #pragma once #include namespace facter { namespace facts { namespace aix { /** * Responsible for resolving serial number fact. */ struct serial_number_resolver : resolver { /* * Constructs the serial_number_resolver. */ serial_number_resolver(); /** * Called to resolve all the facts the resolver is responsible for. * @param facts The fact collection that is resolving facts. */ virtual void resolve(collection& facts) override; }; }}} // namespace facter::facts::aix facter-3.14.12/lib/inc/internal/facts/bsd/0000755005276200011600000000000013702047635020030 5ustar jenkinsjenkinsfacter-3.14.12/lib/inc/internal/facts/bsd/filesystem_resolver.hpp0000644005276200011600000000134313702047406024643 0ustar jenkinsjenkins/** * @file * Declares the BSD file system fact resolver. */ #pragma once #include "../resolvers/filesystem_resolver.hpp" struct statfs; namespace facter { namespace facts { namespace bsd { /** * Responsible for resolving BSD file system facts. */ struct filesystem_resolver : resolvers::filesystem_resolver { protected: /** * Collects the file system data. * @param facts The fact collection that is resolving facts. * @return Returns the file system data. */ virtual data collect_data(collection& facts) override; private: static std::vector to_options(struct statfs const& fs); }; }}} // namespace facter::facts::bsd facter-3.14.12/lib/inc/internal/facts/bsd/networking_resolver.hpp0000644005276200011600000000440713702047406024652 0ustar jenkinsjenkins/** * @file * Declares the BSD networking fact resolver. */ #pragma once #include "../posix/networking_resolver.hpp" #include #include namespace facter { namespace facts { namespace bsd { /** * Responsible for resolving networking facts. */ struct networking_resolver : posix::networking_resolver { protected: /** * Collects the resolver data. * @param facts The fact collection that is resolving facts. * @return Returns the resolver data. */ virtual data collect_data(collection& facts) override; /** * Gets the MTU of the link layer data. * @param interface The name of the link layer interface. * @param data The data pointer from the link layer interface. * @return Returns The MTU of the interface. */ virtual boost::optional get_link_mtu(std::string const& interface, void* data) const = 0; /** * Gets the primary interface. * This is typically the interface of the default route. * @return Returns the primary interface or empty string if one could not be determined. */ virtual std::string get_primary_interface() const; /** * Finds known DHCP servers for all interfaces. * @return Returns a map between interface name and DHCP server. */ virtual std::map find_dhcp_servers() const; /** * Finds the DHCP server for the given interface. * @param interface The interface to find the DHCP server for. * @returns Returns the DHCP server for the interface or empty string if one isn't found. */ virtual std::string find_dhcp_server(std::string const& interface) const; private: void find_dhclient_dhcp_servers(std::map& servers) const; void find_networkd_dhcp_servers(std::map& servers) const; void find_nm_internal_dhcp_servers(std::map& servers) const; void populate_binding(interface& iface, ifaddrs const* addr) const; void populate_mtu(interface& iface, ifaddrs const* addr) const; }; }}} // namespace facter::facts::bsd facter-3.14.12/lib/inc/internal/facts/bsd/uptime_resolver.hpp0000644005276200011600000000101413702047406023755 0ustar jenkinsjenkins/** * @file * Declares the BSD uptime fact resolver. */ #pragma once #include "../posix/uptime_resolver.hpp" namespace facter { namespace facts { namespace bsd { /** * Responsible for resolving uptime facts. */ struct uptime_resolver : posix::uptime_resolver { protected: /** * Gets the system uptime in seconds. * @return Returns the system uptime in seconds. */ virtual int64_t get_uptime() override; }; }}} // namespace facter::facts::bsd facter-3.14.12/lib/inc/internal/facts/cache.hpp0000644005276200011600000000721313702047406021033 0ustar jenkinsjenkins#pragma once #include #include namespace facter { namespace facts { namespace cache { /** * Adds the cached value to the collection if it both exists and * has not expired. Otherwise, resolves the value afresh and caches it. * @param facts the collection of facts to which to add * @param res the resolver that should be cached * @param ttl the duration in seconds for which the cahced value is considered valid */ void use_cache(collection& facts, std::shared_ptr res, int64_t ttl); /** * Checks the given directory for cached facts of the given names. * Each fact found is added to the collection. * @param cache_file the JSON cache file associated with this resolver * @param cached_facts the names of the facts to search for * @param facts to collection of facts to which to add */ void load_facts_from_cache(boost::filesystem::path const& cache_file, std::shared_ptr res, collection& facts); /** * Resolve facts from the given resolver and write them out to the cache, one file per resolver. * @param res the resolver that should be cached * @param cache_file the path to the JSON cache file for this resolver * @param facts the collection of facts to which to add */ void refresh_cache(std::shared_ptr res, boost::filesystem::path const& cache_file, collection& facts); /** * Returns the location of the fact cache directory. * @return the absolute path to the cache directory */ std::string fact_cache_location(); /** * Returns true if the cache has not expired, false otherwise. * @param cache_file the path to the cache file to be verified * @param ttl a duration in seconds representing the time to live for the cache * @return true if cache is expired, false otherwise */ bool cache_is_valid(boost::filesystem::path const& cache_file, int64_t ttl); /** * Creates a cache file for the given fact in JSON format. * @param file_path the path to the cache file * @param fact_name the name of the fact to cache */ void write_json_cache_file(const collection& facts, boost::filesystem::path const& file_path, std::vector const& fact_names); /** * Returns the timespan in seconds since the file was last modified. * @param file_path the path to the file * @return the timespan in seconds since last modification */ int64_t get_file_lifetime(boost::filesystem::path file_path); /** * Removes the cache file for any resolver that does not appear in the * supplied list of fact groups. * @param facts_to_cache the list of fact groups that should be cached * @param cache_location the absolute path to the fact cache directory */ void clean_cache(std::unordered_map const& facts_to_cache, std::string cache_location = fact_cache_location()); /** * Caches the custom facts from cached_facts * @param collection the collection of facts to which to add * @param ttls the duration in seconds for which the cached custom facts file is considered valid */ bool load_cached_custom_facts(collection& collection, int64_t ttl); /** * Creates a cache file for the given custom facts list in JSON format. * @param facts the collection of facts * @param cached_custom_facts_list the name of the facts to cache */ void write_cached_custom_facts(const collection& facts, const std::vector& cached_custom_facts_list); }}} // namespace facter::facts::cache facter-3.14.12/lib/inc/internal/facts/external/0000755005276200011600000000000013702047635021102 5ustar jenkinsjenkinsfacter-3.14.12/lib/inc/internal/facts/external/execution_resolver.hpp0000644005276200011600000000127513702047406025540 0ustar jenkinsjenkins/** * @file * Declares the execution external fact resolver. */ #pragma once #include namespace facter { namespace facts { namespace external { /** * Responsible for resolving facts from executable files. */ struct execution_resolver : resolver { execution_resolver(std::string const &path):resolver(path) {} /** * Resolves facts from the given file. * @param path The path to the file to resolve facts from. * @param facts The fact collection to populate the external facts into. */ virtual void resolve(collection &facts); }; }}} // namespace facter::facts::external facter-3.14.12/lib/inc/internal/facts/external/json_resolver.hpp0000644005276200011600000000125013702047406024477 0ustar jenkinsjenkins/** * @file * Declares the JSON external fact resolver. */ #pragma once #include namespace facter { namespace facts { namespace external { /** * Responsible for resolving facts from JSON files. */ struct json_resolver : resolver { json_resolver(std::string const &path):resolver(path) {} /** * Resolves facts from the given file. * @param path The path to the file to resolve facts from. * @param facts The fact collection to populate the external facts into. */ virtual void resolve(collection& facts); }; }}} // namespace facter::facts::external facter-3.14.12/lib/inc/internal/facts/external/text_resolver.hpp0000644005276200011600000000125013702047406024512 0ustar jenkinsjenkins/** * @file * Declares the text external fact resolver. */ #pragma once #include namespace facter { namespace facts { namespace external { /** * Responsible for resolving facts from text files. */ struct text_resolver : resolver { text_resolver(std::string const &path):resolver(path) {} /** * Resolves facts from the given file. * @param path The path to the file to resolve facts from. * @param facts The fact collection to populate the external facts into. */ virtual void resolve(collection& facts); }; }}} // namespace facter::facts::external facter-3.14.12/lib/inc/internal/facts/external/windows/0000755005276200011600000000000013702047635022574 5ustar jenkinsjenkinsfacter-3.14.12/lib/inc/internal/facts/external/windows/powershell_resolver.hpp0000644005276200011600000000153613702047406027413 0ustar jenkinsjenkins/** * @file * Declares the powershell external fact resolver. */ #ifndef FACTER_FACTS_EXTERNAL_POWERSHELL_RESOLVER_HPP_ #define FACTER_FACTS_EXTERNAL_POWERSHELL_RESOLVER_HPP_ #include namespace facter { namespace facts { namespace external { /** * Responsible for resolving facts from powershell scripts. */ struct powershell_resolver : resolver { powershell_resolver(std::string const &path):resolver(path) {} /** * Resolves facts from the given file. * @param path The path to the file to resolve facts from. * @param facts The fact collection to populate the external facts into. */ virtual void resolve(collection& facts); }; }}} // namespace facter::facts::external #endif // FACTER_FACTS_EXTERNAL_POWERSHELL_RESOLVER_HPP_ facter-3.14.12/lib/inc/internal/facts/external/yaml_resolver.hpp0000644005276200011600000000125013702047406024470 0ustar jenkinsjenkins/** * @file * Declares the YAML external fact resolver. */ #pragma once #include namespace facter { namespace facts { namespace external { /** * Responsible for resolving facts from YAML files. */ struct yaml_resolver : resolver { yaml_resolver(std::string const &path):resolver(path) {} /** * Resolves facts from the given file. * @param path The path to the file to resolve facts from. * @param facts The fact collection to populate the external facts into. */ virtual void resolve(collection& facts); }; }}} // namespace facter::facts::external facter-3.14.12/lib/inc/internal/facts/freebsd/0000755005276200011600000000000013702047635020672 5ustar jenkinsjenkinsfacter-3.14.12/lib/inc/internal/facts/freebsd/disk_resolver.hpp0000644005276200011600000000113113702047406024246 0ustar jenkinsjenkins/** * @file * Declares the FreeBSD disk fact resolver. */ #pragma once #include "../resolvers/disk_resolver.hpp" namespace facter { namespace facts { namespace freebsd { /** * Responsible for resolving disk facts. */ struct disk_resolver : resolvers::disk_resolver { protected: /** * Collects the resolver data. * @param facts The fact collection that is resolving facts. * @return Returns the resolver data. */ virtual data collect_data(collection& facts) override; }; }}} // namespace facter::facts::freebsd facter-3.14.12/lib/inc/internal/facts/freebsd/dmi_resolver.hpp0000644005276200011600000000127413702047406024075 0ustar jenkinsjenkins/** * @file * Declares the FreeBSD Desktop Management Interface (DMI) fact resolver. */ #pragma once #include "../resolvers/dmi_resolver.hpp" namespace facter { namespace facts { namespace freebsd { /** * Responsible for resolving DMI facts. */ struct dmi_resolver : resolvers::dmi_resolver { protected: /** * Collects the resolver data. * @param facts The fact collection that is resolving facts. * @return Returns the resolver data. */ virtual data collect_data(collection& facts) override; private: static std::string kenv_lookup(const char* file); }; }}} // namespace facter::facts::freebsd facter-3.14.12/lib/inc/internal/facts/freebsd/filesystem_resolver.hpp0000644005276200011600000000117313702047406025506 0ustar jenkinsjenkins/** * @file * Declares the FreeBSD file system fact resolver. */ #pragma once #include "../bsd/filesystem_resolver.hpp" namespace facter { namespace facts { namespace freebsd { /** * Responsible for resolving FreeBSD file system facts. */ struct filesystem_resolver : bsd::filesystem_resolver { protected: /** * Collects the file system data. * @param facts The fact collection that is resolving facts. * @return Returns the file system data. */ virtual data collect_data(collection& facts) override; }; }}} // namespace facter::facts::freebsd facter-3.14.12/lib/inc/internal/facts/freebsd/memory_resolver.hpp0000644005276200011600000000113713702047406024632 0ustar jenkinsjenkins/** * @file * Declares the FreeBSD memory fact resolver. */ #pragma once #include "../resolvers/memory_resolver.hpp" namespace facter { namespace facts { namespace freebsd { /** * Responsible for resolving memory facts. */ struct memory_resolver : resolvers::memory_resolver { protected: /** * Collects the resolver data. * @param facts The fact collection that is resolving facts. * @return Returns the resolver data. */ virtual data collect_data(collection& facts) override; }; }}} // namespace facter::facts::osx facter-3.14.12/lib/inc/internal/facts/freebsd/networking_resolver.hpp0000644005276200011600000000333613702047406025514 0ustar jenkinsjenkins/** * @file * Declares the FreeBSD networking fact resolver. */ #pragma once #include "../bsd/networking_resolver.hpp" #include #include namespace facter { namespace facts { namespace freebsd { /** * Responsible for resolving networking facts. */ struct networking_resolver : bsd::networking_resolver { protected: /** * Gets the MTU of the link layer data. * @param interface The name of the link layer interface. * @param data The data pointer from the link layer interface. * @return Returns The MTU of the interface. */ virtual boost::optional get_link_mtu(std::string const& interface, void* data) const override; /** * Determines if the given sock address is a link layer address. * @param addr The socket address to check. * @returns Returns true if the socket address is a link layer address or false if it is not. */ virtual bool is_link_address(sockaddr const* addr) const override; /** * Gets the bytes of the link address. * @param addr The socket address representing the link address. * @return Returns a pointer to the address bytes or nullptr if not a link address. */ virtual uint8_t const* get_link_address_bytes(sockaddr const* addr) const override; /** * Gets the length of the link address. * @param addr The socket address representing the link address. * @return Returns the length of the address or 0 if not a link address. */ virtual uint8_t get_link_address_length(sockaddr const* addr) const override; }; }}} // namespace facter::facts::freebsd facter-3.14.12/lib/inc/internal/facts/freebsd/operating_system_resolver.hpp0000644005276200011600000000126113702047406026714 0ustar jenkinsjenkins/** * @file * Declares the FreeBSD operating system fact resolver. */ #pragma once #include "../posix/operating_system_resolver.hpp" namespace facter { namespace facts { namespace freebsd { /** * Responsible for resolving operating system facts. */ struct operating_system_resolver : posix::operating_system_resolver { protected: /** * Collects the resolver's release data. * @param facts The fact collection that is resolving facts. * @param result The current resolver data. */ virtual void collect_release_data(collection& facts, data& result) override; }; }}} // namespace facter::facts::freebsd facter-3.14.12/lib/inc/internal/facts/freebsd/processor_resolver.hpp0000644005276200011600000000116213702047406025337 0ustar jenkinsjenkins/** * @file * Declares the freebsd processor fact resolver. */ #pragma once #include "../posix/processor_resolver.hpp" namespace facter { namespace facts { namespace freebsd { /** * Responsible for resolving processor-related facts. */ struct processor_resolver : posix::processor_resolver { protected: /** * Collects the resolver data. * @param facts The fact collection that is resolving facts. * @return Returns the resolver data. */ virtual data collect_data(collection& facts) override; }; }}} // namespace facter::facts::freebsd facter-3.14.12/lib/inc/internal/facts/freebsd/virtualization_resolver.hpp0000644005276200011600000000137313702047406026410 0ustar jenkinsjenkins/** * @file * Declares the FreeBSD virtualization fact resolver. */ #pragma once #include "../resolvers/virtualization_resolver.hpp" namespace facter { namespace facts { namespace freebsd { /** * Responsible for resolving virtualization facts. */ struct virtualization_resolver : resolvers::virtualization_resolver { protected: /** * Gets the name of the hypervisor. * @param facts The fact collection that is resolving facts. * @return Returns the name of the hypervisor or empty string if no hypervisor. */ virtual std::string get_hypervisor(collection& facts) override; private: static std::string get_jail_vm(); }; }}} // namespace facter::facts::freebsd facter-3.14.12/lib/inc/internal/facts/freebsd/zfs_resolver.hpp0000644005276200011600000000100113702047406024112 0ustar jenkinsjenkins/** * @file * Declares the ZFS fact resolver. */ #pragma once #include "../resolvers/zfs_resolver.hpp" namespace facter { namespace facts { namespace freebsd { /** * Responsible for resolving ZFS facts. */ struct zfs_resolver : resolvers::zfs_resolver { protected: /** * Gets the platform's ZFS command. * @return Returns the platform's ZFS command. */ virtual std::string zfs_command(); }; }}} // namespace facter::facts::freebsd facter-3.14.12/lib/inc/internal/facts/freebsd/zpool_resolver.hpp0000644005276200011600000000107713702047406024470 0ustar jenkinsjenkins/** * @file * Declares the FreeBSD ZFS storage pool (zpool) fact resolver. */ #pragma once #include "../resolvers/zpool_resolver.hpp" namespace facter { namespace facts { namespace freebsd { /** * Responsible for resolving ZFS storage pool (zpool) facts. */ struct zpool_resolver : resolvers::zpool_resolver { protected: /** * Gets the platform's zpool command. * @return Returns the platform's zpool command. */ virtual std::string zpool_command(); }; }}} // namespace facter::facts::freebsd facter-3.14.12/lib/inc/internal/facts/glib/0000755005276200011600000000000013702047635020175 5ustar jenkinsjenkinsfacter-3.14.12/lib/inc/internal/facts/glib/load_average_resolver.hpp0000644005276200011600000000115713702047406025240 0ustar jenkinsjenkins/** * @file * Declares the glib load average fact resolver. */ #pragma once #include "../resolvers/load_average_resolver.hpp" namespace facter { namespace facts { namespace glib { /** * Responsible for resolving the load average facts. */ struct load_average_resolver : resolvers::load_average_resolver { protected: /** * Gets the load averages (for 1, 5 and 15 minutes period). * @return The load averages. */ virtual boost::optional> get_load_averages() override; }; }}} // namespace facter::facts::glib facter-3.14.12/lib/inc/internal/facts/linux/0000755005276200011600000000000013702047635020417 5ustar jenkinsjenkinsfacter-3.14.12/lib/inc/internal/facts/linux/disk_resolver.hpp0000644005276200011600000000112313702047406023774 0ustar jenkinsjenkins/** * @file * Declares the Linux disk fact resolver. */ #pragma once #include "../resolvers/disk_resolver.hpp" namespace facter { namespace facts { namespace linux { /** * Responsible for resolving disk facts. */ struct disk_resolver : resolvers::disk_resolver { protected: /** * Collects the resolver data. * @param facts The fact collection that is resolving facts. * @return Returns the resolver data. */ virtual data collect_data(collection& facts) override; }; }}} // namespace facter::facts::linux facter-3.14.12/lib/inc/internal/facts/linux/dmi_resolver.hpp0000644005276200011600000000176113702047406023623 0ustar jenkinsjenkins/** * @file * Declares the Linux Desktop Management Information (DMI) fact resolver. */ #pragma once #include "../resolvers/dmi_resolver.hpp" #include namespace facter { namespace facts { namespace linux { /** * Responsible for resolving DMI facts. */ struct dmi_resolver : resolvers::dmi_resolver { protected: /** * Collects the resolver data. * @param facts The fact collection that is resolving facts. * @return Returns the resolver data. */ virtual data collect_data(collection& facts) override; /** * Parses the output of dmidecode. * @param result The resulting data. * @param line The line to parse. * @param dmi_type The current DMI header type. */ static void parse_dmidecode_output(data& result, std::string& line, int& dmi_type); private: std::string read(std::string const& path); }; }}} // namespace facter::facts::linux facter-3.14.12/lib/inc/internal/facts/linux/filesystem_resolver.hpp0000644005276200011600000000252613702047406025236 0ustar jenkinsjenkins/** * @file * Declares the Linux file system fact resolver. */ #pragma once #include "../resolvers/filesystem_resolver.hpp" #include namespace facter { namespace facts { namespace linux { /** * Responsible for resolving Linux file system facts. */ struct filesystem_resolver : resolvers::filesystem_resolver { /** * Converts a string using the same format as blkid's "safe_print" function. * The format uses M-\ (higher than 128) and ^\ (control character), while escaping quotes and backslashes. * @param value The value to convert. * @return Returns the converted value. */ static std::string safe_convert(char const* value); protected: /** * Collects the DMI data. * @param facts The fact collection that is resolving facts. * @return Returns the DMI data. */ virtual data collect_data(collection& facts) override; private: void collect_mountpoint_data(data& result); void collect_filesystem_data(data& result); void collect_partition_data(data& result); void populate_partition_attributes(partition& part, std::string const& device_directory, void* cache, std::map const& mountpoints); }; }}} // namespace facter::facts::linux facter-3.14.12/lib/inc/internal/facts/linux/fips_resolver.hpp0000644005276200011600000000144213702047406024007 0ustar jenkinsjenkins/** * @file * Declares the Linux fips fact resolver. */ #pragma once #include "../resolvers/fips_resolver.hpp" namespace facter { namespace facts { namespace linux { /** * Responsible for resolving fips-related facts. */ struct fips_resolver : resolvers::fips_resolver { protected: /** * The check consists of the following. * (1) Examining the contents of /proc/sys/crypto/fips_enabled. If it is 1 * then fips mode is enabled. */ /** * Collects the resolver data. * @param facts The fact collection that is resolving facts. * @return Returns the resolver data. */ virtual data collect_data(collection& facts) override; }; }}} // namespace facter::facts::linux facter-3.14.12/lib/inc/internal/facts/linux/kernel_resolver.hpp0000644005276200011600000000121213702047406024321 0ustar jenkinsjenkins/** * @file * Declares the Linux kernel fact resolver. */ #pragma once #include "../posix/kernel_resolver.hpp" namespace facter { namespace facts { namespace linux { /** * Responsible for resolving kernel facts. */ struct kernel_resolver : posix::kernel_resolver { protected: /** * Parses the major and minor kernel versions. * @param version The version to parse. * @return Returns a tuple of major and minor versions. */ std::tuple parse_version(std::string const& version) const override; }; }}} // namespace facter::facts::linux facter-3.14.12/lib/inc/internal/facts/linux/memory_resolver.hpp0000644005276200011600000000113513702047406024355 0ustar jenkinsjenkins/** * @file * Declares the Linux memory fact resolver. */ #pragma once #include "../resolvers/memory_resolver.hpp" namespace facter { namespace facts { namespace linux { /** * Responsible for resolving memory facts. */ struct memory_resolver : resolvers::memory_resolver { protected: /** * Collects the resolver data. * @param facts The fact collection that is resolving facts. * @return Returns the resolver data. */ virtual data collect_data(collection& facts) override; }; }}} // namespace facter::facts::linux facter-3.14.12/lib/inc/internal/facts/linux/networking_resolver.hpp0000644005276200011600000000627213702047406025243 0ustar jenkinsjenkins/** * @file * Declares the Linux networking fact resolver. */ #pragma once #include "../bsd/networking_resolver.hpp" namespace facter { namespace facts { namespace linux { /** * Responsible for resolving networking facts. * * The Linux networking_resolver inherits from the BSD networking_resolver. * This is because getifaddrs is a BSD concept that was implemented in Linux. * The only thing this resolver is responsible for is handing link-level * addressing and MTU. */ struct networking_resolver : bsd::networking_resolver { protected: /** * Collects the resolver data. * @param facts The fact collection that is resolving facts. * @return Returns the resolver data. */ virtual data collect_data(collection& facts) override; /** * Determines if the given sock address is a link layer address. * @param addr The socket address to check. * @returns Returns true if the socket address is a link layer address or false if it is not. */ virtual bool is_link_address(sockaddr const* addr) const override; /** * Gets the bytes of the link address. * @param addr The socket address representing the link address. * @return Returns a pointer to the address bytes or nullptr if not a link address. */ virtual uint8_t const* get_link_address_bytes(sockaddr const* addr) const override; /** * Gets the length of the link address. * @param addr The socket address representing the link address. * @return Returns the length of the address or 0 if not a link address. */ virtual uint8_t get_link_address_length(sockaddr const* addr) const override; /** * Gets the MTU of the link layer data. * @param interface The name of the link layer interface. * @param data The data pointer from the link layer interface. * @return Returns The MTU of the interface or -1 if there's no MTU. */ virtual boost::optional get_link_mtu(std::string const& interface, void* data) const override; /** * Gets the primary interface. * This is typically the interface of the default route. * @return Returns the primary interface or empty string if one could not be determined. */ virtual std::string get_primary_interface() const override; private: struct route { // In actuality routes are a destination associated with a // bunch of key-value pairs, but we only require a couple // of those values for our processing of network devices. std::string destination; std::string interface; std::string source; }; void read_routing_table(); void populate_from_routing_table(data&) const; template void associate_src_with_iface(const route&, data&, appender) const; std::string get_bond_master(const std::string& name) const; std::vector routes4; std::vector routes6; }; }}} // namespace facter::facts::linux facter-3.14.12/lib/inc/internal/facts/linux/operating_system_resolver.hpp0000644005276200011600000000131213702047406026436 0ustar jenkinsjenkins/** * @file * Declares the Linux operating system fact resolver. */ #pragma once #include "../posix/operating_system_resolver.hpp" namespace facter { namespace facts { namespace linux { /** * Responsible for resolving operating system facts. */ struct operating_system_resolver : posix::operating_system_resolver { protected: /** * Collects the resolver data. * @param facts The fact collection that is resolving facts. * @return Returns the resolver data. */ virtual data collect_data(collection& facts) override; private: static selinux_data collect_selinux_data(); }; }}} // namespace facter::facts::linux facter-3.14.12/lib/inc/internal/facts/linux/os_cisco.hpp0000644005276200011600000001105213702047406022724 0ustar jenkinsjenkins/** * @file * Declares the Cisco Linux operating system query helper. */ #pragma once #include namespace facter { namespace facts { namespace linux { /** * Responsible for determining the name/family/release of Cisco operating systems. */ struct os_cisco : os_linux { /** * Constructs the os_cisco and reads a release file to gather relevant details. * @param file The release file to read for Cisco-specific OS data. */ os_cisco(std::string const& file) : os_linux({"ID", "ID_LIKE", "VERSION"}, file) {} /** * Finds ID from the release file contents and returns it as the name. * @param distro_id Unused. * @return Returns the release name. */ virtual std::string get_name(std::string const& distro_id) const override { auto val = _release_info.find("ID"); return (val != _release_info.end()) ? val->second : std::string(); } /** * Finds ID_LIKE from the release file contents and returns it as the family. * @param name Unused. * @return Returns the release family. */ virtual std::string get_family(std::string const& name) const override { /* * This benefits from some explanation. * Some Cisco platforms have multiple runtime environments. * For these platforms, the name reports as the same regardless of * the environment (e.g., "nexus"), but we want the family to report * appropriately according to the environment (e.g., "cisco-wrlinux" * versus "RedHat"). * * In order to achieve this goal, we first check to see what would * be reported if we were a standard Linux environment (e.g., a * Linux distro that detects its name as "centos" would map to * family "RedHat"). Only if a standard Linux family is not * detected do we fall back on the information given in our Cisco * release info file. */ auto value = os_linux::get_family(os_linux::get_name("")); if (!value.empty()) { return value; } auto val = _release_info.find("ID_LIKE"); if (val != _release_info.end()) { auto& family = val->second; auto pos = family.find(" "); // If multiple values are found in ID_LIKE, only return the // first one (FACT-1246) if (pos != std::string::npos) { return family.substr(0, pos); } return family; } return std::string(); } /** * Finds VERSION from the release file contents and returns it as the release. * @param name Unused. * @param distro_release Unused. * @return Returns the release version. */ virtual std::string get_release(std::string const& name, std::string const& distro_release) const override { auto val = _release_info.find("VERSION"); return (val != _release_info.end()) ? val->second : std::string(); } /** * Parses the release version string to return the major version. * @param name Unused. * @param release The release version determined using get_release. * @return Returns a tuple of the major and minor versions. */ virtual std::tuple parse_release(std::string const& name, std::string const& release) const override { /* * Cisco software versions can be idiosyncratic. * NX-OS looks something like '7.0(3)I2(0.455)' * IOS XR looks something like '6.0.0.06I' */ auto pos = release.find('.'); if (pos != std::string::npos) { auto second = release.find('(', pos + 1); if (second == std::string::npos) { second = release.find('.', pos + 1); } if (second == std::string::npos) { return std::make_tuple(release.substr(0, pos), std::string()); } return std::make_tuple(release.substr(0, pos), release.substr(pos + 1, second - (pos + 1))); } return std::make_tuple(release, std::string()); } }; }}} // namespace facter::facts::linux facter-3.14.12/lib/inc/internal/facts/linux/os_linux.hpp0000644005276200011600000000542413702047406022771 0ustar jenkinsjenkins/** * @file * Declares the generic Linux operating system query helper. */ #pragma once #include #include #include #include #include namespace facter { namespace facts { namespace linux { /** * Responsible for determining the name/family/release of common operating systems. */ struct os_linux { /** * Constructs the os_linux. * @param items Items to read from the release file; used by inheriting classes. * @param file The release file to read for OS data; used by inheriting classes. */ os_linux(std::set items = {}, std::string file = release_file::os); /** * Returns the name of the operating system. * @param distro_id The distro ID; can be queried as the "Distributor ID" given by lsb_release. * @return Returns the release name. */ virtual std::string get_name(std::string const& distro_id) const; /** * Returns the family of the operating system. * @param name The release name determined using get_name. * @return Returns the release family. */ virtual std::string get_family(std::string const& name) const; /** * Returns the release of the operating system. * @param name The release name determined using get_name. * @param distro_release The distro release; can be queried as the "Release" given by lsb_release. * @return Returns the release version. */ virtual std::string get_release(std::string const& name, std::string const& distro_release) const; /** * Parses the release version string to return the major version. * @param name The release name determined using get_name. * @param release The release version determined using get_release. * @return Returns a tuple of the major and minor versions. */ virtual std::tuple parse_release(std::string const& name, std::string const& release) const; /** * Parses a file containing key-value pairs separated by an equal (=) sign, one pair per line. * @param file The file to parse. * @param items The keys to save from the file. Only keys given in this parameter will be returned. * @return The key-value pairs identified in the items argument and found in the file. */ static std::map key_value_file(std::string file, std::set const& items); protected: /** * A map of key-value pairs read from the release file. */ std::map _release_info; }; }}} // namespace facter::facts::linux facter-3.14.12/lib/inc/internal/facts/linux/os_osrelease.hpp0000644005276200011600000000722413702047406023614 0ustar jenkinsjenkins/** * @file * Declares the Linux operating system query helper based on /etc/os-release. */ #pragma once #include #include #include #include #include using namespace std; namespace facter { namespace facts { namespace linux { /** * Responsible for determining the name/family/release of Freedesktop-compliant operating systems. */ struct os_osrelease : os_linux { /** * Constructs os_release based on details from /etc/os-release. */ os_osrelease() : os_linux({"ID", "VERSION_ID"}) {} /** * Returns the release name based on the ID field from /etc/os-release * (which has fewer variations to check for than the NAME field) * @param distro_id Unused. * @return Returns the OS name. */ virtual std::string get_name(std::string const& distro_id) const override { auto val = _release_info.find("ID"); if (val != _release_info.end()) { auto& id = val->second; if (id == "coreos") { return os::coreos; } else if (id == "cumulus-linux") { return os::cumulus; } else if (id == "opensuse" || id == "opensuse-leap") { return os::open_suse; } else if (id == "sled") { return os::suse_enterprise_desktop; } else if (id == "sles") { return os::suse_enterprise_server; } else if (id == "ubuntu") { return os::ubuntu; } } return std::string(); } /** * Returns the release family based on the ID field from /etc/os-release * (which has fewer variations to check for than the NAME field) * @param name Unused. * @return Returns the OS family. */ virtual std::string get_family(std::string const& name) const override { auto val = _release_info.find("ID"); if (val != _release_info.end()) { auto& id = val->second; if (id == "coreos") { return os_family::coreos; } else if (id == "cumulus-linux") { return os_family::debian; } else if (id == "opensuse" || id == "opensuse-leap" || id == "sled" || id == "sles") { return os_family::suse; } else if (id == "ubuntu") { return os_family::debian; } } return std::string(); } /** * Returns the OS release version based on the VERSION_ID field from /etc/os-release. * @param name Unused. * @param distro_release Unused. * @return Returns the release version. */ virtual std::string get_release(std::string const& name, std::string const& distro_release) const override { auto val = _release_info.find("VERSION_ID"); if (val != _release_info.end()) { if (boost::regex_match(val->second, boost::regex("^\\d+$"))) { // FACT-1880: when VERSION_ID doesn't specify a point-release, // return the major version with ".0" appended so that // os.release.minor always returns a value. return val->second + ".0"; } return val->second; } return std::string(); } }; }}} // namespace facter::facts::linux facter-3.14.12/lib/inc/internal/facts/linux/processor_resolver.hpp0000644005276200011600000000410013702047406025057 0ustar jenkinsjenkins/** * @file * Declares the Linux processor fact resolver. */ #pragma once #include "../posix/processor_resolver.hpp" #include namespace facter { namespace facts { namespace linux { /** * Responsible for resolving processor-related facts. */ struct processor_resolver : posix::processor_resolver { protected: /** * The architecture type of the linux machine. */ enum class ArchitectureType {POWER, X86}; /** * The check consists of the following. * (1) Check the previously computed isa fact. If it starts with * ppc64, then we have a power machine. * * (2) If (1) is empty (possible because exec might have failed to obtain * the isa fact), then we use /proc/cpuinfo by checking whether that file * contains the "cpu", "clock", and "revision" keys -- these keys are only * found in Power machines. * * @param data The currently collected data * @param root Path to the root directory of the system * @return Returns the architecture type of the machine */ ArchitectureType architecture_type(data const& data, std::string const& root); /** * Adds the cpu-specific data to the currently collected data. * @param data The currently collected data * @param root Path to the root directory of the system */ void add_cpu_data(data& data, std::string const& root = ""); /** * Collects the resolver data. * @param facts The fact collection that is resolving facts. * @return Returns the resolver data. */ virtual data collect_data(collection& facts) override; private: void maybe_add_speed(data& data, std::string const& speed); bool compute_cpu_counts(data& data, std::string const& root, std::function is_valid_id); bool add_x86_cpu_data(data& data, std::string const& root = ""); bool add_power_cpu_data(data& data, std::string const& root = ""); }; }}} // namespace facter::facts::linux facter-3.14.12/lib/inc/internal/facts/linux/release_file.hpp0000644005276200011600000000753113702047406023551 0ustar jenkinsjenkins/** * @file * Declares the Linux release file constants. */ #pragma once namespace facter { namespace facts { namespace linux { /** * Stores the constant release file names. */ struct release_file { /** * Release file for RedHat Linux. */ constexpr static char const* redhat = "/etc/redhat-release"; /** * Release file for Fedora. */ constexpr static char const* fedora = "/etc/fedora-release"; /** * Release file for Meego. */ constexpr static char const* meego = "/etc/meego-release"; /** * Release file for Oracle Linux. */ constexpr static char const* oracle_linux = "/etc/oracle-release"; /** * Release file for Oracle Enterprise Linux. */ constexpr static char const* oracle_enterprise_linux = "/etc/enterprise-release"; /** * Release file for Oracle VM Linux. */ constexpr static char const* oracle_vm_linux = "/etc/ovs-release"; /** * Version file for Debian Linux. */ constexpr static char const* debian = "/etc/debian_version"; /** * Version file for Devuan Linux. */ constexpr static char const* devuan = "/etc/devuan_version"; /** * Release file for Alpine Linux. */ constexpr static char const* alpine = "/etc/alpine-release"; /** * Release file for SuSE Linux. */ constexpr static char const* suse = "/etc/SuSE-release"; /** * Release file for generic Linux distros. * Also used for: * - Cisco * - CoreOS * - Cumulus */ constexpr static char const* os = "/etc/os-release"; /** * Release file for LSB distros. */ constexpr static char const* lsb = "/etc/lsb-release"; /** * Release file for Gentoo Linux. */ constexpr static char const* gentoo = "/etc/gentoo-release"; /** * Release file for Open WRT. */ constexpr static char const* openwrt = "/etc/openwrt_release"; /** * Version file for Open WRT. */ constexpr static char const* openwrt_version = "/etc/openwrt_version"; /** * Release file for Mandriva Linux. */ constexpr static char const* mandriva = "/etc/mandriva-release"; /** * Release file for Mandrake Linux. */ constexpr static char const* mandrake = "/etc/mandrake-release"; /** * Release file for Archlinux. */ constexpr static char const* archlinux = "/etc/arch-release"; /** * Release file for Manjaro Linux. */ constexpr static char const* manjarolinux = "/etc/manjaro-release"; /** * Release file for VMWare ESX Linux. */ constexpr static char const* vmware_esx = "/etc/vmware-release"; /** * Version file for Slackware Linux. */ constexpr static char const* slackware = "/etc/slackware-version"; /** * Release file for Mageia Linux. */ constexpr static char const* mageia = "/etc/mageia-release"; /** * Release file for Amazon Linux. */ constexpr static char const* amazon = "/etc/system-release"; /** * Release file for Mint Linux. */ constexpr static char const* linux_mint_info = "/etc/linuxmint/info"; /** * Release file for AristaEOS. */ constexpr static char const* arista_eos = "/etc/Eos-release"; /** * Release file for HuaweiOS. */ constexpr static char const* huawei = "/etc/huawei-release"; }; }}} // namespace facter::facts::linux facter-3.14.12/lib/inc/internal/facts/linux/uptime_resolver.hpp0000644005276200011600000000102213702047406024343 0ustar jenkinsjenkins/** * @file * Declares the Linux uptime fact resolver. */ #pragma once #include "../posix/uptime_resolver.hpp" namespace facter { namespace facts { namespace linux { /** * Responsible for resolving uptime facts. */ struct uptime_resolver : posix::uptime_resolver { protected: /** * Gets the system uptime in seconds. * @return Returns the system uptime in seconds. */ virtual int64_t get_uptime() override; }; }}} // namespace facter::facts::linux facter-3.14.12/lib/inc/internal/facts/linux/virtualization_resolver.hpp0000644005276200011600000000360613702047406026136 0ustar jenkinsjenkins/** * @file * Declares the Linux virtualization fact resolver. */ #pragma once #include "../resolvers/virtualization_resolver.hpp" #include namespace facter { namespace facts { namespace linux { /** * Responsible for resolving virtualization facts. */ struct virtualization_resolver : resolvers::virtualization_resolver { protected: /** * Gets the name of the hypervisor. * @param facts The fact collection that is resolving facts. * @return Returns the name of the hypervisor or empty string if no hypervisor. */ std::string get_hypervisor(collection& facts) override; /** * Gets the name of the cloud provider. * @param facts The fact collection that is resolving facts. * @return Returns the name of the cloud provider or empty string if no hypervisor. */ std::string get_cloud_provider(collection& facts) override; /** * Gets whether the machine is running in Azure. * @return Returns "azure" if running on azure, otherwise an empty string. */ static std::string get_azure(); /** * Checks whether the azure dhcp option (245) is present in leases_file file. * @param leases_file The file containing leases information. * @return Returns "azure" if found, otherwise an empty string. */ static std::string get_azure_from_leases_file(std::string leases_file); private: static std::string get_cgroup_vm(); static std::string get_gce_vm(collection& facts); static std::string get_what_vm(); static std::string get_vserver_vm(); static std::string get_vmware_vm(); static std::string get_openvz_vm(); static std::string get_xen_vm(); static std::string get_lspci_vm(); }; }}} // namespace facter::facts::linux facter-3.14.12/lib/inc/internal/facts/openbsd/0000755005276200011600000000000013702047635020712 5ustar jenkinsjenkinsfacter-3.14.12/lib/inc/internal/facts/openbsd/dmi_resolver.hpp0000644005276200011600000000125613702047406024115 0ustar jenkinsjenkins/** * @file * Declares the OpenBSD Desktop Management Interface (DMI) fact resolver. */ #pragma once #include "../resolvers/dmi_resolver.hpp" namespace facter { namespace facts { namespace openbsd { /** * Responsible for resolving DMI facts. */ struct dmi_resolver : resolvers::dmi_resolver { protected: /** * Collects the resolver data. * @param facts The fact collection that is resolving facts. * @return Returns the resolver data. */ virtual data collect_data(collection& facts) override; private: std::string sysctl_lookup(int mib); }; }}} // namespace facter::facts::openbsd facter-3.14.12/lib/inc/internal/facts/openbsd/memory_resolver.hpp0000644005276200011600000000113713702047406024652 0ustar jenkinsjenkins/** * @file * Declares the OpenBSD memory fact resolver. */ #pragma once #include "../resolvers/memory_resolver.hpp" namespace facter { namespace facts { namespace openbsd { /** * Responsible for resolving memory facts. */ struct memory_resolver : resolvers::memory_resolver { protected: /** * Collects the resolver data. * @param facts The fact collection that is resolving facts. * @return Returns the resolver data. */ virtual data collect_data(collection& facts) override; }; }}} // namespace facter::facts::osx facter-3.14.12/lib/inc/internal/facts/openbsd/networking_resolver.hpp0000644005276200011600000000333613702047406025534 0ustar jenkinsjenkins/** * @file * Declares the OpenBSD networking fact resolver. */ #pragma once #include "../bsd/networking_resolver.hpp" #include #include namespace facter { namespace facts { namespace openbsd { /** * Responsible for resolving networking facts. */ struct networking_resolver : bsd::networking_resolver { protected: /** * Gets the MTU of the link layer data. * @param interface The name of the link layer interface. * @param data The data pointer from the link layer interface. * @return Returns The MTU of the interface. */ virtual boost::optional get_link_mtu(std::string const& interface, void* data) const override; /** * Determines if the given sock address is a link layer address. * @param addr The socket address to check. * @returns Returns true if the socket address is a link layer address or false if it is not. */ virtual bool is_link_address(sockaddr const* addr) const override; /** * Gets the bytes of the link address. * @param addr The socket address representing the link address. * @return Returns a pointer to the address bytes or nullptr if not a link address. */ virtual uint8_t const* get_link_address_bytes(sockaddr const* addr) const override; /** * Gets the length of the link address. * @param addr The socket address representing the link address. * @return Returns the length of the address or 0 if not a link address. */ virtual uint8_t get_link_address_length(sockaddr const* addr) const override; }; }}} // namespace facter::facts::openbsd facter-3.14.12/lib/inc/internal/facts/openbsd/processor_resolver.hpp0000644005276200011600000000116213702047406025357 0ustar jenkinsjenkins/** * @file * Declares the OpenBSD processor fact resolver. */ #pragma once #include "../posix/processor_resolver.hpp" namespace facter { namespace facts { namespace openbsd { /** * Responsible for resolving processor-related facts. */ struct processor_resolver : posix::processor_resolver { protected: /** * Collects the resolver data. * @param facts The fact collection that is resolving facts. * @return Returns the resolver data. */ virtual data collect_data(collection& facts) override; }; }}} // namespace facter::facts::openbsd facter-3.14.12/lib/inc/internal/facts/openbsd/virtualization_resolver.hpp0000644005276200011600000000130313702047406026421 0ustar jenkinsjenkins/** * @file * Declares the OpenBSD virtualization fact resolver. */ #pragma once #include "../resolvers/virtualization_resolver.hpp" namespace facter { namespace facts { namespace openbsd { /** * Responsible for resolving virtualization facts. */ struct virtualization_resolver : resolvers::virtualization_resolver { protected: /** * Gets the name of the hypervisor. * @param facts The fact collection that is resolving facts. * @return Returns the name of the hypervisor or empty string if no hypervisor. */ virtual std::string get_hypervisor(collection& facts) override; }; }}} // namespace facter::facts::openbsd facter-3.14.12/lib/inc/internal/facts/osx/0000755005276200011600000000000013702047635020071 5ustar jenkinsjenkinsfacter-3.14.12/lib/inc/internal/facts/osx/dmi_resolver.hpp0000644005276200011600000000114713702047406023273 0ustar jenkinsjenkins/** * @file * Declares the OSX Desktop Management Interface (DMI) fact resolver. */ #pragma once #include "../resolvers/dmi_resolver.hpp" namespace facter { namespace facts { namespace osx { /** * Responsible for resolving DMI facts. */ struct dmi_resolver : resolvers::dmi_resolver { protected: /** * Collects the resolver data. * @param facts The fact collection that is resolving facts. * @return Returns the resolver data. */ virtual data collect_data(collection& facts) override; }; }}} // namespace facter::facts::osx facter-3.14.12/lib/inc/internal/facts/osx/memory_resolver.hpp0000644005276200011600000000112713702047406024030 0ustar jenkinsjenkins/** * @file * Declares the OSX memory fact resolver. */ #pragma once #include "../resolvers/memory_resolver.hpp" namespace facter { namespace facts { namespace osx { /** * Responsible for resolving memory facts. */ struct memory_resolver : resolvers::memory_resolver { protected: /** * Collects the resolver data. * @param facts The fact collection that is resolving facts. * @return Returns the resolver data. */ virtual data collect_data(collection& facts) override; }; }}} // namespace facter::facts::osx facter-3.14.12/lib/inc/internal/facts/osx/networking_resolver.hpp0000644005276200011600000000506413702047406024713 0ustar jenkinsjenkins/** * @file * Declares the OSX networking fact resolver. */ #pragma once #include "../bsd/networking_resolver.hpp" namespace facter { namespace facts { namespace osx { /** * Responsible for resolving networking facts. */ struct networking_resolver : bsd::networking_resolver { protected: /** * Determines if the given sock address is a link layer address. * @param addr The socket address to check. * @returns Returns true if the socket address is a link layer address or false if it is not. */ virtual bool is_link_address(sockaddr const* addr) const override; /** * Gets the bytes of the link address. * @param addr The socket address representing the link address. * @return Returns a pointer to the address bytes or nullptr if not a link address. */ virtual uint8_t const* get_link_address_bytes(sockaddr const* addr) const override; /** * Gets the length of the link address. * @param addr The socket address representing the link address. * @return Returns the length of the address or 0 if not a link address. */ virtual uint8_t get_link_address_length(sockaddr const* addr) const override; /** * Gets the MTU of the link layer data. * @param interface The name of the link layer interface. * @param data The data pointer from the link layer interface. * @return Returns The MTU of the interface or -1 if there's no MTU. */ virtual boost::optional get_link_mtu(std::string const& interface, void* data) const override; /** * Gets the primary interface. * This is typically the interface of the default route. * @return Returns the primary interface or empty string if one could not be determined. */ virtual std::string get_primary_interface() const override; /** * Finds known DHCP servers for all interfaces. * @return Returns a map between interface name and DHCP server. */ virtual std::map find_dhcp_servers() const override; /** * Finds the DHCP server for the given interface. * @param interface The interface to find the DHCP server for. * @returns Returns the DHCP server for the interface or empty string if one isn't found. */ virtual std::string find_dhcp_server(std::string const& interface) const override; }; }}} // namespace facter::facts::osx facter-3.14.12/lib/inc/internal/facts/osx/operating_system_resolver.hpp0000644005276200011600000000120113702047406026105 0ustar jenkinsjenkins/** * @file * Declares the OSX operating system fact resolver. */ #pragma once #include "../posix/operating_system_resolver.hpp" namespace facter { namespace facts { namespace osx { /** * Responsible for resolving operating system facts. */ struct operating_system_resolver : posix::operating_system_resolver { protected: /** * Collects the resolver data. * @param facts The fact collection that is resolving facts. * @return Returns the resolver data. */ virtual data collect_data(collection& facts) override; }; }}} // namespace facter::facts::osx facter-3.14.12/lib/inc/internal/facts/osx/processor_resolver.hpp0000644005276200011600000000114613702047406024540 0ustar jenkinsjenkins/** * @file * Declares the OSX processor fact resolver. */ #pragma once #include "../posix/processor_resolver.hpp" namespace facter { namespace facts { namespace osx { /** * Responsible for resolving processor-related facts. */ struct processor_resolver : posix::processor_resolver { protected: /** * Collects the resolver data. * @param facts The fact collection that is resolving facts. * @return Returns the resolver data. */ virtual data collect_data(collection& facts) override; }; }}} // namespace facter::facts::osx facter-3.14.12/lib/inc/internal/facts/osx/system_profiler_resolver.hpp0000644005276200011600000000120013702047406025736 0ustar jenkinsjenkins/** * @file * Declares the system profiler fact resolver. */ #pragma once #include "../resolvers/system_profiler_resolver.hpp" namespace facter { namespace facts { namespace osx { /** * Responsible for resolving system profiler facts. */ struct system_profiler_resolver : resolvers::system_profiler_resolver { protected: /** * Collects the resolver data. * @param facts The fact collection that is resolving facts. * @return Returns the resolver data. */ virtual data collect_data(collection& facts) override; }; }}} // namespace facter::facts::osx facter-3.14.12/lib/inc/internal/facts/osx/virtualization_resolver.hpp0000644005276200011600000000126713702047406025611 0ustar jenkinsjenkins/** * @file * Declares the OSX virtualization fact resolver. */ #pragma once #include "../resolvers/virtualization_resolver.hpp" namespace facter { namespace facts { namespace osx { /** * Responsible for resolving virtualization facts. */ struct virtualization_resolver : resolvers::virtualization_resolver { protected: /** * Gets the name of the hypervisor. * @param facts The fact collection that is resolving facts. * @return Returns the name of the hypervisor or empty string if no hypervisor. */ virtual std::string get_hypervisor(collection& facts) override; }; }}} // namespace facter::facts::osx facter-3.14.12/lib/inc/internal/facts/posix/0000755005276200011600000000000013702047635020422 5ustar jenkinsjenkinsfacter-3.14.12/lib/inc/internal/facts/posix/identity_resolver.hpp0000644005276200011600000000116213702047406024701 0ustar jenkinsjenkins/** * @file * Declares the POSIX user and group resolver. */ #pragma once #include "../resolvers/identity_resolver.hpp" namespace facter { namespace facts { namespace posix { /** * Responsible for resolving the user and group facts. */ struct identity_resolver : resolvers::identity_resolver { protected: /** * Collects the resolver data. * @param facts The fact collection that is resolving facts. * @return Returns the resolver data. */ virtual data collect_data(collection& facts) override; }; }}} // namespace facter::facts::posix facter-3.14.12/lib/inc/internal/facts/posix/kernel_resolver.hpp0000644005276200011600000000113513702047406024330 0ustar jenkinsjenkins/** * @file * Declares the POSIX kernel fact resolver. */ #pragma once #include "../resolvers/kernel_resolver.hpp" namespace facter { namespace facts { namespace posix { /** * Responsible for resolving kernel facts. */ struct kernel_resolver : resolvers::kernel_resolver { protected: /** * Collects the resolver data. * @param facts The fact collection that is resolving facts. * @return Returns the resolver data. */ virtual data collect_data(collection& facts) override; }; }}} // namespace facter::facts::posix facter-3.14.12/lib/inc/internal/facts/posix/networking_resolver.hpp0000644005276200011600000000401013702047406025232 0ustar jenkinsjenkins/** * @file * Declares the POSIX networking fact resolver. */ #pragma once #include "../resolvers/networking_resolver.hpp" #include namespace facter { namespace facts { namespace posix { /** * Responsible for resolving networking facts. */ struct networking_resolver : resolvers::networking_resolver { /** * Utility function to convert a socket address to a IPv4 or IPv6 string representation. * @param addr The socket address to convert to a string. * @param mask The mask to apply to the address. * @return Returns the IPv4 or IPv6 representation or an empty string if the family isn't supported. */ std::string address_to_string(sockaddr const* addr, sockaddr const* mask = nullptr) const; protected: /** * Determines if the given sock address is a link layer address. * @param addr The socket address to check. * @returns Returns true if the socket address is a link layer address or false if it is not. */ virtual bool is_link_address(sockaddr const* addr) const = 0; /** * Gets the bytes of the link address. * @param addr The socket address representing the link address. * @return Returns a pointer to the address bytes or nullptr if not a link address. */ virtual uint8_t const* get_link_address_bytes(sockaddr const* addr) const = 0; /** * Gets the length of the link address. * @param addr The socket address representing the link address. * @return Returns the length of the address or 0 if not a link address. */ virtual uint8_t get_link_address_length(sockaddr const* addr) const = 0; /** * Collects the resolver data. * @param facts The fact collection that is resolving facts. * @return Returns the resolver data. */ virtual data collect_data(collection& facts) override; }; }}} // namespace facter::facts::posix facter-3.14.12/lib/inc/internal/facts/posix/operating_system_resolver.hpp0000644005276200011600000000121713702047406026445 0ustar jenkinsjenkins/** * @file * Declares the POSIX operating system fact resolver. */ #pragma once #include "../resolvers/operating_system_resolver.hpp" namespace facter { namespace facts { namespace posix { /** * Responsible for resolving operating system facts. */ struct operating_system_resolver : resolvers::operating_system_resolver { protected: /** * Collects the resolver data. * @param facts The fact collection that is resolving facts. * @return Returns the resolver data. */ virtual data collect_data(collection& facts) override; }; }}} // namespace facter::facts::posix facter-3.14.12/lib/inc/internal/facts/posix/processor_resolver.hpp0000644005276200011600000000116413702047406025071 0ustar jenkinsjenkins/** * @file * Declares the POSIX processor fact resolver. */ #pragma once #include "../resolvers/processor_resolver.hpp" namespace facter { namespace facts { namespace posix { /** * Responsible for resolving processor-related facts. */ struct processor_resolver : resolvers::processor_resolver { protected: /** * Collects the resolver data. * @param facts The fact collection that is resolving facts. * @return Returns the resolver data. */ virtual data collect_data(collection& facts) override; }; }}} // namespace facter::facts::posix facter-3.14.12/lib/inc/internal/facts/posix/timezone_resolver.hpp0000644005276200011600000000103113702047406024675 0ustar jenkinsjenkins/** * @file * Declares the POSIX timezone fact resolver. */ #pragma once #include "../resolvers/timezone_resolver.hpp" namespace facter { namespace facts { namespace posix { /** * Responsible for resolving time zone facts. */ struct timezone_resolver : resolvers::timezone_resolver { protected: /** * Gets the system timezone. * @return Returns the system timezone. */ virtual std::string get_timezone() override; }; }}} // namespace facter::facts::posix facter-3.14.12/lib/inc/internal/facts/posix/uptime_resolver.hpp0000644005276200011600000000150613702047406024355 0ustar jenkinsjenkins/** * @file * Declares the POSIX uptime fact resolver. */ #pragma once #include "../resolvers/uptime_resolver.hpp" #include namespace facter { namespace facts { namespace posix { /** * Responsible for resolving uptime facts. */ struct uptime_resolver : resolvers::uptime_resolver { /** * Utility function to parse the output of the uptime executable. * @param output The output of the uptime executable. * @return Returns the number of uptime seconds. */ static int64_t parse_uptime(std::string const& output); protected: /** * Gets the system uptime in seconds. * @return Returns the system uptime in seconds. */ virtual int64_t get_uptime() override; }; }}} // namespace facter::facts::posix facter-3.14.12/lib/inc/internal/facts/posix/xen_resolver.hpp0000644005276200011600000000103213702047406023636 0ustar jenkinsjenkins/** * @file * Declares the Xen fact resolver on POSIX systems. */ #pragma once #include namespace facter { namespace facts { namespace posix { /** * Responsible for resolving Xen facts. */ struct xen_resolver : resolvers::xen_resolver { protected: /** * Gets the Xen management command. * @return Returns the Xen management command. */ virtual std::string xen_command(); }; }}} // namespace facter::facts::posix facter-3.14.12/lib/inc/internal/facts/resolvers/0000755005276200011600000000000013702047635021304 5ustar jenkinsjenkinsfacter-3.14.12/lib/inc/internal/facts/resolvers/augeas_resolver.hpp0000644005276200011600000000151513702047406025201 0ustar jenkinsjenkins/** * @file * Declares the base augeas fact resolver. */ #pragma once #include namespace facter { namespace facts { namespace resolvers { /** * Responsible for resolving augeas fact, when an augeas runtime is available. */ struct augeas_resolver : resolver { /** * Constructs the augeas_resolver. */ augeas_resolver(); /** * Called to resolve all facts the resolver is responsible for. * @param facts The fact collection that is resolving facts. */ virtual void resolve(collection& facts) override; protected: /** * Gets the augeas version. * @return The augeas version string. */ virtual std::string get_version(); }; }}} // namespace facter::facts::resolvers facter-3.14.12/lib/inc/internal/facts/resolvers/disk_resolver.hpp0000644005276200011600000000357413702047406024675 0ustar jenkinsjenkins/** * @file * Declares the base disk resolver. */ #pragma once #include #include #include #include namespace facter { namespace facts { namespace resolvers { /** * Responsible for resolving disk facts. */ struct disk_resolver : resolver { /** * Constructs the disk_resolver. */ disk_resolver(); /** * Called to resolve all facts the resolver is responsible for. * @param facts The fact collection that is resolving facts. */ virtual void resolve(collection& facts) override; protected: /** * Represents a disk. */ struct disk { /** * Stores the name of the disk. */ std::string name; /** * Stores the vendor of the disk. */ std::string vendor; /** * Stores the model of the disk. */ std::string model; /** * Stores the product of the disk. */ std::string product; /** * Stores the size of the disk. */ uint64_t size; /** * Stores the serial number of the disk */ std::string serial_number; }; /** * Represents the resolver's data. */ struct data { /** * Stores the disks. */ std::vector disks; }; /** * Collects the resolver data. * @param facts The fact collection that is resolving facts. * @return Returns the resolver data. */ virtual data collect_data(collection& facts) = 0; }; }}} // namespace facter::facts::resolvers facter-3.14.12/lib/inc/internal/facts/resolvers/dmi_resolver.hpp0000644005276200011600000000544613702047406024514 0ustar jenkinsjenkins/** * @file * Declares the base Desktop Management Interface (DMI) fact resolver. */ #pragma once #include #include namespace facter { namespace facts { namespace resolvers { /** * Responsible for resolving DMI facts. */ struct dmi_resolver : resolver { /** * Constructs the dmi_resolver. */ dmi_resolver(); /** * Converts the given chassis type identifier to a description string. * @param type The chassis type identifier. * @return Returns the chassis description string. */ static std::string to_chassis_description(std::string const& type); /** * Called to resolve all facts the resolver is responsible for. * @param facts The fact collection that is resolving facts. */ virtual void resolve(collection& facts) override; protected: /** * Represents DMI data. */ struct data { /** * Stores the BIOS vendor. */ std::string bios_vendor; /** * Stores the BIOS version. */ std::string bios_version; /** * Stores the BIOS release date. */ std::string bios_release_date; /** * Stores the board asset tag. */ std::string board_asset_tag; /** * Stores the board manufacturer. */ std::string board_manufacturer; /** * Stores the board product name. */ std::string board_product_name; /** * Stores the board serial number. */ std::string board_serial_number; /** * Stores the chassis asset tag. */ std::string chassis_asset_tag; /** * Stores the system manufacturer. */ std::string manufacturer; /** * Stores the system product name. */ std::string product_name; /** * Stores the system serial number. */ std::string serial_number; /** * Stores the system product UUID. */ std::string uuid; /** * Stores the system chassis type. */ std::string chassis_type; }; /** * Collects the resolver data. * @param facts The fact collection that is resolving facts. * @return Returns resolver DMI data. */ virtual data collect_data(collection& facts) = 0; }; }}} // namespace facter::facts::resolvers facter-3.14.12/lib/inc/internal/facts/resolvers/ec2_resolver.hpp0000644005276200011600000000124113702047406024401 0ustar jenkinsjenkins/** * @file * Declares the base EC2 fact resolver. */ #pragma once #include namespace facter { namespace facts { namespace resolvers { /** * Responsible for resolving EC2 facts. */ struct ec2_resolver : resolver { /** * Constructs the ec2_resolver. */ ec2_resolver(); /** * Called to resolve all facts the resolver is responsible for. * @param facts The fact collection that is resolving facts. */ virtual void resolve(collection& facts) override; bool is_blockable() const override; }; }}} // namespace facter::facts::resolvers facter-3.14.12/lib/inc/internal/facts/resolvers/filesystem_resolver.hpp0000644005276200011600000000770013702047406026122 0ustar jenkinsjenkins/** * @file * Declares the base file system fact resolver. */ #pragma once #include #include #include #include #include namespace facter { namespace facts { namespace resolvers { /** * Responsible for resolving file system facts. */ struct filesystem_resolver : resolver { /** * Constructs the filesystem_resolver. */ filesystem_resolver(); /** * Called to resolve all facts the resolver is responsible for. * @param facts The fact collection that is resolving facts. */ virtual void resolve(collection& facts) override; bool is_blockable() const override; protected: /** * Represents data about a mountpoint. */ struct mountpoint { /** * Constructs a mountpoint. */ mountpoint() : size(0), available(0), free(0) { } /** * Stores the mountpoint name (the mount location). */ std::string name; /** * Stores the mounted device. */ std::string device; /** * Stores the filesystem of the mountpoint. */ std::string filesystem; /** * Stores the total size of the mountpoint. */ uint64_t size; /** * Stores the available size of the mountpoint. */ uint64_t available; /** * Stores the free size of the mountpoint. */ uint64_t free; /** * Stores the mountpoint options. */ std::vector options; }; /** * Represents data about a partition. */ struct partition { /** * Constructs a partition. */ partition() : size(0) { } /** * Stores the name of the partition. */ std::string name; /** * Stores the file system of the partition. */ std::string filesystem; /** * Stores the size of the partition. */ uint64_t size; /** * Stores the UUID of the file system. */ std::string uuid; /** * Stores the UUID of the GPT partition. */ std::string partition_uuid; /** * Stores the label of the file system. */ std::string label; /** * Stores the label of the GPT partition. */ std::string partition_label; /** * Stores the partition mountpoint. */ std::string mount; /** * Stores the backing file for partitions backed by a file. */ std::string backing_file; }; /** * Represents file system data. */ struct data { /** * Stores the mountpoint data. */ std::vector mountpoints; /** * Stores the filesystems. */ std::set filesystems; /** * Stores the partitions data. */ std::vector partitions; }; /** * Collects the file system data. * @param facts The fact collection that is resolving facts. * @return Returns the file system data. */ virtual data collect_data(collection& facts) = 0; }; }}} // namespace facter::facts::resolvers facter-3.14.12/lib/inc/internal/facts/resolvers/fips_resolver.hpp0000644005276200011600000000202713702047406024674 0ustar jenkinsjenkins/** * @file * Declares the base fips fact resolver. */ #pragma once #include namespace facter { namespace facts { namespace resolvers { /** * Responsible for resolving fips facts. */ struct fips_resolver : resolver { fips_resolver(); /** * Called to resolve all facts the resolver is responsible for. * @param facts The fact collection that is resolving facts. */ virtual void resolve(collection& facts) override; protected: /** * Represents fips data. */ struct data { /** * Stores the is_fips_mode_enabled data. */ bool is_fips_mode_enabled; }; /** * * Collects fips data. * @param facts The fact collection that is resolving facts. * @return Returns the fips data. */ virtual data collect_data(collection& facts) = 0; }; }}} // namespace facter::facts::resolvers facter-3.14.12/lib/inc/internal/facts/resolvers/gce_resolver.hpp0000644005276200011600000000121413702047406024466 0ustar jenkinsjenkins/** * @file * Declares the base Google Compute Engine (GCE) fact resolver. */ #pragma once #include namespace facter { namespace facts { namespace resolvers { /** * Responsible for resolving GCE facts. */ struct gce_resolver : resolver { /** * Constructs the gce_resolver. */ gce_resolver(); /** * Called to resolve all facts the resolver is responsible for. * @param facts The fact collection that is resolving facts. */ virtual void resolve(collection& facts) override; }; }}} // namespace facter::facts::resolvers facter-3.14.12/lib/inc/internal/facts/resolvers/hypervisors_resolver.hpp0000644005276200011600000000362213702047406026332 0ustar jenkinsjenkins/** * @file * Declares the hypervisors fact resolver */ #pragma once #include #include #include #include #include #include #include #include namespace facter { namespace facts { namespace resolvers { /** * Represents hypervisor data collected from libwhereami */ using hypervisor_data = std::unordered_map>>; /** * This base resolver exists to allow libfacter schema tests to pass when libwhereami is not included in the build. */ struct hypervisors_resolver_base : resolver { /** * Default constructor */ hypervisors_resolver_base() : resolver( "hypervisors", { fact::hypervisors }) { } /** * Called to resolve all facts the resolver is responsible for * @param facts The fact collection that is resolving the facts */ virtual void resolve(collection& facts) override; bool is_blockable() const override; protected: /** * Collects hypervisor data * @param facts * @return Returns the hypervisor data. */ virtual hypervisor_data collect_data(collection& facts) = 0; }; /** * Hypervisors resolver for use when libwhereami is included */ struct hypervisors_resolver : hypervisors_resolver_base { /** * Collects hypervisor data * @param facts * @return Returns the hypervisor data. */ virtual hypervisor_data collect_data(collection& facts) override; }; }}} // namespace facter::facts::resolvers facter-3.14.12/lib/inc/internal/facts/resolvers/identity_resolver.hpp0000644005276200011600000000370513702047406025570 0ustar jenkinsjenkins/** * @file * Declares the base user and group resolver. */ #pragma once #include #include #include namespace facter { namespace facts { namespace resolvers { /** * Responsible for resolving the user and group facts. */ struct identity_resolver : resolver { /** * Constructs the identity_resolver. */ identity_resolver(); /** * Called to resolve all facts the resolver is responsible for. * @param facts The fact collection that is resolving facts. */ virtual void resolve(collection& facts) override; protected: /** * Represents user information data. */ struct data { /** * Stores the id of the user. */ boost::optional user_id; /** * Stores the name of the user. */ std::string user_name; /** * Stores id of the user's primary group. */ boost::optional group_id; /** * Stores the name of the user's primary group. */ std::string group_name; /** * Stores whether facter is running as a privileged * process: With the effective UID of 0 on *NIX systems * or with elevated privileges on Windows (or with the * local Administrators group privileges on older versions * of windows not supporting privileges elevation). */ boost::optional privileged; }; /** * Collects the resolver data. * @param facts The fact collection that is resolving facts. * @return Returns the resolver data. */ virtual data collect_data(collection& facts) = 0; }; }}} // namespace facter::facts::resolvers facter-3.14.12/lib/inc/internal/facts/resolvers/kernel_resolver.hpp0000644005276200011600000000323713702047406025217 0ustar jenkinsjenkins/** * @file * Declares the base kernel fact resolver. */ #pragma once #include #include #include namespace facter { namespace facts { namespace resolvers { /** * Responsible for resolving kernel facts. */ struct kernel_resolver : resolver { /** * Constructs the kernel_resolver. */ kernel_resolver(); /** * Called to resolve all facts the resolver is responsible for. * @param facts The fact collection that is resolving facts. */ virtual void resolve(collection& facts) override; protected: /** * Represents kernel data. */ struct data { /** * Stores the name of the kernel (e.g. Linux, Darwin, etc). */ std::string name; /** * Stores the release of the kernel. */ std::string release; /** * Stores the version of the kernel. */ std::string version; }; /** * Collects the resolver data. * @param facts The fact collection that is resolving facts. * @return Returns the resolver data. */ virtual data collect_data(collection& facts) = 0; /** * Parses the major and minor kernel versions. * @param version The version to parse. * @return Returns a tuple of major and minor versions. */ virtual std::tuple parse_version(std::string const& version) const; }; }}} // namespace facter::facts::resolvers facter-3.14.12/lib/inc/internal/facts/resolvers/ldom_resolver.hpp0000644005276200011600000000322513702047406024667 0ustar jenkinsjenkins/** * @file * Declares the base LDom (Logical Domain) fact resolver. */ #pragma once #include #include namespace facter { namespace facts { namespace resolvers { /** * Responsible for resolving LDom facts. */ struct ldom_resolver : resolver { /** * Constructs the ldom_resolver. */ ldom_resolver(); /** * Called to resolve all facts the resolver is responsible for. * @param facts The fact collection that is resolving facts. */ virtual void resolve(collection& facts) override; protected: /** * Represents dynamic sub-keys consisting of LDom data. */ struct ldom_info { /** * Stores the top-level name of this category of LDom information. */ std::string key; /** * Stores related LDom information. */ std::map values; }; /** * Represents the resolver's data. */ struct data { /** * Stores all gathered LDom data. */ std::vector ldom; }; /** * Collects the resolver data. * @param facts The fact collection that is resolving facts. * @return Returns the resolver data. */ virtual data collect_data(collection& facts) = 0; }; }}} // namespace facter::facts::resolvers facter-3.14.12/lib/inc/internal/facts/resolvers/load_average_resolver.hpp0000644005276200011600000000170113702047406026342 0ustar jenkinsjenkins/** * @file * Declares the load average fact resolver. */ #pragma once #include #include #include namespace facter { namespace facts { namespace resolvers { /** * Responsible for resolving load_average facts. */ struct load_average_resolver : resolver { /** * Constructs the disk_resolver. */ load_average_resolver(); /** * Called to resolve all facts the resolver is responsible for. * @param facts The fact collection that is resolving facts. */ virtual void resolve(collection& facts) override; protected: /** * Get the system load averages (1, 5 or 15 minutes). * @return Returns the system load averages. */ virtual boost::optional > get_load_averages() = 0; }; }}} // namespace facter::facts::resolvers facter-3.14.12/lib/inc/internal/facts/resolvers/memory_resolver.hpp0000644005276200011600000000446513702047406025253 0ustar jenkinsjenkins/** * @file * Declares the base memory fact resolver. */ #pragma once #include #include namespace facter { namespace facts { namespace resolvers { /** * Responsible for resolving memory facts. */ struct memory_resolver : resolver { /** * Constructs the memory_resolver. */ memory_resolver(); /** * Called to resolve all facts the resolver is responsible for. * @param facts The fact collection that is resolving facts. */ virtual void resolve(collection& facts) override; protected: /** * Represents the possible swap encryption status. */ enum class encryption_status { /** * The swap encryption status is unknown. */ unknown, /** * The swap is encrypted. */ encrypted, /** * The swap is not encrypted. */ not_encrypted }; /** * Represents data about system memory. */ struct data { /** * Constructs the data. */ data() : mem_free(0), mem_total(0), swap_free(0), swap_total(0), swap_encryption(encryption_status::unknown) { } /** * Stores the free memory, in bytes. */ uint64_t mem_free; /** * Stores the total memory, in bytes. */ uint64_t mem_total; /** * Stores the free swap, in bytes. */ uint64_t swap_free; /** * Stores the total swap, in bytes. */ uint64_t swap_total; /** * Stores the swap encryption status. */ encryption_status swap_encryption; }; /** * Collects the resolver data. * @param facts The fact collection that is resolving facts. * @return Returns the resolver data. */ virtual data collect_data(collection& facts) = 0; }; }}} // namespace facter::facts::resolvers facter-3.14.12/lib/inc/internal/facts/resolvers/networking_resolver.hpp0000644005276200011600000001105113702047406026117 0ustar jenkinsjenkins/** * @file * Declares the base networking fact resolver. */ #pragma once #include #include #include #include #include namespace facter { namespace facts { namespace resolvers { /** * Responsible for resolving networking facts. */ struct networking_resolver : resolver { /** * Constructs the networking_resolver. */ networking_resolver(); /** * Utility function to convert the bytes of a MAC address to a string. * @param bytes The bytes of the MAC address; accepts 6-byte and 20-byte addresses. * @param byte_count The number of bytes in the MAC address; defaults to be 6 bytes long. * @returns Returns the MAC address as a string or an empty string if the address is the "NULL" MAC address. */ static std::string macaddress_to_string(uint8_t const* bytes, uint8_t byte_count = 6); /** * Returns whether the address is an ignored IPv4 address. * Ignored addresses are local or auto-assigned private IP. * @param addr The string representation of an IPv4 address. * @return Returns true if an ignored IPv4 address. */ static bool ignored_ipv4_address(std::string const& addr); /** * Returns whether the address is an ignored IPv6 address. Ignored addresses are local or link-local. * @param addr The string representation of an IPv6 address. * @return Returns true if an ignored IPv6 address. */ static bool ignored_ipv6_address(std::string const& addr); /** * Called to resolve all facts the resolver is responsible for. * @param facts The fact collection that is resolving facts. */ virtual void resolve(collection& facts) override; protected: /** * Represents an address binding. */ struct binding { /** * Stores the interface's address. */ std::string address; /** * Stores the netmask represented as an address. */ std::string netmask; /** * Stores the network address. */ std::string network; }; /** * Represents a network interface. */ struct interface { /** * Stores the name of the interface. */ std::string name; /** * Stores the DHCP server address. */ std::string dhcp_server; /** * Stores the IPv4 bindings for the interface. */ std::vector ipv4_bindings; /** * Stores the IPv6 bindings for the interface. */ std::vector ipv6_bindings; /** * Stores the link layer (MAC) address. */ std::string macaddress; /** * Stores the interface MTU. */ boost::optional mtu; }; /** * Represents the resolver's data. */ struct data { /** * Stores the hostname. */ std::string hostname; /** * Stores the domain. */ std::string domain; /** * Stores the FQDN. */ std::string fqdn; /** * Stores the name of the primary interface. */ std::string primary_interface; /** * Stores the interface. */ std::vector interfaces; }; /** * Collects the resolver data. * @param facts The fact collection that is resolving facts. * @return Returns the resolver data. */ virtual data collect_data(collection& facts) = 0; private: static binding const* find_default_binding(std::vector const& bindings, std::function const& ignored); static void add_bindings(interface& iface, bool primary, bool ipv4, collection& facts, map_value& networking, map_value& iface_value); interface const* find_primary_interface(std::vector const& interfaces); static std::string get_scope(const std::string& address); }; }}} // namespace facter::facts::resolvers facter-3.14.12/lib/inc/internal/facts/resolvers/operating_system_resolver.hpp0000644005276200011600000001600113702047406027324 0ustar jenkinsjenkins/** * @file * Declares the base operating system fact resolver. */ #pragma once #include #include namespace facter { namespace facts { namespace resolvers { /** * Responsible for resolving operating system facts. */ struct operating_system_resolver : resolver { /** * Constructs the operating_system_resolver. */ operating_system_resolver(); /** * Called to resolve all facts the resolver is responsible for. * @param facts The fact collection that is resolving facts. */ virtual void resolve(collection& facts) override; /** * Parses the major and minor OS release versions for Linux distros. * @param name The name of the OS. * @param release The release to parse. * @return Returns a tuple of major and minor release versions. */ static std::tuple parse_distro(std::string const& name, std::string const& release); protected: /** * Represents information about an operating system distribution. */ struct distribution { /** * Stores the distribution id. */ std::string id; /** * Stores the distribution release. */ std::string release; /** * Stores the distribution codename. */ std::string codename; /** * Stores the distribution description. */ std::string description; }; /** * Represents information about FreeBSD. */ struct freebsd_data { /** * Stores FreeBSD branch. */ std::string branch; /** * Stores FreeBSD patchlevel. */ std::string patchlevel; }; /** * Represents information about Mac OSX. */ struct mac { /** * Stores the OSX product name. */ std::string product; /** * Stores the OSX build number. */ std::string build; /** * Stores the OSX version. */ std::string version; }; /** * Represents information about Windows. */ struct windows { /** * Stores the Windows Server or Desktop Edition variant */ std::string edition_id; /** * Stores the Windows differentiate Server, Server Core, Client (Desktop) */ std::string installation_type; /** * Stores the Windows textual product name */ std::string product_name; /** * Stores the Windows Build Version. */ std::string release_id; /** * Stores the native system32 directory, the location native OS executables can be found. * For 32-bit facter on 32-bit Windows, typically: 'C:\\Windows\\system32'. * For 32-bit facter on 64-bit Windows, typically: 'C:\\Windows\\sysnative'. * For 64-bit facter on 64-bit Windows, typically: 'C:\\Windows\\system32'. */ std::string system32; }; /** * Represents information about SELinux. */ struct selinux_data { /** * Default constructor for selinux data. */ selinux_data() : supported(false), enabled(false), enforced(false) { } /** * Stores whether or not SELinux is supported. */ bool supported; /** * Stores whether or not SELinux is enabled. */ bool enabled; /** * Stores whether or not SELinux is enforced. */ bool enforced; /** * Stores the SELinux policy version. */ std::string policy_version; /** * Stores the current SELinux mode. */ std::string current_mode; /** * Stores the configured SELinux mode. */ std::string config_mode; /** * Stores the configured SELinux policy. */ std::string config_policy; }; /** * Represents operating system data. */ struct data { /** * Stores the OS name (e.g. CentOS). */ std::string name; /** * Stores the OS family name (e.g. Debian). */ std::string family; /** * Stores the OS release. */ std::string release; /** * Stores the OS major release. */ std::string major; /** * Stores the OS minor release. */ std::string minor; /** * Stores the processor hardware model. */ std::string hardware; /** * Stores the system architecture. */ std::string architecture; /** * Stores the distribution specification version. */ std::string specification_version; /** * Stores information about the OS distribution. */ distribution distro; /** * Stores information about FreeBSD. */ freebsd_data freebsd; /** * Stores information about Mac OSX. */ mac osx; /** * Stores information about Windows. */ windows win; /** * Stores information about SELinux. */ selinux_data selinux; }; /** * Collects the resolver data. * @param facts The fact collection that is resolving facts. * @return Returns the resolver data. */ virtual data collect_data(collection& facts); /** * Collects the resolver's kernel data. * @param facts The fact collection that is resolving facts. * @param result The current resolver data. */ virtual void collect_kernel_data(collection& facts, data &result); /** * Collects the resolver's release data. * @param facts The fact collection that is resolving facts. * @param result The current resolver data. */ virtual void collect_release_data(collection& facts, data &result); }; }}} // namespace facter::facts::resolvers facter-3.14.12/lib/inc/internal/facts/resolvers/path_resolver.hpp0000644005276200011600000000117613702047406024673 0ustar jenkinsjenkins/** * @file * Declares the base PATH fact resolver. */ #pragma once #include namespace facter { namespace facts { namespace resolvers { /** * Responsible for resolving path facts. */ struct path_resolver : resolver { /** * Constructs the path_resolver. */ path_resolver(); /** * Called to resolve all facts the resolver is responsible for. * @param facts The fact collection that is resolving facts. */ virtual void resolve(collection& facts) override; }; }}} // namespace facter::facts::resolvers facter-3.14.12/lib/inc/internal/facts/resolvers/processor_resolver.hpp0000644005276200011600000000361013702047406025751 0ustar jenkinsjenkins/** * @file * Declares the base processor fact resolver. */ #pragma once #include #include #include #include namespace facter { namespace facts { namespace resolvers { /** * Responsible for resolving processor-related facts. */ struct processor_resolver : resolver { /** * Constructs the processor_resolver. */ processor_resolver(); /** * Called to resolve all facts the resolver is responsible for. * @param facts The fact collection that is resolving facts. */ virtual void resolve(collection& facts) override; protected: /** * Represents processor resolver data. */ struct data { /** * Constructs the processor resolver data. */ data(): physical_count(0), logical_count(0), speed(0) { } /** * Stores the physical count of processors. */ int physical_count; /** * Stores the logical count of processors. */ int logical_count; /** * Stores the processor model strings. */ std::vector models; /** * Stores the processor speed, in Hz. */ int64_t speed; /** * Stores the processor instruction set architecture. */ std::string isa; }; /** * Collects the resolver data. * @param facts The fact collection that is resolving facts. * @return Returns the resolver data. */ virtual data collect_data(collection& facts) = 0; }; }}} // namespace facter::facts::resolvers facter-3.14.12/lib/inc/internal/facts/resolvers/ruby_resolver.hpp0000644005276200011600000000245513702047406024721 0ustar jenkinsjenkins/** * @file * Declares the base Ruby fact resolver. */ #pragma once #include namespace facter { namespace facts { namespace resolvers { /** * Responsible for resolving Ruby facts, when a Ruby runtime is available. */ struct ruby_resolver : resolver { /** * Constructs the ruby_resolver. */ ruby_resolver(); /** * Called to resolve all facts the resolver is responsible for. * @param facts The fact collection that is resolving facts. */ virtual void resolve(collection& facts) override; protected: /** * Represents Ruby metadata. */ struct data { /** * Stores RUBY_PLATFORM. */ std::string platform; /** * Stores the Ruby sitelibdir. */ std::string sitedir; /** * Stores RUBY_VERSION. */ std::string version; }; /** * Collects the resolver data. * @param facts The fact collection that is resolving facts. * @return Returns the resolver data. */ virtual data collect_data(collection& facts); }; }}} // namespace facter::facts::resolvers facter-3.14.12/lib/inc/internal/facts/resolvers/ssh_resolver.hpp0000644005276200011600000000546713702047406024543 0ustar jenkinsjenkins/** * @file * Declares the base SSH fact resolver. */ #pragma once #include #include #include #include namespace facter { namespace facts { namespace resolvers { /** * Responsible for resolving ssh facts. */ struct ssh_resolver : resolver { /** * Constructs the ssh_resolver. */ ssh_resolver(); /** * Called to resolve all facts the resolver is responsible for. * @param facts The fact collection that is resolving facts. */ virtual void resolve(collection& facts) override; protected: /** * Represents an SSH fingerprint. */ struct fingerprint { /** * Stores the SHA1 fingerprint. */ std::string sha1; /** * Stores the SHA256 fingerprint. */ std::string sha256; }; /** * Represents information about a SSH key. */ struct ssh_key { /** * Stores the SSH key. */ std::string key; /** * Stores the SSH key's fingerprint. */ fingerprint digest; /** * Stores the SSH key type. One of ssh-dss, ssh-rsa, ssh-ed25519, * ecdsa-sha2-nistp256, ecdsa-sha2-nistp384, or ecdsa-sha2-nistp512 */ std::string type; }; /** * Represents SSH resolver data. */ struct data { /** * Stores the DSA key. */ ssh_key dsa; /** * Stores the RSA key. */ ssh_key rsa; /** * Stores the ECDSA key. */ ssh_key ecdsa; /** * Stores the ED25519 key */ ssh_key ed25519; }; /** * Retrieves the fact's key file * @param filename The searched key file name. * @return Returns the key file's path */ virtual boost::filesystem::path retrieve_key_file(std::string const& filename) = 0; /** * Collects the resolver data. * @param facts The fact collection that is resolving facts. * @return Returns the resolver data. */ virtual data collect_data(collection& facts); private: void add_key(collection& facts, map_value& value, ssh_key& key, std::string const& name, std::string const& key_fact_name, std::string const& fingerprint_fact_name); void populate_key(std::string const& filename, int type, ssh_key& key); }; }}} // namespace facter::facts::resolvers facter-3.14.12/lib/inc/internal/facts/resolvers/system_profiler_resolver.hpp0000644005276200011600000000655313702047406027171 0ustar jenkinsjenkins/** * @file * Declares the base system profiler fact resolver. */ #pragma once #include namespace facter { namespace facts { namespace resolvers { /** * Responsible for resolving system profiler facts. */ struct system_profiler_resolver : resolver { /** * Constructs the system_profiler_resolver. */ system_profiler_resolver(); /** * Called to resolve all facts the resolver is responsible for. * @param facts The fact collection that is resolving facts. */ virtual void resolve(collection& facts) override; protected: /** * Represents the resolver's data. */ struct data { /** * Stores the boot mode. */ std::string boot_mode; /** * Stores the boot ROM version. */ std::string boot_rom_version; /** * Stores the boot volume. */ std::string boot_volume; /** * Stores the processor name. */ std::string processor_name; /** * Stores the processor speed. */ std::string processor_speed; /** * Stores the kernel version. */ std::string kernel_version; /** * Stores the L2 cache per core. */ std::string l2_cache_per_core; /** * Stores the L3 cache. */ std::string l3_cache; /** * Stores the computer name. */ std::string computer_name; /** * Stores the model identifier. */ std::string model_identifier; /** * Stores the model name. */ std::string model_name; /** * Stores the number of cores. */ std::string cores; /** * Stores the system version. */ std::string system_version; /** * Stores the number of processors. */ std::string processors; /** * Stores the physical memory amount. */ std::string memory; /** * Stores the hardware UUID. */ std::string hardware_uuid; /** * Stores whether or not secure virtual memory is enabled. */ std::string secure_virtual_memory; /** * Stores the system serial number. */ std::string serial_number; /** * Stores the SMC version. */ std::string smc_version; /** * Stores the system uptime. */ std::string uptime; /** * Stores the user name. */ std::string username; }; /** * Collects the resolver data. * @param facts The fact collection that is resolving facts. * @return Returns the resolver data. */ virtual data collect_data(collection& facts) = 0; }; }}} // namespace facter::facts::resolvers facter-3.14.12/lib/inc/internal/facts/resolvers/timezone_resolver.hpp0000644005276200011600000000151613702047406025567 0ustar jenkinsjenkins/** * @file * Declares the timezone fact resolver. */ #pragma once #include #include namespace facter { namespace facts { namespace resolvers { /** * Responsible for resolving time zone facts. */ struct timezone_resolver : resolver { /** * Constructs the timezone resolver. */ timezone_resolver(); /** * Called to resolve all facts the resolver is responsible for. * @param facts The fact collection that is resolving facts. */ virtual void resolve(collection& facts) override; protected: /** * Gets the system timezone. * @return Returns the system timezone. */ virtual std::string get_timezone() = 0; }; }}} // namespace facter::facts::resolvers facter-3.14.12/lib/inc/internal/facts/resolvers/uptime_resolver.hpp0000644005276200011600000000152513702047406025240 0ustar jenkinsjenkins/** * @file * Declares the base uptime fact resolver. */ #pragma once #include #include namespace facter { namespace facts { namespace resolvers { /** * Responsible for resolving uptime facts. */ struct uptime_resolver : resolver { /** * Constructs the uptime_resolver. */ uptime_resolver(); /** * Called to resolve all facts the resolver is responsible for. * @param facts The fact collection that is resolving facts. */ virtual void resolve(collection& facts) override; protected: /** * Gets the system uptime in seconds. * @return Returns the system uptime in seconds. */ virtual int64_t get_uptime() = 0; }; }}} // namespace facter::facts::resolvers facter-3.14.12/lib/inc/internal/facts/resolvers/virtualization_resolver.hpp0000644005276200011600000000520613702047406027021 0ustar jenkinsjenkins/** * @file * Declares the base virtualization fact resolver. */ #pragma once #include #include namespace facter { namespace facts { namespace resolvers { /** * Represents cloud data. */ struct cloud_ { /** * Stores the cloud provider. */ std::string provider; }; /** * Represents virtualization data. */ struct data { /** * Stores the cloud data. */ cloud_ cloud; /** * Stores the hypervisor data. */ std::string hypervisor; /** * Stores the is_virtual data. */ bool is_virtual; }; /** * Responsible for resolving virtualization facts. */ struct virtualization_resolver : resolver { /** * Constructs the virtualization_resolver. */ virtualization_resolver(); /** * Called to resolve all facts the resolver is responsible for. * @param facts The fact collection that is resolving facts. */ virtual void resolve(collection& facts) override; protected: /** * Gets the name of the hypervisor. * @param facts The fact collection that is resolving facts. * @return Returns the name of the hypervisor or empty string if no hypervisor. */ virtual std::string get_hypervisor(collection& facts) = 0; /** * Gets the name of the cloud provider. * @param facts The fact collection that is resolving facts. * @return Returns the name of the cloud provider or empty string if no cloud provider. */ virtual std::string get_cloud_provider(collection& facts); /** * Determines if the given hypervisor is considered to be virtual. * @param hypervisor The hypervisor to check. * @return Returns true if the hypervisor is virtual or false if it is physical. */ virtual bool is_virtual(std::string const& hypervisor); /** * Gets the name of the hypervisor based on other facts and a set of matching strings * @param facts The fact collection that is resolving facts * @return Returns the hypervisor name if matched. */ static std::string get_fact_vm(collection& facts); /** * Collects the virtualization data. * @param facts The fact collection that is resolving facts. * @return Returns the virtualization data. */ virtual data collect_data(collection& facts); }; }}} // namespace facter::facts::resolvers facter-3.14.12/lib/inc/internal/facts/resolvers/xen_resolver.hpp0000644005276200011600000000243713702047406024532 0ustar jenkinsjenkins/** * @file * Declares the Xen fact resolver. */ #pragma once #include #include #include namespace facter { namespace facts { namespace resolvers { /** * Responsible for resolving Xen facts. */ struct xen_resolver : resolver { /** * Constructs the xen_resolver. */ xen_resolver(); /** * Called to resolve all facts the resolver is responsible for. * @param facts The fact collection that is resolving facts. */ virtual void resolve(collection& facts) override; protected: /** * Gets the Xen management command. * @return Returns the Xen management command. */ virtual std::string xen_command() = 0; /** * Represents the resolver's data. */ struct data { /** * Stores the Xen domains. */ std::vector domains; }; /** * Collects the resolver data. * @param facts The fact collection that is resolving facts. * @return Returns the resolver data. */ virtual data collect_data(collection& facts); }; }}} // namespace facter::facts::resolvers facter-3.14.12/lib/inc/internal/facts/resolvers/zfs_resolver.hpp0000644005276200011600000000263013702047406024535 0ustar jenkinsjenkins/** * @file * Declares the Solaris ZFS fact resolver. */ #pragma once #include #include #include namespace facter { namespace facts { namespace resolvers { /** * Responsible for resolving ZFS facts. */ struct zfs_resolver : resolver { /** * Constructs the zfs_resolver. */ zfs_resolver(); /** * Called to resolve all facts the resolver is responsible for. * @param facts The fact collection that is resolving facts. */ virtual void resolve(collection& facts) override; protected: /** * Gets the platform's ZFS command. * @return Returns the platform's ZFS command. */ virtual std::string zfs_command() = 0; /** * Represents the resolver's data. */ struct data { /** * Stores the ZFS version. */ std::string version; /** * Stores the ZFS version numbers. */ std::vector versions; }; /** * Collects the resolver data. * @param facts The fact collection that is resolving facts. * @return Returns the resolver data. */ virtual data collect_data(collection& facts); }; }}} // namespace facter::facts::resolvers facter-3.14.12/lib/inc/internal/facts/resolvers/zone_resolver.hpp0000644005276200011600000000406513702047406024712 0ustar jenkinsjenkins/** * @file * Declares the base Solaris zone fact resolver. */ #pragma once #include #include #include namespace facter { namespace facts { namespace resolvers { /** * Responsible for resolving Solaris zone facts. */ struct zone_resolver : resolver { /** * Constructs the zone_resolver. */ zone_resolver(); /** * Called to resolve all facts the resolver is responsible for. * @param facts The fact collection that is resolving facts. */ virtual void resolve(collection& facts) override; protected: /** * Represents a Solaris zone. */ struct zone { /** * Stores the zone id. */ std::string id; /** * Stores the zone name. */ std::string name; /** * Stores the zone status. */ std::string status; /** * Stores the zone path. */ std::string path; /** * Stores the zone unique identifier. */ std::string uuid; /** * Stores the zone brand. */ std::string brand; /** * Stores the zone IP type. */ std::string ip_type; }; /** * Represents the resolver data. */ struct data { /** * Stores the Solaris zones. */ std::vector zones; /** * Stores the current zone name. */ std::string current_zone_name; }; /** * Collects the resolver data. * @param facts The fact collection that is resolving facts. * @return Returns the resolver data. */ virtual data collect_data(collection& facts) = 0; }; }}} // namespace facter::facts::resolvers facter-3.14.12/lib/inc/internal/facts/resolvers/zpool_resolver.hpp0000644005276200011600000000311513702047406025075 0ustar jenkinsjenkins/** * @file * Declares the ZFS storage pool (zpool) fact resolver. */ #pragma once #include #include #include namespace facter { namespace facts { namespace resolvers { /** * Responsible for resolving ZFS storage pool (zpool) facts. */ struct zpool_resolver : resolver { /** * Constructs the zpool_resolver. */ zpool_resolver(); /** * Called to resolve all facts the resolver is responsible for. * @param facts The fact collection that is resolving facts. */ virtual void resolve(collection& facts) override; protected: /** * Gets the platform's zpool command. * @return Returns the platform's zpool command. */ virtual std::string zpool_command() = 0; /** * Represents the resolver's data. */ struct data { /** * Stores the zpool version. */ std::string version; /** * Stores the zpool feature flags. */ std::vector feature_flags; /** * Stores the zpool version numbers. */ std::vector versions; }; /** * Collects the resolver data. * @param facts The fact collection that is resolving facts. * @return Returns the resolver data. */ virtual data collect_data(collection& facts); }; }}} // namespace facter::facts::resolvers facter-3.14.12/lib/inc/internal/facts/solaris/0000755005276200011600000000000013702047635020734 5ustar jenkinsjenkinsfacter-3.14.12/lib/inc/internal/facts/solaris/disk_resolver.hpp0000644005276200011600000000113113702047406024310 0ustar jenkinsjenkins/** * @file * Declares the Solaris disk fact resolver. */ #pragma once #include "../resolvers/disk_resolver.hpp" namespace facter { namespace facts { namespace solaris { /** * Responsible for resolving disk facts. */ struct disk_resolver : resolvers::disk_resolver { protected: /** * Collects the resolver data. * @param facts The fact collection that is resolving facts. * @return Returns the resolver data. */ virtual data collect_data(collection& facts) override; }; }}} // namespace facter::facts::solaris facter-3.14.12/lib/inc/internal/facts/solaris/dmi_resolver.hpp0000644005276200011600000000116313702047406024134 0ustar jenkinsjenkins/** * @file * Declares the Solaris Desktop Management Interface (DMI) fact resolver. */ #pragma once #include "../resolvers/dmi_resolver.hpp" namespace facter { namespace facts { namespace solaris { /** * Responsible for resolving DMI facts. */ struct dmi_resolver : resolvers::dmi_resolver { protected: /** * Collects the resolver data. * @param facts The fact collection that is resolving facts. * @return Returns the resolver data. */ virtual data collect_data(collection& facts) override; }; }}} // namespace facter::facts::solaris facter-3.14.12/lib/inc/internal/facts/solaris/filesystem_resolver.hpp0000644005276200011600000000137613702047406025555 0ustar jenkinsjenkins/** * @file * Declares the Solaris file system fact resolver. */ #pragma once #include "../resolvers/filesystem_resolver.hpp" namespace facter { namespace facts { namespace solaris { /** * Responsible for resolving Solaris file system facts. */ struct filesystem_resolver : resolvers::filesystem_resolver { protected: /** * Collects the file system data. * @param facts The fact collection that is resolving facts. * @return Returns the file system data. */ virtual data collect_data(collection& facts) override; private: void collect_mountpoint_data(data& result); void collect_filesystem_data(data& result); }; }}} // namespace facter::facts::solaris facter-3.14.12/lib/inc/internal/facts/solaris/kernel_resolver.hpp0000644005276200011600000000114313702047406024641 0ustar jenkinsjenkins/** * @file * Declares the Solaris kernel fact resolver. */ #pragma once #include "../resolvers/kernel_resolver.hpp" namespace facter { namespace facts { namespace solaris { /** * Responsible for resolving kernel facts. */ struct kernel_resolver : resolvers::kernel_resolver { protected: /** * Collects the resolver data. * @param facts The fact collection that is resolving facts. * @return Returns the resolver data. */ virtual data collect_data(collection& facts) override; }; }}} // namespace facter::facts::solaris facter-3.14.12/lib/inc/internal/facts/solaris/ldom_resolver.hpp0000644005276200011600000000112013702047406024307 0ustar jenkinsjenkins/** * @file * Declares the ldom fact resolver. */ #pragma once #include "../resolvers/ldom_resolver.hpp" namespace facter { namespace facts { namespace solaris { /** * Responsible for resolving ldom facts. */ struct ldom_resolver : resolvers::ldom_resolver { protected: /** * Collects the resolver data. * @param facts The fact collection that is resolving facts. * @return Returns the resolver data. */ virtual data collect_data(collection& facts) override; }; }}} // namespace facter::facts::solaris facter-3.14.12/lib/inc/internal/facts/solaris/memory_resolver.hpp0000644005276200011600000000114313702047406024671 0ustar jenkinsjenkins/** * @file * Declares the Solaris memory fact resolver. */ #pragma once #include "../resolvers/memory_resolver.hpp" namespace facter { namespace facts { namespace solaris { /** * Responsible for resolving memory facts. */ struct memory_resolver : resolvers::memory_resolver { protected: /** * Collects the resolver data. * @param facts The fact collection that is resolving facts. * @return Returns the resolver data. */ virtual data collect_data(collection& facts) override; }; }}} // namespace facter::facts::solaris facter-3.14.12/lib/inc/internal/facts/solaris/networking_resolver.hpp0000644005276200011600000000367713702047406025566 0ustar jenkinsjenkins/** * @file * Declares the Solaris networking fact resolver. */ #pragma once #include "../posix/networking_resolver.hpp" #include #include namespace facter { namespace facts { namespace solaris { /** * Responsible for resolving networking facts. */ struct networking_resolver : posix::networking_resolver { protected: /** * Collects the resolver data. * @param facts The fact collection that is resolving facts. * @return Returns the resolver data. */ virtual data collect_data(collection& facts) override; /** * Determines if the given sock address is a link layer address. * @param addr The socket address to check. * @returns Returns true if the socket address is a link layer address or false if it is not. */ virtual bool is_link_address(sockaddr const* addr) const override; /** * Gets the bytes of the link address. * @param addr The socket address representing the link address. * @return Returns a pointer to the address bytes or nullptr if not a link address. */ virtual uint8_t const* get_link_address_bytes(sockaddr const* addr) const override; /** * Gets the length of the link address. * @param addr The socket address representing the link address. * @return Returns the length of the address or 0 if not a link address. */ virtual uint8_t get_link_address_length(sockaddr const* addr) const override; private: void populate_binding(interface& iface, lifreq const* addr) const; void populate_macaddress(interface& iface, lifreq const* addr) const; void populate_mtu(interface& iface, lifreq const* addr) const; std::string find_dhcp_server(std::string const& interface) const; std::string get_primary_interface() const; }; }}} // namespace facter::facts::solaris facter-3.14.12/lib/inc/internal/facts/solaris/operating_system_resolver.hpp0000644005276200011600000000121513702047406026755 0ustar jenkinsjenkins/** * @file * Declares the solaris operating system fact resolver. */ #pragma once #include "../posix/operating_system_resolver.hpp" namespace facter { namespace facts { namespace solaris { /** * Responsible for resolving operating system facts. */ struct operating_system_resolver : posix::operating_system_resolver { protected: /** * Collects the resolver data. * @param facts The fact collection that is resolving facts. * @return Returns the resolver data. */ virtual data collect_data(collection& facts) override; }; }}} // namespace facter::facts::solaris facter-3.14.12/lib/inc/internal/facts/solaris/processor_resolver.hpp0000644005276200011600000000116213702047406025401 0ustar jenkinsjenkins/** * @file * Declares the Solaris processor fact resolver. */ #pragma once #include "../posix/processor_resolver.hpp" namespace facter { namespace facts { namespace solaris { /** * Responsible for resolving processor-related facts. */ struct processor_resolver : posix::processor_resolver { protected: /** * Collects the resolver data. * @param facts The fact collection that is resolving facts. * @return Returns the resolver data. */ virtual data collect_data(collection& facts) override; }; }}} // namespace facter::facts::solaris facter-3.14.12/lib/inc/internal/facts/solaris/virtualization_resolver.hpp0000644005276200011600000000130313702047406026443 0ustar jenkinsjenkins/** * @file * Declares the Solaris virtualization fact resolver. */ #pragma once #include "../resolvers/virtualization_resolver.hpp" namespace facter { namespace facts { namespace solaris { /** * Responsible for resolving virtualization facts. */ struct virtualization_resolver : resolvers::virtualization_resolver { protected: /** * Gets the name of the hypervisor. * @param facts The fact collection that is resolving facts. * @return Returns the name of the hypervisor or empty string if no hypervisor. */ virtual std::string get_hypervisor(collection& facts) override; }; }}} // namespace facter::facts::solaris facter-3.14.12/lib/inc/internal/facts/solaris/zfs_resolver.hpp0000644005276200011600000000100113702047406024154 0ustar jenkinsjenkins/** * @file * Declares the ZFS fact resolver. */ #pragma once #include "../resolvers/zfs_resolver.hpp" namespace facter { namespace facts { namespace solaris { /** * Responsible for resolving ZFS facts. */ struct zfs_resolver : resolvers::zfs_resolver { protected: /** * Gets the platform's ZFS command. * @return Returns the platform's ZFS command. */ virtual std::string zfs_command(); }; }}} // namespace facter::facts::solaris facter-3.14.12/lib/inc/internal/facts/solaris/zone_resolver.hpp0000644005276200011600000000112113702047406024330 0ustar jenkinsjenkins/** * @file * Declares the Solaris zone fact resolver. */ #pragma once #include "../resolvers/zone_resolver.hpp" namespace facter { namespace facts { namespace solaris { /** * Responsible for resolving Solaris zone facts. */ struct zone_resolver : resolvers::zone_resolver { protected: /** * Collects the resolver data. * @param facts The fact collection that is resolving facts. * @return Returns the resolver data. */ virtual data collect_data(collection& facts); }; }}} // namespace facter::facts::solaris facter-3.14.12/lib/inc/internal/facts/solaris/zpool_resolver.hpp0000644005276200011600000000107713702047406024532 0ustar jenkinsjenkins/** * @file * Declares the Solaris ZFS storage pool (zpool) fact resolver. */ #pragma once #include "../resolvers/zpool_resolver.hpp" namespace facter { namespace facts { namespace solaris { /** * Responsible for resolving ZFS storage pool (zpool) facts. */ struct zpool_resolver : resolvers::zpool_resolver { protected: /** * Gets the platform's zpool command. * @return Returns the platform's zpool command. */ virtual std::string zpool_command(); }; }}} // namespace facter::facts::solaris facter-3.14.12/lib/inc/internal/facts/ssh_resolver.hpp0000644005276200011600000000101613702047406022501 0ustar jenkinsjenkins/** * @file * Declares the SSH fact resolver. */ #pragma once #include "resolvers/ssh_resolver.hpp" namespace facter { namespace facts { /** * Responsible for resolving ssh facts. */ struct ssh_resolver : resolvers::ssh_resolver { protected: /** * Retrieves the fact's key file * @param filename The searched key file name. * @return Returns the key file's path */ virtual boost::filesystem::path retrieve_key_file(std::string const& filename) override; }; }} // namespace facter::facts facter-3.14.12/lib/inc/internal/facts/windows/0000755005276200011600000000000013702047635020752 5ustar jenkinsjenkinsfacter-3.14.12/lib/inc/internal/facts/windows/dmi_resolver.hpp0000644005276200011600000000207613702047406024156 0ustar jenkinsjenkins/** * @file * Declares the Windows Desktop Management Information (DMI) fact resolver. */ #pragma once #include "../resolvers/dmi_resolver.hpp" #include #include #include namespace facter { namespace facts { namespace windows { /** * Responsible for resolving DMI facts. */ struct dmi_resolver : resolvers::dmi_resolver { /** * Constructs the dmi_resolver. * @param wmi_conn The WMI connection to use when resolving facts. */ dmi_resolver(std::shared_ptr wmi_conn = std::make_shared()); protected: /** * Collects the resolver data. * @param facts The fact collection that is resolving facts. * @return Returns the resolver data. */ virtual data collect_data(collection& facts) override; private: std::string read(std::string const& path); std::shared_ptr _wmi; }; }}} // namespace facter::facts::windows facter-3.14.12/lib/inc/internal/facts/windows/fips_resolver.hpp0000644005276200011600000000156413702047406024347 0ustar jenkinsjenkins/** * @file * Declares the Windows fips fact resolver. */ #pragma once #include "../resolvers/fips_resolver.hpp" namespace facter { namespace facts { namespace windows { /** * Responsible for resolving fips-related facts. */ struct fips_resolver : resolvers::fips_resolver { protected: /** * The check consists of the following. * (1) Examining the contents of * HKEY_LOCAL_MACHINE/System/CurrentControlSet/Control/Lsa/FipsAlgorithmPolicy/Enabled * * If it is 1 then fips mode is enabled. */ /** * Collects the resolver data. * @param facts The fact collection that is resolving facts. * @return Returns the resolver data. */ virtual data collect_data(collection& facts) override; }; }}} // namespace facter::facts::windows facter-3.14.12/lib/inc/internal/facts/windows/identity_resolver.hpp0000644005276200011600000000117013702047406025230 0ustar jenkinsjenkins/** * @file * Declares the Windows user and group resolver. */ #pragma once #include "../resolvers/identity_resolver.hpp" namespace facter { namespace facts { namespace windows { /** * Responsible for resolving the user and group facts. */ struct identity_resolver : resolvers::identity_resolver { protected: /** * Collects the resolver data. * @param facts The fact collection that is resolving facts. * @return Returns the resolver data. */ virtual data collect_data(collection& facts) override; }; }}} // namespace facter::facts::windows facter-3.14.12/lib/inc/internal/facts/windows/kernel_resolver.hpp0000644005276200011600000000114313702047406024657 0ustar jenkinsjenkins/** * @file * Declares the Windows kernel fact resolver. */ #pragma once #include "../resolvers/kernel_resolver.hpp" namespace facter { namespace facts { namespace windows { /** * Responsible for resolving kernel facts. */ struct kernel_resolver : resolvers::kernel_resolver { protected: /** * Collects the resolver data. * @param facts The fact collection that is resolving facts. * @return Returns the resolver data. */ virtual data collect_data(collection& facts) override; }; }}} // namespace facter::facts::windows facter-3.14.12/lib/inc/internal/facts/windows/memory_resolver.hpp0000644005276200011600000000114313702047406024707 0ustar jenkinsjenkins/** * @file * Declares the Windows memory fact resolver. */ #pragma once #include "../resolvers/memory_resolver.hpp" namespace facter { namespace facts { namespace windows { /** * Responsible for resolving memory facts. */ struct memory_resolver : resolvers::memory_resolver { protected: /** * Collects the resolver data. * @param facts The fact collection that is resolving facts. * @return Returns the resolver data. */ virtual data collect_data(collection& facts) override; }; }}} // namespace facter::facts::windows facter-3.14.12/lib/inc/internal/facts/windows/networking_resolver.hpp0000644005276200011600000000520413702047406025570 0ustar jenkinsjenkins/** * @file * Declares the Windows networking fact resolver. */ #pragma once #include "../resolvers/networking_resolver.hpp" #include #include #include /* * Forward declarations from winsock2.h, ws2tcpip.h, windows.h * To use these APIs, include those headers. The headers are not included here * to avoid polluting the global namespace. */ struct sockaddr; struct sockaddr_in; struct sockaddr_in6; namespace facter { namespace facts { namespace windows { /** * Responsible for resolving networking facts. */ struct networking_resolver : resolvers::networking_resolver { /** * Constructs a Windows networking resolver. */ networking_resolver(); protected: /** * Collects the resolver data. * @param facts The fact collection that is resolving facts. * @return Returns the resolver data. */ virtual data collect_data(collection& facts) override; /** * Creates an IPv4 sockaddr_in of the mask. If masklen is too large, returns a full mask. * Windows only allows contiguous subnet masks, representing them by their length. * @param masklen Length of the contiguous mask. * @return The sockaddr_in representation of the mask. */ sockaddr_in create_ipv4_mask(uint8_t masklen); /** * Creates an IPv6 sockaddr_in6 of the mask. If masklen is too large, returns a full mask. * Windows only allows contiguous subnet masks, representing them by their length. * @param masklen Length of the contiguous mask. * @return The sockaddr_in6 representation of the mask. */ sockaddr_in6 create_ipv6_mask(uint8_t masklen); /** * Applies a mask to an IPv4 address, returning a new sockaddr_in. * @param addr A sockaddr structure defining a valid IPv4 address. * @param mask A sockaddr_in structure defining a valid IPv4 mask. * @return A new sockaddr_in structure representing the masked IPv4 address. */ static sockaddr_in mask_ipv4_address(sockaddr const* addr, sockaddr_in const& mask); /** * Applies a mask to an IPv6 address, returning a new sockaddr_in6. * @param addr A sockaddr structure defining a valid IPv6 address. * @param mask A sockaddr_in6 structure defining a valid IPv6 mask. * @return A new sockaddr_in6 structure representing the masked IPv6 address. */ static sockaddr_in6 mask_ipv6_address(sockaddr const* addr, sockaddr_in6 const& mask); }; }}} // namespace facter::facts::windows facter-3.14.12/lib/inc/internal/facts/windows/operating_system_resolver.hpp0000644005276200011600000000206313702047406026775 0ustar jenkinsjenkins/** * @file * Declares the Windows operating system fact resolver. */ #pragma once #include "../resolvers/operating_system_resolver.hpp" #include #include namespace facter { namespace facts { namespace windows { /** * Responsible for resolving operating system facts. */ struct operating_system_resolver : resolvers::operating_system_resolver { /** * Constructs the operating_system_resolver. * @param wmi_conn The WMI connection to use when resolving facts. */ operating_system_resolver(std::shared_ptr wmi_conn = std::make_shared()); protected: /** * Collects the resolver data. * @param facts The fact collection that is resolving facts. * @return Returns the resolver data. */ virtual data collect_data(collection& facts) override; private: std::shared_ptr _wmi; }; }}} // namespace facter::facts::windows facter-3.14.12/lib/inc/internal/facts/windows/processor_resolver.hpp0000644005276200011600000000201213702047406025412 0ustar jenkinsjenkins/** * @file * Declares the Windows processor fact resolver. */ #pragma once #include "../resolvers/processor_resolver.hpp" #include #include namespace facter { namespace facts { namespace windows { /** * Responsible for resolving processor-related facts. */ struct processor_resolver : resolvers::processor_resolver { /** * Constructs the processor_resolver. * @param wmi_conn The WMI connection to use when resolving facts. */ processor_resolver(std::shared_ptr wmi_conn = std::make_shared()); protected: /** * Collects the resolver data. * @param facts The fact collection that is resolving facts. * @return Returns the resolver data. */ virtual data collect_data(collection& facts) override; private: std::shared_ptr _wmi; }; }}} // namespace facter::facts::windows facter-3.14.12/lib/inc/internal/facts/windows/timezone_resolver.hpp0000644005276200011600000000103713702047406025233 0ustar jenkinsjenkins/** * @file * Declares the Windows timezone fact resolver. */ #pragma once #include "../resolvers/timezone_resolver.hpp" namespace facter { namespace facts { namespace windows { /** * Responsible for resolving time zone facts. */ struct timezone_resolver : resolvers::timezone_resolver { protected: /** * Gets the system timezone. * @return Returns the system timezone. */ virtual std::string get_timezone() override; }; }}} // namespace facter::facts::windows facter-3.14.12/lib/inc/internal/facts/windows/uptime_resolver.hpp0000644005276200011600000000131113702047406024677 0ustar jenkinsjenkins/** * @file * Declares the Windows uptime fact resolver. */ #pragma once #include "../resolvers/uptime_resolver.hpp" #include #include #include namespace facter { namespace facts { namespace windows { /** * Responsible for resolving uptime facts. */ struct uptime_resolver : resolvers::uptime_resolver { /** * Constructs the uptime_resolver. */ uptime_resolver(); protected: /** * Gets the system uptime in seconds. * @return Returns the system uptime in seconds. */ virtual int64_t get_uptime() override; }; }}} // namespace facter::facts::windows facter-3.14.12/lib/inc/internal/facts/windows/virtualization_resolver.hpp0000644005276200011600000000215713702047406026471 0ustar jenkinsjenkins/** * @file * Declares the Windows virtualization fact resolver. */ #pragma once #include "../resolvers/virtualization_resolver.hpp" #include #include #include namespace facter { namespace facts { namespace windows { /** * Responsible for resolving virtualization facts. */ struct virtualization_resolver : resolvers::virtualization_resolver { /** * Constructs the virtualization_resolver. * @param wmi_conn The WMI connection to use when resolving facts. */ virtualization_resolver(std::shared_ptr wmi_conn = std::make_shared()); protected: /** * Gets the name of the hypervisor. * @param facts The fact collection that is resolving facts. * @return Returns the name of the hypervisor or empty string if no hypervisor. */ virtual std::string get_hypervisor(collection& facts) override; private: std::shared_ptr _wmi; }; }}} // namespace facter::facts::windows facter-3.14.12/lib/inc/internal/ruby/0000755005276200011600000000000013702047635017141 5ustar jenkinsjenkinsfacter-3.14.12/lib/inc/internal/ruby/aggregate_resolution.hpp0000644005276200011600000000535513702047406024067 0ustar jenkinsjenkins/** * @file * Declares the Ruby Facter::Core::Aggregate class. */ #pragma once #include "resolution.hpp" #include "chunk.hpp" #include #include namespace facter { namespace ruby { /** * Represents the Ruby Facter::Core::Aggregate class. */ struct aggregate_resolution : resolution { /** * Defines the Facter::Core::Aggregate class. * @return Returns the Facter::Core::Aggregate class. */ static leatherman::ruby::VALUE define(); /** * Creates an instance of the Facter::Core::Aggregate class. * @return Returns the new instance. */ static leatherman::ruby::VALUE create(); /** * Gets the value of the resolution. * @return Returns the value of the resolution or nil if the value did not resolve. */ virtual leatherman::ruby::VALUE value(); /** * Finds the value of the given chunk. * @param name The name of the chunk to find the value of. * @return Returns the value of the chunk or nil if the chunk is not found. */ leatherman::ruby::VALUE find_chunk(leatherman::ruby::VALUE name); /** * Defines a chunk. * @param name The name of the chunk. * @param options The options for defining the chunk. */ void define_chunk(leatherman::ruby::VALUE name, leatherman::ruby::VALUE options); private: // Construction and assignment aggregate_resolution(); aggregate_resolution(aggregate_resolution const&) = delete; aggregate_resolution& operator=(aggregate_resolution const&) = delete; aggregate_resolution(aggregate_resolution&& other) = delete; aggregate_resolution& operator=(aggregate_resolution&& other) = delete; // Ruby lifecycle functions static leatherman::ruby::VALUE alloc(leatherman::ruby::VALUE klass); static void mark(void* data); static void free(void* data); // Methods called from Ruby static leatherman::ruby::VALUE ruby_chunk(int argc, leatherman::ruby::VALUE* argv, leatherman::ruby::VALUE self); static leatherman::ruby::VALUE ruby_aggregate(leatherman::ruby::VALUE self); static leatherman::ruby::VALUE ruby_merge_hashes(leatherman::ruby::VALUE obj, leatherman::ruby::VALUE context, int argc, leatherman::ruby::VALUE* argv); // Helper functions static leatherman::ruby::VALUE deep_merge(leatherman::ruby::api const& ruby, leatherman::ruby::VALUE left, leatherman::ruby::VALUE right); leatherman::ruby::VALUE _self; leatherman::ruby::VALUE _block; std::map _chunks; }; }} // namespace facter::ruby facter-3.14.12/lib/inc/internal/ruby/chunk.hpp0000644005276200011600000000435513702047406020765 0ustar jenkinsjenkins/** * @file * Declares the class for aggregate resolution chunks. */ #pragma once #include namespace facter { namespace ruby { struct aggregate_resolution; /** * Represents a aggregate resolution chunk. */ struct chunk { /** * Constructs an aggregate resolution chunk. * @param dependencies The symbol or array of symbols this chunk depends on. * @param block The block to run to resolve the chunk. */ chunk(leatherman::ruby::VALUE dependencies, leatherman::ruby::VALUE block); /** * Moves the given chunk into this chunk. * @param other The chunk to move into this chunk. */ chunk(chunk&& other); /** * Moves the given chunk into this chunk. * @param other The chunk to move into this chunk. * @return Returns this chunk. */ chunk& operator=(chunk&& other); /** * Gets the value of the chunk. * @param resolution The aggregate resolution being resolved. * @return Returns the value of the chunk. */ leatherman::ruby::VALUE value(aggregate_resolution& resolution); /** * Gets the chunk's dependencies. * @return Returns the chunk's dependencies. */ leatherman::ruby::VALUE dependencies() const; /** * Sets the chunk's dependencies. * @param dependencies The chunk's dependencies. */ void dependencies(leatherman::ruby::VALUE dependencies); /** * Gets the chunk's block. * @return Returns the chunk's block. */ leatherman::ruby::VALUE block() const; /** * Sets the chunk's block. * @param block The chunk's block. */ void block(leatherman::ruby::VALUE block); private: chunk(chunk const&) = delete; chunk& operator=(chunk const&) = delete; void mark() const; friend struct aggregate_resolution; leatherman::ruby::VALUE _dependencies; leatherman::ruby::VALUE _block; leatherman::ruby::VALUE _value; bool _resolved; bool _resolving; }; }} // namespace facter::ruby facter-3.14.12/lib/inc/internal/ruby/confine.hpp0000644005276200011600000000337713702047406021301 0ustar jenkinsjenkins/** * @file * Declares the class for Ruby fact confines. */ #pragma once #include #include #include namespace facter { namespace ruby { struct module; /** * Represents a Ruby API confine. */ struct confine { /** * Confines a fact resolution based on a fact name and vector of expected values. * @param fact The fact name to confine to. Can be nil if a block is given. * @param expected The expected value or values for the given fact. Can be nil if no fact given. * @param block The block to call for the confine. Can be nil. */ confine(leatherman::ruby::VALUE fact, leatherman::ruby::VALUE expected, leatherman::ruby::VALUE block); /** * Moves the given confine into this confine. * @param other The confine to move into this confine. */ confine(confine&& other); /** * Moves the given confine into this confine. * @param other The confine to move into this confine. * @return Returns this confine. */ confine& operator=(confine&& other); /** * Determines if the confine is suitable or not. * @param facter The Ruby Facter module to resolve facts with. * @return Returns true if the confine is suitable or false if it is not. */ bool suitable(module& facter) const; private: confine(confine const&) = delete; confine& operator=(confine const&) = delete; void mark() const; friend struct resolution; leatherman::ruby::VALUE _fact; leatherman::ruby::VALUE _expected; leatherman::ruby::VALUE _block; }; }} // namespace facter::ruby facter-3.14.12/lib/inc/internal/ruby/fact.hpp0000644005276200011600000000650113702047406020565 0ustar jenkinsjenkins/** * @file * Declares the Ruby Facter::Util::Fact class. */ #pragma once #include #include "resolution.hpp" #include #include namespace facter { namespace facts { struct value; }} // namespace facter::facts namespace facter { namespace ruby { struct module; /** * Represents the Ruby Facter::Util::Fact class. */ struct fact { /** * Defines the Facter::Util::Fact class. * @return Returns the Facter::Util::Fact class. */ static leatherman::ruby::VALUE define(); /** * Creates an instance of the Facter::Util::Fact class. * @param name The name of the fact. * @return Returns the new instance. */ static leatherman::ruby::VALUE create(leatherman::ruby::VALUE name); /** * Gets the name of the fact. * @return Returns the name of the fact. */ leatherman::ruby::VALUE name() const; /** * Gets the value of the fact. * @return Returns the value of the fact. */ leatherman::ruby::VALUE value(); /** * Sets the value of the fact. * @param v The value of the fact. */ void value(leatherman::ruby::VALUE v); /** * Finds a resolution. * @param name The name of the resolution. * @return Returns the resolution or nil if the resolution was not found. */ leatherman::ruby::VALUE find_resolution(leatherman::ruby::VALUE name) const; /** * Defines a resolution. * @param name The name of the resolution. * @param options The resolution options. * @return Returns the resolution instance. */ leatherman::ruby::VALUE define_resolution(leatherman::ruby::VALUE name, leatherman::ruby::VALUE options); /** * Flushes all resolutions for the fact and resets the value. */ void flush(); private: // Construction and assignment fact(); fact(fact const&) = delete; fact& operator=(fact const&) = delete; fact(fact&& other) = delete; fact& operator=(fact&& other) = delete; // Ruby lifecycle functions static leatherman::ruby::VALUE alloc(leatherman::ruby::VALUE klass); static void mark(void* data); static void free(void* data); // Methods called from Ruby static leatherman::ruby::VALUE ruby_initialize(leatherman::ruby::VALUE self, leatherman::ruby::VALUE name); static leatherman::ruby::VALUE ruby_name(leatherman::ruby::VALUE self); static leatherman::ruby::VALUE ruby_value(leatherman::ruby::VALUE self); static leatherman::ruby::VALUE ruby_resolution(leatherman::ruby::VALUE self, leatherman::ruby::VALUE name); static leatherman::ruby::VALUE ruby_define_resolution(int argc, leatherman::ruby::VALUE* argv, leatherman::ruby::VALUE self); static leatherman::ruby::VALUE ruby_flush(leatherman::ruby::VALUE self); leatherman::ruby::VALUE _self; leatherman::ruby::VALUE _name; leatherman::ruby::VALUE _value; std::vector _resolutions; bool _resolved; bool _resolving; size_t _weight; }; }} // namespace facter::ruby facter-3.14.12/lib/inc/internal/ruby/module.hpp0000644005276200011600000001627513702047406021146 0ustar jenkinsjenkins/** * @file * Declares the Ruby Facter module. */ #pragma once #include #include #include "fact.hpp" #include #include #include namespace facter { namespace facts { struct collection; }} // namespace facter::facts namespace leatherman { namespace logging { enum class log_level; }} // namespace leatherman::logging namespace facter { namespace ruby { /** * Represents the Ruby Facter module. */ struct module { /** * Constructs the Ruby Facter module. * @param facts The collection of facts to populate. * @param paths The search paths for loading custom facts. * @param logging_hooks True if the logging hooks should be defined in the Facter API or false if not. */ module(facter::facts::collection& facts, std::vector const& paths = {}, bool logging_hooks = true); /** * Destructs the Facter module. */ ~module(); /** * Add additional search paths for ruby custom facts * @param paths The search paths for loading custom facts */ void search(std::vector const& paths); /** * Loads all custom facts. */ void load_facts(); /** * Resolves all custom facts. */ void resolve_facts(); /** * Clears the facts. * @param clear_collection True if the underlying collection should be cleared or false if not. */ void clear_facts(bool clear_collection = true); /** * Gets the value of the given fact name. * @param name The name of the fact to get the value of. * @return Returns the fact's value or nil if the fact isn't found. */ leatherman::ruby::VALUE fact_value(leatherman::ruby::VALUE name); /** * Converts the given value to a corresponding Ruby object. * @param val The value to convert. * @return Returns a Ruby object for the value. */ leatherman::ruby::VALUE to_ruby(facter::facts::value const* val) const; /** * Normalizes the given fact name. * @param name The fact name to normalize. * @return Returns the normalized fact name. */ leatherman::ruby::VALUE normalize(leatherman::ruby::VALUE name) const; /** * Gets the collection associated with the module. * @return Returns the collection associated with the Facter module. */ facter::facts::collection& facts(); /** * Gets the module's self. * @return Returns the module's self. */ leatherman::ruby::VALUE self() const; /** * Gets the current module. * @return Returns the current module. */ static module* current(); private: // Methods called from Ruby static leatherman::ruby::VALUE ruby_version(leatherman::ruby::VALUE self); static leatherman::ruby::VALUE ruby_add(int argc, leatherman::ruby::VALUE* argv, leatherman::ruby::VALUE self); static leatherman::ruby::VALUE ruby_define_fact(int argc, leatherman::ruby::VALUE* argv, leatherman::ruby::VALUE self); static leatherman::ruby::VALUE ruby_value(leatherman::ruby::VALUE self, leatherman::ruby::VALUE name); static leatherman::ruby::VALUE ruby_fact(leatherman::ruby::VALUE self, leatherman::ruby::VALUE name); static leatherman::ruby::VALUE ruby_debug(leatherman::ruby::VALUE self, leatherman::ruby::VALUE message); static leatherman::ruby::VALUE ruby_debugonce(leatherman::ruby::VALUE self, leatherman::ruby::VALUE message); static leatherman::ruby::VALUE ruby_warn(leatherman::ruby::VALUE self, leatherman::ruby::VALUE message); static leatherman::ruby::VALUE ruby_warnonce(leatherman::ruby::VALUE self, leatherman::ruby::VALUE message); static leatherman::ruby::VALUE ruby_log_exception(int argc, leatherman::ruby::VALUE* argv, leatherman::ruby::VALUE self); static leatherman::ruby::VALUE ruby_set_debugging(leatherman::ruby::VALUE self, leatherman::ruby::VALUE value); static leatherman::ruby::VALUE ruby_get_debugging(leatherman::ruby::VALUE self); static leatherman::ruby::VALUE ruby_set_trace(leatherman::ruby::VALUE self, leatherman::ruby::VALUE value); static leatherman::ruby::VALUE ruby_get_trace(leatherman::ruby::VALUE self); static leatherman::ruby::VALUE ruby_flush(leatherman::ruby::VALUE self); static leatherman::ruby::VALUE ruby_list(leatherman::ruby::VALUE self); static leatherman::ruby::VALUE ruby_to_hash(leatherman::ruby::VALUE self); static leatherman::ruby::VALUE ruby_each(leatherman::ruby::VALUE self); static leatherman::ruby::VALUE ruby_clear(leatherman::ruby::VALUE self); static leatherman::ruby::VALUE ruby_reset(leatherman::ruby::VALUE self); static leatherman::ruby::VALUE ruby_loadfacts(leatherman::ruby::VALUE self); static leatherman::ruby::VALUE ruby_search(int argc, leatherman::ruby::VALUE* argv, leatherman::ruby::VALUE self); static leatherman::ruby::VALUE ruby_search_path(leatherman::ruby::VALUE self); static leatherman::ruby::VALUE ruby_search_external(leatherman::ruby::VALUE self, leatherman::ruby::VALUE paths); static leatherman::ruby::VALUE ruby_search_external_path(leatherman::ruby::VALUE self); static leatherman::ruby::VALUE ruby_which(leatherman::ruby::VALUE self, leatherman::ruby::VALUE binary); static leatherman::ruby::VALUE ruby_exec(leatherman::ruby::VALUE self, leatherman::ruby::VALUE command); static leatherman::ruby::VALUE ruby_execute(int argc, leatherman::ruby::VALUE* argv, leatherman::ruby::VALUE self); static leatherman::ruby::VALUE ruby_on_message(leatherman::ruby::VALUE self); // Helper functions static module* from_self(leatherman::ruby::VALUE self); static leatherman::ruby::VALUE execute_command(std::string const& command, leatherman::ruby::VALUE failure_default, bool raise, uint32_t timeout = 0, bool expand = true); void initialize_search_paths(std::vector const& paths); leatherman::ruby::VALUE load_fact(leatherman::ruby::VALUE value); void load_file(std::string const& path); leatherman::ruby::VALUE create_fact(leatherman::ruby::VALUE name); static leatherman::ruby::VALUE level_to_symbol(leatherman::logging::log_level level); boost::program_options::variables_map _config_file_settings; facter::facts::collection& _collection; std::map _facts; std::set _debug_messages; std::set _warning_messages; std::vector _search_paths; std::vector _additional_search_paths; std::vector _external_search_paths; std::set _loaded_files; bool _loaded_all; leatherman::ruby::VALUE _self; leatherman::ruby::VALUE _on_message_block; static std::map _instances; }; }} // namespace facter::ruby facter-3.14.12/lib/inc/internal/ruby/resolution.hpp0000644005276200011600000000727013702047406022057 0ustar jenkinsjenkins/** * @file * Declares the base class for Ruby resolution classes. */ #pragma once #include #include "confine.hpp" #include #include namespace facter { namespace facts { struct value; }} // namespace facter::facts namespace facter { namespace ruby { struct module; /** * The base class for Ruby resolution classes. */ struct resolution { /** * Gets the name of the resolution. * @return Returns the name of the resolution or nil if the resolution has no name. */ leatherman::ruby::VALUE name() const; /** * Sets the name of the resolution. * @param name The name of the resolution. */ void name(leatherman::ruby::VALUE name); /** * Gets the weight of the resolution. * The higher the weight value, the more precedence is given to the resolution. * @return Returns the weight of the resolution. */ size_t weight() const; /** * Sets the weight of the resolution. * @param weight The weight of the resolution. */ void weight(size_t weight); /** * Gets the value of the resolution. * @return Returns the value of the resolution or nil if the value did not resolve. */ virtual leatherman::ruby::VALUE value(); /** * Sets the value of the resolution. * @param v The value of the resolution. */ void value(leatherman::ruby::VALUE v); /** * Determines if the resolution is suitable. * @param facter The Ruby facter module to resolve facts with. * @returns Returns true if the resolution is allowed or false if it is not. */ bool suitable(module& facter) const; /** * Confines the resolution. * @param confines The confines for the resolution. */ void confine(leatherman::ruby::VALUE confines); /** * Calls the on_flush block for the resolution, if there is one. */ void flush() const; protected: /** * Constructs the resolution. */ resolution(); /** * Destructs the resolution. */ virtual ~resolution(); /** * Defines the base methods on the given class. * @param klass The Ruby class to define the base methods on. */ static void define(leatherman::ruby::VALUE klass); /** * Called to mark this object's values during GC. */ void mark() const; private: // Construction and assignment resolution(resolution const&) = delete; resolution& operator=(resolution const&) = delete; resolution(resolution&& other) = delete; resolution& operator=(resolution&& other) = delete; // Methods called from Ruby static leatherman::ruby::VALUE ruby_confine(int argc, leatherman::ruby::VALUE* argv, leatherman::ruby::VALUE self); static leatherman::ruby::VALUE ruby_has_weight(leatherman::ruby::VALUE self, leatherman::ruby::VALUE value); static leatherman::ruby::VALUE ruby_name(leatherman::ruby::VALUE self); static leatherman::ruby::VALUE ruby_timeout(leatherman::ruby::VALUE self, leatherman::ruby::VALUE timeout); static leatherman::ruby::VALUE ruby_on_flush(leatherman::ruby::VALUE self); leatherman::ruby::VALUE _name; leatherman::ruby::VALUE _value; leatherman::ruby::VALUE _flush_block; std::vector _confines; bool _has_weight; size_t _weight; }; }} // namespace facter::ruby facter-3.14.12/lib/inc/internal/ruby/ruby_value.hpp0000644005276200011600000001035713702047406022031 0ustar jenkinsjenkins/** * @file * Declares the Ruby fact value. */ #pragma once #include #include "fact.hpp" #include #include namespace facter { namespace ruby { /** * Represents a value for a Ruby fact. */ struct ruby_value : facter::facts::value { /** * Constructs a ruby_value. * @param value The Ruby value. */ ruby_value(leatherman::ruby::VALUE value); /** * Destructs a ruby_value. */ ~ruby_value(); /** * Prevents the ruby_value from being copied. */ ruby_value(ruby_value const&) = delete; /** * Prevents the ruby_value from being copied. * @returns Returns this ruby_value. */ ruby_value& operator=(ruby_value const&) = delete; /** * Moves the given ruby_value into this ruby_value. * @param other The ruby_value to move into this ruby_value. */ ruby_value(ruby_value&& other); /** * Moves the given ruby_value into this ruby_value. * @param other The ruby_value to move into this ruby_value. * @return Returns this ruby_value. */ ruby_value& operator=(ruby_value&& other); /** * Converts the value to a JSON value. * @param allocator The allocator to use for creating the JSON value. * @param value The returned JSON value. */ virtual void to_json(facts::json_allocator& allocator, facts::json_value& value) const override; /** * Writes the value to the given stream. * @param os The stream to write to. * @param quoted True if string values should be quoted or false if not. * @param level The current indentation level. * @returns Returns the stream being written to. */ virtual std::ostream& write(std::ostream& os, bool quoted = true, unsigned int level = 1) const override; /** * Writes the value to the given YAML emitter. * @param emitter The YAML emitter to write to. * @returns Returns the given YAML emitter. */ virtual YAML::Emitter& write(YAML::Emitter& emitter) const override; /** * Gets the Ruby value. * @return Returns the Ruby value. */ leatherman::ruby::VALUE value() const; /** * Exposes an owned ruby VALUE as a facter ruby_value * @param child the owned child object to wrap * @param key the query string for the child * @return pointer to the ruby_value wrapper for the child object */ ruby_value const* wrap_child(leatherman::ruby::VALUE child, std::string key) const; /** * Get a cached ruby_value wrapper for a child VALUE * @param key the query string for the child * @return pointer to the ruby_value wrapper, or nullptr if none exists */ ruby_value const* child(const std::string& key) const; private: static void to_json(leatherman::ruby::api const& ruby, leatherman::ruby::VALUE value, facts::json_allocator& allocator, facts::json_value& json); static void write(leatherman::ruby::api const& ruby, leatherman::ruby::VALUE value, std::ostream& os, bool quoted, unsigned int level); static void write(leatherman::ruby::api const& ruby, leatherman::ruby::VALUE value, YAML::Emitter& emitter); leatherman::ruby::VALUE _value; // This is mutable because of constness that's passed down // from the collection object during dot-syntax fact // querying. That query is const over the collection, which // means the collection's actions on values also need to be // const. Unfortunately, we need a place to stash the owning // pointer to the new value that we extract from a ruby object // during lookup. The logical place for that ownership is the // parent ruby object (right here). So we get this cool // mutable field that owns the C++ wrappers for looked-up ruby // values. mutable std::unordered_map> _children; }; }} // namespace facter::ruby facter-3.14.12/lib/inc/internal/ruby/simple_resolution.hpp0000644005276200011600000000357513702047406023434 0ustar jenkinsjenkins/** * @file * Declares the Ruby Facter::Util::Resolution class. */ #pragma once #include "resolution.hpp" namespace facter { namespace ruby { /** * Represents the Ruby Facter::Util::Resolution class. */ struct simple_resolution : resolution { /** * Defines the Facter::Util::Resolution class. * @return Returns theFacter::Util::Resolution class. */ static leatherman::ruby::VALUE define(); /** * Creates an instance of the Facter::Util::Resolution class. * @return Returns the new instance. */ static leatherman::ruby::VALUE create(); /** * Gets the value of the resolution. * @return Returns the value of the resolution or nil if the value did not resolve. */ virtual leatherman::ruby::VALUE value(); private: // Construction and assignment simple_resolution(); simple_resolution(simple_resolution const&) = delete; simple_resolution& operator=(simple_resolution const&) = delete; simple_resolution(simple_resolution&& other) = delete; simple_resolution& operator=(simple_resolution&& other) = delete; // Ruby lifecycle functions static leatherman::ruby::VALUE alloc(leatherman::ruby::VALUE klass); static void mark(void* data); static void free(void* data); static leatherman::ruby::VALUE ruby_setcode(int argc, leatherman::ruby::VALUE* argv, leatherman::ruby::VALUE self); static leatherman::ruby::VALUE ruby_which(leatherman::ruby::VALUE self, leatherman::ruby::VALUE binary); static leatherman::ruby::VALUE ruby_exec(leatherman::ruby::VALUE self, leatherman::ruby::VALUE command); leatherman::ruby::VALUE _self; leatherman::ruby::VALUE _block; leatherman::ruby::VALUE _command; }; }} // namespace facter::ruby facter-3.14.12/lib/inc/internal/util/0000755005276200011600000000000013702047635017135 5ustar jenkinsjenkinsfacter-3.14.12/lib/inc/internal/util/agent.hpp0000644005276200011600000000246213702047406020744 0ustar jenkinsjenkins/** * @file * Declares methods for Facter's integration with the puppet-agent package. */ #pragma once #include #include #include namespace facter { namespace util { namespace agent { /** * Looks for an executable in Facter's built-in PATH. Falls back * to the system PATH (with a warning) if the requested executable * doesn't exist in Facter's PATH. * @param exe the name of the executable * @return the path to the executable */ inline std::string which(const std::string& exe) { #ifdef FACTER_PATH std::string fixed = leatherman::execution::which(exe, {FACTER_PATH}, true); if (!fixed.empty()) { return fixed; } LOG_WARNING("{1} not found at configured location {2}, using PATH instead", exe, FACTER_PATH); #endif return exe; } inline std::string which(const std::string& exe, bool expand) { #ifdef FACTER_PATH std::string fixed = leatherman::execution::which(exe, {FACTER_PATH}, expand); if (!fixed.empty()) { return fixed; } LOG_WARNING("{1} not found at configured location {2}, using PATH instead, parameter expand is {3}", exe, FACTER_PATH, expand); #endif return exe; } }}} // namespace facter::util::agent facter-3.14.12/lib/inc/internal/util/aix/0000755005276200011600000000000013702047635017716 5ustar jenkinsjenkinsfacter-3.14.12/lib/inc/internal/util/aix/odm.hpp0000644005276200011600000003150713702047406021210 0ustar jenkinsjenkins/** * @file * Declares an iterator interface for examining the AIX object data manager */ #include #include #include #include #include #include namespace facter { namespace util { namespace aix { /** * Singleton representing the ODM subsystem. * The ODM subsystem needs to be explicitly initialized and terminated when * it is used. This wraps that initialization/cleanup such that ODM is * initialized when it is first used, and cleaned up when all consumers * have released their references to it. * * some helper methods for interacting with the ODM are also defined here, * since we can't have a `namespace odm` here. */ class odm { public: /// shared_ptr to the odm reference using ptr = std::shared_ptr; /** * Grab a reference to the ODM subsystem to keep it open. * If no references currently exist, this will initialize the ODM * subsystem. * @return */ static ptr open() { static std::weak_ptr self; auto result = self.lock(); if (!result) { result = ptr(new odm); self = result; } return result; } /// deleted copy constructor odm(const odm&) = delete; /// deleted assignment operator /// @return nothing odm& operator=(const odm&) = delete; /** * Clean up the odm library when there are no more users */ ~odm() { odm_terminate(); } /** * Get the error string for an ODM error state. * @return an error string owned by the ODM subsystem */ static std::string error_string() { char* msg; int result = odm_err_msg(odmerrno, &msg); if (result < 0) { return leatherman::locale::format("failed to retrieve ODM error message"); } else { return std::string(msg); } } private: /** * Initialize the ODM library */ odm() { if (odm_initialize() < 0) { throw std::runtime_error(odm::error_string()); } } }; /** * This represents an ODM class as an iterable thing. An ODM * class can be throught of as a table in a typical database. * Each templatized version of this has a singleton instance, * which represents a process' handle to that table. Each process * can open a single ODM class only once, and concurrent * operations are not supported. * * @tparam T the struct that is stored in the ODM class. */ template class odm_class : public std::enable_shared_from_this> { public: /// shared_ptr to an odm_class using ptr = std::shared_ptr>; /** * Implements the standard C++ iterator interface for an * odm_class. Iterators can be incremented and compared for * inequality. This is the minimum to make range-based for * loops work. * * Additional members may need to be added to make other * algorithms play nice. */ class iterator { public: /** * inequality comparison. * @param rhs the other iterator to compare to * @return true if the iterators are not equal */ bool operator != (const iterator& rhs) { return _owner != rhs._owner || _data != rhs._data; } /** * equality comparison. * @param rhs the other iterator to compare to * @return true if the iterators are equal */ bool operator == (const iterator& rhs) { // We could do !(*this != rhs) here, but it's better to inline // the expression for performance reasons. It's simple enough. return _owner == rhs._owner && _data == rhs._data; } /** * pre-increment operator. This invalidates any * references held to the current data of this iterator. * @return the new value of the iterator */ iterator& operator++() { if (!_data || !_owner) { return *this; } free(_data); _data = static_cast(odm_get_next(_owner->_class, nullptr)); // If data == nullptr, we have reached the end of this query if (!_data) { _owner->_locked = false; _owner = ptr(nullptr); } if ((intptr_t)_data < 0) { throw std::runtime_error(odm::error_string()); } return *this; } /** * dereference operator * @return a reference to the held ODM data structure */ const T& operator*() const{ return *_data; } /** * arrow operator * @return a pointer to the held ODM data structure */ const T* operator->() const{ return _data; } /** * Destructor. Frees any held ODM data. */ ~iterator() { if (_data) { free(_data); } } protected: // Constructor is protected so iterators must come from an odm_class or its associated query_proxy /** * Construct an iterator from an odm_class ptr and the first ODM data pointer * @param data the ODM data we point to * @param owner the odm_class object that owns this iterator */ iterator(T* data, ptr owner) : _data(data), _owner(owner) { if (_data) { if (!_owner) { throw std::logic_error(leatherman::locale::format("Tried to construct an iterator with valid data but no owner. Naughty naughty.")); } _owner->_locked = true; } else { // In theory nobody should be constructing us with // null data and valid owner, but why take the risk? _owner = ptr(nullptr); } } private: T *_data; ptr _owner; friend class odm_class::query_proxy; friend class odm_class; }; friend class iterator; // iterator is our friend so it can lock/unlock us. /** * A query_proxy instance represents a query of an ODM * class. The proxy has begin and end methods to allow it to * be used in context of a range-based for loop or other * algorithm. */ class query_proxy { public: /** * Begin the actual ODM query. This locks the odm_class until all valid iterators from this query are destroyed. * @return first iterator of the query */ iterator begin() { if (_owner->_locked) { throw std::logic_error(leatherman::locale::format("Cannot iterate over the same ODM class concurrently")); } auto data = static_cast(odm_get_first(_owner->_class, const_cast(_query.c_str()), nullptr)); if ((intptr_t)data < 0) { throw std::runtime_error(odm::error_string()); } return iterator(data, _owner); } /// @return an end iterator iterator end() { return iterator(nullptr, nullptr); } protected: /** * Construct a query_proxy for an odm_class query * @param query the query string * @param owner the odm_class that owns this query */ template query_proxy(Arg&& query, ptr owner) : _query(std::forward(query)), _owner(owner) {} private: std::string _query; ptr _owner; friend class odm_class; }; friend class query_proxy; // query proxy needs to know if we're locked so it can begin() properly. /** * This class exists purely to allow nicer syntax when * iterating over an odm_class. Using the proxy, it's possible * to use `.begin()` and `.end()`, isntead of `->begin()`. */ class proxy { public: /** * Begin iterating over the entire odm_class. This could * potentially be MANY values, so use wisely. You * probably want query(). This will lock the odm_class * until iteration is complete or all valid iterators are * destructed. * @return an iterator */ iterator begin() { return _self->begin(); } /** * Get the end iterator. All end iterators are identical * @return the end iterator */ iterator end() { return _self->end(); } /** * Begin a query. This does not look the odm_class until * query_proxy::begin() is called. * @param query the query string * @return a query_proxy representing this query */ template query_proxy query(Arg&& query) { return _self->query(std::forward(query)); } protected: /** * Construct a proxy for an odm_class * @param self The odm_class that we proxy for */ proxy(ptr self) : _self(self) {} private: ptr _self; friend class odm_class; }; friend class proxy; // proxy needs to, well, proxy to us. /** * Get a reference to an odm_class named "name". This will * open the class if it is not yet open. The class will be * closed when all existing references are released. * @param name The name of the ODM class. Usually the string form of T * @return an odm_class::proxy object that represents the requested class */ static proxy open(std::string name) { static std::weak_ptr> self; auto result = self.lock(); if (!result) { result = ptr(new odm_class(name)); self = result; } return proxy { result }; } /// deleted default constructor odm_class() = delete; /// deleted copy constructor odm_class(const odm_class&) = delete; /// deleted assignment operator /// @return nothing odm& operator=(const odm&) = delete; /** * Releases an ODM class when there are no more users of it. */ ~odm_class() { odm_close_class(_class); } protected: /** * @see proxy::query * @param query the query string * @return a query_proxy representing the provided query */ template query_proxy query(Arg&& query) { return query_proxy(std::forward(query), this->shared_from_this()); } /** * @see proxy::begin * @return an iterator */ iterator begin() { return query("").begin(); } /** * @see proxy::end * @return the end/invalid iterator */ iterator end() { return iterator(nullptr, nullptr); } private: odm_class(std::string name) : _locked(false) { _the_odm = odm::open(); _class = odm_mount_class(const_cast(name.c_str())); if (reinterpret_cast(_class) < 0) { throw std::runtime_error(odm::error_string()); } _class = odm_open_class_rdonly(_class); if (reinterpret_cast(_class) < 0) { throw std::runtime_error(odm::error_string()); } } protected: /// The ODM class that we are wrapping CLASS_SYMBOL _class; /// whether we are currently locked for iteration bool _locked; private: odm::ptr _the_odm; }; }}} // namespace facter::util::aix facter-3.14.12/lib/inc/internal/util/aix/vmount.hpp0000644005276200011600000001100013702047406021743 0ustar jenkinsjenkins/** * @file * Declares an iterator interface for examining AIX mountpoints */ #include // AIX doesn't properly wrap these function declarations as C-style extern "C" { #include } #include #include namespace facter { namespace util { namespace aix { /** * This wraps the AIX mntctl(MCTL_QUERY, ...) function in an * iterator interface. Each item is a mountctl struct. */ class mountctl { public: /** * Implements the standard C++ iterator interface for mounted * filesystems. Iterators can be incremented and compared for * inequality. This is the minimum to make range-based for * loops work. * * Additional members may need to be added to make other * algorithms play nice. */ class iterator { mountctl* _parent; size_t _idx; struct vmount* _current; protected: /** * Construct an iterator from a mountctl class and the given * vmount object index. * @param parent the mountctl instance that this iterator points to * @param idx the index into the list of vmount instances */ iterator(mountctl* parent, size_t idx) : _parent(parent), _idx(0) { _current = reinterpret_cast(_parent->_buffer.data()); while (_idx < idx) { ++(*this); } } public: iterator() = delete; /// Defaulted move constructor iterator(iterator&&) = default; /// Defaulted move assignment /// @return myself iterator& operator=(iterator&&) = default; /** * inequality comparison * @param rhs the other iterator to compare us to * @return true if the iterators are not equal */ bool operator != (const iterator& rhs) { return _parent != rhs._parent || _idx != rhs._idx; } /** * pre-increment operator. This moves the iterator to * the next position in the list of vmount structs * @return A reference to this iterator after it has advanced. */ iterator& operator++() { // Only increment if we're not at the end // thus, end()++ == end(); if (_idx != _parent->_count) { uintptr_t pos = reinterpret_cast(_current); pos += _current->vmt_length; _current = reinterpret_cast(pos); _idx++; } return *this; } /** * dereference operator * @return a reference to the held vmount structure */ const struct vmount& operator*() const { return *_current; } friend class mountctl; }; friend class iterator; // iterator is our friend so it can access data /** * Query the mounted filesystems and return an iterable instance */ mountctl() { uint32_t buf_sz; int result = mntctl(MCTL_QUERY, sizeof(uint32_t), reinterpret_cast(&buf_sz)); if (result < 0) { throw std::system_error(errno, std::system_category()); } LOG_DEBUG("Required space for mountpoints is {1}", buf_sz); _buffer.reserve(buf_sz); result = mntctl(MCTL_QUERY, buf_sz, _buffer.data()); if (result < 0) { throw std::system_error(errno, std::system_category()); } _count = result; LOG_DEBUG("Got {1} mountpoints", _count); } /// Start the iteration /// @return an iterator that references me. I must outlive this iterator iterator begin() { return iterator(this, 0); } /// Retrieve iterator sentinel value /// @return an iterator that references me. I must outlive this iterator iterator end() { return iterator(this, _count); } protected: /// The data returned from mntctl. Used by the iterator std::vector _buffer; /// The number of elements returned from mntctl size_t _count; }; }}} // namespace facter::util::aix facter-3.14.12/lib/inc/internal/util/bsd/0000755005276200011600000000000013702047635017705 5ustar jenkinsjenkinsfacter-3.14.12/lib/inc/internal/util/bsd/scoped_ifaddrs.hpp0000644005276200011600000000145413702047406023367 0ustar jenkinsjenkins/** * @file * Declares the scoped ifaddrs resource. */ #pragma once #include #include namespace facter { namespace util { namespace bsd { /** * Represents a scoped ifaddrs pointer that automatically is freed when it goes out of scope. */ struct scoped_ifaddrs : leatherman::util::scoped_resource { /** * Default constructor. * This constructor will handle calling getifaddrs. */ scoped_ifaddrs(); /** * Constructs a scoped_descriptor. * @param addrs The ifaddrs pointer to free when destroyed */ explicit scoped_ifaddrs(ifaddrs* addrs); private: static void free(ifaddrs* addrs); }; }}} // namespace facter::util::bsd facter-3.14.12/lib/inc/internal/util/freebsd/0000755005276200011600000000000013702047635020547 5ustar jenkinsjenkinsfacter-3.14.12/lib/inc/internal/util/freebsd/geom.hpp0000644005276200011600000000707713702047406022216 0ustar jenkinsjenkins/** * @file * Declares geom. */ #pragma once #include #include #include #include namespace facter { namespace util { namespace freebsd { /** * geom exceptions */ struct geom_exception : std::runtime_error { /** * Constructs a geom_exception. * @param message the exception message. */ explicit geom_exception(std::string const& message); }; /** * GEOM configuration. * This is a wrapper for struct gconfig. */ class geom_config { private: std::string _name; std::string _value; public: /** * Constructs a GEOM configuration item. * @param name the name of the item. * @param value the valure of the item. */ geom_config(std::string name, std::string value); /** * Returns the name of the item. * @return the name of the item. */ std::string name(); /** * Returns the value of the item. * @return the value of the item. */ std::string value(); }; /** * Base GEOM class capable of storing configuration. */ class geom_object_with_config { private: std::vector _configs; protected: /** * Loads GEOM configuration. * @param conf the first configuration item. */ geom_object_with_config(struct gconf *conf); public: /** * Fetches a configuration value from the object. * @param name the name of the configuration to get. * @return the value of the configuration. */ std::string config(std::string name); }; /** * GEOM providers. * This is a wrapper for struct gprovider. */ class geom_provider : public geom_object_with_config { private: std::string _name; std::string _mode; off_t _mediasize; u_int _sectorsize; off_t _stripeoffset; off_t _stripesize; public: /** * Loads a GEOM provider. * @param provider the provider to load. */ geom_provider(struct gprovider* provider); /** * Returns the provider name. * @return the name of the provider. */ std::string name(); /** * Returns the provider media size. * @return the media size in bytes. */ off_t mediasize(); }; /** * GEOM geoms (sic). * This is a wrapper for struct ggeom. */ class geom_geom : public geom_object_with_config { private: std::string _name; public: /** * Loads a GEOM Geom. * @param geom the Geom to load. */ geom_geom(struct ggeom *geom); /** * Providers attached to this Geom. */ std::vector providers; /** * Returns the name of the Geom. * @return the name of the Geom. */ std::string name(); }; /** * GEOM classes. * This is a wrapper for struct gclass. */ class geom_class { private: struct gmesh _mesh; struct gclass *_class; public: /** * Loads a GEOM class. Throws a geom_exception on failure. * @param type the GEOM class to load. */ geom_class(std::string type); ~geom_class(); /** * Geoms attached to this class. */ std::vector geoms; }; }}} // namespace facter::util::freebsd facter-3.14.12/lib/inc/internal/util/posix/0000755005276200011600000000000013702047635020277 5ustar jenkinsjenkinsfacter-3.14.12/lib/inc/internal/util/posix/scoped_addrinfo.hpp0000644005276200011600000000226013702047406024127 0ustar jenkinsjenkins/** * @file * Declares the scoped addrinfo resource. */ #pragma once #include #include #include #include #include #include namespace facter { namespace util { namespace posix { /** * Represents a scoped addrinfo for POSIX systems. * Automatically frees the address information pointer when it goes out of scope. */ struct scoped_addrinfo : leatherman::util::scoped_resource { /** * Constructs a scoped_addrinfo. * @param hostname The hostname to get the address information of. */ explicit scoped_addrinfo(std::string const& hostname); /** * Constructs a scoped_addrinfo. * @param info The address info to free when destroyed. */ explicit scoped_addrinfo(addrinfo* info); /** * Returns the result of any call to getaddrinfo. * @returns Returns the result of any call to getaddrinfo. */ int result() const; private: static void free(addrinfo* info); int _result; }; }}} // namespace facter::util::posix facter-3.14.12/lib/inc/internal/util/posix/scoped_descriptor.hpp0000644005276200011600000000136713702047406024526 0ustar jenkinsjenkins/** * @file * Declares the scoped descriptor resource for managing file/socket descriptors. */ #pragma once #include #include namespace facter { namespace util { namespace posix { /** * Represents a scoped file descriptor for POSIX systems. * Automatically closes the file descriptor when it goes out of scope. */ struct scoped_descriptor : leatherman::util::scoped_resource { /** * Constructs a scoped_descriptor. * @param descriptor The file descriptor to close when destroyed. */ explicit scoped_descriptor(int descriptor); private: static void close(int descriptor); }; }}} // namespace facter::util::posix facter-3.14.12/lib/inc/internal/util/posix/utmpx_file.hpp0000644005276200011600000000412213702047406023157 0ustar jenkinsjenkins/** * @file * Declares an interface for querying the contents of the utmpx file */ #pragma once #include namespace facter { namespace util { namespace posix { /** * Class representing a utmpx file. We create only one instance at a time since * the utmpx API calls deal with global state. See https://linux.die.net/man/3/getutxid * for the documentation. */ class utmpx_file { public: /** * Constructs a utmpx_file instance. We only do this if no other utmpx_file instance exists, * which we can determine by querying the 'instance_exists' static variable. Otherwise, * we throw an std::logic_error. */ utmpx_file(); /// deleted copy constructor utmpx_file(const utmpx_file&) = delete; /// deleted assignment operator /// @return nothing utmpx_file& operator=(const utmpx_file&) = delete; /** * Destroys our utmpx_file instance. Here, we also set `instance_exists` to false so that another * utmpx_file instance can be created. */ ~utmpx_file(); /** * Returns a pointer to the utmpx entry corresponding to the passed-in query. Make sure * that the calling instance does not go out of scope after invoking this method, otherwise * the data in the returned utmpx entry will be garbage. Note that this will move the * underlying utmpx file pointer forward, so be sure to call reset() if you want subsequent * calls to this routine to always start from the beginning of the utmpx file. * @param query the utmpx query. See https://www.systutorials.com/docs/linux/man/5-utmpx/ * @return pointer to the utmpx entry satisfying the query */ const utmpx* query(utmpx const& query) const; /** * Resets the utmpx file. */ void reset() const; private: static bool instance_exists; // set to true if a utmpx_file instance exists, false otherwise }; }}} // namespace facter::util::posix facter-3.14.12/lib/inc/internal/util/scoped_bio.hpp0000644005276200011600000000142413702047406021751 0ustar jenkinsjenkins/** * @file * Declares the scoped BIO (OpenSSL) resource. */ #pragma once #include #include namespace facter { namespace util { /** * Represents a scoped OpenSSL BIO object. * Automatically frees the BIO when it goes out of scope. */ struct scoped_bio : leatherman::util::scoped_resource { /** * Constructs a scoped_bio. * @param method The BIO_METHOD to use. */ explicit scoped_bio(const BIO_METHOD* method); /** * Constructs a scoped_bio. * @param bio The BIO to free when destroyed. */ explicit scoped_bio(BIO* bio); private: static void free(BIO* bio); }; }} // namespace facter::util facter-3.14.12/lib/inc/internal/util/scoped_file.hpp0000644005276200011600000000156613702047406022126 0ustar jenkinsjenkins/** * @file * Declares the scoped file resource for managing FILE pointers. */ #pragma once #include #include #include namespace facter { namespace util { /** * Represents a scoped file. * Automatically closes the file when it goes out of scope. */ struct scoped_file : leatherman::util::scoped_resource { /** * Constructs a scoped_file. * @param path The path to the file. * @param mode The open mode. */ explicit scoped_file(std::string const& path, std::string const& mode); /** * Constructs a scoped_file. * @param file The existing file pointer. */ explicit scoped_file(std::FILE* file); private: static void close(std::FILE* file); }; }} // namespace facter::util facter-3.14.12/lib/inc/internal/util/solaris/0000755005276200011600000000000013702047635020611 5ustar jenkinsjenkinsfacter-3.14.12/lib/inc/internal/util/solaris/k_stat.hpp0000644005276200011600000001253613702047406022612 0ustar jenkinsjenkins/** * @file * Declares the k_stat resource. */ #pragma once #include "scoped_kstat.hpp" #include #include namespace facter { namespace util { namespace solaris { /** * Wrapper around the kstat_t structure. */ struct k_stat_entry { /** * Default constructor. Should be created only by k_stat[] call. * @param kp The kstat_t pointer we wrap. * */ k_stat_entry(kstat_t* kp); /** * Get a value out of our kstat_named_t * @param attrib The attribute we are looking up * @tparam T the datatype of the attribute result * @return Returns the looked up value. */ template T value(const std::string& attrib) const; /** * Gets the name of the entry. * @return Returns the name of entry. */ std::string name(); /** * Gets the class of the entry. * @return Returns the class of entry. */ std::string klass(); /** * Gets the module of the entry. * @return Returns the module of entry. */ std::string module(); /** * Gets the instance of the entry. * @return Returns the instance of entry. */ int instance(); private: /** * Lookup the given attribute in the kstat structure. * @param attrib The attribute we are looking up * @return Returns the looked up value. */ kstat_named_t* lookup(const std::string& attrib) const; /** * Lookup the given attribute in the kstat structure, and verify that * the datatype is correct. * @param datatype The datatype of attribute we are looking up * @param attrib The attribute we are looking up * @return Returns the looked up value. */ kstat_named_t* lookup(const int datatype, const std::string& attrib) const; /** * The main data in the struct, obtained by a lookup */ kstat_t* k_stat; }; /** * The template specializations for k_stat_entry::value with ulong_t. * @param attrib The attribute we are looking up. * @return Returns the looked up value. */ template<> ulong_t k_stat_entry::value(const std::string& attrib) const; /** * The template specializations for k_stat_entry::value with long. * @param attrib The attribute we are looking up. * @return Returns the looked up value. */ template<> long k_stat_entry::value(const std::string& attrib) const; /** * The template specializations for k_stat_entry::value with int32_t. * @param attrib The attribute we are looking up. * @return Returns the looked up value. */ template<> int32_t k_stat_entry::value(const std::string& attrib) const; /** * The template specializations for k_stat_entry::value with uint32_t. * @param attrib The attribute we are looking up. * @return Returns the looked up value. */ template<> uint32_t k_stat_entry::value(const std::string& attrib) const; /** * The template specializations for k_stat_entry::value with int64_t. * @param attrib The attribute we are looking up. * @return Returns the looked up value. */ template<> int64_t k_stat_entry::value(const std::string& attrib) const; /** * The template specializations for k_stat_entry::value with uint64_t. * @param attrib The attribute we are looking up. * @return Returns the looked up value. */ template<> uint64_t k_stat_entry::value(const std::string& attrib) const; /** * The template specializations for k_stat_entry::value with string. * @param attrib The attribute we are looking up. * @return Returns the looked up value. */ template<> std::string k_stat_entry::value(const std::string& attrib) const; /** * Wrapper around the kstat_ctl structure. It represents our * link to kernel stats, and controls the lifetime of any kstat * structures associated. (They go away when it is closed) */ struct k_stat { /** * Default constructor. * This constructor will handle calling kstat_open. */ k_stat(); /** * Function for looking up a module. * @param module The module name. * @return Returns the vector containing all entries. */ std::vector operator[](std::string const& module); /** * Function for looking up a module, and an entry name. * @param entry A pair containing module name an entry name. * @return Returns the vector containing all entries. */ std::vector operator[](std::pair const& entry); /** * Function for looking up a module, and an instance id. * @param entry A pair containing module name an instance id. * @return Returns the vector containing all entries. */ std::vector operator[](std::pair const& entry); private: std::vector lookup(std::string const& module, int instance, std::string const& name); scoped_kstat ctrl; }; }}} // namespace facter::util::solaris facter-3.14.12/lib/inc/internal/util/solaris/scoped_kstat.hpp0000644005276200011600000000210113702047406023773 0ustar jenkinsjenkins/** * @file * Declares the scoped kstat resource. */ #pragma once #include #include namespace facter { namespace util { namespace solaris { /** * kstat exceptions */ struct kstat_exception : std::runtime_error { /** * Constructs a kstat_exception. * @param message The exception message. */ explicit kstat_exception(std::string const& message); }; /** * Represents a scoped kstat pointer that automatically is freed when it goes out of scope. */ struct scoped_kstat : leatherman::util::scoped_resource { /** * Default constructor. * This constructor will handle calling kstat_open. */ scoped_kstat(); /** * Constructs a scoped_descriptor. * @param ctrl The kstat pointer to free when destroyed */ explicit scoped_kstat(kstat_ctl* ctrl); private: static void close(kstat_ctl* ctrl); }; }}} // namespace facter::util::solaris facter-3.14.12/lib/inc/internal/util/versions.hpp0000644005276200011600000000212513702047406021512 0ustar jenkinsjenkins/** * @file * Defines helpers for parsing various version strings */ #pragma once #include #include namespace facter { namespace util { namespace versions { /** * Helper function for parsing X.Y from an arbitrary version * string. If there is a .Z component, it will be ignored. * @param version the version string to parse * @return A tuple of */ inline std::tuple major_minor(const std::string& version) { std::string major, minor; auto pos = version.find('.'); if (pos != std::string::npos) { auto second = version.find('.', pos+1); decltype(second) end; major = version.substr(0, pos); if (second != std::string::npos) { end = second - (pos + 1); } else { end = std::string::npos; } minor = version.substr(pos+1, end); } return std::make_tuple(std::move(major), std::move(minor)); } }}} // namespace facter::util::versions facter-3.14.12/lib/inc/internal/util/windows/0000755005276200011600000000000013702047635020627 5ustar jenkinsjenkinsfacter-3.14.12/lib/inc/internal/util/windows/wsa.hpp0000644005276200011600000000600613702047406022130 0ustar jenkinsjenkins/** * @file * Declares utility functions for interacting with Winsock */ #pragma once #include #include #include namespace facter { namespace util { namespace windows { /** * Exception thrown when wsa initialization fails. */ struct wsa_exception : std::runtime_error { /** * Constructs a wsa_exception. * @param message The exception message. */ explicit wsa_exception(std::string const& message); }; /** * A class for initiating use of the Winsock DLL, providing wrappers for WSA calls. */ struct wsa { /** * Initializes Winsock. Throws a wsa_exception on failure. */ wsa(); /** * Do WSA cleanup. */ ~wsa(); /** * Use default move constructer. */ wsa(wsa&&) = default; /** * Use default move assignment. * @return Returns this instance. */ wsa& operator=(wsa&&) = default; /** * This wraps calling WSAAddressToString to translate a sockaddr structure to an IPv4 or IPv6 string. * Throws an exception if passed an IPv6 argument on Windows Server 2003 and IPv6 support isn't installed. * See https://social.technet.microsoft.com/Forums/windowsserver/en-US/7166dcbe-d493-4da1-8441-5b5d6aa0d21c/ipv6-and-windows-server-2003 * @param addr The socket address structure. * @return An IPv4 or IPv6 string, or an empty string if addr is uninitialized. */ std::string saddress_to_string(SOCKET_ADDRESS const& addr) const; /** * This adapts sockaddr structs to the SOCKET_ADDRESS wrapper. * @param addr A sockaddr-like structure (sockaddr, sockaddr_in, sockaddr_in6). * @return An IPv4 or IPv6 string. */ template std::string address_to_string(T &addr) const { return saddress_to_string(SOCKET_ADDRESS{reinterpret_cast(&addr), sizeof(T)}); } /** * This wraps calling WSAStringToAddress to translate a an IPv4 or IPv6 string to a sockaddr structure. * @tparam T The expected sockaddr structure, either sockaddr_in or sockaddr_in6. * @tparam ADDRESS_FAMILY The expected address family, either AF_INET or AF_INET6. * @param addr An IPv4 or IPv6 string. * @return A sockaddr structure containing the IPv4 or IPv6 sockaddr data. */ template T string_to_address(std::string const& addr) const { T sock = {ADDRESS_FAMILY}; string_fill_sockaddr(reinterpret_cast(&sock), addr, sizeof(T)); return sock; } private: wsa(wsa const&) = delete; wsa& operator=(wsa const&) = delete; void string_fill_sockaddr(sockaddr *sock, std::string const& addr, int size) const; }; }}} // namespace facter::util::windows facter-3.14.12/lib/inc/internal/util/yaml.hpp0000644005276200011600000000117513702047406020610 0ustar jenkinsjenkins/** * @file * Declares helper methods for dealing with YAML */ #pragma once #include #include namespace YAML { class Node; } namespace facter { namespace facts { struct collection; struct array_value; struct map_value; }} namespace facter { namespace util { namespace yaml { /** * Adds a YAML value into a Facter collection. */ void add_value(std::string const& name, YAML::Node const& node, facts::collection& facts, std::vector& names, facts::array_value* array_parent = nullptr, facts::map_value* map_parent = nullptr); }}} facter-3.14.12/lib/schema/0000755005276200011600000000000013702047635015033 5ustar jenkinsjenkinsfacter-3.14.12/lib/schema/core_facts.pot0000644005276200011600000016260013702047406017670 0ustar jenkinsjenkins# CORE FACTS SCHEMA # Copyright (C) 2016 Puppet, LLC # This file is distributed under the same license as the FACTER package. # FIRST AUTHOR , 2016. # #, fuzzy msgid "" msgstr "" "Project-Id-Version: FACTER \n" "Report-Msgid-Bugs-To: docs@puppet.com\n" "POT-Creation-Date: \n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" "Language: \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=INTEGER; plural=EXPRESSION;\n" #. aio_agent_version description msgid "Return the version of the puppet-agent package that installed facter." msgstr "" #. aio_agent_version resolution msgid "All platforms: use the compile-time enabled version definition." msgstr "" #. architecture description msgid "Return the operating system's hardware architecture." msgstr "" #. architecture resolution msgid "POSIX platforms: use the `uname` function to retrieve the OS hardware architecture." msgstr "" #. architecture resolution msgid "Windows: use the `GetNativeSystemInfo` function to retrieve the OS hardware architecture." msgstr "" #. architecture caveats msgid "Linux: Debian, Gentoo, kFreeBSD, and Ubuntu use "amd64" for "x86_64" and Gentoo uses "x86" for "i386"." msgstr "" #. augeas description msgid "Return information about augeas." msgstr "" #. augeas resolution msgid "All platforms: query augparse for augeas metadata." msgstr "" #. augeasversion description msgid "Return the version of augeas." msgstr "" #. augeasversion resolution msgid "All platforms: query augparse for the augeas version." msgstr "" #. blockdevices description msgid "Return a comma-separated list of block devices." msgstr "" #. blockdevices resolution msgid "Linux: parse the contents of `/sys/block//`." msgstr "" #. blockdevices resolution msgid "Solaris: use the `kstat` function to query disk information." msgstr "" #. blockdevices caveats msgid "Linux: kernel 2.6+ is required due to the reliance on sysfs." msgstr "" #. blockdevice__model description msgid "Return the model name of block devices attached to the system." msgstr "" #. blockdevice__model resolution msgid "Linux: parse the contents of `/sys/block//device/model` to retrieve the model name/number for a device." msgstr "" #. blockdevice__model resolution msgid "Solaris: use the `kstat` function to query disk information." msgstr "" #. blockdevice__model caveats msgid "Linux: kernel 2.6+ is required due to the reliance on sysfs." msgstr "" #. blockdevice__size description msgid "Return the size of a block device in bytes." msgstr "" #. blockdevice__size resolution msgid "Linux: parse the contents of `/sys/block//size` to receive the size (multiplying by 512 to correct for blocks-to-bytes)." msgstr "" #. blockdevice__size resolution msgid "Solaris: use the `kstat` function to query disk information." msgstr "" #. blockdevice__size caveats msgid "Linux: kernel 2.6+ is required due to the reliance on sysfs." msgstr "" #. blockdevice__vendor description msgid "Return the vendor name of block devices attached to the system." msgstr "" #. blockdevice__vendor resolution msgid "Linux: parse the contents of `/sys/block//device/vendor` to retrieve the vendor for a device." msgstr "" #. blockdevice__vendor resolution msgid "Solaris: use the `kstat` function to query disk information." msgstr "" #. blockdevice__vendor caveats msgid "Linux: kernel 2.6+ is required due to the reliance on sysfs." msgstr "" #. bios_release_date description msgid "Return the release date of the system BIOS." msgstr "" #. bios_release_date resolution msgid "Linux: parse the contents of `/sys/class/dmi/id/bios_date` to retrieve the system BIOS release date." msgstr "" #. bios_release_date resolution msgid "Solaris: use the `smbios` utility to retrieve the system BIOS release date." msgstr "" #. bios_release_date caveats msgid "Linux: kernel 2.6+ is required due to the reliance on sysfs." msgstr "" #. bios_vendor description msgid "Return the vendor of the system BIOS." msgstr "" #. bios_vendor resolution msgid "Linux: parse the contents of `/sys/class/dmi/id/bios_vendor` to retrieve the system BIOS vendor." msgstr "" #. bios_vendor resolution msgid "Solaris: use the `smbios` utility to retrieve the system BIOS vendor." msgstr "" #. bios_vendor caveats msgid "Linux: kernel 2.6+ is required due to the reliance on sysfs." msgstr "" #. bios_version description msgid "Return the version of the system BIOS." msgstr "" #. bios_version resolution msgid "Linux: parse the contents of `/sys/class/dmi/id/bios_version` to retrieve the system BIOS version." msgstr "" #. bios_version resolution msgid "Solaris: use the `smbios` utility to retrieve the system BIOS version." msgstr "" #. bios_version caveats msgid "Linux: kernel 2.6+ is required due to the reliance on sysfs." msgstr "" #. boardassettag description msgid "Return the system board asset tag." msgstr "" #. boardassettag resolution msgid "Linux: parse the contents of `/sys/class/dmi/id/board_asset_tag` to retrieve the system board asset tag." msgstr "" #. boardassettag caveats msgid "Linux: kernel 2.6+ is required due to the reliance on sysfs." msgstr "" #. boardmanufacturer description msgid "Return the system board manufacturer." msgstr "" #. boardmanufacturer resolution msgid "Linux: parse the contents of `/sys/class/dmi/id/board_vendor` to retrieve the system board manufacturer." msgstr "" #. boardmanufacturer caveats msgid "Linux: kernel 2.6+ is required due to the reliance on sysfs." msgstr "" #. boardproductname description msgid "Return the system board product name." msgstr "" #. boardproductname resolution msgid "Linux: parse the contents of `/sys/class/dmi/id/board_name` to retrieve the system board product name." msgstr "" #. boardproductname caveats msgid "Linux: kernel 2.6+ is required due to the reliance on sysfs." msgstr "" #. boardserialnumber description msgid "Return the system board serial number." msgstr "" #. boardserialnumber resolution msgid "Linux: parse the contents of `/sys/class/dmi/id/board_serial` to retrieve the system board serial number." msgstr "" #. boardserialnumber caveats msgid "Linux: kernel 2.6+ is required due to the reliance on sysfs." msgstr "" #. chassisassettag description msgid "Return the system chassis asset tag." msgstr "" #. chassisassettag resolution msgid "Linux: parse the contents of `/sys/class/dmi/id/chassis_asset_tag` to retrieve the system chassis asset tag." msgstr "" #. chassisassettag resolution msgid "Solaris: use the `smbios` utility to retrieve the system chassis asset tag." msgstr "" #. chassisassettag caveats msgid "Linux: kernel 2.6+ is required due to the reliance on sysfs." msgstr "" #. chassistype description msgid "Return the system chassis type." msgstr "" #. chassistype resolution msgid "Linux: parse the contents of `/sys/class/dmi/id/chassis_type` to retrieve the system chassis type." msgstr "" #. chassistype resolution msgid "Solaris: use the `smbios` utility to retrieve the system chassis type." msgstr "" #. chassistype caveats msgid "Linux: kernel 2.6+ is required due to the reliance on sysfs." msgstr "" #. dhcp_servers description msgid "Return the DHCP servers for the system." msgstr "" #. dhcp_servers resolution msgid "Linux: parse `dhclient` lease files or use the `dhcpcd` utility to retrieve the DHCP servers." msgstr "" #. dhcp_servers resolution msgid "Mac OSX: use the `ipconfig` utility to retrieve the DHCP servers." msgstr "" #. dhcp_servers resolution msgid "Solaris: use the `dhcpinfo` utility to retrieve the DHCP servers." msgstr "" #. dhcp_servers resolution msgid "Windows: use the `GetAdaptersAddresses` (Windows Server 2003: `GetAdaptersInfo`) function to retrieve the DHCP servers." msgstr "" #. disks description msgid "Return the disk (block) devices attached to the system." msgstr "" #. disks resolution msgid "Linux: parse the contents of `/sys/block//`." msgstr "" #. disks resolution msgid "Solaris: use the `kstat` function to query disk information." msgstr "" #. disks caveats msgid "Linux: kernel 2.6+ is required due to the reliance on sysfs." msgstr "" #. dmi description msgid "Return the system management information." msgstr "" #. dmi resolution msgid "Linux: parse the contents of `/sys/class/dmi/id/` to retrieve system management information." msgstr "" #. dmi resolution msgid "Mac OSX: use the `sysctl` function to retrieve system management information." msgstr "" #. dmi resolution msgid "Solaris: use the `smbios`, `prtconf`, and `uname` utilities to retrieve system management information." msgstr "" #. dmi resolution msgid "Windows: use WMI to retrieve system management information." msgstr "" #. dmi caveats msgid "Linux: kernel 2.6+ is required due to the reliance on sysfs." msgstr "" #. domain description msgid "Return the network domain of the system." msgstr "" #. domain resolution msgid "POSIX platforms: use the `getaddrinfo` function to retrieve the network domain." msgstr "" #. domain resolution msgid "Windows: query the registry to retrieve the network domain; falls back to the primary interface's domain if not set in the registry." msgstr "" #. ec2_metadata description msgid "Return the Amazon Elastic Compute Cloud (EC2) instance metadata." msgstr "" #. ec2_metadata description msgid "Please see the [EC2 instance metadata documentation](http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-instance-metadata.html) for the contents of this fact." msgstr "" #. ec2_metadata resolution msgid "EC2: query the EC2 metadata endpoint and parse the response." msgstr "" #. ec2_metadata caveats msgid "All platforms: `libfacter` must be built with `libcurl` support." msgstr "" #. ec2_userdata description msgid "Return the Amazon Elastic Compute Cloud (EC2) instance user data." msgstr "" #. ec2_userdata description msgid "Please see the [EC2 instance user data documentation](http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-instance-metadata.html) for the contents of this fact." msgstr "" #. ec2_userdata resolution msgid "EC2: query the EC2 user data endpoint and parse the response." msgstr "" #. ec2_userdata caveats msgid "All platforms: `libfacter` must be built with `libcurl` support." msgstr "" #. env_windows_installdir description msgid "Return the path of the directory in which Puppet was installed." msgstr "" #. env_windows_installdir resolution msgid "Windows: This fact is specific to the Windows MSI generated environment, and is" msgstr "" #. env_windows_installdir resolution msgid " set using the `environment.bat` script that configures the runtime environment" msgstr "" #. env_windows_installdir resolution msgid " for all Puppet executables. Please see [the original commit in the puppet_for_the_win repo](https://github.com/puppetlabs/puppet_for_the_win/commit/0cc32c1a09550c13d725b200d3c0cc17d93ec262) for more information." msgstr "" #. env_windows_installdir caveats msgid "This fact is specific to Windows, and will not resolve on any other platform." msgstr "" #. facterversion description msgid "Return the version of facter." msgstr "" #. facterversion resolution msgid "All platforms: use the built-in version of libfacter." msgstr "" #. filesystems description msgid "Return the usable file systems for block or disk devices." msgstr "" #. filesystems resolution msgid "Linux: parse the contents of `/proc/filesystems` to retrieve the usable file systems." msgstr "" #. filesystems resolution msgid "Mac OSX: use the `getfsstat` function to retrieve the usable file systems." msgstr "" #. filesystems resolution msgid "Solaris: use the `sysdef` utility to retrieve the usable file systems." msgstr "" #. filesystems caveats msgid "Linux: The proc file system must be mounted." msgstr "" #. filesystems caveats msgid "Mac OSX: The usable file systems is limited to the file system of mounted devices." msgstr "" #. fqdn description msgid "Return the fully qualified domain name (FQDN) of the system." msgstr "" #. fqdn resolution msgid "POSIX platforms: use the `getaddrinfo` function to retrieve the FQDN or use host and domain names." msgstr "" #. fqdn resolution msgid "Windows: use the host and domain names to build the FQDN." msgstr "" #. gce description msgid "Return the Google Compute Engine (GCE) metadata." msgstr "" #. gce description msgid "Please see the [GCE metadata documentation](https://cloud.google.com/compute/docs/metadata) for the contents of this fact." msgstr "" #. gce resolution msgid "GCE: query the GCE metadata endpoint and parse the response." msgstr "" #. gce caveats msgid "All platforms: `libfacter` must be built with `libcurl` support." msgstr "" #. gid description msgid "Return the group identifier (GID) of the user running facter." msgstr "" #. gid resolution msgid "POSIX platforms: use the `getegid` fuction to retrieve the group identifier." msgstr "" #. hardwareisa description msgid "Return the hardware instruction set architecture (ISA)." msgstr "" #. hardwareisa resolution msgid "POSIX platforms: use `uname` to retrieve the hardware ISA." msgstr "" #. hardwareisa resolution msgid "Windows: use WMI to retrieve the hardware ISA." msgstr "" #. hardwaremodel description msgid "Return the operating system's hardware model." msgstr "" #. hardwaremodel resolution msgid "POSIX platforms: use the `uname` function to retrieve the OS hardware model." msgstr "" #. hardwaremodel resolution msgid "Windows: use the `GetNativeSystemInfo` function to retrieve the OS hardware model." msgstr "" #. hostname description msgid "Return the host name of the system." msgstr "" #. hostname resolution msgid "POSIX platforms: use the `gethostname` function to retrieve the host name" msgstr "" #. hostname resolution msgid "Windows: use the `GetComputerNameExW` function to retrieve the host name." msgstr "" #. id description msgid "Return the user identifier (UID) of the user running facter." msgstr "" #. id resolution msgid "POSIX platforms: use the `geteuid` fuction to retrieve the user identifier." msgstr "" #. identity description msgid "Return the identity information of the user running facter." msgstr "" #. identity resolution msgid "POSIX platforms: use the `getegid`, `getpwuid_r`, `geteuid`, and `getgrgid_r` functions to retrieve the identity information; use the result of the `geteuid() == 0` test as the value of the privileged element" msgstr "" #. identity resolution msgid "Windows: use the `GetUserNameExW` function to retrieve the identity information; use the `GetTokenInformation` to get the current process token elevation status and use it as the value of the privileged element on versions of Windows supporting the token elevation, on older versions of Windows use the `CheckTokenMembership` to test whether the well known local Administrators group SID is enabled in the current thread impersonation token and use the test result as the value of the privileged element" msgstr "" #. interfaces description msgid "Return the comma-separated list of network interface names." msgstr "" #. interfaces resolution msgid "Linux: use the `getifaddrs` function to retrieve the network interface names." msgstr "" #. interfaces resolution msgid "Mac OSX: use the `getifaddrs` function to retrieve the network interface names." msgstr "" #. interfaces resolution msgid "Solaris: use the `ioctl` function to retrieve the network interface names." msgstr "" #. interfaces resolution msgid "Windows: use the `GetAdaptersAddresses` function to retrieve the network interface names." msgstr "" #. ipaddress description msgid "Return the IPv4 address for the default network interface." msgstr "" #. ipaddress resolution msgid "Linux: use the `getifaddrs` function to retrieve the network interface address." msgstr "" #. ipaddress resolution msgid "Mac OSX: use the `getifaddrs` function to retrieve the network interface address." msgstr "" #. ipaddress resolution msgid "Solaris: use the `ioctl` function to retrieve the network interface address." msgstr "" #. ipaddress resolution msgid "Windows: use the `GetAdaptersAddresses` function to retrieve the network interface address." msgstr "" #. ipaddress6 description msgid "Return the IPv6 address for the default network interface." msgstr "" #. ipaddress6 resolution msgid "Linux: use the `getifaddrs` function to retrieve the network interface address." msgstr "" #. ipaddress6 resolution msgid "Mac OSX: use the `getifaddrs` function to retrieve the network interface address." msgstr "" #. ipaddress6 resolution msgid "Solaris: use the `ioctl` function to retrieve the network interface address." msgstr "" #. ipaddress6 resolution msgid "Windows: use the `GetAdaptersAddresses` function to retrieve the network interface address." msgstr "" #. ipaddress6_ description msgid "Return the IPv6 address for a network interface." msgstr "" #. ipaddress6_ resolution msgid "Linux: use the `getifaddrs` function to retrieve the network interface address." msgstr "" #. ipaddress6_ resolution msgid "Mac OSX: use the `getifaddrs` function to retrieve the network interface address." msgstr "" #. ipaddress6_ resolution msgid "Solaris: use the `ioctl` function to retrieve the network interface address." msgstr "" #. ipaddress6_ resolution msgid "Windows: use the `GetAdaptersAddresses` function to retrieve the network interface address." msgstr "" #. ipaddress_ description msgid "Return the IPv4 address for a network interface." msgstr "" #. ipaddress_ resolution msgid "Linux: use the `getifaddrs` function to retrieve the network interface address." msgstr "" #. ipaddress_ resolution msgid "Mac OSX: use the `getifaddrs` function to retrieve the network interface address." msgstr "" #. ipaddress_ resolution msgid "Solaris: use the `ioctl` function to retrieve the network interface address." msgstr "" #. ipaddress_ resolution msgid "Windows: use the `GetAdaptersAddresses` function to retrieve the network interface address." msgstr "" #. is_virtual description msgid "Return whether or not the host is a virtual machine." msgstr "" #. is_virtual resolution msgid "Linux: use procfs or utilities such as `vmware` and `virt-what` to retrieve virtual machine status." msgstr "" #. is_virtual resolution msgid "Mac OSX: use the system profiler to retrieve virtual machine status." msgstr "" #. is_virtual resolution msgid "Solaris: use the `zonename` utility to retrieve virtual machine status." msgstr "" #. is_virtual resolution msgid "Windows: use WMI to retrieve virtual machine status." msgstr "" #. kernel description msgid "Return the kernel's name." msgstr "" #. kernel resolution msgid "POSIX platforms: use the `uname` function to retrieve the kernel name." msgstr "" #. kernel resolution msgid "Windows: use the value of `windows` for all Windows versions." msgstr "" #. kernelmajversion description msgid "Return the kernel's major version." msgstr "" #. kernelmajversion resolution msgid "POSIX platforms: use the `uname` function to retrieve the kernel's major version." msgstr "" #. kernelmajversion resolution msgid "Windows: use the file version of `kernel32.dll` to retrieve the kernel's major version." msgstr "" #. kernelrelease description msgid "Return the kernel's release." msgstr "" #. kernelrelease resolution msgid "POSIX platforms: use the `uname` function to retrieve the kernel's release." msgstr "" #. kernelrelease resolution msgid "Windows: use the file version of `kernel32.dll` to retrieve the kernel's release." msgstr "" #. kernelversion description msgid "Return the kernel's version." msgstr "" #. kernelversion resolution msgid "POSIX platforms: use the `uname` function to retrieve the kernel's version." msgstr "" #. kernelversion resolution msgid "Windows: use the file version of `kernel32.dll` to retrieve the kernel's version." msgstr "" #. ldom description msgid "Return Solaris LDom information from the `virtinfo` utility." msgstr "" #. ldom resolution msgid "Solaris: use the `virtinfo` utility to retrieve LDom information." msgstr "" #. ldom_ description msgid "Return Solaris LDom information." msgstr "" #. ldom_ resolution msgid "Solaris: use the `virtinfo` utility to retrieve LDom information." msgstr "" #. load_averages description msgid "Return the load average over the last 1, 5 and 15 minutes." msgstr "" #. load_averages resolution msgid "POSIX platforms: use `getloadavg` function to retrieve the system load averages." msgstr "" #. lsbdistcodename description msgid "Return the Linux Standard Base (LSB) distribution code name." msgstr "" #. lsbdistcodename resolution msgid "Linux: use the `lsb_release` utility to retrieve the LSB distribution code name." msgstr "" #. lsbdistcodename caveats msgid "Linux: Requires that the `lsb_release` utility be installed." msgstr "" #. lsbdistdescription description msgid "Return the Linux Standard Base (LSB) distribution description." msgstr "" #. lsbdistdescription resolution msgid "Linux: use the `lsb_release` utility to retrieve the LSB distribution description." msgstr "" #. lsbdistdescription caveats msgid "Linux: Requires that the `lsb_release` utility be installed." msgstr "" #. lsbdistid description msgid "Return the Linux Standard Base (LSB) distribution identifier." msgstr "" #. lsbdistid resolution msgid "Linux: use the `lsb_release` utility to retrieve the LSB distribution identifier." msgstr "" #. lsbdistid caveats msgid "Linux: Requires that the `lsb_release` utility be installed." msgstr "" #. lsbdistrelease description msgid "Return the Linux Standard Base (LSB) distribution release." msgstr "" #. lsbdistrelease resolution msgid "Linux: use the `lsb_release` utility to retrieve the LSB distribution release." msgstr "" #. lsbdistrelease caveats msgid "Linux: Requires that the `lsb_release` utility be installed." msgstr "" #. lsbmajdistrelease description msgid "Return the Linux Standard Base (LSB) major distribution release." msgstr "" #. lsbmajdistrelease resolution msgid "Linux: use the `lsb_release` utility to retrieve the LSB major distribution release." msgstr "" #. lsbmajdistrelease caveats msgid "Linux: Requires that the `lsb_release` utility be installed." msgstr "" #. lsbminordistrelease description msgid "Return the Linux Standard Base (LSB) minor distribution release." msgstr "" #. lsbminordistrelease resolution msgid "Linux: use the `lsb_release` utility to retrieve the LSB minor distribution release." msgstr "" #. lsbminordistrelease caveats msgid "Linux: Requires that the `lsb_release` utility be installed." msgstr "" #. lsbrelease description msgid "Return the Linux Standard Base (LSB) release." msgstr "" #. lsbrelease resolution msgid "Linux: use the `lsb_release` utility to retrieve the LSB release." msgstr "" #. lsbrelease caveats msgid "Linux: Requires that the `lsb_release` utility be installed." msgstr "" #. macaddress description msgid "Return the MAC address for the default network interface." msgstr "" #. macaddress resolution msgid "Linux: use the `getifaddrs` function to retrieve the network interface address." msgstr "" #. macaddress resolution msgid "Mac OSX: use the `getifaddrs` function to retrieve the network interface address." msgstr "" #. macaddress resolution msgid "Solaris: use the `ioctl` function to retrieve the network interface address." msgstr "" #. macaddress resolution msgid "Windows: use the `GetAdaptersAddresses` function to retrieve the network interface address." msgstr "" #. macaddress_ description msgid "Return the MAC address for a network interface." msgstr "" #. macaddress_ resolution msgid "Linux: use the `getifaddrs` function to retrieve the network interface address." msgstr "" #. macaddress_ resolution msgid "Mac OSX: use the `getifaddrs` function to retrieve the network interface address." msgstr "" #. macaddress_ resolution msgid "Solaris: use the `ioctl` function to retrieve the network interface address." msgstr "" #. macaddress_ resolution msgid "Windows: use the `GetAdaptersAddresses` function to retrieve the network interface address." msgstr "" #. macosx_buildversion description msgid "Return the Mac OSX build version." msgstr "" #. macosx_buildversion resolution msgid "Mac OSX: use the `sw_vers` utility to retrieve the Mac OSX build version." msgstr "" #. macosx_productname description msgid "Return the Mac OSX product name." msgstr "" #. macosx_productname resolution msgid "Mac OSX: use the `sw_vers` utility to retrieve the Mac OSX product name." msgstr "" #. macosx_productversion description msgid "Return the Mac OSX product version." msgstr "" #. macosx_productversion resolution msgid "Mac OSX: use the `sw_vers` utility to retrieve the Mac OSX product version." msgstr "" #. macosx_productversion_major description msgid "Return the Mac OSX product major version." msgstr "" #. macosx_productversion_major resolution msgid "Mac OSX: use the `sw_vers` utility to retrieve the Mac OSX product major version." msgstr "" #. macosx_productversion_minor description msgid "Return the Mac OSX product minor version." msgstr "" #. macosx_productversion_minor resolution msgid "Mac OSX: use the `sw_vers` utility to retrieve the Mac OSX product minor version." msgstr "" #. manufacturer description msgid "Return the system manufacturer." msgstr "" #. manufacturer resolution msgid "Linux: parse the contents of `/sys/class/dmi/id/sys_vendor` to retrieve the system manufacturer." msgstr "" #. manufacturer resolution msgid "Solaris: use the `prtconf` utility to retrieve the system manufacturer." msgstr "" #. manufacturer resolution msgid "Windows: use WMI to retrieve the system manufacturer." msgstr "" #. manufacturer caveats msgid "Linux: kernel 2.6+ is required due to the reliance on sysfs." msgstr "" #. memory description msgid "Return the system memory information." msgstr "" #. memory resolution msgid "Linux: parse the contents of `/proc/meminfo` to retrieve the system memory information." msgstr "" #. memory resolution msgid "Mac OSX: use the `sysctl` function to retrieve the system memory information." msgstr "" #. memory resolution msgid "Solaris: use the `kstat` function to retrieve the system memory information." msgstr "" #. memory resolution msgid "Windows: use the `GetPerformanceInfo` function to retrieve the system memory information." msgstr "" #. memoryfree description msgid "Return the display size of the free system memory (e.g. "1 GiB")." msgstr "" #. memoryfree resolution msgid "Linux: parse the contents of `/proc/meminfo` to retrieve the free system memory." msgstr "" #. memoryfree resolution msgid "Mac OSX: use the `sysctl` function to retrieve the free system memory." msgstr "" #. memoryfree resolution msgid "Solaris: use the `kstat` function to retrieve the free system memory." msgstr "" #. memoryfree resolution msgid "Windows: use the `GetPerformanceInfo` function to retrieve the free system memory." msgstr "" #. memoryfree_mb description msgid "Return the size of the free system memory, in mebibytes." msgstr "" #. memoryfree_mb resolution msgid "Linux: parse the contents of `/proc/meminfo` to retrieve the free system memory." msgstr "" #. memoryfree_mb resolution msgid "Mac OSX: use the `sysctl` function to retrieve the free system memory." msgstr "" #. memoryfree_mb resolution msgid "Solaris: use the `kstat` function to retrieve the free system memory." msgstr "" #. memoryfree_mb resolution msgid "Windows: use the `GetPerformanceInfo` function to retrieve the free system memory." msgstr "" #. memorysize description msgid "Return the display size of the total system memory (e.g. "1 GiB")." msgstr "" #. memorysize resolution msgid "Linux: parse the contents of `/proc/meminfo` to retrieve the total system memory." msgstr "" #. memorysize resolution msgid "Mac OSX: use the `sysctl` function to retrieve the total system memory." msgstr "" #. memorysize resolution msgid "Solaris: use the `kstat` function to retrieve the total system memory." msgstr "" #. memorysize resolution msgid "Windows: use the `GetPerformanceInfo` function to retrieve the total system memory." msgstr "" #. memorysize_mb description msgid "Return the size of the total system memory, in mebibytes." msgstr "" #. memorysize_mb resolution msgid "Linux: parse the contents of `/proc/meminfo` to retrieve the total system memory." msgstr "" #. memorysize_mb resolution msgid "Mac OSX: use the `sysctl` function to retrieve the total system memory." msgstr "" #. memorysize_mb resolution msgid "Solaris: use the `kstat` function to retrieve the total system memory." msgstr "" #. memorysize_mb resolution msgid "Windows: use the `GetPerformanceInfo` function to retrieve the total system memory." msgstr "" #. mountpoints description msgid "Return the current mount points of the system." msgstr "" #. mountpoints resolution msgid "Linux: use the `setmntent` function to retrieve the mount points." msgstr "" #. mountpoints resolution msgid "Mac OSX: use the `getfsstat` function to retrieve the mount points." msgstr "" #. mountpoints resolution msgid "Solaris: parse the contents of `/etc/mnttab` to retrieve the mount points." msgstr "" #. mtu_ description msgid "Return the Maximum Transmission Unit (MTU) for a network interface." msgstr "" #. mtu_ resolution msgid "Linux: use the `ioctl` function to retrieve the network interface MTU." msgstr "" #. mtu_ resolution msgid "Mac OSX: use the `getifaddrs` function to retrieve the network interface MTU." msgstr "" #. mtu_ resolution msgid "Solaris: use the `ioctl` function to retrieve the network interface MTU." msgstr "" #. mtu_ resolution msgid "Windows: use the `GetAdaptersAddresses` function to retrieve the network interface MTU." msgstr "" #. netmask description msgid "Return the IPv4 netmask for the default network interface." msgstr "" #. netmask resolution msgid "Linux: use the `getifaddrs` function to retrieve the network interface netmask." msgstr "" #. netmask resolution msgid "Mac OSX: use the `getifaddrs` function to retrieve the network interface netmask." msgstr "" #. netmask resolution msgid "Solaris: use the `ioctl` function to retrieve the network interface netmask." msgstr "" #. netmask resolution msgid "Windows: use the `GetAdaptersAddresses` (Windows Server 2003: `GetAdaptersInfo`) function to retrieve the network interface netmask." msgstr "" #. netmask6 description msgid "Return the IPv6 netmask for the default network interface." msgstr "" #. netmask6 resolution msgid "Linux: use the `getifaddrs` function to retrieve the network interface netmask." msgstr "" #. netmask6 resolution msgid "Mac OSX: use the `getifaddrs` function to retrieve the network interface netmask." msgstr "" #. netmask6 resolution msgid "Solaris: use the `ioctl` function to retrieve the network interface netmask." msgstr "" #. netmask6 resolution msgid "Windows: use the `GetAdaptersAddresses` function to retrieve the network interface netmask." msgstr "" #. netmask6 caveats msgid "Windows Server 2003: IPv6 netmasks are not supported." msgstr "" #. netmask6_ description msgid "Return the IPv6 netmask for a network interface." msgstr "" #. netmask6_ resolution msgid "Linux: use the `getifaddrs` function to retrieve the network interface netmask." msgstr "" #. netmask6_ resolution msgid "Mac OSX: use the `getifaddrs` function to retrieve the network interface netmask." msgstr "" #. netmask6_ resolution msgid "Solaris: use the `ioctl` function to retrieve the network interface netmask." msgstr "" #. netmask6_ resolution msgid "Windows: use the `GetAdaptersAddresses` function to retrieve the network interface netmask." msgstr "" #. netmask6_ caveats msgid "Windows Server 2003: IPv6 netmasks are not supported." msgstr "" #. netmask_ description msgid "Return the IPv4 netmask for a network interface." msgstr "" #. netmask_ resolution msgid "Linux: use the `getifaddrs` function to retrieve the network interface netmask." msgstr "" #. netmask_ resolution msgid "Mac OSX: use the `getifaddrs` function to retrieve the network interface netmask." msgstr "" #. netmask_ resolution msgid "Solaris: use the `ioctl` function to retrieve the network interface netmask." msgstr "" #. netmask_ resolution msgid "Windows: use the `GetAdaptersAddresses` (Windows Server 2003: `GetAdaptersInfo`) function to retrieve the network interface netmask." msgstr "" #. network description msgid "Return the IPv4 network for the default network interface." msgstr "" #. network resolution msgid "Linux: use the `getifaddrs` function to retrieve the network interface network." msgstr "" #. network resolution msgid "Mac OSX: use the `getifaddrs` function to retrieve the network interface network." msgstr "" #. network resolution msgid "Solaris: use the `ioctl` function to retrieve the network interface network." msgstr "" #. network resolution msgid "Windows: use the `GetAdaptersAddresses` function to retrieve the network interface network." msgstr "" #. network6 description msgid "Return the IPv6 network for the default network interface." msgstr "" #. network6 resolution msgid "Linux: use the `getifaddrs` function to retrieve the network interface network." msgstr "" #. network6 resolution msgid "Mac OSX: use the `getifaddrs` function to retrieve the network interface network." msgstr "" #. network6 resolution msgid "Solaris: use the `ioctl` function to retrieve the network interface network." msgstr "" #. network6 resolution msgid "Windows: use the `GetAdaptersAddresses` function to retrieve the network interface network." msgstr "" #. network6_ description msgid "Return the IPv6 network for a network interface." msgstr "" #. network6_ resolution msgid "Linux: use the `getifaddrs` function to retrieve the network interface network." msgstr "" #. network6_ resolution msgid "Mac OSX: use the `getifaddrs` function to retrieve the network interface network." msgstr "" #. network6_ resolution msgid "Solaris: use the `ioctl` function to retrieve the network interface network." msgstr "" #. network6_ resolution msgid "Windows: use the `GetAdaptersAddresses` function to retrieve the network interface network." msgstr "" #. network_ description msgid "Return the IPv4 network for a network interface." msgstr "" #. network_ resolution msgid "Linux: use the `getifaddrs` function to retrieve the network interface network." msgstr "" #. network_ resolution msgid "Mac OSX: use the `getifaddrs` function to retrieve the network interface network." msgstr "" #. network_ resolution msgid "Solaris: use the `ioctl` function to retrieve the network interface network." msgstr "" #. network_ resolution msgid "Windows: use the `GetAdaptersAddresses` function to retrieve the network interface network." msgstr "" #. networking description msgid "Return the networking information for the system." msgstr "" #. networking resolution msgid "Linux: use the `getifaddrs` function to retrieve the network interfaces." msgstr "" #. networking resolution msgid "Mac OSX: use the `getifaddrs` function to retrieve the network interfaces." msgstr "" #. networking resolution msgid "Solaris: use the `ioctl` function to retrieve the network interfaces." msgstr "" #. networking resolution msgid "Windows: use the `GetAdaptersAddresses` function to retrieve the network interfaces." msgstr "" #. networking caveats msgid "Windows Server 2003: the `GetAdaptersInfo` function is used for DHCP and netmask lookup. This function does not support IPv6 netmasks." msgstr "" #. operatingsystem description msgid "Return the name of the operating system." msgstr "" #. operatingsystem resolution msgid "All platforms: default to the kernel name." msgstr "" #. operatingsystem resolution msgid "Linux: use various release files in `/etc` to retrieve the OS name." msgstr "" #. operatingsystemmajrelease description msgid "Return the major release of the operating system." msgstr "" #. operatingsystemmajrelease resolution msgid "All platforms: default to the major version of the kernel release." msgstr "" #. operatingsystemmajrelease resolution msgid "Linux: parse the contents of release files in `/etc` to retrieve the OS major release." msgstr "" #. operatingsystemmajrelease resolution msgid "Solaris: parse the contents of `/etc/release` to retrieve the OS major release." msgstr "" #. operatingsystemmajrelease resolution msgid "Windows: use WMI to retrieve the OS major release." msgstr "" #. operatingsystemmajrelease caveats msgid "Linux: for Ubuntu, the major release is X.Y (e.g. "10.4")." msgstr "" #. operatingsystemrelease description msgid "Return the release of the operating system." msgstr "" #. operatingsystemrelease resolution msgid "All platforms: default to the kernel release." msgstr "" #. operatingsystemrelease resolution msgid "Linux: parse the contents of release files in `/etc` to retrieve the OS release." msgstr "" #. operatingsystemrelease resolution msgid "Solaris: parse the contents of `/etc/release` to retrieve the OS release." msgstr "" #. operatingsystemrelease resolution msgid "Windows: use WMI to retrieve the OS release." msgstr "" #. os description msgid "Return information about the host operating system." msgstr "" #. os resolution msgid "Linux: use the `lsb_release` utility and parse the contents of release files in `/etc` to retrieve the OS information." msgstr "" #. os resolution msgid "OSX: use the `sw_vers` utility to retrieve the OS information." msgstr "" #. os resolution msgid "Solaris: parse the contents of `/etc/release` to retrieve the OS information." msgstr "" #. os resolution msgid "Windows: use WMI to retrieve the OS information." msgstr "" #. osfamily description msgid "Return the family of the operating system." msgstr "" #. osfamily resolution msgid "All platforms: default to the kernel name." msgstr "" #. osfamily resolution msgid "Linux: map various Linux distributions to their base distribution (e.g. Ubuntu is a "Debian" distro)." msgstr "" #. osfamily resolution msgid "Solaris: map various Solaris-based operating systems to the "Solaris" family." msgstr "" #. osfamily resolution msgid "Windows: use "windows" as the family name." msgstr "" #. partitions description msgid "Return the disk partitions of the system." msgstr "" #. partitions resolution msgid "Linux: use `libblkid` to retrieve the disk partitions." msgstr "" #. partitions caveats msgid "Linux: `libfacter` must be built with `libblkid` support." msgstr "" #. path description msgid "Return the PATH environment variable." msgstr "" #. path resolution msgid "All platforms: retrieve the value of the PATH environment variable." msgstr "" #. physicalprocessorcount description msgid "Return the count of physical processors." msgstr "" #. physicalprocessorcount resolution msgid "Linux: parse the contents `/sys/devices/system/cpu/` and `/proc/cpuinfo` to retrieve the count of physical processors." msgstr "" #. physicalprocessorcount resolution msgid "Mac OSX: use the `sysctl` function to retrieve the count of physical processors." msgstr "" #. physicalprocessorcount resolution msgid "Solaris: use the `kstat` function to retrieve the count of physical processors." msgstr "" #. physicalprocessorcount resolution msgid "Windows: use WMI to retrieve the count of physical processors." msgstr "" #. physicalprocessorcount caveats msgid "Linux: kernel 2.6+ is required due to the reliance on sysfs." msgstr "" #. processor description msgid "Return the model string of processor N." msgstr "" #. processor resolution msgid "Linux: parse the contents of `/proc/cpuinfo` to retrieve the processor model string." msgstr "" #. processor resolution msgid "Mac OSX: use the `sysctl` function to retrieve the processor model string." msgstr "" #. processor resolution msgid "Solaris: use the `kstat` function to retrieve the processor model string." msgstr "" #. processor resolution msgid "Windows: use WMI to retrieve the processor model string." msgstr "" #. processorcount description msgid "Return the count of logical processors." msgstr "" #. processorcount resolution msgid "Linux: parse the contents `/sys/devices/system/cpu/` and `/proc/cpuinfo` to retrieve the count of logical processors." msgstr "" #. processorcount resolution msgid "Mac OSX: use the `sysctl` function to retrieve the count of logical processors." msgstr "" #. processorcount resolution msgid "Solaris: use the `kstat` function to retrieve the count of logical processors." msgstr "" #. processorcount resolution msgid "Windows: use WMI to retrieve the count of logical processors." msgstr "" #. processorcount caveats msgid "Linux: kernel 2.6+ is required due to the reliance on sysfs." msgstr "" #. processors description msgid "Return information about the system's processors." msgstr "" #. processors resolution msgid "Linux: parse the contents `/sys/devices/system/cpu/` and `/proc/cpuinfo` to retrieve the processor information." msgstr "" #. processors resolution msgid "Mac OSX: use the `sysctl` function to retrieve the processor information." msgstr "" #. processors resolution msgid "Solaris: use the `kstat` function to retrieve the processor information." msgstr "" #. processors resolution msgid "Windows: use WMI to retrieve the processor information." msgstr "" #. productname description msgid "Return the system product name." msgstr "" #. productname resolution msgid "Linux: parse the contents of `/sys/class/dmi/id/product_name` to retrieve the system product name." msgstr "" #. productname resolution msgid "Mac OSX: use the `sysctl` function to retrieve the system product name." msgstr "" #. productname resolution msgid "Solaris: use the `smbios` utility to retrieve the system product name." msgstr "" #. productname resolution msgid "Windows: use WMI to retrieve the system product name." msgstr "" #. productname caveats msgid "Linux: kernel 2.6+ is required due to the reliance on sysfs." msgstr "" #. ruby description msgid "Return information about the Ruby loaded by facter." msgstr "" #. ruby resolution msgid "All platforms: Use `RbConfig`, `RUBY_PLATFORM`, and `RUBY_VERSION` to retrieve information about Ruby." msgstr "" #. ruby caveats msgid "All platforms: facter must be able to locate `libruby`." msgstr "" #. rubyplatform description msgid "Return the platform Ruby was built for." msgstr "" #. rubyplatform resolution msgid "All platforms: use `RUBY_PLATFORM` from the Ruby loaded by facter." msgstr "" #. rubyplatform caveats msgid "All platforms: facter must be able to locate `libruby`." msgstr "" #. rubysitedir description msgid "Return the path to Ruby's site library directory." msgstr "" #. rubysitedir resolution msgid "All platforms: use `RbConfig` from the Ruby loaded by facter." msgstr "" #. rubysitedir caveats msgid "All platforms: facter must be able to locate `libruby`." msgstr "" #. rubyversion description msgid "Return the version of Ruby." msgstr "" #. rubyversion resolution msgid "All platforms: use `RUBY_VERSION` from the Ruby loaded by facter." msgstr "" #. rubyversion caveats msgid "All platforms: facter must be able to locate `libruby`." msgstr "" #. selinux description msgid "Return whether Security-Enhanced Linux (SELinux) is enabled." msgstr "" #. selinux resolution msgid "Linux: parse the contents of `/proc/self/mounts` to determine if SELinux is enabled." msgstr "" #. selinux_config_mode description msgid "Return the configured Security-Enhanced Linux (SELinux) mode." msgstr "" #. selinux_config_mode resolution msgid "Linux: parse the contents of `/etc/selinux/config` to retrieve the configured SELinux mode." msgstr "" #. selinux_config_policy description msgid "Return the configured Security-Enhanced Linux (SELinux) policy." msgstr "" #. selinux_config_policy resolution msgid "Linux: parse the contents of `/etc/selinux/config` to retrieve the configured SELinux policy." msgstr "" #. selinux_current_mode description msgid "Return the current Security-Enhanced Linux (SELinux) mode." msgstr "" #. selinux_current_mode resolution msgid "Linux: parse the contents of `/enforce` to retrieve the current SELinux mode." msgstr "" #. selinux_enforced description msgid "Return whether Security-Enhanced Linux (SELinux) is enforced." msgstr "" #. selinux_enforced resolution msgid "Linux: parse the contents of `/enforce` to retrieve the current SELinux mode." msgstr "" #. selinux_policyversion description msgid "Return the Security-Enhanced Linux (SELinux) policy version." msgstr "" #. selinux_policyversion resolution msgid "Linux: parse the contents of `/policyvers` to retrieve the SELinux policy version." msgstr "" #. serialnumber description msgid "Return the system product serial number." msgstr "" #. serialnumber resolution msgid "Linux: parse the contents of `/sys/class/dmi/id/product_name` to retrieve the system product serial number." msgstr "" #. serialnumber resolution msgid "Solaris: use the `smbios` utility to retrieve the system product serial number." msgstr "" #. serialnumber resolution msgid "Windows: use WMI to retrieve the system product serial number." msgstr "" #. serialnumber caveats msgid "Linux: kernel 2.6+ is required due to the reliance on sysfs." msgstr "" #. solaris_zones description msgid "Return information about Solaris zones." msgstr "" #. solaris_zones resolution msgid "Solaris: use the `zoneadm` and `zonename` utilities to retrieve information about the Solaris zones." msgstr "" #. sp_ description msgid "Return Mac OSX system profiler information." msgstr "" #. sp_ resolution msgid "Mac OSX: use the `system_profiler` utility to retrieve system profiler information." msgstr "" #. ssh description msgid "Return SSH public keys and fingerprints." msgstr "" #. ssh resolution msgid "POSIX platforms: parse SSH public key files and derive fingerprints." msgstr "" #. ssh caveats msgid "POSIX platforms: facter must be built with OpenSSL support." msgstr "" #. sshkey description msgid "Return the SSH public key for the algorithm." msgstr "" #. sshkey resolution msgid "POSIX platforms: parse SSH public key files." msgstr "" #. sshkey caveats msgid "POSIX platforms: facter must be built with OpenSSL support." msgstr "" #. sshfp_ description msgid "Return the SSH fingerprints for the algorithm's public key." msgstr "" #. sshfp_ resolution msgid "POSIX platforms: derive the SHA1 and SHA256 fingerprints; delimit with a new line character." msgstr "" #. sshfp_ caveats msgid "POSIX platforms: facter must be built with OpenSSL support." msgstr "" #. swapencrypted description msgid "Return whether or not the swap is encrypted." msgstr "" #. swapencrypted resolution msgid "Mac OSX: use the `sysctl` function to retrieve swap encryption status." msgstr "" #. swapfree description msgid "Return the display size of the free swap memory (e.g. "1 GiB")." msgstr "" #. swapfree resolution msgid "Linux: parse the contents of `/proc/meminfo` to retrieve the free swap memory." msgstr "" #. swapfree resolution msgid "Mac OSX: use the `sysctl` function to retrieve the free swap memory." msgstr "" #. swapfree resolution msgid "Solaris: use the `swapctl` function to retrieve the free swap memory." msgstr "" #. swapfree_mb description msgid "Return the size of the free swap memory, in mebibytes." msgstr "" #. swapfree_mb resolution msgid "Linux: parse the contents of `/proc/meminfo` to retrieve the free swap memory." msgstr "" #. swapfree_mb resolution msgid "Mac OSX: use the `sysctl` function to retrieve the free swap memory." msgstr "" #. swapfree_mb resolution msgid "Solaris: use the `swapctl` function to retrieve the free swap memory." msgstr "" #. swapsize description msgid "Return the display size of the total swap memory (e.g. "1 GiB")." msgstr "" #. swapsize resolution msgid "Linux: parse the contents of `/proc/meminfo` to retrieve the total swap memory." msgstr "" #. swapsize resolution msgid "Mac OSX: use the `sysctl` function to retrieve the total swap memory." msgstr "" #. swapsize resolution msgid "Solaris: use the `swapctl` function to retrieve the total swap memory." msgstr "" #. swapsize_mb description msgid "Return the size of the total swap memory, in mebibytes." msgstr "" #. swapsize_mb resolution msgid "Linux: parse the contents of `/proc/meminfo` to retrieve the total swap memory." msgstr "" #. swapsize_mb resolution msgid "Mac OSX: use the `sysctl` function to retrieve the total swap memory." msgstr "" #. swapsize_mb resolution msgid "Solaris: use the `swapctl` function to retrieve the total swap memory." msgstr "" #. system32 description msgid "Return the path to the System32 directory on Windows." msgstr "" #. system32 resolution msgid "Windows: use the `SHGetFolderPath` function to retrieve the path to the System32 directory." msgstr "" #. system_profiler description msgid "Return information from the Mac OSX system profiler." msgstr "" #. system_profiler resolution msgid "Mac OSX: use the `system_profiler` utility to retrieve system profiler information." msgstr "" #. system_uptime description msgid "Return the system uptime information." msgstr "" #. system_uptime resolution msgid "Linux: use the `sysinfo` function to retrieve the system uptime." msgstr "" #. system_uptime resolution msgid "POSIX platforms: use the `uptime` utility to retrieve the system uptime." msgstr "" #. system_uptime resolution msgid "Solaris: use the `kstat` function to retrieve the system uptime." msgstr "" #. system_uptime resolution msgid "Windows: use WMI to retrieve the system uptime." msgstr "" #. timezone description msgid "Return the system timezone." msgstr "" #. timezone resolution msgid "POSIX platforms: use the `localtime_r` function to retrieve the system timezone." msgstr "" #. timezone resolution msgid "Windows: use the `localtime_s` function to retrieve the system timezone." msgstr "" #. uptime description msgid "Return the system uptime." msgstr "" #. uptime resolution msgid "Linux: use the `sysinfo` function to retrieve the system uptime." msgstr "" #. uptime resolution msgid "POSIX platforms: use the `uptime` utility to retrieve the system uptime." msgstr "" #. uptime resolution msgid "Solaris: use the `kstat` function to retrieve the system uptime." msgstr "" #. uptime resolution msgid "Windows: use WMI to retrieve the system uptime." msgstr "" #. uptime_days description msgid "Return the system uptime days." msgstr "" #. uptime_days resolution msgid "Linux: use the `sysinfo` function to retrieve the system uptime days." msgstr "" #. uptime_days resolution msgid "POSIX platforms: use the `uptime` utility to retrieve the system uptime days." msgstr "" #. uptime_days resolution msgid "Solaris: use the `kstat` function to retrieve the system uptime days." msgstr "" #. uptime_days resolution msgid "Windows: use WMI to retrieve the system uptime days." msgstr "" #. uptime_hours description msgid "Return the system uptime hours." msgstr "" #. uptime_hours resolution msgid "Linux: use the `sysinfo` function to retrieve the system uptime hours." msgstr "" #. uptime_hours resolution msgid "POSIX platforms: use the `uptime` utility to retrieve the system uptime hours." msgstr "" #. uptime_hours resolution msgid "Solaris: use the `kstat` function to retrieve the system uptime hours." msgstr "" #. uptime_hours resolution msgid "Windows: use WMI to retrieve the system uptime hours." msgstr "" #. uptime_seconds description msgid "Return the system uptime seconds." msgstr "" #. uptime_seconds resolution msgid "Linux: use the `sysinfo` function to retrieve the system uptime seconds." msgstr "" #. uptime_seconds resolution msgid "POSIX platforms: use the `uptime` utility to retrieve the system uptime seconds." msgstr "" #. uptime_seconds resolution msgid "Solaris: use the `kstat` function to retrieve the system uptime seconds." msgstr "" #. uptime_seconds resolution msgid "Windows: use WMI to retrieve the system uptime seconds." msgstr "" #. uuid description msgid "Return the system product unique identifier." msgstr "" #. uuid resolution msgid "Linux: parse the contents of `/sys/class/dmi/id/product_uuid` to retrieve the system product unique identifier." msgstr "" #. uuid resolution msgid "Solaris: use the `smbios` utility to retrieve the system product unique identifier." msgstr "" #. uuid caveats msgid "Linux: kernel 2.6+ is required due to the reliance on sysfs." msgstr "" #. virtual description msgid "Return the hypervisor name for virtual machines or "physical" for physical machines." msgstr "" #. virtual resolution msgid "Linux: use procfs or utilities such as `vmware` and `virt-what` to retrieve virtual machine name." msgstr "" #. virtual resolution msgid "Mac OSX: use the system profiler to retrieve virtual machine name." msgstr "" #. virtual resolution msgid "Solaris: use the `zonename` utility to retrieve virtual machine name." msgstr "" #. virtual resolution msgid "Windows: use WMI to retrieve virtual machine name." msgstr "" #. xen description msgid "Return metadata for the Xen hypervisor." msgstr "" #. xen resolution msgid "POSIX platforms: use `/usr/lib/xen-common/bin/xen-toolstack` to locate xen admin commands if available, otherwise fallback to `/usr/sbin/xl` or `/usr/sbin/xm`. Use the found command to execute the `list` query." msgstr "" #. xen caveats msgid "POSIX platforms: confined to Xen privileged virtual machines." msgstr "" #. xendomains description msgid "Return a list of comma-separated active Xen domain names." msgstr "" #. xendomains resolution msgid "POSIX platforms: see the `xen` structured fact." msgstr "" #. xendomains caveats msgid "POSIX platforms: confined to Xen privileged virtual machines." msgstr "" #. zfs_featurenumbers description msgid "Return the comma-delimited feature numbers for ZFS." msgstr "" #. zfs_featurenumbers resolution msgid "Solaris: use the `zfs` utility to retrieve the feature numbers for ZFS" msgstr "" #. zfs_featurenumbers caveats msgid "Solaris: the `zfs` utility must be present." msgstr "" #. zfs_version description msgid "Return the version for ZFS." msgstr "" #. zfs_version resolution msgid "Solaris: use the `zfs` utility to retrieve the version for ZFS" msgstr "" #. zfs_version caveats msgid "Solaris: the `zfs` utility must be present." msgstr "" #. zone__brand description msgid "Return the brand for the Solaris zone." msgstr "" #. zone__brand resolution msgid "Solaris: use the `zoneadm` utility to retrieve the brand for the Solaris zone." msgstr "" #. zone__brand caveats msgid "Solaris: the `zoneadm` utility must be present." msgstr "" #. zone__iptype description msgid "Return the IP type for the Solaris zone." msgstr "" #. zone__iptype resolution msgid "Solaris: use the `zoneadm` utility to retrieve the IP type for the Solaris zone." msgstr "" #. zone__iptype caveats msgid "Solaris: the `zoneadm` utility must be present." msgstr "" #. zone__name description msgid "Return the name for the Solaris zone." msgstr "" #. zone__name resolution msgid "Solaris: use the `zoneadm` utility to retrieve the name for the Solaris zone." msgstr "" #. zone__name caveats msgid "Solaris: the `zoneadm` utility must be present." msgstr "" #. zone__uuid description msgid "Return the unique identifier for the Solaris zone." msgstr "" #. zone__uuid resolution msgid "Solaris: use the `zoneadm` utility to retrieve the unique identifier for the Solaris zone." msgstr "" #. zone__uuid caveats msgid "Solaris: the `zoneadm` utility must be present." msgstr "" #. zone__id description msgid "Return the zone identifier for the Solaris zone." msgstr "" #. zone__id resolution msgid "Solaris: use the `zoneadm` utility to retrieve the zone identifier for the Solaris zone." msgstr "" #. zone__id caveats msgid "Solaris: the `zoneadm` utility must be present." msgstr "" #. zone__path description msgid "Return the zone path for the Solaris zone." msgstr "" #. zone__path resolution msgid "Solaris: use the `zoneadm` utility to retrieve the zone path for the Solaris zone." msgstr "" #. zone__path caveats msgid "Solaris: the `zoneadm` utility must be present." msgstr "" #. zone__status description msgid "Return the zone state for the Solaris zone." msgstr "" #. zone__status resolution msgid "Solaris: use the `zoneadm` utility to retrieve the zone state for the Solaris zone." msgstr "" #. zone__status caveats msgid "Solaris: the `zoneadm` utility must be present." msgstr "" #. zonename description msgid "Return the name of the current Solaris zone." msgstr "" #. zonename resolution msgid "Solaris: use the `zonename` utility to retrieve the current zone name." msgstr "" #. zonename caveats msgid "Solaris: the `zonename` utility must be present." msgstr "" #. zones description msgid "Return the count of Solaris zones." msgstr "" #. zones resolution msgid "Solaris: use the `zoneadm` utility to retrieve the count of Solaris zones." msgstr "" #. zones caveats msgid "Solaris: the `zoneadm` utility must be present." msgstr "" #. zpool_featurenumbers description msgid "Return the comma-delimited feature numbers for ZFS storage pools." msgstr "" #. zpool_featurenumbers resolution msgid "Solaris: use the `zpool` utility to retrieve the feature numbers for ZFS storage pools" msgstr "" #. zpool_featurenumbers caveats msgid "Solaris: the `zpool` utility must be present." msgstr "" #. zpool_version description msgid "Return the version for ZFS storage pools." msgstr "" #. zpool_version resolution msgid "Solaris: use the `zpool` utility to retrieve the version for ZFS storage pools" msgstr "" #. zpool_version caveats msgid "Solaris: the `zpool` utility must be present." msgstr "" facter-3.14.12/lib/schema/facter.yaml0000644005276200011600000024166113702047406017171 0ustar jenkinsjenkins# This file is used to validate the facter output schema and also document facts. # # Use the following attributes for each entry: # - pattern (optional): the pattern to match against a fact name; if not specified, an exact match is performed. # - type (required): the type of the fact. Must be one of the following: # * integer # * double # * string # * boolean # * array # * map # * ip (IPv4 address string) # * ip6 (IPv6 address string) # * mac (MAC address string) # - hidden (optional; default: false): true if the value is hidden from facter output by default, false if not. # - description (required): describes the fact's purpose. # - resolution (optional): describes how the fact is resolved. # - caveats (optional): describes any caveats to the fact. # - elements (required for map types): contains the element values of a map value; each element is another entry. # - validate (optional; default: true): true if a map value's elements should be validated or false if not. # - blockgroup (optional): the block group of this fact; if not specified, the fact cannot be blocked # # Please keep the facts in alphabetical order. aio_agent_version: type: string description: Return the version of the puppet-agent package that installed facter. resolution: | All platforms: use the compile-time enabled version definition. architecture: type: string hidden: true description: Return the operating system's hardware architecture. resolution: | POSIX platforms: use the `uname` function to retrieve the OS hardware architecture. Windows: use the `GetNativeSystemInfo` function to retrieve the OS hardware architecture. caveats: | Linux: Debian, Gentoo, kFreeBSD, and Ubuntu use "amd64" for "x86_64" and Gentoo uses "x86" for "i386". augeas: type: map description: Return information about augeas. resolution: | All platforms: query augparse for augeas metadata. elements: version: type: string description: The version of augparse. augeasversion: type: string hidden: true description: Return the version of augeas. resolution: | All platforms: query augparse for the augeas version. blockdevices: type: string hidden: true description: Return a comma-separated list of block devices. resolution: | Linux: parse the contents of `/sys/block//`. Solaris: use the `kstat` function to query disk information. caveats: | Linux: kernel 2.6+ is required due to the reliance on sysfs. blockdevice__model: pattern: '^blockdevice_[A-Za-z0-9]+_model$' type: string hidden: true description: Return the model name of block devices attached to the system. resolution: | Linux: parse the contents of `/sys/block//device/model` to retrieve the model name/number for a device. Solaris: use the `kstat` function to query disk information. caveats: | Linux: kernel 2.6+ is required due to the reliance on sysfs. blockdevice__size: pattern: ^blockdevice_[A-Za-z0-9]+_size$ type: integer hidden: true description: Return the size of a block device in bytes. resolution: | Linux: parse the contents of `/sys/block//size` to receive the size (multiplying by 512 to correct for blocks-to-bytes). Solaris: use the `kstat` function to query disk information. caveats: | Linux: kernel 2.6+ is required due to the reliance on sysfs. blockdevice__vendor: pattern: ^blockdevice_[A-Za-z0-9]+_vendor$ type: string hidden: true description: Return the vendor name of block devices attached to the system. resolution: | Linux: parse the contents of `/sys/block//device/vendor` to retrieve the vendor for a device. Solaris: use the `kstat` function to query disk information. caveats: | Linux: kernel 2.6+ is required due to the reliance on sysfs. bios_release_date: type: string hidden: true description: Return the release date of the system BIOS. resolution: | Linux: parse the contents of `/sys/class/dmi/id/bios_date` to retrieve the system BIOS release date. Solaris: use the `smbios` utility to retrieve the system BIOS release date. caveats: | Linux: kernel 2.6+ is required due to the reliance on sysfs. bios_vendor: type: string hidden: true description: Return the vendor of the system BIOS. resolution: | Linux: parse the contents of `/sys/class/dmi/id/bios_vendor` to retrieve the system BIOS vendor. Solaris: use the `smbios` utility to retrieve the system BIOS vendor. caveats: | Linux: kernel 2.6+ is required due to the reliance on sysfs. bios_version: type: string hidden: true description: Return the version of the system BIOS. resolution: | Linux: parse the contents of `/sys/class/dmi/id/bios_version` to retrieve the system BIOS version. Solaris: use the `smbios` utility to retrieve the system BIOS version. caveats: | Linux: kernel 2.6+ is required due to the reliance on sysfs. boardassettag: type: string hidden: true description: Return the system board asset tag. resolution: | Linux: parse the contents of `/sys/class/dmi/id/board_asset_tag` to retrieve the system board asset tag. caveats: | Linux: kernel 2.6+ is required due to the reliance on sysfs. boardmanufacturer: type: string hidden: true description: Return the system board manufacturer. resolution: | Linux: parse the contents of `/sys/class/dmi/id/board_vendor` to retrieve the system board manufacturer. caveats: | Linux: kernel 2.6+ is required due to the reliance on sysfs. boardproductname: type: string hidden: true description: Return the system board product name. resolution: | Linux: parse the contents of `/sys/class/dmi/id/board_name` to retrieve the system board product name. caveats: | Linux: kernel 2.6+ is required due to the reliance on sysfs. boardserialnumber: type: string hidden: true description: Return the system board serial number. resolution: | Linux: parse the contents of `/sys/class/dmi/id/board_serial` to retrieve the system board serial number. caveats: | Linux: kernel 2.6+ is required due to the reliance on sysfs. chassisassettag: type: string hidden: true description: Return the system chassis asset tag. resolution: | Linux: parse the contents of `/sys/class/dmi/id/chassis_asset_tag` to retrieve the system chassis asset tag. Solaris: use the `smbios` utility to retrieve the system chassis asset tag. caveats: | Linux: kernel 2.6+ is required due to the reliance on sysfs. chassistype: type: string hidden: true description: Return the system chassis type. resolution: | Linux: parse the contents of `/sys/class/dmi/id/chassis_type` to retrieve the system chassis type. Solaris: use the `smbios` utility to retrieve the system chassis type. caveats: | Linux: kernel 2.6+ is required due to the reliance on sysfs. cloud: type: map description: Information about the cloud instance of the node. This is currently only populated on Linux nodes running in Microsoft Azure. elements: provider: type: string description: The cloud provider for the node. dhcp_servers: type: map hidden: true description: Return the DHCP servers for the system. resolution: | Linux: parse `dhclient` lease files or use the `dhcpcd` utility to retrieve the DHCP servers. Mac OSX: use the `ipconfig` utility to retrieve the DHCP servers. Solaris: use the `dhcpinfo` utility to retrieve the DHCP servers. Windows: use the `GetAdaptersAddresses` (Windows Server 2003: `GetAdaptersInfo`) function to retrieve the DHCP servers. elements: : pattern: ^((?!system).+)*$ type: ip description: The DHCP server for the interface. system: type: ip description: The DHCP server for the default interface. disks: type: map description: Return the disk (block) devices attached to the system. resolution: | AIX: query the ODM for all disk devices Linux: parse the contents of `/sys/block//`. Solaris: use the `kstat` function to query disk information. caveats: | Linux: kernel 2.6+ is required due to the reliance on sysfs. elements: : pattern: \w+ type: map description: Represents a disk or block device. elements: model: type: string description: The model of the disk or block device. product: type: string description: The product name of the disk or block device. caveats: Only present on Solaris. serial_number: type: string description: The serial number of the disk or block device. size: type: string description: The display size of the disk or block device, such as "1 GiB". size_bytes: type: integer description: The size of the disk or block device, in bytes. vendor: type: string description: The vendor of the disk or block device. dmi: type: map description: Return the system management information. resolution: | Linux: parse the contents of `/sys/class/dmi/id/` to retrieve system management information. Mac OSX: use the `sysctl` function to retrieve system management information. Solaris: use the `smbios`, `prtconf`, and `uname` utilities to retrieve system management information. Windows: use WMI to retrieve system management information. caveats: | Linux: kernel 2.6+ is required due to the reliance on sysfs. elements: bios: type: map description: The system BIOS information. elements: release_date: type: string description: The release date of the system BIOS. vendor: type: string description: The vendor of the system BIOS. version: type: string description: The version of the system BIOS. board: type: map description: The system board information. elements: asset_tag: type: string description: The asset tag of the system board. manufacturer: type: string description: The manufacturer of the system board. product: type: string description: The product name of the system board. serial_number: type: string description: The serial number of the system board. chassis: type: map description: The system chassis information. elements: asset_tag: type: string description: The asset tag of the system chassis. type: type: string description: The type of the system chassis. manufacturer: type: string description: The system manufacturer. product: type: map description: The system product information. elements: name: type: string description: The product name of the system. serial_number: type: string description: The product serial number of the system. uuid: type: string description: The product unique identifier of the system. domain: type: string hidden: true description: Return the network domain of the system. resolution: | POSIX platforms: use the `getaddrinfo` function to retrieve the network domain. Windows: query the registry to retrieve the network domain; falls back to the primary interface's domain if not set in the registry. ec2_metadata: type: map description: | Return the Amazon Elastic Compute Cloud (EC2) instance metadata. Please see the [EC2 instance metadata documentation](http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-instance-metadata.html) for the contents of this fact. resolution: | EC2: query the EC2 metadata endpoint and parse the response. caveats: | All platforms: `libfacter` must be built with `libcurl` support. validate: false blockgroup: EC2 ec2_userdata: type: string description: | Return the Amazon Elastic Compute Cloud (EC2) instance user data. Please see the [EC2 instance user data documentation](http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-instance-metadata.html) for the contents of this fact. resolution: | EC2: query the EC2 user data endpoint and parse the response. caveats: | All platforms: `libfacter` must be built with `libcurl` support. blockgroup: EC2 env_windows_installdir: type: string description: Return the path of the directory in which Puppet was installed. resolution: | Windows: This fact is specific to the Windows MSI generated environment, and is set using the `environment.bat` script that configures the runtime environment for all Puppet executables. Please see [the original commit in the puppet_for_the_win repo](https://github.com/puppetlabs/puppet_for_the_win/commit/0cc32c1a09550c13d725b200d3c0cc17d93ec262) for more information. caveats: | This fact is specific to Windows, and will not resolve on any other platform. facterversion: type: string description: Return the version of facter. resolution: | All platforms: use the built-in version of libfacter. filesystems: type: string description: Return the usable file systems for block or disk devices. resolution: | AIX: parse the contents of `/etc/vfs` to retrieve the usable file systems. Linux: parse the contents of `/proc/filesystems` to retrieve the usable file systems. Mac OSX: use the `getfsstat` function to retrieve the usable file systems. Solaris: use the `sysdef` utility to retrieve the usable file systems. caveats: | Linux: The proc file system must be mounted. Mac OSX: The usable file systems is limited to the file system of mounted devices. blockgroup: file system fips_enabled: type: boolean description: Return whether the platform is in FIPS mode resolution: | Linux: parse the contents of `/proc/sys/crypto/fips_enabled` which if non-zero indicates fips mode has been enabled. Windows: check if key `HKEY_LOCAL_MACHINE/System/CurrentControlSet/Control/Lsa/FipsAlgorithmPolicy/Enabled` is 1 or 0 caveats: | Linux: Limited to linux redhat family only fqdn: type: string hidden: true description: Return the fully qualified domain name (FQDN) of the system. resolution: | POSIX platforms: use the `getaddrinfo` function to retrieve the FQDN or use host and domain names. Windows: use the host and domain names to build the FQDN. gce: type: map description: | Return the Google Compute Engine (GCE) metadata. Please see the [GCE metadata documentation](https://cloud.google.com/compute/docs/metadata) for the contents of this fact. resolution: | GCE: query the GCE metadata endpoint and parse the response. caveats: | All platforms: `libfacter` must be built with `libcurl` support. validate: false gid: type: string hidden: true description: Return the group identifier (GID) of the user running facter. resolution: | POSIX platforms: use the `getegid` fuction to retrieve the group identifier. hardwareisa: type: string hidden: true description: Return the hardware instruction set architecture (ISA). resolution: | POSIX platforms: use `uname` to retrieve the hardware ISA. Windows: use WMI to retrieve the hardware ISA. hardwaremodel: type: string hidden: true description: Return the operating system's hardware model. resolution: | POSIX platforms: use the `uname` function to retrieve the OS hardware model. Windows: use the `GetNativeSystemInfo` function to retrieve the OS hardware model. hostname: type: string hidden: true description: Return the host name of the system. resolution: | POSIX platforms: use the `gethostname` function to retrieve the host name Windows: use the `GetComputerNameExW` function to retrieve the host name. hypervisors: type: map description: | Experimental fact: Return the names of any detected hypervisors and any collected metadata about them. resolution: | All platforms: Use the external `whereami` library to gather hypervisor data, if available. validate: false id: type: string hidden: true description: Return the user identifier (UID) of the user running facter. resolution: | POSIX platforms: use the `geteuid` fuction to retrieve the user identifier. identity: type: map description: Return the identity information of the user running facter. resolution: | POSIX platforms: use the `getegid`, `getpwuid_r`, `geteuid`, and `getgrgid_r` functions to retrieve the identity information; use the result of the `geteuid() == 0` test as the value of the privileged element Windows: use the `GetUserNameExW` function to retrieve the identity information; use the `GetTokenInformation` to get the current process token elevation status and use it as the value of the privileged element on versions of Windows supporting the token elevation, on older versions of Windows use the `CheckTokenMembership` to test whether the well known local Administrators group SID is enabled in the current thread impersonation token and use the test result as the value of the privileged element elements: gid: type: integer description: The group identifier of the user running facter. group: type: string description: The group name of the user running facter. uid: type: integer description: The user identifier of the user running facter. user: type: string description: The user name of the user running facter. privileged: type: boolean description: True if facter is running as a privileged process or false if not. interfaces: type: string hidden: true description: Return the comma-separated list of network interface names. resolution: | Linux: use the `getifaddrs` function to retrieve the network interface names. Mac OSX: use the `getifaddrs` function to retrieve the network interface names. Solaris: use the `ioctl` function to retrieve the network interface names. Windows: use the `GetAdaptersAddresses` function to retrieve the network interface names. ipaddress: type: ip hidden: true description: Return the IPv4 address for the default network interface. resolution: | Linux: use the `getifaddrs` function to retrieve the network interface address. Mac OSX: use the `getifaddrs` function to retrieve the network interface address. Solaris: use the `ioctl` function to retrieve the network interface address. Windows: use the `GetAdaptersAddresses` function to retrieve the network interface address. ipaddress6: type: ip6 hidden: true description: Return the IPv6 address for the default network interface. resolution: | Linux: use the `getifaddrs` function to retrieve the network interface address. Mac OSX: use the `getifaddrs` function to retrieve the network interface address. Solaris: use the `ioctl` function to retrieve the network interface address. Windows: use the `GetAdaptersAddresses` function to retrieve the network interface address. ipaddress6_: pattern: ^ipaddress6_.+$ type: ip6 hidden: true description: Return the IPv6 address for a network interface. resolution: | Linux: use the `getifaddrs` function to retrieve the network interface address. Mac OSX: use the `getifaddrs` function to retrieve the network interface address. Solaris: use the `ioctl` function to retrieve the network interface address. Windows: use the `GetAdaptersAddresses` function to retrieve the network interface address. ipaddress_: pattern: ^ipaddress_.+$ type: ip hidden: true description: Return the IPv4 address for a network interface. resolution: | Linux: use the `getifaddrs` function to retrieve the network interface address. Mac OSX: use the `getifaddrs` function to retrieve the network interface address. Solaris: use the `ioctl` function to retrieve the network interface address. Windows: use the `GetAdaptersAddresses` function to retrieve the network interface address. is_virtual: type: boolean description: Return whether or not the host is a virtual machine. resolution: | Linux: use procfs or utilities such as `vmware` and `virt-what` to retrieve virtual machine status. Mac OSX: use the system profiler to retrieve virtual machine status. Solaris: use the `zonename` utility to retrieve virtual machine status. Windows: use WMI to retrieve virtual machine status. kernel: type: string description: Return the kernel's name. resolution: | POSIX platforms: use the `uname` function to retrieve the kernel name. Windows: use the value of `windows` for all Windows versions. kernelmajversion: type: string description: Return the kernel's major version. resolution: | POSIX platforms: use the `uname` function to retrieve the kernel's major version. Windows: use the file version of `kernel32.dll` to retrieve the kernel's major version. kernelrelease: type: string description: Return the kernel's release. resolution: | POSIX platforms: use the `uname` function to retrieve the kernel's release. Windows: use the file version of `kernel32.dll` to retrieve the kernel's release. kernelversion: type: string description: Return the kernel's version. resolution: | POSIX platforms: use the `uname` function to retrieve the kernel's version. Windows: use the file version of `kernel32.dll` to retrieve the kernel's version. ldom: type: map description: Return Solaris LDom information from the `virtinfo` utility. resolution: | Solaris: use the `virtinfo` utility to retrieve LDom information. validate: false ldom_: pattern: ^ldom_.+$ hidden: true type: string description: Return Solaris LDom information. resolution: | Solaris: use the `virtinfo` utility to retrieve LDom information. load_averages: type: map description: Return the load average over the last 1, 5 and 15 minutes. resolution: | POSIX platforms: use `getloadavg` function to retrieve the system load averages. elements: 1m: type: double description: The system load average over the last minute. 5m: type: double description: The system load average over the last 5 minutes. 15m: type: double description: The system load average over the last 15 minutes. lsbdistcodename: type: string hidden: true description: Return the Linux Standard Base (LSB) distribution code name. resolution: | Linux: use the `lsb_release` utility to retrieve the LSB distribution code name. caveats: | Linux: Requires that the `lsb_release` utility be installed. lsbdistdescription: type: string hidden: true description: Return the Linux Standard Base (LSB) distribution description. resolution: | Linux: use the `lsb_release` utility to retrieve the LSB distribution description. caveats: | Linux: Requires that the `lsb_release` utility be installed. lsbdistid: type: string hidden: true description: Return the Linux Standard Base (LSB) distribution identifier. resolution: | Linux: use the `lsb_release` utility to retrieve the LSB distribution identifier. caveats: | Linux: Requires that the `lsb_release` utility be installed. lsbdistrelease: type: string hidden: true description: Return the Linux Standard Base (LSB) distribution release. resolution: | Linux: use the `lsb_release` utility to retrieve the LSB distribution release. caveats: | Linux: Requires that the `lsb_release` utility be installed. lsbmajdistrelease: type: string hidden: true description: Return the Linux Standard Base (LSB) major distribution release. resolution: | Linux: use the `lsb_release` utility to retrieve the LSB major distribution release. caveats: | Linux: Requires that the `lsb_release` utility be installed. lsbminordistrelease: type: string hidden: true description: Return the Linux Standard Base (LSB) minor distribution release. resolution: | Linux: use the `lsb_release` utility to retrieve the LSB minor distribution release. caveats: | Linux: Requires that the `lsb_release` utility be installed. lsbrelease: type: string hidden: true description: Return the Linux Standard Base (LSB) release. resolution: | Linux: use the `lsb_release` utility to retrieve the LSB release. caveats: | Linux: Requires that the `lsb_release` utility be installed. macaddress: type: mac hidden: true description: Return the MAC address for the default network interface. resolution: | Linux: use the `getifaddrs` function to retrieve the network interface address. Mac OSX: use the `getifaddrs` function to retrieve the network interface address. Solaris: use the `ioctl` function to retrieve the network interface address. Windows: use the `GetAdaptersAddresses` function to retrieve the network interface address. macaddress_: pattern: ^macaddress_.+$ type: mac hidden: true description: Return the MAC address for a network interface. resolution: | Linux: use the `getifaddrs` function to retrieve the network interface address. Mac OSX: use the `getifaddrs` function to retrieve the network interface address. Solaris: use the `ioctl` function to retrieve the network interface address. Windows: use the `GetAdaptersAddresses` function to retrieve the network interface address. macosx_buildversion: type: string hidden: true description: Return the Mac OSX build version. resolution: | Mac OSX: use the `sw_vers` utility to retrieve the Mac OSX build version. macosx_productname: type: string hidden: true description: Return the Mac OSX product name. resolution: | Mac OSX: use the `sw_vers` utility to retrieve the Mac OSX product name. macosx_productversion: type: string hidden: true description: Return the Mac OSX product version. resolution: | Mac OSX: use the `sw_vers` utility to retrieve the Mac OSX product version. macosx_productversion_major: type: string hidden: true description: Return the Mac OSX product major version. resolution: | Mac OSX: use the `sw_vers` utility to retrieve the Mac OSX product major version. macosx_productversion_minor: type: string hidden: true description: Return the Mac OSX product minor version. resolution: | Mac OSX: use the `sw_vers` utility to retrieve the Mac OSX product minor version. manufacturer: type: string hidden: true description: Return the system manufacturer. resolution: | Linux: parse the contents of `/sys/class/dmi/id/sys_vendor` to retrieve the system manufacturer. Solaris: use the `prtconf` utility to retrieve the system manufacturer. Windows: use WMI to retrieve the system manufacturer. caveats: | Linux: kernel 2.6+ is required due to the reliance on sysfs. memory: type: map description: Return the system memory information. resolution: | Linux: parse the contents of `/proc/meminfo` to retrieve the system memory information. Mac OSX: use the `sysctl` function to retrieve the system memory information. Solaris: use the `kstat` function to retrieve the system memory information. Windows: use the `GetPerformanceInfo` function to retrieve the system memory information. elements: swap: type: map description: Represents information about swap memory. elements: available: type: string description: The display size of the available amount of swap memory, such as "1 GiB". available_bytes: type: integer description: The size of the available amount of swap memory, in bytes. capacity: type: string description: The capacity percentage (0% is empty, 100% is full). encrypted: type: boolean description: True if the swap is encrypted or false if not. total: type: string description: The display size of the total amount of swap memory, such as "1 GiB". total_bytes: type: integer description: The size of the total amount of swap memory, in bytes. used: type: string description: The display size of the used amount of swap memory, such as "1 GiB". used_bytes: type: integer description: The size of the used amount of swap memory, in bytes. system: type: map description: Represents information about system memory. elements: available: type: string description: The display size of the available amount of system memory, such as "1 GiB". available_bytes: type: integer description: The size of the available amount of system memory, in bytes. capacity: type: string description: The capacity percentage (0% is empty, 100% is full). total: type: string description: The display size of the total amount of system memory, such as "1 GiB". total_bytes: type: integer description: The size of the total amount of system memory, in bytes. used: type: string description: The display size of the used amount of system memory, such as "1 GiB". used_bytes: type: integer description: The size of the used amount of system memory, in bytes. memoryfree: type: string hidden: true description: Return the display size of the free system memory, such as "1 GiB". resolution: | Linux: parse the contents of `/proc/meminfo` to retrieve the free system memory. Mac OSX: use the `sysctl` function to retrieve the free system memory. Solaris: use the `kstat` function to retrieve the free system memory. Windows: use the `GetPerformanceInfo` function to retrieve the free system memory. memoryfree_mb: type: double hidden: true description: Return the size of the free system memory, in mebibytes. resolution: | Linux: parse the contents of `/proc/meminfo` to retrieve the free system memory. Mac OSX: use the `sysctl` function to retrieve the free system memory. Solaris: use the `kstat` function to retrieve the free system memory. Windows: use the `GetPerformanceInfo` function to retrieve the free system memory. memorysize: type: string hidden: true description: Return the display size of the total system memory, such as "1 GiB". resolution: | Linux: parse the contents of `/proc/meminfo` to retrieve the total system memory. Mac OSX: use the `sysctl` function to retrieve the total system memory. Solaris: use the `kstat` function to retrieve the total system memory. Windows: use the `GetPerformanceInfo` function to retrieve the total system memory. memorysize_mb: type: double hidden: true description: Return the size of the total system memory, in mebibytes. resolution: | Linux: parse the contents of `/proc/meminfo` to retrieve the total system memory. Mac OSX: use the `sysctl` function to retrieve the total system memory. Solaris: use the `kstat` function to retrieve the total system memory. Windows: use the `GetPerformanceInfo` function to retrieve the total system memory. mountpoints: type: map description: Return the current mount points of the system. resolution: | AIX: use the `mntctl` function to retrieve the mount points. Linux: use the `setmntent` function to retrieve the mount points. Mac OSX: use the `getfsstat` function to retrieve the mount points. Solaris: parse the contents of `/etc/mnttab` to retrieve the mount points. blockgroup: file system elements: : pattern: .+ type: map description: Represents a mount point. elements: available: type: string description: The display size of the available space, such as "1 GiB". available_bytes: type: integer description: The size of the available space, in bytes. capacity: type: string description: The capacity percentage (0% is empty, 100% is full). device: type: string description: The name of the mounted device. filesystem: type: string description: The file system of the mounted device. options: type: array description: The mount options. size: type: string description: The display size of the total space, such as "1 GiB". size_bytes: type: integer description: The size of the total space, in bytes. used: type: string description: The display size of the used space, such as "1 GiB". used_bytes: type: integer description: The size of the used space, in bytes. mtu_: pattern: ^mtu_.+$ type: integer hidden: true description: Return the Maximum Transmission Unit (MTU) for a network interface. resolution: | Linux: use the `ioctl` function to retrieve the network interface MTU. Mac OSX: use the `getifaddrs` function to retrieve the network interface MTU. Solaris: use the `ioctl` function to retrieve the network interface MTU. Windows: use the `GetAdaptersAddresses` function to retrieve the network interface MTU. netmask: type: ip hidden: true description: Return the IPv4 netmask for the default network interface. resolution: | Linux: use the `getifaddrs` function to retrieve the network interface netmask. Mac OSX: use the `getifaddrs` function to retrieve the network interface netmask. Solaris: use the `ioctl` function to retrieve the network interface netmask. Windows: use the `GetAdaptersAddresses` (Windows Server 2003: `GetAdaptersInfo`) function to retrieve the network interface netmask. netmask6: type: ip6 hidden: true description: Return the IPv6 netmask for the default network interface. resolution: | Linux: use the `getifaddrs` function to retrieve the network interface netmask. Mac OSX: use the `getifaddrs` function to retrieve the network interface netmask. Solaris: use the `ioctl` function to retrieve the network interface netmask. Windows: use the `GetAdaptersAddresses` function to retrieve the network interface netmask. caveats: | Windows Server 2003: IPv6 netmasks are not supported. netmask6_: pattern: ^netmask6_.+$ type: ip6 hidden: true description: Return the IPv6 netmask for a network interface. resolution: | Linux: use the `getifaddrs` function to retrieve the network interface netmask. Mac OSX: use the `getifaddrs` function to retrieve the network interface netmask. Solaris: use the `ioctl` function to retrieve the network interface netmask. Windows: use the `GetAdaptersAddresses` function to retrieve the network interface netmask. caveats: | Windows Server 2003: IPv6 netmasks are not supported. netmask_: pattern: ^netmask_.+$ type: ip hidden: true description: Return the IPv4 netmask for a network interface. resolution: | Linux: use the `getifaddrs` function to retrieve the network interface netmask. Mac OSX: use the `getifaddrs` function to retrieve the network interface netmask. Solaris: use the `ioctl` function to retrieve the network interface netmask. Windows: use the `GetAdaptersAddresses` (Windows Server 2003: `GetAdaptersInfo`) function to retrieve the network interface netmask. network: type: ip hidden: true description: Return the IPv4 network for the default network interface. resolution: | Linux: use the `getifaddrs` function to retrieve the network interface network. Mac OSX: use the `getifaddrs` function to retrieve the network interface network. Solaris: use the `ioctl` function to retrieve the network interface network. Windows: use the `GetAdaptersAddresses` function to retrieve the network interface network. network6: type: ip6 hidden: true description: Return the IPv6 network for the default network interface. resolution: | Linux: use the `getifaddrs` function to retrieve the network interface network. Mac OSX: use the `getifaddrs` function to retrieve the network interface network. Solaris: use the `ioctl` function to retrieve the network interface network. Windows: use the `GetAdaptersAddresses` function to retrieve the network interface network. network6_: pattern: ^network6_.+$ type: ip6 hidden: true description: Return the IPv6 network for a network interface. resolution: | Linux: use the `getifaddrs` function to retrieve the network interface network. Mac OSX: use the `getifaddrs` function to retrieve the network interface network. Solaris: use the `ioctl` function to retrieve the network interface network. Windows: use the `GetAdaptersAddresses` function to retrieve the network interface network. network_: pattern: ^network_.+$ type: ip hidden: true description: Return the IPv4 network for a network interface. resolution: | Linux: use the `getifaddrs` function to retrieve the network interface network. Mac OSX: use the `getifaddrs` function to retrieve the network interface network. Solaris: use the `ioctl` function to retrieve the network interface network. Windows: use the `GetAdaptersAddresses` function to retrieve the network interface network. networking: type: map description: Return the networking information for the system. resolution: | Linux: use the `getifaddrs` function to retrieve the network interfaces. Mac OSX: use the `getifaddrs` function to retrieve the network interfaces. Solaris: use the `ioctl` function to retrieve the network interfaces. Windows: use the `GetAdaptersAddresses` function to retrieve the network interfaces. caveats: | Windows Server 2003: the `GetAdaptersInfo` function is used for DHCP and netmask lookup. This function does not support IPv6 netmasks. elements: dhcp: type: ip description: The address of the DHCP server for the default interface. domain: type: string description: The domain name of the system. fqdn: type: string description: The fully-qualified domain name of the system. hostname: type: string description: The host name of the system. interfaces: type: map description: The network interfaces of the system. elements: : pattern: .+ type: map description: Represents a network interface. elements: bindings: type: array description: The array of IPv4 address bindings for the interface. bindings6: type: array description: The array of IPv6 address bindings for the interface. dhcp: type: ip description: The DHCP server for the network interface. ip: type: ip description: The IPv4 address for the network interface. ip6: type: ip6 description: The IPv6 address for the network interface. mac: type: mac description: The MAC address for the network interface. mtu: type: integer description: The Maximum Transmission Unit (MTU) for the network interface. netmask: type: ip description: The IPv4 netmask for the network interface. netmask6: type: ip6 description: The IPv6 netmask for the network interface. network: type: ip description: The IPv4 network for the network interface. network6: type: ip6 description: The IPv6 network for the network interface. scope6: type: string description: The IPv6 scope for the network interface. ip: type: ip description: The IPv4 address of the default network interface. ip6: type: ip6 description: The IPv6 address of the default network interface. mac: type: mac description: The MAC address of the default network interface. mtu: type: integer description: The Maximum Transmission Unit (MTU) of the default network interface. netmask: type: ip description: The IPv4 netmask of the default network interface. netmask6: type: ip6 description: The IPv6 netmask of the default network interface. network: type: ip description: The IPv4 network of the default network interface. network6: type: ip6 description: The IPv6 network of the default network interface. primary: type: string description: The name of the primary interface. scope6: type: string description: The IPv6 scope of the default network interface. operatingsystem: type: string hidden: true description: Return the name of the operating system. resolution: | All platforms: default to the kernel name. Linux: use various release files in `/etc` to retrieve the OS name. operatingsystemmajrelease: type: string hidden: true description: Return the major release of the operating system. resolution: | All platforms: default to the major version of the kernel release. Linux: parse the contents of release files in `/etc` to retrieve the OS major release. Solaris: parse the contents of `/etc/release` to retrieve the OS major release. Windows: use WMI to retrieve the OS major release. caveats: | Linux: for Ubuntu, the major release is X.Y, such as "10.4". operatingsystemrelease: type: string hidden: true description: Return the release of the operating system. resolution: | All platforms: default to the kernel release. Linux: parse the contents of release files in `/etc` to retrieve the OS release. Solaris: parse the contents of `/etc/release` to retrieve the OS release. Windows: use WMI to retrieve the OS release. os: type: map description: Return information about the host operating system. resolution: | Linux: use the `lsb_release` utility and parse the contents of release files in `/etc` to retrieve the OS information. OSX: use the `sw_vers` utility to retrieve the OS information. Solaris: parse the contents of `/etc/release` to retrieve the OS information. Windows: use WMI to retrieve the OS information. elements: architecture: type: string description: The operating system's hardware architecture. distro: type: map description: Represents information about a Linux distribution. caveats: | Linux: requires that the `lsb_release` is present. elements: codename: type: string description: The code name of the Linux distribution. description: type: string description: The description of the Linux distribution. id: type: string description: The identifier of the Linux distribution. release: type: map description: Represents information about a Linux distribution release. elements: full: type: string description: The full release of the Linux distribution. major: type: string description: The major release of the Linux distribution. minor: type: string description: The minor release of the Linux distribution. specification: type: string description: The Linux Standard Base (LSB) release specification. family: type: string description: The operating system family. hardware: type: string description: The operating system's hardware model. macosx: type: map description: Represents information about Mac OSX. elements: build: type: string description: The Mac OSX build version. product: type: string description: The Mac OSX product name. version: type: map description: Represents information about the Mac OSX version. elements: full: type: string description: The full Mac OSX version number. major: type: string description: The major Mac OSX version number. minor: type: string description: The minor Mac OSX version number. name: type: string description: The operating system's name. release: type: map description: Represents the operating system's release. elements: full: type: string description: The full operating system release. major: type: string description: The major release of the operating system. minor: type: string description: The minor release of the operating system. patchlevel: type: string description: The patchlevel of the operating system. branch: type: string description: The branch the operating system was cut from. selinux: type: map description: Represents information about Security-Enhanced Linux (SELinux). resolution: | Linux: parse the contents of `/proc/self/mounts`, `/etc/selinux/config`, and `/enforce` to retrieve SELinux information. elements: config_mode: type: string description: The configured SELinux mode. config_policy: type: string description: The configured SELinux policy. current_mode: type: string description: The current SELinux mode. enabled: type: boolean description: True if SELinux is enabled or false if not. enforced: type: boolean description: True if SELinux policy is enforced or false if not. policy_version: type: string description: The version of the SELinux policy. windows: type: map description: Represents information about Windows. elements: edition_id: type: string description: Specify the edition variant. (ServerStandard|Professional|Enterprise) installation_type: type: string description: Specify the installation type. (Server|Server Core|Client) product_name: type: string description: Specify the textual product name. release_id: type: string description: Windows Build Version of the form YYMM. system32: type: string description: The path to the System32 directory. osfamily: type: string hidden: true description: Return the family of the operating system. resolution: | All platforms: default to the kernel name. Linux: map various Linux distributions to their base distribution. For example, Ubuntu is a "Debian" distro. Solaris: map various Solaris-based operating systems to the "Solaris" family. Windows: use "windows" as the family name. partitions: type: map description: Return the disk partitions of the system. resolution: | AIX: use the ODM to retrieve list of logical volumes; use `lvm_querylv` function to get details Linux: use `libblkid` to retrieve the disk partitions. caveats: | Linux: `libfacter` must be built with `libblkid` support. blockgroup: file system elements: : pattern: \w+ type: map description: Represents a disk partition. elements: filesystem: type: string description: The file system of the partition. label: type: string description: The label of the partition. mount: type: string description: The mount point of the partition (if mounted). partlabel: type: string description: The label of a GPT partition. partuuid: type: string description: The unique identifier of a GPT partition. size: type: string description: The display size of the partition, such as "1 GiB". size_bytes: type: integer description: The size of the partition, in bytes. uuid: type: string description: The unique identifier of a partition. backing_file: type: string description: The path to the file backing the partition. path: type: string description: Return the PATH environment variable. resolution: | All platforms: retrieve the value of the PATH environment variable. physicalprocessorcount: type: integer hidden: true description: Return the count of physical processors. resolution: | Linux: parse the contents `/sys/devices/system/cpu/` and `/proc/cpuinfo` to retrieve the count of physical processors. Mac OSX: use the `sysctl` function to retrieve the count of physical processors. Solaris: use the `kstat` function to retrieve the count of physical processors. Windows: use WMI to retrieve the count of physical processors. caveats: | Linux: kernel 2.6+ is required due to the reliance on sysfs. processor: pattern: ^processor\d+$ type: string hidden: true description: Return the model string of processor N. resolution: | Linux: parse the contents of `/proc/cpuinfo` to retrieve the processor model string. Mac OSX: use the `sysctl` function to retrieve the processor model string. Solaris: use the `kstat` function to retrieve the processor model string. Windows: use WMI to retrieve the processor model string. processorcount: type: integer hidden: true description: Return the count of logical processors. resolution: | Linux: parse the contents `/sys/devices/system/cpu/` and `/proc/cpuinfo` to retrieve the count of logical processors. Mac OSX: use the `sysctl` function to retrieve the count of logical processors. Solaris: use the `kstat` function to retrieve the count of logical processors. Windows: use WMI to retrieve the count of logical processors. caveats: | Linux: kernel 2.6+ is required due to the reliance on sysfs. processors: type: map description: Return information about the system's processors. resolution: | Linux: parse the contents `/sys/devices/system/cpu/` and `/proc/cpuinfo` to retrieve the processor information. Mac OSX: use the `sysctl` function to retrieve the processor information. Solaris: use the `kstat` function to retrieve the processor information. Windows: use WMI to retrieve the processor information. elements: count: type: integer description: The count of logical processors. isa: type: string description: The processor instruction set architecture. models: type: array description: The processor model strings (one for each logical processor). physicalcount: type: integer description: The count of physical processors. speed: type: string description: The speed of the processors, such as "2.0 GHz". productname: type: string hidden: true description: Return the system product name. resolution: | Linux: parse the contents of `/sys/class/dmi/id/product_name` to retrieve the system product name. Mac OSX: use the `sysctl` function to retrieve the system product name. Solaris: use the `smbios` utility to retrieve the system product name. Windows: use WMI to retrieve the system product name. caveats: | Linux: kernel 2.6+ is required due to the reliance on sysfs. ruby: type: map description: Return information about the Ruby loaded by facter. resolution: | All platforms: Use `RbConfig`, `RUBY_PLATFORM`, and `RUBY_VERSION` to retrieve information about Ruby. caveats: | All platforms: facter must be able to locate `libruby`. elements: platform: type: string description: The platform Ruby was built for. sitedir: type: string description: The path to Ruby's site library directory. version: type: string description: The version of Ruby. rubyplatform: type: string hidden: true description: Return the platform Ruby was built for. resolution: | All platforms: use `RUBY_PLATFORM` from the Ruby loaded by facter. caveats: | All platforms: facter must be able to locate `libruby`. rubysitedir: type: string hidden: true description: Return the path to Ruby's site library directory. resolution: | All platforms: use `RbConfig` from the Ruby loaded by facter. caveats: | All platforms: facter must be able to locate `libruby`. rubyversion: type: string hidden: true description: Return the version of Ruby. resolution: | All platforms: use `RUBY_VERSION` from the Ruby loaded by facter. caveats: | All platforms: facter must be able to locate `libruby`. scope6: type: string hidden: true description: Return the IPv6 scope for the default network interface. resolution: | Linux: parse the contents of /proc/net/if_inet6 to retrieve the network interface scope. Mac OSX: use the `getifaddrs` function to retrieve the network interface scope. Solaris: use the `ioctl` function to retrieve the network interface scope. Windows: use the `GetAdaptersAddresses` function to retrieve the network interface scope. scope6_: pattern: ^scope6_.+$ type: string hidden: true description: Return the IPv6 scope for the default network interface. resolution: | Linux: parse the contents of /proc/net/if_inet6 to retrieve the network interface scope. Mac OSX: use the `getifaddrs` function to retrieve the network interface scope. Solaris: use the `ioctl` function to retrieve the network interface scope. Windows: use the `GetAdaptersAddresses` function to retrieve the network interface scope. selinux: type: boolean hidden: true description: Return whether Security-Enhanced Linux (SELinux) is enabled. resolution: | Linux: parse the contents of `/proc/self/mounts` to determine if SELinux is enabled. selinux_config_mode: type: string hidden: true description: Return the configured Security-Enhanced Linux (SELinux) mode. resolution: | Linux: parse the contents of `/etc/selinux/config` to retrieve the configured SELinux mode. selinux_config_policy: type: string hidden: true description: Return the configured Security-Enhanced Linux (SELinux) policy. resolution: | Linux: parse the contents of `/etc/selinux/config` to retrieve the configured SELinux policy. selinux_current_mode: type: string hidden: true description: Return the current Security-Enhanced Linux (SELinux) mode. resolution: | Linux: parse the contents of `/enforce` to retrieve the current SELinux mode. selinux_enforced: type: boolean hidden: true description: Return whether Security-Enhanced Linux (SELinux) is enforced. resolution: | Linux: parse the contents of `/enforce` to retrieve the current SELinux mode. selinux_policyversion: type: string hidden: true description: Return the Security-Enhanced Linux (SELinux) policy version. resolution: | Linux: parse the contents of `/policyvers` to retrieve the SELinux policy version. serialnumber: type: string hidden: true description: Return the system product serial number. resolution: | Linux: parse the contents of `/sys/class/dmi/id/product_name` to retrieve the system product serial number. Solaris: use the `smbios` utility to retrieve the system product serial number. Windows: use WMI to retrieve the system product serial number. caveats: | Linux: kernel 2.6+ is required due to the reliance on sysfs. solaris_zones: type: map description: Return information about Solaris zones. resolution: | Solaris: use the `zoneadm` and `zonename` utilities to retrieve information about the Solaris zones. elements: current: type: string description: The name of the current Solaris zone. zones: type: map description: Represents the Solaris zones. elements: : pattern: .* type: map description: Represents a Solaris zone. elements: brand: type: string description: The brand of the Solaris zone. id: type: string description: The id of the Solaris zone. ip_type: type: string description: The IP type of the Solaris zone. path: type: string description: The path of the Solaris zone. status: type: string description: The status of the Solaris zone. uuid: type: string description: The unique identifier of the Solaris zone. sp_: pattern: ^sp_\w+$ hidden: true type: string description: Return Mac OSX system profiler information. resolution: | Mac OSX: use the `system_profiler` utility to retrieve system profiler information. ssh: type: map description: Return SSH public keys and fingerprints. resolution: | POSIX platforms: parse SSH public key files and derive fingerprints. caveats: | POSIX platforms: facter must be built with OpenSSL support. elements: dsa: type: map description: Represents the public key and fingerprints for the DSA algorithm. elements: fingerprints: type: map description: Represents fingerprint information. elements: sha1: type: string description: The SHA1 fingerprint of the public key. sha256: type: string description: The SHA256 fingerprint of the public key. key: type: string description: The DSA public key. type: type: string description: The exact type of the key, i.e. "ssh-dss". ecdsa: type: map description: Represents the public key and fingerprints for the ECDSA algorithm. elements: fingerprints: type: map description: Represents fingerprint information. elements: sha1: type: string description: The SHA1 fingerprint of the public key. sha256: type: string description: The SHA256 fingerprint of the public key. key: type: string description: The ECDSA public key. type: type: string description: The exact type of the key, e.g. "ecdsa-sha2-nistp256". ed25519: type: map description: Represents the public key and fingerprints for the Ed25519 algorithm. elements: fingerprints: type: map description: Represents fingerprint information. elements: sha1: type: string description: The SHA1 fingerprint of the public key. sha256: type: string description: The SHA256 fingerprint of the public key. key: type: string description: The Ed25519 public key. type: type: string description: The exact type of the key, i.e. "ssh-ed25519". rsa: type: map description: Represents the public key and fingerprints for the RSA algorithm. elements: fingerprints: type: map description: Represents fingerprint information. elements: sha1: type: string description: The SHA1 fingerprint of the public key. sha256: type: string description: The SHA256 fingerprint of the public key. key: type: string description: The RSA public key. type: type: string description: The exact type of the key, i.e. "ssh-rsa". sshkey: pattern: ^ssh\w*key$ hidden: true type: string description: Return the SSH public key for the algorithm. resolution: | POSIX platforms: parse SSH public key files. caveats: | POSIX platforms: facter must be built with OpenSSL support. sshfp_: pattern: ^sshfp_\w*$ hidden: true type: string description: Return the SSH fingerprints for the algorithm's public key. resolution: | POSIX platforms: derive the SHA1 and SHA256 fingerprints; delimit with a new line character. caveats: | POSIX platforms: facter must be built with OpenSSL support. swapencrypted: type: boolean hidden: true description: Return whether or not the swap is encrypted. resolution: | Mac OSX: use the `sysctl` function to retrieve swap encryption status. swapfree: type: string hidden: true description: Return the display size of the free swap memory, such as "1 GiB". resolution: | Linux: parse the contents of `/proc/meminfo` to retrieve the free swap memory. Mac OSX: use the `sysctl` function to retrieve the free swap memory. Solaris: use the `swapctl` function to retrieve the free swap memory. swapfree_mb: type: double hidden: true description: Return the size of the free swap memory, in mebibytes. resolution: | Linux: parse the contents of `/proc/meminfo` to retrieve the free swap memory. Mac OSX: use the `sysctl` function to retrieve the free swap memory. Solaris: use the `swapctl` function to retrieve the free swap memory. swapsize: type: string hidden: true description: Return the display size of the total swap memory, such as "1 GiB". resolution: | Linux: parse the contents of `/proc/meminfo` to retrieve the total swap memory. Mac OSX: use the `sysctl` function to retrieve the total swap memory. Solaris: use the `swapctl` function to retrieve the total swap memory. swapsize_mb: type: double hidden: true description: Return the size of the total swap memory, in mebibytes. resolution: | Linux: parse the contents of `/proc/meminfo` to retrieve the total swap memory. Mac OSX: use the `sysctl` function to retrieve the total swap memory. Solaris: use the `swapctl` function to retrieve the total swap memory. windows_edition_id: type: string hidden: true description: Return the type of Windows edition, Server or Desktop Edition variant. resolution: | Windows: query the registry to retrieve the type of edition (ServerStandard|Professional|Enterprise). windows_installation_type: type: string hidden: true description: Return Windows installation type (Server|Server Core|Client). resolution: | Windows: query the registry to retrive data to differentiate Server, Server Core, Client. windows_product_name: type: string hidden: true description: Return Windows textual product name. resolution: | Windows: uery the registry to retrive textual product name. windows_release_id: type: string hidden: true description: Return Windows Build Version of the form YYMM. resolution: | Windows: query the registry to retrieve the build version number. system32: type: string hidden: true description: Return the path to the System32 directory on Windows. resolution: | Windows: use the `SHGetFolderPath` function to retrieve the path to the System32 directory. system_profiler: type: map description: Return information from the Mac OSX system profiler. resolution: | Mac OSX: use the `system_profiler` utility to retrieve system profiler information. elements: boot_mode: type: string description: The boot mode. boot_rom_version: type: string description: The boot ROM version. boot_volume: type: string description: The boot volume. computer_name: type: string description: The name of the computer. cores: type: string description: The total number of processor cores. hardware_uuid: type: string description: The hardware unique identifier. kernel_version: type: string description: The version of the kernel. l2_cache_per_core: type: string description: The size of the processor per-core L2 cache. l3_cache: type: string description: The size of the processor L3 cache. memory: type: string description: The size of the system memory. model_identifier: type: string description: The identifier of the computer model. model_name: type: string description: The name of the computer model. processor_name: type: string description: The model name of the processor. processor_speed: type: string description: The speed of the processor. processors: type: string description: The total number of processors. secure_virtual_memory: type: string description: Whether or not secure virtual memory is enabled. serial_number: type: string description: The serial number of the computer. smc_version: type: string description: The System Management Controller (SMC) version. system_version: type: string description: The operating system version. uptime: type: string description: The uptime of the system. username: type: string description: The name of the user running facter. system_uptime: type: map description: Return the system uptime information. resolution: | Linux: use the `sysinfo` function to retrieve the system uptime. POSIX platforms: use the `uptime` utility to retrieve the system uptime. Solaris: use the `kstat` function to retrieve the system uptime. Windows: use WMI to retrieve the system uptime. elements: days: type: integer description: The number of complete days the system has been up. hours: type: integer description: The number of complete hours the system has been up. seconds: type: integer description: The number of total seconds the system has been up. uptime: type: string description: The full uptime string. timezone: type: string description: Return the system timezone. resolution: | POSIX platforms: use the `localtime_r` function to retrieve the system timezone. Windows: use the `localtime_s` function to retrieve the system timezone. uptime: type: string hidden: true description: Return the system uptime. resolution: | Linux: use the `sysinfo` function to retrieve the system uptime. POSIX platforms: use the `uptime` utility to retrieve the system uptime. Solaris: use the `kstat` function to retrieve the system uptime. Windows: use WMI to retrieve the system uptime. uptime_days: type: integer hidden: true description: Return the system uptime days. resolution: | Linux: use the `sysinfo` function to retrieve the system uptime days. POSIX platforms: use the `uptime` utility to retrieve the system uptime days. Solaris: use the `kstat` function to retrieve the system uptime days. Windows: use WMI to retrieve the system uptime days. uptime_hours: type: integer hidden: true description: Return the system uptime hours. resolution: | Linux: use the `sysinfo` function to retrieve the system uptime hours. POSIX platforms: use the `uptime` utility to retrieve the system uptime hours. Solaris: use the `kstat` function to retrieve the system uptime hours. Windows: use WMI to retrieve the system uptime hours. uptime_seconds: type: integer hidden: true description: Return the system uptime seconds. resolution: | Linux: use the `sysinfo` function to retrieve the system uptime seconds. POSIX platforms: use the `uptime` utility to retrieve the system uptime seconds. Solaris: use the `kstat` function to retrieve the system uptime seconds. Windows: use WMI to retrieve the system uptime seconds. uuid: type: string hidden: true description: Return the system product unique identifier. resolution: | Linux: parse the contents of `/sys/class/dmi/id/product_uuid` to retrieve the system product unique identifier. Solaris: use the `smbios` utility to retrieve the system product unique identifier. caveats: | Linux: kernel 2.6+ is required due to the reliance on sysfs. virtual: type: string description: Return the hypervisor name for virtual machines or "physical" for physical machines. resolution: | Linux: use procfs or utilities such as `vmware` and `virt-what` to retrieve virtual machine name. Mac OSX: use the system profiler to retrieve virtual machine name. Solaris: use the `zonename` utility to retrieve virtual machine name. Windows: use WMI to retrieve virtual machine name. xen: type: map description: Return metadata for the Xen hypervisor. resolution: | POSIX platforms: use `/usr/lib/xen-common/bin/xen-toolstack` to locate xen admin commands if available, otherwise fallback to `/usr/sbin/xl` or `/usr/sbin/xm`. Use the found command to execute the `list` query. caveats: | POSIX platforms: confined to Xen privileged virtual machines. elements: domains: type: array description: list of strings identifying active Xen domains. xendomains: type: string hidden: true description: Return a list of comma-separated active Xen domain names. resolution: | POSIX platforms: see the `xen` structured fact. caveats: | POSIX platforms: confined to Xen privileged virtual machines. zfs_featurenumbers: type: string description: Return the comma-delimited feature numbers for ZFS. resolution: | Solaris: use the `zfs` utility to retrieve the feature numbers for ZFS caveats: | Solaris: the `zfs` utility must be present. zfs_version: type: string description: Return the version for ZFS. resolution: | Solaris: use the `zfs` utility to retrieve the version for ZFS caveats: | Solaris: the `zfs` utility must be present. zone__brand: pattern: ^zone_[\w\-\.]+_brand$ type: string hidden: true description: Return the brand for the Solaris zone. resolution: | Solaris: use the `zoneadm` utility to retrieve the brand for the Solaris zone. caveats: | Solaris: the `zoneadm` utility must be present. zone__iptype: pattern: ^zone_[\w\-\.]+_iptype$ type: string hidden: true description: Return the IP type for the Solaris zone. resolution: | Solaris: use the `zoneadm` utility to retrieve the IP type for the Solaris zone. caveats: | Solaris: the `zoneadm` utility must be present. zone__name: pattern: ^zone_[\w\-\.]+_name$ type: string hidden: true description: Return the name for the Solaris zone. resolution: | Solaris: use the `zoneadm` utility to retrieve the name for the Solaris zone. caveats: | Solaris: the `zoneadm` utility must be present. zone__uuid: pattern: ^zone_[\w\-\.]+_uuid$ type: string hidden: true description: Return the unique identifier for the Solaris zone. resolution: | Solaris: use the `zoneadm` utility to retrieve the unique identifier for the Solaris zone. caveats: | Solaris: the `zoneadm` utility must be present. zone__id: pattern: ^zone_[\w\-\.]+_id$ type: string hidden: true description: Return the zone identifier for the Solaris zone. resolution: | Solaris: use the `zoneadm` utility to retrieve the zone identifier for the Solaris zone. caveats: | Solaris: the `zoneadm` utility must be present. zone__path: pattern: ^zone_[\w\-\.]+_path$ type: string hidden: true description: Return the zone path for the Solaris zone. resolution: | Solaris: use the `zoneadm` utility to retrieve the zone path for the Solaris zone. caveats: | Solaris: the `zoneadm` utility must be present. zone__status: pattern: ^zone_[\w\-\.]+_status$ type: string hidden: true description: Return the zone state for the Solaris zone. resolution: | Solaris: use the `zoneadm` utility to retrieve the zone state for the Solaris zone. caveats: | Solaris: the `zoneadm` utility must be present. zonename: type: string hidden: true description: Return the name of the current Solaris zone. resolution: | Solaris: use the `zonename` utility to retrieve the current zone name. caveats: | Solaris: the `zonename` utility must be present. zones: type: integer hidden: true description: Return the count of Solaris zones. resolution: | Solaris: use the `zoneadm` utility to retrieve the count of Solaris zones. caveats: | Solaris: the `zoneadm` utility must be present. zpool_featureflags: type: string description: Return the comma-delimited feature flags for ZFS storage pools. resolution: | Solaris: use the `zpool` utility to retrieve the feature numbers for ZFS storage pools caveats: | Solaris: the `zpool` utility must be present. zpool_featurenumbers: type: string description: Return the comma-delimited feature numbers for ZFS storage pools. resolution: | Solaris: use the `zpool` utility to retrieve the feature numbers for ZFS storage pools caveats: | Solaris: the `zpool` utility must be present. zpool_version: type: string description: Return the version for ZFS storage pools. resolution: | Solaris: use the `zpool` utility to retrieve the version for ZFS storage pools caveats: | Solaris: the `zpool` utility must be present. facter-3.14.12/lib/schema/translation_tooling.rb0000644005276200011600000000341613702047406021451 0ustar jenkinsjenkinsrequire 'yaml' fact_schema = YAML.load_file(File.join(File.dirname(__FILE__), "facter.yaml")) facts = [] fact_schema.each do |fact| fact_name = fact[0] fact_details = fact[1] fact_data = {:name => fact_name, :description => fact_details['description'], :resolution => fact_details['resolution'], :caveats => fact_details['caveats']} facts << fact_data end File.open(File.join(File.dirname(__FILE__), "core_facts.pot"), 'w') do |file| file.puts <<-HEADER # CORE FACTS SCHEMA # Copyright (C) 2016 Puppet, LLC # This file is distributed under the same license as the FACTER package. # FIRST AUTHOR , 2016. # #, fuzzy msgid "" msgstr "" "Project-Id-Version: FACTER \\n" "Report-Msgid-Bugs-To: docs@puppet.com\\n" "POT-Creation-Date: \\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\\n" "Last-Translator: FULL NAME \\n" "Language-Team: LANGUAGE \\n" "Language: \\n" "MIME-Version: 1.0\\n" "Content-Type: text/plain; charset=UTF-8\\n" "Content-Transfer-Encoding: 8bit\\n" "Plural-Forms: nplurals=INTEGER; plural=EXPRESSION;\\n" \n HEADER facts.each do |fact| if fact[:description] descriptions = fact[:description].split("\n") descriptions.each do |string| file.puts "#. #{fact[:name]} description\nmsgid \"#{string}\"\nmsgstr \"\"\n\n" end end if fact[:resolution] resolutions = fact[:resolution].split("\n") resolutions.each do |string| file.puts "#. #{fact[:name]} resolution\nmsgid \"#{string}\"\nmsgstr \"\"\n\n" end end if fact[:caveats] caveats = fact[:caveats].split("\n") caveats.each do |string| file.puts "#. #{fact[:name]} caveats\nmsgid \"#{string}\"\nmsgstr \"\"\n\n" end end end end facter-3.14.12/lib/spec/0000755005276200011600000000000013702047635014525 5ustar jenkinsjenkinsfacter-3.14.12/lib/spec/unit/0000755005276200011600000000000013702047635015504 5ustar jenkinsjenkinsfacter-3.14.12/lib/spec/unit/facter_spec.rb0000644005276200011600000001137013702047406020305 0ustar jenkinsjenkins# encoding: UTF-8 require 'spec_helper' Facter.on_message do |level, message| puts message if level == :fatal end describe Facter do it 'should provide a version' do expect(Facter.version).to_not be_nil end describe 'without resetting' do before :all do Facter.reset end it 'should not be an empty hash' do expect(Facter.to_hash).to_not be_empty end it 'should return a fact for []' do fact = Facter[:facterversion] expect(fact).to_not be_nil expect(fact.name).to eq('facterversion') expect(fact.value).to eq(Facter.version) end it 'should return nil value for [] with unknown fact' do expect(Facter[:not_a_fact]).to be_nil end it 'should return nil for value with unknown fact' do expect(Facter.value(:not_a_fact)).to be_nil end it 'should contain a matching facter version' do version = Facter.value('facterversion') expect(version).to eq(Facter.version) expect(version).to eq(Facter::FACTERVERSION) end end describe 'with resetting' do before :each do Facter.reset end it 'should load external facts' do # Check for windows vs posix for executable external facts windows = Facter.value('osfamily') == 'windows' Facter.reset Facter.search_external([ File.expand_path('../../../lib/tests/fixtures/facts/external/yaml', File.dirname(__FILE__)), File.expand_path('../../../lib/tests/fixtures/facts/external/json', File.dirname(__FILE__)), File.expand_path('../../../lib/tests/fixtures/facts/external/text', File.dirname(__FILE__)), File.expand_path("../../../lib/tests/fixtures/facts/external/#{ if windows then 'windows' else 'posix' end }/execution", File.dirname(__FILE__)) ]) facts = Facter.to_hash expect(facts['yaml_fact1']).to be_a(String) expect(facts['yaml_fact2']).to be_a(Integer) expect(facts['yaml_fact3']).to(satisfy { |v| v == true || v == false }) expect(facts['yaml_fact4']).to be_a(Float) expect(facts['yaml_fact5']).to be_a(Array) expect(facts['yaml_fact6']).to be_a(Hash) expect(facts['yaml_fact7']).to be_a(String) expect(facts['not_bool']).to be_a(String) expect(facts['not_int']).to be_a(String) expect(facts['not_double']).to be_a(String) expect(facts['json_fact1']).to be_a(String) expect(facts['json_fact2']).to be_a(Integer) expect(facts['json_fact3']).to(satisfy { |v| v == true || v == false }) expect(facts['json_fact4']).to be_a(Float) expect(facts['json_fact5']).to be_a(Array) expect(facts['json_fact6']).to be_a(Hash) expect(facts['exe_fact1']).to be_a(String) expect(facts['exe_fact2']).to be_a(String) expect(facts['exe_fact3']).to be_nil expect(facts['txt_fact1']).to be_a(String) expect(facts['txt_fact2']).to be_a(String) expect(facts['txt_fact3']).to be_nil end it 'should set search paths' do Facter.search('foo', 'bar', 'baz') expect(Facter.search_path).to include('foo', 'bar', 'baz') Facter.reset expect(Facter.search_path).to eq([]) end it 'should set external search paths' do Facter.search_external(['foo', 'bar', 'baz']) expect(Facter.search_external_path).to include('foo', 'bar', 'baz') end it 'should find encoded search paths' do snowman_path = File.expand_path('../../../lib/tests/fixtures/facts/external/zö', File.dirname(__FILE__)) encoded_path = snowman_path.encode("Windows-1252") Facter.search(encoded_path) expect(Facter.search_path).to include(snowman_path) expect(Facter.value('snowman_fact')).to eq('olaf') end it 'should find encoded external search paths' do snowman_path = File.expand_path('../../../lib/tests/fixtures/facts/external/zö', File.dirname(__FILE__)) encoded_path = snowman_path.encode("Windows-1252") Facter.search_external([encoded_path]) expect(Facter.search_external_path).to include(snowman_path) expect(Facter.value('snowman_fact')).to eq('olaf') end it 'should support stubbing for confine testing' do Facter.fact(:osfamily).expects(:value).at_least(1).returns 'foo' expect(Facter.fact(:osfamily).value).to eq('foo') Facter.add(:test) do confine osfamily: 'foo' setcode do 'bar' end end expect(Facter.value(:test)).to eq('bar') end it 'should allow stubbing on which and exec' do Facter::Util::Resolution.expects(:which).with("foo").returns('/usr/bin/foo') Facter::Util::Resolution.expects(:exec).with("foo").returns('bar') expect(Facter::Util::Resolution.which('foo')).to eq('/usr/bin/foo') expect(Facter::Util::Resolution.exec('foo')).to eq('bar') end end end facter-3.14.12/lib/spec_helper.rb.in0000644005276200011600000000144313702047406017014 0ustar jenkinsjenkins# Set FACTERDIR so that facter.rb can find libfacter.so ENV['FACTERDIR'] = '${CMAKE_BINARY_DIR}' # Add the location of libfacter.so to the path for Windows ENV['PATH'] = '${CMAKE_BINARY_DIR}/${LIBFACTER_INSTALL_DESTINATION}' + File::PATH_SEPARATOR + ENV['PATH'] require 'mocha' require 'rspec' require '${CMAKE_BINARY_DIR}/lib/facter.rb' RSpec.configure do |config| config.mock_with :mocha config.before :each do # Store any environment variables away to be restored later @old_env = {} ENV.each_key {|k| @old_env[k] = ENV[k]} end config.after :each do # Restore environment variables after execution of each test @old_env.each_pair {|k, v| ENV[k] = v} to_remove = ENV.keys.reject {|key| @old_env.include? key } to_remove.each {|key| ENV.delete key } end end facter-3.14.12/lib/src/0000755005276200011600000000000013702047635014362 5ustar jenkinsjenkinsfacter-3.14.12/lib/src/cwrapper.cc0000644005276200011600000000255113702047406016513 0ustar jenkinsjenkins#include #include #include #include #include #include uint8_t get_default_facts(char **result) { try { // NB: ssh resolver cannot be blocked facter::facts::collection facts {{}, // blocklist set {}, // ttls map (resolvers - ttl) true}; // ignore_cache flag // The boolean arg is meant to avoid including ruby facts facts.add_default_facts(false); // NB: skipping the add_environment_facts() call // TODO: consider iterating only the facts we're interested // in by using the 'queries' arg std::ostringstream stream; facts.write(stream, facter::facts::format::json, {}, // queries vector true, // show_legacy flag true); // strict_errors flag auto json_facts = stream.str(); auto l = json_facts.length()+1; *result = static_cast(malloc(sizeof(char)*l)); if (*result == nullptr) { return EXIT_FAILURE; } strncpy(*result, json_facts.c_str(), l); } catch (const std::exception&) { return EXIT_FAILURE; } return EXIT_SUCCESS; } facter-3.14.12/lib/src/facts/0000755005276200011600000000000013702047635015462 5ustar jenkinsjenkinsfacter-3.14.12/lib/src/facts/aix/0000755005276200011600000000000013702047635016243 5ustar jenkinsjenkinsfacter-3.14.12/lib/src/facts/aix/collection.cc0000644005276200011600000000315313702047406020703 0ustar jenkinsjenkins#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include using namespace std; namespace facter { namespace facts { void collection::add_platform_facts() { add(make_shared()); add(make_shared()); add(make_shared()); add(make_shared()); add(make_shared()); add(make_shared()); add(make_shared()); add(make_shared()); add(make_shared()); add(make_shared()); add(make_shared()); add(make_shared()); add(make_shared()); add(make_shared()); } }} // namespace facter::facts facter-3.14.12/lib/src/facts/aix/disk_resolver.cc0000644005276200011600000000606513702047406021430 0ustar jenkinsjenkins#include #include #include #include #include #include #include #include #include using namespace facter::util::aix; using namespace facter::util::posix; using namespace std; namespace facter { namespace facts { namespace aix { disk_resolver::data disk_resolver::collect_data(collection& facts) { data result; vector disk_types; auto pd_dv_query = odm_class::open("PdDv").query("class=disk"); for (auto& pd_dv : pd_dv_query) { LOG_DEBUG("got a disk type: {1}", pd_dv.uniquetype); disk_types.push_back(pd_dv.uniquetype); } auto cu_dv = odm_class::open("CuDv"); for (string& type : disk_types) { string query = (boost::format("PdDvLn=%1%") % type).str(); auto cu_dv_query = cu_dv.query(query); for (auto& cu_dv : cu_dv_query) { LOG_DEBUG("got a disk: {1}", cu_dv.name); disk d; d.name = cu_dv.name; { string device = (boost::format("/dev/%1%") % d.name).str(); auto descriptor = open(device.c_str(), O_RDONLY); if (descriptor < 0) { LOG_DEBUG("Could not open device %1% for reading: %2% (%3%). Disk facts will not be populated for this device", d.name, strerror(errno), errno); continue; } scoped_descriptor fd(descriptor); devinfo info; auto result = ioctl(fd, IOCINFO, &info); if (result < 0) { LOG_DEBUG("Ioctl IOCINFO failed for device %1%: %2% (%3%). Disk facts will not be populated for this device", d.name, strerror(errno), errno); continue; } switch (info.devtype) { case DD_DISK: case DD_SCDISK: if (info.flags & DF_LGDSK) { d.size = (uint32_t)info.un.scdk64.hi_numblks; d.size <<= 32; d.size |= (uint32_t)info.un.scdk64.lo_numblks; d.size *= info.un.scdk64.blksize; } else { d.size = (uint32_t)info.un.scdk.numblks; d.size *= info.un.scdk.blksize; } break; default: LOG_WARNING("Expected a Disk or SCSI disk device, got device code '{1}'. This is probably a Facter bug. Please report it, and include this error message.", info.devtype); break; } } result.disks.emplace_back(move(d)); } } return result; } }}} // namespace facter::facts::aix facter-3.14.12/lib/src/facts/aix/filesystem_resolver.cc0000644005276200011600000001221613702047406022655 0ustar jenkinsjenkins#include #include #include #include #include #include #include #include #include #include #include #include #include using namespace std; using namespace facter::util::aix; namespace fu = leatherman::file_util; namespace facter { namespace facts { namespace aix { filesystem_resolver::data filesystem_resolver::collect_data(collection& facts) { data result; collect_filesystem_data(result); collect_mountpoint_data(result); collect_partition_data(result); return result; } void filesystem_resolver::collect_filesystem_data(data& result) { fu::each_line("/etc/vfs", [&](const string& line) { auto first_char = line.find_first_not_of(" \t"); if (first_char != string::npos && // skip completely blank lines line[first_char] != '#' && // skip comment lines line[first_char] != '%') { // skip defaultvfs line vector tokens; boost::split(tokens, line, boost::is_space(), boost::token_compress_on); _filesystems.emplace(make_pair(stoul(tokens[1]), tokens[0])); result.filesystems.emplace(move(tokens[0])); } return true; }); } void filesystem_resolver::collect_mountpoint_data(data& result) { for (const auto& mount : mountctl()) { mountpoint m; // AIX Version 5.3 does not define the MNT_AHAFS variable. // Anything above aix 5.3 will have _AIXVERSION_610 defined. #ifndef _AIXVERSION_610 if (mount.vmt_gfstype == MNT_PROCFS) { continue; } #else if (mount.vmt_gfstype == MNT_PROCFS || mount.vmt_gfstype == MNT_AHAFS) { continue; } #endif m.filesystem = _filesystems[mount.vmt_gfstype]; m.device = reinterpret_cast(vmt2dataptr(&mount, VMT_OBJECT)); m.name = reinterpret_cast(vmt2dataptr(&mount, VMT_STUB)); string opts = reinterpret_cast(vmt2dataptr(&mount, VMT_ARGS)); boost::split(m.options, opts, boost::is_any_of(",")); struct statfs64 fs; if (0 != statfs64(const_cast(m.name.c_str()), &fs)) { LOG_WARNING("Could not get fs data for {1}: {2}", m.name, errno); } else { m.size = fs.f_bsize*fs.f_blocks; m.available = fs.f_bsize*fs.f_bfree; } _mounts[m.device] = m.name; result.mountpoints.emplace_back(move(m)); } } void filesystem_resolver::collect_partition_data(data& result) { auto cu_dv = odm_class::open("CuDv"); auto cu_at = odm_class::open("CuAt"); for (auto& dv : cu_dv.query("PdDvLn=logical_volume/lvsubclass/lvtype")) { partition p; p.name = string("/dev/") + dv.name; string query = (boost::format("name=%1%") % dv.name).str(); for (auto& at : cu_at.query(query)) { if (0 == strcmp(at.attribute, "label")) { p.label = at.value; } else if (0 == strcmp(at.attribute, "lvserial_id")) { struct lv_id id; // AAAAAAAABBBBBBBBCCCCCCCCDDDDDDDD.EEEE format // First four chunks are hexadecimal 32-bit integers. // After the dot is a decimal integer // Volume groups from the 90s only have 64-bit IDs, // rather than the full 128. auto vgid = string(at.value); auto length = vgid.find_first_of('.'); id.vg_id.word1 = stoul(vgid.substr(0, 8), nullptr, 16); id.vg_id.word2 = stoul(vgid.substr(8, 8), nullptr, 16); if (length == 32) { id.vg_id.word3 = stoul(vgid.substr(16, 8), nullptr, 16); id.vg_id.word4 = stoul(vgid.substr(24, 8), nullptr, 16); } id.minor_num = stoul(vgid.substr(length+1, string::npos), nullptr, 10); struct querylv* lv; if (0 != lvm_querylv(&id, &lv, nullptr)) { LOG_WARNING("Could not get info for partition '{1}' from the LVM subsystem", p.name); } else if (!lv) { LOG_WARNING("querylv returned success but we got a null LV. WTF?"); } else { // Size is calculated as "currentsize * 2^ppsize". p.size = lv->currentsize; p.size <<= lv->ppsize; } } else if (0 == strcmp(at.attribute, "type")) { p.filesystem = at.value; } } p.mount = _mounts[p.name]; result.partitions.emplace_back(move(p)); } } }}} facter-3.14.12/lib/src/facts/aix/kernel_resolver.cc0000644005276200011600000000135313702047406021751 0ustar jenkinsjenkins#include #include #include #include #include #include #include using namespace leatherman::execution; using namespace std; namespace facter { namespace facts { namespace aix { kernel_resolver::data kernel_resolver::collect_data(collection& facts) { data result; auto exec = execute("/usr/bin/oslevel", {"-s"}); result.name = "AIX"; result.release = exec.output; result.version = exec.output.substr(0, 4); return result; } }}} // namespace facter::facts::aix facter-3.14.12/lib/src/facts/aix/load_average_resolver.cc0000644005276200011600000000360013702047406023077 0ustar jenkinsjenkins#include #include #include #include #include // Mark string for translation (alias for leatherman::locale::format) using leatherman::locale::_; using namespace std; /** * This system call lets us query the kernel directly for system * information. We use it to get our current load averages. * * @param info the info we're retrieving from the kernel. * @param buf the buffer that we'll store the information in * @param buf_size a pointer to the variable containing the size of the buffer in bytes * @param arg no idea what this param. represents. we will usually set this to 0. * @return 0 if we successfully retrieve the information, else a negative value */ extern "C" int getkerninfo(int info, char* buf, int* buf_size, int32long64_t arg); // Converts the given integer average into a load average. static double to_load_avg(double average) { // 65536 is the load average scale on AIX machines. return average / 65536; } namespace facter { namespace facts { namespace aix { boost::optional > load_average_resolver::get_load_averages() { // This approach was adapted from screen-4.6.2's loadav.c file. See // https://www.mail-archive.com/opensuse-commit@opensuse.org/msg122486.html array averages; int buf_size = averages.size() * sizeof(long long); int rc = getkerninfo(KINFO_GET_AVENRUN, reinterpret_cast(averages.data()), &buf_size, 0); if (rc < 0) { LOG_DEBUG(_("failed to retrieve the load averages")); return boost::none; } return make_tuple( to_load_avg(averages[0]), to_load_avg(averages[1]), to_load_avg(averages[2])); } }}} // namespace facter::facts::aix facter-3.14.12/lib/src/facts/aix/memory_resolver.cc0000644005276200011600000000453113702047406022002 0ustar jenkinsjenkins#include #include #include #include #include #include #include using namespace std; using namespace facter::util::aix; // This routine is useful to encapsulate knowledge of the PAGE_SIZE // in one place and to also handle implicit conversions of numeric // values to uint64_t, which is what we use to represent bytes. Otherwise, // we risk accidentally capturing an overflowed value in our computed // memory facts. static uint64_t pages_to_bytes(uint64_t num_pages) { return num_pages * PAGE_SIZE; } namespace facter { namespace facts { namespace aix { memory_resolver::data memory_resolver::collect_data(collection& facts) { data result; vminfo info; auto res = vmgetinfo(&info, VMINFO, sizeof(info)); if (res < 0) { throw system_error(errno, system_category()); } result.mem_total = pages_to_bytes(info.memsizepgs); result.mem_free = pages_to_bytes(info.numfrb); auto cu_at_query = odm_class::open("CuAt").query("value=paging and attribute=type"); for (auto& cu_at : cu_at_query) { string device = string("/dev/") + cu_at.name; pginfo info; auto res = swapqry(const_cast(device.c_str()), &info); if (res < 0) { // it's really hard to tell from the ODM if a device // is a disk, just by its name. So we'll always try to // swapqry the things that have an attribute we // expect, but ignore any errno values that look like // "this just wasn't a good device to query" // ENXIO: No such device address. if (errno != ENODEV && errno != ENOENT && errno != ENOTBLK && errno != ENXIO) { throw system_error(errno, system_category(), device); } else { LOG_DEBUG("cannot use device {1}: error is {2}", device, errno); } } result.swap_total += pages_to_bytes(info.size); result.swap_free += pages_to_bytes(info.free); } return result; } }}} // namespace facter::facts::aix facter-3.14.12/lib/src/facts/aix/networking_resolver.cc0000644005276200011600000002413213702047406022660 0ustar jenkinsjenkins#include #include #include #include #include #include #include #include #include #include #include #include // Mark string for translation (alias for leatherman::locale::format) using leatherman::locale::_; // This usage is recommended in several mailing lists, and is used at // least in Samba to query mac addresses. I saw some references to old // IBM publications also recommending its use, but couldn't actually // dig those pubs up. // // The structs it *returns* are in headers, though (specifically // mentioning usage of this function). // // This is all leftovers from ancient versions of the BSD networking // stack that every OS in the world has stolen/borrowed. It is pretty // gross in a lot of ways, but is what we have to work with on AIX. // // There does not appear to be a different or documented way to get // this information, outside of shelling out to tools which provide // human- rather than machine-readable output. extern "C" int getkerninfo(int, char*, int*, int32long64_t); template static std::vector getkerninfo(int query) { for (;;) { auto ksize = getkerninfo(query, nullptr, nullptr, 0); if (ksize == 0) { throw std::runtime_error(_("getkerninfo call was unsuccessful")); } auto alloc_size = ksize; auto count = alloc_size/sizeof(T); std::vector result(count); if (getkerninfo(query, reinterpret_cast(result.data()), &ksize, 0) == -1) { throw std::runtime_error(_("getkerninfo call was unsuccessful")); } // getkerninfo updates the size variable to match our actual // buffer size. If we need more space we loop to // reallocate. Otherwise we make sure the vector is trimmed to // the proper size and return the contents. if (ksize <= alloc_size) { result.resize(ksize/sizeof(T)); return result; } } } namespace facter { namespace facts { namespace aix { networking_resolver::data networking_resolver::collect_data(collection& facts) { auto data = posix::networking_resolver::collect_data(facts); // Query the kernel for the list of network interfaces and // their associated addresses data.interfaces = get_interfaces(); // query the network device descriptors from the kernel. This // gives us physical information, such as mtu. auto mtus = get_mtus(); for (auto& iface : data.interfaces) { auto mtu_iter = mtus.find(iface.name); if (mtu_iter != mtus.end()) { iface.mtu = stoll(mtu_iter->second); } } data.primary_interface = get_primary_interface(); return data; } networking_resolver::mtu_map networking_resolver::get_mtus() const { mtu_map result; leatherman::execution::each_line("/usr/bin/netstat", {"-in"}, [&](std::string line) { std::vector fields; boost::trim(line); boost::split(fields, line, boost::is_space(), boost::token_compress_on); if (boost::starts_with(fields[2], "link")) { result[fields[0]] = fields[1]; } return true; }); return result; } std::vector networking_resolver::get_interfaces() const { auto buffer = getkerninfo(KINFO_RT_IFLIST); // interfaces are identified by 16-bit IDs. these may or may // not be sequential, so we use a map as a sparse array std::map ifaces; decltype(buffer)::size_type cursor = 0; while (cursor < buffer.size()) { if_msghdr* hdr = reinterpret_cast(buffer.data() + cursor); switch (hdr->ifm_type) { case RTM_IFINFO: { sockaddr_dl* link_addr = reinterpret_cast(hdr+1); // sockaddr immediately follows the header // Name is not zero-terminated, we must pass the length to the string constructor. ifaces[hdr->ifm_index].name = std::string(link_addr->sdl_data, link_addr->sdl_nlen); // The mac address is stored in binary immediately following the name length ifaces[hdr->ifm_index].macaddress = macaddress_to_string(reinterpret_cast(link_addr->sdl_data+link_addr->sdl_nlen)); break; } case RTM_NEWADDR: { // This is gross. Immediately following the header is // a number of addresses which may or may not // individually be present based on a bitfield. They // are stored in a specific order, at least. // Additionally, each address struct could be cut off // or padded - we need to check the length of each one // to know where the next one starts. PLUS we don't // know whether we're looking at IPV4 or IPV6 until we // find an address that actually specifies its // protocol (the first one might not). // sockaddr_storage is guaranteed to be big enough for the memcpy below. std::array addrs; memset(addrs.data(), 0, RTAX_MAX*sizeof(sockaddr_storage)); // This represents our position walking the list of address objects int addr_cursor = cursor + sizeof(if_msghdr); #define FACT_READ_ADDR(a) if (hdr->ifm_addrs & RTA_##a) { \ sockaddr* sa = reinterpret_cast(buffer.data()+addr_cursor); \ memcpy(&(addrs[ RTAX_##a ]), sa, sa->sa_len); \ addr_cursor += RT_ROUNDUP(sa); \ } FACT_READ_ADDR(DST); FACT_READ_ADDR(GATEWAY); FACT_READ_ADDR(NETMASK); FACT_READ_ADDR(GENMASK); FACT_READ_ADDR(IFP); FACT_READ_ADDR(IFA); FACT_READ_ADDR(AUTHOR); FACT_READ_ADDR(BRD); // WOO addresses read. Now we try to figure out if // we're IPv4 or IPv6. We skip any other families, and // warn if we get a mixed set of families. int family = AF_UNSPEC; for (const auto& addr : addrs) { if (family != AF_UNSPEC && addr.ss_family != AF_UNSPEC && family != addr.ss_family) { family = AF_MAX; break; } family = addr.ss_family; } binding addr_binding; sockaddr* netmask = reinterpret_cast(&addrs[RTAX_NETMASK]); sockaddr* address = reinterpret_cast(&addrs[RTAX_IFA]); if (netmask->sa_len) { netmask->sa_family = family; // AIX likes to return the netmask with AF_UNSPEC family. addr_binding.netmask = address_to_string(netmask); } if (address->sa_len) { addr_binding.address = address_to_string(address); } if (address->sa_len && netmask->sa_len) { addr_binding.network = address_to_string(address, netmask); } if (family == AF_MAX) { LOG_WARNING("got mixed address families for interface {1}, can't map them to a single binding.", ifaces[hdr->ifm_index].name); } else if (family == AF_INET) { LOG_INFO("got ipv4 addresses for interface {1}", ifaces[hdr->ifm_index].name); ifaces[hdr->ifm_index].ipv4_bindings.push_back(addr_binding); } else if (family == AF_INET6) { LOG_INFO("got ipv6 addresses for interface {1}", ifaces[hdr->ifm_index].name); ifaces[hdr->ifm_index].ipv6_bindings.push_back(addr_binding); } else if (family != AF_UNSPEC) { LOG_INFO("skipping unknown address family {1} for interface {2}", family, ifaces[hdr->ifm_index].name); } else { LOG_INFO("somehow didn't get an address family for interface {1}", ifaces[hdr->ifm_index].name); } break; } default: { LOG_INFO("got an unknown RT_IFLIST message: {1}", hdr->ifm_type); break; } } cursor += hdr->ifm_msglen; } // Now that we're done processing the data we don't care about // the kernel's iface IDs anymore. std::vector result; for (auto& iface : ifaces) { result.push_back(iface.second); } return result; } std::string networking_resolver::get_primary_interface() const { std::string value; leatherman::execution::each_line("netstat", { "-rn"}, [&value](std::string& line) { boost::trim(line); if (boost::starts_with(line, "default")) { std::vector fields; boost::split(fields, line, boost::is_space(), boost::token_compress_on); value = fields.size() < 6 ? "" : fields[5]; return false; } return true; }); return value; } bool networking_resolver::is_link_address(const sockaddr* addr) const { // We explicitly populate the MAC address; we don't need address_to_string to support link layer addresses return false; } uint8_t const* networking_resolver::get_link_address_bytes(const sockaddr * addr) const { return nullptr; } uint8_t networking_resolver::get_link_address_length(const sockaddr * addr) const { return 0; } }}} // namespace facter::facts::aix facter-3.14.12/lib/src/facts/aix/nim_resolver.cc0000644005276200011600000000257713702047406021265 0ustar jenkinsjenkins#include #include #include #include #include #include #include #include #include #include using namespace std; using namespace facter::util::aix; using namespace leatherman::util; using namespace leatherman::execution; using namespace facter::facts; namespace facter { namespace facts { namespace aix { nim_resolver::nim_resolver() : resolver( "AIX NIM type", { fact::nim_type, }) { } string nim_resolver::read_niminfo() { auto exec = execute("cat", {"/etc/niminfo"}); if (!exec.success) { LOG_DEBUG("Could not read `/etc/niminfo`"); return {}; } boost::smatch type; boost::regex expr{"NIM_CONFIGURATION=(master|standalone)"}; boost::regex_search(exec.output, type, expr); return type[1]; } void nim_resolver::resolve(collection& facts) { string type = read_niminfo(); if (type.empty()) { return; } facts.add(fact::nim_type, make_value(type, true)); } }}}; // namespace facter::facts::aix facter-3.14.12/lib/src/facts/aix/operating_system_resolver.cc0000644005276200011600000001021513702047406024062 0ustar jenkinsjenkins#include #include #include #include #include #include #include #include #include #include #include #include using namespace std; using namespace facter::util::aix; // This routine's meant to be a general utility function that replicates the behavior of // lsattr -El -a . Although it's only used to get the modelname of the // sys0 device, we still would like to have it here in case we ever need to separate it // out to an AIX utils file to query other attributes. Part of what lsattr does is check // PdAt if we don't have an entry for the object's attribute in CuAt, even though it is very // unlikely that sys0.modelname will not have a CuAt entry. That is why we have the extra code // in here. static string getattr(string object, string field) { // High-level logic here is: // * Check if there's an entry for our object's field attribute in CuAt (the device-specific // attribute entry). // // * Else, check for the field attribute's default value in PdAt. We do this by first // figuring out the PdDv type from the CuDv entry for the object, then use our PdDv type // to query the field's default value in PdAt. string query = (boost::format("name = %1% AND attribute = %2%") % object % field).str(); auto cuat_query = odm_class::open("CuAt").query(query); // This is a more verbose way of saying that we only expect our query to have one element auto cuat_ref = cuat_query.begin(); if (cuat_ref != cuat_query.end()) { auto value = string(cuat_ref->value); if (value.empty()) { LOG_DEBUG("Could not get a value from the ODM for {1}'s '{2}' attribute.", object, field); } return value; } // Get the PdDv type from the CuDv entry query = (boost::format("name = %1%") % object).str(); auto cudv_query = odm_class::open("CuDv").query(query); auto cudv_ref = cudv_query.begin(); if (cudv_ref == cudv_query.end()) { LOG_DEBUG("Could not get a value from the ODM for {1}'s '{2}' attribute: There is no CuDv entry for {1}.", object, field); return ""; } auto pddv_type = cudv_ref->PdDvLn_Lvalue; query = (boost::format("uniquetype = %1% AND attribute = %2%") % pddv_type % field).str(); auto pdat_query = odm_class::open("PdAt").query(query); auto pdat_ref = pdat_query.begin(); if (pdat_ref != pdat_query.end()) { auto value = string(pdat_ref->deflt); if (value.empty()) { LOG_DEBUG("Could not get a value from the ODM for {1}'s '{2}' attribute.", object, field); } return value; } LOG_DEBUG("Could not get a value from the ODM for {1}'s '{2}' attribute: There is no PdAt entry for {1} with {2}.", object, field); return ""; } namespace facter { namespace facts { namespace aix { operating_system_resolver::data operating_system_resolver::collect_data(collection& facts) { // Default to the base implementation auto result = posix::operating_system_resolver::collect_data(facts); // on AIX, major version is hyphen-delimited. The base // resolver can't figure this out for us. vector tokens; boost::split(tokens, result.release, boost::is_any_of("-")); result.major = tokens[0]; // Get the hardware result.hardware = getattr("sys0", "modelname"); // Now get the architecture. We use processor.models[0] for this information. auto processors = facts.get(fact::processors); auto models = processors ? processors->get("models") : nullptr; if (! models || models->empty()) { LOG_DEBUG("Could not get a value for the OS architecture. Your machine does not have any processors!"); } else { result.architecture = models->get(0)->value(); } return result; } }}} facter-3.14.12/lib/src/facts/aix/processor_resolver.cc0000644005276200011600000001021613702047406022506 0ustar jenkinsjenkins#include #include #include #include #include #include #include #include #include using namespace std; using namespace facter::util::aix; using facter::util::maybe_stoi; struct physical_processor { string type; long long frequency; int smt_threads; bool smt_enabled; }; namespace facter { namespace facts { namespace aix { processor_resolver::data processor_resolver::collect_data(collection& facts) { auto result = posix::processor_resolver::collect_data(facts); // On AIX, we query the object data manager (odm) for // processor information. This is a semi-hierarchical // datastore of all the information about the system. For // processors, we need to go through three links: // // 1. We query for all "predefined devices" with the // "processor" class. I don't know if it's actually possible // to get more than one result here - on the Puppet LPARs // there is only one. // // 2. For each predefined device, we query the "custom // devices". These represent the actual processors in the // machine. // // 3. For each custom device, we query its attributes. These // are things like frequency, type, and SMT information. vector processor_types; auto pd_dv_query = odm_class::open("PdDv").query("class=processor"); for (auto& pd_dv : pd_dv_query) { LOG_DEBUG("got a processor type: {1}", pd_dv.uniquetype); processor_types.push_back(pd_dv.uniquetype); } vector processor_names; for (string& type : processor_types) { string query = (boost::format("PdDvLn=%1%") % type).str(); auto cu_dv_query = odm_class::open("CuDv").query(query); for (auto& cu_dv : cu_dv_query) { LOG_DEBUG("got a processor: {1}", cu_dv.name); processor_names.push_back(cu_dv.name); } } for (string& name : processor_names) { string query = (boost::format("name=%1%") % name).str(); physical_processor proc; auto cu_at_query = odm_class::open("CuAt").query(query); for (auto& cu_at : cu_at_query) { LOG_DEBUG("got attribute {1}={2} for processor {3}", cu_at.attribute, cu_at.value, name); if (cu_at.attribute == string("frequency")) { proc.frequency = stoll(cu_at.value); } else if (cu_at.attribute == string("type")) { proc.type = cu_at.value; } else if (cu_at.attribute == string("smt_threads")) { auto smt_threads = maybe_stoi(cu_at.value); if (smt_threads) { proc.smt_threads = smt_threads.get(); } } else if (cu_at.attribute == string("smt_enabled")) { proc.smt_enabled = (cu_at.value == string("true")); } else { LOG_INFO("don't know what to do with processor attribute {1}", cu_at.attribute) } } if (result.speed == 0) { result.speed = proc.frequency; } else if (result.speed != proc.frequency) { LOG_WARNING("mismatched processor frequencies found; facter will only report one of them"); } if (proc.smt_enabled) { result.logical_count += proc.smt_threads; vector types(proc.smt_threads, proc.type); result.models.insert(result.models.begin(), make_move_iterator(types.begin()), make_move_iterator(types.end())); } else { result.logical_count += 1; result.models.push_back(move(proc.type)); } } return result; } }}} // namespace facter::facts::aix facter-3.14.12/lib/src/facts/aix/serial_number_resolver.cc0000644005276200011600000000271113702047406023317 0ustar jenkinsjenkins#include #include #include #include #include #include #include #include #include using namespace std; using namespace facter::util::aix; using namespace leatherman::util; namespace facter { namespace facts { namespace aix { serial_number_resolver::serial_number_resolver() : resolver( "AIX serial number", { fact::serial_number, }) { } void serial_number_resolver::resolve(collection& facts) { auto cu_at_query = odm_class::open("CuAt").query("name=sys0 and attribute=systemid"); auto result = *cu_at_query.begin(); // the ODM returns a string of the form "IBM,XXSERIAL#". We // need to strip the "IBM,XX" from the start ofthis, and keep // only the 7 actual serial number bytes. const auto regex = boost::regex("^IBM,\\d\\d(.+)"); string serial; if (re_search(string(result.value), regex, &serial)) { facts.add(fact::serial_number, make_value(move(serial), true)); } else { LOG_WARNING("Could not retrieve serial number: sys0 systemid did not match the expected format"); } } }}} // namespace facter::facts::aix facter-3.14.12/lib/src/facts/array_value.cc0000644005276200011600000000536513702047406020310 0ustar jenkinsjenkins#include #include #include #include #include using namespace std; using namespace rapidjson; using namespace YAML; namespace facter { namespace facts { array_value::array_value(array_value&& other) { *this = std::move(other); } array_value& array_value::operator=(array_value&& other) { value::operator=(static_cast(other)); if (this != &other) { _elements = std::move(other._elements); } return *this; } void array_value::add(unique_ptr value) { if (!value) { LOG_DEBUG("null value cannot be added to array."); return; } _elements.emplace_back(move(value)); } bool array_value::empty() const { return _elements.empty(); } size_t array_value::size() const { return _elements.size(); } void array_value::each(function func) const { for (auto const& element : _elements) { if (!func(element.get())) { break; } } } void array_value::to_json(json_allocator& allocator, json_value& value) const { value.SetArray(); value.Reserve(_elements.size(), allocator); for (auto const& element : _elements) { json_value child; element->to_json(allocator, child); value.PushBack(child, allocator); } } value const* array_value::operator[](size_t i) const { if (i >= _elements.size()) { return nullptr; } return _elements[i].get(); } ostream& array_value::write(ostream& os, bool quoted, unsigned int level) const { if (_elements.empty()) { os << "[]"; return os; } // Write out the elements in the array os << "[\n"; bool first = true; for (auto const& element : _elements) { if (first) { first = false; } else { os << ",\n"; } fill_n(ostream_iterator(os), level * 2, ' '); element->write(os, true /* always quote strings in an array */, level + 1); } os << "\n"; fill_n(ostream_iterator(os), (level > 0 ? (level - 1) : 0) * 2, ' '); os << "]"; return os; } Emitter& array_value::write(Emitter& emitter) const { emitter << BeginSeq; for (auto const& element : _elements) { element->write(emitter); } emitter << EndSeq; return emitter; } }} // namespace facter::facts facter-3.14.12/lib/src/facts/bsd/0000755005276200011600000000000013702047635016232 5ustar jenkinsjenkinsfacter-3.14.12/lib/src/facts/bsd/collection.cc0000644005276200011600000000201513702047406020666 0ustar jenkinsjenkins#include #include #include #include #include #include #include #include #include using namespace std; namespace facter { namespace facts { void collection::add_platform_facts() { add(make_shared()); add(make_shared()); add(make_shared()); add(make_shared()); add(make_shared()); add(make_shared()); add(make_shared()); add(make_shared()); } }} // namespace facter::facts facter-3.14.12/lib/src/facts/bsd/filesystem_resolver.cc0000644005276200011600000000723613702047406022652 0ustar jenkinsjenkins#include #include #include #include #include using namespace std; using namespace facter::facts; using namespace facter::util; namespace facter { namespace facts { namespace bsd { filesystem_resolver::data filesystem_resolver::collect_data(collection& facts) { data result; // First get the count of file systems int count = getfsstat(nullptr, 0, MNT_NOWAIT); if (count == -1) { LOG_ERROR("getfsstat failed: {1} ({2}): file system facts are unavailable.", strerror(errno), errno); return result; } // Get the actual data vector filesystems(count); count = getfsstat(filesystems.data(), filesystems.size() * sizeof(struct statfs), MNT_NOWAIT); if (count == -1) { LOG_ERROR("getfsstat failed: {1} ({2}): file system facts are unavailable.", strerror(errno), errno); return result; } result.mountpoints.reserve(count); // Populate an entry for each mounted file system for (auto& fs : filesystems) { mountpoint point; point.name = fs.f_mntonname; point.device = fs.f_mntfromname; point.filesystem = fs.f_fstypename; point.size = (static_cast(fs.f_bsize) * static_cast(fs.f_blocks)); point.available = (static_cast(fs.f_bsize) * static_cast(fs.f_bfree)); point.options = to_options(fs); result.mountpoints.emplace_back(move(point)); result.filesystems.insert(fs.f_fstypename); } return result; } vector filesystem_resolver::to_options(struct statfs const& fs) { static vector> const flags = { make_tuple(MNT_RDONLY, "readonly"), make_tuple(MNT_SYNCHRONOUS, "noasync"), make_tuple(MNT_NOEXEC, "noexec"), make_tuple(MNT_NOSUID, "nosuid"), #ifndef __OpenBSD__ make_tuple(MNT_UNION, "union"), #endif make_tuple(MNT_ASYNC, "async"), make_tuple(MNT_EXPORTED, "exported"), make_tuple(MNT_LOCAL, "local"), make_tuple(MNT_QUOTA, "quota"), make_tuple(MNT_ROOTFS, "root"), make_tuple(MNT_NOATIME, "noatime"), #if !defined(__FreeBSD__) make_tuple(MNT_NODEV, "nodev"), #endif #if !defined(__FreeBSD__) && !defined(__OpenBSD__) // the following constants aren't defined on FreeBSD 10/OpenBSD make_tuple(MNT_DONTBROWSE, "nobrowse"), make_tuple(MNT_AUTOMOUNTED, "automounted"), make_tuple(MNT_JOURNALED, "journaled"), make_tuple(MNT_DEFWRITE, "deferwrites"), #endif #ifdef __OpenBSD__ make_tuple(MNT_WXALLOWED, "wxallowed"), #endif }; vector options; for (auto const& flag : flags) { if (fs.f_flags & get<0>(flag)) { options.push_back(get<1>(flag)); } } return options; } }}} // namespace facter::facts::bsd facter-3.14.12/lib/src/facts/bsd/networking_resolver.cc0000644005276200011600000002434013702047406022650 0ustar jenkinsjenkins#include #include #include #include #include #include #include #include #include #include #include #include using namespace std; using namespace facter::util::bsd; using namespace leatherman::execution; using namespace leatherman::util; using facter::util::maybe_stoi; namespace lth_file = leatherman::file_util; namespace facter { namespace facts { namespace bsd { networking_resolver::data networking_resolver::collect_data(collection& facts) { auto data = posix::networking_resolver::collect_data(facts); // Scope the head ifaddrs ptr scoped_ifaddrs addrs; if (!addrs) { LOG_WARNING("getifaddrs failed: {1} ({2}): interface information is unavailable.", strerror(errno), errno); return data; } // Map an interface to entries describing that interface multimap interface_map; for (ifaddrs* ptr = addrs; ptr; ptr = ptr->ifa_next) { // We only support IPv4, IPv6, and link interfaces if (!ptr->ifa_addr || !ptr->ifa_name || (ptr->ifa_addr->sa_family != AF_INET && ptr->ifa_addr->sa_family != AF_INET6 && !is_link_address(ptr->ifa_addr))) { continue; } interface_map.insert({ ptr->ifa_name, ptr }); } data.primary_interface = get_primary_interface(); // Start by getting the DHCP servers auto dhcp_servers = find_dhcp_servers(); // Walk the interfaces decltype(interface_map.begin()) it = interface_map.begin(); while (it != interface_map.end()) { string const& name = it->first; interface iface; iface.name = name; // Walk the addresses of this interface and populate the data for (; it != interface_map.end() && it->first == name; ++it) { populate_binding(iface, it->second); populate_mtu(iface, it->second); } // Populate the interface's DHCP server value auto dhcp_server_it = dhcp_servers.find(name); if (dhcp_server_it == dhcp_servers.end()) { iface.dhcp_server = find_dhcp_server(name); } else { iface.dhcp_server = dhcp_server_it->second; } data.interfaces.emplace_back(move(iface)); } return data; } void networking_resolver::populate_binding(interface& iface, ifaddrs const* addr) const { // If the address is a link address, populate the MAC if (is_link_address(addr->ifa_addr)) { iface.macaddress = address_to_string(addr->ifa_addr); return; } // Populate the correct bindings list vector* bindings = nullptr; if (addr->ifa_addr->sa_family == AF_INET) { bindings = &iface.ipv4_bindings; } else if (addr->ifa_addr->sa_family == AF_INET6) { bindings = &iface.ipv6_bindings; } if (!bindings) { return; } binding b; b.address = address_to_string(addr->ifa_addr); if (addr->ifa_netmask) { b.netmask = address_to_string(addr->ifa_netmask); b.network = address_to_string(addr->ifa_addr, addr->ifa_netmask); } bindings->emplace_back(std::move(b)); } void networking_resolver::populate_mtu(interface& iface, ifaddrs const* addr) const { // The MTU exists on link addresses if (!is_link_address(addr->ifa_addr) || !addr->ifa_data) { return; } iface.mtu = get_link_mtu(addr->ifa_name, addr->ifa_data); } string networking_resolver::get_primary_interface() const { string interface; each_line("route", { "-n", "get", "default" }, [&interface](string& line){ boost::trim(line); if (boost::starts_with(line, "interface: ")) { interface = line.substr(11); boost::trim(interface); return false; } return true; }); LOG_DEBUG("got primary interface: \"{1}\"", interface); return interface; } void networking_resolver::find_dhclient_dhcp_servers(std::map& servers) const { static vector const dhclient_search_directories = { "/var/lib/dhclient", "/var/lib/dhcp", "/var/lib/dhcp3", "/var/lib/NetworkManager", "/var/db" }; for (auto const& dir : dhclient_search_directories) { LOG_DEBUG("searching \"{1}\" for dhclient lease files.", dir); lth_file::each_file(dir, [&](string const& path) { LOG_DEBUG("reading \"{1}\" for dhclient lease information.", path); // Each lease entry should have the interface declaration before the options // We respect the last lease for an interface in the file string interface; lth_file::each_line(path, [&](string& line) { boost::trim(line); if (boost::starts_with(line, "interface ")) { interface = line.substr(10); trim_if(interface, boost::is_any_of("\";")); } else if (!interface.empty() && boost::starts_with(line, "option dhcp-server-identifier ")) { string server = line.substr(30); trim_if(server, boost::is_any_of("\";")); servers.emplace(make_pair(move(interface), move(server))); } return true; }); return true; }, "^dhclient.*lease.*$"); } } void networking_resolver::find_nm_internal_dhcp_servers(std::map& servers) const { static vector const nm_search_directories = { "/var/lib/NetworkManager" }; for (auto const& dir : nm_search_directories) { LOG_DEBUG("searching \"{1}\" for NetworkManager internal lease files", dir) lth_file::each_file(dir, [&](string const& path) { LOG_DEBUG("reading \"{1}\" for NetworkManager lease information.", path); vector parts; boost::split(parts, path, boost::is_any_of("-")); auto filename = parts.back(); boost::split(parts, filename, boost::is_any_of(".")); string interface = parts[0]; lth_file::each_line(path, [&](string &line) { if (boost::starts_with(line, "SERVER_ADDRESS")) { string server = line.substr(15); servers.emplace(make_pair(move(interface), move(server))); } return true; }); return true; }, "^internal.*lease.*$"); } } void networking_resolver::find_networkd_dhcp_servers(std::map& servers) const { // Files in this lease directory are not part of systemd's public API, // and they include warnings against parsing them, but they seem to be // the only way to get this information for now. // Each file is named after the interface's index number. static const string networkd_lease_directory = "/run/systemd/netif/leases/"; if (!boost::filesystem::is_directory(networkd_lease_directory)) return; static boost::regex ip_link_re("^(\\d+):\\s+([^:]+)"); unordered_map iface_index_names; string key, value; // Gather a map of interface indices and their interface names from `ip link show` -- // Only the index is known in the lease files. each_line("ip", {"link", "show"}, [&](string line) { if (re_search(line, ip_link_re, &key, &value)) { iface_index_names.insert(make_pair(stoi(key), value)); } return true; }); LOG_DEBUG("searching \"{1}\" for systemd-networkd DHCP lease files", networkd_lease_directory); lth_file::each_file(networkd_lease_directory, [&](string const& path) { LOG_DEBUG("searching \"{1}\" for systemd-networkd DHCP lease information", path); string server_address; static boost::regex server_address_re("^SERVER_ADDRESS=(.*)$"); lth_file::each_line(path, [&](string& line) { boost::trim(line); if (re_search(line, server_address_re, &server_address)) { boost::filesystem::path p {path}; auto iface_index = maybe_stoi(p.filename().string()); if (!iface_index) return true; servers.emplace(make_pair(iface_index_names[iface_index.get()], server_address)); } return true; }); return true; }); } map networking_resolver::find_dhcp_servers() const { map servers; find_networkd_dhcp_servers(servers); if (servers.empty()) find_dhclient_dhcp_servers(servers); if (servers.empty()) find_nm_internal_dhcp_servers(servers); return servers; } string networking_resolver::find_dhcp_server(string const& interface) const { // Use dhcpcd if it's present to get the interface's DHCP lease information // This assumes we've already searched for the interface with dhclient string value; each_line("dhcpcd", { "-U", interface }, [&value](string& line) { if (boost::starts_with(line, "dhcp_server_identifier=")) { value = line.substr(23); boost::trim(value); return false; } return true; }); return value; } }}} // namespace facter::facts::bsd facter-3.14.12/lib/src/facts/bsd/uptime_resolver.cc0000644005276200011600000000126513702047406021765 0ustar jenkinsjenkins#include #include #include using namespace std; namespace facter { namespace facts { namespace bsd { int64_t uptime_resolver::get_uptime() { // this approach adapted from: http://stackoverflow.com/a/11676260/1004272 timeval boottime; size_t len = sizeof(boottime); int mib[2] = { CTL_KERN, KERN_BOOTTIME }; if (sysctl(mib, 2, &boottime, &len, NULL, 0) == 0) { time_t bsec = boottime.tv_sec; time_t now = time(NULL); return now - bsec; } return posix::uptime_resolver::get_uptime(); } }}} // namespace facter::facts::bsd facter-3.14.12/lib/src/facts/cache.cc0000644005276200011600000001411313702047406017030 0ustar jenkinsjenkins#include #include #include #include #include #include #include #include #include #include using namespace std; using namespace rapidjson; using namespace facter::facts::external; namespace boost_file = boost::filesystem; namespace facter { namespace facts { namespace cache { void clean_cache(unordered_map const& facts_to_cache, string cache_location) { boost_file::path cache_dir = boost_file::path(cache_location); if (!boost_file::is_directory(cache_dir)) { return; } for (boost_file::directory_iterator itr(cache_dir); itr != boost_file::directory_iterator(); ++itr) { boost_file::path cache_file = itr->path(); if (!facts_to_cache.count(cache_file.filename().string())) { boost::system::error_code ec; boost_file::remove(cache_file, ec); if (!ec) { LOG_DEBUG("Deleting unused cache file {1}", cache_file.string()); } else { continue; } } } } bool cache_is_valid(boost_file::path const& cache_file, int64_t ttl) { time_t last_mod = boost_file::last_write_time(cache_file); time_t now; double lifetime_seconds = difftime(time(&now), last_mod); return static_cast(lifetime_seconds) < ttl; } void load_facts_from_cache(boost_file::path const& cache_file, shared_ptr res, collection& facts) { string cache_file_path = cache_file.string(); if (leatherman::file_util::file_readable(cache_file_path)) { try { json_resolver json_res(cache_file_path); json_res.resolve(facts); } catch (external_fact_exception& ex) { LOG_DEBUG("cache file for {1} facts contained invalid JSON, refreshing", res->name()); refresh_cache(res, cache_file, facts); return; } } else { LOG_DEBUG("cache file for {1} facts was missing, refreshing", res->name()); refresh_cache(res, cache_file, facts); return; } } void refresh_cache(shared_ptr res, boost_file::path const& cache_file, collection& facts) { res->resolve(facts); boost_file::remove(cache_file); write_json_cache_file(facts, cache_file.string(), res->names()); } void use_cache(collection& facts, shared_ptr res, int64_t ttl) { boost_file::path cache_dir = boost_file::path(fact_cache_location()); if (!boost_file::is_directory(cache_dir)) { boost_file::create_directories(cache_dir); } boost_file::path cache_file = cache_dir / res->name(); if (leatherman::file_util::file_readable(cache_file.string()) && cache_is_valid(cache_file, ttl)) { LOG_DEBUG("loading cached values for {1} facts", res->name()); load_facts_from_cache(cache_file, res, facts); } else { LOG_DEBUG("caching values for {1} facts", res->name()); refresh_cache(res, cache_file, facts); } } void write_json_cache_file(const collection& facts, boost_file::path const& file_path, vector const& fact_names) { json_document document; document.SetObject(); auto builder = ([&](string const& key, value const* val) { json_value value; if (val) { val->to_json(document.GetAllocator(), value); } else { value.SetString("", 0); } document.AddMember(StringRef(key.c_str(), key.size()), value, document.GetAllocator()); }); for (auto const& name : fact_names) { auto fact_value = facts.get_resolved(name); if (fact_value) { builder(name, fact_value); } } string file_path_string = file_path.string(); boost::nowide::ofstream stream(file_path_string); stream_adapter adapter(stream); PrettyWriter writer(adapter); writer.SetIndent(' ', 2); document.Accept(writer); } boost_file::path custom_fact_cache_file_location() { boost_file::path cache_dir = boost_file::path(facter::facts::cache::fact_cache_location()); if (!boost_file::is_directory(cache_dir)) boost_file::create_directories(cache_dir); boost_file::path custom_fact_cache_file_location = cache_dir / cached_custom_facts; return custom_fact_cache_file_location; } bool load_cached_custom_facts(collection& collection, int64_t ttl) { boost_file::path cache_file = custom_fact_cache_file_location(); if (leatherman::file_util::file_readable(cache_file.string()) && cache::cache_is_valid(cache_file, ttl)) { try { LOG_DEBUG("Loading cached custom facts from file \"{1}\"", cache_file.string()); facts::external::json_resolver json_res(cache_file.string()); json_res.resolve(collection); return true; } catch (exception& ex) { LOG_DEBUG("Custom facts cache file contained invalid JSON, refreshing"); return false; } } else { LOG_DEBUG("Custom facts cache file expired/missing. Refreshing"); boost_file::remove(cache_file); } return false; } void write_cached_custom_facts(const collection& facts, const std::vector& cached_custom_facts_list) { boost_file::path cache_file = custom_fact_cache_file_location(); LOG_DEBUG("Saving cached custom facts to {1}", cache_file); write_json_cache_file(facts, cache_file, cached_custom_facts_list); } }}} // namespace facter::facts::cache facter-3.14.12/lib/src/facts/collection.cc0000644005276200011600000005663113702047406020133 0ustar jenkinsjenkins#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include using namespace std; using namespace facter::util; using namespace rapidjson; using namespace YAML; using namespace boost::filesystem; using namespace leatherman::util; using namespace leatherman::file_util; using facter::util::maybe_stoi; namespace facter { namespace facts { collection::collection(set const& blocklist, unordered_map const& ttls, bool ignore_cache) : _blocklist(blocklist), _ttls(ttls), _ignore_cache(ignore_cache) { // This needs to be defined here since we use incomplete types in the header } collection::~collection() { // This needs to be defined here since we use incomplete types in the header } collection::collection(collection&& other) { *this = std::move(other); } collection& collection::operator=(collection&& other) { if (this != &other) { _facts = std::move(other._facts); _resolvers = std::move(other._resolvers); _resolver_map = std::move(other._resolver_map); _pattern_resolvers = std::move(other._pattern_resolvers); _blocklist = std::move(other._blocklist); _ttls = std::move(other._ttls); } return *this; } void collection::add_default_facts(bool include_ruby_facts) { add_common_facts(include_ruby_facts); add_platform_facts(); } void collection::add(shared_ptr const& res) { if (!res) { return; } for (auto const& name : res->names()) { _resolver_map.insert({ name, res }); } if (res->has_patterns()) { _pattern_resolvers.push_back(res); } _resolvers.push_back(res); } void collection::add(string name, unique_ptr value) { // Ensure the fact is resolved before replacing it auto old_value = get_value(name); if (LOG_IS_DEBUG_ENABLED()) { if (old_value) { ostringstream old_value_ss; old_value->write(old_value_ss); if (!value) { LOG_DEBUG("fact \"{1}\" resolved to null and the existing value of {2} will be removed.", name, old_value_ss.str()); } else { ostringstream new_value_ss; value->write(new_value_ss); if (old_value->weight() > value->weight()) { LOG_DEBUG("new value for fact \"{1}\" ignored, because it's a lower weight", name); } else { LOG_DEBUG("fact \"{1}\" has changed from {2} to {3}.", name, old_value_ss.str(), new_value_ss.str()); } } } else { if (!value) { LOG_DEBUG("fact \"{1}\" resolved to null and will not be added.", name); } else { ostringstream new_value_ss; value->write(new_value_ss); LOG_DEBUG("fact \"{1}\" has resolved to {2}.", name, new_value_ss.str()); } } } if (!value) { if (old_value) { remove(name); } return; } // keep existing value if it has a larger weight value if (old_value && old_value->weight() > value->weight()) return; _facts[move(name)] = move(value); } void collection::add_custom(string name, unique_ptr value, size_t weight) { if (value) value->weight(weight); add(move(name), move(value)); } void collection::add_external(string name, unique_ptr value) { if (value) value->weight(external_fact_weight); add(move(name), move(value)); } void collection::get_external_facts_files_from_dir(external_files_list& files, string const& dir, bool warn) { // If dir is relative, make it an absolute path before passing to can_resolve. boost::system::error_code ec; path search_dir = absolute(dir); if (!is_directory(search_dir, ec)) { // Warn the user if not using the default search directories string msg = ec ? ec.message() : "not a directory"; if (warn) { LOG_WARNING("skipping external facts for \"{1}\": {2}", dir, msg); } else { LOG_DEBUG("skipping external facts for \"{1}\": {2}", dir, msg); } return; } LOG_DEBUG("searching {1} for external facts.", search_dir); external_resolvers_factory erf; each_file(search_dir.string(), [&](string const& path) { try { auto resolver = erf.get_resolver(path); files.push_back(make_pair(path, resolver)); } catch (external::external_fact_no_resolver& e) { LOG_DEBUG("skipping file \"{1}\": {2}", path, e.what()); } return true; }); } map> collection::get_external_facts_groups(vector const& directories) { map> external_facts_groups; for (auto const& it : get_external_facts_files(directories)) { external_facts_groups[it.second->name()] = {}; } return external_facts_groups; } collection::external_files_list collection::get_external_facts_files(vector const& directories) { external_files_list external_facts_files; // Build a list of pairs of files and the resolver that can resolve it // Start with default Facter search directories, then user-specified directories. for (auto const& dir : get_external_fact_directories()) { get_external_facts_files_from_dir(external_facts_files, dir, false); } for (auto const& dir : directories) { get_external_facts_files_from_dir(external_facts_files, dir, true); } return external_facts_files; } void collection::add_external_facts(vector const& directories) { external_files_list external_facts_files = get_external_facts_files(directories); if (external_facts_files.empty()) { LOG_DEBUG("no external facts were found."); } else { map known_external_facts_cache_groups; for (auto const& kvp : external_facts_files) { // Check if the resolver should be cached auto resolver_ttl = _ttls.find(kvp.second->name()); if (!_ignore_cache && resolver_ttl != _ttls.end()) { auto resolver = kvp.second; auto it = known_external_facts_cache_groups.find(resolver->name()); if ( it != known_external_facts_cache_groups.end() ) { LOG_ERROR( "Caching is enabled for group \"{1}\" while there " "are at least two external facts files with " "the same filename. To fix this either remove " "\"{1}\" from cached " "groups or rename one of the " "files:\n\"{2}\"\n\"{3}\" ", resolver->name(), kvp.first, it->second); break; } known_external_facts_cache_groups.insert(make_pair(resolver->name(), kvp.first)); cache::use_cache(*this, resolver, (*resolver_ttl).second); continue; } try { kvp.second->resolve(*this); } catch (external::external_fact_exception& ex) { LOG_ERROR( "error while processing \"{1}\" for external facts: {2}", kvp.first, ex.what()); } } } } void collection::add_environment_facts(function callback) { environment::each([&](string& name, string& value) { // If the variable starts with "FACTER_", the remainder of the variable is the fact name if (!boost::istarts_with(name, "FACTER_")) { return true; } auto fact_name = name.substr(7); boost::to_lower(fact_name); LOG_DEBUG("setting fact \"{1}\" based on the value of environment variable \"{2}\".", fact_name, name); // Add the value based on the environment variable auto fact_value = make_value(move(value)); fact_value->weight(external_fact_weight); add(fact_name, move(fact_value)); if (callback) { callback(fact_name); } return true; }); } void collection::remove(shared_ptr const& res) { if (!res) { return; } // Remove all name associations for (auto const& name : res->names()) { auto range = _resolver_map.equal_range(name); auto it = range.first; while (it != range.second) { if (it->second != res) { ++it; continue; } it = _resolver_map.erase(it); } } _pattern_resolvers.remove(res); _resolvers.remove(res); } void collection::remove(string const& name) { // Ensure the fact is in the collection // This will properly resolve the fact prior to removing it if (!get_value(name)) { return; } _facts.erase(name); } void collection::clear() { _facts.clear(); _resolvers.clear(); _resolver_map.clear(); _pattern_resolvers.clear(); } bool collection::empty() { return _facts.empty() && _resolvers.empty(); } map> collection::get_fact_groups() { map> fact_groups; for (auto res : _resolvers) { fact_groups.emplace(res->name(), res->names()); } return fact_groups; } map> collection::get_blockable_fact_groups() { map> blockgroups; for (auto res : _resolvers) { if (res->is_blockable()) { blockgroups.emplace(res->name(), res->names()); } } return blockgroups; } size_t collection::size() { resolve_facts(); return _facts.size(); } const std::unordered_map& collection::get_ttls() { return _ttls; } value const* collection::operator[](string const& name) { return get_value(name); } void collection::each(function func) { resolve_facts(); // We intentionally are using find_if with no return value as a "map until" construct. // cppcheck-suppress ignoredReturnValue find_if(begin(_facts), end(_facts), [&func](map>::value_type const& it) { return !func(it.first, it.second.get()); }); } ostream& collection::write(ostream& stream, format fmt, set const& queries) { return write(stream, fmt, queries, false, false); } ostream& collection::write(ostream& stream, format fmt, set const& queries, bool show_legacy, bool strict_errors) { if (queries.empty()) { // Resolve all facts resolve_facts(); } if (fmt == format::hash) { write_hash(stream, queries, show_legacy, strict_errors); } else if (fmt == format::json) { write_json(stream, queries, show_legacy, strict_errors); } else if (fmt == format::yaml) { write_yaml(stream, queries, show_legacy, strict_errors); } return stream; } bool collection::try_block(shared_ptr const& res) { if (_blocklist.count(res->name())) { if (res->is_blockable()) { LOG_DEBUG("blocking collection of {1} facts.", res->name()); return true; } else { LOG_DEBUG("{1} resolver cannot be blocked.", res->name()); } } return false; } void collection::resolve(shared_ptr const& res) { remove(res); // Check if the resolver has been blocked if (try_block(res)) { return; } // Check if the resolver should be cached auto resolver_ttl = _ttls.find(res->name()); if (!_ignore_cache && resolver_ttl != _ttls.end()) { cache::use_cache(*this, res, (*resolver_ttl).second); return; } // Resolve normally LOG_DEBUG("resolving {1} facts.", res->name()); try { res->resolve(*this); } catch (std::runtime_error &e) { LOG_WARNING("exception resolving {1} facts, some facts will not be available: {2}", res->name(), e.what()); } } void collection::resolve_facts() { // Delete any unused cache files if (!_ignore_cache) { cache::clean_cache(_ttls); } // Remove the front of the resolvers list and resolve until no resolvers are left while (!_resolvers.empty()) { auto resolver = _resolvers.front(); resolve(resolver); } } void collection::resolve_fact(string const& name) { // Resolve every resolver mapped to this name first auto range = _resolver_map.equal_range(name); auto it = range.first; while (it != range.second) { auto resolver = (it++)->second; resolve(resolver); } // Resolve every resolver that matches the given name auto pattern_it = _pattern_resolvers.begin(); while (pattern_it != _pattern_resolvers.end()) { if (!(*pattern_it)->is_match(name)) { ++pattern_it; continue; } auto resolver = *(pattern_it++); resolve(resolver); } } value const* collection::get_value(string const& name) { resolve_fact(name); // Lookup the fact auto it = _facts.find(name); return it == _facts.end() ? nullptr : it->second.get(); } value const* collection::query_value(string const& query, bool strict_errors) { // First attempt to lookup a fact with the exact name of the query value const* current = get_value(query); if (current) { return current; } bool in_quotes = false; vector segments; string segment; for (auto const& c : query) { if (c == '"') { in_quotes = !in_quotes; continue; } if (in_quotes || c != '.') { segment += c; continue; } segments.emplace_back(move(segment)); segment.clear(); } if (!segment.empty()) { segments.emplace_back(move(segment)); } auto segment_end = end(segments); for (auto segment = begin(segments); segment != segment_end; ++segment) { auto rb_val = dynamic_cast(current); if (rb_val) { current = facter::ruby::lookup(current, segment, segment_end); if (!current) { LOG_DEBUG("cannot lookup an element with \"{1}\" from Ruby fact", *segment); } // Once we hit Ruby there's no going back, so whatever we get from Ruby is the value. return current; } else { current = lookup(current, *segment, strict_errors); } if (!current) { // Break out early if there's no value for this segment return nullptr; } } return current; } value const* collection::lookup(value const* value, string const& name, bool strict_errors) { if (!value) { value = get_value(name); if (!value) { string message = "fact \"{1}\" does not exist."; if (strict_errors) { LOG_ERROR(message, name); } else { LOG_DEBUG(message, name); } } return value; } auto map = dynamic_cast(value); if (map) { value = (*map)[name]; if (!value) { LOG_DEBUG("cannot lookup a hash element with \"{1}\": element does not exist.", name); } return value; } auto array = dynamic_cast(value); if (!array) { return nullptr; } auto maybe_index = maybe_stoi(name);; if (!maybe_index) { LOG_DEBUG("cannot lookup an array element with \"{1}\": expected an integral value.", name); return nullptr; } int index = maybe_index.get(); if (index < 0) { LOG_DEBUG("cannot lookup an array element with \"{1}\": expected a non-negative value.", name); return nullptr; } if (array->empty()) { LOG_DEBUG("cannot lookup an array element with \"{1}\": the array is empty.", name); return nullptr; } if (static_cast(index) >= array->size()) { LOG_DEBUG("cannot lookup an array element with \"{1}\": expected an integral value between 0 and {2} (inclusive).", name, array->size() - 1); return nullptr; } return (*array)[index]; } void collection::write_hash(ostream& stream, set const& queries, bool show_legacy, bool strict_errors) { // If there's only one query, print the result without the name if (queries.size() == 1u) { auto value = query_value(*queries.begin(), strict_errors); if (value) { value->write(stream, false); } return; } bool first = true; auto writer = ([&](string const& key, value const* val) { // Ignore facts with hidden values if (!show_legacy && queries.empty() && val && val->hidden()) { return; } if (first) { first = false; } else { stream << '\n'; } stream << key << " => "; if (val) { val->write(stream, false); } }); if (!queries.empty()) { // Print queried facts vector> facts; for (auto const& query : queries) { facts.push_back(make_pair(query, this->query_value(query, strict_errors))); } for (auto const& kvp : facts) { writer(kvp.first, kvp.second); } } else { // Print all facts in the map for (auto const& kvp : _facts) { writer(kvp.first, kvp.second.get()); } } } void collection::write_json(ostream& stream, set const& queries, bool show_legacy, bool strict_errors) { json_document document; document.SetObject(); auto builder = ([&](string const& key, value const* val) { // Ignore facts with hidden values if (!show_legacy && queries.empty() && val && val->hidden()) { return; } json_value value; if (val) { val->to_json(document.GetAllocator(), value); } else { value.SetString("", 0); } document.AddMember(StringRef(key.c_str(), key.size()), value, document.GetAllocator()); }); if (!queries.empty()) { for (auto const& query : queries) { builder(query, this->query_value(query, strict_errors)); } } else { for (auto const& kvp : _facts) { builder(kvp.first, kvp.second.get()); } } stream_adapter adapter(stream); PrettyWriter writer(adapter); writer.SetIndent(' ', 2); document.Accept(writer); } void collection::write_yaml(ostream& stream, set const& queries, bool show_legacy, bool strict_errors) { Emitter emitter(stream); emitter << BeginMap; auto writer = ([&](string const& key, value const* val) { // Ignore facts with hidden values if (!show_legacy && queries.empty() && val && val->hidden()) { return; } emitter << Key; if (needs_quotation(key)) { emitter << DoubleQuoted; } emitter << key << YAML::Value; if (val) { val->write(emitter); } else { emitter << DoubleQuoted << ""; } }); if (!queries.empty()) { vector> facts; for (auto const& query : queries) { facts.push_back(make_pair(query, this->query_value(query, strict_errors))); } for (auto const& kvp : facts) { writer(kvp.first, kvp.second); } } else { for (auto const& kvp : _facts) { writer(kvp.first, kvp.second.get()); } } emitter << EndMap; } void collection::add_common_facts(bool include_ruby_facts) { add("facterversion", make_value(LIBFACTER_VERSION)); #ifdef AIO_AGENT_VERSION add("aio_agent_version", make_value(AIO_AGENT_VERSION)); #endif if (include_ruby_facts) { add(make_shared()); } add(make_shared()); add(make_shared()); add(make_shared()); add(make_shared()); #ifdef USE_WHEREAMI add(make_shared()); #endif } }} // namespace facter::facts facter-3.14.12/lib/src/facts/external/0000755005276200011600000000000013702047635017304 5ustar jenkinsjenkinsfacter-3.14.12/lib/src/facts/external/execution_resolver.cc0000644005276200011600000000612513702047406023537 0ustar jenkinsjenkins#include #include #include #include #include #include #include #include #include #include using namespace std; using namespace leatherman::execution; using namespace facter::facts; using namespace facter::facts::external; using namespace facter::util::yaml; namespace facter { namespace facts { namespace external { void execution_resolver::resolve(collection& facts) { LOG_DEBUG("resolving facts from executable file \"{1}\".", _path); try { bool resolved = false; auto result = execute(_path, 0, { execution_options::trim_output, execution_options::merge_environment, execution_options::throw_on_failure, execution_options::convert_newlines }); try { auto node = YAML::Load(result.output); for (auto const& kvp : node) { add_value(kvp.first.as(), kvp.second, facts, _names); // If YAML doesn't correctly parse, it will // sometimes just return an empty node instead of // erroring. Only claiming we've resolved if we // add at least one child value from the YAML // allows us to still pass on to the keyval // interpretation in those cases. resolved = true; } } catch (YAML::Exception& ex) { LOG_DEBUG("Could not parse executable fact output as YAML or JSON ({1})", ex.msg); } if (!resolved) { std::vector lines; boost::split(lines, result.output, boost::is_any_of("\n")); for (const auto& line : lines) { auto pos = line.find('='); if (pos == string::npos) { LOG_DEBUG("ignoring line in output: {1}", line); continue; } // Add as a string fact string fact = line.substr(0, pos); boost::to_lower(fact); _names.push_back(fact); facts.add_external(move(fact), make_value(line.substr(pos+1))); } } // Log a warning if there is error output from the command if (!result.error.empty()) { LOG_WARNING("external fact file \"{1}\" had output on stderr: {2}", _path, result.error); } } catch (execution_exception& ex) { throw external_fact_exception(ex.what()); } LOG_DEBUG("completed resolving facts from executable file \"{1}\".", _path); } }}} // namespace facter::facts::external facter-3.14.12/lib/src/facts/external/json_resolver.cc0000644005276200011600000001411413702047406022502 0ustar jenkinsjenkins#include #include #include #include #include #include #include #include #include #include #include #include #include #include // Mark string for translation (alias for leatherman::locale::format) using leatherman::locale::_; using namespace std; using namespace facter::facts; using namespace facter::util; using namespace rapidjson; namespace facter { namespace facts { namespace external { // Helper event handler for parsing JSON data struct json_event_handler { explicit json_event_handler(collection& facts, vector& names) : _initialized(false), _facts(facts), _names(names) { } bool Null() { check_initialized(); // Ignore this fact as values cannot be null _key.clear(); return true; } bool Bool(bool b) { add_value(make_value(b)); return true; } bool Int(int i) { Int64(static_cast(i)); return true; } bool Uint(unsigned int i) { Int64(static_cast(i)); return true; } bool Int64(int64_t i) { add_value(make_value(i)); return true; } bool Uint64(uint64_t i) { Int64(static_cast(i)); return true; } bool Double(double d) { add_value(make_value(d)); return true; } bool String(char const* str, SizeType length, bool copy) { add_value(make_value(string(str, length))); return true; } bool Key(const char* str, SizeType length, bool copy) { check_initialized(); _key = string(str, length); return true; } bool StartObject() { if (!_initialized) { _initialized = true; return true; } // Push a map onto the stack _stack.emplace(make_tuple(move(_key), make_value())); return true; } bool EndObject(SizeType count) { // Check to see if the stack is empty since we don't push for the top-level object if (_stack.empty()) { return true; } // Pop the data off the stack auto top = move(_stack.top()); _stack.pop(); // Restore the key and add the value _key = move(get<0>(top)); add_value(move(get<1>(top))); return true; } bool StartArray() { check_initialized(); // Push an array onto the stack _stack.emplace(make_tuple(move(_key), make_value())); return true; } bool EndArray(SizeType count) { // Pop the data off the stack auto top = move(_stack.top()); _stack.pop(); // Restore the key and add the value _key = move(get<0>(top)); add_value(move(get<1>(top))); return true; } private: template void add_value(unique_ptr&& val) { check_initialized(); // If the stack is empty, just add it as a top-level fact if (_stack.empty()) { if (_key.empty()) { throw external::external_fact_exception(_("expected non-empty key in object.")); } boost::to_lower(_key); _names.push_back(_key); _facts.add_external(move(_key), move(val)); return; } // If there's an array or map on the stack, add the value as an element auto& top = _stack.top(); auto& current = get<1>(top); auto array = dynamic_cast(current.get()); if (array) { array->add(move(val)); return; } auto map = dynamic_cast(current.get()); if (map) { if (_key.empty()) { throw external::external_fact_exception(_("expected non-empty key in object.")); } map->add(move(_key), move(val)); } } void check_initialized() const { if (!_initialized) { throw external::external_fact_exception(_("expected document to contain an object.")); } } bool _initialized; collection& _facts; vector& _names; string _key; stack>> _stack; }; void json_resolver::resolve(collection& facts) { LOG_DEBUG("resolving facts from JSON file \"{1}\".", _path); // Open the file // We used a scoped_file here because rapidjson expects a FILE* scoped_file file(_path, "r"); if (file == nullptr) { throw external_fact_exception(_("file could not be opened.")); } // Use the existing FileStream class char buffer[4096]; FileReadStream stream(file, buffer, sizeof(buffer)); // Parse the file and report any errors Reader reader; json_event_handler handler(facts, _names); auto result = reader.Parse(stream, handler); if (!result) { throw external_fact_exception(GetParseError_En(result.Code())); } LOG_DEBUG("completed resolving facts from JSON file \"{1}\".", _path); } }}} // namespace facter::facts::external facter-3.14.12/lib/src/facts/external/resolver.cc0000644005276200011600000000137013702047406021451 0ustar jenkinsjenkins#include #include using namespace std; namespace facter { namespace facts { namespace external { external_fact_exception::external_fact_exception(string const& message) : runtime_error(message) { } external_fact_no_resolver::external_fact_no_resolver(std::string const& message) : runtime_error(message) { } resolver::resolver(std::string const &path):_path(path) { boost::filesystem::path p(path); _name =p.filename().string(); } string const& resolver::name() const { return _name; } vector const& resolver::names() const { return _names; } }}} // namespace facter::facts::external facter-3.14.12/lib/src/facts/external/text_resolver.cc0000644005276200011600000000257213702047406022522 0ustar jenkinsjenkins#include #include #include #include #include #include #include // Mark string for translation (alias for leatherman::locale::format) using leatherman::locale::_; using namespace std; namespace lth_file = leatherman::file_util; namespace facter { namespace facts { namespace external { void text_resolver::resolve(collection& facts) { LOG_DEBUG("resolving facts from text file \"{1}\".", _path); if (!lth_file::each_line(_path, [&facts, this](string& line) { auto pos = line.find('='); if (pos == string::npos) { LOG_DEBUG("ignoring line in output: {1}", line); return true; } // Add as a string fact string fact = line.substr(0, pos); boost::to_lower(fact); _names.push_back(fact); facts.add_external(move(fact), make_value(line.substr(pos+1))); return true; })) { throw external_fact_exception(_("file could not be opened.")); } LOG_DEBUG("completed resolving facts from text file \"{1}\".", _path); } }}} // namespace facter::facts::external facter-3.14.12/lib/src/facts/external/windows/0000755005276200011600000000000013702047635020776 5ustar jenkinsjenkinsfacter-3.14.12/lib/src/facts/external/windows/powershell_resolver.cc0000644005276200011600000001062313702047406025410 0ustar jenkinsjenkins#include #include #include #include #include #include #include #include #include #include using namespace std; using namespace boost::filesystem; using namespace facter::util::yaml; using namespace leatherman::execution; namespace facter { namespace facts { namespace external { void powershell_resolver::resolve(collection& facts) { LOG_DEBUG("resolving facts from powershell script \"{1}\".", _path); try { bool resolved = false; string pwrshell = "powershell"; // When facter is a 32-bit process running on 64-bit windows (such as in a 32-bit puppet installation that // includes native facter), PATH-lookp finds the 32-bit powershell and leads to problems. For example, if // using powershell to read values from the registry, it will read the 32-bit view of the registry. Also 32 // and 64-bit versions have different modules available (since PSModulePath is in system32). Use the // system32 fact to find the correct powershell executable. auto system32 = facts.get(fact::windows_system32); if (system32) { auto pathNative = path(system32->value()) / "WindowsPowerShell" / "v1.0" / "powershell.exe"; auto pwrshellNative = which(pathNative.string()); if (!pwrshellNative.empty()) { pwrshell = move(pwrshellNative); } } auto const pwrshell_opts = vector { "-NoProfile", "-NonInteractive", "-NoLogo", "-ExecutionPolicy", "Bypass", "-File", _path }; auto result = execute(pwrshell, pwrshell_opts, 0, { execution_options::trim_output, execution_options::merge_environment, execution_options::throw_on_failure }); try { auto node = YAML::Load(result.output); for (auto const& kvp : node) { string key = kvp.first.as(); boost::to_lower(key); add_value(key, kvp.second, facts, _names); // If YAML doesn't correctly parse, it will // sometimes just return an empty node instead of // erroring. Only claiming we've resolved if we // add at least one child value from the YAML // allows us to still pass on to the key=val // interpretation in those cases. resolved = true; } } catch (YAML::Exception& ex) { LOG_DEBUG("Could not parse executable fact output as YAML or JSON ({1})", ex.msg); } if (!resolved) { // YAML/JSON parse not successful; Look for key=value pairs leatherman::util::each_line(result.output, [&facts, this](string const& line) { auto pos = line.find('='); if (pos == string::npos) { LOG_DEBUG("ignoring line in output: {1}", line); return true; } // Add as a string fact string fact = line.substr(0, pos); boost::to_lower(fact); string value = line.substr(pos + 1); _names.push_back(fact); facts.add_external(move(fact), make_value(move(value))); return true; }); } // Log a warning if the script had any error output if (!result.error.empty()) { LOG_WARNING("external fact file \"{1}\" had output on stderr: {2}", _path, result.error); } } catch (execution_exception& ex) { throw external_fact_exception(ex.what()); } LOG_DEBUG("completed resolving facts from powershell script \"{1}\".", _path); } }}} // namespace facter::facts::external facter-3.14.12/lib/src/facts/external/yaml_resolver.cc0000644005276200011600000000234513702047406022476 0ustar jenkinsjenkins#include #include #include #include #include #include #include #include // Mark string for translation (alias for leatherman::locale::format) using leatherman::locale::_; using namespace std; using namespace YAML; using namespace facter::util::yaml; namespace facter { namespace facts { namespace external { void yaml_resolver::resolve(collection& facts) { LOG_DEBUG("resolving facts from YAML file \"{1}\".", _path); boost::nowide::ifstream stream(_path.c_str()); if (!stream) { throw external_fact_exception(_("file could not be opened.")); } try { Node node = YAML::Load(stream); for (auto const& kvp : node) { add_value(kvp.first.as(), kvp.second, facts, _names); } } catch (Exception& ex) { throw external_fact_exception(ex.msg); } LOG_DEBUG("completed resolving facts from YAML file \"{1}\".", _path); } }}} // namespace facter::facts::external facter-3.14.12/lib/src/facts/external_resolvers_factory.cc0000644005276200011600000000312113702047406023437 0ustar jenkinsjenkins#include #include #include #include #include #include #include using namespace std; namespace facter { namespace facts { bool external_resolvers_factory::text_resolver_can_resolve(string const &path) { return boost::iends_with(path, ".txt"); } bool external_resolvers_factory::json_resolver_can_resolve(string const &path) { return boost::iends_with(path, ".json"); } bool external_resolvers_factory::yaml_resolver_can_resolve(string const &path) { return boost::iends_with(path, ".yaml"); } bool external_resolvers_factory::execution_resolver_can_resolve(string const &path) { return !leatherman::execution::which(path, {}).empty(); } shared_ptr external_resolvers_factory::get_common_resolver(const string& path) { if (text_resolver_can_resolve(path)) { return make_shared(path); } if (json_resolver_can_resolve(path)) { return make_shared(path); } if (yaml_resolver_can_resolve(path)) { return make_shared(path); } if (execution_resolver_can_resolve(path)) { return make_shared(path); } return NULL; } }} // namespace facter::facts facter-3.14.12/lib/src/facts/freebsd/0000755005276200011600000000000013702047635017074 5ustar jenkinsjenkinsfacter-3.14.12/lib/src/facts/freebsd/collection.cc0000644005276200011600000000360513702047406021536 0ustar jenkinsjenkins#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include using namespace std; namespace facter { namespace facts { void collection::add_platform_facts() { add(make_shared()); add(make_shared()); add(make_shared()); add(make_shared()); add(make_shared()); add(make_shared()); add(make_shared()); add(make_shared()); add(make_shared()); add(make_shared()); add(make_shared()); add(make_shared()); add(make_shared()); add(make_shared()); add(make_shared()); add(make_shared()); } }} // namespace facter::facts facter-3.14.12/lib/src/facts/freebsd/disk_resolver.cc0000644005276200011600000000177313702047406022262 0ustar jenkinsjenkins#include #include #include #include using namespace std; namespace facter { namespace facts { namespace freebsd { disk_resolver::data disk_resolver::collect_data(collection& facts) { data result; try { facter::util::freebsd::geom_class disks("DISK"); for (auto& geom : disks.geoms) { for (auto& provider : geom.providers) { disk d; d.name = provider.name(); d.size = provider.mediasize(); d.model = provider.config("descr"); d.serial_number = provider.config("ident"); result.disks.push_back(move(d)); } } } catch (util::freebsd::geom_exception const &e) { LOG_ERROR(e.what()); } return result; } }}} // namespace facter::facts::freebsd facter-3.14.12/lib/src/facts/freebsd/dmi_resolver.cc0000644005276200011600000000262613702047406022077 0ustar jenkinsjenkins#include #include #include using namespace std; namespace facter { namespace facts { namespace freebsd { dmi_resolver::data dmi_resolver::collect_data(collection& facts) { data result; result.bios_vendor = kenv_lookup("smbios.bios.vendor"); result.bios_version = kenv_lookup("smbios.bios.version"); result.bios_release_date = kenv_lookup("smbios.bios.reldate"); result.uuid = kenv_lookup("smbios.system.uuid"); result.serial_number = kenv_lookup("smbios.system.serial"); result.product_name = kenv_lookup("smbios.system.product"); if (result.product_name.length() == 0) { result.product_name = result.bios_vendor; } result.manufacturer = kenv_lookup("smbios.system.maker"); // Fix for Proxmox VMs if (result.manufacturer == "QEMU") { result.product_name = "KVM"; } return result; } string dmi_resolver::kenv_lookup(const char* file) { char buffer[100] = {}; LOG_DEBUG("kenv lookup for {1}", file); if (kenv(KENV_GET, file, buffer, sizeof(buffer) - 1) == -1) { LOG_INFO("kenv lookup for {1} failed: {2} ({3})", file, strerror(errno), errno); return ""; } return buffer; } } } } // namespace facter::facts::freebsd facter-3.14.12/lib/src/facts/freebsd/filesystem_resolver.cc0000644005276200011600000000225413702047406023507 0ustar jenkinsjenkins#include #include #include #include using namespace std; namespace facter { namespace facts { namespace freebsd { filesystem_resolver::data filesystem_resolver::collect_data(collection& facts) { data result = bsd::filesystem_resolver::collect_data(facts); try { facter::util::freebsd::geom_class disks("PART"); for (auto& geom : disks.geoms) { for (auto& provider : geom.providers) { partition p; p.name = provider.name(); p.size = provider.mediasize(); if (geom.config("scheme") == "GPT") { p.partition_label = provider.config("label"); p.partition_uuid = provider.config("rawuuid"); } result.partitions.push_back(move(p)); } } } catch (util::freebsd::geom_exception const& e) { LOG_ERROR(e.what()); } return result; } }}} // namespace facter::facts::freebsd facter-3.14.12/lib/src/facts/freebsd/memory_resolver.cc0000644005276200011600000000440613702047406022634 0ustar jenkinsjenkins#include #include #include #include #include #include #include #include using namespace std; using namespace leatherman::execution; namespace facter { namespace facts { namespace freebsd { memory_resolver::data memory_resolver::collect_data(collection& facts) { data result; size_t size; int pagesize = getpagesize(); // Memory usage unsigned long physmem; size = sizeof(physmem); if (0 == sysctlbyname("hw.physmem", &physmem, &size, NULL, 0)) { result.mem_total = physmem; } unsigned int inactive_count = 0; size = sizeof(inactive_count); sysctlbyname("vm.stats.vm.v_inactive_count", &inactive_count, &size, NULL, 0); unsigned int cache_count = 0; size = sizeof(cache_count); sysctlbyname("vm.stats.vm.v_cache_count", &cache_count, &size, NULL, 0); unsigned int free_count = 0; size = sizeof(free_count); sysctlbyname("vm.stats.vm.v_free_count", &free_count, &size, NULL, 0); long mem_free_page_count = inactive_count + cache_count + free_count; result.mem_free = mem_free_page_count * pagesize; // Swap usage struct xswdev xsw; size = sizeof(xsw); int mib[16]; size_t mibsize; mibsize = sizeof mib / sizeof mib[0]; if (sysctlnametomib("vm.swap_info", mib, &mibsize) == -1) { LOG_DEBUG("sysctlnametomib() failed"); } else { for (int n = 0; ; ++n) { mib[mibsize] = n; if (-1 == sysctl(mib, mibsize + 1, &xsw, &size, NULL, 0)) break; if (xsw.xsw_version != XSWDEV_VERSION) { LOG_DEBUG("xswdev version mismatch"); } else { result.swap_total += xsw.xsw_nblks; result.swap_free += xsw.xsw_nblks - xsw.xsw_used; } } result.swap_free *= pagesize; result.swap_total *= pagesize; } return result; } }}} // namespace facter::facts::freebsd facter-3.14.12/lib/src/facts/freebsd/networking_resolver.cc0000644005276200011600000000422713702047406023514 0ustar jenkinsjenkins#include #include #include #include #include #include #include #include #include #include using namespace std; using namespace facter::util; using namespace facter::util::bsd; using namespace leatherman::execution; namespace facter { namespace facts { namespace freebsd { bool networking_resolver::is_link_address(sockaddr const* addr) const { return addr && addr->sa_family == AF_LINK; } uint8_t const* networking_resolver::get_link_address_bytes(sockaddr const* addr) const { if (!is_link_address(addr)) { return nullptr; } sockaddr_dl const* link_addr = reinterpret_cast(addr); if (link_addr->sdl_alen != 6 && link_addr->sdl_alen != 20) { return nullptr; } return reinterpret_cast(LLADDR(link_addr)); } uint8_t networking_resolver::get_link_address_length(sockaddr const* addr) const { if (!is_link_address(addr)) { return 0; } sockaddr_dl const* link_addr = reinterpret_cast(addr); return link_addr->sdl_alen; } boost::optional networking_resolver::get_link_mtu(string const& interface, void* data) const { ifreq ifr; memset(&ifr, 0, sizeof(ifr)); strncpy(ifr.ifr_name, interface.c_str(), sizeof(ifr.ifr_name)); int s = socket(AF_INET, SOCK_DGRAM, 0); if (s < 0) { LOG_WARNING("socket failed: {1} ({2}): interface MTU fact is unavailable for interface {3}.", strerror(errno), errno, interface); return boost::none; } if (ioctl(s, SIOCGIFMTU, &ifr) == -1) { LOG_WARNING("ioctl failed: {1} ({2}): interface MTU fact is unavailable for interface {3}.", strerror(errno), errno, interface); return boost::none; } return ifr.ifr_mtu; } }}} // namespace facter::facts::freebsd facter-3.14.12/lib/src/facts/freebsd/operating_system_resolver.cc0000644005276200011600000000200413702047406024710 0ustar jenkinsjenkins#include #include #include using namespace std; using namespace leatherman::execution; using namespace leatherman::util; namespace facter { namespace facts { namespace freebsd { void operating_system_resolver::collect_release_data(collection& facts, data& result) { auto exec = execute("freebsd-version"); if (exec.success) { result.release = exec.output; string major, minor, branch; re_search(exec.output, boost::regex("(\\d+)\\.(\\d+)-(.*)"), &major, &minor, &branch); result.major = move(major); result.minor = move(minor); result.freebsd.branch = move(branch); string patchlevel; re_search(result.freebsd.branch, boost::regex("RELEASE-p(\\d+)"), &patchlevel); result.freebsd.patchlevel = move(patchlevel); } } } } } // namespace facter::facts::freebsd facter-3.14.12/lib/src/facts/freebsd/processor_resolver.cc0000644005276200011600000000431013702047406023335 0ustar jenkinsjenkins#include #include #include #include using namespace std; namespace facter { namespace facts { namespace freebsd { processor_resolver::data processor_resolver::collect_data(collection& facts) { auto result = posix::processor_resolver::collect_data(facts); size_t len; int mib[2]; mib[0] = CTL_HW; // Get the logical count of processors len = sizeof(result.logical_count); mib[1] = HW_NCPU; if (sysctl(mib, 2, &result.logical_count, &len, nullptr, 0) == -1) { LOG_DEBUG("sysctl hw.ncpu failed: {1} ({2}): logical processor count is unavailable.", strerror(errno), errno); } // For each logical processor, collect the model name if (result.logical_count > 0) { // Note: we're using the same description string for all logical processors: // using different CPUs is not even likely to work. vector buffer(256); while (true) { size_t size = buffer.size(); mib[1] = HW_MODEL; if (sysctl(mib, 2, buffer.data(), &size, nullptr, 0) == 0) { buffer.resize(size + 1); result.models.resize(result.logical_count, buffer.data()); break; } if (errno != ENOMEM) { LOG_DEBUG("sysctl hw.model failed: {1} ({2}): processor models are unavailable.", strerror(errno), errno); break; } buffer.resize(buffer.size() * 2); } } // Set the speed len = sizeof(result.speed); int cmd[2]; size_t two = 2; sysctlnametomib("hw.clockrate", cmd, &two); if (sysctl(cmd, 2, &result.speed, &len, nullptr, 0) == -1) { LOG_DEBUG("sysctl hw.cpuspeed failed: {1} ({2}): processor speed is unavailable.", strerror(errno), errno); } // Scale the speed to something resolve() can correctly map result.speed *= 1000 * 1000; return result; } }}} // namespace facter::facts::freebsd facter-3.14.12/lib/src/facts/freebsd/virtualization_resolver.cc0000644005276200011600000000202613702047406024404 0ustar jenkinsjenkins#include #include #include #include #include #include #include #include #include using namespace std; using namespace facter::facts; using namespace leatherman::execution; namespace facter { namespace facts { namespace freebsd { string virtualization_resolver::get_hypervisor(collection& facts) { string value = get_jail_vm(); if (value.empty()) { value = get_fact_vm(facts); } return value; } string virtualization_resolver::get_jail_vm() { int jailed; size_t size = sizeof(jailed); if (sysctlbyname("security.jail.jailed", &jailed, &size, NULL, 0) == 0) { if (jailed) return vm::jail; } return {}; } } } } // namespace facter::facts::freebsd facter-3.14.12/lib/src/facts/freebsd/zfs_resolver.cc0000644005276200011600000000037513702047406022127 0ustar jenkinsjenkins#include using namespace std; namespace facter { namespace facts { namespace freebsd { string zfs_resolver::zfs_command() { return "/sbin/zfs"; } }}} // namespace facter::facts::freebsd facter-3.14.12/lib/src/facts/freebsd/zpool_resolver.cc0000644005276200011600000000040513702047406022462 0ustar jenkinsjenkins#include using namespace std; namespace facter { namespace facts { namespace freebsd { string zpool_resolver::zpool_command() { return "/sbin/zpool"; } }}} // namespace facter::facts::freebsd facter-3.14.12/lib/src/facts/glib/0000755005276200011600000000000013702047635016377 5ustar jenkinsjenkinsfacter-3.14.12/lib/src/facts/glib/load_average_resolver.cc0000644005276200011600000000126313702047406023236 0ustar jenkinsjenkins#include #include #include #ifdef __sun #include #endif using namespace std; namespace facter { namespace facts { namespace glib { boost::optional > load_average_resolver::get_load_averages() { array averages; if (getloadavg(averages.data(), averages.size()) == -1) { LOG_DEBUG("failed to retrieve load averages: {1} ({2}).", strerror(errno), errno); return boost::none; } return make_tuple(averages[0], averages[1], averages[2]); } }}} // namespace facter::facts::glib facter-3.14.12/lib/src/facts/linux/0000755005276200011600000000000013702047635016621 5ustar jenkinsjenkinsfacter-3.14.12/lib/src/facts/linux/collection.cc0000644005276200011600000000354013702047406021261 0ustar jenkinsjenkins#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include using namespace std; namespace facter { namespace facts { void collection::add_platform_facts() { add(make_shared()); add(make_shared()); add(make_shared()); add(make_shared()); add(make_shared()); add(make_shared()); add(make_shared()); add(make_shared()); add(make_shared()); add(make_shared()); add(make_shared()); add(make_shared()); add(make_shared()); add(make_shared()); add(make_shared()); add(make_shared()); } }} // namespace facter::facts facter-3.14.12/lib/src/facts/linux/disk_resolver.cc0000644005276200011600000000661613702047406022010 0ustar jenkinsjenkins#include #include #include #include #include #include #include #ifdef USE_UDEV #include #endif // USE_UDEV using namespace std; using namespace boost::filesystem; using boost::lexical_cast; using boost::bad_lexical_cast; namespace lth_file = leatherman::file_util; namespace facter { namespace facts { namespace linux { disk_resolver::data disk_resolver::collect_data(collection& facts) { static string root_directory = "/sys/block"; // The size of the block devices is in 512 byte blocks const int block_size = 512; data result; boost::system::error_code ec; if (!is_directory(root_directory, ec)) { LOG_DEBUG("{1}: {2}: disk facts are unavailable.", root_directory, ec.message()); return result; } #ifdef USE_UDEV struct udev *udev; udev = udev_new(); #endif // USE_UDEV lth_file::each_subdirectory(root_directory, [&](string const& dir) { path device_directory(dir); disk d; d.name = device_directory.filename().string(); // Check for the device subdirectory's existence path device_subdirectory = device_directory / "device"; boost::system::error_code ec; if (!is_directory(device_subdirectory, ec)) { return true; } string size_file_path = (device_directory / "size").string(); string vendor_file_path = (device_subdirectory / "vendor").string(); string model_file_path = (device_subdirectory / "model").string(); // Read the size of the block device // The size is in 512 byte blocks if (is_regular_file(size_file_path, ec)) { try { string blocks = lth_file::read(size_file_path); boost::trim(blocks); d.size = lexical_cast(blocks) * block_size; } catch (bad_lexical_cast& ex) { LOG_DEBUG("size of disk {1} is invalid: size information is unavailable.", d.name); } } // Read the vendor fact if (is_regular_file(vendor_file_path, ec)) { d.vendor = lth_file::read(vendor_file_path); boost::trim(d.vendor); } // Read the model fact if (is_regular_file(model_file_path, ec)) { d.model = lth_file::read(model_file_path); boost::trim(d.model); } #ifdef USE_UDEV auto dev = udev_device_new_from_subsystem_sysname(udev, "block", d.name.c_str()); if (dev) { const char *serial; serial = udev_device_get_property_value(dev, "ID_SCSI_SERIAL"); if (!serial) serial = udev_device_get_property_value(dev, "ID_SERIAL_SHORT"); if (serial) d.serial_number = serial; } #endif // USE_UDEV result.disks.emplace_back(move(d)); return true; }); #ifdef USE_UDEV udev_unref(udev); #endif // USE_UDEV return result; } }}} // namespace facter::facts::linux facter-3.14.12/lib/src/facts/linux/dmi_resolver.cc0000644005276200011600000001627313702047406021627 0ustar jenkinsjenkins#include #include #include #include #include #include #include #include #include #include #include using namespace std; using namespace boost::filesystem; namespace bs = boost::system; namespace lth_file = leatherman::file_util; using namespace facter::util; using namespace leatherman::util; namespace facter { namespace facts { namespace linux { dmi_resolver::data dmi_resolver::collect_data(collection& facts) { data result; // Check that /sys/class/dmi exists (requires kernel 2.6.23+) bs::error_code ec; if (exists("/sys/class/dmi/", ec)) { result.bios_vendor = read("/sys/class/dmi/id/bios_vendor"); result.bios_version = read("/sys/class/dmi/id/bios_version"); result.bios_release_date = read("/sys/class/dmi/id/bios_date"); result.board_asset_tag = read("/sys/class/dmi/id/board_asset_tag"); result.board_manufacturer = read("/sys/class/dmi/id/board_vendor"); result.board_product_name = read("/sys/class/dmi/id/board_name"); result.board_serial_number = read("/sys/class/dmi/id/board_serial"); result.chassis_asset_tag = read("/sys/class/dmi/id/chassis_asset_tag"); result.manufacturer = read("/sys/class/dmi/id/sys_vendor"); result.product_name = read("/sys/class/dmi/id/product_name"); result.serial_number = read("/sys/class/dmi/id/product_serial"); result.uuid = read("/sys/class/dmi/id/product_uuid"); result.chassis_type = to_chassis_description(read("/sys/class/dmi/id/chassis_type")); } else { // dmidecode does not work on power machines, so if we're on one, then there's no need // to proceed any further auto isa = facts.get(fact::hardware_isa); if (isa && boost::starts_with(isa->value(), "ppc64")) { return result; } LOG_DEBUG("/sys/class/dmi cannot be accessed: using dmidecode to query DMI information."); int dmi_type = -1; string dmidecode = agent::which("dmidecode"); leatherman::execution::each_line(dmidecode, [&](string& line) { parse_dmidecode_output(result, line, dmi_type); return true; }); } return result; } void dmi_resolver::parse_dmidecode_output(data& result, string& line, int& dmi_type) { static const boost::regex dmi_section_pattern("^Handle 0x.{4}, DMI type (\\d{1,3})"); // Stores the relevant sections; this is in order based on DMI type ID // Ensure there's a trailing semicolon on each entry and keep in sync with the switch statement below static const vector> sections = { { // BIOS (0) "vendor:", "version:", "release date:", }, { // System (1) "manufacturer:", "product:", "product name:", "serial number:", "uuid:", }, { // Base Board (2) "manufacturer:", "product:", "product name:", "serial number:", "asset tag:", }, { // Chassis (3) "type:", "chassis type:", "asset tag:", } }; // Check for a section header if (re_search(line, dmi_section_pattern, &dmi_type)) { return; } // Check that we're in a relevant section if (dmi_type < 0 || static_cast(dmi_type) >= sections.size()) { return; } // Trim leading whitespace boost::trim_left(line); // Find a matching header auto const& headers = sections[dmi_type]; auto it = find_if(headers.begin(), headers.end(), [&](string const& header) { return boost::istarts_with(line, header); }); if (it == headers.end()) { return; } // Get the value and trim it string value = line.substr(it->size()); boost::trim(value); // Calculate the index into the header vector size_t index = it - headers.begin(); // Assign to the appropriate member string* member = nullptr; switch (dmi_type) { case 0: { // BIOS information if (index == 0) { member = &result.bios_vendor; } else if (index == 1) { member = &result.bios_version; } else if (index == 2) { member = &result.bios_release_date; } break; } case 1: { // System information if (index == 0) { member = &result.manufacturer; } else if (index == 1 || index == 2) { member = &result.product_name; } else if (index == 3) { member = &result.serial_number; } else if (index == 4) { member = &result.uuid; } break; } case 2: { // Base board information if (index == 0) { member = &result.board_manufacturer; } else if (index == 1 || index == 2) { member = &result.board_product_name; } else if (index == 3) { member = &result.board_serial_number; } else if (index == 4) { member = &result.board_asset_tag; } break; } case 3: { // Chassis information if (index == 0 || index == 1) { member = &result.chassis_type; } else if (index == 2) { member = &result.chassis_asset_tag; } break; } default: break; } if (member) { *member = std::move(value); } } string dmi_resolver::read(std::string const& path) { bs::error_code ec; if (!is_regular_file(path, ec)) { LOG_DEBUG("{1}: {2}.", path, ec.message()); return {}; } string value; if (!lth_file::read(path, value)) { LOG_DEBUG("{1}: file could not be read.", path); return {}; } boost::trim(value); // Replace any non-printable ASCII characters with '.' // This mimics the behavior of dmidecode for (auto& c : value) { if (c < 32 || c == 127) { c = '.'; } } return value; } }}} // namespace facter::facts::linux facter-3.14.12/lib/src/facts/linux/filesystem_resolver.cc0000644005276200011600000002645713702047406023247 0ustar jenkinsjenkins#include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef USE_BLKID #include #endif // USE_BLKID using namespace std; using namespace facter::facts; using namespace facter::util; using namespace boost::filesystem; namespace sys = boost::system; namespace lth_file = leatherman::file_util; using namespace leatherman::util; using boost::lexical_cast; using boost::bad_lexical_cast; namespace facter { namespace facts { namespace linux { string filesystem_resolver::safe_convert(char const* value) { string result; if (value) { while (*value) { unsigned char c = static_cast(*value); if (c >= 128) { result += "M-"; c -= 128; } if (c < 32 || c == 0xf7) { result += '^'; c ^= 0x40; } else if (c == '"' || c == '\\') { result += '\\'; } result += static_cast(c); ++value; } } return result; } filesystem_resolver::data filesystem_resolver::collect_data(collection& facts) { data result; collect_mountpoint_data(result); collect_filesystem_data(result); collect_partition_data(result); return result; } void filesystem_resolver::collect_mountpoint_data(data& result) { // Populate the mountpoint data scoped_file file(setmntent("/etc/mtab", "r")); if (!static_cast(file)) { LOG_ERROR("setmntent failed: {1} ({2}): mountpoints are unavailable.", strerror(errno), errno); return; } string root_device; mntent entry; char buffer[4096]; map mountpoints_map; while (mntent *ptr = getmntent_r(file, &entry, buffer, sizeof(buffer))) { string device = ptr->mnt_fsname; string mtype = ptr->mnt_type; // Skip over any non-tmpfs mount under /proc or /sys if (mtype != "tmpfs" && (boost::starts_with(ptr->mnt_dir, "/proc") || boost::starts_with(ptr->mnt_dir, "/sys"))) { continue; } // Skip over automounts if (mtype == "autofs") { continue; } // If the "root" device, lookup the actual device from the kernel options // This is done because not all systems symlink /dev/root if (device == "/dev/root") { if (root_device.empty()) { boost::regex root_pattern("root=([^\\s]+)"); lth_file::each_line("/proc/cmdline", [&](string& line) { if (re_search(line, root_pattern, &root_device)) { return false; } return true; }); } if (!root_device.empty()) { device = root_device; } } mountpoint point; point.name = ptr->mnt_dir; point.device = std::move(device); point.filesystem = ptr->mnt_type; boost::split(point.options, ptr->mnt_opts, boost::is_any_of(","), boost::token_compress_on); struct statfs stats; if (statfs(ptr->mnt_dir, &stats) != -1) { point.size = (static_cast(stats.f_frsize) * static_cast(stats.f_blocks)); point.available = (static_cast(stats.f_frsize) * static_cast(stats.f_bavail)); point.free = (static_cast(stats.f_frsize) * static_cast(stats.f_bfree)); } auto iterator = mountpoints_map.find(point.name); if (iterator != mountpoints_map.end()){ if (boost::starts_with(point.device, "/dev/") || point.filesystem == "tmpfs") iterator->second = point; } else { mountpoints_map[point.name] = point; } } result.mountpoints.reserve(mountpoints_map.size()); for_each(mountpoints_map.begin(), mountpoints_map.end(), [&](const map::value_type& p) { result.mountpoints.emplace_back(p.second); }); } void filesystem_resolver::collect_filesystem_data(data& result) { // Populate the partition data lth_file::each_line("/proc/filesystems", [&](string &line) { boost::trim(line); // Ignore lines without devices or fuseblk if (boost::starts_with(line, "nodev") || line == "fuseblk") { return true; } result.filesystems.emplace(move(line)); return true; }); } void filesystem_resolver::collect_partition_data(data& result) { // Populate a map of device -> mountpoint map mountpoints; for (auto const& point : result.mountpoints) { mountpoints.insert(make_pair(point.device, point.name)); } void* cache = nullptr; #ifdef USE_BLKID blkid_cache actual = nullptr; if (blkid_get_cache(&actual, "/dev/null") == 0) { // Do a probe since we're not using a cache file if (blkid_probe_all(actual) != 0) { LOG_DEBUG("blkid_probe_all failed: partition attributes are not available."); blkid_put_cache(actual); actual = nullptr; } cache = actual; } else { LOG_DEBUG("blkid_get_cache failed: partition attributes are not available."); } #else LOG_DEBUG("facter was built without libblkid support: partition attributes are not available."); #endif // USE_BLKID lth_file::each_subdirectory("/sys/block", [&](string const& subdirectory) { path block_device_path(subdirectory); auto block_device_filename = block_device_path.filename().string(); // For devices, look up partition subdirectories sys::error_code ec; if (is_directory(block_device_path / "device", ec)) { lth_file::each_subdirectory(subdirectory, [&](string const& subdirectory) { path partition_path(subdirectory); auto partition_name = partition_path.filename().string(); // Ignore any subdirectory that does not start with the device file name if (!boost::starts_with(partition_name, block_device_filename)) { return true; } partition part; part.name = "/dev/" + partition_name; populate_partition_attributes(part, subdirectory, cache, mountpoints); result.partitions.emplace_back(std::move(part)); return true; }); } else if (is_directory(block_device_path / "dm", ec)) { // For mapped devices, lookup the mapping name partition part; string mapping_name = lth_file::read((block_device_path / "dm" / "name").string()); boost::trim(mapping_name); if (mapping_name.empty()) { mapping_name = "/dev/" + block_device_filename; } else { mapping_name = "/dev/mapper/" + mapping_name; } part.name = std::move(mapping_name); populate_partition_attributes(part, block_device_path.string(), cache, mountpoints); result.partitions.emplace_back(std::move(part)); } else if (is_directory(block_device_path / "loop")) { // Lookup the backing file partition part; part.name = "/dev/" + block_device_filename; part.backing_file = lth_file::read((block_device_path / "loop" / "backing_file").string()); boost::trim(part.backing_file); populate_partition_attributes(part, block_device_path.string(), cache, mountpoints); result.partitions.emplace_back(std::move(part)); } return true; }); #ifdef USE_BLKID // Cleanup the blkid cache if there is one if (cache) { blkid_put_cache(static_cast(cache)); cache = nullptr; } #endif // USE_BLKID } void filesystem_resolver::populate_partition_attributes(partition& part, string const& device_directory, void* cache, map const& mountpoints) { #ifdef USE_BLKID if (cache) { auto device = blkid_get_dev(static_cast(cache), part.name.c_str(), 0); if (!device) { LOG_DEBUG("blkid_get_dev failed: partition attributes are unavailable for '{1}'.", part.name); } else { // Populate the attributes auto it = blkid_tag_iterate_begin(device); if (it) { const char* name; const char* value; while (blkid_tag_next(it, &name, &value) == 0) { string* ptr = nullptr; string attribute = name; boost::to_lower(attribute); if (attribute == "type") { ptr = &part.filesystem; } else if (attribute == "label") { ptr = &part.label; } else if (attribute == "partlabel") { ptr = &part.partition_label; } else if (attribute == "uuid") { ptr = &part.uuid; } else if (attribute == "partuuid") { ptr = &part.partition_uuid; } if (!ptr) { continue; } (*ptr) = safe_convert(value); } blkid_tag_iterate_end(it); } } } #endif // USE_BLKID // Lookup the mountpoint auto it = mountpoints.find(part.name); if (it != mountpoints.end()) { part.mount = it->second; } // The size of a block, in bytes const int block_size = 512; // Read the size string blocks = lth_file::read(device_directory + "/size"); boost::trim(blocks); if (!blocks.empty()) { try { part.size = lexical_cast(blocks) * block_size; } catch (bad_lexical_cast& ex) { LOG_DEBUG("cannot determine size of partition '{1}': '{2}' is not an integral value.", part.name, blocks); } } } }}} // namespace facter::facts::linux facter-3.14.12/lib/src/facts/linux/fips_resolver.cc0000644005276200011600000000143313702047406022007 0ustar jenkinsjenkins#include #include #include #include using namespace std; using boost::lexical_cast; using boost::bad_lexical_cast; namespace lth_file = leatherman::file_util; namespace facter { namespace facts { namespace linux { fips_resolver::data fips_resolver::collect_data(collection& facts) { data result; // Set a safe default result.is_fips_mode_enabled = false; lth_file::each_line("/proc/sys/crypto/fips_enabled", [&](string& line) { boost::trim(line); result.is_fips_mode_enabled = line != "0"; return true; }); return result; } }}} // namespace facter::facts::linux facter-3.14.12/lib/src/facts/linux/kernel_resolver.cc0000644005276200011600000000114113702047406022322 0ustar jenkinsjenkins#include #include #include #include using namespace std; using namespace leatherman::util; namespace facter { namespace facts { namespace linux { tuple kernel_resolver::parse_version(string const& version) const { string major, minor; if (re_search(version, boost::regex("(\\d+\\.\\d+)(.*)"), &major, &minor)) { return make_tuple(major, minor); } return make_tuple(move(version), string()); } }}} // namespace facter::facts::resolvers facter-3.14.12/lib/src/facts/linux/memory_resolver.cc0000644005276200011600000000322313702047406022355 0ustar jenkinsjenkins#include #include #include #include using namespace std; using boost::lexical_cast; using boost::bad_lexical_cast; namespace lth_file = leatherman::file_util; namespace facter { namespace facts { namespace linux { memory_resolver::data memory_resolver::collect_data(collection& facts) { data result; lth_file::each_line("/proc/meminfo", [&](string& line) { uint64_t* variable = nullptr; if (boost::starts_with(line, "MemTotal:")) { variable = &result.mem_total; } else if (boost::starts_with(line, "MemFree:") || boost::starts_with(line, "Buffers:") || boost::starts_with(line, "Cached:")) { variable = &result.mem_free; } else if (boost::starts_with(line, "SwapTotal:")) { variable = &result.swap_total; } else if (boost::starts_with(line, "SwapFree:")) { variable = &result.swap_free; } if (!variable) { return true; } vector> parts; boost::split(parts, line, boost::is_space(), boost::token_compress_on); if (parts.size() < 2) { return true; } try { *variable += lexical_cast(parts[1]) * 1024; } catch (bad_lexical_cast&) { } return true; }); return result; } }}} // namespace facter::facts::linux facter-3.14.12/lib/src/facts/linux/networking_resolver.cc0000644005276200011600000002665213702047406023247 0ustar jenkinsjenkins#include #include #include #include #include #include #include #include #include #include #include #include using namespace std; using namespace facter::util::posix; namespace lth_file = leatherman::file_util; namespace lth_exe = leatherman::execution; namespace facter { namespace facts { namespace linux { networking_resolver::data networking_resolver::collect_data(collection& facts) { read_routing_table(); data result = bsd::networking_resolver::collect_data(facts); populate_from_routing_table(result); // On linux, the macaddress of bonded interfaces is reported // as the address of the bonding master. We want to report the // original HW address, so we dig it out of /proc for (auto& interface : result.interfaces) { // For each interface we check if we're part of a bond, // and update the `macaddress` fact if we are auto bond_master = get_bond_master(interface.name); if (!bond_master.empty()) { bool in_our_block = false; lth_file::each_line("/proc/net/bonding/"+bond_master, [&](string& line) { // /proc/net/bonding files are organized into chunks for each slave // interface. We want to grab the mac address for the block we're in. if (line == "Slave Interface: " + interface.name) { in_our_block = true; } else if (line.find("Slave Interface") != string::npos) { in_our_block = false; } // If we're in the block for our iface, we can grab the HW address if (in_our_block && line.find("Permanent HW addr: ") != string::npos) { auto split = line.find(':') + 2; interface.macaddress = line.substr(split, string::npos); return false; } return true; }); } } return result; } bool networking_resolver::is_link_address(sockaddr const* addr) const { return addr && addr->sa_family == AF_PACKET; } uint8_t const* networking_resolver::get_link_address_bytes(sockaddr const* addr) const { if (!is_link_address(addr)) { return nullptr; } sockaddr_ll const* link_addr = reinterpret_cast(addr); if (link_addr->sll_halen != 6 && link_addr->sll_halen != 20) { return nullptr; } return reinterpret_cast(link_addr->sll_addr); } uint8_t networking_resolver::get_link_address_length(sockaddr const* addr) const { if (!is_link_address(addr)) { return 0; } sockaddr_ll const* link_addr = reinterpret_cast(addr); return link_addr->sll_halen; } boost::optional networking_resolver::get_link_mtu(string const& interface, void* data) const { // Unfortunately in Linux, the data points at interface statistics // Nothing useful for us, so we need to use ioctl to query the MTU ifreq req; memset(&req, 0, sizeof(req)); strncpy(req.ifr_name, interface.c_str(), sizeof(req.ifr_name) - 1); scoped_descriptor sock(socket(AF_INET, SOCK_DGRAM, 0)); if (static_cast(sock) < 0) { LOG_WARNING("socket failed: {1} ({2}): interface MTU fact is unavailable for interface {3}.", strerror(errno), errno, interface); return boost::none; } if (ioctl(sock, SIOCGIFMTU, &req) == -1) { LOG_WARNING("ioctl failed: {1} ({2}): interface MTU fact is unavailable for interface {3}.", strerror(errno), errno, interface); return boost::none; } return req.ifr_mtu; } string networking_resolver::get_primary_interface() const { // If we have a list of routes, then we'll determine the // primary interface from that later on when we are processing // them. if (routes4.size()) { return {}; } // Read /proc/net/route to determine the primary interface // We consider the primary interface to be the one that has 0.0.0.0 as the // routing destination. string interface; lth_file::each_line("/proc/net/route", [&interface](string& line) { vector> parts; boost::split(parts, line, boost::is_space(), boost::token_compress_on); if (parts.size() > 7 && parts[1] == boost::as_literal("00000000") && parts[7] == boost::as_literal("00000000")) { interface.assign(parts[0].begin(), parts[0].end()); return false; } return true; }); return interface; } void networking_resolver::read_routing_table() { auto ip_command = lth_exe::which("ip"); if (ip_command.empty()) { LOG_DEBUG("Could not find the 'ip' command. Network bindings will not be populated from routing table"); return; } unordered_set known_route_types { "anycast", "unicast", "broadcast", "local", "nat", "unreachable", "prohibit", "blackhole", "throw" }; auto parse_route_line = [&known_route_types](string& line, int family, std::vector& routes) { vector> parts; boost::split(parts, line, boost::is_space(), boost::token_compress_on); // skip links that are linkdown if (std::find_if(parts.cbegin(), parts.cend(), [](const boost::iterator_range& range) { return std::string(range.begin(), range.end()) == "linkdown"; }) != parts.cend()) { return true; } // FACT-1282 std::string route_type(parts[0].begin(), parts[0].end()); if (known_route_types.find(route_type) != known_route_types.end()) { parts.erase(parts.begin()); } route r; r.destination.assign(parts[0].begin(), parts[0].end()); // Check if we queried for the IPV6 routing tables. If yes, then check if our // destination address is missing a ':'. If yes, then IPV6 is disabled since // IPV6 addresses have a ':' in them. Our ip command has mistakenly outputted IPV4 // information. This is bogus data that we want to flush. // // See FACT-1475 for more details. if (family == AF_INET6 && r.destination.find(':') == string::npos) { routes = {}; return false; } // Iterate over key/value pairs and add the ones we care // about to our routes entries for (size_t i = 1; i < parts.size(); i += 2) { std::string key(parts[i].begin(), parts[i].end()); if (key == "dev") { r.interface.assign(parts[i+1].begin(), parts[i+1].end()); } if (key == "src") { r.source.assign(parts[i+1].begin(), parts[i+1].end()); } } routes.push_back(r); return true; }; lth_exe::each_line(ip_command, { "route", "show" }, [this, &parse_route_line](string& line) { return parse_route_line(line, AF_INET, this->routes4); }); lth_exe::each_line(ip_command, { "-6", "route", "show" }, [this, &parse_route_line](string& line) { return parse_route_line(line, AF_INET6, this->routes6); }); } void networking_resolver::populate_from_routing_table(networking_resolver::data& result) const { for (const auto& r : routes4) { if (r.destination == "default" && result.primary_interface.empty()) { result.primary_interface = r.interface; } associate_src_with_iface(r, result, [](interface& iface) -> vector& { return iface.ipv4_bindings; }); } for (const auto& r : routes6) { associate_src_with_iface(r, result, [](interface& iface) -> vector& { return iface.ipv6_bindings; }); } } template void networking_resolver::associate_src_with_iface(const networking_resolver::route& r, networking_resolver::data& result, F get_bindings) const { if (!r.source.empty()) { auto iface = find_if(result.interfaces.begin(), result.interfaces.end(), [&](const interface& iface) { return iface.name == r.interface; }); if (iface != result.interfaces.end()) { auto& bindings = get_bindings(*iface); auto existing_binding = find_if(bindings.begin(), bindings.end(), [&](const binding& b) { return b.address == r.source; }); if (existing_binding == bindings.end()) { binding b = { r.source, "", "" }; bindings.emplace_back(move(b)); } } } } string networking_resolver::get_bond_master(const std::string& name) const { static bool have_logged_about_bonding = false; auto ip_command = lth_exe::which("ip"); if (ip_command.empty()) { if (!have_logged_about_bonding) { LOG_DEBUG("Could not find the 'ip' command. Physical macaddress for bonded interfaces will be incorrect."); have_logged_about_bonding = true; } return {}; } string bonding_master; lth_exe::each_line(ip_command, {"link", "show", name}, [&bonding_master](string& line) { if (line.find("SLAVE") != string::npos) { vector> parts; boost::split(parts, line, boost::is_space(), boost::token_compress_on); // We have to use find_if here since a boost::iterator_range doesn't compare properly to a string. auto master = find_if(parts.begin(), parts.end(), [](boost::iterator_range& part){ string p {part.begin(), part.end()}; return p == "master"; }); // the actual master interface is in the output as // "master ". Once we've found the master // string above, we get the next token and return that // as our interface device. if (master != parts.end()) { auto master_iface = master + 1; if (master_iface != parts.end()) { bonding_master.assign(master_iface->begin(), master_iface->end()); return false; } } } return true; }); return bonding_master; } }}} // namespace facter::facts::linux facter-3.14.12/lib/src/facts/linux/operating_system_resolver.cc0000644005276200011600000001463213702047406024447 0ustar jenkinsjenkins#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include using namespace std; using namespace leatherman::execution; using namespace boost::filesystem; using namespace leatherman::util; namespace lth_file = leatherman::file_util; namespace facter { namespace facts { namespace linux { static unique_ptr get_os() { auto release_info = os_linux::key_value_file(release_file::os, {"ID", "CISCO_RELEASE_INFO"}); auto const& id = release_info["ID"]; if (id == "coreos" || id == "cumulus-linux" || id == "opensuse" || id == "opensuse-leap" || id== "sled" || id == "sles" || id == "ubuntu") { return unique_ptr(new os_osrelease()); } else { auto const& cisco = release_info["CISCO_RELEASE_INFO"]; boost::system::error_code ec; if (!cisco.empty() && is_regular_file(cisco, ec)) { return unique_ptr(new os_cisco(cisco)); } } return unique_ptr(new os_linux()); } static string get_selinux_mountpoint() { static boost::regex regexp("\\S+ (\\S+) selinuxfs"); string mountpoint; lth_file::each_line("/proc/self/mounts", [&](string& line) { if (re_search(line, regexp, &mountpoint)) { return false; } return true; }); return mountpoint; } operating_system_resolver::selinux_data operating_system_resolver::collect_selinux_data() { static string SELINUX_CONFIG_FILE("/etc/selinux/config"); selinux_data result; result.supported = true; string mountpoint = get_selinux_mountpoint(); result.enabled = !mountpoint.empty() && exists(SELINUX_CONFIG_FILE); if (!result.enabled) { return result; } // Get the policy version result.policy_version = lth_file::read(mountpoint + "/policyvers"); // Check for enforcement string enforce = lth_file::read(mountpoint + "/enforce"); if (!enforce.empty()) { if (enforce == "1") { result.enforced = true; result.current_mode = "enforcing"; } else { result.current_mode = "permissive"; } } // Parse the SELinux config for mode and policy static boost::regex mode_regex("(?m)^SELINUX=(\\w+)$"); static boost::regex policy_regex("(?m)^SELINUXTYPE=(\\w+)$"); lth_file::each_line(SELINUX_CONFIG_FILE, [&](string& line) { if (re_search(line, mode_regex, &result.config_mode)) { return true; } if (re_search(line, policy_regex, &result.config_policy)) { return true; } return true; }); return result; } operating_system_resolver::data operating_system_resolver::collect_data(collection& facts) { // Default to the base implementation data result = posix::operating_system_resolver::collect_data(facts); // Populate distro info each_line("lsb_release", {"-a"}, [&](string& line) { string* variable = nullptr; size_t offset = 0; if (boost::starts_with(line, "LSB Version:")) { variable = &result.specification_version; offset = 12; } else if (boost::starts_with(line, "Distributor ID:")) { variable = &result.distro.id; offset = 15; } else if (boost::starts_with(line, "Description:")) { variable = &result.distro.description; offset = 12; } else if (boost::starts_with(line, "Codename:")) { variable = &result.distro.codename; offset = 9; } else if (boost::starts_with(line, "Release:")) { variable = &result.distro.release; offset = 8; } if (!variable) { return true; } *variable = line.substr(offset); boost::trim(*variable); return true; }); auto implementation = get_os(); auto name = implementation->get_name(result.distro.id); if (!name.empty()) { result.name = move(name); } auto family = implementation->get_family(result.name); if (!family.empty()) { result.family = move(family); } auto release = implementation->get_release(result.name, result.distro.release); if (!release.empty()) { if (result.name == os::debian) { // on debian 10 final iso, versions from lsb_release and /etc/debian_version are different result.distro.release = release; } result.release = move(release); tie(result.major, result.minor) = implementation->parse_release(result.name, result.release); } // Convert the architecture value depending on distro // For certain distros, use "amd64" for "x86_64" // For certain distros, use "x86" for "i386" if (result.architecture == "x86_64" && ( result.name == os::debian || result.name == os::linux_mint || result.name == os::gentoo || result.name == os::kfreebsd || result.name == os::ubuntu)) { result.architecture = "amd64"; } else if (re_search(result.architecture, boost::regex("i[3456]86|pentium"))) { // For 32-bit, use "x86" for Gentoo and "i386" for everyone else if (result.name == os::gentoo) { result.architecture = "x86"; } else { result.architecture = "i386"; } } result.selinux = collect_selinux_data(); return result; } }}} // namespace facter::facts::linux facter-3.14.12/lib/src/facts/linux/os_linux.cc0000644005276200011600000004252613702047406020775 0ustar jenkinsjenkins#include #include #include #include #include #include #include #include #include #include using namespace std; using namespace leatherman::execution; using namespace boost::filesystem; using namespace leatherman::util; namespace bs = boost::system; namespace lth_file = leatherman::file_util; namespace facter { namespace facts { namespace linux { // Return contents of the os-release file // http://www.freedesktop.org/software/systemd/man/os-release.html map os_linux::key_value_file(string file, set const& items) { map values; bs::error_code ec; if (!items.empty() && is_regular_file(file, ec)) { string key, value; lth_file::each_line(file, [&](string& line) { if (re_search(line, boost::regex("(?m)^(\\w+)=[\"']?(.+?)[\"']?$"), &key, &value)) { if (items.count(key)) { values.insert(make_pair(key, value)); } } return items.size() != values.size(); }); } return values; } os_linux::os_linux(std::set items, std::string file) : _release_info(key_value_file(file, items)) {} static string check_debian_linux(string const& distro_id) { // Check for Debian variants bs::error_code ec; if (is_regular_file(release_file::huawei, ec)) { return os::huawei; } if (is_regular_file(release_file::devuan, ec)) { return os::devuan; } if (is_regular_file(release_file::debian, ec)) { if (distro_id == os::ubuntu || distro_id == os::linux_mint) { return distro_id; } return os::debian; } return {}; } static string check_oracle_linux() { bs::error_code ec; if (is_regular_file(release_file::oracle_enterprise_linux, ec)) { if (is_regular_file(release_file::oracle_vm_linux, ec)) { return os::oracle_vm_linux; } return os::oracle_enterprise_linux; } return {}; } static string check_redhat_linux() { bs::error_code ec; if (is_regular_file(release_file::redhat, ec)) { static vector> const regexs { make_tuple(boost::regex("(?i)centos"), string(os::centos)), make_tuple(boost::regex("(?i)scientific linux CERN"), string(os::scientific_cern)), make_tuple(boost::regex("(?i)scientific linux release"), string(os::scientific)), make_tuple(boost::regex("(?im)^cloudlinux"), string(os::cloud_linux)), make_tuple(boost::regex("(?im)^virtuozzo linux"), string(os::virtuozzo_linux)), make_tuple(boost::regex("(?im)^virtuozzolinux"), string(os::virtuozzo_linux)), make_tuple(boost::regex("(?i)Ascendos"), string(os::ascendos)), make_tuple(boost::regex("(?im)^XenServer"), string(os::xen_server)), make_tuple(boost::regex("(?im)^XCP-ng"), string(os::xcp_ng)), make_tuple(boost::regex("XCP"), string(os::zen_cloud_platform)), make_tuple(boost::regex("(?im)^Parallels Server Bare Metal"), string(os::psbm)), make_tuple(boost::regex("(?m)^Fedora release"), string(os::fedora)), }; string contents = lth_file::read(release_file::redhat); boost::trim(contents); for (auto const& regex : regexs) { if (re_search(contents, get<0>(regex))) { return get<1>(regex); } } return os::redhat; } return {}; } static string check_photon_linux() { string contents = lth_file::read(release_file::lsb); boost::trim(contents); if (re_search(contents, boost::regex("VMware Photon"))) { return string(os::photon_os); } return {}; } static string check_suse_linux() { bs::error_code ec; if (is_regular_file(release_file::suse, ec)) { static vector> const regexs { make_tuple(boost::regex("(?im)^SUSE LINUX Enterprise Server"), string(os::suse_enterprise_server)), make_tuple(boost::regex("(?im)^SUSE LINUX Enterprise Desktop"), string(os::suse_enterprise_desktop)), make_tuple(boost::regex("(?im)^openSUSE"), string(os::open_suse)), }; string contents = lth_file::read(release_file::suse); boost::trim(contents); for (auto const& regex : regexs) { if (re_search(contents, get<0>(regex))) { return get<1>(regex); } } return os::suse; } return {}; } static string check_other_linux() { static vector> const files { make_tuple(string(release_file::arista_eos), string(os::arista_eos)), make_tuple(string(release_file::gentoo), string(os::gentoo)), make_tuple(string(release_file::mageia), string(os::mageia)), make_tuple(string(release_file::mandriva), string(os::mandriva)), make_tuple(string(release_file::mandrake), string(os::mandrake)), make_tuple(string(release_file::meego), string(os::meego)), make_tuple(string(release_file::archlinux), string(os::archlinux)), make_tuple(string(release_file::manjarolinux), string(os::manjarolinux)), make_tuple(string(release_file::oracle_linux), string(os::oracle_linux)), make_tuple(string(release_file::openwrt), string(os::openwrt)), make_tuple(string(release_file::alpine), string(os::alpine)), make_tuple(string(release_file::vmware_esx), string(os::vmware_esx)), make_tuple(string(release_file::slackware), string(os::slackware)), }; for (auto const& file : files) { bs::error_code ec; if (is_regular_file(get<0>(file), ec)) { return get<1>(file); } } return {}; } static string check_amazon() { bs::error_code ec; if (is_regular_file(release_file::amazon, ec)) { return os::amazon; } return {}; } string os_linux::get_name(string const& distro_id) const { // Check for Debian first; this happens after AristaEOS in Facter 2.x // but that platform is not a Debian so shouldn't matter. auto value = check_debian_linux(distro_id); if (!value.empty()) { return value; } // Check for specialized distributions next value = check_other_linux(); if (!value.empty()) { return value; } // Check for Oracle Enterprise Linux next value = check_oracle_linux(); if (!value.empty()) { return value; } // Check for RedHat next value = check_redhat_linux(); if (!value.empty()) { return value; } // Check for SuSE next value = check_suse_linux(); if (!value.empty()) { return value; } value = check_photon_linux(); if (!value.empty()) { return value; } // This should happen after everything else because it's a relatively broad match return check_amazon(); } string os_linux::get_family(string const& name) const { static map const systems = { { string(os::redhat), string(os_family::redhat) }, { string(os::fedora), string(os_family::redhat) }, { string(os::centos), string(os_family::redhat) }, { string(os::scientific), string(os_family::redhat) }, { string(os::scientific_cern), string(os_family::redhat) }, { string(os::ascendos), string(os_family::redhat) }, { string(os::cloud_linux), string(os_family::redhat) }, { string(os::psbm), string(os_family::redhat) }, { string(os::oracle_linux), string(os_family::redhat) }, { string(os::oracle_vm_linux), string(os_family::redhat) }, { string(os::oracle_enterprise_linux), string(os_family::redhat) }, { string(os::amazon), string(os_family::redhat) }, { string(os::xen_server), string(os_family::redhat) }, { string(os::xcp_ng), string(os_family::redhat) }, { string(os::virtuozzo_linux), string(os_family::redhat) }, { string(os::photon_os), string(os_family::redhat) }, { string(os::huawei), string(os_family::debian) }, { string(os::linux_mint), string(os_family::debian) }, { string(os::ubuntu), string(os_family::debian) }, { string(os::debian), string(os_family::debian) }, { string(os::devuan), string(os_family::debian) }, { string(os::suse_enterprise_server), string(os_family::suse) }, { string(os::suse_enterprise_desktop), string(os_family::suse) }, { string(os::open_suse), string(os_family::suse) }, { string(os::suse), string(os_family::suse) }, { string(os::gentoo), string(os_family::gentoo) }, { string(os::archlinux), string(os_family::archlinux) }, { string(os::manjarolinux), string(os_family::archlinux) }, { string(os::mandrake), string(os_family::mandrake) }, { string(os::mandriva), string(os_family::mandrake) }, { string(os::mageia), string(os_family::mandrake) }, }; auto const& it = systems.find(name); if (it != systems.end()) { return it->second; } return {}; } string os_linux::get_release(string const& name, string const& distro_release) const { // Map of release files that contain a "release X.X.X" on the first line static map const release_files = { { string(os::amazon), string(release_file::amazon) }, { string(os::centos), string(release_file::redhat) }, { string(os::redhat), string(release_file::redhat) }, { string(os::scientific), string(release_file::redhat) }, { string(os::scientific_cern), string(release_file::redhat) }, { string(os::ascendos), string(release_file::redhat) }, { string(os::cloud_linux), string(release_file::redhat) }, { string(os::psbm), string(release_file::redhat) }, { string(os::xen_server), string(release_file::redhat) }, { string(os::xcp_ng), string(release_file::redhat) }, { string(os::virtuozzo_linux), string(release_file::redhat) }, { string(os::fedora), string(release_file::fedora) }, { string(os::meego), string(release_file::meego) }, { string(os::oracle_linux), string(release_file::oracle_linux) }, { string(os::oracle_enterprise_linux), string(release_file::oracle_enterprise_linux) }, { string(os::oracle_vm_linux), string(release_file::oracle_vm_linux) }, { string(os::arista_eos), string(release_file::arista_eos) }, { string(os::gentoo), string(release_file::gentoo) }, }; string value; auto it = release_files.find(name); if (it != release_files.end()) { string contents; if (lth_file::each_line(it->second, [&](string& line) { // We only need the first line contents = move(line); return false; })) { if (boost::ends_with(contents, "(Rawhide)")) { value = "Rawhide"; } else if (contents.find("release") != string::npos) { re_search(contents, boost::regex("release (\\d[\\d.]*)"), &value); } else { re_search(contents, boost::regex("Amazon Linux (\\d+)"), &value); } } } // Debian uses the entire contents of the release file as the version if (value.empty() && name == os::debian) { value = lth_file::read(release_file::debian); boost::trim_right(value); } // Devuan uses the entire contents of the release file as the version if (value.empty() && name == os::devuan) { value = lth_file::read(release_file::devuan); boost::trim_right(value); } // Alpine uses the entire contents of the release file as the version if (value.empty() && name == os::alpine) { value = lth_file::read(release_file::alpine); boost::trim_right(value); } // HuaweiOS uses the entire contents of the release file as the version if (value.empty() && name == os::huawei) { value = lth_file::read(release_file::huawei); boost::trim_right(value); } // Check for SuSE related distros, read the release file if (value.empty() && ( name == os::suse || name == os::suse_enterprise_server || name == os::suse_enterprise_desktop || name == os::open_suse)) { string contents = lth_file::read(release_file::suse); string major; string minor; if (re_search(contents, boost::regex("(?m)^VERSION\\s*=\\s*(\\d+)\\.?(\\d+)?"), &major, &minor)) { // Check that we have a minor version; if not, use the patch level if (minor.empty()) { if (!re_search(contents, boost::regex("(?m)^PATCHLEVEL\\s*=\\s*(\\d+)"), &minor)) { minor = "0"; } } value = major + "." + minor; } else { value = "unknown"; } } if (value.empty() && name == os::photon_os) { string major, minor; string contents = lth_file::read(release_file::lsb); string pattern = "DISTRIB_RELEASE=\"(\\d+)\\.(\\d+)( ([a-zA-Z]+\\d+))?\""; if (re_search(contents, boost::regex(pattern), &major, &minor)) { value = major + "." + minor; } } // Read version files of particular operating systems if (value.empty()) { const char* file = nullptr; boost::regex pattern; if (name == os::ubuntu) { file = release_file::lsb; pattern = "(?m)^DISTRIB_RELEASE=(\\d+\\.\\d+)(?:\\.\\d+)*"; } else if (name == os::slackware) { file = release_file::slackware; pattern = "Slackware ([0-9.]+)"; } else if (name == os::mageia) { file = release_file::mageia; pattern = "Mageia release ([0-9.]+)"; } else if (name == os::linux_mint) { file = release_file::linux_mint_info; pattern = "(?m)^RELEASE=(\\d+)"; } else if (name == os::openwrt) { file = release_file::openwrt_version; pattern = "(?m)^(\\d+\\.\\d+.*)"; } else if (name == os::arista_eos) { file = release_file::arista_eos; pattern = "Arista Networks EOS (\\d+\\.\\d+\\.\\d+[A-M]?)"; } if (file) { string contents = lth_file::read(file); re_search(contents, pattern, &value); } } // For VMware ESX, execute the vmware tool if (value.empty() && name == os::vmware_esx) { auto exec = execute("vmware", { "-v" }); if (exec.success) { re_search(exec.output, boost::regex("VMware ESX .*?(\\d.*)"), &value); } } return value; } tuple os_linux::parse_release(string const& name, string const& release) const { return facter::facts::resolvers::operating_system_resolver::parse_distro(name, release); } }}} // namespace facter::facts::linux facter-3.14.12/lib/src/facts/linux/processor_resolver.cc0000644005276200011600000001605413702047406023072 0ustar jenkinsjenkins#include #include #include #include #include #include #include #include #include #include #include #include using namespace std; using namespace boost::filesystem; using facter::util::maybe_stoi; namespace lth_file = leatherman::file_util; namespace lth_util = leatherman::util; namespace facter { namespace facts { namespace linux { static bool split_line(string const& line, string& key, string& value) { // Split the line on colon auto pos = line.find(":"); if (pos == string::npos) { return false; } key = line.substr(0, pos); boost::trim(key); value = line.substr(pos + 1); boost::trim(value); return true; } processor_resolver::ArchitectureType processor_resolver::architecture_type(data const& data, std::string const& root) { if (!data.isa.empty()) { return (boost::starts_with(data.isa, "ppc64")) ? ArchitectureType::POWER : ArchitectureType::X86; } // use /proc/cpuinfo unordered_set to_be_seen; bool seen_all = false; lth_file::each_line(root + "/proc/cpuinfo", [&](string& line) { // if we already know that we're on a Power machine, we can just skip // the remaining lines if (seen_all) { return false; } string key, value; if (!split_line(line, key, value)) { return true; } if (key == "processor") { to_be_seen = unordered_set{{"cpu", "clock", "revision"}}; } else if (find(to_be_seen.begin(), to_be_seen.end(), key) != to_be_seen.end()) { to_be_seen.erase(key); seen_all = to_be_seen.empty(); } return true; }); return seen_all ? ArchitectureType::POWER : ArchitectureType::X86; } // returns true if the first cpu is a valid, physical cpu to use when computing the processor // speed bool processor_resolver::compute_cpu_counts(data& data, std::string const& root, std::function is_valid_id) { unordered_set cpus; bool cpu0_valid = false; lth_file::each_subdirectory(root + "/sys/devices/system/cpu", [&](string const& cpu_directory) { string physical_id_path = (path(cpu_directory) / "/topology/physical_package_id").string(); if (lth_file::file_readable(physical_id_path)) { bool at_cpu0 = data.logical_count == 0; data.logical_count++; string id = lth_file::read(physical_id_path); boost::trim(id); if ((is_valid_id(id) && cpus.emplace(move(id)).second)) { // Haven't seen this processor before ++data.physical_count; if (at_cpu0) { cpu0_valid = true; } } } return true; }, "^cpu\\d+$"); return cpu0_valid; } void processor_resolver::maybe_add_speed(data& data, std::string const& speed) { auto maybe_speed = maybe_stoi(speed); if (maybe_speed && maybe_speed.get() > 0) { data.speed = maybe_speed.get() * static_cast(1000); } } bool processor_resolver::add_x86_cpu_data(data& data, std::string const& root) { bool cpu0_valid = compute_cpu_counts(data, root, [](string const& id) { // any id is fine for x86 cpus return true; }); bool have_counts = data.logical_count > 0; unordered_set cpus; string id; lth_file::each_line(root + "/proc/cpuinfo", [&](string& line) { string key, value; if (!split_line(line, key, value)) { return true; } if (key == "processor") { // Start of a logical processor id = move(value); if (!have_counts) { ++data.logical_count; } } else if (!id.empty() && key == "model name") { // Add the model for this logical processor data.models.emplace_back(move(value)); } else if (!have_counts && key == "physical id" && cpus.emplace(move(value)).second) { // Couldn't determine physical count from sysfs, but CPU topology is present, so use it ++data.physical_count; } return true; }); return cpu0_valid; } bool processor_resolver::add_power_cpu_data(data& data, std::string const& root) { bool cpu0_valid = compute_cpu_counts(data, root, [](string const& id) { // only non-negative ids are allowed for power cpus auto maybe_id = maybe_stoi(id); return !maybe_id || maybe_id.get() >= 0; }); // per ticket specs, logical count is computed below data.logical_count = 0; unordered_set cpus; string id; lth_file::each_line(root + "/proc/cpuinfo", [&](string& line) { string key, value; if (!split_line(line, key, value)) { return true; } if (key == "processor") { // Start of a logical processor id = move(value); ++data.logical_count; } else if (!id.empty() && key == "cpu") { // Add the model for this logical processor data.models.emplace_back(move(value)); } else if (key == "clock" && data.speed == 0) { // Parse out the processor speed (in MHz) string speed; if (lth_util::re_search(value, boost::regex("^(\\d+).*MHz"), &speed)) { maybe_add_speed(data, speed); } } return true; }); return cpu0_valid; } void processor_resolver::add_cpu_data(data& data, std::string const& root) { bool cpu0_valid = (architecture_type(data, root) == ArchitectureType::X86) ? add_x86_cpu_data(data, root) : add_power_cpu_data(data, root); if (data.speed != 0 || !cpu0_valid) { return; } // Read in the max speed from the first cpu // The speed is in kHz string speed = lth_file::read(root + "/sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_max_freq"); maybe_add_speed(data, speed); } processor_resolver::data processor_resolver::collect_data(collection& facts) { auto result = posix::processor_resolver::collect_data(facts); add_cpu_data(result); return result; } }}} // namespace facter::facts::linux facter-3.14.12/lib/src/facts/linux/uptime_resolver.cc0000644005276200011600000000060313702047406022347 0ustar jenkinsjenkins#include #include namespace facter { namespace facts { namespace linux { int64_t uptime_resolver::get_uptime() { struct sysinfo info; if (sysinfo(&info) == 0) { return info.uptime; } return posix::uptime_resolver::get_uptime(); } }}} // namespace facter::facts::linux facter-3.14.12/lib/src/facts/linux/virtualization_resolver.cc0000644005276200011600000002344313702047406024137 0ustar jenkinsjenkins#include #include #include #include #include #include #include #include #include #include #include #include using namespace std; using namespace facter::facts; using namespace facter::util; using namespace leatherman::util; using namespace leatherman::execution; using namespace boost::filesystem; namespace bs = boost::system; namespace lth_file = leatherman::file_util; namespace facter { namespace facts { namespace linux { string virtualization_resolver::get_cloud_provider(collection& facts) { std::string provider = get_azure(); return provider; } string virtualization_resolver::get_azure() { std::string provider; static vector const dhclient_search_directories = { "/var/lib/dhcp", "/var/lib/NetworkManager" }; for (auto const& dir : dhclient_search_directories) { LOG_DEBUG("searching \"{1}\" for dhclient lease files.", dir); lth_file::each_file(dir, [&](string const& leases_file) { LOG_DEBUG("reading \"{1}\" for dhclient lease azure information.", leases_file); provider = get_azure_from_leases_file(leases_file); return provider.empty(); }, "^dhclient.*lease.*$"); if (!provider.empty()) break; } return provider; } // Search for DHCP option 245. This is an accepted method of determining // whether a machine is running inside Azure. Source: // https://social.msdn.microsoft.com/Forums/azure/en-US/f7fbbee6-370a-41c2-a384-d14ab2a0ac12/what-is-the-correct-method-in-linux-on-azure-to-test-if-you-are-an-azure-vm-?forum=WAVirtualMachinesforWindows string virtualization_resolver::get_azure_from_leases_file(string leases_file) { string provider; lth_file::each_line(leases_file, [&](string& line) { if (line.find("option 245") != std::string::npos || line.find("option unknown-245") != std::string::npos) { LOG_DEBUG("found azure option in \"{1}\" lease file.", leases_file); provider = "azure"; return false; } return true; }); return provider; } string virtualization_resolver::get_hypervisor(collection& facts) { // First check for Docker/LXC string value = get_cgroup_vm(); // Next check for Google Compute Engine if (value.empty()) { value = get_gce_vm(facts); } // Next check based on the virt-what command if (value.empty()) { value = get_what_vm(); } // Next check the vmware tool output if (value.empty()) { value = get_vmware_vm(); } // Next check for OpenVZ if (value.empty()) { value = get_openvz_vm(); } // Next check for VServer if (value.empty()) { value = get_vserver_vm(); } // Next check for Xen if (value.empty()) { value = get_xen_vm(); } // Next check other facts for the VM if (value.empty()) { value = get_fact_vm(facts); } // Lastly, resort to lspci to look for hardware related to certain VMs if (value.empty()) { value = get_lspci_vm(); } return value; } string virtualization_resolver::get_cgroup_vm() { string value; lth_file::each_line("/proc/1/cgroup", [&](string& line) { vector> parts; boost::split(parts, line, boost::is_any_of(":"), boost::token_compress_on); if (parts.size() < 3) { return true; } if (boost::contains(parts[2], boost::as_literal("/docker"))) { value = vm::docker; return false; } if (boost::contains(parts[2], boost::as_literal("/lxc"))) { value = vm::lxc; return false; } return true; }); return value; } string virtualization_resolver::get_gce_vm(collection& facts) { auto vendor = facts.get(fact::bios_vendor); if (vendor && vendor->value().find("Google") != string::npos) { return vm::gce; } return {}; } string virtualization_resolver::get_what_vm() { string virt_what = agent::which("virt-what"); string value; each_line(virt_what, [&](string& line) { // Some versions of virt-what dump error/warning messages to stdout if (boost::starts_with(line, "virt-what:")) { return true; } // Take the first line that isn't an error/warning // unless it's "xen", in which case we expect a second // line with more useful information if (line == "xen") { return true; } value = move(line); return false; }); // Do some normalization of virt-what's output if (!value.empty()) { boost::to_lower(value); if (value == "linux_vserver") { return get_vserver_vm(); } if (value == "xen-hvm") { return vm::xen_hardware; } if (value == "xen-dom0") { return vm::xen_privileged; } if (value == "xen-domu") { return vm::xen_unprivileged; } if (value == "ibm_systemz") { return vm::zlinux; } } return value; } string virtualization_resolver::get_vserver_vm() { string value; lth_file::each_line("/proc/self/status", [&](string& line) { vector> parts; boost::split(parts, line, boost::is_space(), boost::token_compress_on); if (parts.size() != 2) { return true; } if (parts[0] == boost::as_literal("s_context:") || parts[0] == boost::as_literal("VxID:")) { if (parts[1] == boost::as_literal("0")) { value = vm::vserver_host; } else { value = vm::vserver; } return false; } return true; }); return value; } string virtualization_resolver::get_vmware_vm() { auto exec = execute("vmware", { "-v" }); if (!exec.success) { return {}; } vector parts; boost::split(parts, exec.output, boost::is_space(), boost::token_compress_on); if (parts.size() < 2) { return {}; } boost::to_lower(parts[0]); boost::to_lower(parts[1]); return parts[0] + '_' + parts[1]; } string virtualization_resolver::get_openvz_vm() { // Detect if it's a OpenVZ without being CloudLinux bs::error_code ec; if (!is_directory("/proc/vz", ec) || is_regular_file("/proc/lve/list", ec) || boost::filesystem::is_empty("/proc/vz", ec)) { return {}; } string value; lth_file::each_line("/proc/self/status", [&](string& line) { vector> parts; boost::split(parts, line, boost::is_space(), boost::token_compress_on); if (parts.size() != 2) { return true; } if (parts[0] == boost::as_literal("envID:")) { if (parts[1] == boost::as_literal("0")) { value = vm::openvz_hn; } else { value = vm::openvz_ve; } return false; } return true; }); return value; } string virtualization_resolver::get_xen_vm() { // Check for a required Xen file bs::error_code ec; if (exists("/dev/xen/evtchn", ec) && !ec) { return vm::xen_privileged; } ec.clear(); if (exists("/proc/xen", ec) && !ec) { return vm::xen_unprivileged; } ec.clear(); if (exists("/dev/xvda1", ec) && !ec) { return vm::xen_unprivileged; } return {}; } string virtualization_resolver::get_lspci_vm() { static vector> vms = { make_tuple(boost::regex("VM[wW]are"), string(vm::vmware)), make_tuple(boost::regex("VirtualBox"), string(vm::virtualbox)), make_tuple(boost::regex("1ab8:|[Pp]arallels"), string(vm::parallels)), make_tuple(boost::regex("XenSource"), string(vm::xen_hardware)), make_tuple(boost::regex("Microsoft Corporation Hyper-V"), string(vm::hyperv)), make_tuple(boost::regex("Class 8007: Google, Inc"), string(vm::gce)), make_tuple(boost::regex("virtio", boost::regex::icase), string(vm::kvm)), }; string value; each_line("lspci", [&](string& line) { for (auto const& vm : vms) { if (re_search(line, get<0>(vm))) { value = get<1>(vm); return false; } } return true; }); return value; } }}} // namespace facter::facts::linux facter-3.14.12/lib/src/facts/map_value.cc0000644005276200011600000000612713702047406017744 0ustar jenkinsjenkins#include #include #include #include #include #include using namespace std; using namespace facter::util; using namespace rapidjson; using namespace YAML; namespace facter { namespace facts { map_value::map_value(map_value&& other) { *this = std::move(other); } map_value& map_value::operator=(map_value&& other) { value::operator=(static_cast(other)); if (this != &other) { _elements = std::move(other._elements); } return *this; } void map_value::add(string name, unique_ptr value) { if (!value) { LOG_DEBUG("null value cannot be added to map."); return; } _elements.emplace(move(name), move(value)); } bool map_value::empty() const { return _elements.empty(); } size_t map_value::size() const { return _elements.size(); } void map_value::each(function func) const { for (auto const& kvp : _elements) { if (!func(kvp.first, kvp.second.get())) { break; } } } value const* map_value::operator[](string const& name) const { auto it = _elements.find(name); if (it == _elements.end()) { return nullptr; } return it->second.get(); } void map_value::to_json(json_allocator& allocator, json_value& value) const { value.SetObject(); for (auto const& kvp : _elements) { json_value child; kvp.second->to_json(allocator, child); value.AddMember(rapidjson::StringRef(kvp.first.c_str(), kvp.first.size()), std::move(child), allocator); } } ostream& map_value::write(ostream& os, bool quoted, unsigned int level) const { if (_elements.empty()) { os << "{}"; return os; } // Write out the elements in the map os << "{\n"; bool first = true; for (auto const& kvp : _elements) { if (first) { first = false; } else { os << ",\n"; } fill_n(ostream_iterator(os), level * 2, ' '); os << kvp.first << " => "; kvp.second->write(os, true /* always quote strings in a map */, level + 1); } os << "\n"; fill_n(ostream_iterator(os), (level > 0 ? (level - 1) : 0) * 2, ' '); os << "}"; return os; } Emitter& map_value::write(Emitter& emitter) const { emitter << BeginMap; for (auto const& kvp : _elements) { emitter << Key; if (needs_quotation(kvp.first)) { emitter << DoubleQuoted; } emitter << kvp.first << YAML::Value; kvp.second->write(emitter); } emitter << EndMap; return emitter; } }} // namespace facter::facts facter-3.14.12/lib/src/facts/openbsd/0000755005276200011600000000000013702047635017114 5ustar jenkinsjenkinsfacter-3.14.12/lib/src/facts/openbsd/collection.cc0000644005276200011600000000310113702047406021545 0ustar jenkinsjenkins#include #include #include #include #include #include #include #include #include #include #include #include #include #include using namespace std; namespace facter { namespace facts { void collection::add_platform_facts() { add(make_shared()); add(make_shared()); add(make_shared()); add(make_shared()); add(make_shared()); add(make_shared()); add(make_shared()); add(make_shared()); add(make_shared()); add(make_shared()); add(make_shared()); add(make_shared()); add(make_shared()); } }} // namespace facter::facts facter-3.14.12/lib/src/facts/openbsd/dmi_resolver.cc0000644005276200011600000000252613702047406022116 0ustar jenkinsjenkins#include #include #include using namespace std; namespace facter { namespace facts { namespace openbsd { dmi_resolver::data dmi_resolver::collect_data(collection& facts) { data result; result.bios_vendor = sysctl_lookup(HW_VENDOR); result.uuid = sysctl_lookup(HW_UUID); result.serial_number = sysctl_lookup(HW_SERIALNO); // OpenBSD running as virtual machine within // OpenBSD vmm don't return HW_PRODUCT. For that // case use the HW_VENDOR, to please the // virtualization_resolver result.product_name = sysctl_lookup(HW_PRODUCT); if (result.product_name.length() == 0) { result.product_name = result.bios_vendor; } result.bios_version = sysctl_lookup(HW_VERSION); return result; } string dmi_resolver::sysctl_lookup(int mib_2) { int mib[2]; size_t len; char value[BUFSIZ]; mib[0] = CTL_HW; mib[1] = mib_2; len = sizeof(value) - 1; if (sysctl(mib, 2, &value, &len, nullptr, 0) == -1) { LOG_DEBUG("sysctl_lookup failed: {1} ({2}).", strerror(errno), errno); return ""; } return value; } } } } // namespace facter::facts::openbsd facter-3.14.12/lib/src/facts/openbsd/memory_resolver.cc0000644005276200011600000000535013702047406022653 0ustar jenkinsjenkins#include #include #include #include #include #include #include #include #include using namespace std; using namespace leatherman::execution; namespace facter { namespace facts { namespace openbsd { memory_resolver::data memory_resolver::collect_data(collection& facts) { data result; // Get the system page size int pagesize_mib[] = { CTL_HW, HW_PAGESIZE }; int page_size = 0; size_t len = sizeof(page_size); if (sysctl(pagesize_mib, 2, &page_size, &len, nullptr, 0) == -1) { LOG_DEBUG("sysctl failed: {1} ({2}): system page size is unknown.", strerror(errno), errno); } else { int uvmexp_mib[] = { CTL_VM, VM_UVMEXP }; struct uvmexp uvmexp; len = sizeof(uvmexp); if (sysctl(uvmexp_mib, 2, &uvmexp, &len, nullptr, 0) == -1) { LOG_DEBUG("sysctl uvmexp failed: {1} ({2}): free memory is not available.", strerror(errno), errno); } // Should we account for the buffer cache? result.mem_total = static_cast(uvmexp.npages) << uvmexp.pageshift; result.mem_free = static_cast(uvmexp.free) << uvmexp.pageshift; } // NB: swapctl(2) for SWAP_NSWAP cannot fail int nswaps = swapctl(SWAP_NSWAP, 0, 0); vector swapdev(nswaps); if (swapctl(SWAP_STATS, swapdev.data(), nswaps) == -1) { LOG_DEBUG("swapctl: SWAP_STATS failed: {1} ({2})", strerror(errno), errno); return result; } uint64_t swap_used = 0; for (auto &&swap : swapdev) { if (swap.se_flags & SWF_ENABLE) { result.swap_total += swap.se_nblks / (1024 / DEV_BSIZE); swap_used += swap.se_inuse / (1024 / DEV_BSIZE); } } result.swap_free = result.swap_total - swap_used; // Adjust for expected scale result.swap_total *= 1024; result.swap_free *= 1024; // 0 is for CTL_SWPENC_NAMES' "enable", see uvm_swap_encrypt.h int swap_encrypted_mib[] = { CTL_VM, VM_SWAPENCRYPT, 0 }; int encrypted; len = sizeof(encrypted); if (sysctl(swap_encrypted_mib, 3, &encrypted, &len, nullptr, 0) == -1) { LOG_DEBUG("sysctl failed: {1} ({2}): encrypted swap fact not available.", strerror(errno), errno); } result.swap_encryption = encrypted ? encryption_status::encrypted : encryption_status::not_encrypted; return result; } }}} // namespace facter::facts::openbsd facter-3.14.12/lib/src/facts/openbsd/networking_resolver.cc0000644005276200011600000000423213702047406023530 0ustar jenkinsjenkins#include #include #include #include #include #include #include #include #include #include using namespace std; using namespace facter::util; using namespace facter::util::bsd; using namespace leatherman::execution; namespace facter { namespace facts { namespace openbsd { bool networking_resolver::is_link_address(sockaddr const* addr) const { return addr && addr->sa_family == AF_LINK; } uint8_t const* networking_resolver::get_link_address_bytes(sockaddr const* addr) const { if (!is_link_address(addr)) { return nullptr; } sockaddr_dl const* link_addr = reinterpret_cast(addr); if (link_addr->sdl_alen != 6 && link_addr->sdl_alen != 20) { return nullptr; } return reinterpret_cast(LLADDR(link_addr)); } uint8_t networking_resolver::get_link_address_length(sockaddr const* addr) const { if (!is_link_address(addr)) { return 0; } sockaddr_dl const* link_addr = reinterpret_cast(addr); return link_addr->sdl_alen; } boost::optional networking_resolver::get_link_mtu(string const& interface, void* data) const { ifreq ifr; memset(&ifr, 0, sizeof(ifr)); strncpy(ifr.ifr_name, interface.c_str(), sizeof(ifr.ifr_name)); int s = socket(AF_INET, SOCK_DGRAM, 0); if (s < 0) { LOG_WARNING("socket failed: {1} ({2}): interface MTU fact is unavailable for interface {3}.", strerror(errno), errno, interface); return boost::none; } if (ioctl(s, SIOCGIFMTU, &ifr) == -1) { LOG_WARNING("ioctl failed: {1} ({2}): interface MTU fact is unavailable for interface {3}.", strerror(errno), errno, interface); return boost::none; } return ifr.ifr_mtu; } }}} // namespace facter::facts::openbsdbsd facter-3.14.12/lib/src/facts/openbsd/processor_resolver.cc0000644005276200011600000000420413702047406023357 0ustar jenkinsjenkins#include #include #include #include using namespace std; namespace facter { namespace facts { namespace openbsd { processor_resolver::data processor_resolver::collect_data(collection& facts) { auto result = posix::processor_resolver::collect_data(facts); size_t len; int mib[2]; mib[0] = CTL_HW; // Get the logical count of processors len = sizeof(result.logical_count); mib[1] = HW_NCPU; if (sysctl(mib, 2, &result.logical_count, &len, nullptr, 0) == -1) { LOG_DEBUG("sysctl hw.ncpu failed: {1} ({2}): logical processor count is unavailable.", strerror(errno), errno); } // For each logical processor, collect the model name if (result.logical_count > 0) { // Note: we're using the same description string for all logical processors: // using different CPUs is not even likely to work. vector buffer(256); while (true) { size_t size = buffer.size(); mib[1] = HW_MODEL; if (sysctl(mib, 2, buffer.data(), &size, nullptr, 0) == 0) { buffer.resize(size + 1); result.models.resize(result.logical_count, buffer.data()); break; } if (errno != ENOMEM) { LOG_DEBUG("sysctl hw.model failed: {1} ({2}): processor models are unavailable.", strerror(errno), errno); break; } buffer.resize(buffer.size() * 2); } } // Set the speed len = sizeof(result.speed); mib[1] = HW_CPUSPEED; if (sysctl(mib, 2, &result.speed, &len, nullptr, 0) == -1) { LOG_DEBUG("sysctl hw.cpuspeed failed: {1} ({2}): processor speed is unavailable.", strerror(errno), errno); } // Scale the speed to something resolve() can correctly map result.speed *= 1000 * 1000; return result; } }}} // namespace facter::facts::openbsd facter-3.14.12/lib/src/facts/openbsd/virtualization_resolver.cc0000644005276200011600000000113213702047406024421 0ustar jenkinsjenkins#include #include #include #include #include #include #include using namespace std; using namespace facter::facts; using namespace leatherman::execution; namespace facter { namespace facts { namespace openbsd { string virtualization_resolver::get_hypervisor(collection& facts) { return get_fact_vm(facts); } } } } // namespace facter::facts::openbsd facter-3.14.12/lib/src/facts/osx/0000755005276200011600000000000013702047635016273 5ustar jenkinsjenkinsfacter-3.14.12/lib/src/facts/osx/collection.cc0000644005276200011600000000321313702047406020730 0ustar jenkinsjenkins#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include using namespace std; namespace facter { namespace facts { void collection::add_platform_facts() { add(make_shared()); add(make_shared()); add(make_shared()); add(make_shared()); add(make_shared()); add(make_shared()); add(make_shared()); add(make_shared()); add(make_shared()); add(make_shared()); add(make_shared()); add(make_shared()); add(make_shared()); add(make_shared()); } }} // namespace facter::facts facter-3.14.12/lib/src/facts/osx/dmi_resolver.cc0000644005276200011600000000201613702047406021267 0ustar jenkinsjenkins#include #include #include using namespace std; namespace facter { namespace facts { namespace osx { dmi_resolver::data dmi_resolver::collect_data(collection& facts) { data result; int mib[] = { CTL_HW, HW_MODEL }; size_t length = 0; // OSX only supports the product name if (sysctl(mib, sizeof(mib) / sizeof(mib[0]), nullptr, &length, nullptr, 0) == -1) { LOG_DEBUG("sysctl failed: {1} ({2}): DMI facts are unavailable.", strerror(errno), errno); return result; } vector model_name(length); if (sysctl(mib, sizeof(mib) / sizeof(mib[0]), model_name.data(), &length, nullptr, 0) == -1) { LOG_DEBUG("sysctl failed: {1} ({2}): DMI facts are unavailable.", strerror(errno), errno); return result; } result.product_name = model_name.data(); return result; } }}} // namespace facter::facts::osx facter-3.14.12/lib/src/facts/osx/memory_resolver.cc0000644005276200011600000000521613702047406022033 0ustar jenkinsjenkins#include #include #include #include #include using namespace std; using namespace leatherman::execution; namespace facter { namespace facts { namespace osx { memory_resolver::data memory_resolver::collect_data(collection& facts) { data result; // Get the total memory size int mib[] = { CTL_HW, HW_MEMSIZE }; size_t size = sizeof(result.mem_total); if (sysctl(mib, sizeof(mib) / sizeof(mib[0]), &result.mem_total, &size, nullptr, 0) == -1) { LOG_DEBUG("sysctl failed: {1} ({2}): total memory size is not available.", strerror(errno), errno); } // Get the system page size mib[0] = CTL_HW; mib[1] = HW_PAGESIZE; uint32_t page_size = 0; size = sizeof(page_size); if (sysctl(mib, sizeof(mib) / sizeof(mib[0]), &page_size, &size, nullptr, 0) == -1) { LOG_DEBUG("sysctl failed: {1} ({2}): system page size is unknown.", strerror(errno), errno); } else { // Get the VM stats for free memory vm_statistics64 vm_stats; mach_msg_type_number_t type = HOST_VM_INFO64_COUNT; kern_return_t err = host_statistics64(mach_host_self(), HOST_VM_INFO64, reinterpret_cast(&vm_stats), &type); if (err != KERN_SUCCESS) { LOG_DEBUG("host_statistics64 failed: {1} ({2}): free memory size is not available.", mach_error_string(err), err); } else { // The free count already counts the free speculative pages // To be consistent with what Activity Monitor displays for the "used" amount, // subtract out those pages and only count the "completely free" pages. result.mem_free = (vm_stats.free_count - vm_stats.speculative_count) * page_size; } } // Get the swap usage statistics mib[0] = CTL_VM; mib[1] = VM_SWAPUSAGE; xsw_usage swap_usage; size = sizeof(swap_usage); if (sysctl(mib, sizeof(mib) / sizeof(mib[0]), &swap_usage, &size, nullptr, 0) == -1) { LOG_DEBUG("sysctl failed: {1} ({2}): swap data is not available.", strerror(errno), errno); } else { result.swap_free = swap_usage.xsu_total - swap_usage.xsu_used; result.swap_total = swap_usage.xsu_total; result.swap_encryption = swap_usage.xsu_encrypted ? encryption_status::encrypted : encryption_status::not_encrypted; } return result; } }}} // namespace facter::facts::osx facter-3.14.12/lib/src/facts/osx/networking_resolver.cc0000644005276200011600000000473613702047406022720 0ustar jenkinsjenkins#include #include #include #include #include #include #include #include using namespace std; using namespace leatherman::execution; namespace facter { namespace facts { namespace osx { bool networking_resolver::is_link_address(sockaddr const* addr) const { return addr && addr->sa_family == AF_LINK; } uint8_t const* networking_resolver::get_link_address_bytes(sockaddr const* addr) const { if (!is_link_address(addr)) { return nullptr; } sockaddr_dl const* link_addr = reinterpret_cast(addr); if (link_addr->sdl_alen != 6 && link_addr->sdl_alen != 20) { return nullptr; } return reinterpret_cast(LLADDR(link_addr)); } uint8_t networking_resolver::get_link_address_length(sockaddr const* addr) const { if (!is_link_address(addr)) { return 0; } sockaddr_dl const* link_addr = reinterpret_cast(addr); return link_addr->sdl_alen; } boost::optional networking_resolver::get_link_mtu(string const& interface, void* data) const { if (!data) { return boost::none; } return reinterpret_cast(data)->ifi_mtu; } string networking_resolver::get_primary_interface() const { string interface; each_line("route", { "-n", "get", "default" }, [&interface](string& line){ boost::trim(line); if (boost::starts_with(line, "interface: ")) { interface = line.substr(11); boost::trim(interface); return false; } return true; }); return interface; } map networking_resolver::find_dhcp_servers() const { // We don't parse dhclient information on OSX return map(); } string networking_resolver::find_dhcp_server(string const& interface) const { // Use ipconfig to get the server identifier auto exec = execute("ipconfig", { "getoption", interface, "server_identifier" }); if (!exec.success) { return {}; } return exec.output; } }}} // namespace facter::facts::osx facter-3.14.12/lib/src/facts/osx/operating_system_resolver.cc0000644005276200011600000000322313702047406024113 0ustar jenkinsjenkins#include #include #include #include #include using namespace std; using namespace facter::facts; using namespace leatherman::execution; namespace facter { namespace facts { namespace osx { operating_system_resolver::data operating_system_resolver::collect_data(collection& facts) { // Default to the base implementation data result = posix::operating_system_resolver::collect_data(facts); each_line("/usr/bin/sw_vers", [&](string& line) { // Split at the first ':' auto pos = line.find(':'); if (pos == string::npos) { return true; } string key = line.substr(0, pos); boost::trim(key); string value = line.substr(pos + 1); boost::trim(value); if (key == "ProductName") { result.osx.product = move(value); } else if (key == "BuildVersion") { result.osx.build = move(value); } else if (key == "ProductVersion") { result.osx.version = move(value); } // Continue only if we haven't populated the data return result.osx.product.empty() || result.osx.build.empty() || result.osx.version.empty(); }); // If osx.build is missing the patch version, add '.0' if (boost::regex_match(result.osx.version, boost::regex("^\\d+\\.\\d+$"))) { result.osx.version += ".0"; } return result; } }}} // namespace facter::facts::osx facter-3.14.12/lib/src/facts/osx/processor_resolver.cc0000644005276200011600000000425713702047406022546 0ustar jenkinsjenkins#include #include #include #include using namespace std; namespace facter { namespace facts { namespace osx { processor_resolver::data processor_resolver::collect_data(collection& facts) { auto result = posix::processor_resolver::collect_data(facts); // Get the logical count of processors size_t size = sizeof(result.logical_count); if (sysctlbyname("hw.logicalcpu_max", &result.logical_count, &size, nullptr, 0) == -1) { LOG_DEBUG("sysctlbyname failed: logical processor count is unavailable.", strerror(errno), errno); } // Get the physical count of processors size = sizeof(result.physical_count); if (sysctlbyname("hw.physicalcpu_max", &result.physical_count, &size, nullptr, 0) == -1) { LOG_DEBUG("sysctlbyname failed: {1} ({2}): physical processor count is unavailable.", strerror(errno), errno); } // For each logical processor, collect the model name if (result.logical_count > 0) { // Note: we're using the same description string for all logical processors vector buffer(256); while (true) { size_t size = buffer.size(); if (sysctlbyname("machdep.cpu.brand_string", buffer.data(), &size, nullptr, 0) == 0) { buffer.resize(size + 1); result.models.resize(result.logical_count, buffer.data()); break; } if (errno != ENOMEM) { LOG_DEBUG("sysctlbyname failed: {1} ({2}): processor models are unavailable.", strerror(errno), errno); break; } buffer.resize(buffer.size() * 2); } } // Set the speed size = sizeof(result.speed); if (sysctlbyname("hw.cpufrequency_max", &result.speed, &size, nullptr, 0) == -1) { LOG_DEBUG("sysctlbyname failed: {1} ({2}): processor speed is unavailable.", strerror(errno), errno); } return result; } }}} // namespace facter::facts::osx facter-3.14.12/lib/src/facts/osx/system_profiler_resolver.cc0000644005276200011600000000642313702047406023752 0ustar jenkinsjenkins#include #include #include #include #include using namespace std; using namespace facter::facts; using namespace leatherman::execution; namespace facter { namespace facts { namespace osx { system_profiler_resolver::data system_profiler_resolver::collect_data(collection& facts) { static map> data_map = { { "Boot Mode", [](data& d) -> string& { return d.boot_mode; } }, { "Boot ROM Version", [](data& d) -> string& { return d.boot_rom_version; } }, { "Boot Volume", [](data& d) -> string& { return d.boot_volume; } }, { "Processor Name", [](data& d) -> string& { return d.processor_name; } }, { "Processor Speed", [](data& d) -> string& { return d.processor_speed; } }, { "Kernel Version", [](data& d) -> string& { return d.kernel_version; } }, { "L2 Cache (per Core)", [](data& d) -> string& { return d.l2_cache_per_core; } }, { "L3 Cache", [](data& d) -> string& { return d.l3_cache; } }, { "Computer Name", [](data& d) -> string& { return d.computer_name; } }, { "Model Identifier", [](data& d) -> string& { return d.model_identifier; } }, { "Model Name", [](data& d) -> string& { return d.model_name; } }, { "Total Number of Cores", [](data& d) -> string& { return d.cores; } }, { "System Version", [](data& d) -> string& { return d.system_version; } }, { "Number of Processors", [](data& d) -> string& { return d.processors; } }, { "Memory", [](data& d) -> string& { return d.memory; } }, { "Hardware UUID", [](data& d) -> string& { return d.hardware_uuid; } }, { "Secure Virtual Memory", [](data& d) -> string& { return d.secure_virtual_memory; } }, { "Serial Number (system)", [](data& d) -> string& { return d.serial_number; } }, { "SMC Version (system)", [](data& d) -> string& { return d.smc_version; } }, { "Time since boot", [](data& d) -> string& { return d.uptime; } }, { "User Name", [](data& d) -> string& { return d.username; } } }; data result; size_t count = 0; each_line("/usr/sbin/system_profiler", { "SPSoftwareDataType", "SPHardwareDataType" }, [&](string& line) { // Split at the first ':' auto pos = line.find(':'); if (pos == string::npos) { return true; } string key = line.substr(0, pos); boost::trim(key); string value = line.substr(pos + 1); boost::trim(value); // Lookup the data based on the "key" auto it = data_map.find(key); if (it == data_map.end()) { return true; } it->second(result) = move(value); // Continue only if we haven't collected all the data return ++count < data_map.size(); }); return result; } }}} // namespace facter::facts::osx facter-3.14.12/lib/src/facts/osx/virtualization_resolver.cc0000644005276200011600000000267513702047406023615 0ustar jenkinsjenkins#include #include #include #include #include #include #include using namespace std; using namespace facter::facts; using namespace leatherman::execution; namespace facter { namespace facts { namespace osx { string virtualization_resolver::get_hypervisor(collection& facts) { // Check for VMWare auto machine_model = facts.get(fact::sp_machine_model); if (machine_model) { if (boost::starts_with(machine_model->value(), "VMware")) { return vm::vmware; } } // Check for VirtualBox auto boot_rom_version = facts.get(fact::sp_boot_rom_version); if (boot_rom_version) { if (boot_rom_version->value() == "VirtualBox") { return vm::virtualbox; } } // Check for Parallels string value; each_line("/usr/sbin/system_profiler", { "SPEthernetDataType" }, [&](string& line) { boost::trim(line); if (line == "Subsystem Vendor ID: 0x1ab8") { value = vm::parallels; return false; } return true; }); return value; } }}} // namespace facter::facts::osx facter-3.14.12/lib/src/facts/posix/0000755005276200011600000000000013702047635016624 5ustar jenkinsjenkinsfacter-3.14.12/lib/src/facts/posix/cache.cc0000644005276200011600000000036013702047406020171 0ustar jenkinsjenkins#include namespace facter { namespace facts { namespace cache { std::string fact_cache_location() { return "/opt/puppetlabs/facter/cache/cached_facts/"; } }}} // namespace facter::facts::cache facter-3.14.12/lib/src/facts/posix/collection.cc0000644005276200011600000000173213702047406021265 0ustar jenkinsjenkins#include #include #include #include #include #include #include using namespace std; using namespace leatherman::util; using namespace facter::facts::external; namespace facter { namespace facts { vector collection::get_external_fact_directories() const { vector directories; if (getuid()) { string home; if (environment::get("HOME", home)) { directories.emplace_back(home + "/.puppetlabs/opt/facter/facts.d"); directories.emplace_back(home + "/.facter/facts.d"); } } else { directories.emplace_back("/opt/puppetlabs/facter/facts.d"); directories.emplace_back("/etc/facter/facts.d"); directories.emplace_back("/etc/puppetlabs/facter/facts.d"); } return directories; } }} // namespace facter::facts facter-3.14.12/lib/src/facts/posix/external_resolvers_factory.cc0000644005276200011600000000075613702047406024614 0ustar jenkinsjenkins#include #include using namespace std; namespace facter { namespace facts { shared_ptr external_resolvers_factory::get_resolver(const string& path) { auto resolver = get_common_resolver(path); if (resolver) return resolver; throw external::external_fact_no_resolver(leatherman::locale::_("No resolver for external facts file {1}", path)); } }} // facter::facts facter-3.14.12/lib/src/facts/posix/identity_resolver.cc0000644005276200011600000000432413702047406022704 0ustar jenkinsjenkins#include #include #include #include #include #include using namespace std; namespace facter { namespace facts { namespace posix { identity_resolver::data identity_resolver::collect_data(collection& facts) { data result; vector buffer; long buffer_size = sysconf(_SC_GETPW_R_SIZE_MAX); if (buffer_size == -1) { buffer.resize(1024); } else { buffer.resize(buffer_size); } uid_t uid = geteuid(); struct passwd pwd; struct passwd *pwd_ptr; int err = -1; do { err = getpwuid_r(uid, &pwd, buffer.data(), buffer.size(), &pwd_ptr); if (err == ERANGE) { buffer.resize(buffer.size() + 1024); } } while (err == EINTR || err == ERANGE); if (err != 0) { LOG_WARNING("getpwuid_r failed: {1} ({2})", strerror(err), err); } else if (pwd_ptr == NULL) { LOG_WARNING("effective uid {1} does not have a passwd entry.", uid); } else { result.user_id = static_cast(uid); result.user_name = pwd.pw_name; result.privileged = (uid == 0); } buffer_size = sysconf(_SC_GETGR_R_SIZE_MAX); if (buffer_size == -1) { buffer.resize(1024); } else { buffer.resize(buffer_size); } gid_t gid = getegid(); struct group grp; struct group *grp_ptr; do { err = getgrgid_r(gid, &grp, buffer.data(), buffer.size(), &grp_ptr); if (err == ERANGE) { buffer.resize(buffer.size() + 1024); } } while (err == EINTR || err == ERANGE); if (err != 0) { LOG_WARNING("getgrgid_r failed: {1} ({2})", strerror(err), err); } else if (grp_ptr == NULL) { LOG_WARNING("effective gid {1} does not have a group entry.", gid); } else { result.group_id = static_cast(gid); result.group_name = grp.gr_name; } return result; } }}} // facter::facts::posix facter-3.14.12/lib/src/facts/posix/kernel_resolver.cc0000644005276200011600000000140013702047406022323 0ustar jenkinsjenkins#include #include #include #include using namespace std; namespace facter { namespace facts { namespace posix { kernel_resolver::data kernel_resolver::collect_data(collection& facts) { data result; struct utsname name; if (uname(&name) == -1) { LOG_WARNING("uname failed: {1} ({2}): kernel facts are unavailable.", strerror(errno), errno); return result; } result.name = name.sysname; result.release = name.release; result.version = result.release.substr(0, result.release.find('-')); return result; } }}} // namespace facter::facts::posix facter-3.14.12/lib/src/facts/posix/networking_resolver.cc0000644005276200011600000001315013702047406023237 0ustar jenkinsjenkins#include #include #include #include #include #include #include #include #include using namespace std; using namespace facter::util::posix; namespace lth_file = leatherman::file_util; namespace facter { namespace facts { namespace posix { string networking_resolver::address_to_string(sockaddr const* addr, sockaddr const* mask) const { if (!addr) { return {}; } // Check for IPv4 and IPv6 if (addr->sa_family == AF_INET) { in_addr ip = reinterpret_cast(addr)->sin_addr; // Apply an IPv4 mask if (mask && mask->sa_family == addr->sa_family) { ip.s_addr &= reinterpret_cast(mask)->sin_addr.s_addr; } char buffer[INET_ADDRSTRLEN] = {}; inet_ntop(AF_INET, &ip, buffer, sizeof(buffer)); return buffer; } else if (addr->sa_family == AF_INET6) { in6_addr ip = reinterpret_cast(addr)->sin6_addr; // Apply an IPv6 mask if (mask && mask->sa_family == addr->sa_family) { auto mask_ptr = reinterpret_cast(mask); for (size_t i = 0; i < 16; ++i) { ip.s6_addr[i] &= mask_ptr->sin6_addr.s6_addr[i]; } } char buffer[INET6_ADDRSTRLEN] = {}; inet_ntop(AF_INET6, &ip, buffer, sizeof(buffer)); return buffer; } else if (is_link_address(addr)) { auto link_addr = get_link_address_bytes(addr); uint8_t link_addr_len = get_link_address_length(addr); if (link_addr) { return macaddress_to_string(reinterpret_cast(link_addr), link_addr_len); } } return {}; } networking_resolver::data networking_resolver::collect_data(collection& facts) { data result; // Get the maximum size of the host name int size = sysconf(_SC_HOST_NAME_MAX); if (size <= 0) { size = 1024; } // Get the hostname (+1 to ensure a null is returned on platforms where maximum truncation may occur) vector name(size + 1); if (gethostname(name.data(), size + 1) != 0) { LOG_WARNING("gethostname failed: {1} ({2}): hostname is unavailable.", strerror(errno), errno); } else { // Check for fully-qualified hostname auto it = find(name.begin(), name.end(), '.'); if (it != name.end()) { LOG_DEBUG("using the FQDN returned by gethostname: {1}.", name.data()); result.hostname.assign(name.begin(), it); if (++it != name.end()) { // Use the remainder of the string, up to the first null character result.domain = &*it; } } else { // Not fully qualified; just set hostname result.hostname = name.data(); } } // If the hostname was not already fully qualified, attempt to resolve it if (result.domain.empty() && !result.hostname.empty()) { // Retrieve the FQDN by resolving the hostname scoped_addrinfo info(result.hostname); if (info.result() != 0 && info.result() != EAI_NONAME) { LOG_WARNING("getaddrinfo failed: {1} ({2}): hostname may not be externally resolvable.", gai_strerror(info.result()), info.result()); } else if (!info || info.result() == EAI_NONAME || !static_cast(info)->ai_canonname || result.hostname == static_cast(info)->ai_canonname) { LOG_DEBUG("hostname \"{1}\" could not be resolved: hostname may not be externally resolvable.", result.hostname); } else { result.fqdn = static_cast(info)->ai_canonname; } // Set the domain name if the FQDN is prefixed with the hostname if (boost::starts_with(result.fqdn, result.hostname + ".")) { result.domain = result.fqdn.substr(result.hostname.size() + 1); } } // If no domain, look it up based on resolv.conf if (result.domain.empty()) { string search; lth_file::each_line("/etc/resolv.conf", [&](string& line) { vector> parts; boost::split(parts, line, boost::is_space(), boost::token_compress_on); if (parts.size() < 2) { return true; } if (parts[0] == boost::as_literal("domain")) { // Treat the first domain entry as the domain result.domain.assign(parts[1].begin(), parts[1].end()); return false; } if (search.empty() && parts[0] == boost::as_literal("search")) { // Found a "search" entry, but keep looking for other domain entries // We use the first search domain as the domain. search.assign(parts[1].begin(), parts[1].end()); return true; } return true; }); if (result.domain.empty()) { result.domain = move(search); } } return result; } }}} // namespace facter::facts::posix facter-3.14.12/lib/src/facts/posix/operatingsystem_resolver.cc0000644005276200011600000000173613702047406024314 0ustar jenkinsjenkins#include #include #include #include using namespace std; using namespace leatherman::execution; namespace facter { namespace facts { namespace posix { operating_system_resolver::data operating_system_resolver::collect_data(collection& facts) { // Default to the base implementation data result = resolvers::operating_system_resolver::collect_data(facts); struct utsname name; memset(&name, 0, sizeof(name)); if (uname(&name) == -1) { LOG_DEBUG("uname failed: {1} ({2}): OS hardware is unavailable.", strerror(errno), errno); } else { result.hardware = name.machine; } // By default, the architecture is the same as the hardware model result.architecture = result.hardware; return result; } }}} // namespace facter::facts::posix facter-3.14.12/lib/src/facts/posix/processor_resolver.cc0000644005276200011600000000123413702047406023067 0ustar jenkinsjenkins#include #include #include using namespace std; using namespace leatherman::execution; namespace facter { namespace facts { namespace posix { processor_resolver::data processor_resolver::collect_data(collection& facts) { data result; // Unfortunately there's no corresponding member in utsname for "processor", so we need to spawn auto exec = execute("uname", { "-p" }); if (exec.success) { result.isa = exec.output; } return result; } }}} // namespace facter::facts::posix facter-3.14.12/lib/src/facts/posix/ssh_resolver.cc0000644005276200011600000000161413702047406021647 0ustar jenkinsjenkins#pragma clang diagnostic ignored "-Wdeprecated-declarations" #include using namespace std; using namespace boost::filesystem; namespace bs = boost::system; namespace facter { namespace facts { path ssh_resolver::retrieve_key_file(string const& filename) { path key_file; static vector const search_directories = { "/etc/ssh", "/usr/local/etc/ssh", "/etc", "/usr/local/etc", "/etc/opt/ssh" }; for (auto const& directory : search_directories) { key_file = directory; key_file /= filename; bs::error_code ec; if (!is_regular_file(key_file, ec)) { key_file.clear(); continue; } break; } return key_file; } }} // namespace facter::facts facter-3.14.12/lib/src/facts/posix/timezone_resolver.cc0000644005276200011600000000133213702047406022701 0ustar jenkinsjenkins#include #include #include using namespace std; namespace facter { namespace facts { namespace posix { string timezone_resolver::get_timezone() { time_t since_epoch = time(NULL); tm localtime; char buffer[16]; if (!::localtime_r(&since_epoch, &localtime)) { LOG_WARNING("localtime_r failed: timezone is unavailable."); return {}; } if (::strftime(buffer, sizeof(buffer), "%Z", &localtime) == 0) { LOG_WARNING("strftime failed: timezone is unavailable."); return {}; } return buffer; } }}} // facter::facts::posix facter-3.14.12/lib/src/facts/posix/uptime_resolver.cc0000644005276200011600000000563113702047406022360 0ustar jenkinsjenkins#include #ifdef HAVE_UTMPX_H #include #endif #include #include #include #include #include // Mark string for translation (alias for leatherman::locale::format) using leatherman::locale::_; using namespace std; using namespace leatherman::util; using namespace leatherman::execution; #ifdef HAVE_UTMPX_H using namespace facter::util::posix; #endif namespace facter { namespace facts { namespace posix { int64_t uptime_resolver::parse_uptime(string const& output) { // This regex parsing is directly ported from facter: // https://github.com/puppetlabs/facter/blob/2.0.1/lib/facter/util/uptime.rb#L42-L60 static boost::regex days_hours_mins_pattern("(\\d+) day(?:s|\\(s\\))?,?\\s+(\\d+):-?(\\d+)"); static boost::regex days_hours_pattern("(\\d+) day(?:s|\\(s\\))?,\\s+(\\d+) hr(?:s|\\(s\\))?,"); static boost::regex days_mins_pattern("(\\d+) day(?:s|\\(s\\))?,\\s+(\\d+) min(?:s|\\(s\\))?,"); static boost::regex days_pattern("(\\d+) day(?:s|\\(s\\))?,"); static boost::regex hours_mins_pattern("up\\s+(\\d+):-?(\\d+),"); static boost::regex hours_pattern("(\\d+) hr(?:s|\\(s\\))?,"); static boost::regex mins_pattern("(\\d+) min(?:s|\\(s\\))?,"); int days, hours, minutes; if (re_search(output, days_hours_mins_pattern, &days, &hours, &minutes)) { return 86400ll * days + 3600ll * hours + 60ll * minutes; } else if (re_search(output, days_hours_pattern, &days, &hours)) { return 86400ll * days + 3600ll * hours; } else if (re_search(output, days_mins_pattern, &days, &minutes)) { return 86400ll * days + 60ll * minutes; } else if (re_search(output, days_pattern, &days)) { return 86400ll * days; } else if (re_search(output, hours_mins_pattern, &hours, &minutes)) { return 3600ll * hours + 60ll * minutes; } else if (re_search(output, hours_pattern, &hours)) { return 3600ll * hours; } else if (re_search(output, mins_pattern, &minutes)) { return 60ll * minutes; } return -1; } int64_t uptime_resolver::get_uptime() { #ifdef HAVE_UTMPX_H LOG_DEBUG(_("Attempting to calculate the uptime from the utmpx file")); utmpx query; query.ut_type = BOOT_TIME; utmpx_file file; auto ent = file.query(query); if (ent) { return time(NULL) - ent->ut_tv.tv_sec; } LOG_DEBUG(_("Could not calculate the uptime from the utmpx file")); #endif auto exec = execute("uptime"); if (!exec.success) { return -1; } return parse_uptime(exec.output); } }}} // namespace facter::facts::posix facter-3.14.12/lib/src/facts/posix/xen_resolver.cc0000644005276200011600000000252113702047406021642 0ustar jenkinsjenkins#include #include #include #include using namespace std; using namespace facter::facts; using namespace leatherman::execution; using namespace boost::filesystem; namespace bs = boost::system; namespace facter { namespace facts { namespace posix { string xen_resolver::xen_command() { constexpr char const* xen_toolstack = "/usr/lib/xen-common/bin/xen-toolstack"; bs::error_code ec; if (exists(xen_toolstack, ec) && !ec) { auto exec = execute(xen_toolstack); if (exec.success) { return exec.output; } else { LOG_DEBUG("failure executing {1}: {2}", xen_toolstack, exec.error); return {}; } } else { LOG_TRACE("xen toolstack command not found: {1}", ec.message()); static vector xen_commands{"/usr/sbin/xl", "/usr/sbin/xm"}; for (auto const& cmd : xen_commands) { auto cmd_path = which(cmd); if (!cmd_path.empty()) { return cmd_path; } } LOG_TRACE("no xen commands found"); return {}; } } }}} // namespace facter::facts::posix facter-3.14.12/lib/src/facts/resolver.cc0000644005276200011600000000570413702047406017634 0ustar jenkinsjenkins#include #include #include #include #include #include using namespace std; using namespace leatherman::util; namespace facter { namespace facts { invalid_name_pattern_exception::invalid_name_pattern_exception(string const& message) : runtime_error(message) { } resolver::resolver(string name, vector names, vector const& patterns) : _name(move(name)), _names(move(names)) { for (auto const& pattern : patterns) { try { _regexes.push_back(boost::regex(pattern)); } catch (boost::regex_error const& ex) { throw invalid_name_pattern_exception(ex.what()); } } } resolver::~resolver() { // This needs to be defined here since we use incomplete types in the header } resolver::resolver(resolver&& other) { *this = std::move(other); } resolver& resolver::operator=(resolver&& other) { if (this != &other) { _name = std::move(other._name); _names = std::move(other._names); _regexes = std::move(other._regexes); _http_langs = std::move(other._http_langs); } return *this; } string const& resolver::name() const { return _name; } vector const& resolver::names() const { return _names; } bool resolver::has_patterns() const { return _regexes.size() > 0; } bool resolver::is_match(string const& name) const { // Check to see if any of our regexes match for (auto const& regex : _regexes) { if (re_search(name, regex)) { return true; } } return false; } string const& resolver::http_langs() { #ifdef LEATHERMAN_USE_LOCALES if (_http_langs.empty()) { // build Accept-Language list for HTTP-based resolvers const auto& loc = leatherman::locale::get_locale(); if (std::has_facet(loc)) { const auto& info = std::use_facet(loc); string lang = info.language(); // use country code when available; add fallback to base lang if (!info.country().empty()) lang += "-" + info.country() + ", " + info.language(); // always include English (en) as a fallback if (info.language() != "en") lang += ", en"; std::transform(lang.begin(), lang.end(), lang.begin(), ::tolower); _http_langs = lang; } } #endif return _http_langs; } bool resolver::is_blockable() const { return false; } }} // namespace facter::facts facter-3.14.12/lib/src/facts/resolvers/0000755005276200011600000000000013702047635017506 5ustar jenkinsjenkinsfacter-3.14.12/lib/src/facts/resolvers/augeas_resolver.cc0000644005276200011600000000317213702047406023202 0ustar jenkinsjenkins#include #include #include #include #include #include #include #include #include using namespace std; using namespace facter::util; using namespace leatherman::util; using namespace leatherman::execution; namespace facter { namespace facts { namespace resolvers { augeas_resolver::augeas_resolver() : resolver( "augeas", { fact::augeas, fact::augeasversion, }) { } string augeas_resolver::get_version() { string augparse = agent::which("augparse"); string value; boost::regex regexp("^augparse (\\d+\\.\\d+\\.\\d+)"); // Version info goes on stderr. each_line(augparse, {"--version"}, nullptr, [&](string& line) { if (re_search(line, regexp, &value)) { return false; } return true; }); return value; } void augeas_resolver::resolve(collection& facts) { auto version = get_version(); if (version.empty()) { return; } auto augeas = make_value(); augeas->add("version", make_value(version)); facts.add(fact::augeasversion, make_value(move(version), true)); facts.add(fact::augeas, move(augeas)); } }}} // namespace facter::facts::resolvers facter-3.14.12/lib/src/facts/resolvers/disk_resolver.cc0000644005276200011600000000476113702047406022674 0ustar jenkinsjenkins#include #include #include #include #include #include using namespace std; using namespace facter::util; namespace facter { namespace facts { namespace resolvers { disk_resolver::disk_resolver() : resolver( "disk", { fact::block_devices, fact::disks }, { string("^") + fact::block_device + "_", }) { } void disk_resolver::resolve(collection& facts) { auto data = collect_data(facts); ostringstream names; auto disks = make_value(); for (auto& disk : data.disks) { if (disk.name.empty()) { continue; } auto value = make_value(); if (!disk.vendor.empty()) { facts.add(string(fact::block_device) + "_" + disk.name + "_vendor" , make_value(disk.vendor, true)); value->add("vendor", make_value(move(disk.vendor))); } if (!disk.model.empty()) { facts.add(string(fact::block_device) + "_" + disk.name + "_model" , make_value(disk.model, true)); value->add("model", make_value(move(disk.model))); } if (!disk.product.empty()) { value->add("product", make_value(move(disk.product))); } facts.add(string(fact::block_device) + "_" + disk.name + "_size" , make_value(static_cast(disk.size), true)); value->add("size_bytes", make_value(disk.size)); value->add("size", make_value(si_string(disk.size))); if (!disk.serial_number.empty()) { value->add("serial_number", make_value(move(disk.serial_number))); } if (names.tellp() != 0) { names << ','; } names << disk.name; disks->add(move(disk.name), move(value)); } if (names.tellp() > 0) { facts.add(fact::block_devices, make_value(names.str(), true)); } if (!disks->empty()) { facts.add(fact::disks, move(disks)); } } }}} // namespace facter::facts::resolvers facter-3.14.12/lib/src/facts/resolvers/dmi_resolver.cc0000644005276200011600000001455313702047406022513 0ustar jenkinsjenkins#include #include #include #include #include using namespace std; namespace facter { namespace facts { namespace resolvers { dmi_resolver::dmi_resolver() : resolver( "desktop management interface", { fact::dmi, fact::bios_vendor, fact::bios_version, fact::bios_release_date, fact::board_asset_tag, fact::board_manufacturer, fact::board_product_name, fact::board_serial_number, fact::chassis_asset_tag, fact::manufacturer, fact::product_name, fact::serial_number, fact::uuid, fact::chassis_type, }) { } string dmi_resolver::to_chassis_description(string const& type) { if (type.empty()) { return {}; } static map const descriptions = { { "1", "Other" }, // 2 is Unknown, which we'll output if it's not in the map anyway { "3", "Desktop" }, { "4", "Low Profile Desktop" }, { "5", "Pizza Box" }, { "6", "Mini Tower" }, { "7", "Tower" }, { "8", "Portable" }, { "9", "Laptop" }, { "10", "Notebook" }, { "11", "Hand Held" }, { "12", "Docking Station" }, { "13", "All in One" }, { "14", "Sub Notebook" }, { "15", "Space-Saving" }, { "16", "Lunch Box" }, { "17", "Main System Chassis" }, { "18", "Expansion Chassis" }, { "19", "SubChassis" }, { "20", "Bus Expansion Chassis" }, { "21", "Peripheral Chassis" }, { "22", "Storage Chassis" }, { "23", "Rack Mount Chassis" }, { "24", "Sealed-Case PC" }, { "25", "Multi-system" }, { "26", "CompactPCI" }, { "27", "AdvancedTCA" }, { "28", "Blade" }, { "29", "Blade Enclosure" }, { "30", "Tablet" }, { "31", "Convertible" }, { "32", "Detachable" }, }; auto it = descriptions.find(type); if (it != descriptions.end()) { return it->second; } return "Unknown"; } void dmi_resolver::resolve(collection& facts) { auto data = collect_data(facts); auto dmi = make_value(); auto bios = make_value(); if (!data.bios_vendor.empty()) { facts.add(fact::bios_vendor, make_value(data.bios_vendor, true)); bios->add("vendor", make_value(move(data.bios_vendor))); } if (!data.bios_version.empty()) { facts.add(fact::bios_version, make_value(data.bios_version, true)); bios->add("version", make_value(move(data.bios_version))); } if (!data.bios_release_date.empty()) { facts.add(fact::bios_release_date, make_value(data.bios_release_date, true)); bios->add("release_date", make_value(move(data.bios_release_date))); } auto board = make_value(); if (!data.board_asset_tag.empty()) { facts.add(fact::board_asset_tag, make_value(data.board_asset_tag, true)); board->add("asset_tag", make_value(move(data.board_asset_tag))); } if (!data.board_manufacturer.empty()) { facts.add(fact::board_manufacturer, make_value(data.board_manufacturer, true)); board->add("manufacturer", make_value(move(data.board_manufacturer))); } if (!data.board_product_name.empty()) { facts.add(fact::board_product_name, make_value(data.board_product_name, true)); board->add("product", make_value(move(data.board_product_name))); } if (!data.board_serial_number.empty()) { facts.add(fact::board_serial_number, make_value(data.board_serial_number, true)); board->add("serial_number", make_value(move(data.board_serial_number))); } auto product = make_value(); if (!data.product_name.empty()) { facts.add(fact::product_name, make_value(data.product_name, true)); product->add("name", make_value(move(data.product_name))); } if (!data.serial_number.empty()) { facts.add(fact::serial_number, make_value(data.serial_number, true)); product->add("serial_number", make_value(move(data.serial_number))); } if (!data.uuid.empty()) { facts.add(fact::uuid, make_value(data.uuid, true)); product->add("uuid", make_value(move(data.uuid))); } auto chassis = make_value(); if (!data.chassis_asset_tag.empty()) { facts.add(fact::chassis_asset_tag, make_value(data.chassis_asset_tag, true)); chassis->add("asset_tag", make_value(move(data.chassis_asset_tag))); } if (!data.chassis_type.empty()) { facts.add(fact::chassis_type, make_value(data.chassis_type, true)); chassis->add("type", make_value(move(data.chassis_type))); } if (!data.manufacturer.empty()) { facts.add(fact::manufacturer, make_value(data.manufacturer, true)); dmi->add("manufacturer", make_value(move(data.manufacturer))); } if (!bios->empty()) { dmi->add("bios", move(bios)); } if (!board->empty()) { dmi->add("board", move(board)); } if (!product->empty()) { dmi->add("product", move(product)); } if (!chassis->empty()) { dmi->add("chassis", move(chassis)); } if (!dmi->empty()) { facts.add(fact::dmi, move(dmi)); } } }}} // namespace facter::facts::resolvers facter-3.14.12/lib/src/facts/resolvers/ec2_resolver.cc0000644005276200011600000001421213702047406022403 0ustar jenkinsjenkins#include #include #include #include #include #include #include #include #include #include #include #include #ifdef USE_CURL #include namespace lth_curl = leatherman::curl; #endif using namespace std; using namespace leatherman::util; namespace facter { namespace facts { namespace resolvers { ec2_resolver::ec2_resolver() : resolver( "EC2", { fact::ec2_metadata, fact::ec2_userdata }) { } #ifdef USE_CURL static const char* EC2_METADATA_ROOT_URL = "http://169.254.169.254/latest/meta-data/"; static const char* EC2_USERDATA_ROOT_URL = "http://169.254.169.254/latest/user-data/"; static const unsigned int EC2_CONNECTION_TIMEOUT = 600; #ifdef HAS_LTH_GET_INT static const unsigned int EC2_SESSION_TIMEOUT = environment::get_int("EC2_SESSION_TIMEOUT", 5000); #else static const unsigned int EC2_SESSION_TIMEOUT = 5000; #endif static void query_metadata_value(lth_curl::client& cli, map_value& value, string const& url, string const& name, string const& http_langs) { lth_curl::request req(url + name); req.connection_timeout(EC2_CONNECTION_TIMEOUT); req.timeout(EC2_SESSION_TIMEOUT); if (!http_langs.empty()) req.add_header("Accept-Language", http_langs); auto response = cli.get(req); if (response.status_code() != 200) { LOG_DEBUG("request for {1} returned a status code of {2}.", req.url(), response.status_code()); return; } auto body = response.body(); boost::trim(body); value.add(name, make_value(move(body))); } static void query_metadata(lth_curl::client& cli, map_value& value, string const& url, string const& http_langs) { // Stores the metadata names to filter out static set filter = { "security-credentials/" }; lth_curl::request req(url); req.connection_timeout(EC2_CONNECTION_TIMEOUT); req.timeout(EC2_SESSION_TIMEOUT); if (!http_langs.empty()) req.add_header("Accept-Language", http_langs); auto response = cli.get(req); if (response.status_code() != 200) { LOG_DEBUG("request for {1} returned a status code of {2}.", req.url(), response.status_code()); return; } util::each_line(response.body(), [&](string& name) { if (name.empty()) { return true; } static boost::regex array_regex("^(\\d+)=.*$"); string index; if (re_search(name, array_regex, &index)) { name = index + "/"; } // Check the filter for this name if (filter.count(name) != 0) { return true; } // If the name does not end with a '/', then it is a key name; request the value if (name.back() != '/') { query_metadata_value(cli, value, url, name, http_langs); return true; } // Otherwise, this is a category; recurse down it auto child = make_value(); query_metadata(cli, *child, url + name, http_langs); trim_right_if(name, boost::is_any_of("/")); value.add(move(name), move(child)); return true; }); } #endif void ec2_resolver::resolve(collection& facts) { #ifndef USE_CURL LOG_INFO("EC2 facts are unavailable: facter was built without libcurl support."); return; #else auto virtualization = facts.get(fact::virtualization); if (!virtualization || (virtualization->value() != vm::kvm && !boost::starts_with(virtualization->value(), "xen"))) { LOG_DEBUG("EC2 facts are unavailable: not running under an EC2 instance."); return; } LOG_DEBUG("querying EC2 instance metadata at {1}.", EC2_METADATA_ROOT_URL); lth_curl::client cli; auto metadata = make_value(); try { query_metadata(cli, *metadata, EC2_METADATA_ROOT_URL, http_langs()); if (!metadata->empty()) { facts.add(fact::ec2_metadata, move(metadata)); } } catch (lth_curl::http_request_exception& ex) { if (ex.req().url() == EC2_METADATA_ROOT_URL) { // The very first query failed; most likely not an EC2 instance LOG_DEBUG("EC2 facts are unavailable: not running under an EC2 instance or EC2 is not responding in a timely manner."); LOG_TRACE("EC2 metadata request failed: {1}", ex.what()); return; } LOG_ERROR("EC2 metadata request failed: {1}", ex.what()); } catch (runtime_error& ex) { LOG_ERROR("EC2 metadata request failed: {1}", ex.what()); } LOG_DEBUG("querying EC2 instance user data at {1}.", EC2_USERDATA_ROOT_URL); try { lth_curl::request req(EC2_USERDATA_ROOT_URL); req.connection_timeout(EC2_CONNECTION_TIMEOUT); req.timeout(EC2_SESSION_TIMEOUT); if (!http_langs().empty()) req.add_header("Accept-Language", http_langs()); auto response = cli.get(req); if (response.status_code() != 200) { LOG_DEBUG("request for {1} returned a status code of {2}.", req.url(), response.status_code()); return; } facts.add(fact::ec2_userdata, make_value(response.body())); } catch (runtime_error& ex) { LOG_ERROR("EC2 user data request failed: {1}", ex.what()); } #endif } bool ec2_resolver::is_blockable() const { return true; } }}} // namespace facter::facts::resolvers facter-3.14.12/lib/src/facts/resolvers/filesystem_resolver.cc0000644005276200011600000001141613702047406024121 0ustar jenkinsjenkins#include #include #include #include #include #include #include #include using namespace std; using namespace facter::util; namespace facter { namespace facts { namespace resolvers { filesystem_resolver::filesystem_resolver() : resolver( "file system", { fact::mountpoints, fact::filesystems, fact::partitions }) { } void filesystem_resolver::resolve(collection& facts) { auto data = collect_data(facts); // Populate the mountpoints fact if (!data.mountpoints.empty()) { auto mountpoints = make_value(); for (auto& mountpoint : data.mountpoints) { if (mountpoint.name.empty()) { continue; } uint64_t used = mountpoint.size - mountpoint.free; uint64_t total = used + mountpoint.available; auto value = make_value(); if (!mountpoint.filesystem.empty()) { value->add("filesystem", make_value(move(mountpoint.filesystem))); } if (!mountpoint.device.empty()) { value->add("device", make_value(move(mountpoint.device))); } value->add("size_bytes", make_value(mountpoint.size)); value->add("size", make_value(si_string(mountpoint.size))); value->add("available_bytes", make_value(mountpoint.available)); value->add("available", make_value(si_string(mountpoint.available))); value->add("used_bytes", make_value(used)); value->add("used", make_value(si_string(used))); value->add("capacity", make_value(percentage(used, total))); if (!mountpoint.options.empty()) { auto options = make_value(); for (auto &option : mountpoint.options) { options->add(make_value(move(option))); } value->add("options", move(options)); } mountpoints->add(move(mountpoint.name), move(value)); } facts.add(fact::mountpoints, move(mountpoints)); } // Populate the filesystems fact if (!data.filesystems.empty()) { facts.add(fact::filesystems, make_value(boost::join(data.filesystems, ","))); } // Populate the partitions fact if (!data.partitions.empty()) { auto partitions = make_value(); for (auto& partition : data.partitions) { if (partition.name.empty()) { continue; } auto value = make_value(); if (!partition.filesystem.empty()) { value->add("filesystem", make_value(move(partition.filesystem))); } if (!partition.mount.empty()) { value->add("mount", make_value(move(partition.mount))); } if (!partition.label.empty()) { value->add("label", make_value(move(partition.label))); } if (!partition.partition_label.empty()) { value->add("partlabel", make_value(move(partition.partition_label))); } if (!partition.uuid.empty()) { value->add("uuid", make_value(move(partition.uuid))); } if (!partition.partition_uuid.empty()) { value->add("partuuid", make_value(move(partition.partition_uuid))); } if (!partition.backing_file.empty()) { value->add("backing_file", make_value(move(partition.backing_file))); } value->add("size_bytes", make_value(partition.size)); value->add("size", make_value(si_string(partition.size))); partitions->add(move(partition.name), move(value)); } facts.add(fact::partitions, move(partitions)); } } bool filesystem_resolver::is_blockable() const { return true; } }}} // namespace facter::facts::resolvers facter-3.14.12/lib/src/facts/resolvers/fips_resolver.cc0000644005276200011600000000122113702047406022667 0ustar jenkinsjenkins#include #include #include #include #include using namespace std; using namespace facter::facts; namespace facter { namespace facts { namespace resolvers { fips_resolver::fips_resolver() : resolver("fips", {fact::fips_enabled}) { } void fips_resolver::resolve(collection& facts) { auto data = collect_data(facts); facts.add(fact::fips_enabled, make_value(data.is_fips_mode_enabled)); } }}} // namespace facter::facts::resolvers facter-3.14.12/lib/src/facts/resolvers/gce_resolver.cc0000644005276200011600000002011413702047406022466 0ustar jenkinsjenkins#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include // Mark string for translation (alias for leatherman::locale::format) using leatherman::locale::_; #ifdef USE_CURL #include #include #include namespace lth_curl = leatherman::curl; #endif using namespace std; using namespace rapidjson; namespace facter { namespace facts { namespace resolvers { #ifdef USE_CURL static const unsigned int GCE_CONNECTION_TIMEOUT = 1000; static const unsigned int GCE_SESSION_TIMEOUT = 5000; #endif // Helper event handler for parsing JSON data struct gce_event_handler { explicit gce_event_handler(map_value& root) : _initialized(false), _root(root) { } bool Null() { check_initialized(); _key.clear(); return true; } bool Bool(bool b) { add_value(make_value(b)); return true; } bool Int(int i) { Uint64(static_cast(i)); return true; } bool Uint(unsigned int i) { Uint64(static_cast(i)); return true; } bool Int64(int64_t i) { Uint64(static_cast(i)); return true; } bool Uint64(uint64_t i) { add_value(make_value(i)); return true; } bool Double(double d) { add_value(make_value(d)); return true; } bool String(char const* s, SizeType len, bool copy) { string value(s, len); // See https://cloud.google.com/compute/docs/metadata for information about these values if (_key == "sshKeys") { // The sshKeys attribute is a list of SSH keys delimited by newline characters // Turn this value into an array for the fact // Trim any whitespace off the string before splitting boost::trim(value); // Split at newlines and transform into an array value vector keys; boost::split(keys, value, boost::is_any_of("\n"), boost::token_compress_on); auto array = make_value(); for (auto& key : keys) { array->add(make_value(move(key))); } add_value(move(array)); return true; } if (_key == "image" || _key == "machineType" || _key == "zone" || _key == "network") { // These values are fully qualified, but we only want to display the last name // Therefore, use only what comes after the last / character auto pos = value.find_last_of('/'); if (pos != string::npos) { value = value.substr(pos + 1); } } add_value(make_value(move(value))); return true; } bool Key(const char* str, SizeType length, bool copy) { check_initialized(); _key = string(str, length); return true; } bool StartObject() { if (!_initialized) { _initialized = true; return true; } // Push a map onto the stack _stack.emplace(make_tuple(move(_key), make_value())); return true; } bool EndObject(SizeType count) { // Check to see if the stack is empty since we don't push for the top-level object if (_stack.empty()) { return true; } // Pop the data off the stack auto top = move(_stack.top()); _stack.pop(); // Restore the key and add the value _key = move(get<0>(top)); add_value(move(get<1>(top))); return true; } bool StartArray() { check_initialized(); // Push an array onto the stack _stack.emplace(make_tuple(move(_key), make_value())); return true; } bool EndArray(SizeType count) { // Pop the data off the stack auto top = move(_stack.top()); _stack.pop(); // Restore the key and add the value _key = move(get<0>(top)); add_value(move(get<1>(top))); return true; } private: template void add_value(unique_ptr&& val) { check_initialized(); value* current = nullptr; if (_stack.empty()) { current = &_root; } else { current = get<1>(_stack.top()).get(); } auto map = dynamic_cast(current); if (map) { if (_key.empty()) { throw external::external_fact_exception(_("expected non-empty key in object.")); } map->add(move(_key), move(val)); return; } auto array = dynamic_cast(current); if (array) { array->add(move(val)); return; } } void check_initialized() const { if (!_initialized) { throw external::external_fact_exception(_("expected document to contain an object.")); } } bool _initialized; map_value& _root; string _key; stack>> _stack; }; gce_resolver::gce_resolver() : resolver("GCE", { fact::gce }) { } void gce_resolver::resolve(collection& facts) { auto virtualization = facts.get(fact::virtualization); if (!virtualization || virtualization->value() != vm::gce) { LOG_DEBUG("not running under a GCE instance."); return; } #ifndef USE_CURL LOG_INFO("GCE facts are unavailable: facter was built without libcurl support."); return; #else LOG_DEBUG("querying GCE metadata."); try { lth_curl::request req("http://metadata.google.internal/computeMetadata/v1/?recursive=true&alt=json"); req.add_header("Metadata-Flavor", "Google"); req.connection_timeout(GCE_CONNECTION_TIMEOUT); req.timeout(GCE_SESSION_TIMEOUT); if (!http_langs().empty()) req.add_header("Accept-Language", http_langs()); lth_curl::client cli; auto response = cli.get(req); if (response.status_code() != 200) { LOG_DEBUG("request for {1} returned a status code of {2}.", req.url(), response.status_code()); return; } auto data = make_value(); Reader reader; StringStream ss(response.body().c_str()); gce_event_handler handler(*data); auto result = reader.Parse(ss, handler); if (!result) { LOG_ERROR("failed to parse GCE metadata: {1}.", GetParseError_En(result.Code())); return; } if (!data->empty()) { facts.add(fact::gce, move(data)); } } catch (runtime_error& ex) { LOG_ERROR("GCE metadata request failed: {1}", ex.what()); } #endif } }}} // namespace facter::facts::resolvers facter-3.14.12/lib/src/facts/resolvers/hypervisors_resolver.cc0000644005276200011600000000423213702047406024330 0ustar jenkinsjenkins#include #include #ifdef USE_WHEREAMI #include #endif using namespace std; using namespace facter::facts; namespace facter { namespace facts { namespace resolvers { using value_ptr = std::unique_ptr; /** * Raw pointers must be extracted here because old versions of boost don't allow visitors to return move-only types. */ struct metadata_value_visitor : public boost::static_visitor { value* operator()(int value) const { return make_value(value).release(); } value* operator()(const std::string& value) const { return make_value(value).release(); } value* operator()(bool value) const { return make_value(value).release(); } }; void hypervisors_resolver_base::resolve(collection& facts) { auto data = collect_data(facts); auto hypervisors = make_value(); for (auto const& hypervisor_pair : data) { auto hypervisor_metadata = make_value(); for (auto const& metadata_pair : hypervisor_pair.second) { value* the_value = boost::apply_visitor(metadata_value_visitor(), metadata_pair.second); hypervisor_metadata->add( metadata_pair.first, unique_ptr(the_value)); } hypervisors->add(hypervisor_pair.first, move(hypervisor_metadata)); } if (!hypervisors->empty()) { facts.add(fact::hypervisors, move(hypervisors)); } } #ifdef USE_WHEREAMI hypervisor_data hypervisors_resolver::collect_data(collection& facts) { hypervisor_data data; auto results = whereami::hypervisors(); for (auto const& res : results) { data.insert({res.name(), res.metadata()}); } return data; } #endif bool hypervisors_resolver_base::is_blockable() const { return true; } }}} // namespace facter::facts::resolvers facter-3.14.12/lib/src/facts/resolvers/identity_resolver.cc0000644005276200011600000000305313702047406023564 0ustar jenkinsjenkins#include #include #include #include #include using namespace std; namespace facter { namespace facts { namespace resolvers { identity_resolver::identity_resolver() : resolver( "id", { fact::id, fact::gid, fact::identity }) { } void identity_resolver::resolve(collection &facts) { auto data = collect_data(facts); auto identity = make_value(); if (!data.user_name.empty()) { facts.add(fact::id, make_value(data.user_name, true)); identity->add("user", make_value(move(data.user_name))); } if (data.user_id) { identity->add("uid", make_value(*data.user_id)); } if (!data.group_name.empty()) { facts.add(fact::gid, make_value(data.group_name, true)); identity->add("group", make_value(move(data.group_name))); } if (data.group_id) { identity->add("gid", make_value(*data.group_id)); } if (data.privileged) { identity->add("privileged", make_value(*data.privileged)); } if (!identity->empty()) { facts.add(fact::identity, move(identity)); } } }}} // facter::facts::resolvers facter-3.14.12/lib/src/facts/resolvers/kernel_resolver.cc0000644005276200011600000000363413702047406023220 0ustar jenkinsjenkins#include #include #include #include #include using namespace std; namespace facter { namespace facts { namespace resolvers { kernel_resolver::kernel_resolver() : resolver( "kernel", { fact::kernel, fact::kernel_version, fact::kernel_release, fact::kernel_major_version }) { } void kernel_resolver::resolve(collection& facts) { auto data = collect_data(facts); if (!data.name.empty()) { facts.add(fact::kernel, make_value(move(data.name))); } if (!data.release.empty()) { facts.add(fact::kernel_release, make_value(move(data.release))); } if (!data.version.empty()) { string major, minor; tie(major, minor) = parse_version(data.version); if (!major.empty()) { facts.add(fact::kernel_major_version, make_value(move(major))); } if (!minor.empty()) { // TODO: for use in a structured fact; no point adding a new flat fact for it } facts.add(fact::kernel_version, make_value(move(data.version))); } } tuple kernel_resolver::parse_version(string const& version) const { auto pos = version.find('.'); if (pos != string::npos) { auto second = version.find('.', pos + 1); if (second != string::npos) { pos = second; } return make_tuple(version.substr(0, pos), version.substr(pos + 1)); } return make_tuple(move(version), string()); } }}} // namespace facter::facts::resolvers facter-3.14.12/lib/src/facts/resolvers/ldom_resolver.cc0000644005276200011600000000352213702047406022667 0ustar jenkinsjenkins#include #include #include #include #include using namespace std; using namespace facter::facts; namespace facter { namespace facts { namespace resolvers { ldom_resolver::ldom_resolver() : resolver( "ldom", { fact::ldom, }, { string("^ldom_"), }) { } void ldom_resolver::resolve(collection& facts) { auto data = collect_data(facts); if (!data.ldom.empty()) { auto ldom = make_value(); for (auto& sub_key : data.ldom) { if (sub_key.values.size() == 0) { continue; } else if (sub_key.values.size() == 1) { string key = sub_key.values.begin()->first; string value = sub_key.values.begin()->second; ldom->add(key, make_value(value)); facts.add("ldom_" + key, make_value(move(value), true)); } else { // If we have multiple sub key values, insert a map into the structured fact to contain them. auto sub_value = make_value(); for (auto& kv : sub_key.values) { sub_value->add(kv.first, make_value(kv.second)); facts.add("ldom_" + sub_key.key + "_" + move(kv.first), make_value(move(kv.second), true)); } ldom->add(sub_key.key, move(sub_value)); } } facts.add(fact::ldom, move(ldom)); } } }}} // namespace facter::facts facter-3.14.12/lib/src/facts/resolvers/load_average_resolver.cc0000644005276200011600000000203213702047406024340 0ustar jenkinsjenkins#include #include #include #include #include using namespace std; namespace facter { namespace facts { namespace resolvers { load_average_resolver::load_average_resolver() : resolver( "load_average", { fact::load_averages, } ) { } void load_average_resolver::resolve(collection& facts) { /* Get the load averages */ auto averages = get_load_averages(); if (!averages) { return; } auto value = make_value(); value->add("1m", make_value(get<0>(*averages))); value->add("5m", make_value(get<1>(*averages))); value->add("15m", make_value(get<2>(*averages))); facts.add(fact::load_averages, move(value)); } }}} // namespace facter::facts::resolvers facter-3.14.12/lib/src/facts/resolvers/memory_resolver.cc0000644005276200011600000001002113702047406023234 0ustar jenkinsjenkins#include #include #include #include #include #include using namespace std; using namespace facter::util; namespace facter { namespace facts { namespace resolvers { memory_resolver::memory_resolver() : resolver( "memory", { fact::memory, fact::memoryfree, fact::memoryfree_mb, fact::memorysize, fact::memorysize_mb, fact::swapfree, fact::swapfree_mb, fact::swapsize, fact::swapsize_mb, fact::swapencrypted }) { } void memory_resolver::resolve(collection& facts) { data result = collect_data(facts); auto value = make_value(); if (result.mem_total > 0) { uint64_t mem_used = result.mem_total - result.mem_free; auto stats = make_value(); stats->add("total", make_value(si_string(result.mem_total))); stats->add("total_bytes", make_value(result.mem_total)); stats->add("used", make_value(si_string(mem_used))); stats->add("used_bytes", make_value(mem_used)); stats->add("available", make_value(si_string(result.mem_free))); stats->add("available_bytes", make_value(result.mem_free)); stats->add("capacity", make_value(percentage(mem_used, result.mem_total))); value->add("system", move(stats)); // Add hidden facts facts.add(fact::memoryfree, make_value(si_string(result.mem_free), true)); facts.add(fact::memoryfree_mb, make_value(result.mem_free / (1024.0 * 1024.0), true)); facts.add(fact::memorysize, make_value(si_string(result.mem_total), true)); facts.add(fact::memorysize_mb, make_value(result.mem_total / (1024.0 * 1024.0), true)); } if (result.swap_total > 0) { uint64_t swap_used = result.swap_total - result.swap_free; auto stats = make_value(); stats->add("total", make_value(si_string(result.swap_total))); stats->add("total_bytes", make_value(result.swap_total)); stats->add("used", make_value(si_string(swap_used))); stats->add("used_bytes", make_value(swap_used)); stats->add("available", make_value(si_string(result.swap_free))); stats->add("available_bytes", make_value(result.swap_free)); stats->add("capacity", make_value(percentage(swap_used, result.swap_total))); if (result.swap_encryption != encryption_status::unknown) { stats->add("encrypted", make_value(result.swap_encryption == encryption_status::encrypted)); } value->add("swap", move(stats)); // Add hidden facts facts.add(fact::swapfree, make_value(si_string(result.swap_free), true)); facts.add(fact::swapfree_mb, make_value(result.swap_free / (1024.0 * 1024.0), true)); facts.add(fact::swapsize, make_value(si_string(result.swap_total), true)); facts.add(fact::swapsize_mb, make_value(result.swap_total / (1024.0 * 1024.0), true)); if (result.swap_encryption != encryption_status::unknown) { facts.add(fact::swapencrypted, make_value(result.swap_encryption == encryption_status::encrypted, true)); } } if (!value->empty()) { facts.add(fact::memory, move(value)); } } }}} // namespace facter::facts::resolvers facter-3.14.12/lib/src/facts/resolvers/networking_resolver.cc0000644005276200011600000003411013702047406024120 0ustar jenkinsjenkins#include #include #include #include #include #include #include #include #include #include #include using namespace std; namespace facter { namespace facts { namespace resolvers { networking_resolver::networking_resolver() : resolver( "networking", { fact::networking, fact::hostname, fact::ipaddress, fact::ipaddress6, fact::netmask, fact::netmask6, fact::network, fact::network6, fact::scope6, fact::macaddress, fact::interfaces, fact::domain, fact::fqdn, fact::dhcp_servers, }, { string("^") + fact::ipaddress + "_", string("^") + fact::ipaddress6 + "_", string("^") + fact::mtu + "_", string("^") + fact::netmask + "_", string("^") + fact::netmask6 + "_", string("^") + fact::network + "_", string("^") + fact::network6 + "_", string("^") + fact::scope6 + "_", string("^") + fact::macaddress + "_", }) { } void networking_resolver::resolve(collection& facts) { auto data = collect_data(facts); // Some queries, such as /etc/resolv.conf, can return domains with a trailing dot (.). // We want to strip the trailing dot, as it is not useful as a valid domain or fqdn. boost::trim_right_if(data.domain, boost::is_any_of(".")); // If no FQDN, set it to the hostname + domain if (!data.hostname.empty() && data.fqdn.empty()) { data.fqdn = data.hostname + (data.domain.empty() ? "" : ".") + data.domain; } // If no primary interface was found, default to the first interface with a valid address if (data.primary_interface.empty()) { LOG_DEBUG("no primary interface found: using the first interface with an assigned address as the primary interface."); auto primary = find_primary_interface(data.interfaces); if (primary) { data.primary_interface = primary->name; } } auto networking = make_value(); // Add the interface data ostringstream interface_names; auto dhcp_servers = make_value(true); auto interfaces = make_value(); for (auto& interface : data.interfaces) { bool primary = interface.name == data.primary_interface; auto value = make_value(); // Add the ipv4 bindings add_bindings(interface, primary, true, facts, *networking, *value); // Add the ipv6 bindings add_bindings(interface, primary, false, facts, *networking, *value); // Add the MAC address if (!interface.macaddress.empty()) { facts.add(string(fact::macaddress) + "_" + interface.name, make_value(interface.macaddress, true)); if (primary) { facts.add(fact::macaddress, make_value(interface.macaddress, true)); networking->add("mac", make_value(interface.macaddress)); } value->add("mac", make_value(move(interface.macaddress))); } // Add the DHCP server if (!interface.dhcp_server.empty()) { if (primary) { dhcp_servers->add("system", make_value(interface.dhcp_server)); networking->add("dhcp", make_value(interface.dhcp_server)); } dhcp_servers->add(string(interface.name), make_value(interface.dhcp_server)); value->add("dhcp", make_value(move(interface.dhcp_server))); } // Add the interface MTU if (interface.mtu) { facts.add(string(fact::mtu) + "_" + interface.name, make_value(*interface.mtu, true)); if (primary) { networking->add("mtu", make_value(*interface.mtu)); } value->add("mtu", make_value(*interface.mtu)); } // Add the interface to the list of names if (interface_names.tellp() != 0) { interface_names << ","; } interface_names << interface.name; interfaces->add(move(interface.name), move(value)); } // Add top-level network data if (!data.hostname.empty()) { facts.add(fact::hostname, make_value(data.hostname, true)); networking->add("hostname", make_value(move(data.hostname))); } if (!data.domain.empty()) { facts.add(fact::domain, make_value(data.domain, true)); networking->add("domain", make_value(move(data.domain))); } if (!data.fqdn.empty()) { facts.add(fact::fqdn, make_value(data.fqdn, true)); networking->add("fqdn", make_value(move(data.fqdn))); } if (!data.primary_interface.empty()) { networking->add("primary", make_value(move(data.primary_interface))); } if (interface_names.tellp() != 0) { facts.add(fact::interfaces, make_value(interface_names.str(), true)); } if (!dhcp_servers->empty()) { facts.add(fact::dhcp_servers, move(dhcp_servers)); } if (!interfaces->empty()) { networking->add("interfaces", move(interfaces)); } if (!networking->empty()) { facts.add(fact::networking, move(networking)); } } string networking_resolver::get_scope(const string& address) { std::ostringstream ostream; boost::asio::ip::address_v6 addr; try { addr = boost::asio::ip::address_v6::from_string(address); } catch (boost::exception &e) { return ostream.str(); } if (addr.is_v4_compatible()) { ostream << "compat,"; } if (addr.is_link_local()) ostream << "link"; else if (addr.is_site_local()) ostream << "site"; else if (addr.is_loopback()) ostream << "host"; else ostream << "global"; return ostream.str(); } string networking_resolver::macaddress_to_string(uint8_t const* bytes, uint8_t byte_count) { if (!bytes || (byte_count != 6 && byte_count != 20)) { return {}; } // Ignore MAC address "0" bool nonzero = false; for (size_t i = 0; i < byte_count; ++i) { if (bytes[i] != 0) { nonzero = true; break; } } if (!nonzero) { return {}; } if (byte_count == 6) { return (boost::format("%02x:%02x:%02x:%02x:%02x:%02x") % static_cast(bytes[0]) % static_cast(bytes[1]) % static_cast(bytes[2]) % static_cast(bytes[3]) % static_cast(bytes[4]) % static_cast(bytes[5])).str(); } else if (byte_count == 20) { return (boost::format("%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x") % static_cast(bytes[0]) % static_cast(bytes[1]) % static_cast(bytes[2]) % static_cast(bytes[3]) % static_cast(bytes[4]) % static_cast(bytes[5]) % static_cast(bytes[6]) % static_cast(bytes[7]) % static_cast(bytes[8]) % static_cast(bytes[9]) % static_cast(bytes[10]) % static_cast(bytes[11]) % static_cast(bytes[12]) % static_cast(bytes[13]) % static_cast(bytes[14]) % static_cast(bytes[15]) % static_cast(bytes[16]) % static_cast(bytes[17]) % static_cast(bytes[18]) % static_cast(bytes[19])).str(); } else { return {}; } } bool networking_resolver::ignored_ipv4_address(string const& addr) { // Excluding localhost and 169.254.x.x in Windows - this is the DHCP APIPA, meaning that if the node cannot // get an ip address from the dhcp server, it auto-assigns a private ip address return addr.empty() || boost::starts_with(addr, "127.") || boost::starts_with(addr, "169.254."); } bool networking_resolver::ignored_ipv6_address(string const& addr) { return addr.empty() || addr == "::1" || boost::starts_with(addr, "fe80"); } networking_resolver::binding const* networking_resolver::find_default_binding(vector const& bindings, function const& ignored) { for (auto& binding : bindings) { if (!ignored(binding.address)) { return &binding; } } return bindings.empty() ? nullptr : &bindings.front(); } void networking_resolver::add_bindings(interface& iface, bool primary, bool ipv4, collection& facts, map_value& networking, map_value& iface_value) { auto ip_fact = ipv4 ? fact::ipaddress : fact::ipaddress6; auto ip_name = ipv4 ? "ip" : "ip6"; auto netmask_fact = ipv4 ? fact::netmask : fact::netmask6; auto netmask_name = ipv4 ? "netmask" : "netmask6"; auto network_fact = ipv4 ? fact::network : fact::network6; auto network_name = ipv4 ? "network" : "network6"; auto& bindings = ipv4 ? iface.ipv4_bindings : iface.ipv6_bindings; auto bindings_name = ipv4 ? "bindings" : "bindings6"; auto ignored = ipv4 ? &ignored_ipv4_address : &ignored_ipv6_address; // Add the default binding to the collection and interface auto binding = find_default_binding(bindings, ignored); if (binding) { if (!binding->address.empty()) { facts.add(string(ip_fact) + "_" + iface.name, make_value(binding->address, true)); iface_value.add(ip_name, make_value(binding->address)); if (!ipv4) { facts.add(string(fact::scope6) + "_" + iface.name, make_value(get_scope(binding->address), true)); iface_value.add("scope6", make_value(get_scope(binding->address))); } if (primary) { facts.add(ip_fact, make_value(binding->address, true)); networking.add(ip_name, make_value(binding->address)); if (!ipv4) { facts.add(fact::scope6, make_value(get_scope(binding->address), true)); networking.add("scope6", make_value(get_scope(binding->address))); } } } if (!binding->netmask.empty()) { facts.add(string(netmask_fact) + "_" + iface.name, make_value(binding->netmask, true)); if (primary) { facts.add(netmask_fact, make_value(binding->netmask, true)); networking.add(netmask_name, make_value(binding->netmask)); } iface_value.add(netmask_name, make_value(binding->netmask)); } if (!binding->network.empty()) { facts.add(string(network_fact) + "_" + iface.name, make_value(binding->network, true)); if (primary) { facts.add(network_fact, make_value(binding->network, true)); networking.add(network_name, make_value(binding->network)); } iface_value.add(network_name, make_value(binding->network)); } } // Set the bindings in the interface if (!bindings.empty()) { auto bindings_value = make_value(); for (auto& binding : bindings) { auto binding_value = make_value(); if (!binding.address.empty()) { binding_value->add("address", make_value(move(binding.address))); } if (!binding.netmask.empty()) { binding_value->add("netmask", make_value(move(binding.netmask))); } if (!binding.network.empty()) { binding_value->add("network", make_value(move(binding.network))); } if (!binding_value->empty()) { bindings_value->add(move(binding_value)); } } iface_value.add(bindings_name, move(bindings_value)); } } networking_resolver::interface const* networking_resolver::find_primary_interface(vector const& interfaces) { for (auto const& interface : interfaces) { for (auto const& binding : interface.ipv4_bindings) { if (!ignored_ipv4_address(binding.address)) { return &interface; } } for (auto const& binding : interface.ipv6_bindings) { if (!ignored_ipv6_address(binding.address)) { return &interface; } } } return nullptr; } }}} // namespace facter::facts::posix facter-3.14.12/lib/src/facts/resolvers/operating_system_resolver.cc0000644005276200011600000003250513702047406025333 0ustar jenkinsjenkins#include #include #include #include #include #include #include #include using namespace std; using namespace facter::util; using namespace leatherman::util; namespace facter { namespace facts { namespace resolvers { operating_system_resolver::operating_system_resolver() : resolver( "operating system", { fact::os, fact::operating_system, fact::os_family, fact::operating_system_release, fact::operating_system_major_release, fact::hardware_model, fact::architecture, fact::lsb_dist_id, fact::lsb_dist_release, fact::lsb_dist_codename, fact::lsb_dist_description, fact::lsb_dist_major_release, fact::lsb_dist_minor_release, fact::lsb_release, fact::macosx_buildversion, fact::macosx_productname, fact::macosx_productversion, fact::macosx_productversion_major, fact::macosx_productversion_minor, fact::windows_edition_id, fact::windows_installation_type, fact::windows_product_name, fact::windows_release_id, fact::windows_system32, fact::selinux, fact::selinux_enforced, fact::selinux_policyversion, fact::selinux_current_mode, fact::selinux_config_mode, fact::selinux_config_policy, }) { } void operating_system_resolver::resolve(collection& facts) { auto data = collect_data(facts); auto os = make_value(); if (!data.family.empty()) { facts.add(fact::os_family, make_value(data.family, true)); os->add("family", make_value(move(data.family))); } if (!data.release.empty()) { auto value = make_value(); // When we have no major or minor, do a 'trivial' parse of // the release to try to get SOMETHING out of it. if (data.minor.empty() && data.major.empty()) { std::tie(data.major, data.minor) = versions::major_minor(data.release); } if (!data.major.empty()) { facts.add(fact::operating_system_major_release, make_value(data.major, true)); value->add("major", make_value(move(data.major))); } if (!data.minor.empty()) { value->add("minor", make_value(move(data.minor))); } facts.add(fact::operating_system_release, make_value(data.release, true)); value->add("full", make_value(move(data.release))); // Populate FreeBSD-specific data if (!data.freebsd.branch.empty()) { value->add("branch", make_value(move(data.freebsd.branch))); } if (!data.freebsd.patchlevel.empty()) { value->add("patchlevel", make_value(move(data.freebsd.patchlevel))); } os->add("release", move(value)); } // Add the OS hardware and architecture facts if (!data.hardware.empty()) { facts.add(fact::hardware_model, make_value(data.hardware, true)); os->add("hardware", make_value(move(data.hardware))); } if (!data.architecture.empty()) { facts.add(fact::architecture, make_value(data.architecture, true)); os->add("architecture", make_value(move(data.architecture))); } // Add distro facts auto distro = make_value(); if (!data.distro.id.empty()) { facts.add(fact::lsb_dist_id, make_value(data.distro.id, true)); distro->add("id", make_value(move(data.distro.id))); } if (!data.distro.codename.empty()) { facts.add(fact::lsb_dist_codename, make_value(data.distro.codename, true)); distro->add("codename", make_value(move(data.distro.codename))); } if (!data.distro.description.empty()) { facts.add(fact::lsb_dist_description, make_value(data.distro.description, true)); distro->add("description", make_value(move(data.distro.description))); } if (!data.distro.release.empty()) { auto value = make_value(); string major, minor; tie(major, minor) = parse_distro(data.name, data.distro.release); if (major.empty()) { major = data.distro.release; } facts.add(fact::lsb_dist_major_release, make_value(major, true)); value->add("major", make_value(move(major))); if (!minor.empty()) { facts.add(fact::lsb_dist_minor_release, make_value(minor, true)); value->add("minor", make_value(move(minor))); } facts.add(fact::lsb_dist_release, make_value(data.distro.release, true)); value->add("full", make_value(move(data.distro.release))); distro->add("release", move(value)); } if (!data.specification_version.empty()) { facts.add(fact::lsb_release, make_value(data.specification_version, true)); distro->add("specification", make_value(move(data.specification_version))); } // Add the name last since the above release parsing is dependent on it if (!data.name.empty()) { facts.add(fact::operating_system, make_value(data.name, true)); os->add("name", make_value(move(data.name))); } if (!distro->empty()) { os->add("distro", move(distro)); } // Populate OSX-specific data auto macosx = make_value(); if (!data.osx.product.empty()) { facts.add(fact::macosx_productname, make_value(data.osx.product, true)); macosx->add("product", make_value(move(data.osx.product))); } if (!data.osx.build.empty()) { facts.add(fact::macosx_buildversion, make_value(data.osx.build, true)); macosx->add("build", make_value(move(data.osx.build))); } if (!data.osx.version.empty()) { // Look for the last '.' for major/minor auto version = make_value(); auto pos = data.osx.version.rfind('.'); if (pos != string::npos) { string major = data.osx.version.substr(0, pos); string minor = data.osx.version.substr(pos + 1); // If the major doesn't have a '.', treat the entire version as the major // and use a minor of "0" if (major.find('.') == string::npos) { major = data.osx.version; minor = "0"; } if (!major.empty()) { facts.add(fact::macosx_productversion_major, make_value(major, true)); version->add("major", make_value(move(major))); } if (!minor.empty()) { facts.add(fact::macosx_productversion_minor, make_value(minor, true)); version->add("minor", make_value(move(minor))); } } facts.add(fact::macosx_productversion, make_value(data.osx.version, true)); version->add("full", make_value(move(data.osx.version))); macosx->add("version", move(version)); } if (!macosx->empty()) { os->add("macosx", move(macosx)); } // Populate Windows-specific data auto windows = make_value(); if (!data.win.edition_id.empty()) { facts.add(fact::windows_edition_id, make_value(data.win.edition_id, true)); windows->add("edition_id", make_value(move(data.win.edition_id))); } if (!data.win.installation_type.empty()) { facts.add(fact::windows_installation_type, make_value(data.win.installation_type, true)); windows->add("installation_type", make_value(move(data.win.installation_type))); } if (!data.win.product_name.empty()) { facts.add(fact::windows_product_name, make_value(data.win.product_name, true)); windows->add("product_name", make_value(move(data.win.product_name))); } if (!data.win.release_id.empty()) { facts.add(fact::windows_release_id, make_value(data.win.release_id, true)); windows->add("release_id", make_value(move(data.win.release_id))); } if (!data.win.system32.empty()) { facts.add(fact::windows_system32, make_value(data.win.system32, true)); windows->add("system32", make_value(move(data.win.system32))); } if (!windows->empty()) { os->add("windows", move(windows)); } if (data.selinux.supported) { auto selinux = make_value(); facts.add(fact::selinux, make_value(data.selinux.enabled, true)); selinux->add("enabled", make_value(data.selinux.enabled)); if (data.selinux.enabled) { facts.add(fact::selinux_enforced, make_value(data.selinux.enforced, true)); selinux->add("enforced", make_value(data.selinux.enforced)); if (!data.selinux.current_mode.empty()) { facts.add(fact::selinux_current_mode, make_value(data.selinux.current_mode, true)); selinux->add("current_mode", make_value(move(data.selinux.current_mode))); } if (!data.selinux.config_mode.empty()) { facts.add(fact::selinux_config_mode, make_value(data.selinux.config_mode, true)); selinux->add("config_mode", make_value(move(data.selinux.config_mode))); } if (!data.selinux.config_policy.empty()) { facts.add(fact::selinux_config_policy, make_value(data.selinux.config_policy, true)); selinux->add("config_policy", make_value(move(data.selinux.config_policy))); } if (!data.selinux.policy_version.empty()) { facts.add(fact::selinux_policyversion, make_value(data.selinux.policy_version, true)); selinux->add("policy_version", make_value(move(data.selinux.policy_version))); } } os->add("selinux", move(selinux)); } if (!os->empty()) { facts.add(fact::os, move(os)); } } operating_system_resolver::data operating_system_resolver::collect_data(collection& facts) { data result; collect_kernel_data(facts, result); collect_release_data(facts, result); return result; } void operating_system_resolver::collect_kernel_data(collection& facts, data& result) { auto kernel = facts.get(fact::kernel); if (kernel) { result.name = kernel->value(); result.family = kernel->value(); } } void operating_system_resolver::collect_release_data(collection& facts, data& result) { auto release = facts.get(fact::kernel_release); if (release) { result.release = release->value(); } } tuple operating_system_resolver::parse_distro(string const& name, string const& release) { // This implementation couples all known formats for lsb_dist and the Linux release versions. If that // coupling becomes a problem, we'll probably need to push parsing distro major/minor to inheriting resolvers, // as we've done for parsing the release version. if (name != os::ubuntu) { auto pos = release.find('.'); if (pos != string::npos) { auto second = release.find('.', pos + 1); return make_tuple(release.substr(0, pos), release.substr(pos + 1, second - (pos + 1))); } return make_tuple(release, string()); } string major, minor; re_search(release, boost::regex("(\\d+\\.\\d*)\\.?(\\d*)"), &major, &minor); return make_tuple(move(major), move(minor)); } }}} // namespace facter::facts::resolvers facter-3.14.12/lib/src/facts/resolvers/path_resolver.cc0000644005276200011600000000125513702047406022671 0ustar jenkinsjenkins#include #include #include #include #include using namespace std; using namespace leatherman::util; namespace facter { namespace facts { namespace resolvers { path_resolver::path_resolver() : resolver("path", {fact::path}) { } void path_resolver::resolve(collection& facts) { string path_val; if (environment::get("PATH", path_val)) { facts.add(fact::path, make_value(move(path_val))); } } }}} // namespace facter::facts::resolvers facter-3.14.12/lib/src/facts/resolvers/processor_resolver.cc0000644005276200011600000000431313702047406023752 0ustar jenkinsjenkins#include #include #include #include #include #include #include using namespace std; using namespace facter::util; namespace facter { namespace facts { namespace resolvers { processor_resolver::processor_resolver() : resolver( "processor", { fact::processors, fact::processor_count, fact::physical_processor_count, fact::hardware_isa, }, { string("^") + fact::processor + "[0-9]+$", }) { } void processor_resolver::resolve(collection& facts) { auto data = collect_data(facts); auto cpus = make_value(); if (!data.isa.empty()) { facts.add(fact::hardware_isa, make_value(data.isa, true)); cpus->add("isa", make_value(move(data.isa))); } if (data.logical_count > 0) { facts.add(fact::processor_count, make_value(data.logical_count, true)); cpus->add("count", make_value(data.logical_count)); } if (data.physical_count > 0) { facts.add(fact::physical_processor_count, make_value(data.physical_count, true)); cpus->add("physicalcount", make_value(data.physical_count)); } if (data.speed > 0) { cpus->add("speed", make_value(frequency(data.speed))); } auto models = make_value(); int processor = 0; for (auto& model : data.models) { facts.add(fact::processor + to_string(processor++), make_value(model, true)); models->add(make_value(move(model))); } if (!models->empty()) { cpus->add("models", move(models)); } if (!cpus->empty()) { facts.add(fact::processors, move(cpus)); } } }}} // namespace facter::facts::resolvers facter-3.14.12/lib/src/facts/resolvers/ruby_resolver.cc0000644005276200011600000000627413702047406022724 0ustar jenkinsjenkins#include #include #include #include #include #include #include using namespace std; using namespace leatherman::ruby; namespace facter { namespace facts { namespace resolvers { ruby_resolver::ruby_resolver() : resolver( "ruby", { fact::ruby, fact::rubyplatform, fact::rubysitedir, fact::rubyversion }) { } static void ruby_fact_rescue(api const& rb, function cb, string const& label) { // Use rescue, because Ruby exceptions don't call destructors. The callback cb shouldn't // have any object construction/destruction in it. rb.rescue(cb, [&](VALUE ex) { LOG_ERROR("error while resolving ruby {1} fact: {2}", label, rb.exception_to_string(ex)); return 0; }); } static string get_platform(api const& rb) { string platform; ruby_fact_rescue(rb, [&]() { auto val = rb.lookup({"RUBY_PLATFORM"}); platform = rb.to_string(val); return 0; }, "platform"); return platform; } static string get_sitedir(api const& rb) { string sitedir; ruby_fact_rescue(rb, [&]() { rb.rb_require("rbconfig"); auto config = rb.lookup({"RbConfig", "CONFIG"}); auto val = rb.rb_hash_lookup(config, rb.utf8_value("sitelibdir")); sitedir = rb.to_string(val); return 0; }, "sitedir"); return sitedir; } static string get_version(api const& rb) { string version; ruby_fact_rescue(rb, [&]() { auto val = rb.lookup({"RUBY_VERSION"}); version = rb.to_string(val); return 0; }, "version"); return version; } static void add(collection& f, map_value& d, string s, string hidden, string nested) { if (!s.empty()) { f.add(move(hidden), make_value(s, true)); d.add(move(nested), make_value(move(s))); } } ruby_resolver::data ruby_resolver::collect_data(collection& facts) { data rb_data; auto const& ruby = api::instance(); if (!ruby.initialized()) { return rb_data; } rb_data.platform = get_platform(ruby); rb_data.sitedir = get_sitedir(ruby); rb_data.version = get_version(ruby); return rb_data; } void ruby_resolver::resolve(collection& facts) { auto rb_data = collect_data(facts); auto rb_map = make_value(); add(facts, *rb_map, move(rb_data.platform), fact::rubyplatform, "platform"); add(facts, *rb_map, move(rb_data.sitedir), fact::rubysitedir, "sitedir"); add(facts, *rb_map, move(rb_data.version), fact::rubyversion, "version"); if (!rb_map->empty()) { facts.add(fact::ruby, move(rb_map)); } } }}} // namespace facter::facts::resolvers facter-3.14.12/lib/src/facts/resolvers/ssh_resolver.cc0000644005276200011600000001352513702047406022535 0ustar jenkinsjenkins#include #include #include #include #include #include #include #include #include #ifdef USE_OPENSSL #include #include #include using namespace facter::util; #endif // USE_OPENSSL using namespace std; using namespace facter::util; using namespace boost::filesystem; namespace lth_file = leatherman::file_util; namespace facter { namespace facts { namespace resolvers { ssh_resolver::ssh_resolver() : resolver( "ssh", { fact::ssh, fact::ssh_dsa_key, fact::ssh_rsa_key, fact::ssh_ecdsa_key, fact::ssh_ed25519_key, fact::sshfp_dsa, fact::sshfp_rsa, fact::sshfp_ecdsa, fact::sshfp_ed25519, }) { } ssh_resolver::data ssh_resolver::collect_data(collection& facts) { ssh_resolver::data result; populate_key("ssh_host_rsa_key.pub", 1, result.rsa); populate_key("ssh_host_dsa_key.pub", 2, result.dsa); populate_key("ssh_host_ecdsa_key.pub", 3, result.ecdsa); populate_key("ssh_host_ed25519_key.pub", 4, result.ed25519); return result; } void ssh_resolver::resolve(collection& facts) { auto data = collect_data(facts); auto ssh = make_value(); add_key(facts, *ssh, data.dsa, "dsa", fact::ssh_dsa_key, fact::sshfp_dsa); add_key(facts, *ssh, data.rsa, "rsa", fact::ssh_rsa_key, fact::sshfp_rsa); add_key(facts, *ssh, data.ecdsa, "ecdsa", fact::ssh_ecdsa_key, fact::sshfp_ecdsa); add_key(facts, *ssh, data.ed25519, "ed25519", fact::ssh_ed25519_key, fact::sshfp_ed25519); if (!ssh->empty()) { facts.add(fact::ssh, move(ssh)); } } void ssh_resolver::add_key(collection& facts, map_value& value, ssh_key& key, string const& name, string const& key_fact_name, string const& fingerprint_fact_name) { if (key.key.empty()) { return; } auto key_value = make_value(); auto fingerprint_value = make_value(); facts.add(string(key_fact_name), make_value(key.key, true)); key_value->add("key", make_value(move(key.key))); key_value->add("type", make_value(move(key.type))); string fingerprint; if (!key.digest.sha1.empty()) { fingerprint = key.digest.sha1; fingerprint_value->add("sha1", make_value(move(key.digest.sha1))); } if (!key.digest.sha256.empty()) { if (!fingerprint.empty()) { fingerprint += "\n"; } fingerprint += key.digest.sha256; fingerprint_value->add("sha256", make_value(move(key.digest.sha256))); } if (!fingerprint.empty()) { facts.add(string(fingerprint_fact_name), make_value(move(fingerprint), true)); } if (!fingerprint_value->empty()) { key_value->add("fingerprints", move(fingerprint_value)); } value.add(string(name), move(key_value)); } void ssh_resolver::populate_key(std::string const& filename, int type, ssh_key& key) { path key_file = retrieve_key_file(filename); // Log if we didn't find the file if (key_file.empty()) { LOG_DEBUG("{1} could not be located.", filename); return; } // Read the file's contents string contents = lth_file::read(key_file.string()); if (contents.empty()) { LOG_DEBUG("{1} could not be read.", key_file); return; } boost::trim(contents); // The SSH public key file format is vector> parts; boost::split(parts, contents, boost::is_any_of(" "), boost::token_compress_on); if (parts.size() < 2) { LOG_DEBUG("unexpected contents for {1}.", key_file); return; } // Assign the key and its type key.type.assign(parts[0].begin(), parts[0].end()); key.key.assign(parts[1].begin(), parts[1].end()); // Only fingerprint if we are using OpenSSL #ifdef USE_OPENSSL // Decode the key which is expected to be base64 encoded vector key_bytes(key.key.size()); scoped_bio b64((BIO_f_base64())); BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL); // Despite the const_cast here, we're only reading from the string; BIO_new_mem_buf is not const-correct scoped_bio mem(BIO_new_mem_buf(const_cast(key.key.c_str()), key.key.size())); BIO* stream = BIO_push(b64, mem); int length = BIO_read(stream, key_bytes.data(), key_bytes.size()); if (length < 1) { LOG_DEBUG("failed to decode SSH key \"{1}\".", key.key); return; } // Do a SHA1 and a SHA-256 hash for the fingerprints uint8_t hash[SHA_DIGEST_LENGTH]; SHA1(key_bytes.data(), length, hash); uint8_t hash256[SHA256_DIGEST_LENGTH]; SHA256(key_bytes.data(), length, hash256); key.digest.sha1 = (boost::format("SSHFP %1% 1 %2%") % type % to_hex(hash, sizeof(hash))).str(); key.digest.sha256 = (boost::format("SSHFP %1% 2 %2%") % type % to_hex(hash256, sizeof(hash256))).str(); #else LOG_INFO("facter was built without OpenSSL support: SSH fingerprint information is unavailable."); #endif // USE_OPENSSL } }}} // namespace facter::facts::resolvers facter-3.14.12/lib/src/facts/resolvers/system_profiler_resolver.cc0000644005276200011600000001542513702047406025167 0ustar jenkinsjenkins#include #include #include #include #include using namespace std; using namespace facter::facts; namespace facter { namespace facts { namespace resolvers { system_profiler_resolver::system_profiler_resolver() : resolver( "system profiler", { fact::system_profiler, fact::sp_boot_mode, fact::sp_boot_rom_version, fact::sp_boot_volume, fact::sp_cpu_type, fact::sp_current_processor_speed, fact::sp_kernel_version, fact::sp_l2_cache_core, fact::sp_l3_cache, fact::sp_local_host_name, fact::sp_machine_model, fact::sp_machine_name, fact::sp_number_processors, fact::sp_os_version, fact::sp_packages, fact::sp_physical_memory, fact::sp_platform_uuid, fact::sp_secure_vm, fact::sp_serial_number, fact::sp_smc_version_system, fact::sp_uptime, fact::sp_user_name, }) { } void system_profiler_resolver::resolve(collection& facts) { auto data = collect_data(facts); auto system_profiler = make_value(); if (!data.boot_mode.empty()) { facts.add(fact::sp_boot_mode, make_value(data.boot_mode, true)); system_profiler->add("boot_mode", make_value(move(data.boot_mode))); } if (!data.boot_rom_version.empty()) { facts.add(fact::sp_boot_rom_version, make_value(data.boot_rom_version, true)); system_profiler->add("boot_rom_version", make_value(move(data.boot_rom_version))); } if (!data.boot_volume.empty()) { facts.add(fact::sp_boot_volume, make_value(data.boot_volume, true)); system_profiler->add("boot_volume", make_value(move(data.boot_volume))); } if (!data.processor_name.empty()) { facts.add(fact::sp_cpu_type, make_value(data.processor_name, true)); system_profiler->add("processor_name", make_value(move(data.processor_name))); } if (!data.processor_speed.empty()) { facts.add(fact::sp_current_processor_speed, make_value(data.processor_speed, true)); system_profiler->add("processor_speed", make_value(move(data.processor_speed))); } if (!data.kernel_version.empty()) { facts.add(fact::sp_kernel_version, make_value(data.kernel_version, true)); system_profiler->add("kernel_version", make_value(move(data.kernel_version))); } if (!data.l2_cache_per_core.empty()) { facts.add(fact::sp_l2_cache_core, make_value(data.l2_cache_per_core, true)); system_profiler->add("l2_cache_per_core", make_value(move(data.l2_cache_per_core))); } if (!data.l3_cache.empty()) { facts.add(fact::sp_l3_cache, make_value(data.l3_cache, true)); system_profiler->add("l3_cache", make_value(move(data.l3_cache))); } if (!data.computer_name.empty()) { facts.add(fact::sp_local_host_name, make_value(data.computer_name, true)); system_profiler->add("computer_name", make_value(move(data.computer_name))); } if (!data.model_identifier.empty()) { facts.add(fact::sp_machine_model, make_value(data.model_identifier, true)); system_profiler->add("model_identifier", make_value(move(data.model_identifier))); } if (!data.model_name.empty()) { facts.add(fact::sp_machine_name, make_value(data.model_name, true)); system_profiler->add("model_name", make_value(move(data.model_name))); } if (!data.cores.empty()) { facts.add(fact::sp_number_processors, make_value(data.cores, true)); system_profiler->add("cores", make_value(move(data.cores))); } if (!data.system_version.empty()) { facts.add(fact::sp_os_version, make_value(data.system_version, true)); system_profiler->add("system_version", make_value(move(data.system_version))); } if (!data.processors.empty()) { facts.add(fact::sp_packages, make_value(data.processors, true)); system_profiler->add("processors", make_value(move(data.processors))); } if (!data.memory.empty()) { facts.add(fact::sp_physical_memory, make_value(data.memory, true)); system_profiler->add("memory", make_value(move(data.memory))); } if (!data.hardware_uuid.empty()) { facts.add(fact::sp_platform_uuid, make_value(data.hardware_uuid, true)); system_profiler->add("hardware_uuid", make_value(move(data.hardware_uuid))); } if (!data.secure_virtual_memory.empty()) { facts.add(fact::sp_secure_vm, make_value(data.secure_virtual_memory, true)); system_profiler->add("secure_virtual_memory", make_value(move(data.secure_virtual_memory))); } if (!data.serial_number.empty()) { facts.add(fact::sp_serial_number, make_value(data.serial_number, true)); system_profiler->add("serial_number", make_value(move(data.serial_number))); } if (!data.smc_version.empty()) { facts.add(fact::sp_smc_version_system, make_value(data.smc_version, true)); system_profiler->add("smc_version", make_value(move(data.smc_version))); } if (!data.uptime.empty()) { facts.add(fact::sp_uptime, make_value(data.uptime, true)); system_profiler->add("uptime", make_value(move(data.uptime))); } if (!data.username.empty()) { facts.add(fact::sp_user_name, make_value(data.username, true)); system_profiler->add("username", make_value(move(data.username))); } if (!system_profiler->empty()) { facts.add(fact::system_profiler, move(system_profiler)); } } }}} // namespace facter::facts::resolvers facter-3.14.12/lib/src/facts/resolvers/timezone_resolver.cc0000644005276200011600000000124213702047406023563 0ustar jenkinsjenkins#include #include #include #include namespace facter { namespace facts { namespace resolvers { timezone_resolver::timezone_resolver() : resolver( "timezone", { fact::timezone, }) { } void timezone_resolver::resolve(collection& facts) { auto timezone = get_timezone(); if (timezone.empty()) { return; } facts.add(fact::timezone, make_value(move(timezone))); } }}} // facter::facts::resolvers facter-3.14.12/lib/src/facts/resolvers/uptime_resolver.cc0000644005276200011600000000375113702047406023243 0ustar jenkinsjenkins#include #include #include #include #include #include using namespace std; namespace facter { namespace facts { namespace resolvers { uptime_resolver::uptime_resolver() : resolver( "uptime", { fact::system_uptime, fact::uptime, fact::uptime_days, fact::uptime_hours, fact::uptime_seconds }) { } void uptime_resolver::resolve(collection& facts) { auto seconds = get_uptime(); if (seconds < 0) { return; } auto minutes = (seconds / 60) % 60; auto hours = seconds / (60 * 60); auto days = seconds / (60 * 60 * 24); string uptime; switch (days) { case 0: uptime = (boost::format("%d:%02d hours") % hours % minutes).str(); break; case 1: uptime = "1 day"; break; default: uptime = (boost::format("%d days") % days).str(); break; } // Add hidden facts facts.add(fact::uptime_seconds, make_value(seconds, true)); facts.add(fact::uptime_hours, make_value(hours, true)); facts.add(fact::uptime_days, make_value(days, true)); facts.add(fact::uptime, make_value(uptime, true)); auto value = make_value(); value->add("seconds", make_value(seconds)); value->add("hours", make_value(hours)); value->add("days", make_value(days)); value->add("uptime", make_value(move(uptime))); facts.add(fact::system_uptime, move(value)); } }}} // namespace facter::facts::resolvers facter-3.14.12/lib/src/facts/resolvers/virtualization_resolver.cc0000644005276200011600000000767613702047406025036 0ustar jenkinsjenkins#include #include #include #include #include #include #include using namespace std; using namespace facter::facts; namespace facter { namespace facts { namespace resolvers { virtualization_resolver::virtualization_resolver() : resolver( "virtualization", { fact::virtualization, fact::is_virtual, fact::cloud }) { } void virtualization_resolver::resolve(collection& facts) { auto data = collect_data(facts); facts.add(fact::is_virtual, make_value(data.is_virtual)); facts.add(fact::virtualization, make_value(data.hypervisor)); if (!data.cloud.provider.empty()) { auto cloud = make_value(); cloud->add("provider", make_value(data.cloud.provider)); facts.add(fact::cloud, move(cloud)); } } data virtualization_resolver::collect_data(collection& facts) { data data; auto hypervisor = get_hypervisor(facts); if (hypervisor.empty()) { hypervisor = "physical"; } auto cloud_provider = get_cloud_provider(facts); data.is_virtual = is_virtual(hypervisor); data.hypervisor = hypervisor; data.cloud.provider = cloud_provider; return data; } string virtualization_resolver::get_cloud_provider(collection& facts) { // Default implementation for other resolvers. return ""; } bool virtualization_resolver::is_virtual(string const& hypervisor) { // Set of hypervisor values we consider to not be virtual static set hypervisors = { "physical", string(vm::xen_privileged), string(vm::vmware_server), string(vm::vmware_workstation), string(vm::openvz_hn), string(vm::vserver_host), }; return hypervisors.count(hypervisor) == 0; } string virtualization_resolver::get_fact_vm(collection& facts) { // First, attempt to match on the SMBIOS reported product name static vector> product_names = { make_tuple("VMware", string(vm::vmware)), make_tuple("VirtualBox", string(vm::virtualbox)), make_tuple("Parallels", string(vm::parallels)), make_tuple("KVM", string(vm::kvm)), make_tuple("Virtual Machine", string(vm::hyperv)), make_tuple("RHEV Hypervisor", string(vm::redhat_ev)), make_tuple("oVirt Node", string(vm::ovirt)), make_tuple("HVM domU", string(vm::xen_hardware)), make_tuple("Bochs", string(vm::bochs)), make_tuple("OpenBSD", string(vm::vmm)), make_tuple("BHYVE", string(vm::bhyve)), }; auto product_name = facts.get(fact::product_name); if (product_name) { for (auto const& vm : product_names) { if (product_name->value().find(get<0>(vm)) != string::npos) { return get<1>(vm); } } } // Next, try the reported BIOS vendor static vector> vendor_names = { make_tuple("Amazon EC2", string(vm::kvm)), }; auto vendor_name = facts.get(fact::bios_vendor); if (vendor_name) { for (auto const& vm : vendor_names) { if (vendor_name->value().find(get<0>(vm)) != string::npos) { return get<1>(vm); } } } return {}; } }}} // namespace facter::facts::resolvers facter-3.14.12/lib/src/facts/resolvers/xen_resolver.cc0000644005276200011600000000455513702047406022535 0ustar jenkinsjenkins#include #include #include #include #include #include #include #include #include #include #include using namespace std; using namespace facter::facts; using namespace leatherman::execution; using namespace leatherman::util; namespace facter { namespace facts { namespace resolvers { xen_resolver::xen_resolver() : resolver( "Xen", { fact::xen, fact::xendomains }) { } void xen_resolver::resolve(collection& facts) { // Confine to fact virtual == xen0 auto virt = facts.get(fact::virtualization); if (!virt || virt->value() != vm::xen_privileged) { return; } auto data = collect_data(facts); if (!data.domains.empty()) { auto xendomains = boost::algorithm::join(data.domains, ","); facts.add(fact::xendomains, make_value(move(xendomains), true)); } auto domains = make_value(); for (auto& domain : data.domains) { domains->add(make_value(move(domain))); } auto xen = make_value(); if (!domains->empty()) { xen->add("domains", move(domains)); } if (!xen->empty()) { facts.add(fact::xen, move(xen)); } } xen_resolver::data xen_resolver::collect_data(collection& facts) { data result; auto command = xen_command(); if (!command.empty()) { static boost::regex domain_header("^(Name|Domain-0)"); static boost::regex domain_entry("^([^\\s]*)\\s"); each_line(command, {"list"}, [&](string& line) { string domain; if (!boost::regex_match(line, domain_header) && re_search(line, domain_entry, &domain)) { result.domains.emplace_back(move(domain)); } return true; }); } return result; } }}} // namespace facter::facts::resolvers facter-3.14.12/lib/src/facts/resolvers/zfs_resolver.cc0000644005276200011600000000364013702047406022537 0ustar jenkinsjenkins#include #include #include #include #include #include #include using namespace std; using namespace facter::facts; using namespace leatherman::execution; using namespace leatherman::util; namespace facter { namespace facts { namespace resolvers { zfs_resolver::zfs_resolver() : resolver( "ZFS", { fact::zfs_version, fact::zfs_versionnumbers }) { } void zfs_resolver::resolve(collection& facts) { auto data = collect_data(facts); if (!data.version.empty()) { facts.add(fact::zfs_version, make_value(move(data.version))); } if (!data.versions.empty()) { facts.add(fact::zfs_versionnumbers, make_value(boost::join(data.versions, ","))); } } zfs_resolver::data zfs_resolver::collect_data(collection& facts) { data result; // Get the ZFS version static boost::regex zfs_version("currently running ZFS filesystem version (\\d+)[.]"); each_line(zfs_command(), {"upgrade"}, [&] (string& line) { if (re_search(line, zfs_version, &result.version)) { return false; } return true; }); // Get the ZFS versions static boost::regex zfs_supported_version("^\\s*(\\d+)[ ]"); each_line(zfs_command(), {"upgrade", "-v"}, [&] (string& line) { string version; if (re_search(line, zfs_supported_version, &version)) { result.versions.emplace_back(move(version)); } return true; }); return result; } }}} // namespace facter::facts::resolvers facter-3.14.12/lib/src/facts/resolvers/zone_resolver.cc0000644005276200011600000000723713702047406022716 0ustar jenkinsjenkins#include #include #include #include #include #include using namespace std; using namespace facter::facts; namespace facter { namespace facts { namespace resolvers { zone_resolver::zone_resolver() : resolver( "Solaris zone", { fact::zones, fact::zonename, fact::solaris_zones, }, { string("^zone_.+_") + fact::zone_id + "$", string("^zone_.+_") + fact::zone_name + "$", string("^zone_.+_") + fact::zone_status + "$", string("^zone_.+_") + fact::zone_path + "$", string("^zone_.+_") + fact::zone_uuid + "$", string("^zone_.+_") + fact::zone_brand + "$", string("^zone_.+_") + fact::zone_iptype + "$" } ) { } void zone_resolver::resolve(collection& facts) { auto data = collect_data(facts); auto zones = make_value(); for (auto& zone : data.zones) { auto value = make_value(); if (!zone.id.empty()) { facts.add(string("zone_") + zone.name + "_" + fact::zone_id, make_value(zone.id, true)); value->add("id", make_value(move(zone.id))); } if (!zone.name.empty()) { facts.add(string("zone_") + zone.name + "_" + fact::zone_name, make_value(zone.name, true)); } if (!zone.status.empty()) { facts.add(string("zone_") + zone.name + "_" + fact::zone_status, make_value(zone.status, true)); value->add("status", make_value(move(zone.status))); } if (!zone.path.empty()) { facts.add(string("zone_") + zone.name + "_" + fact::zone_path, make_value(zone.path, true)); value->add("path", make_value(move(zone.path))); } if (!zone.uuid.empty()) { facts.add(string("zone_") + zone.name + "_" + fact::zone_uuid, make_value(zone.uuid, true)); value->add("uuid", make_value(move(zone.uuid))); } if (!zone.brand.empty()) { facts.add(string("zone_") + zone.name + "_" + fact::zone_brand, make_value(zone.brand, true)); value->add("brand", make_value(move(zone.brand))); } if (!zone.ip_type.empty()) { facts.add(string("zone_") + zone.name + "_" + fact::zone_iptype, make_value(zone.ip_type, true)); value->add("ip_type", make_value(move(zone.ip_type))); } zones->add(move(zone.name), move(value)); } facts.add(fact::zones, make_value(zones->size(), true)); if (zones->size() > 0) { auto solaris_zones = make_value(); if (!data.current_zone_name.empty()) { solaris_zones->add("current", make_value(data.current_zone_name)); } solaris_zones->add("zones", move(zones)); facts.add(fact::solaris_zones, move(solaris_zones)); } if (!data.current_zone_name.empty()) { facts.add(fact::zonename, make_value(move(data.current_zone_name), true)); } } }}} // namespace facter::facts::resolvers facter-3.14.12/lib/src/facts/resolvers/zpool_resolver.cc0000644005276200011600000000672413702047406023106 0ustar jenkinsjenkins#include #include #include #include #include #include #include using namespace std; using namespace facter::facts; using namespace leatherman::execution; using namespace leatherman::util; namespace facter { namespace facts { namespace resolvers { zpool_resolver::zpool_resolver() : resolver( "ZFS storage pool", { fact::zpool_version, fact::zpool_featureflags, fact::zpool_versionnumbers, }) { } void zpool_resolver::resolve(collection& facts) { auto data = collect_data(facts); if (!data.version.empty()) { facts.add(fact::zpool_version, make_value(move(data.version))); } if (!data.feature_flags.empty()) { facts.add(fact::zpool_featureflags, make_value(boost::join(data.feature_flags, ","))); } if (!data.versions.empty()) { facts.add(fact::zpool_versionnumbers, make_value(boost::join(data.versions, ","))); } } zpool_resolver::data zpool_resolver::collect_data(collection& facts) { data result; enum { UNKNOWN, FEATURES, VERSIONS } state = UNKNOWN; // Get the zpool version and features static boost::regex zpool_version("^This system is currently running ZFS pool version (\\d+)\\.$"); static boost::regex zpool_feature_flags("^This system supports ZFS pool feature flags\\.$"); static boost::regex zpool_supported_feature_header("^The following features are supported:$"); static boost::regex zpool_supported_versions_header("^The following versions are supported:$"); static boost::regex zpool_supported_legacy_versions_header("^The following legacy versions are also supported:$"); static boost::regex zpool_supported_feature("^([[:alnum:]_]+)(\\s+\\(read-only compatible\\))?$"); static boost::regex zpool_supported_version("^\\s*(\\d+)[ ]"); string feature; each_line(zpool_command(), {"upgrade", "-v"}, [&] (string& line) { switch (state) { case UNKNOWN: if (re_search(line, zpool_version, &result.version)) { } else if (re_search(line, zpool_feature_flags)) { result.version = "5000"; } else if (re_search(line, zpool_supported_feature_header)) { state = FEATURES; } else if (re_search(line, zpool_supported_versions_header)) { state = VERSIONS; } break; case FEATURES: if (re_search(line, zpool_supported_feature, &feature)) { result.feature_flags.emplace_back(move(feature)); } else if (re_search(line, zpool_supported_legacy_versions_header)) { state = VERSIONS; } break; case VERSIONS: string feature; if (re_search(line, zpool_supported_version, &feature)) { result.versions.emplace_back(move(feature)); } break; } return true; }); return result; } }}} // namespace facter::facts::resolvers facter-3.14.12/lib/src/facts/scalar_value.cc0000644005276200011600000000343013702047406020426 0ustar jenkinsjenkins#include #include #include #include #include using namespace std; using namespace facter::util; using namespace rapidjson; using namespace YAML; namespace facter { namespace facts { template <> void scalar_value::to_json(json_allocator& allocator, json_value& value) const { value.SetString(_value.c_str(), _value.size()); } template <> void scalar_value::to_json(json_allocator& allocator, json_value& value) const { value.SetInt64(_value); } template <> void scalar_value::to_json(json_allocator& allocator, json_value& value) const { value.SetBool(_value); } template <> void scalar_value::to_json(json_allocator& allocator, json_value& value) const { value.SetDouble(_value); } template <> Emitter& scalar_value::write(Emitter& emitter) const { if (needs_quotation(_value)) { emitter << DoubleQuoted; } emitter << _value; return emitter; } template <> ostream& scalar_value::write(ostream& os, bool quoted, unsigned int level) const { os << boolalpha << _value << noboolalpha; return os; } template <> ostream& scalar_value::write(ostream& os, bool quoted, unsigned int level) const { if (quoted) { os << '"'; } os << _value; if (quoted) { os << '"'; } return os; } template struct scalar_value; template struct scalar_value; template struct scalar_value; template struct scalar_value; }} // namespace facter::facts facter-3.14.12/lib/src/facts/solaris/0000755005276200011600000000000013702047635017136 5ustar jenkinsjenkinsfacter-3.14.12/lib/src/facts/solaris/collection.cc0000644005276200011600000000433413702047406021600 0ustar jenkinsjenkins#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include using namespace std; namespace facter { namespace facts { void collection::add_platform_facts() { add(make_shared()); add(make_shared()); add(make_shared()); add(make_shared()); add(make_shared()); add(make_shared()); add(make_shared()); add(make_shared()); add(make_shared()); add(make_shared()); add(make_shared()); add(make_shared()); add(make_shared()); add(make_shared()); add(make_shared()); // solaris specific add(make_shared()); add(make_shared()); add(make_shared()); add(make_shared()); } }} // namespace facter::facts facter-3.14.12/lib/src/facts/solaris/disk_resolver.cc0000644005276200011600000000223513702047406022316 0ustar jenkinsjenkins#include #include #include #include using namespace std; using namespace facter::util::solaris; namespace facter { namespace facts { namespace solaris { disk_resolver::data disk_resolver::collect_data(collection& facts) { try { data result; k_stat ks; auto ke = ks["sderr"]; for (auto& kv : ke) { disk d; string name = kv.name(); d.name = name.substr(0, name.find(',')); d.product = kv.value("Product"); boost::trim(d.product); d.vendor = kv.value("Vendor"); boost::trim(d.vendor); d.size = static_cast(kv.value("Size")); result.disks.emplace_back(move(d)); } return result; } catch (kstat_exception& ex) { LOG_DEBUG("disk information is unavailable: {1}.", ex.what()); return {}; } } }}} // namespace facter::facts::solaris facter-3.14.12/lib/src/facts/solaris/dmi_resolver.cc0000644005276200011600000000777513702047406022153 0ustar jenkinsjenkins#include #include #include #include #include #include #include #include using namespace std; using namespace leatherman::util; using namespace leatherman::execution; namespace facter { namespace facts { namespace solaris { dmi_resolver::data dmi_resolver::collect_data(collection& facts) { data result; auto isa = facts.get(fact::hardware_isa); if (isa && isa->value() == "i386") { static boost::regex bios_vendor_re("Vendor: (.+)"); static boost::regex bios_version_re("Version String: (.+)"); static boost::regex bios_release_re("Release Date: (.+)"); each_line("/usr/sbin/smbios", {"-t", "SMB_TYPE_BIOS"}, [&](string& line) { if (result.bios_vendor.empty()) { re_search(line, bios_vendor_re, &result.bios_vendor); } if (result.bios_version.empty()) { re_search(line, bios_version_re, &result.bios_version); } if (result.bios_release_date.empty()) { re_search(line, bios_release_re, &result.bios_release_date); } return result.bios_release_date.empty() || result.bios_vendor.empty() || result.bios_version.empty(); }); static boost::regex manufacturer_re("Manufacturer: (.+)"); static boost::regex uuid_re("UUID: (.+)"); static boost::regex serial_re("Serial Number: (.+)"); static boost::regex product_re("Product: (.+)"); each_line("/usr/sbin/smbios", {"-t", "SMB_TYPE_SYSTEM"}, [&](string& line) { if (result.manufacturer.empty()) { re_search(line, manufacturer_re, &result.manufacturer); } if (result.product_name.empty()) { re_search(line, product_re, &result.product_name); } if (result.uuid.empty()) { re_search(line, uuid_re, &result.uuid); } if (result.serial_number.empty()) { re_search(line, serial_re, &result.serial_number); } return result.manufacturer.empty() || result.product_name.empty() || result.uuid.empty() || result.serial_number.empty(); }); static boost::regex chassis_type_re("(?:Chassis )?Type: (.+)"); static boost::regex chassis_asset_tag_re("Asset Tag: (.+)"); each_line("/usr/sbin/smbios", {"-t", "SMB_TYPE_CHASSIS"}, [&](string& line) { if (result.chassis_type.empty()) { re_search(line, chassis_type_re, &result.chassis_type); } if (result.chassis_asset_tag.empty()) { re_search(line, chassis_asset_tag_re, &result.chassis_asset_tag); } return result.chassis_type.empty() || result.chassis_asset_tag.empty(); }); } else if (isa && isa->value() == "sparc") { static boost::regex product_name_manufacturer_re("^System Configuration:\\s+(.+?)\\s+sun\\d+\\S+\\s+(.+)"); each_line("/usr/sbin/prtdiag", [&](string& line) { re_search(line, product_name_manufacturer_re, &result.manufacturer, &result.product_name); return result.manufacturer.empty() || result.product_name.empty(); }); // Manufacturer appears to have two spaces before and after it, but we don't want to rely on that formatting. boost::trim(result.manufacturer); auto exec = execute("/usr/sbin/sneep"); if (exec.success) { result.serial_number = exec.output; } } return result; } }}} // namespace facter::facts::solaris facter-3.14.12/lib/src/facts/solaris/filesystem_resolver.cc0000644005276200011600000000610213702047406023545 0ustar jenkinsjenkins#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include using namespace std; using namespace facter::facts; using namespace facter::util; using namespace facter::util::solaris; using namespace leatherman::util; using namespace boost::filesystem; namespace facter { namespace facts { namespace solaris { filesystem_resolver::data filesystem_resolver::collect_data(collection& facts) { data result; collect_mountpoint_data(result); collect_filesystem_data(result); return result; } void filesystem_resolver::collect_mountpoint_data(data& result) { scoped_file file(fopen("/etc/mnttab", "r")); if (!static_cast(file)) { LOG_ERROR("fopen of /etc/mnttab failed: {1} ({2}): mountpoint data is unavailable.", strerror(errno), errno); return; } mnttab entry; unordered_set auto_home_paths; vector mountpoints; while (getmntent(file, &entry) == 0) { mountpoint point; struct statvfs64 stats; if (statvfs64(entry.mnt_mountp, &stats) != -1) { point.size = stats.f_frsize * stats.f_blocks; point.available = stats.f_frsize * stats.f_bfree; } if (entry.mnt_special == string("auto_home")) { auto_home_paths.emplace(entry.mnt_mountp); continue; } else if (entry.mnt_fstype == string("autofs")) { continue; } point.name = entry.mnt_mountp; point.device = entry.mnt_special; point.filesystem = entry.mnt_fstype; boost::split(point.options, entry.mnt_mntopts, boost::is_any_of(","), boost::token_compress_on); mountpoints.emplace_back(move(point)); } for (auto& point : mountpoints) { auto mount_parent = point.name.substr(0, point.name.find_last_of('/')); // Only add entries that are not mounted from an auto_home setup if (auto_home_paths.count(mount_parent) == 0) { result.mountpoints.emplace_back(move(point)); } } } void filesystem_resolver::collect_filesystem_data(data& result) { // Build a list of mounted filesystems static boost::regex fs_re("^fs/.*/(.*)$"); leatherman::execution::each_line("/usr/sbin/sysdef", [&](string& line) { string fs; if (re_search(line, fs_re, &fs)) { result.filesystems.insert(move(fs)); } return true; }); } }}} // namespace facter::facts::solaris facter-3.14.12/lib/src/facts/solaris/kernel_resolver.cc0000644005276200011600000000127113702047406022643 0ustar jenkinsjenkins#include #include #include using namespace std; namespace facter { namespace facts { namespace solaris { kernel_resolver::data kernel_resolver::collect_data(collection& facts) { data result; struct utsname name; if (uname(&name) == -1) { LOG_WARNING("uname failed: {1} ({2}): kernel facts are unavailable.", strerror(errno), errno); return result; } result.name = name.sysname; result.release = name.release; result.version = name.version; return result; } }}} // namespace facter::facts::solaris facter-3.14.12/lib/src/facts/solaris/ldom_resolver.cc0000644005276200011600000000602313702047406022316 0ustar jenkinsjenkins#include #include #include #include #include #include #include #include #include #include using namespace std; using namespace facter::facts; using namespace leatherman::execution; using namespace leatherman::util; namespace facter { namespace facts { namespace solaris { ldom_resolver::data ldom_resolver::collect_data(collection& facts) { /* Convert virtinfo parseable output format to array of arrays. DOMAINROLE|impl=LDoms|control=true|io=true|service=true|root=true DOMAINNAME|name=primary DOMAINUUID|uuid=8e0d6ec5-cd55-e57f-ae9f-b4cc050999a4 DOMAINCONTROL|name=san-t2k-6 DOMAINCHASSIS|serialno=0704RB0280 For keys containing multiple value such as domain role: ldom_{key}_{subkey} = value Otherwise the fact will simply be: ldom_{key} = value */ data result; auto isa = facts.get(fact::hardware_isa); if (isa && isa->value() != "sparc") { return result; } each_line("/usr/sbin/virtinfo", { "-a", "-p" }, [&] (string& line) { if (!re_search(line, boost::regex("^DOMAIN"))) { return true; } vector items; boost::split(items, line, boost::is_any_of("|")); // The first element is the key, i.e, "domainrole." Subsequent entries are values. if (items.empty()) { return true; } else if (items.size() == 2) { ldom_info ldom_data; string key = items[0]; string value = items[1].substr(items[1].find("=") + 1); transform(key.begin(), key.end(), key.begin(), ::tolower); ldom_data.key = key; ldom_data.values.insert({ key, value }); result.ldom.emplace_back(ldom_data); } else { // When there are multiple values to a line, we insert them all in a single sub-map. ldom_info ldom_data; string base_key = items[0]; // Base key is used as top level sub-key in the structured fact transform(base_key.begin(), base_key.end(), base_key.begin(), ::tolower); ldom_data.key = base_key; items.erase(items.begin()); for (string val : items) { auto pos = val.find("="); string sub_key = val.substr(0, pos); string value = val.substr(pos + 1); ldom_data.values.insert({ sub_key, value }); } result.ldom.emplace_back(ldom_data); } return true; }); return result; } }}} // namespace facter::facts::solaris facter-3.14.12/lib/src/facts/solaris/memory_resolver.cc0000644005276200011600000000631713702047406022701 0ustar jenkinsjenkins#include #include #include #include #include #include #include #include #include #include using namespace std; using namespace facter::util::solaris; using namespace leatherman::execution; using namespace leatherman::util; namespace facter { namespace facts { namespace solaris { memory_resolver::data memory_resolver::collect_data(collection& facts) { data result; const uint64_t page_size = sysconf(_SC_PAGESIZE); const auto max_dev_size = PATH_MAX; try { k_stat ks; auto ke = ks[make_pair("unix", "system_pages")][0]; result.mem_total = ke.value("physmem") * page_size; result.mem_free = ke.value("pagesfree") * page_size; } catch (kstat_exception &ex) { LOG_DEBUG("failed to read memory facts from kstat api: {1}.", ex.what()); uint64_t physmem, pagesfree; static boost::regex physmem_rx("^\\s*physmem\\s+(.+)$"); static boost::regex pagesfree_rx("^\\s*pagesfree\\s+(\\d+)$"); each_line("/usr/bin/kstat", {"-m", "unix", "-n", "system_pages"}, [&] (string& line) { if (re_search(line, physmem_rx, &physmem)) { result.mem_total = physmem * page_size; } else if (re_search(line, pagesfree_rx, &pagesfree)) { result.mem_free = pagesfree * page_size; } return result.mem_total == 0 || result.mem_free == 0; }); } // Swap requires a little more effort. See // https://community.oracle.com/thread/1951228?start=0&tstart=0 // http://www.brendangregg.com/K9Toolkit/swapinfo int num = 0; if ((num = swapctl(SC_GETNSWP, 0)) == -1) { LOG_DEBUG("swapctl failed: {1} ({2}): swap information is unavailable", strerror(errno), errno); return result; } if (num == 0) { // no swap devices configured return result; } // swap devices can be added online. So add one extra. num++; vector buffer(num * sizeof(swapent_t) + sizeof(swaptbl_t)); vector> str_table(num); swaptbl_t* swaps = reinterpret_cast(buffer.data()); swaps->swt_n = num; for (int i = 0; i < num; i++) { str_table[i].resize(max_dev_size); swaps->swt_ent[i].ste_path = str_table[i].data(); } if (swapctl(SC_LIST, swaps) == -1) { LOG_DEBUG("swapctl with SC_LIST failed: {1} ({2}): swap information is unavailable", strerror(errno), errno); return result; } for (int i = 0; i < num; i++) { result.swap_free += swaps->swt_ent[i].ste_free; result.swap_total += swaps->swt_ent[i].ste_pages; } result.swap_free *= page_size; result.swap_total *= page_size; return result; } }}} // namespace facter::facts::solaris facter-3.14.12/lib/src/facts/solaris/networking_resolver.cc0000644005276200011600000001612113702047406023552 0ustar jenkinsjenkins#include #include #include #include #include #include #include #include using namespace std; using namespace facter::util::posix; using namespace facter::util; using namespace leatherman::execution; namespace facter { namespace facts { namespace solaris { networking_resolver::data networking_resolver::collect_data(collection& facts) { auto data = posix::networking_resolver::collect_data(facts); scoped_descriptor ctl(socket(AF_INET, SOCK_DGRAM, 0)); if (static_cast(ctl) == -1) { LOG_DEBUG("socket failed {1} ({2}): interface information is unavailable.", strerror(errno), errno); return data; } // (patterned on bsd impl) lifnum ifnr{AF_UNSPEC, 0, 0}; if (ioctl(ctl, SIOCGLIFNUM, &ifnr) == -1) { LOG_DEBUG("ioctl with SIOCGLIFNUM failed: {1} ({2}): interface information is unavailable.", strerror(errno), errno); return data; } vector buffer(ifnr.lifn_count); lifconf lifc = {AF_UNSPEC, 0, static_cast(buffer.size() * sizeof(lifreq)), reinterpret_cast(buffer.data())}; if (ioctl(ctl, SIOCGLIFCONF, &lifc) == -1) { LOG_DEBUG("ioctl with SIOCGLIFCONF failed: {1} ({2}): interface information is unavailable.", strerror(errno), errno); return data; } // put them in a multimap so that similar address can be // grouped together. multimap interface_map; for (lifreq const& lreq : buffer) { interface_map.insert({lreq.lifr_name, &lreq}); } data.primary_interface = get_primary_interface(); // Walk the interfaces decltype(interface_map.begin()) it = interface_map.begin(); while (it != interface_map.end()) { string const& name = it->first; interface iface; iface.name = name; // Populate the MAC address and MTU once per interface populate_macaddress(iface, it->second); populate_mtu(iface, it->second); // Walk the addresses for this interface do { populate_binding(iface, it->second); ++it; } while (it != interface_map.end() && it->first == name); // Find the DCHP server for the interface iface.dhcp_server = find_dhcp_server(name); data.interfaces.emplace_back(move(iface)); } return data; } void networking_resolver::populate_binding(interface& iface, lifreq const* addr) const { // Populate the correct bindings list vector* bindings = nullptr; if (addr->lifr_addr.ss_family == AF_INET) { bindings = &iface.ipv4_bindings; } else if (addr->lifr_addr.ss_family == AF_INET) { bindings = &iface.ipv6_bindings; } if (!bindings) { return; } // Create a binding binding b; b.address = address_to_string(reinterpret_cast(&addr->lifr_addr)); // Get the netmask scoped_descriptor ctl(socket(addr->lifr_addr.ss_family, SOCK_DGRAM, 0)); if (static_cast(ctl) == -1) { LOG_DEBUG("socket failed: {1} ({2}): netmask and network for interface {3} are unavailable.", strerror(errno), errno, addr->lifr_name); } else { lifreq netmask_addr = *addr; if (ioctl(ctl, SIOCGLIFNETMASK, &netmask_addr) == -1) { LOG_DEBUG("ioctl with SIOCGLIFNETMASK failed: {1} ({2}): netmask and network for interface {3} are unavailable.", strerror(errno), errno, addr->lifr_name); } else { b.netmask = address_to_string(reinterpret_cast(&netmask_addr.lifr_addr)); b.network = address_to_string(reinterpret_cast(&addr->lifr_addr), reinterpret_cast(&netmask_addr.lifr_addr)); } } bindings->emplace_back(std::move(b)); } void networking_resolver::populate_macaddress(interface& iface, lifreq const* addr) const { scoped_descriptor ctl(socket(addr->lifr_addr.ss_family, SOCK_DGRAM, 0)); if (static_cast(ctl) == -1) { LOG_DEBUG("socket failed: {1} ({2}): link level address for interface {3} is unavailable.", strerror(errno), errno, addr->lifr_name); return; } arpreq arp; sockaddr_in* arp_addr = reinterpret_cast(&arp.arp_pa); arp_addr->sin_addr.s_addr = reinterpret_cast(&addr->lifr_addr)->sin_addr.s_addr; if (ioctl(ctl, SIOCGARP, &arp) == -1) { LOG_DEBUG("ioctl with SIOCGARP failed: {1} ({2}): link level address for {3} is unavailable.", strerror(errno), errno, addr->lifr_name); return; } iface.macaddress = macaddress_to_string(reinterpret_cast(arp.arp_ha.sa_data)); } void networking_resolver::populate_mtu(interface& iface, lifreq const* addr) const { scoped_descriptor ctl(socket(addr->lifr_addr.ss_family, SOCK_DGRAM, 0)); if (static_cast(ctl) == -1) { LOG_DEBUG("socket failed: {1} ({2}): MTU for interface {3} is unavailable.", strerror(errno), errno, addr->lifr_name); return; } lifreq mtu = *addr; if (ioctl(ctl, SIOCGLIFMTU, &mtu) == -1) { LOG_DEBUG("ioctl with SIOCGLIFMTU failed: {1} ({2}): MTU for interface {3} is unavailable.", strerror(errno), errno, addr->lifr_name); return; } iface.mtu = mtu.lifr_metric; } string networking_resolver::get_primary_interface() const { string interface; each_line("route", { "-n", "get", "default" }, [&interface](string& line){ boost::trim(line); if (boost::starts_with(line, "interface: ")) { interface = line.substr(11); boost::trim(interface); return false; } return true; }); LOG_DEBUG("got primary interface: \"{1}\"", interface); return interface; } bool networking_resolver::is_link_address(const sockaddr* addr) const { // We explicitly populate the MAC address; we don't need address_to_string to support link layer addresses return false; } uint8_t const* networking_resolver::get_link_address_bytes(const sockaddr * addr) const { return nullptr; } uint8_t networking_resolver::get_link_address_length(const sockaddr * addr) const { return 0; } string networking_resolver::find_dhcp_server(string const& interface) const { auto exec = execute("dhcpinfo", { "-i", interface, "ServerID" }); if (!exec.success) { return {}; } return exec.output; } }}} // namespace facter::facts::solaris facter-3.14.12/lib/src/facts/solaris/operating_system_resolver.cc0000644005276200011600000000626413702047406024766 0ustar jenkinsjenkins#include #include #include #include #include using namespace std; using namespace leatherman::util; namespace lth_file = leatherman::file_util; namespace facter { namespace facts { namespace solaris { static string get_family(string const& name) { if (!name.empty()) { static map const systems = { { string(os::sunos), string(os_family::solaris) }, { string(os::solaris), string(os_family::solaris) }, { string(os::nexenta), string(os_family::solaris) }, { string(os::omni), string(os_family::solaris) }, { string(os::open_indiana), string(os_family::solaris) }, { string(os::smart), string(os_family::solaris) }, }; auto const& it = systems.find(name); if (it != systems.end()) { return it->second; } } return {}; } operating_system_resolver::data operating_system_resolver::collect_data(collection& facts) { // Default to the base implementation auto result = posix::operating_system_resolver::collect_data(facts); if (result.name == os::sunos) { result.name = os::solaris; } auto family = get_family(result.name); if (!family.empty()) { result.family = move(family); } /* Oracle Solaris 10 1/13 s10x_u11wos_24a X86 Oracle Solaris 10 9/10 s10s_u9wos_14a SPARC Oracle Solaris 11 11/11 X86 Oracle Solaris 11.2 X86 There are a few places (operatingsystemmajrelease,...) where s10 and s11 differ for similar versioning. For e.g it shifts from `10_u11` to `11 11/11` these needs to be resolved further using the `pkg info kernel` command (TODO). */ static boost::regex regexp_s10("Solaris \\d+ \\d+/\\d+ s(\\d+)[sx]?_u(\\d+)wos_"); static boost::regex regexp_s11("Solaris (\\d+)[.](\\d+)"); static boost::regex regexp_s11b("Solaris (\\d+) "); lth_file::each_line("/etc/release", [&](string& line) { string major, minor; if (re_search(line, regexp_s10, &major, &minor)) { result.release = major + "_u" + minor; result.major = move(major); result.minor = move(minor); return false; } else if (re_search(line, regexp_s11, &major, &minor)) { result.release = major + "." + minor; result.major = move(major); result.minor = move(minor); return false; } else if (re_search(line, regexp_s11b, &major)) { result.release = major + ".0"; result.major = move(major); result.minor = "0"; return false; } return true; }); return result; } }}} // namespace facter::facts::solaris facter-3.14.12/lib/src/facts/solaris/processor_resolver.cc0000644005276200011600000001047013702047406023403 0ustar jenkinsjenkins#include #include #include #include #include #include #include using namespace std; using namespace facter::util::solaris; using namespace leatherman::util; using namespace leatherman::execution; /* * https://blogs.oracle.com/mandalika/entry/solaris_show_me_the_cpu * What we want to do is to count the distinct number of chip_id (#nproc), * then the distinct number of core_id (#ncores) and the number of instances * of hardware threads (given by valid procid). * * Our info comes from the following structure * $ kstat -m cpu_info module: cpu_info instance: 0 name: cpu_info0 class: misc brand Intel(r) Core(tm) i7-4850HQ CPU @ 2.30GHz cache_id 0 chip_id 0 clock_MHz 2300 clog_id 0 core_id 0 cpu_type i386 crtime 6.654772184 current_clock_Hz 2294715939 current_cstate 0 family 6 fpu_type i387 compatible implementation x86 (chipid 0x0 GenuineIntel family 6 model 70 step 1 clock 2300 MHz) model 70 ncore_per_chip 1 ncpu_per_chip 1 pg_id -1 pkg_core_id 0 snaptime 22631.883297199 state on-line state_begin 1409334365 stepping 1 supported_frequencies_Hz 2294715939 supported_max_cstates 1 vendor_id GenuineIntel */ namespace facter { namespace facts { namespace solaris { processor_resolver::data processor_resolver::collect_data(collection& facts) { auto result = posix::processor_resolver::collect_data(facts); try { unordered_set chips; k_stat kc; auto kv = kc["cpu_info"]; for (auto const& ke : kv) { try { ++result.logical_count; result.models.emplace_back(ke.value("brand")); chips.insert(ke.value("chip_id")); // Get the speed of the first processor if (result.speed == 0) { result.speed = static_cast(ke.value("current_clock_Hz")); } } catch (kstat_exception& ex) { LOG_DEBUG("failed to read processor data entry: {1}.", ex.what()); } } result.physical_count = chips.size(); } catch (kstat_exception& ex) { LOG_DEBUG("failed to read processor data from kstat api: {1}.", ex.what()); unordered_set chips; string brand; int32_t chip_id; int64_t current_clock_hz; static boost::regex brand_rx("^\\s*brand\\s+(.+)$"); static boost::regex chip_id_rx("^\\s*chip_id\\s+(\\d+)$"); static boost::regex current_clock_hz_rx("^\\s*current_clock_Hz\\s+(\\d+)$"); each_line("/usr/bin/kstat", {"cpu_info"}, [&] (string& line) { if (re_search(line, brand_rx, &brand)) { result.models.emplace_back(move(brand)); } else if (re_search(line, chip_id_rx, &chip_id)) { ++result.logical_count; chips.insert(chip_id); } else if (result.speed == 0 && re_search(line, current_clock_hz_rx, ¤t_clock_hz)) { result.speed = current_clock_hz; } return true; }); result.physical_count = chips.size(); } return result; } }}} // namespace facter::facts::solaris facter-3.14.12/lib/src/facts/solaris/virtualization_resolver.cc0000644005276200011600000000266313702047406024455 0ustar jenkinsjenkins#include #include #include #include #include #include #include #include #include using namespace std; using namespace facter::facts; using namespace leatherman::execution; namespace facter { namespace facts { namespace solaris { string virtualization_resolver::get_hypervisor(collection& facts) { // If in an LDom, the LDom facts will resolve and we can use them to identify // that we're in a virtual LDom environment. They should only resolve on SPARC. auto ldom_domainrole_control = facts.get("ldom_domainrole_control"); if (ldom_domainrole_control && ldom_domainrole_control->value() == "false") { auto ldom_domainrole_impl = facts.get("ldom_domainrole_impl"); if (ldom_domainrole_impl) { return ldom_domainrole_impl->value(); } } // works for both x86 & sparc. auto exec = execute("/usr/bin/zonename"); if (exec.success && exec.output != "global") { return vm::zone; } // Look for hypervisor matches based on other facts return get_fact_vm(facts); } }}} // namespace facter::facts::solaris facter-3.14.12/lib/src/facts/solaris/zfs_resolver.cc0000644005276200011600000000037513702047406022171 0ustar jenkinsjenkins#include using namespace std; namespace facter { namespace facts { namespace solaris { string zfs_resolver::zfs_command() { return "/sbin/zfs"; } }}} // namespace facter::facts::solaris facter-3.14.12/lib/src/facts/solaris/zone_resolver.cc0000644005276200011600000000213613702047406022337 0ustar jenkinsjenkins#include #include #include #include #include using namespace std; using namespace facter::facts; using namespace leatherman::util; using namespace leatherman::execution; namespace facter { namespace facts { namespace solaris { zone_resolver::data zone_resolver::collect_data(collection& facts) { data result; auto exec = execute("/bin/zonename"); if (exec.success) { result.current_zone_name = exec.output; } static boost::regex zone_pattern("(\\d+|-):([^:]*):([^:]*):([^:]*):([^:]*):([^:]*):([^:]*)"); each_line("/usr/sbin/zoneadm", {"list", "-cp"}, [&](string& line) { zone z; if (re_search(line, zone_pattern, &z.id, &z.name, &z.status, &z.path, &z.uuid, &z.brand, &z.ip_type)) { result.zones.emplace_back(move(z)); } return true; }); return result; } }}} // namespace facter::facts::solaris facter-3.14.12/lib/src/facts/solaris/zpool_resolver.cc0000644005276200011600000000040513702047406022524 0ustar jenkinsjenkins#include using namespace std; namespace facter { namespace facts { namespace solaris { string zpool_resolver::zpool_command() { return "/sbin/zpool"; } }}} // namespace facter::facts::solaris facter-3.14.12/lib/src/facts/windows/0000755005276200011600000000000013702047635017154 5ustar jenkinsjenkinsfacter-3.14.12/lib/src/facts/windows/cache.cc0000644005276200011600000000054113702047406020522 0ustar jenkinsjenkins#include #include namespace facter { namespace facts { namespace cache { std::string fact_cache_location() { return leatherman::windows::file_util::get_programdata_dir() + "\\PuppetLabs\\facter\\cache\\cached_facts\\"; } }}} // namespace facter::facts::cache facter-3.14.12/lib/src/facts/windows/collection.cc0000644005276200011600000000610513702047406021614 0ustar jenkinsjenkins#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include using namespace std; using namespace leatherman::windows; using namespace leatherman::util; using namespace facter::facts::external; using namespace boost::filesystem; namespace facter { namespace facts { vector collection::get_external_fact_directories() const { if (user::is_admin()) { // Get the common data path try { path p = file_util::get_programdata_dir() / "PuppetLabs" / "facter" / "facts.d"; return {p.string()}; } catch (file_util::unknown_folder_exception &e) { LOG_WARNING("external facts unavailable, %1%", e.what()); } } else { auto home = user::home_dir(); if (!home.empty()) { path p1 = path(home) / ".puppetlabs" / "opt" / "facter" / "facts.d"; path p2 = path(home) / ".facter" / "facts.d"; return {p1.string(), p2.string()}; } LOG_DEBUG("HOME environment variable not set, external facts unavailable"); } return {}; } void collection::add_platform_facts() { #ifdef HAS_LTH_GET_DWORD add(make_shared()); #endif add(make_shared()); add(make_shared()); add(make_shared()); add(make_shared()); add(make_shared()); add(make_shared()); add(make_shared()); try { shared_ptr shared_wmi = make_shared(); add(make_shared(shared_wmi)); add(make_shared(shared_wmi)); add(make_shared(shared_wmi)); add(make_shared(shared_wmi)); } catch (wmi_exception &e) { LOG_ERROR("failed adding platform facts that require WMI: {1}", e.what()); } } }} // namespace facter::facts facter-3.14.12/lib/src/facts/windows/dmi_resolver.cc0000644005276200011600000000251713702047406022156 0ustar jenkinsjenkins#include #include #include using namespace std; using namespace leatherman::windows; namespace facter { namespace facts { namespace windows { dmi_resolver::dmi_resolver(shared_ptr wmi_conn) : resolvers::dmi_resolver(), _wmi(move(wmi_conn)) { } dmi_resolver::data dmi_resolver::collect_data(collection& facts) { data result; auto vals = _wmi->query(wmi::computersystemproduct, {wmi::name, wmi::uuid}); if (vals.empty()) { LOG_DEBUG("WMI query returned no results for {1} with values {2} and {3}.", wmi::computersystemproduct, wmi::name, wmi::uuid); } else { result.product_name = wmi::get(vals, wmi::name); result.uuid = wmi::get(vals, wmi::uuid); } vals = _wmi->query(wmi::bios, {wmi::manufacturer, wmi::serialnumber}); if (vals.empty()) { LOG_DEBUG("WMI query returned no results for {1} with values {2} and {3}.", wmi::bios, wmi::serialnumber, wmi::manufacturer); } else { result.serial_number = wmi::get(vals, wmi::serialnumber); result.manufacturer = wmi::get(vals, wmi::manufacturer); } return result; } }}} // namespace facter::facts::windows facter-3.14.12/lib/src/facts/windows/external_resolvers_factory.cc0000644005276200011600000000223113702047406025132 0ustar jenkinsjenkins#include #include #include #include #include using namespace std; using namespace boost::filesystem; namespace facter { namespace facts { bool external_resolvers_factory::powershell_resolver_can_resolve(string const& file) { try { path p = file; return boost::iends_with(file, ".ps1") && is_regular_file(p); } catch (filesystem_error &e) { LOG_TRACE("error reading status of path {1}: {2}", file, e.what()); return false; } } shared_ptr external_resolvers_factory::get_resolver(const string& path) { auto resolver = get_common_resolver(path); if (resolver) return resolver; if (powershell_resolver_can_resolve(path)) { return make_shared(path); } throw external::external_fact_no_resolver(leatherman::locale::_("No resolver for external facts file {1}", path)); } }} // namespace facter::facts facter-3.14.12/lib/src/facts/windows/fips_resolver.cc0000644005276200011600000000173513702047406022347 0ustar jenkinsjenkins#include #include #include #include using namespace std; using boost::lexical_cast; using boost::bad_lexical_cast; using namespace leatherman::windows; namespace facter { namespace facts { namespace windows { fips_resolver::data fips_resolver::collect_data(collection& facts) { data result; // Set a safe default result.is_fips_mode_enabled = false; unsigned long enabled; try { enabled = registry::get_registry_dword(registry::HKEY::LOCAL_MACHINE, "System\\CurrentControlSet\\Control\\Lsa\\FipsAlgorithmPolicy\\", "Enabled"); result.is_fips_mode_enabled = enabled != 0; } catch (registry_exception &e) { LOG_DEBUG("failure getting fips_mode: {1}", e.what()); } return result; } }}} // namespace facter::facts::windows facter-3.14.12/lib/src/facts/windows/identity_resolver.cc0000644005276200011600000000330713702047406023234 0ustar jenkinsjenkins#include #include #include #include #include #include #include using namespace std; using namespace leatherman::windows; namespace facter { namespace facts { namespace windows { identity_resolver::data identity_resolver::collect_data(collection& facts) { data result; // Groups are a lot more flexible on Windows than Linux. We only support // identifying the user right now. ULONG size = 0ul; auto nameformat = NameSamCompatible; GetUserNameExW(nameformat, nullptr, &size); if (GetLastError() != ERROR_MORE_DATA) { LOG_DEBUG("failure resolving identity facts: {1}", leatherman::windows::system_error()); return result; } // Use the string as a raw buffer that supports move and ref operations. wstring buffer(size, '\0'); if (!GetUserNameExW(nameformat, &buffer[0], &size)) { LOG_DEBUG("failure resolving identity facts: {1}", leatherman::windows::system_error()); return result; } // Resize the buffer to the returned string size. buffer.resize(size); result.user_name = boost::nowide::narrow(buffer); // Check whether this thread is running with elevated privileges // (or with the privileges of the local Administrators group on // older versions of Windows not supporting privileges elevation). result.privileged = user::is_admin(); return result; } }}} // facter::facts::windows facter-3.14.12/lib/src/facts/windows/kernel_resolver.cc0000644005276200011600000000317413702047406022665 0ustar jenkinsjenkins#include #include #include #include #include #include #include #include using namespace std; using namespace leatherman::dynamic_library; using RtlGetVersionPtr = NTSTATUS (WINAPI *)(PRTL_OSVERSIONINFOW); namespace facter { namespace facts { namespace windows { static boost::optional get_release() { dynamic_library ntoskrnl; if (! ntoskrnl.load("ntoskrnl.exe")) { return boost::none; } auto rtlGetVersion = reinterpret_cast( ntoskrnl.find_symbol("RtlGetVersion")); if (! rtlGetVersion) { return boost::none; } OSVERSIONINFOW versionInfo; if (rtlGetVersion(&versionInfo) != STATUS_SUCCESS) { LOG_DEBUG("failed to get the OS version information from RtlGetVersion"); return boost::none; } auto versionStr = (boost::format("%1%.%2%.%3%") % versionInfo.dwMajorVersion % versionInfo.dwMinorVersion % versionInfo.dwBuildNumber).str(); return versionStr; } kernel_resolver::data kernel_resolver::collect_data(collection& facts) { data result; auto release = get_release(); if (release) { result.release = move(*release); result.version = result.release; } result.name = os::windows; return result; } }}} // namespace facter::facts::windows facter-3.14.12/lib/src/facts/windows/memory_resolver.cc0000644005276200011600000000146213702047406022713 0ustar jenkinsjenkins#include #include #include #include #include using namespace leatherman::windows; namespace facter { namespace facts { namespace windows { memory_resolver::data memory_resolver::collect_data(collection& facts) { PERFORMANCE_INFORMATION statex; if (!GetPerformanceInfo(&statex, sizeof(statex))) { LOG_DEBUG("resolving memory facts failed: {1}", system_error()); return {}; } data result; result.mem_total = statex.PhysicalTotal*statex.PageSize; result.mem_free = statex.PhysicalAvailable*statex.PageSize; return result; } }}} // namespace facter::facts::windows facter-3.14.12/lib/src/facts/windows/networking_resolver.cc0000644005276200011600000002324013702047406023570 0ustar jenkinsjenkins#include #include #include #include #include #include #include #include #include #include #include #ifdef interface // Something's bleeding in and making it impossible to instantiate an interface object. #undef interface #endif using namespace std; using namespace facter::util; using namespace facter::util::windows; using namespace leatherman::windows; namespace facter { namespace facts { namespace windows { networking_resolver::networking_resolver() { } static string get_computername(COMPUTER_NAME_FORMAT nameFormat) { DWORD size = 0u; GetComputerNameExW(nameFormat, nullptr, &size); if (GetLastError() != ERROR_MORE_DATA) { LOG_DEBUG("failure resolving hostname: {1}", leatherman::windows::system_error()); return ""; } wstring buffer(size, '\0'); if (!GetComputerNameExW(nameFormat, &buffer[0], &size)) { LOG_DEBUG("failure resolving hostname: {1}", leatherman::windows::system_error()); return ""; } buffer.resize(size); return boost::nowide::narrow(buffer); } sockaddr_in networking_resolver::create_ipv4_mask(uint8_t masklen) { sockaddr_in mask = {AF_INET}; if (ConvertLengthToIpv4Mask(masklen, &mask.sin_addr.S_un.S_addr) != NO_ERROR) { LOG_DEBUG("failed creating IPv4 mask of length {1}", masklen); } return mask; } sockaddr_in6 networking_resolver::create_ipv6_mask(uint8_t masklen) { sockaddr_in6 mask = {AF_INET6}; const uint8_t incr = 32u; for (size_t i = 0; i < 16 && masklen > 0; i += 4, masklen -= min(masklen, incr)) { if (ConvertLengthToIpv4Mask(min(masklen, incr), reinterpret_cast(&mask.sin6_addr.u.Byte[i])) != NO_ERROR) { LOG_DEBUG("failed creating IPv6 mask with component of length {1}", incr); break; } } return mask; } sockaddr_in networking_resolver::mask_ipv4_address(sockaddr const* addr, sockaddr_in const& mask) { sockaddr_in masked = *reinterpret_cast(addr); masked.sin_addr.S_un.S_addr &= mask.sin_addr.S_un.S_addr; return masked; } sockaddr_in6 networking_resolver::mask_ipv6_address(sockaddr const* addr, sockaddr_in6 const& mask) { sockaddr_in6 masked = *reinterpret_cast(addr); for (size_t i = 0; i < 8; ++i) { masked.sin6_addr.u.Word[i] &= mask.sin6_addr.u.Word[i]; } return masked; } networking_resolver::data networking_resolver::collect_data(collection& facts) { data result; result.hostname = get_computername(ComputerNameDnsHostname); try { result.domain = registry::get_registry_string(registry::HKEY::LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters\\", "Domain"); } catch (registry_exception &e) { LOG_DEBUG("failure getting networking::domain fact: {1}", e.what()); } // Get linked list of adapters. ULONG family = AF_UNSPEC; ULONG flags = GAA_FLAG_SKIP_ANYCAST | GAA_FLAG_SKIP_MULTICAST | GAA_FLAG_SKIP_DNS_SERVER; // Pre-allocate and try several times, because the adapter configuration may change between calls. ULONG outBufLen = 15000; vector pAddresses(outBufLen); DWORD err; for (int i = 0; i < 3; ++i) { err = GetAdaptersAddresses(family, flags, nullptr, reinterpret_cast(pAddresses.data()), &outBufLen); if (err == ERROR_SUCCESS) { break; } else if (err == ERROR_BUFFER_OVERFLOW) { pAddresses.resize(outBufLen); } else { LOG_DEBUG("failure resolving networking facts: {1}", leatherman::windows::system_error(err)); return result; } } if (err != ERROR_SUCCESS) { LOG_DEBUG("failure resolving networking facts: {1}", leatherman::windows::system_error(err)); return result; } facter::util::windows::wsa winsock; for (auto pCurAddr = reinterpret_cast(pAddresses.data()); pCurAddr; pCurAddr = pCurAddr->Next) { if (pCurAddr->OperStatus != IfOperStatusUp || (pCurAddr->IfType != IF_TYPE_ETHERNET_CSMACD && pCurAddr->IfType != IF_TYPE_IEEE80211)) { continue; } if (result.domain.empty()) { // If domain isn't set in the registry, fall back to the first DnsDomain encountered in the adapters. result.domain = boost::nowide::narrow(pCurAddr->DnsSuffix); } interface net_interface; net_interface.name = boost::nowide::narrow(pCurAddr->FriendlyName); // Only supported on platforms after Windows Server 2003. if (pCurAddr->Flags & IP_ADAPTER_DHCP_ENABLED && pCurAddr->Length >= sizeof(IP_ADAPTER_ADDRESSES_LH)) { auto adapter = reinterpret_cast(*pCurAddr); if (adapter.Flags & IP_ADAPTER_DHCP_ENABLED) { try { net_interface.dhcp_server = winsock.saddress_to_string(adapter.Dhcpv4Server); } catch (wsa_exception &e) { LOG_DEBUG("failed to retrieve dhcp v4 server address for {1}: {2}", net_interface.name, e.what()); } } } for (auto it = pCurAddr->FirstUnicastAddress; it; it = it->Next) { string addr; try { addr = winsock.saddress_to_string(it->Address); } catch (wsa_exception &e) { string iptype = (it->Address.lpSockaddr->sa_family == AF_INET) ? " v4" : (it->Address.lpSockaddr->sa_family == AF_INET6) ? " v6" : ""; LOG_DEBUG("failed to retrieve ip{1} address for {2}: {3}", iptype, net_interface.name, e.what()); } if (addr.empty()) { continue; } if (it->Address.lpSockaddr->sa_family == AF_INET || it->Address.lpSockaddr->sa_family == AF_INET6) { bool ipv6 = it->Address.lpSockaddr->sa_family == AF_INET6; binding b; // IpAddress6 contains interface identifier, and should be removed when returning the ipaddress6 b.address = ipv6 ? addr.substr(0, addr.find('%')) : addr; // Need to do lookup based on the structure length. auto adapterAddr = reinterpret_cast(*it); if (ipv6) { auto mask = create_ipv6_mask(adapterAddr.OnLinkPrefixLength); auto masked = mask_ipv6_address(it->Address.lpSockaddr, mask); b.netmask = winsock.address_to_string(mask); b.network = winsock.address_to_string(masked); // Network6 also contains the interface identifier, so it should be removed b.network = b.network.substr(0, b.network.find('%')); } else { auto mask = create_ipv4_mask(adapterAddr.OnLinkPrefixLength); auto masked = mask_ipv4_address(it->Address.lpSockaddr, mask); b.netmask = winsock.address_to_string(mask); b.network = winsock.address_to_string(masked); } if (ipv6) { net_interface.ipv6_bindings.emplace_back(std::move(b)); } else { net_interface.ipv4_bindings.emplace_back(std::move(b)); } // http://support.microsoft.com/kb/894564 talks about how binding order is determined. // GetAdaptersAddresses returns adapters in binding order. This way, the domain and primary_interface match. // The old facter behavior didn't make a lot of sense (it would pick the last in binding order, not 1st). // Only accept this as a primary interface if it has a non-link-local address. if (result.primary_interface.empty() && ( (it->Address.lpSockaddr->sa_family == AF_INET && !ignored_ipv4_address(addr)) || (it->Address.lpSockaddr->sa_family == AF_INET6 && !ignored_ipv6_address(addr)))) { result.primary_interface = net_interface.name; } } } stringstream macaddr; for (DWORD i = 0u; i < pCurAddr->PhysicalAddressLength; ++i) { macaddr << setfill('0') << setw(2) << hex << uppercase << static_cast(pCurAddr->PhysicalAddress[i]) << ':'; } net_interface.macaddress = macaddr.str(); if (!net_interface.macaddress.empty()) { net_interface.macaddress.pop_back(); } net_interface.mtu = pCurAddr->Mtu; result.interfaces.emplace_back(move(net_interface)); } return result; } }}} // namespace facter::facts::windows facter-3.14.12/lib/src/facts/windows/operating_system_resolver.cc0000644005276200011600000001652113702047406025001 0ustar jenkinsjenkins#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include using namespace std; using namespace leatherman::util; using namespace leatherman::windows; using namespace boost::filesystem; namespace facter { namespace facts { namespace windows { static string get_hardware() { SYSTEM_INFO sysInfo; GetNativeSystemInfo(&sysInfo); switch (sysInfo.wProcessorArchitecture) { case PROCESSOR_ARCHITECTURE_AMD64: return "x86_64"; case PROCESSOR_ARCHITECTURE_ARM: return "arm"; case PROCESSOR_ARCHITECTURE_IA64: return "ia64"; case PROCESSOR_ARCHITECTURE_INTEL: return "i" + to_string((sysInfo.wProcessorLevel > 5) ? 6 : sysInfo.wProcessorLevel) + "86"; default: return "unknown"; } } static string get_architecture(string const& hardware) { // Use "x86" for 32-bit systems if (re_search(hardware, boost::regex("i[3456]86"))) { return "x86"; } else if (hardware == "x86_64") { return "x64"; } return hardware; } static string get_system32() { // When facter is a 32-bit process running on 64-bit windows (such as in a 32-bit puppet installation that // includes native facter), system32 points to 32-bit executables; Windows invisibly redirects it. It also // provides a link at %SYSTEMROOT%\sysnative for the 64-bit versions. Return the system path where OS-native // executables can be found. BOOL isWow = FALSE; if (!IsWow64Process(GetCurrentProcess(), &isWow)) { LOG_DEBUG("Could not determine if we are running in WOW64: {1}", leatherman::windows::system_error()); } string szPath; if (!environment::get("SystemRoot", szPath)) { LOG_DEBUG("error finding SYSTEMROOT: {1}", leatherman::windows::system_error()); } if (isWow) { return ((path(szPath) / "sysnative").string()); } else { return ((path(szPath) / "system32").string()); } } static string get_release_id() { string releaseID; try { releaseID = registry::get_registry_string(registry::HKEY::LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\", "ReleaseId"); } catch (registry_exception &e) { LOG_DEBUG("failure getting ReleaseId: {1}", e.what()); } return releaseID; } static string get_edition_id() { string editionID; try { editionID = registry::get_registry_string(registry::HKEY::LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\", "EditionID"); } catch (registry_exception &e) { LOG_DEBUG("failure getting EditionID: {1}", e.what()); } return editionID; } static string get_installation_type() { string installation_type; try { installation_type = registry::get_registry_string(registry::HKEY::LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\", "InstallationType"); } catch (registry_exception &e) { LOG_DEBUG("failure getting InstallationType: {1}", e.what()); } return installation_type; } static string get_product_name() { string product_name; try { product_name = registry::get_registry_string(registry::HKEY::LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\", "ProductName"); } catch (registry_exception &e) { LOG_DEBUG("failure getting ProductName: {1}", e.what()); } return product_name; } operating_system_resolver::operating_system_resolver(shared_ptr wmi_conn) : resolvers::operating_system_resolver(), _wmi(move(wmi_conn)) { } operating_system_resolver::data operating_system_resolver::collect_data(collection& facts) { // Default to the base implementation data result = resolvers::operating_system_resolver::collect_data(facts); result.family = os_family::windows; result.hardware = get_hardware(); result.architecture = get_architecture(result.hardware); result.win.system32 = get_system32(); result.win.release_id = get_release_id(); result.win.edition_id = get_edition_id(); result.win.installation_type = get_installation_type(); result.win.product_name = get_product_name(); auto lastDot = result.release.rfind('.'); if (lastDot == string::npos) { return result; } auto vals = _wmi->query(wmi::operatingsystem, {wmi::producttype, wmi::othertypedescription}); if (vals.empty()) { return result; } // Override default release with Windows release names auto version = result.release.substr(0, lastDot); bool consumerrel = (wmi::get(vals, wmi::producttype) == "1"); if (version == "10.0") { // Calculate the build number to distinguish between // Windows Server 2016 and 2019. Note that the kernel // version is written as .. auto kernel_version_fact = facts.get(fact::kernel_version); if (! kernel_version_fact) { LOG_DEBUG("Could not resolve the OS release and OS major version facts from the kernel version fact"); return result; } auto kernel_version = kernel_version_fact->value(); auto build_number_as_str = kernel_version.substr( kernel_version.find_last_of('.') + 1); auto build_number = stol(build_number_as_str); if (consumerrel) { result.release = "10"; } else if (build_number >= 17623L) { result.release = "2019"; } else { result.release = "2016"; } } else if (version == "6.3") { result.release = consumerrel ? "8.1" : "2012 R2"; } else if (version == "6.2") { result.release = consumerrel ? "8" : "2012"; } else if (version == "6.1") { result.release = consumerrel ? "7" : "2008 R2"; } else if (version == "6.0") { result.release = consumerrel ? "Vista" : "2008"; } else if (version == "5.2") { if (consumerrel) { result.release = "XP"; } else { result.release = (wmi::get(vals, wmi::othertypedescription) == "R2") ? "2003 R2" : "2003"; } } result.major = result.release; return result; } }}} // namespace facter::facts::windows facter-3.14.12/lib/src/facts/windows/processor_resolver.cc0000644005276200011600000000657613702047406023435 0ustar jenkinsjenkins#include #include #include #include #include using namespace std; using namespace leatherman::util; using namespace leatherman::windows; using facter::util::maybe_stoi; namespace facter { namespace facts { namespace windows { processor_resolver::processor_resolver(shared_ptr wmi_conn) : resolvers::processor_resolver(), _wmi(move(wmi_conn)) { } // Returns physical_count, logical_count, models, isa, speed static tuple, string, int64_t> get_processors(wmi const& _wmi) { vector models; string isa; int logical_count = 0; auto procs = _wmi.query(wmi::processor, {wmi::name, wmi::architecture}); if (procs.empty()) { LOG_DEBUG("WMI processor Name, Architecture query returned no results."); } for (auto const& procobj : procs) { models.emplace_back(wmi::get(procobj, wmi::name)); if (!isa.empty()) { continue; } // Query for architecture and transform numerical ID into a string based on // https://msdn.microsoft.com/en-us/library/aa394373%28v=vs.85%29.aspx. // Use the architecture of the first result. auto maybe_architecture = maybe_stoi(wmi::get(procobj, wmi::architecture)); if (!maybe_architecture) { continue; } int architecture = maybe_architecture.get(); switch (architecture) { case 0: isa = "x86"; break; case 1: isa = "MIPS"; break; case 2: isa = "Alpha"; break; case 3: isa = "PowerPC"; break; case 5: isa = "ARM"; break; case 6: isa = "Itanium-based systems"; break; case 9: isa = "x64"; break; default: LOG_DEBUG("Unable to determine processor type: unknown architecture"); break; } } // Query number of logical processors separately; it's not supported on Server 2003, and will cause // the entire query to return empty if used. auto logicalprocs = _wmi.query(wmi::processor, {wmi::numberoflogicalprocessors}); for (auto const& objs : logicalprocs) { auto maybe_logical_count = maybe_stoi(wmi::get(objs, wmi::numberoflogicalprocessors)); if (maybe_logical_count) { logical_count += maybe_logical_count.get(); } } if (logical_count == 0) { logical_count = models.size(); } return make_tuple(models.size(), logical_count, move(models), move(isa), 0); } processor_resolver::data processor_resolver::collect_data(collection& facts) { data result; tie(result.physical_count, result.logical_count, result.models, result.isa, result.speed) = get_processors(*_wmi); return result; } }}} // namespace facter::facts::windows facter-3.14.12/lib/src/facts/windows/ssh_resolver.cc0000644005276200011600000000251413702047406022177 0ustar jenkinsjenkins#include #include #include #include #include #include #include #include using namespace std; using namespace boost::filesystem; using namespace leatherman::util; namespace bs = boost::system; namespace facter { namespace facts { path ssh_resolver::retrieve_key_file(string const& filename) { string dataPath; if (!environment::get("programdata", dataPath)) { LOG_DEBUG("error finding programdata: {1}", leatherman::windows::system_error()); } // https://docs.microsoft.com/en-us/windows-server/administration/openssh/openssh_keymanagement // Since there is no user associated with the sshd service, the host keys are stored under \ProgramData\ssh. string sshPath = ((path(dataPath) / "ssh").string()); // Search in sshPath for the fact's key file path key_file; key_file = sshPath; key_file /= filename; bs::error_code ec; if (!is_regular_file(key_file, ec)) { key_file.clear(); } return key_file; } }} // namespace facter::facts facter-3.14.12/lib/src/facts/windows/timezone_resolver.cc0000644005276200011600000000157213702047406023237 0ustar jenkinsjenkins#include #include #include #include using namespace std; namespace facter { namespace facts { namespace windows { string timezone_resolver::get_timezone() { time_t since_epoch = time(NULL); tm localtime; if (localtime_s(&localtime, &since_epoch)) { LOG_WARNING("localtime failed: timezone is unavailable: {1} ({2})", strerror(errno), errno); return {}; } wchar_t buffer[256] = {}; if (wcsftime(buffer, (sizeof(buffer) / sizeof(wchar_t)) - 1, L"%Z", &localtime) == 0) { LOG_WARNING("wcsftime failed: timezone is unavailable: {1} ({2})", strerror(errno), errno); return {}; } return boost::nowide::narrow(buffer); } }}} // facter::facts::windows facter-3.14.12/lib/src/facts/windows/uptime_resolver.cc0000644005276200011600000000132713702047406022706 0ustar jenkinsjenkins#include #include #include #include // Mark string for translation (alias for leatherman::locale::format) using leatherman::locale::_; namespace facter { namespace facts { namespace windows { using namespace std; using namespace leatherman::util; using namespace leatherman::windows; uptime_resolver::uptime_resolver() : resolvers::uptime_resolver() { } int64_t uptime_resolver::get_uptime() { uint64_t tickCount = GetTickCount64(); return (int64_t)(tickCount / 1000); // seconds } }}} // namespace facter::facts::windows facter-3.14.12/lib/src/facts/windows/virtualization_resolver.cc0000644005276200011600000000402413702047406024464 0ustar jenkinsjenkins#include #include #include #include #include #include #include #include #include using namespace std; using namespace facter::facts; using namespace leatherman::windows; namespace facter { namespace facts { namespace windows { virtualization_resolver::virtualization_resolver(shared_ptr wmi_conn) : resolvers::virtualization_resolver(), _wmi(move(wmi_conn)) { } string virtualization_resolver::get_hypervisor(collection& facts) { static vector> vms = { make_tuple("VirtualBox", string(vm::virtualbox)), make_tuple("VMware", string(vm::vmware)), make_tuple("KVM", string(vm::kvm)), make_tuple("Bochs", string(vm::bochs)), make_tuple("Google", string(vm::gce)), make_tuple("OpenStack", string(vm::openstack)), make_tuple("AHV", string(vm::ahv)), }; auto vals = _wmi->query(wmi::computersystem, {wmi::manufacturer, wmi::model}); if (vals.empty()) { return {}; } auto &manufacturer = wmi::get(vals, wmi::manufacturer); auto &model = wmi::get(vals, wmi::model); for (auto const& vm : vms) { if (model.find(get<0>(vm)) != string::npos) { return get<1>(vm); } } if (model.find("Virtual Machine") != string::npos && manufacturer.find("Microsoft") != string::npos) { return vm::hyperv; } if (manufacturer.find("Xen") != string::npos) { return vm::xen; } if (manufacturer.find("Amazon EC2") != string::npos) { return vm::kvm; } return {}; } }}} // namespace facter::facts::windows facter-3.14.12/lib/src/java/0000755005276200011600000000000013702047635015303 5ustar jenkinsjenkinsfacter-3.14.12/lib/src/java/facter.cc0000644005276200011600000001421013702047406017050 0ustar jenkinsjenkins#include "com_puppetlabs_Facter.h" #include #include #include #include #include #include #include #include #include using namespace std; using namespace facter::facts; using namespace facter::logging; static jclass object_class, long_class, double_class, boolean_class, hash_class; static jmethodID long_constructor, double_constructor, boolean_constructor, hash_constructor, hash_put; static std::unique_ptr facts_collection; static string to_string(JNIEnv* env, jstring str) { if (!str) { return {}; } auto ptr = env->GetStringUTFChars(str, nullptr); if (!ptr) { return {}; } auto size = env->GetStringUTFLength(str); string result(ptr, size); env->ReleaseStringUTFChars(str, ptr); return result; } static jclass find_class(JNIEnv* env, char const* name) { // Find the class and return a global reference auto klass = env->FindClass(name); if (!klass) { return nullptr; } return static_cast(env->NewGlobalRef(klass)); } static jobject to_object(JNIEnv* env, value const* val) { if (!val) { return nullptr; } if (auto ptr = dynamic_cast(val)) { return env->NewStringUTF(ptr->value().c_str()); } if (auto ptr = dynamic_cast(val)) { return env->NewObject(long_class, long_constructor, static_cast(ptr->value())); } if (auto ptr = dynamic_cast(val)) { return env->NewObject(boolean_class, boolean_constructor, static_cast(ptr->value())); } if (auto ptr = dynamic_cast(val)) { return env->NewObject(double_class, double_constructor, static_cast(ptr->value())); } if (auto ptr = dynamic_cast(val)) { auto array = env->NewObjectArray(ptr->size(), object_class, nullptr); // Recurse on each element of the array jsize index = 0; ptr->each([&](value const* element) { env->SetObjectArrayElement(array, index++, to_object(env, element)); return true; }); return array; } if (auto ptr = dynamic_cast(val)) { auto hashmap = env->NewObject(hash_class, hash_constructor, static_cast(ptr->size())); // Recurse on each element in the map ptr->each([&](string const& name, value const* element) { env->CallObjectMethod(hashmap, hash_put, env->NewStringUTF(name.c_str()), to_object(env, element)); return true; }); return hashmap; } return nullptr; } extern "C" { LIBFACTER_EXPORT jint JNI_OnLoad(JavaVM* vm, void* reserved) { JNIEnv* env; if (vm->GetEnv(reinterpret_cast(&env), JNI_VERSION_1_6) != JNI_OK) { return JNI_ERR; } // For the classes, we need global refs object_class = find_class(env, "java/lang/Object"); if (!object_class) { return JNI_ERR; } long_class = find_class(env, "java/lang/Long"); if (!long_class) { return JNI_ERR; } double_class = find_class(env, "java/lang/Double"); if (!double_class) { return JNI_ERR; } boolean_class = find_class(env, "java/lang/Boolean"); if (!boolean_class) { return JNI_ERR; } hash_class = find_class(env, "java/util/HashMap"); if (!hash_class) { return JNI_ERR; } // For the method ids, we can keep these cached as is long_constructor = env->GetMethodID(long_class, "", "(J)V"); double_constructor = env->GetMethodID(double_class, "", "(D)V"); boolean_constructor = env->GetMethodID(boolean_class, "", "(Z)V");; hash_constructor = env->GetMethodID(hash_class, "", "(I)V"); hash_put = env->GetMethodID(hash_class, "put", "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;"); setup_logging(boost::nowide::cerr); set_level(level::warning); // Create a non-const collection to start; we'll move it to the const pointer at the end of initialization unique_ptr facts(new collection()); // Do not load the ruby facts as we're running under JRuby and not MRI facts->add_default_facts(false); facts->add_external_facts(); // Resolve all facts now for thread-safety // We only support reading facts from JRuby, so the collection is assumed to be immutable after this facts->resolve_facts(); // Move to the const pointer to prevent future modifications facts_collection = std::move(facts); return JNI_VERSION_1_6; } LIBFACTER_EXPORT void JNI_OnUnload(JavaVM* vm, void* reserved) { // Delete the fact collection facts_collection.reset(); JNIEnv* env; if (vm->GetEnv(reinterpret_cast(&env), JNI_VERSION_1_6) != JNI_OK) { return; } // Free all of the global references above if (object_class) { env->DeleteGlobalRef(object_class); object_class = nullptr; } if (long_class) { env->DeleteGlobalRef(long_class); long_class = nullptr; } if (double_class) { env->DeleteGlobalRef(double_class); double_class = nullptr; } if (boolean_class) { env->DeleteGlobalRef(boolean_class); boolean_class = nullptr; } if (hash_class) { env->DeleteGlobalRef(hash_class); hash_class = nullptr; } } LIBFACTER_EXPORT jobject JNICALL Java_com_puppetlabs_Facter_lookup(JNIEnv* env, jclass klass, jstring name) { // Ensure initialized if (!facts_collection) { return nullptr; } return to_object(env, facts_collection->get_resolved(to_string(env, name))); } } // extern "C" facter-3.14.12/lib/src/logging/0000755005276200011600000000000013702047635016010 5ustar jenkinsjenkinsfacter-3.14.12/lib/src/logging/logging.cc0000644005276200011600000001043713702047406017746 0ustar jenkinsjenkins#include #include #include #include #include // Mark string for translation (alias for leatherman::locale::format) using leatherman::locale::_; using namespace std; using namespace leatherman::util; namespace lm = leatherman::logging; #ifdef LEATHERMAN_USE_LOCALES static void setup_logging_internal(ostream& os, bool use_locale) { // Initialize boost filesystem's locale to a UTF-8 default. // Logging gets setup the same way via the default 2nd argument. if (use_locale) { boost::filesystem::path::imbue(leatherman::locale::get_locale()); } lm::setup_logging(os, "", PROJECT_NAME, use_locale); } #else static void setup_logging_internal(ostream& os, bool) { lm::setup_logging(os, "", PROJECT_NAME, false); } #endif static const char* lc_vars[] = { "LC_CTYPE", "LC_NUMERIC", "LC_TIME", "LC_COLLATE", "LC_MONETARY", "LC_MESSAGES", "LC_PAPER", "LC_ADDRESS", "LC_TELEPHONE", "LC_MEASUREMENT", "LC_IDENTIFICATION", "LC_ALL" }; namespace facter { namespace logging { istream& operator>>(istream& in, level& lvl) { lm::log_level lm_level; in >> lm_level; lvl = static_cast(lm_level); return in; } ostream& operator<<(ostream& os, level lvl) { os << static_cast(lvl); return os; } void setup_logging(ostream& os) { try { setup_logging_internal(os, true); } catch (exception const&) { for (auto var : lc_vars) { environment::clear(var); } environment::set("LANG", "C"); environment::set("LC_ALL", "C"); try { setup_logging_internal(os, true); // We can't log the issue until after logging is setup. Rely on the exception for any other // error reporting. log(level::warning, "locale environment variables were bad; continuing with LANG=C LC_ALL=C"); } catch (exception const& e) { // If we fail again even with a clean environment, we // need to signal to our consumer that things went // sideways. // // Since logging is busted, we raise an exception that // signals to the consumer that a special action must // be taken to alert the user. try { setup_logging_internal(os, false); log(level::warning, "Could not initialize locale, even with LC_* variables cleared. Continuing without localization support"); } catch (exception const& e) { throw locale_error(_("could not initialize logging, even with locale variables reset to LANG=C LC_ALL=C: {1}", e.what())); } } } } void set_level(level lvl) { lm::set_level(static_cast(lvl)); } level get_level() { return static_cast(lm::get_level()); } void set_colorization(bool color) { lm::set_colorization(color); } bool get_colorization() { return lm::get_colorization(); } bool is_enabled(level lvl) { return lm::is_enabled(static_cast(lvl)); } bool error_logged() { return lm::error_has_been_logged(); } void clear_logged_errors() { lm::clear_error_logged_flag(); } std::string translate(std::string const& msg) { #ifdef LEATHERMAN_I18N return leatherman::locale::translate(msg); #else // When locales are disabled, use boost::format, which expects %N% style formatting static const boost::regex match{"\\{(\\d+)\\}"}; static const std::string repl{"%\\1%"}; return boost::regex_replace(leatherman::locale::translate(msg), match, repl); #endif } void log(level lvl, string const& message) { lm::log(LOG_NAMESPACE, static_cast(lvl), 0, translate(message)); } void colorize(ostream &os, level lvl) { lm::colorize(os, static_cast(lvl)); } }} // namespace facter::logging facter-3.14.12/lib/src/ruby/0000755005276200011600000000000013702047635015343 5ustar jenkinsjenkinsfacter-3.14.12/lib/src/ruby/aggregate_resolution.cc0000644005276200011600000002157713702047406022073 0ustar jenkinsjenkins#include #include #include // Mark string for translation (alias for leatherman::locale::format) using leatherman::locale::_; using namespace std; using namespace leatherman::ruby; namespace facter { namespace ruby { aggregate_resolution::aggregate_resolution() { auto const& ruby = api::instance(); _self = ruby.nil_value(); _block = ruby.nil_value(); } VALUE aggregate_resolution::define() { auto const& ruby = api::instance(); // Define the Resolution class VALUE klass = ruby.rb_define_class_under(ruby.lookup({"Facter", "Core"}), "Aggregate", *ruby.rb_cObject); ruby.rb_define_alloc_func(klass, alloc); ruby.rb_define_method(klass, "chunk", RUBY_METHOD_FUNC(ruby_chunk), -1); ruby.rb_define_method(klass, "aggregate", RUBY_METHOD_FUNC(ruby_aggregate), 0); resolution::define(klass); return klass; } VALUE aggregate_resolution::create() { auto const& ruby = api::instance(); return ruby.rb_class_new_instance(0, nullptr, ruby.lookup({"Facter", "Core", "Aggregate"})); } VALUE aggregate_resolution::value() { auto const& ruby = api::instance(); // If given an aggregate block, build a hash and call the block if (!ruby.is_nil(_block)) { volatile VALUE result = ruby.rb_hash_new(); for (auto& chunk : _chunks) { ruby.rb_hash_aset( result, chunk.first, chunk.second.value(*this)); } return ruby.rb_funcall(_block, ruby.rb_intern("call"), 1, result); } // Otherwise perform a default aggregation by doing a deep merge volatile VALUE merged = ruby.nil_value(); for (auto& chunk : _chunks) { volatile VALUE value = chunk.second.value(*this); if (ruby.is_nil(merged)) { merged = value; continue; } merged = deep_merge(ruby, merged, value); } return merged; } VALUE aggregate_resolution::find_chunk(VALUE name) { auto const& ruby = api::instance(); if (ruby.is_nil(name)) { return ruby.nil_value(); } if (!ruby.is_symbol(name)) { ruby.rb_raise(*ruby.rb_eTypeError, _("expected chunk name to be a Symbol").c_str()); } auto it = _chunks.find(name); if (it == _chunks.end()) { return ruby.nil_value(); } return it->second.value(*this); } void aggregate_resolution::define_chunk(VALUE name, VALUE options) { auto const& ruby = api::instance(); // A block is required if (!ruby.rb_block_given_p()) { ruby.rb_raise(*ruby.rb_eArgError, _("a block must be provided").c_str()); } if (!ruby.is_symbol(name)) { ruby.rb_raise(*ruby.rb_eTypeError, _("expected chunk name to be a Symbol").c_str()); } volatile VALUE dependencies = ruby.nil_value(); volatile VALUE block = ruby.rb_block_proc(); if (!ruby.is_nil(options)) { ID require_id = ruby.rb_intern("require"); ruby.hash_for_each(options, [&](VALUE key, VALUE value) { if (!ruby.is_symbol(key)) { ruby.rb_raise(*ruby.rb_eTypeError, _("expected a Symbol for options key").c_str()); } ID key_id = ruby.rb_to_id(key); if (key_id == require_id) { if (ruby.is_array((value))) { ruby.array_for_each(value, [&](VALUE element) { if (!ruby.is_symbol(element)) { ruby.rb_raise(*ruby.rb_eTypeError, _("expected a Symbol or Array of Symbol for require option").c_str()); } return true; }); } else if (!ruby.is_symbol(value)) { ruby.rb_raise(*ruby.rb_eTypeError, _("expected a Symbol or Array of Symbol for require option").c_str()); } dependencies = value; } else { ruby.rb_raise(*ruby.rb_eArgError, _("unexpected option {1}", ruby.rb_id2name(key_id)).c_str()); } return true; }); } auto it = _chunks.find(name); if (it == _chunks.end()) { it = _chunks.emplace(make_pair(name, ruby::chunk(dependencies, block))).first; } it->second.dependencies(dependencies); it->second.block(block); } VALUE aggregate_resolution::alloc(VALUE klass) { auto const& ruby = api::instance(); // Create a resolution and wrap with a Ruby data object unique_ptr r(new aggregate_resolution()); VALUE self = r->_self = ruby.rb_data_object_alloc(klass, r.get(), mark, free); ruby.register_data_object(self); // Release the smart pointer; ownership is now with Ruby's GC r.release(); return self; } void aggregate_resolution::mark(void* data) { // Mark all VALUEs contained in the aggregate resolution auto const& ruby = api::instance(); auto instance = reinterpret_cast(data); // Mark the base first instance->resolution::mark(); // Mark the aggregate block ruby.rb_gc_mark(instance->_block); // Mark the chunks for (auto& kvp : instance->_chunks) { ruby.rb_gc_mark(kvp.first); kvp.second.mark(); } } void aggregate_resolution::free(void* data) { auto instance = reinterpret_cast(data); // Unregister the data object auto const& ruby = api::instance(); ruby.unregister_data_object(instance->_self); // Delete the aggregate resolution delete instance; } VALUE aggregate_resolution::ruby_chunk(int argc, VALUE* argv, VALUE self) { auto const& ruby = api::instance(); if (argc == 0 || argc > 2) { ruby.rb_raise(*ruby.rb_eArgError, _("wrong number of arguments ({1} for 2)", argc).c_str()); } ruby.to_native(self)->define_chunk(argv[0], argc > 1 ? argv[1] : ruby.nil_value()); return self; } VALUE aggregate_resolution::ruby_aggregate(VALUE self) { auto const& ruby = api::instance(); // A block is required if (!ruby.rb_block_given_p()) { ruby.rb_raise(*ruby.rb_eArgError, _("a block must be provided").c_str()); } ruby.to_native(self)->_block = ruby.rb_block_proc(); return self; } VALUE aggregate_resolution::ruby_merge_hashes(VALUE obj, VALUE context, int argc, VALUE argv[]) { api const* ruby = reinterpret_cast(context); if (argc != 3) { ruby->rb_raise(*ruby->rb_eArgError, _("wrong number of arguments ({1} for 3)", argc).c_str()); } // Recurse on left and right return deep_merge(*ruby, argv[1], argv[2]); } VALUE aggregate_resolution::deep_merge(api const& ruby, VALUE left, VALUE right) { volatile VALUE result = ruby.nil_value(); if (ruby.is_hash(left) && ruby.is_hash(right)) { result = ruby.rb_block_call(left, ruby.rb_intern("merge"), 1, &right, RUBY_METHOD_FUNC(ruby_merge_hashes), reinterpret_cast(&ruby)); } else if (ruby.is_array(left) && ruby.is_array(right)) { result = ruby.rb_funcall(left, ruby.rb_intern("+"), 1, right); } else if (ruby.is_nil(right)) { result = left; } else if (ruby.is_nil(left)) { result = right; } else if (ruby.is_nil(left) && ruby.is_nil(right)) { result = ruby.nil_value(); } else { // Let the user know we couldn't merge the chunks volatile VALUE inspect_left = ruby.rb_funcall(left, ruby.rb_intern("inspect"), 0); volatile VALUE inspect_right = ruby.rb_funcall(right, ruby.rb_intern("inspect"), 0); volatile VALUE class_left = ruby.rb_funcall(ruby.rb_funcall(left, ruby.rb_intern("class"), 0), ruby.rb_intern("to_s"), 0); volatile VALUE class_right = ruby.rb_funcall(ruby.rb_funcall(right, ruby.rb_intern("class"), 0), ruby.rb_intern("to_s"), 0); ruby.rb_raise(*ruby.rb_eRuntimeError, _("cannot merge {1}:{2} and {3}:{4}", ruby.rb_string_value_ptr(&inspect_left), ruby.rb_string_value_ptr(&class_left), ruby.rb_string_value_ptr(&inspect_right), ruby.rb_string_value_ptr(&class_right)).c_str()); } return result; } }} // namespace facter::ruby facter-3.14.12/lib/src/ruby/chunk.cc0000644005276200011600000000751113702047406016762 0ustar jenkinsjenkins#include #include #include // Mark string for translation (alias for leatherman::locale::format) using leatherman::locale::_; using namespace std; using namespace leatherman::ruby; namespace facter { namespace ruby { chunk::chunk(VALUE dependencies, VALUE block) : _dependencies(dependencies), _block(block), _resolved(false), _resolving(false) { auto const& ruby = api::instance(); _value = ruby.nil_value(); } chunk::chunk(chunk&& other) { *this = move(other); } chunk& chunk::operator=(chunk&& other) { _dependencies = other._dependencies; _block = other._block; _value = other._value; _resolved = other._resolved; _resolving = other._resolving; return *this; } VALUE chunk::value(aggregate_resolution& resolution) { auto const& ruby = api::instance(); // Prevent cycles by raising an exception if (_resolving) { ruby.rb_raise(*ruby.rb_eRuntimeError, _("chunk dependency cycle detected").c_str()); } if (_resolved) { return _value; } _resolving = true; volatile VALUE value = ruby.nil_value(); int tag = 0; { // Declare all C++ objects here vector values; value = ruby.protect(tag, [&]{ // Do not declare any C++ objects inside the protect // Their destructors will not be invoked if there is a Ruby exception if (ruby.is_symbol(_dependencies)) { values.push_back(resolution.find_chunk(_dependencies)); ruby.rb_gc_register_address(&values[0]); } else if (ruby.is_array(_dependencies)) { // Resize the vector now to ensure it is fully allocated before registering with GC values.resize(ruby.num2size_t(ruby.rb_funcall(_dependencies, ruby.rb_intern("size"), 0)), ruby.nil_value()); for (auto& v : values) { ruby.rb_gc_register_address(&v); } int i = 0; ruby.array_for_each(_dependencies, [&](VALUE element) { values[i++] = resolution.find_chunk(element); return true; }); } // Call the block to get this chunk's value return ruby.rb_funcallv(_block, ruby.rb_intern("call"), values.size(), values.data()); }); // Unregister all the values from the GC for (auto& v : values) { ruby.rb_gc_unregister_address(&v); } } _resolving = false; if (!tag) { _value = value; _resolved = true; return _value; } // Now that the above block has exited, it's safe to jump to the given tag ruby.rb_jump_tag(tag); return ruby.nil_value(); } VALUE chunk::dependencies() const { return _dependencies; } void chunk::dependencies(VALUE dependencies) { auto const& ruby = api::instance(); _dependencies = dependencies; _value = ruby.nil_value(); _resolved = false; } VALUE chunk::block() const { return _block; } void chunk::block(VALUE block) { auto const& ruby = api::instance(); _block = block; _value = ruby.nil_value(); _resolved = false; } void chunk::mark() const { auto const& ruby = api::instance(); ruby.rb_gc_mark(_dependencies); ruby.rb_gc_mark(_block); ruby.rb_gc_mark(_value); } }} // namespace facter::ruby facter-3.14.12/lib/src/ruby/confine.cc0000644005276200011600000000557013702047406017276 0ustar jenkinsjenkins#include #include #include using namespace std; using namespace leatherman::ruby; namespace facter { namespace ruby { confine::confine(VALUE fact, VALUE expected, VALUE block) : _fact(fact), _expected(expected), _block(block) { } confine::confine(confine&& other) { *this = move(other); } confine& confine::operator=(confine&& other) { _fact = other._fact; _expected = other._expected; _block = other._block; return *this; } bool confine::suitable(module& facter) const { auto const& ruby = api::instance(); // If given a fact, either call the block or check the values if (!ruby.is_nil(_fact)) { // Rather than calling facter.fact_value, we call through the Ruby API to get the fact value the same way Ruby Facter did // This enables users to alter the behavior of confines during testing, like this: // Facter.fact(:name).expects(:value).returns 'overrride' volatile VALUE fact = ruby.rb_funcall(facter.self(), ruby.rb_intern("fact"), 1, _fact); if (ruby.is_nil(fact)) { return false; } // Get the value of the fact volatile VALUE value = facter.normalize(ruby.rb_funcall(fact, ruby.rb_intern("value"), 0)); if (ruby.is_nil(value)) { return false; } // Pass the value to the block if given one if (!ruby.is_nil(_block)) { volatile VALUE result = ruby.rb_funcall(_block, ruby.rb_intern("call"), 1, value); return !ruby.is_nil(result) && !ruby.is_false(result); } // Otherwise, if it's an array, search for the value if (ruby.is_array(_expected)) { bool found = false; ruby.array_for_each(_expected, [&](VALUE expected_value) { expected_value = facter.normalize(expected_value); found = ruby.equals(facter.normalize(expected_value), value); return !found; }); return found; } // Compare the value directly return ruby.case_equals(facter.normalize(_expected), value); } // If we have only a block, execute it if (!ruby.is_nil(_block)) { volatile VALUE result = ruby.rb_funcall(_block, ruby.rb_intern("call"), 0); return !ruby.is_nil(result) && !ruby.is_false(result); } return false; } void confine::mark() const { // Mark all VALUEs contained in the confine auto const& ruby = api::instance(); ruby.rb_gc_mark(_fact); ruby.rb_gc_mark(_expected); ruby.rb_gc_mark(_block); } }} // namespace facter::ruby facter-3.14.12/lib/src/ruby/fact.cc0000644005276200011600000003352513702047406016573 0ustar jenkinsjenkins#include #include #include #include #include #include #include #include #include #include // Mark string for translation (alias for leatherman::locale::format) using leatherman::locale::_; using namespace std; using namespace facter::facts; using namespace leatherman::util; using namespace leatherman::ruby; namespace facter { namespace ruby { // The maximum number of resolutions allowed for a fact static const size_t MAXIMUM_RESOLUTIONS = 100; fact::fact() : _resolved(false), _resolving(false), _weight(0) { auto const& ruby = api::instance(); _self = ruby.nil_value(); _name = ruby.nil_value(); _value = ruby.nil_value(); } VALUE fact::define() { auto const& ruby = api::instance(); VALUE klass = ruby.rb_define_class_under(ruby.lookup({ "Facter", "Util" }), "Fact", *ruby.rb_cObject); ruby.rb_define_alloc_func(klass, alloc); ruby.rb_define_method(klass, "initialize", RUBY_METHOD_FUNC(ruby_initialize), 1); ruby.rb_define_method(klass, "name", RUBY_METHOD_FUNC(ruby_name), 0); ruby.rb_define_method(klass, "value", RUBY_METHOD_FUNC(ruby_value), 0); ruby.rb_define_method(klass, "resolution", RUBY_METHOD_FUNC(ruby_resolution), 1); ruby.rb_define_method(klass, "define_resolution", RUBY_METHOD_FUNC(ruby_define_resolution), -1); ruby.rb_define_method(klass, "flush", RUBY_METHOD_FUNC(ruby_flush), 0); return klass; } VALUE fact::create(VALUE name) { auto const& ruby = api::instance(); return ruby.rb_class_new_instance(1, &name, ruby.lookup({"Facter", "Util", "Fact"})); } VALUE fact::name() const { return _name; } VALUE fact::value() { auto const& ruby = api::instance(); auto facter = module::current(); collection& facts = facter->facts(); // Prevent cycles by raising an exception if (_resolving) { ruby.rb_raise(*ruby.rb_eRuntimeError, _("cycle detected while requesting value of fact \"{1}\"", ruby.rb_string_value_ptr(&_name)).c_str()); } if (_resolved) { return _value; } // Sort the resolutions by weight (descending) sort(_resolutions.begin(), _resolutions.end(), [&](VALUE first, VALUE second) { auto res_first = ruby.to_native(first); auto res_second = ruby.to_native(second); return res_first->weight() > res_second->weight(); }); _resolving = true; bool add = true; vector::iterator it; ruby.rescue([&]() { volatile VALUE value = ruby.nil_value(); size_t weight = 0; // Look through the resolutions and find the first allowed resolution that resolves for (it = _resolutions.begin(); it != _resolutions.end(); ++it) { auto res = ruby.to_native(*it); if (!res->suitable(*facter)) { continue; } value = res->value(); if (!ruby.is_nil(value)) { weight = res->weight(); break; } } // Set the value to what was resolved _value = value; _weight = weight; if (! ruby.is_nil(_value) && _weight != 0) { return 0; } // There's two possibilities here: // 1. None of our resolvers could resolve the value // 2. A resolver of weight 0 resolved the value // // In both cases, we attempt to use the "built-in" fact's // value. This serves as a fallback resolver for Case (1) // while for Case (2), we want built-in values to take // precedence over 0-weight custom facts. auto builtin_value = facts[ruby.to_string(_name)]; if (! builtin_value) { return 0; } auto builtin_ruby_value = facter->to_ruby(builtin_value); // We need this check for Case (2). Otherwise, we risk // overwriting our resolved value in the small chance // that builtin_value exists, but its ruby value is // nil. if (! ruby.is_nil(builtin_ruby_value)) { // Already in collection, do not add add = false; _value = builtin_ruby_value; _weight = builtin_value->weight(); } return 0; }, [&](VALUE ex) { LOG_ERROR("error while resolving custom fact \"{1}\": {2}", ruby.rb_string_value_ptr(&_name), ruby.exception_to_string(ex)); // Failed, so set to nil _value = ruby.nil_value(); _weight = 0; return 0; }); if (add) { facts.add_custom(ruby.to_string(_name), ruby.is_nil(_value) ? nullptr : make_value(_value), _weight); } _resolved = true; _resolving = false; return _value; } void fact::value(VALUE v) { _value = v; _resolved = true; } VALUE fact::find_resolution(VALUE name) const { auto const& ruby = api::instance(); if (ruby.is_nil(name)) { return ruby.nil_value(); } if (!ruby.is_string(name)) { ruby.rb_raise(*ruby.rb_eTypeError, _("expected resolution name to be a String").c_str()); } // Search for the resolution by name auto it = find_if(_resolutions.begin(), _resolutions.end(), [&](VALUE self) { return ruby.equals(ruby.to_native(self)->name(), name); }); if (it == _resolutions.end()) { return ruby.nil_value(); } return *it; } VALUE fact::define_resolution(VALUE name, VALUE options) { // Do not declare types with destructors; if you do, wrap below in a api::protect call auto const& ruby = api::instance(); if (!ruby.is_nil(name) && !ruby.is_string(name) && !ruby.is_symbol(name)) { ruby.rb_raise(*ruby.rb_eTypeError, _("expected resolution name to be a Symbol or String").c_str()); } if (ruby.is_symbol(name)) { name = ruby.rb_sym_to_s(name); } bool aggregate = false; bool has_weight = false; size_t weight = 0; volatile VALUE resolution_value = ruby.nil_value(); // Read the options if provided if (!ruby.is_nil(options)) { ID simple_id = ruby.rb_intern("simple"); ID aggregate_id = ruby.rb_intern("aggregate"); ID type_id = ruby.rb_intern("type"); ID value_id = ruby.rb_intern("value"); ID weight_id = ruby.rb_intern("weight"); ID timeout_id = ruby.rb_intern("timeout"); if (!ruby.is_hash(options)) { ruby.rb_raise(*ruby.rb_eTypeError, _("expected a Hash for the options").c_str()); } ruby.hash_for_each(options, [&](VALUE key, VALUE value) { if (!ruby.is_symbol(key)) { ruby.rb_raise(*ruby.rb_eTypeError, _("expected a Symbol for options key").c_str()); } ID key_id = ruby.rb_to_id(key); if (key_id == type_id) { // Handle the type option if (!ruby.is_symbol(value)) { ruby.rb_raise(*ruby.rb_eTypeError, _("expected a Symbol for type option").c_str()); } ID type_id = ruby.rb_to_id(value); if (type_id != simple_id && type_id != aggregate_id) { ruby.rb_raise(*ruby.rb_eArgError, _("expected simple or aggregate for resolution type but was given {1}", ruby.rb_id2name(type_id)).c_str()); } aggregate = (type_id == aggregate_id); } else if (key_id == value_id) { // Handle the value option resolution_value = value; } else if (key_id == weight_id) { // Handle the weight option has_weight = true; weight = ruby.num2size_t(value); } else if (key_id == timeout_id) { // Ignore timeout as it isn't supported static bool timeout_warning = true; if (timeout_warning) { LOG_WARNING("timeout option is not supported for custom facts and will be ignored.") timeout_warning = false; } } else { ruby.rb_raise(*ruby.rb_eArgError, _("unexpected option {1}", ruby.rb_id2name(key_id)).c_str()); } return true; }); } // Find or create the resolution VALUE resolution_self = find_resolution(name); if (ruby.is_nil(resolution_self)) { if (_resolutions.size() == MAXIMUM_RESOLUTIONS) { ruby.rb_raise(*ruby.rb_eRuntimeError, _("fact \"{1}\" already has the maximum number of resolutions allowed ({2}).", ruby.rb_string_value_ptr(&_name), MAXIMUM_RESOLUTIONS).c_str()); } if (aggregate) { _resolutions.push_back(aggregate_resolution::create()); } else { _resolutions.push_back(simple_resolution::create()); } resolution_self = _resolutions.back(); } else { if (aggregate && !ruby.is_a(resolution_self, ruby.lookup({ "Facter", "Core", "Aggregate"}))) { ruby.rb_raise(*ruby.rb_eArgError, _("cannot define an aggregate resolution with name \"{1}\": a simple resolution with the same name already exists", ruby.rb_string_value_ptr(&name)).c_str()); } else if (!aggregate && !ruby.is_a(resolution_self, ruby.lookup({ "Facter", "Util", "Resolution"}))) { ruby.rb_raise(*ruby.rb_eArgError, _("cannot define a simple resolution with name \"{1}\": an aggregate resolution with the same name already exists", ruby.rb_string_value_ptr(&name)).c_str()); } } // Set the name, value, and weight auto res = ruby.to_native(resolution_self); res->name(name); res->value(resolution_value); if (has_weight) { res->weight(weight); } // Call the block if one was given if (ruby.rb_block_given_p()) { ruby.rb_funcall_passing_block(resolution_self, ruby.rb_intern("instance_eval"), 0, nullptr); } return resolution_self; } void fact::flush() { auto const& ruby = api::instance(); // Call flush on every resolution for (auto r : _resolutions) { ruby.to_native(r)->flush(); } // Reset the value _resolved = false; _value = ruby.nil_value(); } VALUE fact::alloc(VALUE klass) { auto const& ruby = api::instance(); // Create a fact and wrap with a Ruby data object unique_ptr f(new fact()); VALUE self = f->_self = ruby.rb_data_object_alloc(klass, f.get(), mark, free); ruby.register_data_object(self); // Release the smart pointer; ownership is now with Ruby's GC f.release(); return self; } void fact::mark(void* data) { // Mark all VALUEs contained in the fact auto const& ruby = api::instance(); auto instance = reinterpret_cast(data); // Mark the name and value ruby.rb_gc_mark(instance->_name); ruby.rb_gc_mark(instance->_value); // Mark the resolutions for (auto v : instance->_resolutions) { ruby.rb_gc_mark(v); } } void fact::free(void* data) { auto instance = reinterpret_cast(data); // Unregister the data object auto const& ruby = api::instance(); ruby.unregister_data_object(instance->_self); // Delete the fact delete instance; } VALUE fact::ruby_initialize(VALUE self, VALUE name) { auto const& ruby = api::instance(); if (!ruby.is_string(name) && !ruby.is_symbol(name)) { ruby.rb_raise(*ruby.rb_eTypeError, _("expected a String or Symbol for fact name").c_str()); } ruby.to_native(self)->_name = name; return self; } VALUE fact::ruby_name(VALUE self) { auto const& ruby = api::instance(); return ruby.to_native(self)->name(); } VALUE fact::ruby_value(VALUE self) { auto const& ruby = api::instance(); return ruby.to_native(self)->value(); } VALUE fact::ruby_resolution(VALUE self, VALUE name) { auto const& ruby = api::instance(); return ruby.to_native(self)->find_resolution(name); } VALUE fact::ruby_define_resolution(int argc, VALUE* argv, VALUE self) { auto const& ruby = api::instance(); if (argc == 0 || argc > 2) { ruby.rb_raise(*ruby.rb_eArgError, _("wrong number of arguments ({1} for 2)", argc).c_str()); } return ruby.to_native(self)->define_resolution(argv[0], argc > 1 ? argv[1] : ruby.nil_value()); } VALUE fact::ruby_flush(VALUE self) { auto const& ruby = api::instance(); ruby.to_native(self)->flush(); return ruby.nil_value(); } }} // namespace facter::ruby facter-3.14.12/lib/src/ruby/module.cc0000644005276200011600000012223113702047406017134 0ustar jenkinsjenkins#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include // Mark string for translation (alias for leatherman::locale::format) using leatherman::locale::_; using namespace std; using namespace facter::facts; using namespace facter::util::config; using namespace leatherman::execution; using namespace leatherman::file_util; using namespace leatherman::util; using namespace boost::filesystem; using namespace leatherman::logging; using namespace leatherman::ruby; namespace facter { namespace ruby { /** * Helper for maintaining context when initialized via a Ruby require. */ struct require_context { /** * Constructs a new require context. */ require_context() { // Create a collection and a facter module boost::program_options::variables_map vm; auto hocon_conf = load_default_config_file(); load_fact_settings(hocon_conf, vm); set blocklist; if (vm.count("blocklist")) { auto facts_to_block = vm["blocklist"].as>(); blocklist.insert(facts_to_block.begin(), facts_to_block.end()); } auto ttls = load_ttls(hocon_conf); _facts.reset(new collection(blocklist, ttls)); _module.reset(new module(*_facts)); // Ruby doesn't have a proper way of notifying extensions that the VM is shutting down // The easiest way to get notified is to have a global data object that never gets collected // until the VM shuts down auto const& ruby = api::instance(); _canary = ruby.rb_data_object_alloc(*ruby.rb_cObject, this, nullptr, cleanup); ruby.rb_gc_register_address(&_canary); ruby.register_data_object(_canary); } /** * Destructs the require context. */ ~require_context() { _module.reset(); _facts.reset(); // Remove the finalizer and let Ruby collect the object auto const& ruby = api::instance(); ruby.rb_gc_unregister_address(&_canary); ruby.unregister_data_object(_canary); } /** * Creates the require context. */ static void create() { // Reset first before allocating a new context reset(); _instance.reset(new require_context()); } /** * Resets the require context. */ static void reset() { _instance.reset(); } private: static void cleanup(void* ptr) { if (ptr == _instance.get()) { reset(); } } unique_ptr _facts; unique_ptr _module; VALUE _canary; static unique_ptr _instance; }; unique_ptr require_context::_instance; }} // Exports for a Ruby extension. extern "C" { /** * Called by the Ruby VM when native facter is required. */ void LIBFACTER_EXPORT Init_libfacter() { bool logging_init_failed = false; string logging_init_error_msg; try { facter::logging::setup_logging(boost::nowide::cerr); set_level(log_level::warning); } catch(facter::logging::locale_error const& e) { logging_init_failed = true; logging_init_error_msg = e.what(); } // Initialize ruby api* ruby = nullptr; try { ruby = &api::instance(); } catch (runtime_error& ex) { if (!logging_init_failed) { LOG_WARNING("{1}: facts requiring Ruby will not be resolved.", ex.what()); } else { // This could only happen if some non-ruby library // consumer called this function for some reason and // we didn't have a libruby loaded. AND the locales // are messed up so badly that even resetting locale // environment variables fails. This seems so // astronomically unlikely that I don't really think // it's worth figuring out what we should do in this // case - I'm honestly not even sure there's a correct // behavior at this point. // -- Branan } return; } ruby->initialize(); // If logging init failed, we'll raise a load error // here. Otherwise we Create the context if (logging_init_failed) { ruby->rb_raise(*ruby->rb_eLoadError, _("could not initialize facter due to a locale error: {1}", logging_init_error_msg).c_str()); } else { facter::ruby::require_context::create(); } } } namespace facter { namespace ruby { static string canonicalize(string p) { // Get the canonical/absolute directory name // If it can be resolved, use canonical to avoid duplicate search paths. // Fall back to absolute because canonical on Windows won't recognize paths as valid if // they resolve to symlinks to non-NTFS volumes. boost::system::error_code ec; auto directory = canonical(p, ec); if (ec) { return absolute(p).string(); } return directory.string(); } map module::_instances; module::module(collection& facts, vector const& paths, bool logging_hooks) : _collection(facts), _loaded_all(false) { auto const& ruby = api::instance(); if (!ruby.initialized()) { throw runtime_error(_("Ruby API is not initialized.").c_str()); } // Load global settigs from config file load_global_settings(load_default_config_file(), _config_file_settings); initialize_search_paths(paths); // Register the block for logging callback with the GC _on_message_block = ruby.nil_value(); ruby.rb_gc_register_address(&_on_message_block); // Install a logging message handler on_message([this](log_level level, string const& message) { auto const& ruby = api::instance(); if (ruby.is_nil(_on_message_block)) { return true; } // Call the block and don't log messages ruby.rescue([&]() { ruby.rb_funcall(_on_message_block, ruby.rb_intern("call"), 2, level_to_symbol(level), ruby.utf8_value(message)); return ruby.nil_value(); }, [&](VALUE) { // Logging can take place from locations where we do not expect Ruby exceptions to be raised // Therefore, intentionally swallow any exceptions. return ruby.nil_value(); }); return false; }); // Define the Facter module _self = ruby.rb_define_module("Facter"); _instances[_self] = this; VALUE core = ruby.rb_define_module_under(_self, "Core"); VALUE execution = ruby.rb_define_module_under(core, "Execution"); ruby.rb_define_module_under(_self, "Util"); // Define the methods on the Facter module volatile VALUE version = ruby.utf8_value(LIBFACTER_VERSION); ruby.rb_const_set(_self, ruby.rb_intern("FACTERVERSION"), version); ruby.rb_define_singleton_method(_self, "version", RUBY_METHOD_FUNC(ruby_version), 0); ruby.rb_define_singleton_method(_self, "add", RUBY_METHOD_FUNC(ruby_add), -1); ruby.rb_define_singleton_method(_self, "define_fact", RUBY_METHOD_FUNC(ruby_define_fact), -1); ruby.rb_define_singleton_method(_self, "value", RUBY_METHOD_FUNC(ruby_value), 1); ruby.rb_define_singleton_method(_self, "[]", RUBY_METHOD_FUNC(ruby_fact), 1); ruby.rb_define_singleton_method(_self, "fact", RUBY_METHOD_FUNC(ruby_fact), 1); ruby.rb_define_singleton_method(_self, "debug", RUBY_METHOD_FUNC(ruby_debug), 1); ruby.rb_define_singleton_method(_self, "debugonce", RUBY_METHOD_FUNC(ruby_debugonce), 1); ruby.rb_define_singleton_method(_self, "warn", RUBY_METHOD_FUNC(ruby_warn), 1); ruby.rb_define_singleton_method(_self, "warnonce", RUBY_METHOD_FUNC(ruby_warnonce), 1); ruby.rb_define_singleton_method(_self, "log_exception", RUBY_METHOD_FUNC(ruby_log_exception), -1); ruby.rb_define_singleton_method(_self, "debugging?", RUBY_METHOD_FUNC(ruby_get_debugging), 0); ruby.rb_define_singleton_method(_self, "trace?", RUBY_METHOD_FUNC(ruby_get_trace), 0); ruby.rb_define_singleton_method(_self, "flush", RUBY_METHOD_FUNC(ruby_flush), 0); ruby.rb_define_singleton_method(_self, "list", RUBY_METHOD_FUNC(ruby_list), 0); ruby.rb_define_singleton_method(_self, "to_hash", RUBY_METHOD_FUNC(ruby_to_hash), 0); ruby.rb_define_singleton_method(_self, "each", RUBY_METHOD_FUNC(ruby_each), 0); ruby.rb_define_singleton_method(_self, "clear", RUBY_METHOD_FUNC(ruby_clear), 0); ruby.rb_define_singleton_method(_self, "reset", RUBY_METHOD_FUNC(ruby_reset), 0); ruby.rb_define_singleton_method(_self, "loadfacts", RUBY_METHOD_FUNC(ruby_loadfacts), 0); ruby.rb_define_singleton_method(_self, "search", RUBY_METHOD_FUNC(ruby_search), -1); ruby.rb_define_singleton_method(_self, "search_path", RUBY_METHOD_FUNC(ruby_search_path), 0); ruby.rb_define_singleton_method(_self, "search_external", RUBY_METHOD_FUNC(ruby_search_external), 1); ruby.rb_define_singleton_method(_self, "search_external_path", RUBY_METHOD_FUNC(ruby_search_external_path), 0); // Only define these if requested to do so // This prevents consumers of Facter from altering the logging behavior if (logging_hooks) { ruby.rb_define_singleton_method(_self, "debugging", RUBY_METHOD_FUNC(ruby_set_debugging), 1); ruby.rb_define_singleton_method(_self, "trace", RUBY_METHOD_FUNC(ruby_set_trace), 1); ruby.rb_define_singleton_method(_self, "on_message", RUBY_METHOD_FUNC(ruby_on_message), 0); } // Define the execution module ruby.rb_define_singleton_method(execution, "which", RUBY_METHOD_FUNC(ruby_which), 1); ruby.rb_define_singleton_method(execution, "exec", RUBY_METHOD_FUNC(ruby_exec), 1); ruby.rb_define_singleton_method(execution, "execute", RUBY_METHOD_FUNC(ruby_execute), -1); ruby.rb_define_class_under(execution, "ExecutionFailure", *ruby.rb_eStandardError); // Define the Fact and resolution classes fact::define(); simple_resolution::define(); aggregate_resolution::define(); // Custom facts may `require 'facter'` // To allow those custom facts to still function, add facter.rb to loaded features using the first directory in the load path // Note: use forward slashes in the path even on Windows because that's what Ruby expects in $LOADED_FEATURES volatile VALUE first = ruby.rb_ary_entry(ruby.rb_gv_get("$LOAD_PATH"), 0); if (!ruby.is_nil(first)) { ruby.rb_ary_push(ruby.rb_gv_get("$LOADED_FEATURES"), ruby.utf8_value(ruby.to_string(first) + "/facter.rb")); } } module::~module() { _instances.erase(_self); clear_facts(false); try { api& ruby = api::instance(); // Unregister the on message block ruby.rb_gc_unregister_address(&_on_message_block); on_message(nullptr); // Undefine the module ruby.rb_const_remove(*ruby.rb_cObject, ruby.rb_intern("Facter")); } catch (runtime_error& ex) { LOG_WARNING("{1}: Ruby cleanup ended prematurely", ex.what()); return; } } void module::search(vector const& paths) { for (auto dir : paths) { _additional_search_paths.emplace_back(dir); _search_paths.emplace_back(canonicalize(_additional_search_paths.back())); } } void module::load_facts() { if (_loaded_all) { return; } LOG_DEBUG("loading all custom facts."); LOG_DEBUG("loading custom fact directories from config file"); if (_config_file_settings.count("custom-dir")) { auto config_paths = _config_file_settings["custom-dir"].as>(); _search_paths.insert(_search_paths.end(), config_paths.begin(), config_paths.end()); } for (auto const& directory : _search_paths) { LOG_DEBUG("searching for custom facts in {1}.", directory); each_file(directory, [&](string const& file) { load_file(file); return true; }, "\\.rb$"); } _loaded_all = true; } void module::resolve_facts() { // Before we do anything, call facts to ensure the collection is populated facts(); load_facts(); auto const& ruby = api::instance(); LOG_DEBUG(_("loading external fact directories from config file")); boost::program_options::variables_map vm; auto hocon_conf = load_default_config_file(); load_fact_groups_settings(hocon_conf, vm); vector cached_custom_facts_list; if (vm.count(cached_custom_facts)) { auto facts_to_cache = vm[cached_custom_facts].as>(); cached_custom_facts_list.insert(cached_custom_facts_list.end(), facts_to_cache.begin(), facts_to_cache.end()); } auto ttls = _collection.get_ttls(); bool custom_cache_file_loaded = false; bool custom_cache_enabled = !cached_custom_facts_list.empty() || ttls.count(cached_custom_facts); if (custom_cache_enabled) { custom_cache_file_loaded = cache::load_cached_custom_facts(_collection, ttls.find(cached_custom_facts)->second); } auto cached_fact = ([&](string const& key) { return custom_cache_file_loaded && std::find(cached_custom_facts_list.begin(), cached_custom_facts_list.end(), key) != cached_custom_facts_list.end(); }); for (auto const& kvp_name_value : _facts) { if (!cached_fact(kvp_name_value.first)) { ruby.to_native(kvp_name_value.second)->value(); } } if (custom_cache_enabled && !custom_cache_file_loaded) { cache::write_cached_custom_facts(_collection, cached_custom_facts_list); } } void module::clear_facts(bool clear_collection) { auto const& ruby = api::instance(); // Unregister all the facts for (auto& kvp : _facts) { ruby.rb_gc_unregister_address(&kvp.second); } // Clear the custom facts _facts.clear(); // Clear the collection if (clear_collection) { _collection.clear(); } } VALUE module::fact_value(VALUE name) { auto const& ruby = api::instance(); VALUE fact_self = load_fact(name); if (ruby.is_nil(fact_self)) { return ruby.nil_value(); } return ruby.to_native(fact_self)->value(); } VALUE module::to_ruby(value const* val) const { auto const& ruby = api::instance(); if (!val) { return ruby.nil_value(); } if (auto ptr = dynamic_cast(val)) { return ptr->value(); } if (auto ptr = dynamic_cast(val)) { return ruby.utf8_value(ptr->value()); } if (auto ptr = dynamic_cast(val)) { return ruby.rb_ll2inum(static_cast(ptr->value())); } if (auto ptr = dynamic_cast(val)) { return ptr->value() ? ruby.true_value() : ruby.false_value(); } if (auto ptr = dynamic_cast(val)) { return ruby.rb_float_new_in_heap(ptr->value()); } if (auto ptr = dynamic_cast(val)) { volatile VALUE array = ruby.rb_ary_new_capa(static_cast(ptr->size())); ptr->each([&](value const* element) { ruby.rb_ary_push(array, to_ruby(element)); return true; }); return array; } if (auto ptr = dynamic_cast(val)) { volatile VALUE hash = ruby.rb_hash_new(); ptr->each([&](string const& name, value const* element) { ruby.rb_hash_aset(hash, ruby.utf8_value(name), to_ruby(element)); return true; }); return hash; } return ruby.nil_value(); } VALUE module::normalize(VALUE name) const { auto const& ruby = api::instance(); if (ruby.is_symbol(name)) { name = ruby.rb_sym_to_s(name); } if (ruby.is_string(name)) { name = ruby.rb_funcall(name, ruby.rb_intern("downcase"), 0); } return name; } collection& module::facts() { if (_collection.empty()) { bool include_ruby_facts = true; _collection.add_default_facts(include_ruby_facts); _collection.add_external_facts(_external_search_paths); auto const& ruby = api::instance(); _collection.add_environment_facts([&](string const& name) { // Create a fact and explicitly set the value // We honor environment variables above custom fact resolutions ruby.to_native(create_fact(ruby.utf8_value(name)))->value(to_ruby(_collection[name])); }); } return _collection; } VALUE module::self() const { return _self; } module* module::current() { auto const& ruby = api::instance(); return from_self(ruby.lookup({"Facter"})); } static VALUE safe_eval(char const* scope, function body) { try { return body(); } catch (exception const& e) { LOG_ERROR("{1} uncaught exception: {2}", scope, e.what()); } return api::instance().nil_value(); } VALUE module::ruby_version(VALUE self) { return safe_eval("Facter.version", [&]() { auto const& ruby = api::instance(); return ruby.lookup({ "Facter", "FACTERVERSION" }); }); } VALUE module::ruby_add(int argc, VALUE* argv, VALUE self) { return safe_eval("Facter.add", [&]() { auto const& ruby = api::instance(); if (argc == 0 || argc > 2) { ruby.rb_raise(*ruby.rb_eArgError, _("wrong number of arguments ({1} for 2)", argc).c_str()); } VALUE fact_self = from_self(self)->create_fact(argv[0]); // Read the resolution name from the options hash, if present volatile VALUE name = ruby.nil_value(); VALUE options = argc == 2 ? argv[1] : ruby.nil_value(); if (!ruby.is_nil(options)) { name = ruby.rb_funcall(options, ruby.rb_intern("delete"), 1, ruby.to_symbol("name")); } ruby.to_native(fact_self)->define_resolution(name, options); return fact_self; }); } VALUE module::ruby_define_fact(int argc, VALUE* argv, VALUE self) { return safe_eval("Facter.define_fact", [&]() { auto const& ruby = api::instance(); if (argc == 0 || argc > 2) { ruby.rb_raise(*ruby.rb_eArgError, _("wrong number of arguments ({1} for 2)", argc).c_str()); } VALUE fact_self = from_self(self)->create_fact(argv[0]); // Call the block if one was given if (ruby.rb_block_given_p()) { ruby.rb_funcall_passing_block(fact_self, ruby.rb_intern("instance_eval"), 0, nullptr); } return fact_self; }); } VALUE module::ruby_value(VALUE self, VALUE name) { return safe_eval("Facter.value", [&]() { return from_self(self)->fact_value(name); }); } VALUE module::ruby_fact(VALUE self, VALUE name) { return safe_eval("Facter.fact", [&]() { return from_self(self)->load_fact(name); }); } VALUE module::ruby_debug(VALUE self, VALUE message) { return safe_eval("Facter.debug", [&]() { auto const& ruby = api::instance(); LOG_DEBUG(ruby.to_string(message)); return ruby.nil_value(); }); } VALUE module::ruby_debugonce(VALUE self, VALUE message) { return safe_eval("Facter.debugonce", [&]() { auto const& ruby = api::instance(); string msg = ruby.to_string(message); if (from_self(self)->_debug_messages.insert(msg).second) { LOG_DEBUG(msg); } return ruby.nil_value(); }); } VALUE module::ruby_warn(VALUE self, VALUE message) { return safe_eval("Facter.warn", [&]() { auto const& ruby = api::instance(); LOG_WARNING(ruby.to_string(message)); return ruby.nil_value(); }); } VALUE module::ruby_warnonce(VALUE self, VALUE message) { return safe_eval("Facter.warnonce", [&]() { auto const& ruby = api::instance(); string msg = ruby.to_string(message); if (from_self(self)->_warning_messages.insert(msg).second) { LOG_WARNING(msg); } return ruby.nil_value(); }); } VALUE module::ruby_set_debugging(VALUE self, VALUE value) { return safe_eval("Facter.debugging", [&]() { auto const& ruby = api::instance(); if (ruby.is_true(value)) { set_level(log_level::debug); } else { set_level(log_level::warning); } return ruby_get_debugging(self); }); } VALUE module::ruby_get_debugging(VALUE self) { return safe_eval("Facter.debugging?", [&]() { auto const& ruby = api::instance(); return is_enabled(log_level::debug) ? ruby.true_value() : ruby.false_value(); }); } VALUE module::ruby_set_trace(VALUE self, VALUE value) { return safe_eval("Facter.trace", [&]() { auto& ruby = api::instance(); ruby.include_stack_trace(ruby.is_true(value)); return ruby_get_trace(self); }); } VALUE module::ruby_get_trace(VALUE self) { return safe_eval("Facter.trace?", [&]() { auto const& ruby = api::instance(); return ruby.include_stack_trace() ? ruby.true_value() : ruby.false_value(); }); } VALUE module::ruby_log_exception(int argc, VALUE* argv, VALUE self) { return safe_eval("Facter.log_exception", [&]() { auto const& ruby = api::instance(); if (argc == 0 || argc > 2) { ruby.rb_raise(*ruby.rb_eArgError, _("wrong number of arguments ({1} for 2)", argc).c_str()); } string message; if (argc == 2) { // Use the given argument provided it is not a symbol equal to :default if (!ruby.is_symbol(argv[1]) || ruby.rb_to_id(argv[1]) != ruby.rb_intern("default")) { message = ruby.to_string(argv[1]); } } LOG_ERROR(ruby.exception_to_string(argv[0], message)); return ruby.nil_value(); }); } VALUE module::ruby_flush(VALUE self) { return safe_eval("Facter.flush", [&]() { auto const& ruby = api::instance(); for (auto& kvp : from_self(self)->_facts) { ruby.to_native(kvp.second)->flush(); } return ruby.nil_value(); }); } VALUE module::ruby_list(VALUE self) { return safe_eval("Facter.list", [&]() { auto const& ruby = api::instance(); module* instance = from_self(self); instance->resolve_facts(); volatile VALUE array = ruby.rb_ary_new_capa(instance->facts().size()); instance->facts().each([&](string const& name, value const*) { ruby.rb_ary_push(array, ruby.utf8_value(name)); return true; }); return array; }); } VALUE module::ruby_to_hash(VALUE self) { return safe_eval("Facter.to_hash", [&]() { auto const& ruby = api::instance(); module* instance = from_self(self); instance->resolve_facts(); volatile VALUE hash = ruby.rb_hash_new(); instance->facts().each([&](string const& name, value const* val) { ruby.rb_hash_aset(hash, ruby.utf8_value(name), instance->to_ruby(val)); return true; }); return hash; }); } VALUE module::ruby_each(VALUE self) { return safe_eval("Facter.each", [&]() { auto const& ruby = api::instance(); module* instance = from_self(self); instance->resolve_facts(); instance->facts().each([&](string const& name, value const* val) { ruby.rb_yield_values(2, ruby.utf8_value(name), instance->to_ruby(val)); return true; }); return self; }); } VALUE module::ruby_clear(VALUE self) { return safe_eval("Facter.clear", [&]() { auto const& ruby = api::instance(); ruby_flush(self); ruby_reset(self); return ruby.nil_value(); }); } VALUE module::ruby_reset(VALUE self) { return safe_eval("Facter.reset", [&]() { auto const& ruby = api::instance(); module* instance = from_self(self); instance->clear_facts(); instance->initialize_search_paths({}); instance->_external_search_paths.clear(); instance->_loaded_all = false; instance->_loaded_files.clear(); return ruby.nil_value(); }); } VALUE module::ruby_loadfacts(VALUE self) { return safe_eval("Facter.loadfacts", [&]() { auto const& ruby = api::instance(); from_self(self)->load_facts(); return ruby.nil_value(); }); } VALUE module::ruby_search(int argc, VALUE* argv, VALUE self) { return safe_eval("Facter.search", [&]() { auto const& ruby = api::instance(); module* instance = from_self(self); for (int i = 0; i < argc; ++i) { if (!ruby.is_string(argv[i])) { continue; } instance->_additional_search_paths.emplace_back(ruby.to_string(argv[i])); instance->_search_paths.emplace_back(canonicalize(instance->_additional_search_paths.back())); } return ruby.nil_value(); }); } VALUE module::ruby_search_path(VALUE self) { return safe_eval("Facter.search_path", [&]() { auto const& ruby = api::instance(); module* instance = from_self(self); volatile VALUE array = ruby.rb_ary_new_capa(instance->_additional_search_paths.size()); for (auto const& path : instance->_additional_search_paths) { ruby.rb_ary_push(array, ruby.utf8_value(path)); } return array; }); } VALUE module::ruby_search_external(VALUE self, VALUE paths) { return safe_eval("Facter.search_external", [&]() { auto const& ruby = api::instance(); module* instance = from_self(self); ruby.array_for_each(paths, [&](VALUE element) { if (!ruby.is_string(element)) { return true; } instance->_external_search_paths.emplace_back(ruby.to_string(element)); return true; }); // Add external path from config file LOG_DEBUG(_("loading external fact directories from config file")); if (instance->_config_file_settings.count("external-dir")) { auto config_paths = instance->_config_file_settings["external-dir"].as>(); instance->_external_search_paths.insert(instance->_external_search_paths.end(), config_paths.begin(), config_paths.end()); } return ruby.nil_value(); }); } VALUE module::ruby_search_external_path(VALUE self) { return safe_eval("Facter.search_external_path", [&]() { auto const& ruby = api::instance(); module* instance = from_self(self); volatile VALUE array = ruby.rb_ary_new_capa(instance->_external_search_paths.size()); for (auto const& path : instance->_external_search_paths) { ruby.rb_ary_push(array, ruby.utf8_value(path)); } return array; }); } VALUE module::ruby_which(VALUE self, VALUE binary) { return safe_eval("Facter::Core::Execution::which", [&]() { // Note: self is Facter::Core::Execution auto const& ruby = api::instance(); string path = which(ruby.to_string(binary)); if (path.empty()) { return ruby.nil_value(); } return ruby.utf8_value(path); }); } VALUE module::ruby_exec(VALUE self, VALUE command) { return safe_eval("Facter::Core::Execution::exec", [&]() { // Note: self is Facter::Core::Execution auto const& ruby = api::instance(); return execute_command(ruby.to_string(command), ruby.nil_value(), false); }); } VALUE module::ruby_execute(int argc, VALUE* argv, VALUE self) { return safe_eval("Facter::Core::Execution::execute", [&]() { // Note: self is Facter::Core::Execution auto const& ruby = api::instance(); if (argc == 0 || argc > 2) { ruby.rb_raise(*ruby.rb_eArgError, _("wrong number of arguments ({1} for 2)", argc).c_str()); } if (argc == 1) { return execute_command(ruby.to_string(argv[0]), ruby.nil_value(), true); } // Unfortunately we have to call to_sym rather than using ID2SYM, which is Ruby version dependent uint32_t timeout = 0; volatile VALUE timeout_option = ruby.rb_hash_lookup(argv[1], ruby.to_symbol("timeout")); if (ruby.is_integer(timeout_option)) { timeout = ruby.num2size_t(timeout_option); } // Get the on_fail option (defaults to :raise) bool raise = false; volatile VALUE raise_value = ruby.to_symbol("raise"); volatile VALUE fail_option = ruby.rb_hash_lookup2(argv[1], ruby.to_symbol("on_fail"), raise_value); if (ruby.equals(fail_option, raise_value)) { raise = true; fail_option = ruby.nil_value(); } bool expand = true; volatile VALUE expand_option = ruby.rb_hash_lookup2(argv[1], ruby.to_symbol("expand"), ruby.true_value()); if (ruby.is_false(expand_option)) { expand = false; } return execute_command(ruby.to_string(argv[0]), fail_option, raise, timeout, expand); }); } VALUE module::ruby_on_message(VALUE self) { return safe_eval("Facter.on_message", [&]() { auto const& ruby = api::instance(); from_self(self)->_on_message_block = ruby.rb_block_given_p() ? ruby.rb_block_proc() : ruby.nil_value(); return ruby.nil_value(); }); } module* module::from_self(VALUE self) { auto it = _instances.find(self); if (it == _instances.end()) { auto const& ruby = api::instance(); ruby.rb_raise(*ruby.rb_eArgError, _("unexpected self value {1}", self).c_str()); return nullptr; } return it->second; } VALUE module::execute_command(std::string const& command, VALUE failure_default, bool raise, uint32_t timeout, bool expand) { auto const& ruby = api::instance(); // Expand the command only if expand is true, std::string expanded; try { #ifdef HAS_LTH_EXPAND expanded = expand_command(command, leatherman::util::environment::search_paths(), expand); #else expanded = expand_command(command); LOG_DEBUG("Facter was compiled with a Leatherman version that cannot expand shell builtins. Falling back to the default behavior."); #endif } catch (const std::invalid_argument &ex) { ruby.rb_raise(*ruby.rb_eArgError, _("Cause: {1}", ex.what()).c_str()); } if (!expanded.empty()) { try { auto exec = execute( command_shell, { command_args, expanded }, timeout, { execution_options::trim_output, execution_options::merge_environment, execution_options::redirect_stderr_to_null, execution_options::preserve_arguments }); // Ruby can encode some additional information in the // lower 8 bits. None of those set means "process exited normally" ruby.rb_last_status_set(exec.exit_code << 8, static_cast(exec.pid)); return ruby.utf8_value(exec.output); } catch (timeout_exception const& ex) { // Always raise for timeouts ruby.rb_raise(ruby.lookup({ "Facter", "Core", "Execution", "ExecutionFailure"}), ex.what()); } } // Command was not found if (raise) { if (expanded.empty()) { ruby.rb_raise(ruby.lookup({ "Facter", "Core", "Execution", "ExecutionFailure"}), _("execution of command \"{1}\" failed: command not found.", command).c_str()); } ruby.rb_raise(ruby.lookup({ "Facter", "Core", "Execution", "ExecutionFailure"}), _("execution of command \"{1}\" failed.", command).c_str()); } return failure_default; } void module::initialize_search_paths(vector const& paths) { auto const& ruby = api::instance(); _search_paths.clear(); _additional_search_paths.clear(); // Look for "facter" subdirectories on the load path for (auto const& directory : ruby.get_load_path()) { boost::system::error_code ec; // Use forward-slash to keep this consistent with Ruby conventions. auto dir = canonicalize(directory) + "/facter"; // Ignore facter itself if it's on the load path if (is_regular_file(dir, ec)) { continue; } if (!is_directory(dir, ec)) { continue; } _search_paths.push_back(dir); } // Append the FACTERLIB paths string variable; if (environment::get("FACTERLIB", variable)) { vector env_paths; boost::split(env_paths, variable, bind(equal_to(), placeholders::_1, environment::get_path_separator()), boost::token_compress_on); _search_paths.insert(_search_paths.end(), make_move_iterator(env_paths.begin()), make_move_iterator(env_paths.end())); } // Insert the given paths last _search_paths.insert(_search_paths.end(), paths.begin(), paths.end()); // Do a canonical/absolute transform transform(_search_paths.begin(), _search_paths.end(), _search_paths.begin(), [](string const& directory) -> string { return canonicalize(directory); }); // Remove anything that is empty using the erase-remove idiom. _search_paths.erase( remove_if(begin(_search_paths), end(_search_paths), [](string const& path) { return path.empty(); }), end(_search_paths)); } VALUE module::load_fact(VALUE name) { auto const& ruby = api::instance(); name = normalize(name); string fact_name = ruby.to_string(name); // First check to see if we have that fact already auto it = _facts.find(fact_name); if (it != _facts.end()) { return it->second; } // Try to load it by file name if (!_loaded_all) { // Next, attempt to load it by file string filename = fact_name + ".rb"; LOG_DEBUG("searching for custom fact \"{1}\".", fact_name); for (auto const& directory : _search_paths) { LOG_DEBUG("searching for {1} in {2}.", filename, directory); // Check to see if there's a file of a matching name in this directory path full_path = path(directory) / filename; boost::system::error_code ec; if (!is_regular_file(full_path, ec)) { continue; } // Load the fact file load_file(full_path.string()); } // Check to see if we now have the fact it = _facts.find(fact_name); if (it != _facts.end()) { return it->second; } } // Otherwise, check to see if it's already in the collection auto value = facts()[fact_name]; if (value) { return create_fact(name); } // Couldn't load the fact by file name, load all facts to try to find it load_facts(); // Check to see if we now have the fact it = _facts.find(fact_name); if (it != _facts.end()) { return it->second; } // Couldn't find the fact LOG_DEBUG("custom fact \"{1}\" was not found.", fact_name); return ruby.nil_value(); } void module::load_file(std::string const& path) { // Only load the file if we haven't done so before if (!_loaded_files.insert(path).second) { return; } auto const& ruby = api::instance(); LOG_INFO("loading custom facts from {1}.", path); ruby.rescue([&]() { // Do not construct C++ objects in a rescue callback // C++ stack unwinding will not take place if a Ruby exception is thrown! ruby.rb_load(ruby.utf8_value(path), 0); return 0; }, [&](VALUE ex) { LOG_ERROR("error while resolving custom facts in {1}: {2}", path, ruby.exception_to_string(ex)); return 0; }); } VALUE module::create_fact(VALUE name) { auto const& ruby = api::instance(); if (!ruby.is_string(name) && !ruby.is_symbol(name)) { ruby.rb_raise(*ruby.rb_eTypeError, _("expected a String or Symbol for fact name").c_str()); } name = normalize(name); string fact_name = ruby.to_string(name); // First check to see if we have that fact already auto it = _facts.find(fact_name); if (it == _facts.end()) { // Before adding the first fact, call facts to ensure the collection is populated facts(); // facts() may add entries to _facts, so check again to ensure entry has not already been added (avoid duplicate Ruby GC registration) it = _facts.find(fact_name); if (it == _facts.end()) { it = _facts.insert(make_pair(fact_name, fact::create(name))).first; ruby.rb_gc_register_address(&it->second); } } return it->second; } VALUE module::level_to_symbol(log_level level) { auto const& ruby = api::instance(); char const* name = nullptr; if (level == log_level::trace) { name = "trace"; } else if (level == log_level::debug) { name = "debug"; } else if (level == log_level::info) { name = "info"; } else if (level == log_level::warning) { name = "warn"; } else if (level == log_level::error) { name = "error"; } else if (level == log_level::fatal) { name = "fatal"; } if (!name) { ruby.rb_raise(*ruby.rb_eArgError, _("invalid log level specified.").c_str(), 0); } return ruby.to_symbol(name); } }} // namespace facter::ruby facter-3.14.12/lib/src/ruby/resolution.cc0000644005276200011600000001600413702047406020052 0ustar jenkinsjenkins#include #include #include #include // Mark string for translation (alias for leatherman::locale::format) using leatherman::locale::_; using namespace std; using namespace facter::facts; using namespace leatherman::ruby; namespace facter { namespace ruby { resolution::resolution() : _has_weight(false), _weight(0) { auto const& ruby = api::instance(); _name = ruby.nil_value(); _value = ruby.nil_value(); _flush_block = ruby.nil_value(); } resolution::~resolution() { } VALUE resolution::name() const { return _name; } void resolution::name(VALUE name) { _name = name; } size_t resolution::weight() const { if (_has_weight) { return _weight; } return _confines.size(); } void resolution::weight(size_t weight) { _has_weight = true; _weight = weight; } VALUE resolution::value() { return _value; } void resolution::value(VALUE v) { _value = v; } bool resolution::suitable(module& facter) const { auto const& ruby = api::instance(); int tag = 0; { // Declare all C++ objects here vector::const_iterator it; VALUE result = ruby.protect(tag, [&]() { // Do not declare any C++ objects inside the protect // Their destructors will not be invoked if there is a Ruby exception for (it = _confines.begin(); it != _confines.end(); ++it) { if (!it->suitable(facter)) { return ruby.false_value(); } } return ruby.true_value(); }); // If all confines were suitable, the resolution is considered to be suitable if (!tag) { return ruby.is_true(result); } } // Now that the above block has exited, it's safe to jump to the given tag ruby.rb_jump_tag(tag); return false; } void resolution::flush() const { auto const& ruby = api::instance(); if (ruby.is_nil(_flush_block)) { return; } ruby.rb_funcall(_flush_block, ruby.rb_intern("call"), 0); } void resolution::confine(VALUE confines) { auto const& ruby = api::instance(); if (ruby.is_nil(confines)) { // No confines, only a block is required if (!ruby.rb_block_given_p()) { ruby.rb_raise(*ruby.rb_eArgError, _("a block must be provided").c_str()); } _confines.emplace_back(ruby::confine(ruby.nil_value(), ruby.nil_value(), ruby.rb_block_proc())); } else { if (ruby.is_symbol(confines)) { confines = ruby.rb_sym_to_s(confines); } if (ruby.is_string(confines)) { // Argument is a string and a is block required if (!ruby.rb_block_given_p()) { ruby.rb_raise(*ruby.rb_eArgError, _("a block must be provided").c_str()); } _confines.emplace_back(ruby::confine(confines, ruby.nil_value(), ruby.rb_block_proc())); } else if (ruby.is_hash(confines)) { // Argument is a hash (block should not be given) if (ruby.rb_block_given_p()) { ruby.rb_raise(*ruby.rb_eArgError, _("a block is unexpected when passing a Hash").c_str()); } ruby.hash_for_each(confines, [&](VALUE key, VALUE value) { if (ruby.is_symbol(key)) { key = ruby.rb_sym_to_s(key); } if (!ruby.is_string(key)) { ruby.rb_raise(*ruby.rb_eTypeError, _("expected a String or Symbol for confine key").c_str()); } if (ruby.is_symbol(value)) { value = ruby.rb_sym_to_s(value); } _confines.emplace_back(ruby::confine(key, value, ruby.nil_value())); return true; }); } else { ruby.rb_raise(*ruby.rb_eTypeError, _("expected argument to be a String, Symbol, or Hash").c_str()); } } } void resolution::define(VALUE klass) { auto const& ruby = api::instance(); ruby.rb_define_method(klass, "confine", RUBY_METHOD_FUNC(ruby_confine), -1); ruby.rb_define_method(klass, "has_weight", RUBY_METHOD_FUNC(ruby_has_weight), 1); ruby.rb_define_method(klass, "name", RUBY_METHOD_FUNC(ruby_name), 0); ruby.rb_define_method(klass, "timeout=", RUBY_METHOD_FUNC(ruby_timeout), 1); ruby.rb_define_method(klass, "on_flush", RUBY_METHOD_FUNC(ruby_on_flush), 0); } void resolution::mark() const { auto const& ruby = api::instance(); // Mark the name and value ruby.rb_gc_mark(_name); ruby.rb_gc_mark(_value); ruby.rb_gc_mark(_flush_block); // Mark all of the confines for (auto const& confine : _confines) { confine.mark(); } } VALUE resolution::ruby_confine(int argc, VALUE* argv, VALUE self) { auto const& ruby = api::instance(); if (argc > 1) { ruby.rb_raise(*ruby.rb_eArgError, _("wrong number of arguments ({1} for 1)", argc).c_str()); } ruby.to_native(self)->confine(argc == 0 ? ruby.nil_value() : argv[0]); return self; } VALUE resolution::ruby_has_weight(VALUE self, VALUE value) { auto const& ruby = api::instance(); int64_t val = ruby.rb_num2ll(value); if (val < 0) { ruby.rb_raise(*ruby.rb_eTypeError, "expected a non-negative value for has_weight (not %lld)", val); } auto instance = ruby.to_native(self); instance->_has_weight = true; instance->_weight = static_cast(val); return self; } VALUE resolution::ruby_name(VALUE self) { auto const& ruby = api::instance(); return ruby.to_native(self)->name(); } VALUE resolution::ruby_timeout(VALUE self, VALUE timeout) { static bool timeout_warning = true; if (timeout_warning) { LOG_WARNING("timeout= is not supported for custom facts and will be ignored.") timeout_warning = false; } // Do nothing as we don't support timeouts return self; } VALUE resolution::ruby_on_flush(VALUE self) { auto const& ruby = api::instance(); if (!ruby.rb_block_given_p()) { ruby.rb_raise(*ruby.rb_eArgError, _("a block must be provided").c_str()); } ruby.to_native(self)->_flush_block = ruby.rb_block_proc(); return self; } }} // namespace facter::ruby facter-3.14.12/lib/src/ruby/ruby.cc0000644005276200011600000001605313702047406016634 0ustar jenkinsjenkins#include #include #include #include #include #include #ifdef _WIN32 #include #endif #include using namespace std; using namespace facter::facts; using namespace leatherman::ruby; static const char load_puppet[] = "require 'puppet'\n" "Puppet.initialize_settings\n" "unless $LOAD_PATH.include?(Puppet[:libdir])\n" " $LOAD_PATH << Puppet[:libdir]\n" "end\n" "Facter.reset\n" "Facter.search_external([Puppet[:pluginfactdest]])\n" "if Puppet.respond_to? :initialize_facts\n" " Puppet.initialize_facts\n" "else\n" " Facter.add(:puppetversion) do\n" " setcode { Puppet.version.to_s }\n" " end\n" "end\n"; // This struct redirects stdout to stderr in the ruby runtime for the // duration of its lifetime. We use this to ensure that any custom // facts writing to stdout during their initialization or execution // won't corrupt json/yaml output from the facter executable. struct RbStdoutGuard { VALUE old_stdout; api& ruby; RbStdoutGuard(api& ruby) :ruby(ruby) { LOG_DEBUG("Redirecting ruby's stdout to stderr"); auto rb_stderr = ruby.rb_gv_get("$stderr"); old_stdout = ruby.rb_gv_get("$stdout"); ruby.rb_gv_set("$stdout", rb_stderr); } ~RbStdoutGuard() { LOG_DEBUG("Restoring Ruby's stdout"); ruby.rb_gv_set("$stdout", old_stdout); } }; namespace facter { namespace ruby { bool initialize(bool include_stack_trace) { #ifdef FACTER_RUBY api::ruby_lib_location = FACTER_RUBY; #endif try { auto& ruby = api::instance(); ruby.initialize(); ruby.include_stack_trace(include_stack_trace); } catch (runtime_error& ex) { LOG_WARNING("{1}: facts requiring Ruby will not be resolved.", ex.what()); return false; } return true; } void load_custom_facts(collection& facts, bool initialize_puppet, bool redirect_stdout, vector const& paths) { #ifdef _WIN32 // Initialize WSA before resolving custom facts. The Ruby runtime does this only when running // in a Ruby process, it leaves it up to us when embedding it. See // https://github.com/ruby/ruby/blob/v2_1_9/ruby.c#L2011-L2022 for comments. // The only piece we seem to need out of rb_w32_sysinit is WSAStartup. util::windows::wsa winsocket; // Disable stdout buffering while loading custom facts, similar to `stderr` in `init_stdhandle` // https://github.com/ruby/ruby/blob/9e41a75255d15765648279629fd3134cae076398/win32/win32.c#L2655 // This is needed in a specific case: // - run facter from ruby with backticks // - have a custom fact executing external command with backticks // In this case, `\x00` character will be shown on stdout instead of fact output // We suppose that somwhere between ruby(`facter my_fact`)<->c(rb_load)<->ruby(Facter.add)<->c(rb_funcall_passing_block)<->ruby(`echo test`) // stdout gets the wchar end of string that will break it setvbuf(stdout, NULL, _IONBF, 0); #endif api& ruby = api::instance(); module mod(facts, {}, !initialize_puppet); if (initialize_puppet) { try { ruby.eval(load_puppet); } catch (exception& ex) { LOG_WARNING("Could not load puppet; some facts may be unavailable: {1}", ex.what()); } } mod.search(paths); if (redirect_stdout) { // Redirect stdout->stderr for custom facts. RbStdoutGuard stdout_guard{ruby}; mod.resolve_facts(); } else { mod.resolve_facts(); } #ifdef _WIN32 // Enable stdout line buffering (disabled due custom facts loading) setvbuf(stdout, NULL, _IOLBF, 0); #endif } void load_custom_facts(collection& facts, vector const& paths) { load_custom_facts(facts, false, false, paths); } void load_custom_facts(collection& facts, bool initialize_puppet, vector const& paths) { load_custom_facts(facts, initialize_puppet, false, paths); } value const* lookup(value const* value, vector::iterator segment, vector::iterator end) { auto rb_value = dynamic_cast(value); if (!rb_value) { return nullptr; } // Check for a cached lookup auto key = accumulate(segment, end, string{}, [](const string& a, const string& b) -> string { if (b.find(".") != string::npos) { return a+".\""+b+"\""; } else { return a+"."+b; } }); auto child_value = rb_value->child(key); if (child_value) { return child_value; } auto val = rb_value->value(); // now we're in ruby land api& ruby = api::instance(); for (; segment != end; ++segment) { if (ruby.is_array(val)) { long index; try { index = stol(*segment); } catch (logic_error&) { LOG_DEBUG("cannot lookup an array element with \"{1}\": expected an integral value.", *segment); return nullptr; } if (index < 0) { LOG_DEBUG("cannot lookup an array element with \"{1}\": expected a non-negative value.", *segment); return nullptr; } long length = ruby.array_len(val); if (0 == length) { LOG_DEBUG("cannot lookup an array element with \"{1}\": the array is empty.", *segment); return nullptr; } if (index >= length) { LOG_DEBUG("cannot lookup an array element with \"{1}\": expected an integral value between 0 and {2} (inclusive).", *segment, length - 1); return nullptr; } val = ruby.rb_ary_entry(val, index); } else if (ruby.is_hash(val)) { // if we're anything but an array, we look up by name auto key = ruby.utf8_value(*segment); auto result = ruby.rb_hash_lookup(val, key); if (ruby.is_nil(result)) { // We also want to try looking up as a symbol key = ruby.to_symbol(*segment); result = ruby.rb_hash_lookup(val, key); } val = result; } else { LOG_DEBUG("cannot lookup element \"{1}\": container is not an array or hash", *segment); } if (ruby.is_nil(val)) { return nullptr; } } return rb_value->wrap_child(val, move(key)); } void uninitialize() { api& ruby = api::instance(); ruby.uninitialize(); } }} // namespace facter::ruby facter-3.14.12/lib/src/ruby/ruby_value.cc0000644005276200011600000002130613702047406020025 0ustar jenkinsjenkins#include #include #include #include #include using namespace std; using namespace facter::facts; using namespace facter::util; using namespace rapidjson; using namespace YAML; using namespace leatherman::ruby; namespace facter { namespace ruby { ruby_value::ruby_value(VALUE value) : _value(value) { auto const& ruby = api::instance(); ruby.rb_gc_register_address(&_value); } ruby_value::~ruby_value() { auto const& ruby = api::instance(); ruby.rb_gc_unregister_address(&_value); } ruby_value::ruby_value(ruby_value&& other) : _value(other._value) { auto const& ruby = api::instance(); ruby.rb_gc_register_address(&_value); } ruby_value& ruby_value::operator=(ruby_value&& other) { _value = other._value; return *this; } void ruby_value::to_json(json_allocator& allocator, json_value& value) const { auto const& ruby = api::instance(); to_json(ruby, _value, allocator, value); } ostream& ruby_value::write(ostream& os, bool quoted, unsigned int level) const { auto const& ruby = api::instance(); write(ruby, _value, os, quoted, level); return os; } Emitter& ruby_value::write(Emitter& emitter) const { auto const& ruby = api::instance(); write(ruby, _value, emitter); return emitter; } VALUE ruby_value::value() const { return _value; } void ruby_value::to_json(api const& ruby, VALUE value, json_allocator& allocator, json_value& json) { if (ruby.is_true(value)) { json.SetBool(true); return; } if (ruby.is_false(value)) { json.SetBool(false); return; } if (ruby.is_string(value) || ruby.is_symbol(value)) { volatile VALUE temp = value; if (ruby.is_symbol(value)) { temp = ruby.rb_funcall(value, ruby.rb_intern("to_s"), 0); } size_t size = ruby.num2size_t(ruby.rb_funcall(temp, ruby.rb_intern("bytesize"), 0)); char const* str = ruby.rb_string_value_ptr(&temp); json.SetString(str, size, allocator); return; } if (ruby.is_integer(value)) { json.SetInt64(ruby.rb_num2ll(value)); return; } if (ruby.is_float(value)) { json.SetDouble(ruby.rb_num2dbl(value)); return; } if (ruby.is_array(value)) { json.SetArray(); size_t size = ruby.num2size_t(ruby.rb_funcall(value, ruby.rb_intern("size"), 0)); json.Reserve(size, allocator); ruby.array_for_each(value, [&](VALUE element) { json_value child; to_json(ruby, element, allocator, child); json.PushBack(child, allocator); return true; }); return; } if (ruby.is_hash(value)) { json.SetObject(); ruby.hash_for_each(value, [&](VALUE key, VALUE element) { // If the key isn't a string, convert to string if (!ruby.is_string(key)) { key = ruby.rb_funcall(key, ruby.rb_intern("to_s"), 0); } json_value child; to_json(ruby, element, allocator, child); json.AddMember(json_value(ruby.rb_string_value_ptr(&key), allocator), child, allocator); return true; }); return; } json.SetNull(); } void ruby_value::write(api const& ruby, VALUE value, ostream& os, bool quoted, unsigned int level) { if (ruby.is_true(value)) { os << boolalpha << true << noboolalpha; return; } if (ruby.is_false(value)) { os << boolalpha << false << noboolalpha; return; } if (ruby.is_string(value) || ruby.is_symbol(value)) { volatile VALUE temp = value; if (ruby.is_symbol(value)) { temp = ruby.rb_funcall(value, ruby.rb_intern("to_s"), 0); } size_t size = ruby.num2size_t(ruby.rb_funcall(temp, ruby.rb_intern("bytesize"), 0)); char const* str = ruby.rb_string_value_ptr(&temp); if (quoted) { os << '"'; } os.write(str, size); if (quoted) { os << '"'; } return; } if (ruby.is_integer(value)) { os << ruby.rb_num2ll(value); return; } if (ruby.is_float(value)) { os << ruby.rb_num2dbl(value); return; } if (ruby.is_array(value)) { auto size = ruby.num2size_t(ruby.rb_funcall(value, ruby.rb_intern("size"), 0)); if (size == 0) { os << "[]"; return; } os << "[\n"; bool first = true; ruby.array_for_each(value, [&](VALUE element) { if (first) { first = false; } else { os << ",\n"; } fill_n(ostream_iterator(os), level * 2, ' '); write(ruby, element, os, true, level + 1); return true; }); os << "\n"; fill_n(ostream_iterator(os), (level > 0 ? (level - 1) : 0) * 2, ' '); os << "]"; return; } if (ruby.is_hash(value)) { auto size = ruby.num2size_t(ruby.rb_funcall(value, ruby.rb_intern("size"), 0)); if (size == 0) { os << "{}"; return; } os << "{\n"; bool first = true; ruby.hash_for_each(value, [&](VALUE key, VALUE element) { if (first) { first = false; } else { os << ",\n"; } // If the key isn't a string, convert to string if (!ruby.is_string(key)) { key = ruby.rb_funcall(key, ruby.rb_intern("to_s"), 0); } size_t size = ruby.num2size_t(ruby.rb_funcall(key, ruby.rb_intern("bytesize"), 0)); char const* str = ruby.rb_string_value_ptr(&key); fill_n(ostream_iterator(os), level * 2, ' '); os.write(str, size); os << " => "; write(ruby, element, os, true, level + 1); return true; }); os << "\n"; fill_n(ostream_iterator(os), (level > 0 ? (level - 1) : 0) * 2, ' '); os << "}"; return; } } void ruby_value::write(api const& ruby, VALUE value, YAML::Emitter& emitter) { if (ruby.is_true(value)) { emitter << true; return; } if (ruby.is_false(value)) { emitter << false; return; } if (ruby.is_string(value) || ruby.is_symbol(value)) { auto str = ruby.to_string(value); if (needs_quotation(str)) { emitter << DoubleQuoted; } emitter << str; return; } if (ruby.is_integer(value)) { emitter << ruby.rb_num2ll(value); return; } if (ruby.is_float(value)) { emitter << ruby.rb_num2dbl(value); return; } if (ruby.is_array(value)) { emitter << BeginSeq; ruby.array_for_each(value, [&](VALUE element) { write(ruby, element, emitter); return true; }); emitter << EndSeq; return; } if (ruby.is_hash(value)) { emitter << BeginMap; ruby.hash_for_each(value, [&](VALUE key, VALUE element) { emitter << Key << ruby.to_string(key) << YAML::Value; write(ruby, element, emitter); return true; }); emitter << EndMap; return; } emitter << Null; } ruby_value const* ruby_value::wrap_child(VALUE child, string key) const { return _children.emplace(move(key), std::unique_ptr(new ruby_value(child))).first->second.get(); } ruby_value const* ruby_value::child(const string& key) const { auto child = _children.find(key); if (child != end(_children)) { return child->second.get(); } else { return nullptr; } } }} // namespace facter::ruby facter-3.14.12/lib/src/ruby/simple_resolution.cc0000644005276200011600000001231613702047406021425 0ustar jenkinsjenkins#include #include #include #include // Mark string for translation (alias for leatherman::locale::format) using leatherman::locale::_; using namespace std; using namespace facter::facts; using namespace leatherman::execution; using namespace leatherman::ruby; namespace facter { namespace ruby { simple_resolution::simple_resolution() { auto const& ruby = api::instance(); _self = ruby.nil_value(); _block = ruby.nil_value(); _command = ruby.nil_value(); } VALUE simple_resolution::define() { auto const& ruby = api::instance(); // Define the Resolution class VALUE klass = ruby.rb_define_class_under(ruby.lookup({"Facter", "Util"}), "Resolution", *ruby.rb_cObject); ruby.rb_define_alloc_func(klass, alloc); ruby.rb_define_method(klass, "setcode", RUBY_METHOD_FUNC(ruby_setcode), -1); // Deprecated in Facter 2.0; implementing for backwards compatibility ruby.rb_define_singleton_method(klass, "which", RUBY_METHOD_FUNC(ruby_which), 1); ruby.rb_define_singleton_method(klass, "exec", RUBY_METHOD_FUNC(ruby_exec), 1); resolution::define(klass); return klass; } VALUE simple_resolution::create() { auto const& ruby = api::instance(); return ruby.rb_class_new_instance(0, nullptr, ruby.lookup({"Facter", "Util", "Resolution"})); } VALUE simple_resolution::value() { auto const& ruby = api::instance(); volatile VALUE value = resolution::value(); // If the resolution has a value, return it if (!ruby.is_nil(value)) { return value; } // If given a block, call it to resolve if (!ruby.is_nil(_block)) { return ruby.rb_funcall(_block, ruby.rb_intern("call"), 0); } if (ruby.is_nil(_command)) { return ruby.nil_value(); } // Otherwise, we were given a command so execute it VALUE result = ruby.rb_funcall(ruby.lookup({ "Facter", "Core", "Execution" }), ruby.rb_intern("exec"), 1, _command); if (ruby.is_nil(result) || ruby.is_true(ruby.rb_funcall(result, ruby.rb_intern("empty?"), 0))) { return ruby.nil_value(); } return result; } VALUE simple_resolution::alloc(VALUE klass) { auto const& ruby = api::instance(); // Create a resolution and wrap with a Ruby data object unique_ptr r(new simple_resolution()); VALUE self = r->_self = ruby.rb_data_object_alloc(klass, r.get(), mark, free); ruby.register_data_object(self); // Release the smart pointer; ownership is now with Ruby's GC r.release(); return self; } void simple_resolution::mark(void* data) { // Mark all VALUEs contained in the simple resolution auto const& ruby = api::instance(); auto instance = reinterpret_cast(data); // Call the base first instance->resolution::mark(); // Mark the setcode block and command ruby.rb_gc_mark(instance->_block); ruby.rb_gc_mark(instance->_command); } void simple_resolution::free(void* data) { auto instance = reinterpret_cast(data); // Unregister the data object auto const& ruby = api::instance(); ruby.unregister_data_object(instance->_self); // Delete the simple resolution delete instance; } VALUE simple_resolution::ruby_setcode(int argc, VALUE* argv, VALUE self) { auto const& ruby = api::instance(); if (argc > 1) { ruby.rb_raise(*ruby.rb_eArgError, _("wrong number of arguments ({1} for 1)", argc).c_str()); } auto instance = ruby.to_native(self); if (argc == 0) { // No arguments, only a block is required if (!ruby.rb_block_given_p()) { ruby.rb_raise(*ruby.rb_eArgError, _("a block must be provided").c_str()); } instance->_block = ruby.rb_block_proc(); } else if (argc == 1) { VALUE arg = argv[0]; if (!ruby.is_string(arg) || ruby.is_true(ruby.rb_funcall(arg, ruby.rb_intern("empty?"), 0))) { ruby.rb_raise(*ruby.rb_eTypeError, _("expected a non-empty String for first argument").c_str()); } if (ruby.rb_block_given_p()) { ruby.rb_raise(*ruby.rb_eArgError, _("a block is unexpected when passing a String").c_str()); } instance->_command = arg; } return self; } VALUE simple_resolution::ruby_which(VALUE klass, VALUE binary) { auto const& ruby = api::instance(); return ruby.rb_funcall(ruby.lookup({ "Facter", "Core", "Execution" }), ruby.rb_intern("which"), 1, binary); } VALUE simple_resolution::ruby_exec(VALUE klass, VALUE command) { auto const& ruby = api::instance(); return ruby.rb_funcall(ruby.lookup({ "Facter", "Core", "Execution" }), ruby.rb_intern("exec"), 1, command); } }} // namespace facter::ruby facter-3.14.12/lib/src/util/0000755005276200011600000000000013702047635015337 5ustar jenkinsjenkinsfacter-3.14.12/lib/src/util/bsd/0000755005276200011600000000000013702047635016107 5ustar jenkinsjenkinsfacter-3.14.12/lib/src/util/bsd/scoped_ifaddrs.cc0000644005276200011600000000121213702047406021357 0ustar jenkinsjenkins#include using namespace std; using namespace leatherman::util; namespace facter { namespace util { namespace bsd { scoped_ifaddrs::scoped_ifaddrs() : scoped_resource(nullptr, free) { // Get the linked list of interfaces if (getifaddrs(&_resource) == -1) { _resource = nullptr; } } scoped_ifaddrs::scoped_ifaddrs(ifaddrs* addrs) : scoped_resource(move(addrs), free) { } void scoped_ifaddrs::free(ifaddrs* addrs) { if (addrs) { ::freeifaddrs(addrs); } } }}} // namespace facter::util::bsd facter-3.14.12/lib/src/util/config/0000755005276200011600000000000013702047635016604 5ustar jenkinsjenkinsfacter-3.14.12/lib/src/util/config/config.cc0000644005276200011600000001133113702047406020353 0ustar jenkinsjenkins#include #include #include #include using namespace std; using namespace hocon; namespace po = boost::program_options; namespace facter { namespace util { namespace config { shared_config load_config_from(string config_path) { if (leatherman::file_util::file_readable(config_path)) { return hocon::config::parse_file_any_syntax(config_path)->resolve(); } return nullptr; } void load_global_settings(shared_config hocon_config, po::variables_map& vm) { if (hocon_config && hocon_config->has_path("global")) { auto global_settings = hocon_config->get_object("global")->to_config(); po::store(hocon::program_options::parse_hocon(global_settings, global_config_options(), true), vm); } } void load_cli_settings(shared_config hocon_config, po::variables_map& vm) { if (hocon_config && hocon_config->has_path("cli")) { auto cli_settings = hocon_config->get_object("cli")->to_config(); po::store(hocon::program_options::parse_hocon(cli_settings, cli_config_options(), true), vm); } } void load_fact_settings(shared_config hocon_config, po::variables_map& vm) { if (hocon_config && hocon_config->has_path("facts")) { auto fact_settings = hocon_config->get_object("facts")->to_config(); po::store(hocon::program_options::parse_hocon(fact_settings, fact_config_options(), true), vm); } } void load_fact_groups_settings(shared_config hocon_config, po::variables_map& vm) { if (hocon_config && hocon_config->has_path("fact-groups")) { auto fact_groups_settings = hocon_config->get_object("fact-groups")->to_config(); po::store(hocon::program_options::parse_hocon(fact_groups_settings, fact_groups_config_options(), true), vm); } } po::options_description global_config_options() { po::options_description global_options(""); global_options.add_options() ("custom-dir", po::value>(), "A directory or list of directories to use for custom facts.") ("external-dir", po::value>(), "A directory or list of directories to use for external facts.") ("no-custom-facts", po::value()->default_value(false), "Disables custom facts.") ("no-external-facts", po::value()->default_value(false), "Disables external facts.") ("no-ruby", po::value()->default_value(false), "Disables loading Ruby, facts requiring Ruby, and custom facts."); return global_options; } po::options_description cli_config_options() { po::options_description cli_options(""); cli_options.add_options() ("debug", po::value()->default_value(false), "Enable debug output.") ("log-level", po::value()->default_value(logging::level::warning, "warn"), "Set logging level.\nSupported levels are: none, trace, debug, info, warn, error, and fatal.") ("trace", po::value()->default_value(false), "Enable backtraces for custom facts.") ("verbose", po::value()->default_value(false), "Enable verbose (info) output."); return cli_options; } po::options_description fact_config_options() { po::options_description fact_settings(""); fact_settings.add_options() ("blocklist", po::value>(), "A set of facts to block."); return fact_settings; } po::options_description fact_groups_config_options() { po::options_description fact_groups_settings(""); fact_groups_settings.add_options() ("cached-custom-facts", po::value>(), "A list of custom facts to be cached."); return fact_groups_settings; } unordered_map load_ttls(shared_config hocon_config) { unordered_map ttls; if (hocon_config && hocon_config->has_path("facts.ttls")) { auto ttl_objs = hocon_config->get_object_list("facts.ttls"); for (auto entry : ttl_objs) { shared_config entry_conf = entry->to_config(); // triple-quote this string so that cpp-hocon will correctly parse it as a single path element // and ignore otherwise reserved characters string fact = entry->key_set().front(); int64_t duration = entry_conf->get_duration("\"\"\"" + fact + "\"\"\"", time_unit::SECONDS); ttls.insert({ fact, duration }); } } return ttls; } }}} // namespace facter::util::config; facter-3.14.12/lib/src/util/config/posix/0000755005276200011600000000000013702047635017746 5ustar jenkinsjenkinsfacter-3.14.12/lib/src/util/config/posix/config.cc0000644005276200011600000000054213702047406021517 0ustar jenkinsjenkins#include namespace facter { namespace util { namespace config { hocon::shared_config load_default_config_file() { return load_config_from(default_config_location()); } std::string default_config_location() { return "/etc/puppetlabs/facter/facter.conf"; } }}} // namespace facter::util::config facter-3.14.12/lib/src/util/config/windows/0000755005276200011600000000000013702047635020276 5ustar jenkinsjenkinsfacter-3.14.12/lib/src/util/config/windows/config.cc0000644005276200011600000000072613702047406022053 0ustar jenkinsjenkins#include #include namespace facter { namespace util { namespace config { hocon::shared_config load_default_config_file() { return load_config_from(default_config_location()); } std::string default_config_location() { return leatherman::windows::file_util::get_programdata_dir() + "\\PuppetLabs\\facter\\etc\\facter.conf"; } }}} // namespace facter::util::config facter-3.14.12/lib/src/util/freebsd/0000755005276200011600000000000013702047635016751 5ustar jenkinsjenkinsfacter-3.14.12/lib/src/util/freebsd/geom.cc0000644005276200011600000000550313702047406020206 0ustar jenkinsjenkins#include #include #include using leatherman::locale::_; using namespace std; namespace facter { namespace util { namespace freebsd { geom_exception::geom_exception(std::string const& message) : runtime_error(message) { } geom_config::geom_config(string name, string value) { _name = name; _value = value; } string geom_config::name() { return _name; } string geom_config::value() { return _value; } geom_object_with_config::geom_object_with_config(struct gconf *conf) { struct gconfig *config; LIST_FOREACH(config, conf, lg_config) { if (!config->lg_val) { LOG_DEBUG(_("Skipping config {1} because it has a null value", config->lg_name)); continue; } _configs.push_back(geom_config(config->lg_name, config->lg_val)); } } string geom_object_with_config::config(string name) { for (auto config : _configs) { if (config.name() == name) return config.value(); } return ""; } geom_provider::geom_provider(struct gprovider* provider) : geom_object_with_config(&provider->lg_config) { _name = provider->lg_name; _mode = provider->lg_mode; _mediasize = provider->lg_mediasize; _sectorsize = provider->lg_sectorsize; _stripeoffset = provider->lg_stripeoffset; _stripesize = provider->lg_stripesize; } string geom_provider::name() { return _name; } off_t geom_provider::mediasize() { return _mediasize; } geom_geom::geom_geom(struct ggeom *geom) : geom_object_with_config(&geom->lg_config) { _name = geom->lg_name; struct gprovider *provider; LIST_FOREACH(provider, &geom->lg_provider, lg_provider) { providers.push_back(geom_provider(provider)); } } string geom_geom::name() { return _name; } geom_class::geom_class(string type) { if (geom_gettree(&_mesh) < 0) { throw geom_exception(_("Unable to get GEOM tree")); } LIST_FOREACH(_class, &(_mesh.lg_class), lg_class) { if (type == string(_class->lg_name)) break; } if (!_class) { throw geom_exception(_("The GEOM class \"{1}\" was not found", type)); } struct ggeom *geom; LIST_FOREACH(geom, &(_class->lg_geom), lg_geom) { geoms.push_back(geom_geom(geom)); } } geom_class::~geom_class() { geom_deletetree(&_mesh); } }}} // namespace facter::util::freebsd facter-3.14.12/lib/src/util/posix/0000755005276200011600000000000013702047635016501 5ustar jenkinsjenkinsfacter-3.14.12/lib/src/util/posix/scoped_addrinfo.cc0000644005276200011600000000172313702047406022132 0ustar jenkinsjenkins#include using namespace std; using namespace leatherman::util; namespace facter { namespace util { namespace posix { scoped_addrinfo::scoped_addrinfo(string const& hostname) : scoped_resource(nullptr, free) { addrinfo hints; memset(&hints, 0, sizeof hints); hints.ai_family = AF_UNSPEC; hints.ai_socktype = SOCK_STREAM; hints.ai_flags = AI_CANONNAME; _result = getaddrinfo(hostname.c_str(), nullptr, &hints, &_resource); if (_result != 0) { _resource = nullptr; } } scoped_addrinfo::scoped_addrinfo(addrinfo* info) : scoped_resource(move(info), free), _result(0) { } int scoped_addrinfo::result() const { return _result; } void scoped_addrinfo::free(addrinfo* info) { if (info) { ::freeaddrinfo(info); } } }}} // namespace facter::util::posix facter-3.14.12/lib/src/util/posix/scoped_descriptor.cc0000644005276200011600000000071513702047406022522 0ustar jenkinsjenkins#include using namespace std; using namespace leatherman::util; namespace facter { namespace util { namespace posix { scoped_descriptor::scoped_descriptor(int descriptor) : scoped_resource(move(descriptor), close) { } void scoped_descriptor::close(int descriptor) { if (descriptor >= 0) { ::close(descriptor); } } }}} // namespace facter::util::posix facter-3.14.12/lib/src/util/posix/utmpx_file.cc0000644005276200011600000000165713702047406021171 0ustar jenkinsjenkins#include #include #include // Mark string for translation (alias for leatherman::locale::format) using leatherman::locale::_; using namespace std; namespace facter { namespace util { namespace posix { bool utmpx_file::instance_exists = false; utmpx_file::utmpx_file() { if (utmpx_file::instance_exists) { throw logic_error(_("only one utmpx_file instance can exist at a time!")); } utmpx_file::instance_exists = true; reset(); } utmpx_file::~utmpx_file() { endutxent(); utmpx_file::instance_exists = false; } const utmpx* utmpx_file::query(utmpx const& query) const { LOG_DEBUG(_("Reading the utmpx file ...")); return getutxid(&query); } void utmpx_file::reset() const { setutxent(); } }}} // namespace facter::util::posix facter-3.14.12/lib/src/util/scoped_bio.cc0000644005276200011600000000135013702047406017747 0ustar jenkinsjenkins#pragma clang diagnostic ignored "-Wdeprecated-declarations" #include using namespace std; using namespace leatherman::util; namespace facter { namespace util { // Remove const-ness before calling BIO_new. This is "unsafe", // but in isolation here will not cause issues. Allows the code to work // with both OpenSSL 1.0 and 1.1. scoped_bio::scoped_bio(const BIO_METHOD* method) : scoped_resource(BIO_new(const_cast(method)), free) { } scoped_bio::scoped_bio(BIO* bio) : scoped_resource(move(bio), free) { } void scoped_bio::free(BIO* bio) { if (bio) { BIO_free(bio); } } }} // namespace facter::util facter-3.14.12/lib/src/util/scoped_file.cc0000644005276200011600000000107013702047406020114 0ustar jenkinsjenkins#include #include using namespace std; using namespace leatherman::util; namespace facter { namespace util { scoped_file::scoped_file(string const& path, string const& mode) : scoped_resource(boost::nowide::fopen(path.c_str(), mode.c_str()), close) { } scoped_file::scoped_file(FILE* file) : scoped_resource(move(file), close) { } void scoped_file::close(FILE* file) { if (file) { fclose(file); } } }} // namespace facter::util facter-3.14.12/lib/src/util/solaris/0000755005276200011600000000000013702047635017013 5ustar jenkinsjenkinsfacter-3.14.12/lib/src/util/solaris/k_stat.cc0000644005276200011600000001112413702047406020602 0ustar jenkinsjenkins#include #include #include #include // Mark string for translation (alias for leatherman::locale::format) using leatherman::locale::_; using namespace std; namespace facter { namespace util { namespace solaris { k_stat::k_stat() { if (ctrl == nullptr) { throw kstat_exception(_("kstat_open failed")); } } vector k_stat::operator[](string const& module) { return lookup(module, -1, {}); } vector k_stat::operator[](pair const& entry) { return lookup(entry.first, entry.second, {}); } vector k_stat::operator[](pair const& entry) { return lookup(entry.first, -1, entry.second); } // I believe precedence to be sufficiently obvious in this function, // but this is a worthwhile diagnostic in most cases. We disable it // here, instead of globally. #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wparentheses" vector k_stat::lookup(string const& module, int instance, string const& name) { kstat_t* kp = static_cast(ctrl)->kc_chain; vector arr; do { if (!module.empty() && module != kp->ks_module || !name.empty() && name != kp->ks_name || instance != -1 && instance != kp->ks_instance) { continue; } while (kstat_read(ctrl, kp, 0) == -1) { if (errno == EAGAIN) { continue; } else { throw kstat_exception(_("kstat_read failed: {1} ({2})", string(strerror(errno)), to_string(errno))); } } arr.push_back(k_stat_entry(kp)); } while (kp = kp->ks_next); return arr; } #pragma GCC diagnostic pop k_stat_entry::k_stat_entry(kstat_t* kp) : k_stat(kp) { } int k_stat_entry::instance() { return k_stat->ks_instance; } string k_stat_entry::klass() { return k_stat->ks_class; } string k_stat_entry::module() { return k_stat->ks_module; } string k_stat_entry::name() { return k_stat->ks_name; } kstat_named_t* k_stat_entry::lookup(const string& attrib) const { kstat_named_t* knp = reinterpret_cast(kstat_data_lookup(k_stat, const_cast(attrib.c_str()))); if (knp == nullptr) { throw kstat_exception(_("kstat_data_lookup failed for {1}", attrib)); } return knp; } kstat_named_t* k_stat_entry::lookup(int datatype, const string& attrib) const { kstat_named_t* knp = reinterpret_cast(kstat_data_lookup(k_stat, const_cast(attrib.c_str()))); if (knp == nullptr) { throw kstat_exception(_("kstat_data_lookup failed for {1}", attrib)); } if (knp->data_type != datatype) { throw kstat_exception(_("invalid datatype {1} {2}", attrib, to_string(knp->data_type))); } return knp; } template<> ulong_t k_stat_entry::value(const std::string& attrib) const { return lookup(KSTAT_DATA_ULONG, attrib)->value.ul; } template<> long k_stat_entry::value(const std::string& attrib) const { return lookup(KSTAT_DATA_LONG, attrib)->value.l; } template<> int32_t k_stat_entry::value(const std::string& attrib) const { return lookup(KSTAT_DATA_INT32, attrib)->value.i32; } template<> uint32_t k_stat_entry::value(const std::string& attrib) const { return lookup(KSTAT_DATA_UINT32, attrib)->value.ui32; } template<> int64_t k_stat_entry::value(const std::string& attrib) const { return lookup(KSTAT_DATA_INT64, attrib)->value.i64; } template<> uint64_t k_stat_entry::value(const std::string& attrib) const { return lookup(KSTAT_DATA_UINT64, attrib)->value.ui64; } template<> std::string k_stat_entry::value(const std::string& attrib) const { auto res = lookup(attrib); if (res->data_type == KSTAT_DATA_STRING) { return res->value.str.addr.ptr; } else if (res->data_type == KSTAT_DATA_CHAR) { return string(res->value.c); } throw kstat_exception(_("invalid datatype {1} {2}", attrib, to_string(res->data_type))); } }}} // namespace facter::util::solaris facter-3.14.12/lib/src/util/solaris/scoped_kstat.cc0000644005276200011600000000123013702047406021775 0ustar jenkinsjenkins#include using namespace std; using namespace leatherman::util; namespace facter { namespace util { namespace solaris { scoped_kstat::scoped_kstat() : scoped_resource(nullptr, close) { _resource = kstat_open(); } scoped_kstat::scoped_kstat(kstat_ctl* ctrl) : scoped_resource(move(ctrl), free) { } void scoped_kstat::close(kstat_ctl* ctrl) { if (ctrl) { ::kstat_close(ctrl); } } kstat_exception::kstat_exception(std::string const& message) : runtime_error(message) { } }}} // namespace facter::util::solaris facter-3.14.12/lib/src/util/string.cc0000644005276200011600000001240113702047406017146 0ustar jenkinsjenkins#include #include #include #include #include #include #include #include using namespace std; namespace facter { namespace util { string to_hex(uint8_t const* bytes, size_t length, bool uppercase) { ostringstream ss; if (bytes) { ss << hex << (uppercase ? std::uppercase : std::nouppercase) << setfill('0'); for (size_t i = 0; i < length; ++i) { ss << setw(2) << static_cast(bytes[i]); } } return ss.str(); } void each_line(string const& s, function callback) { string line; istringstream in(s); while (getline(in, line)) { // Handle Windows CR in the string. if (line.size() && line.back() == '\r') { line.pop_back(); } if (!callback(line)) { break; } } } string si_string(uint64_t size) { static char prefixes[] = { 'K', 'M', 'G', 'T', 'P', 'E' }; if (size < 1024) { return to_string(size) + " bytes"; } unsigned int exp = floor(log2(size) / 10.0); double converted = round(100.0 * (size / pow(1024.0, exp))) / 100.0; // Check to see if rounding up gets us to 1024; if so, move to the next unit if (fabs(converted - 1024.0) < numeric_limits::epsilon()) { converted = 1.00; ++exp; } // If we exceed the SI prefix (we shouldn't, but just in case), just return the bytes if (exp - 1 >= sizeof(prefixes)) { return to_string(size) + " bytes"; } ostringstream ss; ss << fixed << setprecision(2) << converted << " " << prefixes[exp - 1] << "iB"; return ss.str(); } string percentage(uint64_t used, uint64_t total) { if (total == 0 || used >= total) { return "100%"; } if (used == 0) { return "0%"; } double converted = round(10000.0 * (used / static_cast(total))) / 100.0; // Check to see if we would round up to 100%; if so, keep it at 99.99% if (fabs(converted - 100.0) < numeric_limits::epsilon()) { converted = 99.99; } ostringstream ss; ss << fixed << setprecision(2) << converted << "%"; return ss.str(); } string frequency(int64_t freq) { static char prefixes[] = { 'k', 'M', 'G', 'T' }; if (freq < 1000) { return to_string(freq) + " Hz"; } unsigned int exp = floor(log10(freq) / 3.0); double converted = round(100.0 * (freq / pow(1000.0, exp))) / 100.0; // Check to see if rounding up gets us to 1000; if so, move to the next unit if (fabs(converted - 1000.0) < numeric_limits::epsilon()) { converted = 1.00; ++exp; } // If we exceed the SI prefix (we shouldn't, but just in case), just return the speed in Hz if (exp - 1 >= sizeof(prefixes)) { return to_string(freq) + " Hz"; } ostringstream ss; ss << fixed << setprecision(2) << converted << " " << prefixes[exp - 1] << "Hz"; return ss.str(); } bool needs_quotation(string const& str) { // Empty strings should be quoted if (str.empty()) { return true; } // Taken from http://yaml.org/type/bool.html. // The string would be interpreted as a boolean, so quote it. static boost::regex yaml_bool("y|Y|yes|Yes|YES|n|N|no|No|NO|true|True|TRUE|false|False|FALSE|on|On|ON|off|Off|OFF"); if (boost::regex_match(str, yaml_bool)) { return true; } // A string starting with the ':' special character interferes with parsing. // Other string patterns containing ':' can be unexpectedly parsed as sexagesimal. // To be safe quote all strings that contain ':' characters. if (str.find(':') != string::npos) { return true; } // Poor man's check for a numerical string or list of numbers // May start with - or + // May contain one . and one or more , // All other characters should be digits // Note: Ruby YAML interprets 1,2,3 as a number, but not 1.2.3. // It doesn't appear to honor locales when parsing YAML. bool has_dot = false; for (size_t i = 0; i < str.size(); ++i) { char c = str[i]; if (i == 0 && (c == '+' || c == '-')) { continue; } if (c == ',') { continue; } if (c == '.') { if (has_dot) { return false; } has_dot = true; continue; } if (!isdigit(c)) { return false; } } // Numerical strings should be quoted return true; } boost::optional maybe_stoi(string const& str) { try { return stoi(str); } catch (invalid_argument&) { return boost::optional(); } } }} // namespace facter::util facter-3.14.12/lib/src/util/windows/0000755005276200011600000000000013702047635017031 5ustar jenkinsjenkinsfacter-3.14.12/lib/src/util/windows/wsa.cc0000644005276200011600000000405113702047406020126 0ustar jenkinsjenkins#include #include #include #include #include #include // Mark string for translation (alias for leatherman::locale::format) using leatherman::locale::_; using namespace std; namespace facter { namespace util { namespace windows { wsa_exception::wsa_exception(string const& message) : runtime_error(message) { } string format_err(string const& s, int err) { return str(boost::format("%1% (%2%)") % s % boost::io::group(hex, showbase, err)); } wsa::wsa() { LOG_DEBUG("initializing Winsock"); WSADATA wsaData; auto wVersionRequested = MAKEWORD(2, 2); auto err = WSAStartup(wVersionRequested, &wsaData); if (err != 0) { throw wsa_exception(format_err(_("WSAStartup failed with error"), err)); } if (LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2) { throw wsa_exception(_("could not find a usable version of Winsock.dll")); } } wsa::~wsa() { WSACleanup(); } string wsa::saddress_to_string(SOCKET_ADDRESS const& addr) const { if (!addr.lpSockaddr) { return {}; } DWORD size = INET6_ADDRSTRLEN+1; wchar_t buffer[INET6_ADDRSTRLEN+1]; if (0 != WSAAddressToStringW(addr.lpSockaddr, addr.iSockaddrLength, NULL, buffer, &size)) { throw wsa_exception(format_err(_("address to string translation failed"), WSAGetLastError())); } return boost::nowide::narrow(buffer); } void wsa::string_fill_sockaddr(sockaddr *sock, std::string const& addr, int size) const { auto addrW = boost::nowide::widen(addr); if (0 != WSAStringToAddressW(&addrW[0], sock->sa_family, NULL, sock, &size)) { throw wsa_exception(format_err(_("string to address translation failed"), WSAGetLastError())); } } }}} // namespace facter::util::windows facter-3.14.12/lib/src/util/yaml.cc0000644005276200011600000000506113702047406016606 0ustar jenkinsjenkins#include #include #include #include #include #include #include using namespace std; using namespace YAML; using namespace facter::facts; namespace facter { namespace util { namespace yaml { void add_value( string const& name, Node const& node, collection& facts, vector& names, array_value* array_parent, map_value* map_parent) { unique_ptr val; // For scalars, code the value into a specific value type if (node.IsScalar()) { bool bool_val; int64_t int_val; double double_val; // If the node tag is "!", it was a quoted scalar and should be treated as a string if (node.Tag() != "!") { if (convert::decode(node, bool_val)) { val = make_value(bool_val); } else if (convert::decode(node, int_val)) { val = make_value(int_val); } else if (convert::decode(node, double_val)) { val = make_value(double_val); } } if (!val) { val = make_value(node.as()); } } else if (node.IsSequence()) { // For arrays, convert to a array value auto array = make_value(); for (auto const& child : node) { add_value({}, child, facts, names, array.get()); } val = move(array); } else if (node.IsMap()) { // For maps, convert to a map value auto map = make_value(); for (auto const& child : node) { add_value(child.first.as(), child.second, facts, names, nullptr, map.get()); } val = move(map); } else if (!node.IsNull()) { // Ignore nodes we don't understand return; } // Put the value in the array, map, or directly as a top-level fact if (array_parent) { array_parent->add(move(val)); } else if (map_parent) { map_parent->add(string(name), move(val)); } else { facts.add_external(boost::to_lower_copy(name), move(val)); names.push_back(boost::to_lower_copy(name)); } } }}} facter-3.14.12/lib/tasks/0000755005276200011600000000000013702047635014720 5ustar jenkinsjenkinsfacter-3.14.12/lib/tasks/spec.rake0000644005276200011600000000111413702047406016507 0ustar jenkinsjenkins['rubygems', 'rspec', 'rspec/core/rake_task', 'rcov',].each do |lib| begin require lib rescue LoadError end end if defined?(RSpec::Core::RakeTask) desc "Run all specs" RSpec::Core::RakeTask.new do |t| t.pattern ='spec/{unit,integration}/**/*_spec.rb' t.fail_on_error = true end RSpec::Core::RakeTask.new('spec:rcov') do |t| t.pattern ='spec/{unit,integration}/**/*_spec.rb' t.fail_on_error = true if defined?(Rcov) t.rcov = true t.rcov_opts = ['--exclude', 'spec/*,test/*,results/*,/usr/lib/*,/usr/local/lib/*,gems/*'] end end endfacter-3.14.12/lib/tests/0000755005276200011600000000000013702047635014735 5ustar jenkinsjenkinsfacter-3.14.12/lib/tests/CMakeLists.txt0000644005276200011600000001144313702047406017474 0ustar jenkinsjenkinscmake_minimum_required(VERSION 3.2.2) find_package(Ruby 1.9) # Set the common (platform-independent) sources set(LIBFACTER_TESTS_COMMON_SOURCES "facts/array_value.cc" "facts/boolean_value.cc" "facts/double_value.cc" "facts/external/json_resolver.cc" "facts/external/text_resolver.cc" "facts/external/yaml_resolver.cc" "facts/collection.cc" "facts/external_resolvers_factory.cc" "facts/integer_value.cc" "facts/map_value.cc" "facts/resolvers/augeas_resolver.cc" "facts/resolvers/disk_resolver.cc" "facts/resolvers/dmi_resolver.cc" "facts/resolvers/filesystem_resolver.cc" "facts/resolvers/identity_resolver.cc" "facts/resolvers/kernel_resolver.cc" "facts/resolvers/ldom_resolver.cc" "facts/resolvers/memory_resolver.cc" "facts/resolvers/networking_resolver.cc" "facts/resolvers/operating_system_resolver.cc" "facts/resolvers/processor_resolver.cc" "facts/resolvers/ruby_resolver.cc" "facts/resolvers/ssh_resolver.cc" "facts/resolvers/system_profiler_resolver.cc" "facts/resolvers/timezone_resolver.cc" "facts/resolvers/uptime_resolver.cc" "facts/resolvers/virtualization_resolver.cc" "facts/resolvers/xen_resolver.cc" "facts/resolvers/zfs_resolver.cc" "facts/resolvers/zone_resolver.cc" "facts/resolvers/zpool_resolver.cc" "facts/schema.cc" "facts/cache.cc" "facts/string_value.cc" "logging/logging.cc" "log_capture.cc" "main.cc" "mock_server.cc" "util/string.cc" "fixtures.cc" "collection_fixture.cc" "cwrapper.cc" ) # Set compiler-specific flags set(CMAKE_CXX_FLAGS ${FACTER_CXX_FLAGS}) # Add the ruby tests if there's a ruby installed if (RUBY_FOUND) set(LIBFACTER_TESTS_COMMON_SOURCES ${LIBFACTER_TESTS_COMMON_SOURCES} "ruby/ruby.cc" "ruby/ruby_dirfacts.cc" "ruby/ruby_helper.cc") if (WIN32) set(LIBFACTER_TESTS_COMMON_SOURCES ${LIBFACTER_TESTS_COMMON_SOURCES} "ruby/windows/ruby.cc") endif() endif() # Set the POSIX sources if on a POSIX platform if (UNIX) set(LIBFACTER_TESTS_CATEGORY_SOURCES "facts/posix/collection.cc" "facts/posix/external_resolvers_factory.cc" "facts/posix/uptime_resolver.cc" "facts/external/posix/execution_resolver.cc" "util/posix/scoped_addrinfo.cc" "util/posix/scoped_descriptor.cc" ) set(POSIX_TESTS_LIBRARIES ${POSIX_LIBRARIES}) endif() set(LIBFACTER_TESTS_PLATFORM_LIBRARIES ${LIBFACTER_PLATFORM_LIBRARIES} ) if (WIN32) list(APPEND LIBFACTER_TESTS_PLATFORM_LIBRARIES Mswsock) set(LIBFACTER_TESTS_CATEGORY_SOURCES "facts/windows/collection.cc" "facts/windows/external_resolvers_factory.cc" "facts/windows/networking_resolver.cc" "facts/windows/operating_system_resolver.cc" "facts/external/windows/execution_resolver.cc" "facts/external/windows/powershell_resolver.cc" ) endif() if (OPENSSL_FOUND) set(LIBFACTER_TESTS_CATEGORY_SOURCES ${LIBFACTER_TESTS_CATEGORY_SOURCES} "util/scoped_bio.cc") endif() # Set the platform-specific sources if ("${CMAKE_SYSTEM_NAME}" MATCHES "Darwin") set(LIBFACTER_TESTS_PLATFORM_SOURCES "util/bsd/scoped_ifaddrs.cc" ) elseif ("${CMAKE_SYSTEM_NAME}" MATCHES "Linux") set(LIBFACTER_TESTS_PLATFORM_SOURCES "facts/linux/dmi_resolver.cc" "facts/linux/filesystem_resolver.cc" "facts/linux/virtualization_resolver.cc" "facts/linux/processor_fixture.cc" "facts/linux/processor_resolver.cc" "util/bsd/scoped_ifaddrs.cc" ) endif() if (JRUBY_SUPPORT) include_directories(${JNI_INCLUDE_DIRS}) set(LIBFACTER_TESTS_COMMON_SOURCES ${LIBFACTER_TESTS_COMMON_SOURCES} java/facter.cc) endif() include_directories( ../inc ${Boost_INCLUDE_DIRS} ${OPENSSL_INCLUDE_DIRS} ${YAMLCPP_INCLUDE_DIRS} ${LEATHERMAN_CATCH_INCLUDE} ${CPPHOCON_INCLUDE_DIRS} ) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-deprecated-declarations") if (WIN32) # On Windows with GCC 5.2, Boost.System emits warnings that aren't correctly # suppressed by pragmas. Explicitly skip them. set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-unused-variable") endif() add_executable(libfacter_test $ ${LIBFACTER_TESTS_COMMON_SOURCES} ${LIBFACTER_TESTS_PLATFORM_SOURCES} ${LIBFACTER_TESTS_CATEGORY_SOURCES}) target_link_libraries(libfacter_test ${LIBS} ${LIBFACTER_TESTS_PLATFORM_LIBRARIES}) if (${CMAKE_SYSTEM_NAME} MATCHES "Darwin" AND BOOST_STATIC AND LEATHERMAN_USE_LOCALES) target_link_libraries(libfacter_test iconv) endif() target_compile_definitions(libfacter_test PRIVATE "-Dlibfacter_EXPORTS") # Generate a file containing the path to the fixtures configure_file ( "fixtures.hpp.in" "${CMAKE_CURRENT_LIST_DIR}/fixtures.hpp" ) facter-3.14.12/lib/tests/collection_fixture.cc0000644005276200011600000000062713702047406021146 0ustar jenkinsjenkins#include "collection_fixture.hpp" namespace facter { namespace testing { using namespace std; collection_fixture::collection_fixture(set const& blocklist, unordered_map const& ttls) : collection(blocklist, ttls) { } vector collection_fixture::get_external_fact_directories() const { return {}; } }} // namespace facter::testing facter-3.14.12/lib/tests/collection_fixture.hpp0000644005276200011600000000106713702047406021347 0ustar jenkinsjenkins#pragma once #include #include #include namespace facter { namespace testing { class collection_fixture : public facter::facts::collection { public: collection_fixture(std::set const& blocklist = std::set(), std::unordered_map const& ttls = std::unordered_map{}); protected: virtual std::vector get_external_fact_directories() const override; }; }} // namespace facter::testing facter-3.14.12/lib/tests/cwrapper.cc0000644005276200011600000000122413702047406017062 0ustar jenkinsjenkins#include #include SCENARIO("using the C wrapper function to collect default facts") { GIVEN("a get_default_facts invocation") { char *result {nullptr}; THEN("no error should be thrown") { REQUIRE_NOTHROW(get_default_facts(&result)); } THEN("the function execution should succeed") { REQUIRE(get_default_facts(&result) == 0); } THEN("the function stores the collected facts and sets the pointer arg") { REQUIRE(result == nullptr); get_default_facts(&result); REQUIRE_FALSE(result == nullptr); } } } facter-3.14.12/lib/tests/facts/0000755005276200011600000000000013702047635016035 5ustar jenkinsjenkinsfacter-3.14.12/lib/tests/facts/array_value.cc0000644005276200011600000001242513702047406020656 0ustar jenkinsjenkins#include #include #include #include #include #include using namespace std; using namespace facter::facts; using namespace rapidjson; using namespace YAML; SCENARIO("using an array fact value") { array_value value; REQUIRE(value.empty()); GIVEN("a null value to add") { value.add(nullptr); THEN("it should still be empty") { REQUIRE(value.empty()); } } GIVEN("an out of range index") { THEN("get() raises out_of_range") { REQUIRE_THROWS_AS(value.get(0), std::out_of_range&); } THEN("operator[] returns nullptr") { REQUIRE_FALSE(value[42]); } } GIVEN("a string value to add") { value.add(make_value("hello")); THEN("it should contain the string value") { REQUIRE_FALSE(value.empty()); REQUIRE(value.size() == 1u); REQUIRE(value.get(0)); REQUIRE(value.get(0)->value() == "hello"); } } GIVEN("an integer value to add") { value.add(make_value(123)); THEN("it should contain the string value") { REQUIRE_FALSE(value.empty()); REQUIRE(value.size() == 1u); REQUIRE(value.get(0)); REQUIRE(value.get(0)->value() == 123); } } GIVEN("multiple values to add") { auto subarray = make_value(); subarray->add(make_value("element")); value.add(make_value("1")); value.add(make_value(2)); value.add(move(subarray)); THEN("it should contain the values in order they were added") { REQUIRE(value.size() == 3u); auto string_val = value.get(0); REQUIRE(string_val); REQUIRE(string_val->value() == "1"); auto int_val = value.get(1); REQUIRE(int_val); REQUIRE(int_val->value() == 2); auto subarray = value.get(2); REQUIRE(subarray); REQUIRE(subarray->size() == 1u); string_val = subarray->get(0); REQUIRE(string_val); REQUIRE(string_val->value() == "element"); } THEN("each is enumerated in order") { size_t index = 0u; value.each([&](struct value const* val) { if (index == 0u) { auto string_val = dynamic_cast(val); REQUIRE(string_val); REQUIRE(string_val->value() == "1"); } else if (index == 1u) { auto int_val = dynamic_cast(val); REQUIRE(int_val); REQUIRE(int_val->value() == 2); } else if (index == 2u) { auto subarray = dynamic_cast(val); REQUIRE(subarray); REQUIRE(subarray->size() == 1u); auto string_val = subarray->get(0); REQUIRE(string_val); REQUIRE(string_val->value() == "element"); } else { FAIL("should not be reached"); } ++index; return true; }); REQUIRE(index == value.size()); } WHEN("serialized to JSON") { THEN("it should contain the same values") { json_value json; json_allocator allocator; value.to_json(allocator, json); REQUIRE(json.IsArray()); REQUIRE(json.Size() == 3); REQUIRE(json[0u].IsString()); REQUIRE(string(json[0u].GetString()) == "1"); REQUIRE(json[1u].IsNumber()); REQUIRE(json[1u].GetInt64() == 2ll); REQUIRE(json[2u].IsArray()); REQUIRE(json[2u].Size() == 1); REQUIRE(json[2u][0u].IsString()); REQUIRE(string(json[2u][0u].GetString()) == "element"); } } WHEN("serialized to text") { THEN("it should contain the same values") { ostringstream stream; value.write(stream); REQUIRE(stream.str() == "[\n \"1\",\n 2,\n [\n \"element\"\n ]\n]"); } } WHEN("serialized to YAML") { THEN("it should contain the same values") { Emitter emitter; value.write(emitter); REQUIRE(string(emitter.c_str()) == "- \"1\"\n- 2\n-\n - element"); } } } GIVEN("each with a callback that returns false") { THEN("it should stop enumerating") { value.add(make_value(1)); value.add(make_value(2)); value.add(make_value(3)); size_t index = 0u; value.each([&](struct value const* val) { ++index; return false; }); REQUIRE(index == 1u); } } } facter-3.14.12/lib/tests/facts/boolean_value.cc0000644005276200011600000000412113702047406021151 0ustar jenkinsjenkins#include #include #include #include #include using namespace std; using namespace facter::facts; using namespace rapidjson; using namespace YAML; SCENARIO("using a boolean fact value") { GIVEN("true to the constructor") { boolean_value value(true); REQUIRE(value.value()); WHEN("serialized to JSON") { THEN("it should serialize as true") { json_value json; json_allocator allocator; value.to_json(allocator, json); REQUIRE(json.IsBool()); REQUIRE(json.GetBool()); } } WHEN("serialized to YAML") { THEN("it should serialize as true") { Emitter emitter; value.write(emitter); REQUIRE(string(emitter.c_str()) == "true"); } } WHEN("serialized to text") { THEN("it should serialize to text as true") { ostringstream stream; value.write(stream); REQUIRE(stream.str() == "true"); } } } GIVEN("false to the constructor") { boolean_value value(false); REQUIRE_FALSE(value.value()); WHEN("serialized to JSON") { THEN("it should serialize as false") { json_value json; json_allocator allocator; value.to_json(allocator, json); REQUIRE(json.IsBool()); REQUIRE_FALSE(json.GetBool()); } } WHEN("serialized to YAML") { THEN("it should serialize as false") { Emitter emitter; value.write(emitter); REQUIRE(string(emitter.c_str()) == "false"); } } WHEN("serialized to text") { THEN("it should serialize to text as false") { ostringstream stream; value.write(stream); REQUIRE(stream.str() == "false"); } } } } facter-3.14.12/lib/tests/facts/cache.cc0000644005276200011600000000643013702047406017406 0ustar jenkinsjenkins#include #include "../fixtures.hpp" #include #include #include using namespace std; using namespace facter::testing; using namespace facter::facts; namespace boost_file = boost::filesystem; struct simple_resolver : facter::facts::resolver { simple_resolver() : resolver("test", { "foo" }) { } virtual void resolve(collection& facts) override { facts.add("foo", make_value("bar")); } bool is_blockable() const override { return true; } }; SCENARIO("refreshing cache") { boost_file::path cache_dir(LIBFACTER_TESTS_DIRECTORY + string("/fixtures/cache")); GIVEN("a resolver that needs to be cached") { collection_fixture facts; auto test_res = make_shared(); boost_file::create_directories(cache_dir); THEN("new JSON files should be written") { auto cache_file = (cache_dir / "test").string(); REQUIRE_FALSE(leatherman::file_util::file_readable(cache_file)); cache::refresh_cache(test_res, cache_file, facts); REQUIRE(leatherman::file_util::file_readable(cache_file)); string contents; load_fixture("cache/test", contents); REQUIRE(contents.find("foo") != string::npos); } } // Clean up directory boost_file::remove_all(cache_dir); } SCENARIO("loading facts from cache") { boost_file::path cache_dir(LIBFACTER_TESTS_DIRECTORY + string("/fixtures/cache")); GIVEN("an existing cache directory with cached fact") { collection_fixture facts; auto test_res = make_shared(); boost_file::create_directories(cache_dir); auto cache_file = cache_dir / "test"; leatherman::file_util::atomic_write_to_file("{ \"foo\" : \"bar\" }", cache_file.string()); THEN("facts should be loaded from the cache") { cache::load_facts_from_cache(cache_file, test_res, facts); REQUIRE(facts.get_resolved("foo")); } } // Clean up directory boost_file::remove_all(cache_dir); } SCENARIO("cleaning the cache") { boost_file::path cache_dir(LIBFACTER_TESTS_DIRECTORY + string("/fixtures/cache")); GIVEN("an existing cache directory with a fact that should no longer be cached") { boost_file::create_directories(cache_dir); // unused cache file auto unused_cache_file = (cache_dir / "unused").string(); leatherman::file_util::atomic_write_to_file("{ \"foo\" : \"bar\" }", unused_cache_file); // used cached file auto used_cache_file = (cache_dir / "test").string(); leatherman::file_util::atomic_write_to_file("{ \"foo\" : \"bar\" }", used_cache_file); THEN("unused cache file should be deleted") { // cache "test", but not "unused" cache::clean_cache(unordered_map({ make_pair("test", 600) }), cache_dir.string()); REQUIRE_FALSE(leatherman::file_util::file_readable(unused_cache_file)); REQUIRE(leatherman::file_util::file_readable(used_cache_file)); } } boost_file::remove_all(cache_dir); } facter-3.14.12/lib/tests/facts/collection.cc0000644005276200011600000005412713702047406020504 0ustar jenkinsjenkins#include #include #include #include #include #include #include #include "../fixtures.hpp" #include using namespace std; using namespace facter::facts; using namespace leatherman::util; using namespace facter::testing; struct simple_resolver : facter::facts::resolver { simple_resolver() : resolver("test", { "foo" }) { } virtual void resolve(collection& facts) override { facts.add("foo", make_value("bar")); } bool is_blockable() const override { return true; } }; struct unblockable_resolver : facter::facts::resolver { unblockable_resolver() : resolver("unblockable", { "foo" }) { } virtual void resolve(collection& facts) override { facts.add("foo", make_value("bar")); } bool is_blockable() const override { return false; } }; struct multi_resolver : facter::facts::resolver { multi_resolver() : resolver("test", { "foo", "bar" }) { } virtual void resolve(collection& facts) override { facts.add("foo", make_value("bar")); facts.add("bar", make_value("foo")); } bool is_blockable() const override { return true; } }; struct temp_variable { temp_variable(string&& name, string const& value) : _name(move(name)) { environment::set(_name, value); } ~temp_variable() { environment::clear(_name); } string _name; }; SCENARIO("using the fact collection") { collection_fixture facts; REQUIRE(facts.size() == 0u); REQUIRE(facts.empty()); GIVEN("default facts") { facts.add_default_facts(true); THEN("facts should resolve") { REQUIRE(facts.size() > 0u); REQUIRE_FALSE(facts.empty()); } } GIVEN("a hidden fact and a revealed fact") { facts.add("foo", make_value("bar")); facts.add("hidden_foo", make_value("hidden_bar", true)); THEN("they should be in the collection") { REQUIRE(facts.size() == 2u); REQUIRE_FALSE(facts.empty()); auto fact = facts.get("foo"); REQUIRE(fact); REQUIRE(fact->value() == "bar"); fact = dynamic_cast(facts["foo"]); REQUIRE(fact); REQUIRE(fact->value() == "bar"); auto hidden_fact = facts.get("hidden_foo"); REQUIRE(hidden_fact); REQUIRE(hidden_fact->value() == "hidden_bar"); hidden_fact = dynamic_cast(facts["hidden_foo"]); REQUIRE(hidden_fact); REQUIRE(hidden_fact->value() == "hidden_bar"); } WHEN("writing default facts") { THEN("it should serialize the revealed fact to JSON") { ostringstream ss; facts.write(ss, format::json); REQUIRE(ss.str() == "{\n \"foo\": \"bar\"\n}"); } THEN("it should serialize the revealed fact to YAML") { ostringstream ss; facts.write(ss, format::yaml); REQUIRE(ss.str() == "foo: bar"); } THEN("it should serialize the revealed fact to text") { ostringstream ss; facts.write(ss, format::hash); REQUIRE(ss.str() == "foo => bar"); } } WHEN("writing all (hidden) facts") { THEN("it should serialize both facts to JSON") { ostringstream ss; facts.write(ss, format::json, set{}, true, false); REQUIRE(ss.str() == "{\n \"foo\": \"bar\",\n \"hidden_foo\": \"hidden_bar\"\n}"); } THEN("it should serialize both facts to YAML") { ostringstream ss; facts.write(ss, format::yaml, set{}, true, false); REQUIRE(ss.str() == "foo: bar\nhidden_foo: hidden_bar"); } THEN("it should serialize both facts to text") { ostringstream ss; facts.write(ss, format::hash, set{}, true, false); REQUIRE(ss.str() == "foo => bar\nhidden_foo => hidden_bar"); } } WHEN("querying facts") { THEN("it should serialize both facts to JSON") { ostringstream ss; facts.write(ss, format::json, {"foo", "hidden_foo"}); REQUIRE(ss.str() == "{\n \"foo\": \"bar\",\n \"hidden_foo\": \"hidden_bar\"\n}"); } THEN("it should serialize both facts to YAML") { ostringstream ss; facts.write(ss, format::yaml, {"foo", "hidden_foo"}); REQUIRE(ss.str() == "foo: bar\nhidden_foo: hidden_bar"); } THEN("it should serialize both facts to text") { ostringstream ss; facts.write(ss, format::hash, {"foo", "hidden_foo"}); REQUIRE(ss.str() == "foo => bar\nhidden_foo => hidden_bar"); } } WHEN("querying hidden facts") { THEN("it should serialize both facts to JSON") { ostringstream ss; facts.write(ss, format::json, {"foo", "hidden_foo"}, true, false); REQUIRE(ss.str() == "{\n \"foo\": \"bar\",\n \"hidden_foo\": \"hidden_bar\"\n}"); } THEN("it should serialize both facts to YAML") { ostringstream ss; facts.write(ss, format::yaml, {"foo", "hidden_foo"}, true, false); REQUIRE(ss.str() == "foo: bar\nhidden_foo: hidden_bar"); } THEN("it should serialize both facts to text") { ostringstream ss; facts.write(ss, format::hash, {"foo", "hidden_foo"}, true, false); REQUIRE(ss.str() == "foo => bar\nhidden_foo => hidden_bar"); } } } GIVEN("a resolver that adds a single fact") { facts.add(make_shared()); THEN("it should resolve facts into the collection") { REQUIRE(facts.size() == 1u); REQUIRE_FALSE(facts.empty()); auto fact = facts.get("foo"); REQUIRE(fact); REQUIRE(fact->value() == "bar"); fact = dynamic_cast(facts["foo"]); REQUIRE(fact); REQUIRE(fact->value() == "bar"); } WHEN("serializing to JSON") { THEN("it should contain the same values") { ostringstream ss; facts.write(ss, format::json); REQUIRE(ss.str() == "{\n \"foo\": \"bar\"\n}"); } } WHEN("serializing to YAML") { THEN("it should contain the same values") { ostringstream ss; facts.write(ss, format::yaml); REQUIRE(ss.str() == "foo: bar"); } } WHEN("serializing to text") { GIVEN("only a single query") { THEN("it should output only the value") { ostringstream ss; facts.write(ss, format::hash, {"foo"}); REQUIRE(ss.str() == "bar"); } } GIVEN("no queries") { THEN("it should contain the same values") { ostringstream ss; facts.write(ss, format::hash); REQUIRE(ss.str() == "foo => bar"); } } } } GIVEN("a resolver that adds multiple facts") { facts.add(make_shared()); THEN("it should enumerate the facts in order") { int index = 0; facts.each([&](string const &name, value const *val) { auto string_val = dynamic_cast(val); REQUIRE(string_val); if (index == 0) { REQUIRE(name == "bar"); REQUIRE(string_val->value() == "foo"); } else if (index == 1) { REQUIRE(name == "foo"); REQUIRE(string_val->value() == "bar"); } else { FAIL("should not be reached"); } ++index; return true; }); } WHEN("serializing to JSON") { THEN("it should contain the same values") { ostringstream ss; facts.write(ss, format::json); REQUIRE(ss.str() == "{\n \"bar\": \"foo\",\n \"foo\": \"bar\"\n}"); } } WHEN("serializing to YAML") { THEN("it should contain the same values") { ostringstream ss; facts.write(ss, format::yaml); REQUIRE(ss.str() == "bar: foo\nfoo: bar"); } } WHEN("serializing to text") { THEN("it should contain the same values") { ostringstream ss; facts.write(ss, format::hash); REQUIRE(ss.str() == "bar => foo\nfoo => bar"); } } } GIVEN("external facts paths to search") { facts.add_external_facts({ LIBFACTER_TESTS_DIRECTORY "/fixtures/facts/external/yaml", LIBFACTER_TESTS_DIRECTORY "/fixtures/facts/external/json", LIBFACTER_TESTS_DIRECTORY "/fixtures/facts/external/text", }); REQUIRE_FALSE(facts.empty()); REQUIRE(facts.size() == 20u); WHEN("YAML files are present") { THEN("facts should be added") { REQUIRE(facts.get("yaml_fact1")); REQUIRE(facts.get("yaml_fact2")); REQUIRE(facts.get("yaml_fact3")); REQUIRE(facts.get("yaml_fact4")); REQUIRE(facts.get("yaml_fact5")); REQUIRE(facts.get("yaml_fact6")); REQUIRE(facts.get("yaml_fact7")); REQUIRE(facts.get("not_bool")); REQUIRE(facts.get("not_int")); REQUIRE(facts.get("not_double")); } } WHEN("JSON files are present") { THEN("facts should be added") { REQUIRE(facts.get("json_fact1")); REQUIRE(facts.get("json_fact2")); REQUIRE(facts.get("json_fact3")); REQUIRE(facts.get("json_fact4")); REQUIRE(facts.get("json_fact5")); REQUIRE(facts.get("json_fact6")); REQUIRE(facts.get("json_fact7")); } } WHEN("text files are present") { THEN("facts should be added") { REQUIRE(facts.get("txt_fact1")); REQUIRE(facts.get("txt_fact2")); REQUIRE_FALSE(facts.get("txt_fact3")); REQUIRE(facts.get("txt_fact4")); } } } GIVEN("structured fact data") { auto map = make_value(); map->add("string", make_value("hello")); map->add("integer", make_value(5)); map->add("double", make_value(0.3)); map->add("boolean", make_value(true)); auto submap = make_value(); submap->add("foo", make_value("bar")); map->add("submap", move(submap)); submap = make_value(); submap->add("jam", make_value("cakes")); map->add("name.with.dots", move(submap)); auto array = make_value(); array->add(make_value("foo")); array->add(make_value(10)); array->add(make_value(2.3)); array->add(make_value(false)); submap = make_value(); submap->add("bar", make_value("baz")); array->add(move(submap)); map->add("array", move(array)); facts.add("map", move(map)); facts.add("string", make_value("world")); WHEN("queried with a matching top level name") { THEN("a value should be returned") { auto mvalue = facts.query("map"); REQUIRE(mvalue); REQUIRE(mvalue->size() == 7u); } } WHEN("queried with a non-matching top level name") { THEN("it should return null") { REQUIRE_FALSE(facts.query("does not exist")); } } WHEN("querying for a sub element of a type that is not a map") { THEN("it should return null") { REQUIRE_FALSE(facts.query("string.foo")); } } WHEN("queried with for a sub element") { THEN("a value should be returned") { auto svalue = facts.query("map.string"); REQUIRE(svalue); REQUIRE(svalue->value() == "hello"); auto ivalue = facts.query("map.integer"); REQUIRE(ivalue); REQUIRE(ivalue->value() == 5); auto dvalue = facts.query("map.double"); REQUIRE(dvalue); REQUIRE(dvalue->value() == Approx(0.3)); auto bvalue = facts.query("map.boolean"); REQUIRE(bvalue); REQUIRE(bvalue->value()); auto mvalue = facts.query("map.submap"); REQUIRE(mvalue); REQUIRE(mvalue->size() == 1u); } } WHEN("querying along a path of map values") { THEN("a value should be returned") { auto svalue = facts.query("map.submap.foo"); REQUIRE(svalue); REQUIRE(svalue->value() == "bar"); } } WHEN("querying into an array with an in-bounds index") { THEN("a value should be returned") { auto avalue = facts.query("map.array"); REQUIRE(avalue); REQUIRE(avalue->size() == 5u); for (size_t i = 0; i < avalue->size(); ++i) { REQUIRE(facts.query("map.array." + to_string(i))); } } } WHEN("querying into an array with a non-numeric index") { THEN("it should return null") { REQUIRE_FALSE(facts.query("map.array.foo")); } } WHEN("uerying into an array with an out-of-bounds index") { THEN("it should return null") { REQUIRE_FALSE(facts.query("map.array.5")); } } WHEN("querying into an element inside of an array") { THEN("it should return a value") { auto svalue = facts.query("map.array.4.bar"); REQUIRE(svalue); REQUIRE(svalue->value() == "baz"); } } WHEN("a fact name contains dots") { THEN("it not return a value unless quoted") { REQUIRE_FALSE(facts.query("map.name.with.dots")); } THEN("it should return a value when quoted") { auto svalue = facts.query("map.\"name.with.dots\".jam"); REQUIRE(svalue); REQUIRE(svalue->value() == "cakes"); } } } GIVEN("a fact from an environment variable") { auto var = temp_variable("FACTER_Foo", "bar"); bool added = false; facts.add_environment_facts([&](string const& name) { added = name == "foo"; }); REQUIRE(added); THEN("the fact should be present in the collection") { REQUIRE(facts.size() == 1u); auto value = facts.get("foo"); REQUIRE(value); REQUIRE(value->value() == "bar"); } } GIVEN("a fact from an environment with the same name as a built-in fact") { facts.add_default_facts(true); auto var = temp_variable("FACTER_KERNEL", "overridden"); bool added = false; facts.add_environment_facts([&](string const& name) { added = name == "kernel"; }); REQUIRE(added); THEN("it should override the built-in fact's value") { auto value = facts.get("kernel"); REQUIRE(value); REQUIRE(value->value() == "overridden"); } } GIVEN("two external fact directories to search") { facts.add_external_facts({ LIBFACTER_TESTS_DIRECTORY "/fixtures/facts/external/ordering/foo", LIBFACTER_TESTS_DIRECTORY "/fixtures/facts/external/ordering/bar" }); THEN("it should have the fact value from the last file loaded") { REQUIRE(facts.size() == 1u); REQUIRE(facts.get("foo")); REQUIRE(facts.get("foo")->value() == "set in bar/foo.yaml"); } facts.clear(); facts.add_external_facts({ LIBFACTER_TESTS_DIRECTORY "/fixtures/facts/external/ordering/bar", LIBFACTER_TESTS_DIRECTORY "/fixtures/facts/external/ordering/foo" }); THEN("it should have the fact value from the last file loaded") { REQUIRE(facts.size() == 1u); REQUIRE(facts.get("foo")); REQUIRE(facts.get("foo")->value() == "set in foo/foo.yaml"); } } } class collection_override : public collection { protected: virtual vector get_external_fact_directories() const override { return {LIBFACTER_TESTS_DIRECTORY "/fixtures/facts/external/ordering/foo"}; } }; SCENARIO("using the fact collection with a default external fact path") { collection_override facts; REQUIRE(facts.size() == 0u); REQUIRE(facts.empty()); GIVEN("a specified external fact directory with an overriding fact to search") { facts.add_external_facts({ LIBFACTER_TESTS_DIRECTORY "/fixtures/facts/external/ordering/bar" }); THEN("it should have the fact value from the last file loaded") { REQUIRE(facts.size() == 1u); REQUIRE(facts.get("foo")); REQUIRE(facts.get("foo")->value() == "set in bar/foo.yaml"); } } GIVEN("a specified external fact directory with new facts to search") { facts.add_external_facts({ LIBFACTER_TESTS_DIRECTORY "/fixtures/facts/external/text", }); REQUIRE_FALSE(facts.empty()); REQUIRE(facts.size() == 4u); THEN("facts from both directories should be added") { REQUIRE(facts.get("foo")); REQUIRE(facts.get("txt_fact1")); REQUIRE(facts.get("txt_fact2")); REQUIRE_FALSE(facts.get("txt_fact3")); REQUIRE(facts.get("txt_fact4")); } } } SCENARIO("using the fact collection with a blocklist") { collection_fixture facts({ "test" }); REQUIRE(facts.size() == 0u); REQUIRE(facts.empty()); GIVEN("a resolver that adds a single fact") { facts.add(make_shared()); THEN("the fact should not be resolved") { REQUIRE(facts.size() == 0u); REQUIRE_FALSE(facts.get("foo")); } } GIVEN("a resolver that adds multiple facts") { facts.add(make_shared()); THEN("none of the facts should resolve") { REQUIRE(facts.size() == 0u); REQUIRE_FALSE(facts.get("foo")); REQUIRE_FALSE(facts.get("bar")); } } } SCENARIO("querying blockable and cacheable fact groups") { collection_fixture facts; REQUIRE(facts.size() == 0u); REQUIRE(facts.empty()); GIVEN("a blockable resolver that adds a single fact") { facts.add(make_shared()); THEN("resolver and its fact should be listed as blockable") { auto blockable = facts.get_blockable_fact_groups(); REQUIRE(blockable.size() == 1); REQUIRE(blockable["test"] == vector({"foo"})); } THEN("resolver and its fact should be listed as in the collection") { auto facts_present = facts.get_fact_groups(); REQUIRE(facts_present.size() == 1); REQUIRE(facts_present["test"] == vector({"foo"})); } } GIVEN("a blockable resolver that adds multiple facts") { facts.add(make_shared()); THEN("resolver and its facts should be listed as blockable") { auto blockable = facts.get_blockable_fact_groups(); REQUIRE(blockable.size() == 1); REQUIRE(blockable["test"] == vector({"foo", "bar"})); } THEN("resolver and its facts should be listed as in the collection") { auto facts_present = facts.get_fact_groups(); REQUIRE(facts_present.size() == 1); REQUIRE(facts_present["test"] == vector({"foo", "bar"})); } } GIVEN("a unblockable resolver that adds a single fact") { facts.add(make_shared()); THEN("resolver and its facts should not be listed as blockable") { auto blockable = facts.get_blockable_fact_groups(); REQUIRE(blockable.size() == 0); } THEN("resolver and its fact should be listed as in the collection") { auto facts_present = facts.get_fact_groups(); REQUIRE(facts_present.size() == 1); REQUIRE(facts_present["unblockable"] == vector({"foo"})); } } } facter-3.14.12/lib/tests/facts/double_value.cc0000644005276200011600000000215713702047406021013 0ustar jenkinsjenkins#include #include #include #include #include #include #include using namespace std; using namespace facter::facts; using namespace rapidjson; using namespace YAML; SCENARIO("using a double fact value") { double_value value(42.4242); REQUIRE(value.value() == Approx(42.4242)); WHEN("serialized to JSON") { THEN("it should have the same value") { json_value json; json_allocator allocator; value.to_json(allocator, json); REQUIRE(json.IsNumber()); REQUIRE(json.GetDouble() == Approx(42.4242)); } } WHEN("serialized to YAML") { THEN("it should have the same value") { Emitter emitter; value.write(emitter); REQUIRE(string(emitter.c_str()) == "42.4242"); } } WHEN("serialized to text") { THEN("it should have the same value") { ostringstream stream; value.write(stream); REQUIRE(stream.str() == "42.4242"); } } } facter-3.14.12/lib/tests/facts/external/0000755005276200011600000000000013702047635017657 5ustar jenkinsjenkinsfacter-3.14.12/lib/tests/facts/external/json_resolver.cc0000644005276200011600000000435113702047406023057 0ustar jenkinsjenkins#include #include #include #include #include #include #include "../../fixtures.hpp" using namespace std; using namespace facter::facts; using namespace facter::facts::external; using namespace facter::testing; SCENARIO("resolving external JSON facts") { collection_fixture facts; GIVEN("a non-existent file to resolve") { THEN("it should throw an exception") { json_resolver resolver("doesnotexist.json"); REQUIRE_THROWS_AS(resolver.resolve(facts), external_fact_exception&); } } GIVEN("invalid JSON") { THEN("it should throw an exception") { json_resolver resolver(LIBFACTER_TESTS_DIRECTORY "/fixtures/facts/external/json/invalid.json"); REQUIRE_THROWS_AS(resolver.resolve(facts), external_fact_exception&); } } GIVEN("valid JSON") { THEN("it should populate the facts") { json_resolver resolver(LIBFACTER_TESTS_DIRECTORY "/fixtures/facts/external/json/facts.json"); resolver.resolve(facts); REQUIRE_FALSE(facts.empty()); REQUIRE(facts.get("json_fact1")); REQUIRE(facts.get("json_fact1")->value() == "foo"); REQUIRE(facts.get("json_fact2")); REQUIRE(facts.get("json_fact2")->value() == 5); REQUIRE(facts.get("json_fact3")); REQUIRE(facts.get("json_fact3")->value()); REQUIRE(facts.get("json_fact4")); REQUIRE(facts.get("json_fact4")->value() == Approx(5.1)); auto array = facts.get("json_fact5"); REQUIRE(array); REQUIRE(array->size() == 3u); auto map = facts.get("json_fact6"); REQUIRE(map); REQUIRE(map->size() == 2u); REQUIRE(facts.get("json_fact7")); REQUIRE_FALSE(facts.get("JSON_fact7")); REQUIRE(facts.get("json_fact7")->value() == "bar"); } } } facter-3.14.12/lib/tests/facts/external/posix/0000755005276200011600000000000013702047635021021 5ustar jenkinsjenkinsfacter-3.14.12/lib/tests/facts/external/posix/execution_resolver.cc0000644005276200011600000000506013702047406025251 0ustar jenkinsjenkins#include #include #include #include #include #include #include "../../../fixtures.hpp" #include "../../../log_capture.hpp" using namespace std; using namespace facter::facts; using namespace facter::util; using namespace facter::facts::external; using namespace facter::logging; using namespace facter::testing; using namespace leatherman::util; SCENARIO("resolving external executable facts") { collection_fixture facts; GIVEN("an executable file") { WHEN("the execution fails") { THEN("an exception is thrown") { execution_resolver resolver(LIBFACTER_TESTS_DIRECTORY "/fixtures/facts/external/posix/execution/failed"); REQUIRE_THROWS_AS(resolver.resolve(facts), external_fact_exception&); } } WHEN("the execution succeeds") { THEN("it populates facts") { execution_resolver resolver(LIBFACTER_TESTS_DIRECTORY "/fixtures/facts/external/posix/execution/facts"); resolver.resolve(facts); REQUIRE(!facts.empty()); REQUIRE(facts.get("exe_fact1")); REQUIRE(facts.get("exe_fact1")->value() == "value1"); REQUIRE(facts.get("exe_fact2")); REQUIRE(facts.get("exe_fact2")->value() == ""); REQUIRE_FALSE(facts.get("exe_fact3")); REQUIRE(facts.get("exe_fact4")); REQUIRE_FALSE(facts.get("EXE_fact4")); REQUIRE(facts.get("exe_fact4")->value() == "value2"); } } WHEN("messages are logged to stderr") { THEN("a warning is generated") { log_capture capture(level::warning); execution_resolver resolver(LIBFACTER_TESTS_DIRECTORY "/fixtures/facts/external/posix/execution/error_message"); resolver.resolve(facts); REQUIRE(facts.size() == 1u); REQUIRE(facts.get("foo")); REQUIRE(facts.get("foo")->value() == "bar"); auto output = capture.result(); CAPTURE(output); REQUIRE(re_search(output, boost::regex("WARN puppetlabs\\.facter - external fact file \".*/error_message\" had output on stderr: error message!"))); } } } } facter-3.14.12/lib/tests/facts/external/text_resolver.cc0000644005276200011600000000266213702047406023075 0ustar jenkinsjenkins#include #include #include #include #include "../../fixtures.hpp" using namespace std; using namespace facter::facts; using namespace facter::facts::external; using namespace facter::testing; SCENARIO("resolving external text facts") { collection_fixture facts; GIVEN("a non-existent file to resolve") { THEN("it should throw an exception") { text_resolver resolver("doesnotexist.txt"); REQUIRE_THROWS_AS(resolver.resolve(facts), external_fact_exception&); } } GIVEN("a text file to resolve") { THEN("it should populate the facts") { text_resolver resolver(LIBFACTER_TESTS_DIRECTORY "/fixtures/facts/external/text/facts.txt"); resolver.resolve(facts); REQUIRE_FALSE(facts.empty()); REQUIRE(facts.get("txt_fact1")); REQUIRE(facts.get("txt_fact1")->value() == "value1"); REQUIRE(facts.get("txt_fact2")); REQUIRE(facts.get("txt_fact2")->value() == ""); REQUIRE_FALSE(facts.get("txt_fact3")); REQUIRE(facts.get("txt_fact4")); REQUIRE_FALSE(facts.get("TXT_Fact4")); REQUIRE(facts.get("txt_fact4")->value() == "value2"); } } } facter-3.14.12/lib/tests/facts/external/windows/0000755005276200011600000000000013702047635021351 5ustar jenkinsjenkinsfacter-3.14.12/lib/tests/facts/external/windows/execution_resolver.cc0000644005276200011600000000505013702047406025600 0ustar jenkinsjenkins#include #include #include #include #include #include #include "../../../fixtures.hpp" #include "../../../log_capture.hpp" using namespace std; using namespace facter::facts; using namespace facter::facts::external; using namespace facter::logging; using namespace facter::testing; using namespace leatherman::util; SCENARIO("resolving external executable facts") { collection_fixture facts; GIVEN("an executable file") { WHEN("the execution fails") { THEN("an exception is thrown") { execution_resolver resolver(LIBFACTER_TESTS_DIRECTORY "/fixtures/facts/external/windows/execution/failed.cmd");; REQUIRE_THROWS_AS(resolver.resolve(facts), external_fact_exception&); } } WHEN("the execution succeeds") { THEN("it populates facts") { execution_resolver resolver(LIBFACTER_TESTS_DIRECTORY "/fixtures/facts/external/windows/execution/facts.bat"); resolver.resolve(facts); REQUIRE(!facts.empty()); REQUIRE(facts.get("exe_fact1")); REQUIRE(facts.get("exe_fact1")->value() == "value1"); REQUIRE(facts.get("exe_fact2")); REQUIRE(facts.get("exe_fact2")->value() == ""); REQUIRE_FALSE(facts.get("exe_fact3")); REQUIRE(facts.get("exe_fact4")); REQUIRE_FALSE(facts.get("EXE_fact4")); REQUIRE(facts.get("exe_fact4")->value() == "value2"); } } WHEN("messages are logged to stderr") { THEN("a warning is generated") { log_capture capture(level::warning); execution_resolver resolver(LIBFACTER_TESTS_DIRECTORY "/fixtures/facts/external/windows/execution/error_message.bat"); resolver.resolve(facts); REQUIRE(facts.size() == 1u); REQUIRE(facts.get("foo")); REQUIRE(facts.get("foo")->value() == "bar"); auto output = capture.result(); CAPTURE(output); REQUIRE(re_search(output, boost::regex("WARN puppetlabs\\.facter - external fact file \".*error_message.bat\" had output on stderr: error message!"))); } } } } facter-3.14.12/lib/tests/facts/external/windows/powershell_resolver.cc0000644005276200011600000001243413702047406025765 0ustar jenkinsjenkins#include #include #include #include #include #include #include #include #include "../../../fixtures.hpp" #include "../../../log_capture.hpp" using namespace std; using namespace facter::facts; using namespace leatherman::util; using namespace facter::logging; using namespace facter::testing; using namespace facter::facts::external; SCENARIO("resolving external powershell facts") { collection_fixture facts; GIVEN("a powershell file") { WHEN("the execution fails") { THEN("an exception is thrown") { powershell_resolver resolver(LIBFACTER_TESTS_DIRECTORY "/fixtures/facts/external/windows/powershell/failed.ps1"); REQUIRE_THROWS_AS(resolver.resolve(facts), external_fact_exception&); } } WHEN("the execution succeeds") { THEN("it populates facts") { powershell_resolver resolver(LIBFACTER_TESTS_DIRECTORY "/fixtures/facts/external/windows/powershell/facts.ps1"); resolver.resolve(facts); REQUIRE(!facts.empty()); REQUIRE(facts.get("ps1_fact1")); REQUIRE(facts.get("ps1_fact1")->value() == "value1"); REQUIRE(facts.get("ps1_fact2")); REQUIRE(facts.get("ps1_fact2")->value() == ""); REQUIRE_FALSE(facts.get("ps1_fact3")); REQUIRE(facts.get("ps1_fact4")); REQUIRE_FALSE(facts.get("PS1_fact4")); REQUIRE(facts.get("ps1_fact4")->value() == "value2"); } } WHEN("the output is json") { THEN("it populates facts from the json") { powershell_resolver resolver(LIBFACTER_TESTS_DIRECTORY "/fixtures/facts/external/windows/powershell/json.ps1"); resolver.resolve(facts); REQUIRE(!facts.empty()); REQUIRE_FALSE(facts.get("PS1_JSON_FACT1")); REQUIRE(facts.get("ps1_json_fact1")); REQUIRE(facts.get("ps1_json_fact1")->value() == "value1"); REQUIRE(facts.get("ps1_json_fact2")); REQUIRE(facts.get("ps1_json_fact2")->value() == 2); REQUIRE(facts.get("ps1_json_fact3")); REQUIRE(facts.get("ps1_json_fact3")->value()); auto array = facts.get("ps1_json_fact4"); REQUIRE(array); REQUIRE(array->size() == 2u); REQUIRE_FALSE(facts.get("ps1_json_fact5")); auto map = facts.get("ps1_json_fact6"); REQUIRE(map); REQUIRE(map->size() == 2u); } } WHEN("the output is yaml") { THEN("it populates facts from the yaml") { powershell_resolver resolver(LIBFACTER_TESTS_DIRECTORY "/fixtures/facts/external/windows/powershell/yaml.ps1"); resolver.resolve(facts); REQUIRE(!facts.empty()); REQUIRE_FALSE(facts.get("PS1_YAML_FACT1")); REQUIRE(facts.get("ps1_yaml_fact1")); REQUIRE(facts.get("ps1_yaml_fact1")->value() == "yaml"); REQUIRE(facts.get("ps1_yaml_fact2")); REQUIRE(facts.get("ps1_yaml_fact2")->value() == 2); REQUIRE(facts.get("ps1_yaml_fact3")); REQUIRE(facts.get("ps1_yaml_fact3")->value() == "one value\nbut\nmany lines\n"); auto array1 = facts.get("ps1_yaml_fact4"); REQUIRE(array1); REQUIRE(array1->size() == 2u); auto array2 = facts.get("ps1_yaml_fact5"); REQUIRE(array2); REQUIRE(array2->size() == 3u); auto map1 = facts.get("ps1_yaml_fact6"); REQUIRE(map1); REQUIRE(map1->size() == 3u); auto map2 = facts.get("ps1_yaml_fact7"); REQUIRE(map2); REQUIRE(map2->size() == 1u); } } WHEN("messages are logged to stderr") { THEN("a warning is generated") { log_capture capture(level::warning); powershell_resolver resolver(LIBFACTER_TESTS_DIRECTORY "/fixtures/facts/external/windows/powershell/error_message.ps1"); resolver.resolve(facts); REQUIRE(facts.size() == 1u); REQUIRE(facts.get("foo")); REQUIRE(facts.get("foo")->value() == "bar"); auto output = capture.result(); CAPTURE(output); REQUIRE(re_search(output, boost::regex("WARN puppetlabs\\.facter - external fact file \".*error_message.ps1\" had output on stderr: error message!"))); } } } } facter-3.14.12/lib/tests/facts/external/yaml_resolver.cc0000644005276200011600000000543613702047406023055 0ustar jenkinsjenkins#include #include #include #include #include #include #include "../../fixtures.hpp" using namespace std; using namespace facter::facts; using namespace facter::facts::external; using namespace facter::testing; SCENARIO("resolving external YAML facts") { collection_fixture facts; GIVEN("a non-existent file to resolve") { THEN("it should throw an exception") { yaml_resolver resolver("doesnotexist.yaml"); REQUIRE_THROWS_AS(resolver.resolve(facts), external_fact_exception&); } } GIVEN("invalid YAML") { THEN("it should throw an exception") { yaml_resolver resolver(LIBFACTER_TESTS_DIRECTORY "/fixtures/facts/external/yaml/invalid.yaml"); REQUIRE_THROWS_AS(resolver.resolve(facts), external_fact_exception&); } } GIVEN("valid YAML") { THEN("it should populate the facts") { yaml_resolver resolver(LIBFACTER_TESTS_DIRECTORY "/fixtures/facts/external/yaml/facts.yaml"); resolver.resolve(facts); REQUIRE_FALSE(facts.empty()); REQUIRE(facts.get("yaml_fact1")); REQUIRE(facts.get("yaml_fact1")->value() == "foo"); REQUIRE(facts.get("yaml_fact2")); REQUIRE(facts.get("yaml_fact2")->value() == 5); REQUIRE(facts.get("yaml_fact3")); REQUIRE(facts.get("yaml_fact3")->value()); REQUIRE(facts.get("yaml_fact4")); REQUIRE(facts.get("yaml_fact4")->value() == Approx(5.1)); auto array = facts.get("yaml_fact5"); REQUIRE(array); REQUIRE(array->size() == 3u); auto map = facts.get("yaml_fact6"); REQUIRE(map); REQUIRE(map->size() == 2u); REQUIRE(facts.get("yaml_fact7")); REQUIRE_FALSE(facts.get("YAML_fact7")); REQUIRE(facts.get("yaml_fact7")->value() == "bar"); REQUIRE(facts.get("yaml_fact7")->value() == "bar"); REQUIRE(facts.get("yaml_fact7")->value() == "bar"); REQUIRE(facts.get("not_bool")); REQUIRE(facts.get("not_bool")->value() == "true"); REQUIRE(facts.get("not_int")); REQUIRE(facts.get("not_int")->value() == "123"); REQUIRE(facts.get("not_double")); REQUIRE(facts.get("not_double")->value() == "123.456"); } } } facter-3.14.12/lib/tests/facts/external_resolvers_factory.cc0000644005276200011600000000206113702047406024014 0ustar jenkinsjenkins#include #include #include "../fixtures.hpp" using namespace std; using namespace facter::facts; SCENARIO("checking common external file resolvers factory") { external_resolvers_factory erf; GIVEN("a file with unknown extension") { THEN("should throw no resolver exception") { REQUIRE_THROWS_AS(erf.get_resolver("foo.bin"), external::external_fact_no_resolver&); } } GIVEN("a JSON file extension") { THEN("it should be able to resolve") { REQUIRE(erf.get_resolver("foo.json")); REQUIRE(erf.get_resolver("FoO.jsOn")); } } GIVEN("a text file extension") { THEN("it should be able to resolve") { REQUIRE(erf.get_resolver("foo.txt")); REQUIRE(erf.get_resolver("FoO.TxT")); } } GIVEN("a YAML file extension") { THEN("it should be able to resolve") { REQUIRE(erf.get_resolver("foo.yaml")); REQUIRE(erf.get_resolver("FoO.yAmL")); } } } facter-3.14.12/lib/tests/facts/integer_value.cc0000644005276200011600000000440513702047406021174 0ustar jenkinsjenkins#include #include #include #include #include using namespace std; using namespace facter::facts; using namespace rapidjson; using namespace YAML; SCENARIO("using an integer fact value") { GIVEN("a small integer value") { int expected_value = 42; integer_value value(expected_value); REQUIRE(value.value() == expected_value); WHEN("serialized to JSON") { THEN("it should have the same value") { json_value json; json_allocator allocator; value.to_json(allocator, json); REQUIRE(json.IsNumber()); REQUIRE(json.GetInt64() == expected_value); } } WHEN("serialized to YAML") { THEN("it should have the same value") { Emitter emitter; value.write(emitter); REQUIRE(string(emitter.c_str()) == "42"); } } WHEN("serialized to text") { THEN("it should have the same value") { ostringstream stream; value.write(stream); REQUIRE(stream.str() == "42"); } } } GIVEN("a very large integer value") { int64_t expected_value = 1LL << 62; integer_value value(expected_value); REQUIRE(value.value() == expected_value); WHEN("serialized to JSON") { THEN("it should have the same value") { json_value json; json_allocator allocator; value.to_json(allocator, json); REQUIRE(json.IsNumber()); REQUIRE(json.GetInt64() == expected_value); } } WHEN("serialized to YAML") { THEN("it should have the same value") { Emitter emitter; value.write(emitter); REQUIRE(string(emitter.c_str()) == "4611686018427387904"); } } WHEN("serialized to text") { THEN("it should have the same value") { ostringstream stream; value.write(stream); REQUIRE(stream.str() == "4611686018427387904"); } } } } facter-3.14.12/lib/tests/facts/linux/0000755005276200011600000000000013702047635017174 5ustar jenkinsjenkinsfacter-3.14.12/lib/tests/facts/linux/dmi_resolver.cc0000644005276200011600000001264013702047406022174 0ustar jenkinsjenkins#include #include #include #include "../../fixtures.hpp" using namespace std; using namespace facter::util; using namespace facter::testing; using namespace facter::facts::linux; struct dmi_output : facter::facts::linux::dmi_resolver { explicit dmi_output(string const& output) { data result; int dmi_type = -1; each_line(output, [&](string& line) { parse_dmidecode_output(result, line, dmi_type); return true; }); bios_vendor = std::move(result.bios_vendor); bios_version = std::move(result.bios_version); bios_release_date = std::move(result.bios_release_date); board_asset_tag = std::move(result.board_asset_tag); board_manufacturer = std::move(result.board_manufacturer); board_product_name = std::move(result.board_product_name); board_serial_number = std::move(result.board_serial_number); chassis_asset_tag = std::move(result.chassis_asset_tag); manufacturer = std::move(result.manufacturer); product_name = std::move(result.product_name); serial_number = std::move(result.serial_number); uuid = std::move(result.uuid); chassis_type = std::move(result.chassis_type); } string bios_vendor; string bios_version; string bios_release_date; string board_asset_tag; string board_manufacturer; string board_product_name; string board_serial_number; string chassis_asset_tag; string manufacturer; string product_name; string serial_number; string uuid; string chassis_type; }; SCENARIO("parsing empty dmidecode output") { string contents; REQUIRE(load_fixture("facts/linux/dmidecode/none.txt", contents)); dmi_output output(contents); THEN("all fields should be empty") { REQUIRE(output.bios_vendor.empty()); REQUIRE(output.bios_version.empty()); REQUIRE(output.bios_release_date.empty()); REQUIRE(output.board_asset_tag.empty()); REQUIRE(output.board_manufacturer.empty()); REQUIRE(output.board_product_name.empty()); REQUIRE(output.board_serial_number.empty()); REQUIRE(output.chassis_asset_tag.empty()); REQUIRE(output.manufacturer.empty()); REQUIRE(output.serial_number.empty()); REQUIRE(output.product_name.empty()); REQUIRE(output.uuid.empty()); REQUIRE(output.chassis_type.empty()); } } SCENARIO("parsing full dmidecode output") { string contents; REQUIRE(load_fixture("facts/linux/dmidecode/full.txt", contents)); dmi_output output(contents); THEN("all fields should be populated") { REQUIRE(output.bios_vendor == "innotek GmbH"); REQUIRE(output.bios_version == "VirtualBox"); REQUIRE(output.bios_release_date == "12/01/2006"); REQUIRE(output.board_asset_tag == "Not Specified"); REQUIRE(output.board_manufacturer == "Oracle Corporation"); REQUIRE(output.board_product_name == "VirtualBox"); REQUIRE(output.board_serial_number == "0"); REQUIRE(output.chassis_asset_tag == "Not Specified"); REQUIRE(output.manufacturer == "innotek GmbH"); REQUIRE(output.serial_number == "0"); REQUIRE(output.product_name == "VirtualBox"); REQUIRE(output.uuid == "735AE71B-8655-4AE2-9CA9-172C1BBEDAB5"); REQUIRE(output.chassis_type == "Other"); } } SCENARIO("parsing full dmidecode output in an alternative format") { string contents; REQUIRE(load_fixture("facts/linux/dmidecode/full_alternative.txt", contents)); dmi_output output(contents); THEN("all fields should be populated") { REQUIRE(output.bios_vendor == "innotek GmbH"); REQUIRE(output.bios_version == "VirtualBox"); REQUIRE(output.bios_release_date == "12/01/2006"); REQUIRE(output.board_asset_tag == "Not Specified"); REQUIRE(output.board_manufacturer == "Oracle Corporation"); REQUIRE(output.board_product_name == "VirtualBox"); REQUIRE(output.board_serial_number == "0"); REQUIRE(output.chassis_asset_tag == "Not Specified"); REQUIRE(output.manufacturer == "innotek GmbH"); REQUIRE(output.serial_number == "0"); REQUIRE(output.product_name == "VirtualBox"); REQUIRE(output.uuid == "735AE71B-8655-4AE2-9CA9-172C1BBEDAB5"); REQUIRE(output.chassis_type == "Other"); } } SCENARIO("Verify chassis_type for new id's", "id"){ // new ids are not mapped to unkown for (int id = 25; id < 33; id++){ REQUIRE(dmi_resolver::to_chassis_description(std::to_string(id)) != "Unknown"); } // new ids are recognised REQUIRE(dmi_resolver::to_chassis_description("24") == "Sealed-Case PC"); REQUIRE(dmi_resolver::to_chassis_description("25") == "Multi-system"); REQUIRE(dmi_resolver::to_chassis_description("26") == "CompactPCI"); REQUIRE(dmi_resolver::to_chassis_description("27") == "AdvancedTCA"); REQUIRE(dmi_resolver::to_chassis_description("28") == "Blade"); REQUIRE(dmi_resolver::to_chassis_description("29") == "Blade Enclosure"); REQUIRE(dmi_resolver::to_chassis_description("30") == "Tablet"); REQUIRE(dmi_resolver::to_chassis_description("31") == "Convertible"); REQUIRE(dmi_resolver::to_chassis_description("32") == "Detachable"); // out of range id are maped to unknown REQUIRE(dmi_resolver::to_chassis_description("33") == "Unknown"); } facter-3.14.12/lib/tests/facts/linux/filesystem_resolver.cc0000644005276200011600000000326213702047406023607 0ustar jenkinsjenkins#include #include #include #include #include #include "../../collection_fixture.hpp" #include using namespace std; using namespace facter::facts::linux; using namespace facter::testing; SCENARIO("blkid output with non-printable ASCII characters") { REQUIRE(filesystem_resolver::safe_convert("") == ""); REQUIRE(filesystem_resolver::safe_convert("hello") == "hello"); REQUIRE(filesystem_resolver::safe_convert("\"hello\"") == "\\\"hello\\\""); REQUIRE(filesystem_resolver::safe_convert("\\hello\\") == "\\\\hello\\\\"); REQUIRE(filesystem_resolver::safe_convert("i am \xE0\xB2\xA0\x5F\xE0\xB2\xA0") == "i am M-`M-2M- _M-`M-2M- "); } SCENARIO("using the filesystem resolver") { // Create fact struct to store results collection_fixture facts; WHEN("populating facts") { // Add filesystem resolver facts.add(make_shared()); THEN("filesystem, mountpoints, and partition facts should resolve") { REQUIRE(facts.size() != 0u); REQUIRE(facts.query("filesystems")); REQUIRE(facts.query("mountpoints")); REQUIRE(facts.query("partitions")); } THEN("non-tmpfs proc and sys mounts should not exist") { REQUIRE_FALSE(facts.query("mountpoints./proc/")); REQUIRE_FALSE(facts.query("mountpoints./sys/")); } THEN("non-tmpfs mounts should exist") { REQUIRE(facts.query("mountpoints./")); } } } facter-3.14.12/lib/tests/facts/linux/processor_fixture.cc0000644005276200011600000001553613702047406023276 0ustar jenkinsjenkins#include "processor_fixture.hpp" #include #include #include #include using namespace std; using key_cmp = std::function; using architecture_type = test_linux_processor_resolver::ArchitectureType; namespace fs = boost::filesystem; static void reset_directory(fs::path const& path) { fs::remove_all(path); fs::create_directories(path); } template static void write_value(boost::filesystem::path const& path, T const& value) { boost::nowide::ofstream ofs(path.string()); ofs << value; } template static int key_index(const container& keys, const std::string& key) { return find(keys.begin(), keys.end(), key) - keys.begin(); } static key_cmp default_cpu_info_key_cmp = [](const std::string& k1, const std::string& k2) { static array KEYS = { "processor", "vendor_id", "cpu_family", "model", "model name", "stepping", "microcode", "physical id" }; return key_index(KEYS, k1) < key_index(KEYS, k2); }; static key_cmp power_cpu_info_key_cmp = [](const std::string& k1, const std::string& k2) { static array KEYS = { "processor", "cpu", "clock", "revision" }; return key_index(KEYS, k1) < key_index(KEYS, k2); }; linux_cpu_fixture::linux_cpu_fixture(boost::filesystem::path const& sys_dir, int id, std::string const& model_name) { _cpuroot = sys_dir / ("cpu" + to_string(id)); fs::create_directory(_cpuroot); _topology = _cpuroot / "topology"; fs::create_directory(_topology); _cpufreq = _cpuroot / "cpufreq"; fs::create_directory(_cpufreq); init_info(model_name); } void linux_cpu_fixture::set_logical_id(std::string const& logical_id) { _info["processor"] = logical_id; } void linux_cpu_fixture::set_physical_id(std::string const& physical_id) { write_value(_topology / "physical_package_id", physical_id); _info["physical id"] = physical_id; } void linux_cpu_fixture::set_speed(int64_t speed) { write_value(_cpufreq / "cpuinfo_max_freq", speed); } void linux_cpu_fixture::set_info(std::string const& key, std::string const& value) { _info[key] = value; } void linux_cpu_fixture::erase_info(std::string const& key) { _info.erase(key); } void linux_cpu_fixture::erase_all_info() { _info = map(default_cpu_info_key_cmp); } std::string linux_cpu_fixture::get_info() { ostringstream buf; for (auto& entry : _info) { buf << entry.first << " : " << entry.second << endl; } return buf.str(); } void linux_cpu_fixture::init_info(std::string const& model_name) { _info = map(default_cpu_info_key_cmp); _info["vendor_id"] = "GenuineIntel"; _info["cpu_family"] = "6"; _info["model"] = "69"; _info["model name"] = model_name; _info["stepping"] = "1"; _info["microcode"] = "0x17"; } linux_power_cpu_fixture::linux_power_cpu_fixture(boost::filesystem::path const& sys_dir, int id, std::string const& model_name) : linux_cpu_fixture(sys_dir, id, model_name) { // what's called in the base class is not the right "init_info" method, so // need to call this again. init_info(model_name); } void linux_power_cpu_fixture::set_physical_id(std::string const& physical_id) { linux_cpu_fixture::set_physical_id(physical_id); // Power's /proc/cpuinfo file does not have physical id entries // so we need to erase the one written in the base class erase_info("physical id"); } void linux_power_cpu_fixture::set_speed(int64_t speed) { linux_cpu_fixture::set_speed(speed); _info["clock"] = to_string(speed) + "MHz"; } void linux_power_cpu_fixture::init_info(std::string const& model_name) { _info = map(power_cpu_info_key_cmp); _info["cpu"] = model_name; _info["revision"] = "2.1 (pvr 004b 0201)"; } linux_processor_fixture::linux_processor_fixture(std::string const& root, test_linux_processor_resolver::ArchitectureType arch_type) : _next_id(0), _root(fs::path(root)) { fs::create_directory(_root); _proc = _root / "proc"; _sys = _root / "sys" / "devices" / "system" / "cpu"; reset(arch_type); } linux_processor_fixture::~linux_processor_fixture() { fs::remove_all(_root); } int linux_processor_fixture::add_cpu(std::string const& model_name) { _cpus.push_back(unique_ptr(make_cpu(_sys, _next_id, model_name))); return _next_id++; } linux_cpu_fixture& linux_processor_fixture::get_cpu(int id) { return *(_cpus[id]); } void linux_processor_fixture::write_cpuinfo() { vector cpu_infos; for (auto& cpu : _cpus) { cpu_infos.push_back(cpu->get_info()); } write_value(_proc / "cpuinfo", boost::algorithm::join(cpu_infos, "\n\n")); } void linux_processor_fixture::add_to_sys_dir(std::string const& dir_name) { fs::create_directory(_sys / dir_name); } void linux_processor_fixture::clear_sys_dir() { reset_directory(_sys); } void linux_processor_fixture::reset(test_linux_processor_resolver::ArchitectureType arch_type) { clear_sys_dir(); reset_directory(_proc); _cpus = std::vector>(); _next_id = 0; make_cpu = [arch_type](fs::path const& sys_dir, int id, std::string const& model_name) { return (arch_type == architecture_type::X86) ? new linux_cpu_fixture(sys_dir, id, model_name) : new linux_power_cpu_fixture(sys_dir, id, model_name); }; } test_linux_processor_resolver::test_linux_data test_linux_processor_resolver::collect_cpu_data(std::string const& root) { test_linux_data data; add_cpu_data(data, root); return data; } test_linux_processor_resolver::ArchitectureType test_linux_processor_resolver::architecture_type(test_linux_data const& data, std::string const& root) { return facter::facts::linux::processor_resolver::architecture_type(data, root); } std::vector setup_linux_processor_fixture(linux_processor_fixture& fixture, std::vector>> const& cpu_params) { std::vector ids; for (auto& cpu_param : cpu_params) { auto& model_name = get<0>(cpu_param); auto& logical_id = get<1>(cpu_param); auto& physical_id = get<2>(cpu_param); auto& speed = get<3>(cpu_param); int id = fixture.add_cpu(model_name); auto& cpu = fixture.get_cpu(id); cpu.set_logical_id(logical_id); cpu.set_physical_id(physical_id); if (speed) { cpu.set_speed(speed.get()); } ids.push_back(id); } // create garbage directories to ensure that only the cpu directories // are checked, where x >= 0 fixture.add_to_sys_dir("cpuabc"); fixture.add_to_sys_dir("cpugarbage"); return ids; } facter-3.14.12/lib/tests/facts/linux/processor_fixture.hpp0000644005276200011600000000555713702047406023502 0ustar jenkinsjenkins#pragma once #include #include #include #include #include #include #include #include #include #include struct linux_cpu_fixture { explicit linux_cpu_fixture(boost::filesystem::path const& sys_dir, int id, std::string const& model_name); void set_logical_id(std::string const& logical_id); virtual void set_physical_id(std::string const& physical_id); virtual void set_speed(int64_t speed); void set_info(std::string const& key, std::string const& value); void erase_info(std::string const& key); void erase_all_info(); std::string get_info(); protected: virtual void init_info(std::string const& model_name); std::map> _info; boost::filesystem::path _cpuroot; boost::filesystem::path _topology; boost::filesystem::path _cpufreq; }; struct linux_power_cpu_fixture : linux_cpu_fixture { explicit linux_power_cpu_fixture(boost::filesystem::path const& sys_dir, int id, std::string const& model_name); virtual void set_physical_id(std::string const& physical_id) override; virtual void set_speed(int64_t speed) override; protected: virtual void init_info(std::string const& model_name) override; }; struct test_linux_processor_resolver : facter::facts::linux::processor_resolver { using facter::facts::linux::processor_resolver::ArchitectureType; struct test_linux_data : facter::facts::resolvers::processor_resolver::data {}; test_linux_data collect_cpu_data(std::string const& root); ArchitectureType architecture_type(test_linux_data const& data, std::string const& root); }; struct linux_processor_fixture { explicit linux_processor_fixture(std::string const& root, test_linux_processor_resolver::ArchitectureType arch_type); ~linux_processor_fixture(); int add_cpu(std::string const& model_name); linux_cpu_fixture& get_cpu(int id); void write_cpuinfo(); void add_to_sys_dir(std::string const& dir_name); void clear_sys_dir(); void reset(test_linux_processor_resolver::ArchitectureType arch_type = test_linux_processor_resolver::ArchitectureType::X86); private: std::vector> _cpus; std::function make_cpu; int _next_id; boost::filesystem::path _root; boost::filesystem::path _proc; boost::filesystem::path _sys; }; // a cpu is defined as (Model name, Logical id, Physical id, (Optional) Speed) std::vector setup_linux_processor_fixture(linux_processor_fixture& fixture, std::vector>> const& cpu_params); facter-3.14.12/lib/tests/facts/linux/processor_resolver.cc0000644005276200011600000004112613702047406023443 0ustar jenkinsjenkins#include #include #include #include #include "processor_fixture.hpp" using namespace std; using namespace facter::facts::linux; using cpu_param = tuple>; using architecture_type = test_linux_processor_resolver::ArchitectureType; using test_data = test_linux_processor_resolver::test_linux_data; namespace fs = boost::filesystem; SCENARIO("determing the architecture of a linux machine") { test_linux_processor_resolver resolver; GIVEN("that the isa fact was successfully calculated") { WHEN("it starts with ppc64") { THEN("POWER is returned for the machine's architecture") { test_data data; array inputs{{"ppc64", "ppc64el", "ppc64le"}}; for (auto& input : inputs) { data.isa = input; REQUIRE(resolver.architecture_type(data, "non-existent-root") == architecture_type::POWER); } } } WHEN("it does not start with ppc64") { THEN("X86 is returned for the machine's architecture") { test_data data; array inputs{{"x86_64", "i386", "amd64"}}; for (auto& input : inputs) { data.isa = input; REQUIRE(resolver.architecture_type(data, "non-existent-root") == architecture_type::X86); } } } } GIVEN("that the isa fact was not successfully calculated") { string root_dir = fs::unique_path("temp_processor_resolver_root%%%%-%%%%-%%%%-%%%%").string(); linux_processor_fixture fixture(root_dir, architecture_type::X86); WHEN("the /proc/cpuinfo file has the x86 structure") { THEN("X86 is returned for the machine's architecture") { fixture.reset(); vector cpu_params({ make_tuple("Model A", "0", "0", 10), make_tuple("Model B", "1", "1", 15), }); setup_linux_processor_fixture(fixture, cpu_params); fixture.write_cpuinfo(); test_data data; REQUIRE(resolver.architecture_type(data, "non-existent-root") == architecture_type::X86); } } WHEN("the proc/cpu/info file almost has the power structure") { THEN("X86 is returned for the machine's architecture") { fixture.reset(architecture_type::POWER); vector cpu_params({ make_tuple("Model A", "0", "0", 10), make_tuple("Model B", "1", "1", 15), make_tuple("Model C", "2", "2", 15), make_tuple("Model D", "3", "3", 15) }); vector ids = setup_linux_processor_fixture(fixture, cpu_params); fixture.get_cpu(ids[0]).erase_info("processor"); fixture.get_cpu(ids[1]).erase_info("cpu"); fixture.get_cpu(ids[2]).erase_info("clock"); fixture.get_cpu(ids[3]).erase_info("revision"); fixture.write_cpuinfo(); test_data data; REQUIRE(resolver.architecture_type(data, root_dir) == architecture_type::X86); } } WHEN("the proc/cpu/info file has the power structure") { THEN("POWER is returned for the machine's architecture") { fixture.reset(architecture_type::POWER); vector cpu_params({ make_tuple("Model A", "0", "0", 10), make_tuple("Model B", "1", "1", 15), make_tuple("Model C", "2", "2", 15), make_tuple("Model D", "3", "3", 15) }); vector ids = setup_linux_processor_fixture(fixture, cpu_params); fixture.write_cpuinfo(); test_data data; REQUIRE(resolver.architecture_type(data, root_dir) == architecture_type::POWER); } } } } SCENARIO("resolving processor-specific facts for linux machines") { string root_dir = fs::unique_path("temp_processor_resolver_root%%%%-%%%%-%%%%-%%%%").string(); linux_processor_fixture fixture(root_dir, architecture_type::X86); test_linux_processor_resolver resolver; GIVEN("an x86 architecture") { WHEN("/sys/devices/system/cpu contains cpu information and /sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_max_freq exists") { THEN("the processor facts are correctly resolved, and the speed is set to cpu0's speed") { fixture.reset(); // here, speed is in KHz vector cpu_params({ make_tuple("Model A", "0", "0", 10), // ensure that duplicate CPUs are not counted twice in the // physical count make_tuple("Model B", "1", "0", 15), make_tuple("Model C", "2", "1", 20), // ensure that some arbitrary string is also recognized as a valid physical cpu make_tuple("Model D", "3", "some physical id", 35), // ensure that empty CPU ids are recognized as a valid physical cpu make_tuple("Model E", "4", "", 35) }); setup_linux_processor_fixture(fixture, cpu_params); fixture.write_cpuinfo(); auto result = resolver.collect_cpu_data(root_dir); REQUIRE(result.logical_count == 5); REQUIRE(result.physical_count == 4); array EXPECTED_MODELS{{"Model A", "Model B", "Model C", "Model D", "Model E"}}; REQUIRE(result.models.size() == EXPECTED_MODELS.size()); for (size_t i = 0; i < result.models.size(); ++i) { REQUIRE(result.models[i] == EXPECTED_MODELS[i]); } REQUIRE(result.speed == 10000); } } WHEN("/sys/devices/system/cpu contains cpu information and /sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_max_freq does not exist") { THEN("the processor facts are correctly resolved, but the speed is not calculated") { fixture.reset(); // here, speed is in KHz vector cpu_params({ make_tuple("Model A", "0", "0", boost::optional()), // ensure that duplicate CPUs are not counted twice in the // physical count make_tuple("Model B", "1", "0", 15), make_tuple("Model C", "2", "1", 20), // ensure that some arbitrary string is also recognized as a valid physical cpu make_tuple("Model D", "3", "some physical id", 35), // ensure that empty CPU ids are recognized as a valid physical cpu make_tuple("Model E", "4", "", 35) }); setup_linux_processor_fixture(fixture, cpu_params); fixture.write_cpuinfo(); auto result = resolver.collect_cpu_data(root_dir); REQUIRE(result.logical_count == 5); REQUIRE(result.physical_count == 4); array EXPECTED_MODELS{{"Model A", "Model B", "Model C", "Model D", "Model E"}}; REQUIRE(result.models.size() == EXPECTED_MODELS.size()); for (size_t i = 0; i < result.models.size(); ++i) { REQUIRE(result.models[i] == EXPECTED_MODELS[i]); } REQUIRE(result.speed == 0); } } WHEN("/sys/devices/system/cpu does not contain cpu information") { THEN("the processor facts are correctly resolved, with the logical and physical counts are obtained from /proc/cpuinfo") { fixture.reset(); // here, speed is in KHz vector cpu_params({ make_tuple("Model A", "0", "0", boost::optional()), // ensure that duplicate CPUs are not counted twice in the // physical count make_tuple("Model B", "1", "0", 15), make_tuple("Model C", "2", "1", 20), make_tuple("Model D", "3", "2", 35), // ensure that a CPU with an empty logical ID's model name // is not collected make_tuple("Model E", "", "3", 35) }); setup_linux_processor_fixture(fixture, cpu_params); fixture.write_cpuinfo(); fixture.clear_sys_dir(); // for this test, we want to ensure that the processor facts are obtained from // /proc/cpuinfo only. REQUIRE(fs::is_empty(fs::path(root_dir) / "sys" / "devices" / "system" / "cpu")); auto result = resolver.collect_cpu_data(root_dir); REQUIRE(result.logical_count == 5); REQUIRE(result.physical_count == 4); array EXPECTED_MODELS{{"Model A", "Model B", "Model C", "Model D"}}; REQUIRE(result.models.size() == EXPECTED_MODELS.size()); for (size_t i = 0; i < result.models.size(); ++i) { REQUIRE(result.models[i] == EXPECTED_MODELS[i]); } REQUIRE(result.speed == 0); } } WHEN("/sys/devices/system/cpu contains cpu information but some cpus are offline") { THEN("the processor facts are correctly resolved for online cpus") { fixture.reset(); // here, speed is in KHz vector cpu_params({ make_tuple("Model A", "0", "0", 10), // ensure that duplicate CPUs are not counted twice in the // physical count make_tuple("Model B", "1", "0", 15), make_tuple("Model C", "2", "1", 20), make_tuple("Model D", "3", "2", 35), make_tuple("Model E", "4", "3", 35) }); vector ids = setup_linux_processor_fixture(fixture, cpu_params); fixture.write_cpuinfo(); // for this test, we want to ensure that Model D and Model E cpus are disabled, meaning the last 2 cpus will not have the topology folder int number_cpu_to_disable = 2; vector disabled_cpu_params(cpu_params.end() - number_cpu_to_disable, cpu_params.end()); for (auto& cpu_param : disabled_cpu_params) { string logical_id = get<1>(cpu_param); // Remove the topology foder for offline cpus string topology_folder = root_dir + "/sys/devices/system/cpu"+ "/cpu"+logical_id + "/topology"; fs::remove_all(topology_folder); } auto result = resolver.collect_cpu_data(root_dir); // logical and physical count should count cpus without offline cpus REQUIRE(result.logical_count == 3); REQUIRE(result.physical_count == 2); } } } GIVEN("a power architecture") { WHEN("/sys/devices/system/cpu contains cpu information and /sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_max_freq exists") { THEN("the processor facts are correctly resolved, with the speed being read from the 'clock' entry") { fixture.reset(architecture_type::POWER); // here, speed is in KHz vector cpu_params({ // ensure that speed is read from the "clock" entry make_tuple("Model A", "0", "0", boost::optional()), // ensure that duplicate CPUs are not counted twice in the // physical count make_tuple("Model B", "1", "0", 15), make_tuple("Model C", "2", "1", 20), // ensure that some arbitrary string is also recognized as a valid physical cpu make_tuple("Model D", "3", "some physical id", 35), // ensure that empty CPU ids are recognized as a valid physical cpu make_tuple("Model E", "4", "", 35), // ensure that negative ids are not included in the physical count // this entry simulates an invalid power cpu make_tuple("Invalid CPU", "5", "-1", 35), }); vector ids = setup_linux_processor_fixture(fixture, cpu_params); fixture.get_cpu(ids.back()).erase_all_info(); fixture.write_cpuinfo(); auto result = resolver.collect_cpu_data(root_dir); REQUIRE(result.logical_count == 5); REQUIRE(result.physical_count == 4); array EXPECTED_MODELS{{"Model A", "Model B", "Model C", "Model D", "Model E"}}; REQUIRE(result.models.size() == EXPECTED_MODELS.size()); for (size_t i = 0; i < result.models.size(); ++i) { REQUIRE(result.models[i] == EXPECTED_MODELS[i]); } REQUIRE(result.speed == 15000); } } WHEN("/sys/devices/system/cpu contains cpu information but cpu0 is invalid") { THEN("the processor facts are correctly resolved, but the speed is not calculated") { fixture.reset(architecture_type::POWER); // here, speed is in KHz vector cpu_params({ make_tuple("Model A", "0", "-1", 15), make_tuple("Model B", "0", "-1", -1) }); vector ids = setup_linux_processor_fixture(fixture, cpu_params); fixture.get_cpu(ids.front()).erase_all_info(); fixture.write_cpuinfo(); auto result = resolver.collect_cpu_data(root_dir); REQUIRE(result.logical_count == 1); // /proc/cpuinfo does not have any "physical_id" entries for power architectures REQUIRE(result.physical_count == 0); array EXPECTED_MODELS{{"Model B"}}; REQUIRE(result.models.size() == EXPECTED_MODELS.size()); for (size_t i = 0; i < result.models.size(); ++i) { REQUIRE(result.models[i] == EXPECTED_MODELS[i]); } REQUIRE(result.speed == 0); } } WHEN("/sys/devices/system/cpu does not contain cpu information") { THEN("the processor facts are correctly resolved, with the speed being read from the 'clock' entry, but the physical count is not computed") { fixture.reset(architecture_type::POWER); // here, speed is in KHz vector cpu_params({ make_tuple("Model A", "0", "0", boost::optional()), // ensure that duplicate CPUs are not counted twice in the // physical count make_tuple("Model B", "1", "0", 15), make_tuple("Model C", "2", "1", 20), make_tuple("Model D", "3", "2", 35), // ensure that a CPU with an empty logical ID's model name // is not collected make_tuple("Model E", "", "3", 35) }); setup_linux_processor_fixture(fixture, cpu_params); fixture.write_cpuinfo(); fixture.clear_sys_dir(); // for this test, we want to ensure that the processor facts are obtained from // /proc/cpuinfo only. REQUIRE(fs::is_empty(fs::path(root_dir) / "sys" / "devices" / "system" / "cpu")); auto result = resolver.collect_cpu_data(root_dir); REQUIRE(result.logical_count == 5); // /proc/cpuinfo does not have any "physical_id" entries for power architectures REQUIRE(result.physical_count == 0); array EXPECTED_MODELS{{"Model A", "Model B", "Model C", "Model D"}}; REQUIRE(result.models.size() == EXPECTED_MODELS.size()); for (size_t i = 0; i < result.models.size(); ++i) { REQUIRE(result.models[i] == EXPECTED_MODELS[i]); } REQUIRE(result.speed == 15000); } } } } facter-3.14.12/lib/tests/facts/linux/virtualization_resolver.cc0000644005276200011600000000304713702047406024510 0ustar jenkinsjenkins#include #include #include #include "../../fixtures.hpp" #include using namespace std; using namespace facter::util; using namespace facter::facts; using namespace facter::facts::resolvers; using namespace facter::testing; struct peek_resolver : linux::virtualization_resolver { using virtualization_resolver::get_azure_from_leases_file; }; SCENARIO("azure") { collection_fixture facts; WHEN("leases file does not exist") { auto result = peek_resolver::get_azure_from_leases_file("does-not-exist"); THEN("azure is empty") { REQUIRE(result == ""); } } WHEN("leases file contains 'option 245'") { auto result = peek_resolver::get_azure_from_leases_file(string(LIBFACTER_TESTS_DIRECTORY) + "/fixtures/facts/linux/cloud/azure"); THEN("it reports azure") { REQUIRE(result == "azure"); } } WHEN("leases file contains 'option unknown-245'") { auto result = peek_resolver::get_azure_from_leases_file(string(LIBFACTER_TESTS_DIRECTORY) + "/fixtures/facts/linux/cloud/azure-unknown"); THEN("it reports azure") { REQUIRE(result == "azure"); } } WHEN("leases file does not contain correct option") { auto result = peek_resolver::get_azure_from_leases_file(string(LIBFACTER_TESTS_DIRECTORY) + "/fixtures/facts/linux/cloud/not-azure"); THEN("it does not report azure") { REQUIRE(result == ""); } } } facter-3.14.12/lib/tests/facts/map_value.cc0000644005276200011600000001067513702047406020322 0ustar jenkinsjenkins#include #include #include #include #include #include #include using namespace std; using namespace facter::facts; using namespace rapidjson; using namespace YAML; SCENARIO("using a map fact value") { map_value value; REQUIRE(value.empty()); GIVEN("a null value to add") { value.add("key", nullptr); THEN("it should still be empty") { REQUIRE(value.empty()); } } GIVEN("elements to insert") { value.add("string", make_value("hello")); value.add("integer", make_value(5)); auto array_element = make_value(); array_element->add(make_value("1")); array_element->add(make_value(2)); value.add("array", move(array_element)); auto map_element = make_value(); map_element->add("foo", make_value("bar")); value.add("map", move(map_element)); THEN("it should contain the elements that were added") { REQUIRE(value.size() == 4u); auto str = value.get("string"); REQUIRE(str); REQUIRE(str->value() == "hello"); auto integer = value.get("integer"); REQUIRE(integer); REQUIRE(integer->value() == 5); auto array = value.get("array"); REQUIRE(array); REQUIRE(array->size() == 2u); str = array->get(0); REQUIRE(str); REQUIRE(str->value() == "1"); integer = array->get(1); REQUIRE(integer); REQUIRE(integer->value() == 2); auto mapval = value.get("map"); REQUIRE(mapval); REQUIRE(mapval->size() == 1u); str = mapval->get("foo"); REQUIRE(str); REQUIRE(str->value() == "bar"); } THEN("elements should be in sort order") { int index = 0; value.each([&](string const& name, struct value const* val) { if (index == 0) { REQUIRE(name == "array"); } else if (index == 1) { REQUIRE(name == "integer"); } else if (index == 2) { REQUIRE(name == "map"); } else if (index == 3) { REQUIRE(name == "string"); } else { FAIL("should not be reached"); return false; } ++index; return true; }); } WHEN("serialized to JSON") { THEN("it should contain the same values") { json_value json; json_allocator allocator; value.to_json(allocator, json); REQUIRE(json.IsObject()); REQUIRE(json["string"].IsString()); REQUIRE(string(json["string"].GetString()) == "hello"); REQUIRE(json["integer"].IsNumber()); REQUIRE(json["integer"].GetInt64() == 5); REQUIRE(json["array"].IsArray()); REQUIRE(json["array"].Size() == 2); REQUIRE(json["array"][0u].IsString()); REQUIRE(string(json["array"][0u].GetString()) == "1"); REQUIRE(json["array"][1u].IsNumber()); REQUIRE(json["array"][1u].GetInt64() == 2); REQUIRE(json["map"].IsObject()); REQUIRE(json["map"]["foo"].IsString()); REQUIRE(string(json["map"]["foo"].GetString()) == "bar"); } } WHEN("serialized to text") { THEN("it should contain the same values") { ostringstream stream; value.write(stream); REQUIRE(stream.str() == "{\n array => [\n \"1\",\n 2\n ],\n integer => 5,\n map => {\n foo => \"bar\"\n },\n string => \"hello\"\n}"); } } WHEN("serialized to text") { THEN("it should contain the same values") { Emitter emitter; value.write(emitter); REQUIRE(string(emitter.c_str()) == "array:\n - \"1\"\n - 2\ninteger: 5\nmap:\n foo: bar\nstring: hello"); } } } } facter-3.14.12/lib/tests/facts/posix/0000755005276200011600000000000013702047635017177 5ustar jenkinsjenkinsfacter-3.14.12/lib/tests/facts/posix/collection.cc0000644005276200011600000000267013702047406021642 0ustar jenkinsjenkins#include #include #include #include #include #include #include "../../fixtures.hpp" #include using namespace std; using namespace facter::facts; using namespace facter::testing; SCENARIO("resolving external executable facts into a collection") { collection_fixture facts; REQUIRE(facts.size() == 0u); GIVEN("an absolute path") { facts.add_external_facts({ LIBFACTER_TESTS_DIRECTORY "/fixtures/facts/external/posix/execution", }); THEN("facts should resolve") { REQUIRE(facts.size() == 4u); REQUIRE(facts.get("exe_fact1")); REQUIRE(facts.get("exe_fact2")); REQUIRE_FALSE(facts.get("exe_fact3")); REQUIRE(facts.get("exe_fact4")); REQUIRE(facts.get("foo")); } } GIVEN("a relative path") { test_with_relative_path fixture("foo", "bar", "#! /usr/bin/env sh\necho local_exec_fact=value"); facts.add_external_facts({ "foo" }); THEN("facts should resolve") { REQUIRE(facts.size() == 1u); REQUIRE(facts.get("local_exec_fact")); REQUIRE(facts.get("local_exec_fact")->value() == "value"); } } } facter-3.14.12/lib/tests/facts/posix/external_resolvers_factory.cc0000644005276200011600000000175413702047406025166 0ustar jenkinsjenkins#include #include #include "../../fixtures.hpp" using namespace std; using namespace facter::facts; SCENARIO("checking external file posix resolvers factory") { external_resolvers_factory erf; GIVEN("a non-executable file") { THEN("the file cannot be resolved") { REQUIRE_THROWS_AS(erf.get_resolver(LIBFACTER_TESTS_DIRECTORY "/fixtures/facts/external/posix/execution/not_executable"), external::external_fact_no_resolver&); } } GIVEN("a executable file") { THEN("the file can be resolved") { REQUIRE(erf.get_resolver(LIBFACTER_TESTS_DIRECTORY "/fixtures/facts/external/posix/execution/facts")); } } GIVEN("a relative path not on PATH") { THEN("the file cannot be resolved") { REQUIRE_THROWS_AS(erf.get_resolver("foo/bar.bat"), external::external_fact_no_resolver&); } } } facter-3.14.12/lib/tests/facts/posix/uptime_resolver.cc0000644005276200011600000001135613702047406022734 0ustar jenkinsjenkins#include #include #include using namespace std; using namespace facter::facts; SCENARIO("parsing uptime formats") { WHEN("given an uptime to parse") { static const map test_cases = { {" 4:42pm up 1 min(s), 0 users, load average: 0.95, 0.25, 0.09", 1*60}, {"13:16 up 58 mins, 2 users, load average: 0.00, 0.02, 0.05", 58*60}, {"13:18 up 1 hr, 1 user, load average: 0.58, 0.23, 0.14", 1*60*60 }, {" 10:14pm up 3 hr(s), 0 users, load average: 0.00, 0.00, 0.00", 3*60*60 }, {"14:18 up 2 hrs, 0 users, load average: 0.33, 0.27, 0.29", 2*60*60 }, {" 9:01pm up 1:47, 0 users, load average: 0.00, 0.00, 0.00", 1*60*60 + 47*60}, {"13:19 up 1:01, 1 user, load average: 0.10, 0.26, 0.21", 1*60*60 + 1*60}, {"10:49 up 22:31, 0 users, load average: 0.26, 0.34, 0.27", 22*60*60 + 31*60}, {"12:18 up 1 day, 0 users, load average: 0.74, 0.20, 0.10", 1*24*60*60 }, {" 2:48pm up 1 day(s), 0 users, load average: 0.21, 0.20, 0.17", 1*24*60*60 }, {"12:18 up 2 days, 0 users, load average: 0.50, 0.27, 0.16", 2*24*60*60 }, {" 1:56pm up 25 day(s), 2 users, load average: 0.59, 0.56, 0.50", 25*24*60*60 }, {" 1:29pm up 485 days, 0 users, load average: 0.00, 0.01, 0.01", 485*24*60*60 }, {" 18:11:24 up 69 days, 0 min, 0 users, load average: 0.00, 0.00, 0.00", 69*24*60*60 }, {"12:19 up 1 day, 1 min, 0 users, load average: 0.07, 0.16, 0.13", 1*24*60*60 + 1*60}, {" 3:23pm up 25 day(s), 27 min(s), 2 users, load average: 0.49, 0.45, 0.46", 25*24*60*60 + 27*60}, {" 02:42PM up 1 day, 39 mins, 0 users, load average: 1.49, 1.74, 1.80", 1*24*60*60 + 39*60}, {" 18:13:13 up 245 days, 44 min, 1 user, load average: 0.00, 0.00, 0.00", 245*24*60*60 + 44*60}, {" 6:09pm up 350 days, 2 min, 1 user, load average: 0.02, 0.03, 0.00", 350*24*60*60 + 2*60}, {" 1:07pm up 174 day(s), 16 hr(s), 0 users, load average: 0.05, 0.04, 0.03", 174*24*60*60 + 16*60*60 }, {" 02:34PM up 621 days, 18 hrs, 0 users, load average: 2.67, 2.52, 2.56", 621*24*60*60 + 18*60*60 }, {" 3:30am up 108 days, 1 hr, 31 users, load average: 0.39, 0.40, 0.41", 108*24*60*60 + 1*60*60 }, {"13:18 up 1 day, 1 hr, 0 users, load average: 0.78, 0.33, 0.18", 1*24*60*60 + 1*60*60 }, {"14:18 up 1 day, 2 hrs, 0 users, load average: 1.17, 0.48, 0.41", 1*24*60*60 + 2*60*60 }, {"15:56 up 152 days, 17 hrs, 0 users, load average: 0.01, 0.06, 0.07", 152*24*60*60 + 17*60*60 }, {" 5:37pm up 25 days, 21:00, 0 users, load average: 0.01, 0.02, 0.00", 25*24*60*60 + 21*60*60 }, {" 8:59pm up 94 day(s), 3:17, 46 users, load average: 0.66, 0.67, 0.70", 94*24*60*60 + 3*60*60 + 17*60}, {" 3:01pm up 4496 day(s), 21:19, 32 users, load average: 0.61, 0.62, 0.62", 4496*24*60*60 + 21*60*60 + 19*60}, {" 02:42PM up 41 days, 2:38, 0 users, load average: 0.38, 0.70, 0.55", 41*24*60*60 + 2*60*60 + 38*60}, {" 18:13:29 up 25 days, 21:36, 0 users, load average: 0.00, 0.00, 0.00", 25*24*60*60 + 21*60*60 + 36*60}, {" 13:36:05 up 118 days, 1:15, 1 user, load average: 0.00, 0.00, 0.00", 118*24*60*60 + 1*60*60 + 15*60}, {"10:27am up 1 day 7:26, 1 user, load average: 0.00, 0.00, 0.00", 1*24*60*60 + 7*60*60 + 26*60}, {"22:45pm up 0:-6, 1 user, load average: 0.00, 0.00, 0.00", 6*60}, {"22:45pm up 1 day 0:-6, 1 user, load average: 0.00, 0.00, 0.00", 1*24*60*60 + 6*60} }; THEN("it parses each format correctly") { for (auto const& t : test_cases) { REQUIRE(posix::uptime_resolver::parse_uptime(t.first) == t.second); } } } } facter-3.14.12/lib/tests/facts/resolvers/0000755005276200011600000000000013702047635020061 5ustar jenkinsjenkinsfacter-3.14.12/lib/tests/facts/resolvers/augeas_resolver.cc0000644005276200011600000000322313702047406023552 0ustar jenkinsjenkins#include #include #include #include #include #include #include "../../collection_fixture.hpp" using namespace std; using namespace facter::facts; using namespace facter::facts::resolvers; using namespace facter::testing; struct empty_augeas_resolver : augeas_resolver { protected: virtual string get_version() override { return {}; } }; struct fixed_augeas_resolver : augeas_resolver { protected: virtual string get_version() override { return "foo"; } }; SCENARIO("using the augeas resolver") { collection_fixture facts; WHEN("no version is returned") { facts.add(make_shared()); THEN("the fact is not present") { REQUIRE(facts.size() == 0u); } } WHEN("an augeas version is returned") { facts.add(make_shared()); THEN("a structured fact is returned") { REQUIRE(facts.size() == 2u); auto augeas = facts.get(fact::augeas); REQUIRE(augeas); REQUIRE(augeas->size() == 1u); auto version = augeas->get("version"); REQUIRE(version); REQUIRE(version->value() == "foo"); } THEN("flat facts are added") { REQUIRE(facts.size() == 2u); auto augeasversion = facts.get(fact::augeasversion); REQUIRE(augeasversion); REQUIRE(augeasversion->value() == "foo"); } } } facter-3.14.12/lib/tests/facts/resolvers/disk_resolver.cc0000644005276200011600000000730513702047406023244 0ustar jenkinsjenkins#include #include #include #include #include #include #include "../../collection_fixture.hpp" using namespace std; using namespace facter::facts; using namespace facter::facts::resolvers; using namespace facter::testing; struct test_disk_resolver : disk_resolver { void add_disk(string name, string vendor, string model, string product, uint64_t size) { disk d; d.name = move(name); d.vendor = move(vendor); d.model = move(model); d.product = move(product); d.size = size; disks.emplace_back(move(d)); } protected: virtual data collect_data(collection& facts) override { data result; result.disks = move(disks); return result; } private: vector disks; }; SCENARIO("using the disk resolver") { collection_fixture facts; auto resolver = make_shared(); facts.add(resolver); GIVEN("no disks present") { THEN("facts should not be added") { REQUIRE(facts.size() == 0u); } } GIVEN("five present disks") { const unsigned int count = 5; for (unsigned int i = 0; i < count; ++i) { string num = to_string(i); resolver->add_disk("disk" + num, "vendor" + num, "model" + num, "product" + num, 12345 + i); } THEN("a structured fact should be added") { auto disks = facts.get(fact::disks); REQUIRE(disks); REQUIRE(disks->size() == count); for (unsigned int i = 0; i < count; ++i) { string num = to_string(i); auto disk = disks->get("disk" + num); REQUIRE(disk); REQUIRE(disk->size() == 5u); auto model = disk->get("model"); REQUIRE(model); REQUIRE(model->value() == "model" + num); auto product = disk->get("product"); REQUIRE(product); REQUIRE(product->value() == "product" + num); auto size = disk->get("size"); REQUIRE(size); REQUIRE(size->value() == "12.06 KiB"); auto size_bytes = disk->get("size_bytes"); REQUIRE(size_bytes); REQUIRE(size_bytes->value() == 12345 + i); auto vendor = disk->get("vendor"); REQUIRE(vendor); REQUIRE(vendor->value() == "vendor" + num); } } THEN("flat facts should be added") { string names; for (unsigned int i = 0; i < count; ++i) { string num = to_string(i); auto model = facts.get("blockdevice_disk" + num + "_model"); REQUIRE(model); REQUIRE(model->value() == "model" + num); auto size = facts.get("blockdevice_disk" + num + "_size"); REQUIRE(size); REQUIRE(size->value() == 12345 + i); auto vendor = facts.get("blockdevice_disk" + num + "_vendor"); REQUIRE(vendor); REQUIRE(vendor->value() == "vendor" + num); if (names.size() > 0u) { names += ","; } names += "disk" + num; } auto devices = facts.get(fact::block_devices); REQUIRE(devices); REQUIRE(devices->value() == names); } } } facter-3.14.12/lib/tests/facts/resolvers/dmi_resolver.cc0000644005276200011600000001226313702047406023062 0ustar jenkinsjenkins#include #include #include #include #include #include #include "../../collection_fixture.hpp" using namespace std; using namespace facter::facts; using namespace facter::facts::resolvers; using namespace facter::testing; struct empty_dmi_resolver : dmi_resolver { protected: virtual data collect_data(collection& facts) override { return {}; } }; struct test_dmi_resolver : dmi_resolver { protected: virtual data collect_data(collection& facts) override { data result; result.bios_vendor = fact::bios_vendor; result.bios_version = fact::bios_version; result.bios_release_date = fact::bios_release_date; result.board_asset_tag = fact::board_asset_tag; result.board_manufacturer = fact::board_manufacturer; result.board_product_name = fact::board_product_name; result.board_serial_number = fact::board_serial_number; result.chassis_asset_tag = fact::chassis_asset_tag; result.manufacturer = fact::manufacturer; result.product_name = fact::product_name; result.serial_number = fact::serial_number; result.uuid = fact::uuid; result.chassis_type = fact::chassis_type; return result; } }; SCENARIO("using the DMI resolver") { collection_fixture facts; WHEN("data is not present") { facts.add(make_shared()); THEN("facts should not be added") { REQUIRE(facts.size() == 0u); } } WHEN("data is present") { facts.add(make_shared()); THEN("a structured fact is added") { auto dmi = facts.get(fact::dmi); REQUIRE(dmi); REQUIRE(dmi->size() == 5u); auto bios = dmi->get("bios"); REQUIRE(bios); REQUIRE(bios->size() == 3u); auto value = bios->get("release_date"); REQUIRE(value); REQUIRE(value->value() == string(fact::bios_release_date)); value = bios->get("vendor"); REQUIRE(value); REQUIRE(value->value() == string(fact::bios_vendor)); value = bios->get("version"); REQUIRE(value); REQUIRE(value->value() == string(fact::bios_version)); auto board = dmi->get("board"); REQUIRE(board); REQUIRE(board->size() == 4u); value = board->get("asset_tag"); REQUIRE(value); REQUIRE(value->value() == string(fact::board_asset_tag)); value = board->get("manufacturer"); REQUIRE(value); REQUIRE(value->value() == string(fact::board_manufacturer)); value = board->get("product"); REQUIRE(value); REQUIRE(value->value() == string(fact::board_product_name)); value = board->get("serial_number"); REQUIRE(value); REQUIRE(value->value() == string(fact::board_serial_number)); auto chassis = dmi->get("chassis"); REQUIRE(chassis); REQUIRE(chassis->size() == 2u); value = chassis->get("asset_tag"); REQUIRE(value); REQUIRE(value->value() == string(fact::chassis_asset_tag)); value = chassis->get("type"); REQUIRE(value); REQUIRE(value->value() == string(fact::chassis_type)); value = dmi->get("manufacturer"); REQUIRE(value); REQUIRE(value->value() == string(fact::manufacturer)); auto product = dmi->get("product"); REQUIRE(product); REQUIRE(product->size() == 3u); value = product->get("name"); REQUIRE(value); REQUIRE(value->value() == string(fact::product_name)); value = product->get("serial_number"); REQUIRE(value); REQUIRE(value->value() == string(fact::serial_number)); value = product->get("uuid"); REQUIRE(value); REQUIRE(value->value() == string(fact::uuid)); } THEN("flat facts are added") { static vector const names = { fact::bios_vendor, fact::bios_version, fact::bios_release_date, fact::board_asset_tag, fact::board_manufacturer, fact::board_product_name, fact::board_serial_number, fact::chassis_asset_tag, fact::manufacturer, fact::product_name, fact::serial_number, fact::uuid, fact::chassis_type, }; for (auto const& name : names) { auto fact = facts.get(name); REQUIRE(fact); REQUIRE(fact->value() == name); } } } } facter-3.14.12/lib/tests/facts/resolvers/filesystem_resolver.cc0000644005276200011600000001733713702047406024504 0ustar jenkinsjenkins#include #include #include #include #include #include #include #include "../../collection_fixture.hpp" using namespace std; using namespace facter::facts; using namespace facter::facts::resolvers; using namespace facter::testing; struct test_filesystem_resolver : filesystem_resolver { void add_mountpoint(string name, string device, string filesystem, uint64_t size, uint64_t available, uint64_t reserved, vector options) { mountpoint mp; mp.name = move(name); mp.device = move(device); mp.filesystem = move(filesystem); mp.size = size; mp.available = available; mp.free = available + reserved; mp.options = move(options); mountpoints.emplace_back(move(mp)); } void add_filesystem(string filesystem) { filesystems.emplace(move(filesystem)); } void add_partition(string name, string filesystem, uint64_t size, string uuid, string partuuid, string label, string partlabel, string mount, string backing_file) { partition p; p.name = move(name); p.filesystem = move(filesystem); p.size = size; p.uuid = move(uuid); p.partition_uuid = move(partuuid); p.label = move(label); p.partition_label = move(partlabel); p.mount = move(mount); p.backing_file = move(backing_file); partitions.emplace_back(move(p)); } protected: virtual data collect_data(collection& facts) override { data result; result.mountpoints = move(mountpoints); result.filesystems = move(filesystems); result.partitions = move(partitions); return result; } vector mountpoints; set filesystems; vector partitions; }; SCENARIO("using the file system resolver") { collection_fixture facts; auto resolver = make_shared(); facts.add(resolver); WHEN("data is not present") { THEN("facts should not be added") { REQUIRE(facts.size() == 0u); } } WHEN("mount point data is present") { const unsigned int count = 5; for (unsigned int i = 0; i < count; ++i) { string num = to_string(i); resolver->add_mountpoint("mount" + num, "device" + num, "filesystem" + num, 12345, 1000, 0, {"option1" + num, "option2" + num, "option3" + num}); } THEN("a structured fact is added") { REQUIRE(facts.size() == 1u); auto mountpoints = facts.get(fact::mountpoints); REQUIRE(mountpoints); REQUIRE(mountpoints->size() == 5u); for (unsigned int i = 0; i < count; ++i) { string num = to_string(i); auto mountpoint = mountpoints->get("mount" + num); REQUIRE(mountpoint); REQUIRE(mountpoint->size() == 10u); auto available = mountpoint->get("available"); REQUIRE(available); REQUIRE(available->value() == "1000 bytes"); auto available_bytes = mountpoint->get("available_bytes"); REQUIRE(available_bytes); REQUIRE(available_bytes->value() == 1000); auto capacity = mountpoint->get("capacity"); REQUIRE(capacity); REQUIRE(capacity->value() == "91.90%"); auto device = mountpoint->get("device"); REQUIRE(device); REQUIRE(device->value() == "device" + num); auto filesystem = mountpoint->get("filesystem"); REQUIRE(filesystem); REQUIRE(filesystem->value() == "filesystem" + num); auto options = mountpoint->get("options"); REQUIRE(options); REQUIRE(options->size() == 3u); REQUIRE(options->get(0)->value() == "option1" + num); REQUIRE(options->get(1)->value() == "option2" + num); REQUIRE(options->get(2)->value() == "option3" + num); auto size = mountpoint->get("size"); REQUIRE(size); REQUIRE(size->value() == "12.06 KiB"); auto size_bytes = mountpoint->get("size_bytes"); REQUIRE(size_bytes); REQUIRE(size_bytes->value() == 12345); auto used = mountpoint->get("used"); REQUIRE(used); REQUIRE(used->value() == "11.08 KiB"); auto used_bytes = mountpoint->get("used_bytes"); REQUIRE(used_bytes); REQUIRE(used_bytes->value() == 12345 - 1000); } } } WHEN("file system data is present") { resolver->add_filesystem("foo"); resolver->add_filesystem("bar"); resolver->add_filesystem("baz"); THEN("a flat fact is added") { REQUIRE(facts.size() == 1u); auto filesystems = facts.get(fact::filesystems); REQUIRE(filesystems); REQUIRE(filesystems->value() == "bar,baz,foo"); } } WHEN("partition data is present") { const unsigned int count = 5; for (unsigned int i = 0; i < count; ++i) { string num = to_string(i); resolver->add_partition("partition" + num, "filesystem" + num, 12345 + i, "uuid" + num, "partuuid" + num, "label" + num, "partlabel" + num, "mount" + num, "file" + num); } THEN("a structured fact is added") { REQUIRE(facts.size() == 1u); auto partitions = facts.get(fact::partitions); REQUIRE(partitions); for (unsigned int i = 0; i < count; ++i) { string num = to_string(i); auto partition = partitions->get("partition" + num); REQUIRE(partition); REQUIRE(partition->size() == 9u); auto filesystem = partition->get("filesystem"); REQUIRE(filesystem); REQUIRE(filesystem->value() == "filesystem" + num); auto label = partition->get("label"); REQUIRE(label); REQUIRE(label->value() == "label" + num); auto partlabel = partition->get("partlabel"); REQUIRE(partlabel); REQUIRE(partlabel->value() == "partlabel" + num); auto mount = partition->get("mount"); REQUIRE(mount); REQUIRE(mount->value() == "mount" + num); auto partuuid = partition->get("partuuid"); REQUIRE(partuuid); REQUIRE(partuuid->value() == "partuuid" + num); auto uuid = partition->get("uuid"); REQUIRE(uuid); REQUIRE(uuid->value() == "uuid" + num); auto size_bytes = partition->get("size_bytes"); REQUIRE(size_bytes); REQUIRE(size_bytes->value() == 12345 + i); auto size = partition->get("size"); REQUIRE(size); REQUIRE(size->value() == "12.06 KiB"); auto file = partition->get("backing_file"); REQUIRE(file); REQUIRE(file->value() == "file" + num); } } } } facter-3.14.12/lib/tests/facts/resolvers/identity_resolver.cc0000644005276200011600000000461113702047406024140 0ustar jenkinsjenkins#include #include #include #include #include #include #include "../../collection_fixture.hpp" using namespace std; using namespace facter::facts; using namespace facter::facts::resolvers; using namespace facter::testing; struct empty_identity_resolver : identity_resolver { protected: virtual data collect_data(collection& facts) override { return {}; } }; struct test_identity_resolver : identity_resolver { protected: virtual data collect_data(collection& facts) override { data result; result.group_id = 123; result.group_name = "foo"; result.user_id = 456; result.user_name = "bar"; result.privileged = false; return result; } }; SCENARIO("using the identity resolver") { collection_fixture facts; WHEN("data is not present") { facts.add(make_shared()); THEN("facts should not be added") { REQUIRE(facts.size() == 0u); } } WHEN("data is present") { facts.add(make_shared()); THEN("a structured fact is added") { auto identity = facts.get(fact::identity); REQUIRE(identity); REQUIRE(identity->size() == 5u); auto name = identity->get("group"); REQUIRE(name); REQUIRE(name->value() == "foo"); auto id = identity->get("gid"); REQUIRE(id); REQUIRE(id->value() == 123); name = identity->get("user"); REQUIRE(name); REQUIRE(name->value() == "bar"); id = identity->get("uid"); REQUIRE(id); REQUIRE(id->value() == 456); auto privileged = identity->get("privileged"); REQUIRE(privileged); REQUIRE(privileged->value() == false); } THEN("flat facts are added") { auto name = facts.get(fact::gid); REQUIRE(name); REQUIRE(name->value() == "foo"); name = facts.get(fact::id); REQUIRE(name); REQUIRE(name->value() == "bar"); } } } facter-3.14.12/lib/tests/facts/resolvers/kernel_resolver.cc0000644005276200011600000000346313702047406023573 0ustar jenkinsjenkins#include #include #include #include #include #include "../../collection_fixture.hpp" using namespace std; using namespace facter::facts; using namespace facter::facts::resolvers; using namespace facter::testing; struct empty_kernel_resolver : kernel_resolver { protected: virtual data collect_data(collection& facts) override { return {}; } }; struct test_kernel_resolver : kernel_resolver { protected: virtual data collect_data(collection& facts) override { data result; result.name = "foo"; result.release = "1.2.3-foo"; result.version = "1.2.3"; return result; } }; SCENARIO("using the kernel resolver") { collection_fixture facts; WHEN("data is not present") { facts.add(make_shared()); THEN("facts should not be added") { REQUIRE(facts.size() == 0u); } } WHEN("data is present") { facts.add(make_shared()); THEN("flat facts are added") { REQUIRE(facts.size() == 4u); auto kernel = facts.get(fact::kernel); REQUIRE(kernel); REQUIRE(kernel->value() == "foo"); auto release = facts.get(fact::kernel_release); REQUIRE(release); REQUIRE(release->value() == "1.2.3-foo"); auto version = facts.get(fact::kernel_version); REQUIRE(version); REQUIRE(version->value() == "1.2.3"); auto major = facts.get(fact::kernel_major_version); REQUIRE(major); REQUIRE(major->value() == "1.2"); } } } facter-3.14.12/lib/tests/facts/resolvers/ldom_resolver.cc0000644005276200011600000000500413702047406023237 0ustar jenkinsjenkins#include #include #include #include #include #include #include "../../collection_fixture.hpp" using namespace std; using namespace facter::facts; using namespace facter::facts::resolvers; using namespace facter::testing; struct empty_ldom_resolver : ldom_resolver { protected: virtual data collect_data(collection& facts) override { data result; return result; } }; struct test_ldom_resolver : ldom_resolver { protected: virtual data collect_data(collection& facts) override { ldom_info single_value; single_value.key = "domainname"; single_value.values.insert({ "domainname", "somedomain"}); ldom_info multi_value; multi_value.key = "domainrole"; multi_value.values.insert({ "impl", "true"}); multi_value.values.insert({ "io", "false"}); data result; result.ldom.emplace_back(single_value); result.ldom.emplace_back(multi_value); return result; } }; SCENARIO("Using the Solaris LDom resolver") { collection_fixture facts; WHEN("data is not present") { facts.add(make_shared()); THEN("no LDom facts should be added") { REQUIRE(facts.size() == 0u); } } WHEN("data is present") { facts.add(make_shared()); THEN("a structured fact is added") { REQUIRE(facts.size() == 4u); auto ldom = facts.get(fact::ldom); REQUIRE(ldom); REQUIRE(ldom->size() == 2u); auto sval = ldom->get("domainname"); REQUIRE(sval); REQUIRE(sval->value() == "somedomain"); auto mval = ldom->get("domainrole"); REQUIRE(mval); REQUIRE(mval->size() == 2u); } THEN("flat facts are added") { REQUIRE(facts.size() == 4u); auto sval_2 = facts.get("ldom_domainname"); REQUIRE(sval_2); REQUIRE(sval_2->value() == "somedomain"); auto sval_3 = facts.get("ldom_domainrole_impl"); REQUIRE(sval_3); REQUIRE(sval_3->value() == "true"); auto sval_4 = facts.get("ldom_domainrole_io"); REQUIRE(sval_4); REQUIRE(sval_4->value() == "false"); } } } facter-3.14.12/lib/tests/facts/resolvers/memory_resolver.cc0000644005276200011600000001270713702047406023624 0ustar jenkinsjenkins#include #include #include #include #include #include #include "../../collection_fixture.hpp" using namespace std; using namespace facter::facts; using namespace facter::facts::resolvers; using namespace facter::testing; struct empty_memory_resolver : memory_resolver { protected: virtual data collect_data(collection& facts) override { return {}; } }; struct test_memory_resolver : memory_resolver { protected: virtual data collect_data(collection& facts) override { data result; result.swap_encryption = encryption_status::encrypted; result.mem_total = 10 * 1024 * 1024; result.mem_free = 5 * 1024 * 1024; result.swap_total = 20 * 1024 * 1024; result.swap_free = 4 * 1024 * 1024; return result; } }; SCENARIO("using the memory resolver") { collection_fixture facts; WHEN("data is not present") { facts.add(make_shared()); THEN("facts should not be added") { REQUIRE(facts.size() == 0u); } } WHEN("data is present") { facts.add(make_shared()); THEN("a structured fact is added") { REQUIRE(facts.size() == 10u); auto memory = facts.get(fact::memory); REQUIRE(memory); auto info = memory->get("swap"); REQUIRE(info); REQUIRE(info->size() == 8u); auto available = info->get("available"); REQUIRE(available); REQUIRE(available->value() == "4.00 MiB"); auto available_bytes = info->get("available_bytes"); REQUIRE(available_bytes); REQUIRE(available_bytes->value() == 4194304); auto capacity = info->get("capacity"); REQUIRE(capacity); REQUIRE(capacity->value() == "80.00%"); auto encrypted = info->get("encrypted"); REQUIRE(encrypted); REQUIRE(encrypted->value()); auto total = info->get("total"); REQUIRE(total); REQUIRE(total->value() == "20.00 MiB"); auto total_bytes = info->get("total_bytes"); REQUIRE(total_bytes); REQUIRE(total_bytes->value() == 20971520); auto used = info->get("used"); REQUIRE(used); REQUIRE(used->value() == "16.00 MiB"); auto used_bytes = info->get("used_bytes"); REQUIRE(used_bytes); REQUIRE(used_bytes->value() == 16777216); info = memory->get("system"); REQUIRE(info); REQUIRE(info->size() == 7u); available = info->get("available"); REQUIRE(available); REQUIRE(available->value() == "5.00 MiB"); available_bytes = info->get("available_bytes"); REQUIRE(available_bytes); REQUIRE(available_bytes->value() == 5242880); capacity = info->get("capacity"); REQUIRE(capacity); REQUIRE(capacity->value() == "50.00%"); total = info->get("total"); REQUIRE(total); REQUIRE(total->value() == "10.00 MiB"); total_bytes = info->get("total_bytes"); REQUIRE(total_bytes); REQUIRE(total_bytes->value() == 10485760); used = info->get("used"); REQUIRE(used); REQUIRE(used->value() == "5.00 MiB"); used_bytes = info->get("used_bytes"); REQUIRE(used_bytes); REQUIRE(used_bytes->value() == 5242880); } THEN("flat facts are added") { REQUIRE(facts.size() == 10u); auto memoryfree = facts.get(fact::memoryfree); REQUIRE(memoryfree); REQUIRE(memoryfree->value() == "5.00 MiB"); auto memoryfree_mb = facts.get(fact::memoryfree_mb); REQUIRE(memoryfree_mb); REQUIRE(memoryfree_mb->value() == Approx(5.0)); auto memorysize = facts.get(fact::memorysize); REQUIRE(memorysize); REQUIRE(memorysize->value() == "10.00 MiB"); auto memorysize_mb = facts.get(fact::memorysize_mb); REQUIRE(memorysize_mb); REQUIRE(memorysize_mb->value() == Approx(10.0)); auto swapencrypted = facts.get(fact::swapencrypted); REQUIRE(swapencrypted); REQUIRE(swapencrypted->value()); auto swapfree = facts.get(fact::swapfree); REQUIRE(swapfree); REQUIRE(swapfree->value() == "4.00 MiB"); auto swapfree_mb = facts.get(fact::swapfree_mb); REQUIRE(swapfree_mb); REQUIRE(swapfree_mb->value() == Approx(4.0)); auto swapsize = facts.get(fact::swapsize); REQUIRE(swapsize); REQUIRE(swapsize->value() == "20.00 MiB"); auto swapsize_mb = facts.get(fact::swapsize_mb); REQUIRE(swapsize_mb); REQUIRE(swapsize_mb->value() == Approx(20.0)); } } } facter-3.14.12/lib/tests/facts/resolvers/networking_resolver.cc0000644005276200011600000005060213702047406024477 0ustar jenkinsjenkins#include #include #include #include #include #include #include #include "../../collection_fixture.hpp" using namespace std; using namespace facter::facts; using namespace facter::facts::resolvers; using namespace facter::testing; struct empty_networking_resolver : networking_resolver { protected: virtual data collect_data(collection& facts) override { return {}; } }; struct test_hostname_resolver : networking_resolver { protected: virtual data collect_data(collection& facts) override { data result; result.hostname = "hostname"; return result; } }; struct test_domain_resolver : networking_resolver { protected: virtual data collect_data(collection& facts) override { data result; result.domain = "domain"; return result; } }; struct test_fqdn_resolver : networking_resolver { protected: virtual data collect_data(collection& facts) override { data result; result.fqdn = "fqdn"; return result; } }; struct test_missing_fqdn_resolver : networking_resolver { protected: virtual data collect_data(collection& facts) override { data result; result.hostname = "hostname"; result.domain = "domain.com"; return result; } }; struct test_domain_with_trailing_dot : networking_resolver { protected: virtual data collect_data(collection& facts) override { data result; result.domain = "domain.com."; return result; } }; struct test_interface_resolver : networking_resolver { protected: virtual data collect_data(collection& facts) override { data result; for (int i = 0; i < 5; ++i) { string num = to_string(i); interface iface; iface.name = "iface_" + num; iface.dhcp_server = "dhcp_" + num; for (int binding_index = 0; binding_index < 2; ++binding_index) { string binding_num = to_string(binding_index); iface.ipv4_bindings.emplace_back(binding { "ip_" + num + "_" + binding_num, "netmask_" + num + "_" + binding_num, "network_" + num + "_" + binding_num }); iface.ipv6_bindings.emplace_back(binding { "ip6_" + num + "_" + binding_num, "netmask6_" + num + "_" + binding_num, "network6_" + num + "_" + binding_num }); } iface.macaddress = "macaddress_" + num; iface.mtu = i; result.interfaces.emplace_back(move(iface)); } result.primary_interface = "iface_2"; return result; } }; struct primary_interface_resolver : networking_resolver { protected: virtual data collect_data(collection& facts) override { data result; interface lo0; lo0.name = "lo0"; lo0.ipv4_bindings.emplace_back(binding { "127.0.0.1", "255.255.255.0", "127.0.0.0" }); lo0.ipv6_bindings.emplace_back(binding { "::1", "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff", "::1" }); result.interfaces.emplace_back(move(lo0)); interface en0; en0.name = "en0"; en0.ipv4_bindings.emplace_back(binding { "123.123.123.123", "255.255.255.0", "123.123.123.0" }); en0.ipv6_bindings.emplace_back(binding { "fe80::6203:8ff:fe95:2d16", "ffff:ffff:ffff:ffff::", "fe80::" }); result.interfaces.emplace_back(move(en0)); interface en1; en1.name = "en1"; en1.ipv4_bindings.emplace_back(binding { "123.123.123.124", "255.255.255.0", "123.123.123.0" }); en1.ipv6_bindings.emplace_back(binding { "fe80::6203:8ff:fe95:2d17", "ffff:ffff:ffff:ffff::", "fe80::" }); result.interfaces.emplace_back(move(en1)); return result; } }; SCENARIO("using the networking resolver") { collection_fixture facts; WHEN("data is not present") { facts.add(make_shared()); THEN("facts should not be added") { REQUIRE(facts.size() == 0u); } } WHEN("only hostname is present") { facts.add(make_shared()); REQUIRE(facts.size() == 3u); THEN("a flat fact is added") { auto hostname = facts.get(fact::hostname); REQUIRE(hostname); REQUIRE(hostname->value() == "hostname"); } THEN("a structured fact is added") { auto networking = facts.get(fact::networking); REQUIRE(networking); REQUIRE(networking->size() == 2u); auto hostname = networking->get("hostname"); REQUIRE(hostname); REQUIRE(hostname->value() == "hostname"); auto fqdn = networking->get("fqdn"); REQUIRE(fqdn); REQUIRE(fqdn->value() == "hostname"); } THEN("the FQDN fact is the hostname") { auto fqdn = facts.get(fact::fqdn); REQUIRE(fqdn); REQUIRE(fqdn->value() == "hostname"); } } WHEN("only domain is present") { facts.add(make_shared()); REQUIRE(facts.size() == 2u); THEN("a flat fact is added") { auto domain = facts.get(fact::domain); REQUIRE(domain); REQUIRE(domain->value() == "domain"); } THEN("a structured fact is added") { auto networking = facts.get(fact::networking); REQUIRE(networking); REQUIRE(networking->size() == 1u); auto domain = networking->get("domain"); REQUIRE(domain); REQUIRE(domain->value() == "domain"); } THEN("the FQDN fact is not present") { auto fqdn = facts.get(fact::fqdn); REQUIRE_FALSE(fqdn); } } WHEN("domain contains a trailing dot, the dot is removed") { facts.add(make_shared()); REQUIRE(facts.size() == 2u); THEN("a flat fact is added") { auto domain = facts.get(fact::domain); REQUIRE(domain); REQUIRE(domain->value() == "domain.com"); } THEN("a structured fact is added") { auto networking = facts.get(fact::networking); REQUIRE(networking); REQUIRE(networking->size() == 1u); auto domain = networking->get("domain"); REQUIRE(domain); REQUIRE(domain->value() == "domain.com"); } THEN("the FQDN fact is not present") { auto fqdn = facts.get(fact::fqdn); REQUIRE_FALSE(fqdn); } } WHEN("FQDN is present") { facts.add(make_shared()); REQUIRE(facts.size() == 2u); THEN("a flat fact is added") { auto fqdn = facts.get(fact::fqdn); REQUIRE(fqdn); REQUIRE(fqdn->value() == "fqdn"); } THEN("a structured fact is added") { auto networking = facts.get(fact::networking); REQUIRE(networking); REQUIRE(networking->size() == 1u); auto fqdn = networking->get("fqdn"); REQUIRE(fqdn); REQUIRE(fqdn->value() == "fqdn"); } THEN("the FQDN fact is present") { auto fqdn = facts.get(fact::fqdn); REQUIRE(fqdn); REQUIRE(fqdn->value() == "fqdn"); } } WHEN("FQDN is not present") { facts.add(make_shared()); REQUIRE(facts.size() == 4u); THEN("the FQDN fact is the combination of hostname and domain") { auto svalue = facts.get(fact::hostname); REQUIRE(svalue); REQUIRE(svalue->value() == "hostname"); svalue = facts.get(fact::domain); REQUIRE(svalue); REQUIRE(svalue->value() == "domain.com"); svalue = facts.get(fact::fqdn); REQUIRE(svalue); REQUIRE(svalue->value() == "hostname.domain.com"); } THEN("the FQDN in the structured fact is the combination of hostname and domain") { auto networking = facts.get(fact::networking); REQUIRE(networking); REQUIRE(networking->size() == 3u); auto svalue = networking->get("hostname"); REQUIRE(svalue); REQUIRE(svalue->value() == "hostname"); svalue = networking->get("domain"); REQUIRE(svalue); REQUIRE(svalue->value() == "domain.com"); svalue = networking->get("fqdn"); REQUIRE(svalue); REQUIRE(svalue->value() == "hostname.domain.com"); } } WHEN("network interfaces are present") { facts.add(make_shared()); REQUIRE(facts.size() == 56u); THEN("the DHCP servers fact is present") { auto dhcp_servers = facts.get(fact::dhcp_servers); REQUIRE(dhcp_servers); REQUIRE(dhcp_servers->size() == 6u); for (unsigned int i = 0; i < 5; ++i) { string num = to_string(i); auto server = dhcp_servers->get("iface_" + num); REQUIRE(server); REQUIRE(server->value() == "dhcp_" + num); } auto dhcp = dhcp_servers->get("system"); REQUIRE(dhcp); REQUIRE(dhcp->value() == "dhcp_2"); } THEN("the interface names fact is present") { auto interfaces_list = facts.get(fact::interfaces); REQUIRE(interfaces_list); REQUIRE(interfaces_list->value() == "iface_0,iface_1,iface_2,iface_3,iface_4"); } THEN("the interface flat facts are present") { for (unsigned int i = 0; i < 5; ++i) { string num = to_string(i); auto ip = facts.get(fact::ipaddress + string("_iface_") + num); REQUIRE(ip); REQUIRE(ip->value() == "ip_" + num + "_0"); auto ip6 = facts.get(fact::ipaddress6 + string("_iface_") + num); REQUIRE(ip6); REQUIRE(ip6->value() == "ip6_" + num + "_0"); auto macaddress = facts.get(fact::macaddress + string("_iface_") + num); REQUIRE(macaddress); REQUIRE(macaddress->value() == "macaddress_" + num); auto mtu = facts.get(fact::mtu + string("_iface_") + num); REQUIRE(mtu); REQUIRE(mtu->value() == i); auto netmask = facts.get(fact::netmask + string("_iface_") + num); REQUIRE(netmask); REQUIRE(netmask->value() == "netmask_" + num + "_0"); auto netmask6 = facts.get(fact::netmask6 + string("_iface_") + num); REQUIRE(netmask6); REQUIRE(netmask6->value() == "netmask6_" + num + "_0"); auto network = facts.get(fact::network + string("_iface_") + num); REQUIRE(network); REQUIRE(network->value() == "network_" + num + "_0"); auto network6 = facts.get(fact::network6 + string("_iface_") + num); REQUIRE(network6); REQUIRE(network6->value() == "network6_" + num + "_0"); auto scope6 = facts.get(fact::scope6 + string("_iface_") + num); REQUIRE(scope6); } } THEN("the system fact facts are present") { auto ip = facts.get(fact::ipaddress); REQUIRE(ip); REQUIRE(ip->value() == "ip_2_0"); auto ip6 = facts.get(fact::ipaddress6); REQUIRE(ip6); REQUIRE(ip6->value() == "ip6_2_0"); auto macaddress = facts.get(fact::macaddress); REQUIRE(macaddress); REQUIRE(macaddress->value() == "macaddress_2"); auto netmask = facts.get(fact::netmask); REQUIRE(netmask); REQUIRE(netmask->value() == "netmask_2_0"); auto netmask6 = facts.get(fact::netmask6); REQUIRE(netmask6); REQUIRE(netmask6->value() == "netmask6_2_0"); auto network = facts.get(fact::network); REQUIRE(network); REQUIRE(network->value() == "network_2_0"); auto network6 = facts.get(fact::network6); REQUIRE(network6); REQUIRE(network6->value() == "network6_2_0"); auto scope6 = facts.get(fact::scope6); REQUIRE(scope6); } THEN("the networking structured fact is present") { auto networking = facts.get(fact::networking); REQUIRE(networking); REQUIRE(networking->size() == 12u); auto primary = networking->get("primary"); REQUIRE(primary); REQUIRE(primary->value() == "iface_2"); auto dhcp = networking->get("dhcp"); REQUIRE(dhcp); REQUIRE(dhcp->value() == "dhcp_2"); auto ip = networking->get("ip"); REQUIRE(ip); REQUIRE(ip->value() == "ip_2_0"); auto ip6 = networking->get("ip6"); REQUIRE(ip6); REQUIRE(ip6->value() == "ip6_2_0"); auto macaddress = networking->get("mac"); REQUIRE(macaddress); REQUIRE(macaddress->value() == "macaddress_2"); auto netmask = networking->get("netmask"); REQUIRE(netmask); REQUIRE(netmask->value() == "netmask_2_0"); auto netmask6 = networking->get("netmask6"); REQUIRE(netmask6); REQUIRE(netmask6->value() == "netmask6_2_0"); auto network = networking->get("network"); REQUIRE(network); REQUIRE(network->value() == "network_2_0"); auto network6 = networking->get("network6"); REQUIRE(network6); REQUIRE(network6->value() == "network6_2_0"); auto scope6 = networking->get("scope6"); REQUIRE(scope6); auto mtu = networking->get("mtu"); REQUIRE(mtu); REQUIRE(mtu->value() == 2); auto interfaces = networking->get("interfaces"); REQUIRE(interfaces); for (unsigned int i = 0; i < 5; ++i) { string num = to_string(i); auto interface = interfaces->get("iface_" + num); REQUIRE(interface); dhcp = interface->get("dhcp"); REQUIRE(dhcp); REQUIRE(dhcp->value() == "dhcp_" + num); ip = interface->get("ip"); REQUIRE(ip); REQUIRE(ip->value() == "ip_" + num + "_0"); ip6 = interface->get("ip6"); REQUIRE(ip6); REQUIRE(ip6->value() == "ip6_" + num + "_0"); macaddress = interface->get("mac"); REQUIRE(macaddress); REQUIRE(macaddress->value() == "macaddress_" + num); netmask = interface->get("netmask"); REQUIRE(netmask); REQUIRE(netmask->value() == "netmask_" + num + "_0"); netmask6 = interface->get("netmask6"); REQUIRE(netmask6); REQUIRE(netmask6->value() == "netmask6_" + num + "_0"); network = interface->get("network"); REQUIRE(network); REQUIRE(network->value() == "network_" + num + "_0"); network6 = interface->get("network6"); REQUIRE(network6); REQUIRE(network6->value() == "network6_" + num + "_0"); mtu = interface->get("mtu"); REQUIRE(mtu); REQUIRE(mtu->value() == i); auto bindings = interface->get("bindings"); REQUIRE(bindings); REQUIRE(bindings->size() == 2u); for (size_t binding_index = 0; binding_index < bindings->size(); ++binding_index) { auto interface_num = to_string(binding_index); auto binding = bindings->get(binding_index); REQUIRE(binding); auto address = binding->get("address"); REQUIRE(address); REQUIRE(address->value() == "ip_" + num + "_" + interface_num); auto netmask = binding->get("netmask"); REQUIRE(netmask); REQUIRE(netmask->value() == "netmask_" + num + "_" + interface_num); auto network = binding->get("network"); REQUIRE(network); REQUIRE(network->value() == "network_" + num + "_" + interface_num); } bindings = interface->get("bindings6"); REQUIRE(bindings); REQUIRE(bindings->size() == 2u); for (size_t binding_index = 0; binding_index < bindings->size(); ++binding_index) { auto interface_num = to_string(binding_index); auto binding = bindings->get(binding_index); REQUIRE(binding); auto address = binding->get("address"); REQUIRE(address); REQUIRE(address->value() == "ip6_" + num + "_" + interface_num); auto netmask = binding->get("netmask"); REQUIRE(netmask); REQUIRE(netmask->value() == "netmask6_" + num + "_" + interface_num); auto network = binding->get("network"); REQUIRE(network); REQUIRE(network->value() == "network6_" + num + "_" + interface_num); } } } } WHEN("the primary interface is not resolved") { facts.add(make_shared()); THEN("the first interface with a valid address should be treated as primary") { REQUIRE(facts.query("networking.primary")); REQUIRE(facts.query("networking.primary")->value() == "en0"); } } } SCENARIO("ignored IPv4 addresses") { char const* ignored_addresses[] = { "", "127.0.0.1", "127.0.0.2", "127.1.0.0", "127.0.1.0", "169.254.7.14", "169.254.0.0", "169.254.255.255" }; for (auto s : ignored_addresses) { CAPTURE(s); REQUIRE(networking_resolver::ignored_ipv4_address(s)); } char const* accepted_addresses[] = { "169.253.0.0", "169.255.0.0", "100.100.100.100", "0.0.0.0", "1.1.1.1", "10.0.18.142", "192.168.0.1", "255.255.255.255", "128.0.0.1", }; for (auto s : accepted_addresses) { CAPTURE(s); REQUIRE_FALSE(networking_resolver::ignored_ipv4_address(s)); } } SCENARIO("ignore IPv6 adddresses") { char const* ignored_addresses[] = { "", "::1", "fe80::9c84:7ca1:794b:12ed", "fe80::75f2:2f55:823b:a513%10" }; for (auto s : ignored_addresses) { CAPTURE(s); REQUIRE(networking_resolver::ignored_ipv6_address(s)); } char const* accepted_addresses[] = { "::fe80:75f2:2f55:823b:a513", "fe7f::75f2:2f55:823b:a513%10", "::2", "::fe01", "::fe80" }; for (auto s : accepted_addresses) { CAPTURE(s); REQUIRE_FALSE(networking_resolver::ignored_ipv6_address(s)); } } facter-3.14.12/lib/tests/facts/resolvers/operating_system_resolver.cc0000644005276200011600000003053713702047406025711 0ustar jenkinsjenkins#include #include #include #include #include #include #include "../../collection_fixture.hpp" using namespace std; using namespace facter::facts; using namespace facter::facts::resolvers; using namespace facter::testing; struct empty_os_resolver : operating_system_resolver { protected: virtual data collect_data(collection& facts) override { return {}; } }; struct test_os_resolver : operating_system_resolver { protected: virtual data collect_data(collection& facts) override { data result; result.name = "Archlinux"; result.family = "Archlinux"; result.release = "1.2.3"; result.specification_version = "1.4"; result.distro.id = "Arch"; result.distro.release = "1.2.3"; result.distro.codename = "awesomesauce"; result.distro.description = "best distro ever"; result.osx.product = "Mac OS X"; result.osx.build = "14A388b"; result.osx.version = "10.10"; result.win.release_id = "1904"; result.win.edition_id = "ServerStandard"; result.win.installation_type = "Server"; result.win.product_name = "Windows 2019 Standard Edition"; result.win.system32 = "C:\\WINDOWS\\sysnative"; result.architecture = "amd64"; result.hardware = "x86-64"; result.selinux.supported = true; result.selinux.enabled = true; result.selinux.enforced = true; result.selinux.current_mode = "current mode"; result.selinux.config_mode = "config mode"; result.selinux.config_policy = "config policy"; result.selinux.policy_version = "policy version"; return result; } }; SCENARIO("using the operating system resolver") { collection_fixture facts; WHEN("data is not present") { facts.add(make_shared()); THEN("facts should not be added") { REQUIRE(facts.size() == 0u); } } WHEN("data is present") { facts.add(make_shared()); REQUIRE(facts.size() == 30u); THEN("a structured fact is added") { auto os = facts.get(fact::os); REQUIRE(os); REQUIRE(os->size() == 9u); auto distro = os->get("distro"); REQUIRE(distro); REQUIRE(distro->size() == 5u); auto codename = distro->get("codename"); REQUIRE(codename); REQUIRE(codename->value() == "awesomesauce"); auto description = distro->get("description"); REQUIRE(description); REQUIRE(description->value() == "best distro ever"); auto id = distro->get("id"); REQUIRE(description); REQUIRE(id->value() == "Arch"); auto lsbrelease = distro->get("specification"); REQUIRE(lsbrelease); REQUIRE(lsbrelease->value() == "1.4"); auto release_attribute = distro->get("release"); REQUIRE(release_attribute); REQUIRE(release_attribute->size() == 3u); auto release = release_attribute->get("full"); REQUIRE(release); REQUIRE(release->value() == "1.2.3"); auto major = release_attribute->get("major"); REQUIRE(major); REQUIRE(major->value() == "1"); auto minor = release_attribute->get("minor"); REQUIRE(minor); REQUIRE(minor->value() == "2"); auto family = os->get("family"); REQUIRE(family); REQUIRE(family->value() == "Archlinux"); auto name = os->get("name"); REQUIRE(name); REQUIRE(name->value() == "Archlinux"); auto architecture = os->get("architecture"); REQUIRE(architecture); REQUIRE(architecture->value() == "amd64"); auto hardware = os->get("hardware"); REQUIRE(hardware); REQUIRE(hardware->value() == "x86-64"); release_attribute = os->get("release"); REQUIRE(release_attribute); REQUIRE(release_attribute->size() == 3u); release = release_attribute->get("full"); REQUIRE(release); REQUIRE(release->value() == "1.2.3"); major = release_attribute->get("major"); REQUIRE(major); REQUIRE(major->value() == "1"); minor = release_attribute->get("minor"); REQUIRE(minor); REQUIRE(minor->value() == "2"); auto macosx = os->get("macosx"); REQUIRE(macosx); REQUIRE(macosx->size() == 3u); auto product = macosx->get("product"); REQUIRE(product); REQUIRE(product->value() == "Mac OS X"); auto build = macosx->get("build"); REQUIRE(build); REQUIRE(build->value() == "14A388b"); release_attribute = macosx->get("version"); REQUIRE(release_attribute); REQUIRE(release_attribute->size() == 3u); release = release_attribute->get("full"); REQUIRE(release); REQUIRE(release->value() == "10.10"); major = release_attribute->get("major"); REQUIRE(major); REQUIRE(major->value() == "10.10"); minor = release_attribute->get("minor"); REQUIRE(minor); REQUIRE(minor->value() == "0"); auto windows = os->get("windows"); REQUIRE(windows); REQUIRE(windows->size() == 5u); auto edition_id = facts.get(fact::windows_edition_id); REQUIRE(edition_id); REQUIRE(edition_id->value() == "ServerStandard"); auto installation_type = facts.get(fact::windows_installation_type); REQUIRE(installation_type); REQUIRE(installation_type->value() == "Server"); auto product_name = facts.get(fact::windows_product_name); REQUIRE(product_name); REQUIRE(product_name->value() == "Windows 2019 Standard Edition"); auto release_id = facts.get(fact::windows_release_id); REQUIRE(release_id); REQUIRE(release_id->value() == "1904"); auto system32 = windows->get("system32"); REQUIRE(system32); REQUIRE(system32->value() == "C:\\WINDOWS\\sysnative"); auto selinux = os->get("selinux"); REQUIRE(selinux); REQUIRE(selinux->size() == 6u); auto bval = selinux->get("enabled"); REQUIRE(bval); REQUIRE(bval->value()); bval = selinux->get("enforced"); REQUIRE(bval); REQUIRE(bval->value()); auto sval = selinux->get("policy_version"); REQUIRE(sval); REQUIRE(sval->value() == "policy version"); sval = selinux->get("current_mode"); REQUIRE(sval); REQUIRE(sval->value() == "current mode"); sval = selinux->get("config_mode"); REQUIRE(sval); REQUIRE(sval->value() == "config mode"); sval = selinux->get("config_policy"); REQUIRE(sval); REQUIRE(sval->value() == "config policy"); } THEN("flat facts are added") { auto name = facts.get(fact::operating_system); REQUIRE(name); REQUIRE(name->value() == "Archlinux"); auto architecture = facts.get(fact::architecture); REQUIRE(architecture); REQUIRE(architecture->value() == "amd64"); auto hardware = facts.get(fact::hardware_model); REQUIRE(hardware); REQUIRE(hardware->value() == "x86-64"); auto release = facts.get(fact::operating_system_release); REQUIRE(release); REQUIRE(release->value() == "1.2.3"); auto major = facts.get(fact::operating_system_major_release); REQUIRE(major); REQUIRE(major->value() == "1"); auto family = facts.get(fact::os_family); REQUIRE(family); REQUIRE(family->value() == "Archlinux"); auto codename = facts.get(fact::lsb_dist_codename); REQUIRE(codename); REQUIRE(codename->value() == "awesomesauce"); auto description = facts.get(fact::lsb_dist_description); REQUIRE(description); REQUIRE(description->value() == "best distro ever"); auto id = facts.get(fact::lsb_dist_id); REQUIRE(id); REQUIRE(id->value() == "Arch"); release = facts.get(fact::lsb_dist_release); REQUIRE(release); REQUIRE(release->value() == "1.2.3"); major = facts.get(fact::lsb_dist_major_release); REQUIRE(major); REQUIRE(major->value() == "1"); auto minor = facts.get(fact::lsb_dist_minor_release); REQUIRE(minor); REQUIRE(minor->value() == "2"); auto lsbrelease = facts.get(fact::lsb_release); REQUIRE(lsbrelease); REQUIRE(lsbrelease->value() == "1.4"); auto build = facts.get(fact::macosx_buildversion); REQUIRE(build); REQUIRE(build->value() == "14A388b"); auto product = facts.get(fact::macosx_productname); REQUIRE(product); REQUIRE(product->value() == "Mac OS X"); release = facts.get(fact::macosx_productversion); REQUIRE(release); REQUIRE(release->value() == "10.10"); major = facts.get(fact::macosx_productversion_major); REQUIRE(major); REQUIRE(major->value() == "10.10"); minor = facts.get(fact::macosx_productversion_minor); REQUIRE(minor); REQUIRE(minor->value() == "0"); auto edition_id = facts.get(fact::windows_edition_id); REQUIRE(edition_id); REQUIRE(edition_id->value() == "ServerStandard"); auto installation_type = facts.get(fact::windows_installation_type); REQUIRE(installation_type); REQUIRE(installation_type->value() == "Server"); auto product_name = facts.get(fact::windows_product_name); REQUIRE(product_name); REQUIRE(product_name->value() == "Windows 2019 Standard Edition"); auto release_id = facts.get(fact::windows_release_id); REQUIRE(release_id); REQUIRE(release_id->value() == "1904"); auto system32 = facts.get(fact::windows_system32); REQUIRE(system32); REQUIRE(system32->value() == "C:\\WINDOWS\\sysnative"); auto bval = facts.get(fact::selinux); REQUIRE(bval); REQUIRE(bval->value()); bval = facts.get(fact::selinux_enforced); REQUIRE(bval); REQUIRE(bval->value()); auto sval = facts.get(fact::selinux_policyversion); REQUIRE(sval); REQUIRE(sval->value() == "policy version"); sval = facts.get(fact::selinux_current_mode); REQUIRE(sval); REQUIRE(sval->value() == "current mode"); sval = facts.get(fact::selinux_config_mode); REQUIRE(sval); REQUIRE(sval->value() == "config mode"); sval = facts.get(fact::selinux_config_policy); REQUIRE(sval); REQUIRE(sval->value() == "config policy"); } } } facter-3.14.12/lib/tests/facts/resolvers/processor_resolver.cc0000644005276200011600000001310613702047406024325 0ustar jenkinsjenkins#include #include #include #include #include #include #include #include "../../collection_fixture.hpp" using namespace std; using namespace facter::facts; using namespace facter::facts::resolvers; using namespace facter::testing; struct empty_processor_resolver : processor_resolver { protected: virtual data collect_data(collection& facts) override { return {}; } }; struct test_processor_resolver : processor_resolver { protected: virtual data collect_data(collection& facts) override { data result; result.isa = "isa"; result.logical_count = 4; result.physical_count = 2; result.models = { "processor1", "processor2", "processor3", "processor4" }; result.speed = 10 * 1000 * 1000 * 1000ull; return result; } }; struct test_processor_resolver_no_physical_count : processor_resolver { protected: virtual data collect_data(collection& facts) override { data result; result.isa = "isa"; result.logical_count = 4; result.models = { "processor1", "processor2", "processor3", "processor4" }; result.speed = 10 * 1000 * 1000 * 1000ull; return result; } }; SCENARIO("using the processor resolver") { collection_fixture facts; WHEN("data is not present") { facts.add(make_shared()); THEN("facts should not be added") { REQUIRE(facts.size() == 0u); } } WHEN("typical data is present") { facts.add(make_shared()); THEN("a structured fact is added") { REQUIRE(facts.size() == 8u); auto processors = facts.get(fact::processors); REQUIRE(processors); REQUIRE(processors->size() == 5u); auto count = processors->get("count"); REQUIRE(count); REQUIRE(count->value() == 4); count = processors->get("physicalcount"); REQUIRE(count); REQUIRE(count->value() == 2); auto isa = processors->get("isa"); REQUIRE(isa); REQUIRE(isa->value() == "isa"); auto models = processors->get("models"); REQUIRE(models); REQUIRE(models->size() == 4u); for (size_t i = 0; i < 4; ++i) { auto model = models->get(i); REQUIRE(model); REQUIRE(model->value() == "processor" + to_string(i + 1)); } auto speed = processors->get("speed"); REQUIRE(speed); REQUIRE(speed->value() == "10.00 GHz"); } THEN("flat facts are added") { REQUIRE(facts.size() == 8u); auto count = facts.get(fact::physical_processor_count); REQUIRE(count); REQUIRE(count->value() == 2); count = facts.get(fact::processor_count); REQUIRE(count); REQUIRE(count->value() == 4); auto isa = facts.get(fact::hardware_isa); REQUIRE(isa); REQUIRE(isa->value() == "isa"); for (size_t i = 0; i < 4; ++i) { auto model = facts.get(fact::processor + to_string(i)); REQUIRE(model); REQUIRE(model->value() == "processor" + to_string(i + 1)); } } } WHEN("data is present with no physical count") { facts.add(make_shared()); THEN("a structured fact is added, not including physical_processor_count") { REQUIRE(facts.size() == 7u); auto processors = facts.get(fact::processors); REQUIRE(processors); REQUIRE(processors->size() == 4u); auto count = processors->get("count"); REQUIRE(count); REQUIRE(count->value() == 4); auto isa = processors->get("isa"); REQUIRE(isa); REQUIRE(isa->value() == "isa"); auto models = processors->get("models"); REQUIRE(models); REQUIRE(models->size() == 4u); for (size_t i = 0; i < 4; ++i) { auto model = models->get(i); REQUIRE(model); REQUIRE(model->value() == "processor" + to_string(i + 1)); } auto speed = processors->get("speed"); REQUIRE(speed); REQUIRE(speed->value() == "10.00 GHz"); } THEN("standard flat facts are added, not including physical_processor_count") { REQUIRE(facts.size() == 7u); auto count = facts.get(fact::processor_count); REQUIRE(count); REQUIRE(count->value() == 4); auto isa = facts.get(fact::hardware_isa); REQUIRE(isa); REQUIRE(isa->value() == "isa"); for (size_t i = 0; i < 4; ++i) { auto model = facts.get(fact::processor + to_string(i)); REQUIRE(model); REQUIRE(model->value() == "processor" + to_string(i + 1)); } } } } facter-3.14.12/lib/tests/facts/resolvers/ruby_resolver.cc0000644005276200011600000000466213702047406023276 0ustar jenkinsjenkins#include #include #include #include #include #include #include "../../collection_fixture.hpp" using namespace std; using namespace facter::facts; using namespace facter::facts::resolvers; using namespace facter::testing; struct empty_ruby_resolver : ruby_resolver { protected: virtual data collect_data(collection& facts) override { return {}; } }; struct test_ruby_resolver : ruby_resolver { protected: virtual data collect_data(collection& facts) override { data result; result.platform = "i386-mingw32"; result.sitedir = "C:/Ruby21/lib/ruby/site_ruby/2.1.0"; result.version = "2.1.4"; return result; } }; SCENARIO("using the ruby resolver") { collection_fixture facts; WHEN("data is not present") { facts.add(make_shared()); THEN("facts should not be added") { REQUIRE(facts.size() == 0u); } } WHEN("data is present") { facts.add(make_shared()); THEN("a structured fact is added") { REQUIRE(facts.size() == 4u); auto ruby = facts.get(fact::ruby); REQUIRE(ruby); REQUIRE(ruby->size() == 3u); auto platform = ruby->get("platform"); REQUIRE(platform); REQUIRE(platform->value() == "i386-mingw32"); auto sitedir = ruby->get("sitedir"); REQUIRE(sitedir); REQUIRE(sitedir->value() == "C:/Ruby21/lib/ruby/site_ruby/2.1.0"); auto version = ruby->get("version"); REQUIRE(version); REQUIRE(version->value() == "2.1.4"); } THEN("flat facts are added") { REQUIRE(facts.size() == 4u); auto platform = facts.get(fact::rubyplatform); REQUIRE(platform); REQUIRE(platform->value() == "i386-mingw32"); auto sitedir = facts.get(fact::rubysitedir); REQUIRE(sitedir); REQUIRE(sitedir->value() == "C:/Ruby21/lib/ruby/site_ruby/2.1.0"); auto version = facts.get(fact::rubyversion); REQUIRE(version); REQUIRE(version->value() == "2.1.4"); } } } facter-3.14.12/lib/tests/facts/resolvers/ssh_resolver.cc0000644005276200011600000000761713702047406023115 0ustar jenkinsjenkins#include #include #include #include #include #include #include "../../collection_fixture.hpp" using namespace std; using namespace boost::filesystem; using namespace facter::facts; using namespace facter::facts::resolvers; using namespace facter::testing; struct empty_ssh_resolver : ssh_resolver { protected: data collect_data(collection& facts) override { return {}; } virtual path retrieve_key_file(std::string const& filename) override { return path(""); } }; struct test_ssh_resolver : ssh_resolver { protected: data collect_data(collection& facts) override { data result; result.dsa.key = "dsa:key"; result.dsa.type = "dsa:type"; result.dsa.digest.sha1 = "dsa:sha1"; result.dsa.digest.sha256 = "dsa:sha256"; result.ecdsa.key = "ecdsa:key"; result.ecdsa.type = "ecdsa:type"; result.ecdsa.digest.sha1 = "ecdsa:sha1"; result.ecdsa.digest.sha256 = "ecdsa:sha256"; result.ed25519.key = "ed25519:key"; result.ed25519.type = "ed25519:type"; result.ed25519.digest.sha1 = "ed25519:sha1"; result.ed25519.digest.sha256 = "ed25519:sha256"; result.rsa.key = "rsa:key"; result.rsa.type = "rsa:type"; result.rsa.digest.sha1 = "rsa:sha1"; result.rsa.digest.sha256 = "rsa:sha256"; return result; } virtual path retrieve_key_file(std::string const& filename) override { return path(filename); } }; SCENARIO("using the ssh resolver") { collection_fixture facts; WHEN("data is not present") { facts.add(make_shared()); THEN("facts should not be added") { REQUIRE(facts.size() == 0u); } } WHEN("data is present") { static const vector algorithms = { "dsa", "ecdsa", "ed25519", "rsa" }; facts.add(make_shared()); THEN("a structured fact is added") { REQUIRE(facts.size() == 9u); auto ssh = facts.get(fact::ssh); REQUIRE(ssh); REQUIRE(ssh->size() == 4u); for (auto const& algorithm : algorithms) { auto entry = ssh->get(algorithm); REQUIRE(entry); REQUIRE(entry->size() == 3u); auto key = entry->get("key"); REQUIRE(key); REQUIRE(key->value() == algorithm + ":key"); auto type = entry->get("type"); REQUIRE(type); REQUIRE(type->value() == algorithm + ":type"); auto fingerprints = entry->get("fingerprints"); REQUIRE(fingerprints); REQUIRE(fingerprints->size() == 2u); auto fingerprint = fingerprints->get("sha1"); REQUIRE(fingerprint); REQUIRE(fingerprint->value() == algorithm + ":sha1"); fingerprint = fingerprints->get("sha256"); REQUIRE(fingerprint); REQUIRE(fingerprint->value() == algorithm + ":sha256"); } } THEN("flat facts are added") { REQUIRE(facts.size() == 9u); for (auto const& algorithm : algorithms) { auto key = facts.get("ssh" + algorithm + "key"); REQUIRE(key); REQUIRE(key->value() == algorithm + ":key"); auto fingerprint = facts.get("sshfp_" + algorithm); REQUIRE(fingerprint); REQUIRE(fingerprint->value() == algorithm + ":sha1\n" + algorithm + ":sha256"); } } } } facter-3.14.12/lib/tests/facts/resolvers/system_profiler_resolver.cc0000644005276200011600000001213313702047406025533 0ustar jenkinsjenkins#include #include #include #include #include #include #include "../../collection_fixture.hpp" using namespace std; using namespace facter::facts; using namespace facter::facts::resolvers; using namespace facter::testing; struct empty_system_profiler_resolver : system_profiler_resolver { protected: virtual data collect_data(collection& facts) override { return {}; } }; struct test_system_profiler_resolver : system_profiler_resolver { protected: virtual data collect_data(collection& facts) override { data result; result.boot_mode = "boot_mode"; result.boot_rom_version = "boot_rom_version"; result.boot_volume = "boot_volume"; result.processor_name = "processor_name"; result.processor_speed = "processor_speed"; result.kernel_version = "kernel_version"; result.l2_cache_per_core = "l2_cache_per_core"; result.l3_cache = "l3_cache"; result.computer_name = "computer_name"; result.model_identifier = "model_identifier"; result.model_name = "model_name"; result.cores = "cores"; result.system_version = "system_version"; result.processors = "processors"; result.memory = "memory"; result.hardware_uuid = "hardware_uuid"; result.secure_virtual_memory = "secure_virtual_memory"; result.serial_number = "serial_number"; result.smc_version = "smc_version"; result.uptime = "uptime"; result.username = "username"; return result; } }; SCENARIO("using the system profiler resolver") { collection_fixture facts; WHEN("data is not present") { facts.add(make_shared()); THEN("facts should not be added") { REQUIRE(facts.size() == 0u); } } WHEN("data is present") { static const vector algorithms = { "dsa", "ecdsa", "ed25519", "rsa" }; facts.add(make_shared()); THEN("a structured fact is added") { auto system_profiler = facts.get(fact::system_profiler); REQUIRE(system_profiler); REQUIRE(system_profiler->size() == 21u); static const vector names = { "boot_mode", "boot_rom_version", "boot_volume", "processor_name", "processor_speed", "kernel_version", "l2_cache_per_core" , "l3_cache", "computer_name", "model_identifier", "model_name", "cores", "system_version", "processors", "memory", "hardware_uuid", "secure_virtual_memory", "serial_number", "smc_version", "uptime", "username" }; for (auto const& name : names) { auto sval = system_profiler->get(name); REQUIRE(sval); REQUIRE(sval->value() == name); } } THEN("flat facts are added") { REQUIRE(facts.size() == 22u); static const map check = { { string(fact::sp_boot_mode), "boot_mode" }, { string(fact::sp_boot_rom_version), "boot_rom_version" }, { string(fact::sp_boot_volume), "boot_volume" }, { string(fact::sp_cpu_type), "processor_name" }, { string(fact::sp_current_processor_speed), "processor_speed" }, { string(fact::sp_kernel_version), "kernel_version" }, { string(fact::sp_l2_cache_core), "l2_cache_per_core" }, { string(fact::sp_l3_cache), "l3_cache" }, { string(fact::sp_local_host_name), "computer_name" }, { string(fact::sp_machine_model), "model_identifier" }, { string(fact::sp_machine_name), "model_name" }, { string(fact::sp_number_processors), "cores" }, { string(fact::sp_os_version), "system_version" }, { string(fact::sp_packages), "processors" }, { string(fact::sp_physical_memory), "memory" }, { string(fact::sp_platform_uuid), "hardware_uuid" }, { string(fact::sp_secure_vm), "secure_virtual_memory" }, { string(fact::sp_serial_number), "serial_number" }, { string(fact::sp_smc_version_system), "smc_version" }, { string(fact::sp_uptime), "uptime" }, { string(fact::sp_user_name), "username" } }; for (auto const& kvp : check) { auto sval = facts.get(kvp.first); REQUIRE(sval); REQUIRE(sval->value() == kvp.second); } } } } facter-3.14.12/lib/tests/facts/resolvers/timezone_resolver.cc0000644005276200011600000000236513702047406024145 0ustar jenkinsjenkins#include #include #include #include #include #include "../../collection_fixture.hpp" using namespace std; using namespace facter::facts; using namespace facter::facts::resolvers; using namespace facter::testing; struct empty_timezone_resolver : timezone_resolver { protected: virtual string get_timezone() override { return {}; } }; struct test_timezone_resolver : timezone_resolver { protected: virtual string get_timezone() override { return "PDT"; } }; // TestRail C69635 SCENARIO("using the timezone resolver") { collection_fixture facts; WHEN("data is not present") { facts.add(make_shared()); THEN("facts should not be added") { REQUIRE(facts.size() == 0u); } } WHEN("data is present") { facts.add(make_shared()); THEN("a flat fact is added") { REQUIRE(facts.size() == 1u); auto timezone = facts.get(fact::timezone); REQUIRE(timezone); REQUIRE(timezone->value() == "PDT"); } } } facter-3.14.12/lib/tests/facts/resolvers/uptime_resolver.cc0000644005276200011600000001335013702047406023612 0ustar jenkinsjenkins#include #include #include #include #include #include #include "../../collection_fixture.hpp" using namespace std; using namespace facter::facts; using namespace facter::facts::resolvers; using namespace facter::testing; struct test_less_than_day_resolver : uptime_resolver { protected: virtual int64_t get_uptime() override { // 13 hours, 35 minutes, 6 seconds return (13 * 60 * 60) + (35 * 60) + 6; } }; struct test_one_day_resolver : uptime_resolver { protected: virtual int64_t get_uptime() override { // 1 day, 2 hours, 12 minutes, 22 seconds return (1 * 24 * 60 * 60) + (2 * 60 * 60) + (12 * 60) + 22; } }; struct test_more_than_day_resolver : uptime_resolver { protected: virtual int64_t get_uptime() override { // 3 day, 4 hours, 19 minutes, 45 seconds return (3 * 24 * 60 * 60) + (4 * 60 * 60) + (19 * 60) + 45; } }; SCENARIO("using the uptime resolver") { collection_fixture facts; WHEN("the uptime is less than one day") { facts.add(make_shared()); THEN("a structured fact with 'hours' uptime is added") { auto system_uptime = facts.get(fact::system_uptime); REQUIRE(system_uptime); REQUIRE(system_uptime->size() == 4u); auto time = system_uptime->get("seconds"); REQUIRE(time); REQUIRE(time->value() == 48906); time = system_uptime->get("hours"); REQUIRE(time); REQUIRE(time->value() == 13); time = system_uptime->get("days"); REQUIRE(time); REQUIRE(time->value() == 0); auto uptime = system_uptime->get("uptime"); REQUIRE(uptime); REQUIRE(uptime->value() == "13:35 hours"); } THEN("flat facts with 'hours' uptime is added") { REQUIRE(facts.size() == 5u); auto time = facts.get(fact::uptime_seconds); REQUIRE(time); REQUIRE(time->value() == 48906); time = facts.get(fact::uptime_hours); REQUIRE(time); REQUIRE(time->value() == 13); time = facts.get(fact::uptime_days); REQUIRE(time); REQUIRE(time->value() == 0); auto uptime = facts.get(fact::uptime); REQUIRE(uptime); REQUIRE(uptime->value() == "13:35 hours"); } } WHEN("the uptime is one day") { facts.add(make_shared()); THEN("a structured fact with '1 day' uptime is added") { auto system_uptime = facts.get(fact::system_uptime); REQUIRE(system_uptime); REQUIRE(system_uptime->size() == 4u); auto time = system_uptime->get("seconds"); REQUIRE(time); REQUIRE(time->value() == 94342); time = system_uptime->get("hours"); REQUIRE(time); REQUIRE(time->value() == 26); time = system_uptime->get("days"); REQUIRE(time); REQUIRE(time->value() == 1); auto uptime = system_uptime->get("uptime"); REQUIRE(uptime); REQUIRE(uptime->value() == "1 day"); } THEN("flat facts with '1 day' uptime is added") { REQUIRE(facts.size() == 5u); auto time = facts.get(fact::uptime_seconds); REQUIRE(time); REQUIRE(time->value() == 94342); time = facts.get(fact::uptime_hours); REQUIRE(time); REQUIRE(time->value() == 26); time = facts.get(fact::uptime_days); REQUIRE(time); REQUIRE(time->value() == 1); auto uptime = facts.get(fact::uptime); REQUIRE(uptime); REQUIRE(uptime->value() == "1 day"); } } WHEN("the uptime is more than one day") { facts.add(make_shared()); THEN("a structured fact with 'x days' uptime is added") { auto system_uptime = facts.get(fact::system_uptime); REQUIRE(system_uptime); REQUIRE(system_uptime->size() == 4u); auto time = system_uptime->get("seconds"); REQUIRE(time); REQUIRE(time->value() == 274785); time = system_uptime->get("hours"); REQUIRE(time); REQUIRE(time->value() == 76); time = system_uptime->get("days"); REQUIRE(time); REQUIRE(time->value() == 3); auto uptime = system_uptime->get("uptime"); REQUIRE(uptime); REQUIRE(uptime->value() == "3 days"); } THEN("flat facts with 'x days' uptime is added") { REQUIRE(facts.size() == 5u); auto time = facts.get(fact::uptime_seconds); REQUIRE(time); REQUIRE(time->value() == 274785); time = facts.get(fact::uptime_hours); REQUIRE(time); REQUIRE(time->value() == 76); time = facts.get(fact::uptime_days); REQUIRE(time); REQUIRE(time->value() == 3); auto uptime = facts.get(fact::uptime); REQUIRE(uptime); REQUIRE(uptime->value() == "3 days"); } } } facter-3.14.12/lib/tests/facts/resolvers/virtualization_resolver.cc0000644005276200011600000001277613702047406025406 0ustar jenkinsjenkins#include #include #include #include #include #include #include "../../collection_fixture.hpp" using namespace std; using namespace facter::facts; using namespace facter::facts::resolvers; using namespace facter::testing; struct empty_virtualization_resolver : virtualization_resolver { protected: string get_hypervisor(collection& facts) override { return ""; } string get_cloud_provider(collection& facts) override { return ""; } }; struct unknown_hypervisor_resolver : virtualization_resolver { protected: string get_hypervisor(collection& facts) override { return "foobar"; } string get_cloud_provider(collection& facts) override { return "provider"; } }; struct unknown_non_virtual_hypervisor_resolver : virtualization_resolver { protected: string get_hypervisor(collection& facts) override { return "foobar"; } string get_cloud_provider(collection& facts) override { return "provider"; } bool is_virtual(string const& hypervisor) override { return hypervisor != "foobar"; } }; struct known_hypervisor_resolver : virtualization_resolver { protected: string get_hypervisor(collection& facts) override { return vm::docker; } string get_cloud_provider(collection& facts) override { return "provider"; } }; struct matched_product_hypervisor_resolver : virtualization_resolver { protected: string get_hypervisor(collection& facts) override { facts.add(fact::product_name, make_value("VMware")); auto result = get_fact_vm(facts); facts.remove(fact::product_name); return result; } string get_cloud_provider(collection& facts) override { return "provider"; } }; struct matched_vendor_hypervisor_resolver : virtualization_resolver { protected: string get_hypervisor(collection& facts) override { facts.add(fact::bios_vendor, make_value("Amazon EC2")); auto result = get_fact_vm(facts); facts.remove(fact::bios_vendor); return result; } string get_cloud_provider(collection& facts) override { return "provider"; } }; SCENARIO("using the virtualization resolver") { collection_fixture facts; WHEN("no hypervisor is returned") { facts.add(make_shared()); THEN("the system is reported as physical") { REQUIRE(facts.size() == 2u); auto is_virt = facts.get(fact::is_virtual); REQUIRE(is_virt); REQUIRE_FALSE(is_virt->value()); auto hypervisor = facts.get(fact::virtualization); REQUIRE(hypervisor); REQUIRE(hypervisor->value() == "physical"); } } WHEN("an unknown virtual hypervisor is returned") { facts.add(make_shared()); THEN("the system is reported as virtual") { REQUIRE(facts.size() == 3u); auto is_virt = facts.get(fact::is_virtual); REQUIRE(is_virt); REQUIRE(is_virt->value()); auto hypervisor = facts.get(fact::virtualization); REQUIRE(hypervisor); REQUIRE(hypervisor->value() == "foobar"); } } WHEN("an unknown physical hypervisor is returned") { facts.add(make_shared()); THEN("the system is reported as virtual") { REQUIRE(facts.size() == 3u); auto is_virt = facts.get(fact::is_virtual); REQUIRE(is_virt); REQUIRE_FALSE(is_virt->value()); auto hypervisor = facts.get(fact::virtualization); REQUIRE(hypervisor); REQUIRE(hypervisor->value() == "foobar"); } } WHEN("a known hypervisor is returned") { facts.add(make_shared()); THEN("the system is reported as virtual") { REQUIRE(facts.size() == 3u); auto is_virt = facts.get(fact::is_virtual); REQUIRE(is_virt); REQUIRE(is_virt->value()); auto hypervisor = facts.get(fact::virtualization); REQUIRE(hypervisor); REQUIRE(hypervisor->value() == string(vm::docker)); } } WHEN("a hypervisor is matched from product name") { facts.add(make_shared()); THEN("the system is reported as virtual") { REQUIRE(facts.size() == 3u); auto is_virt = facts.get(fact::is_virtual); REQUIRE(is_virt); REQUIRE(is_virt->value()); auto hypervisor = facts.get(fact::virtualization); REQUIRE(hypervisor); REQUIRE(hypervisor->value() == string(vm::vmware)); } } WHEN("a hypervisor is matched from the vendor name") { facts.add(make_shared()); auto is_virt = facts.get(fact::is_virtual); REQUIRE(is_virt); REQUIRE(is_virt->value()); auto hypervisor = facts.get(fact::virtualization); REQUIRE(hypervisor); REQUIRE(hypervisor->value() == string(vm::kvm)); } } facter-3.14.12/lib/tests/facts/resolvers/xen_resolver.cc0000644005276200011600000000555713702047406023113 0ustar jenkinsjenkins#include #include #include #include #include #include #include #include #include "../../collection_fixture.hpp" using namespace std; using namespace facter::facts; using namespace facter::facts::resolvers; using namespace facter::testing; struct empty_xen_resolver : xen_resolver { protected: virtual string xen_command() override { return ""; } virtual data collect_data(collection& facts) override { data result; return result; } }; struct test_xen_resolver : xen_resolver { protected: virtual string xen_command() override { return ""; } virtual data collect_data(collection& facts) override { data result; result.domains = { "domain1", "domain2" }; return result; } }; // CATCH doesn't behave well with constexpr, so create memory for // the string here before using it in the test. constexpr static char const* xen_privileged = vm::xen_privileged; SCENARIO("using the Xen resolver on a privileged VM") { collection_fixture facts; facts.add(fact::virtualization, make_value(xen_privileged)); WHEN("data is not present") { facts.add(make_shared()); THEN("facts should not be added") { REQUIRE(facts.size() == 1u); } } WHEN("data is present") { facts.add(make_shared()); THEN("flat facts are added") { REQUIRE(facts.size() == 3u); auto value = facts.get(fact::xendomains); REQUIRE(value); REQUIRE(value->value() == "domain1,domain2"); } THEN("structured facts are added") { REQUIRE(facts.size() == 3u); auto xen = facts.get(fact::xen); REQUIRE(xen); REQUIRE(xen->size() == 1u); auto domains = xen->get("domains"); REQUIRE(domains); REQUIRE(domains->size() == 2u); for (size_t i = 0; i < 2; ++i) { auto domain = domains->get(i); REQUIRE(domain); REQUIRE(domain->value() == "domain" + to_string(i+1)); } } } } SCENARIO("using the Xen resolver on an unprivileged machine") { collection_fixture facts; WHEN("data is not present") { facts.add(make_shared()); THEN("facts should not be added") { REQUIRE(facts.size() == 0u); } } WHEN("data is present") { facts.add(make_shared()); THEN("facts should not be added") { REQUIRE(facts.size() == 0u); } } } facter-3.14.12/lib/tests/facts/resolvers/zfs_resolver.cc0000644005276200011600000000316113702047406023110 0ustar jenkinsjenkins#include #include #include #include #include #include "../../collection_fixture.hpp" using namespace std; using namespace facter::facts; using namespace facter::facts::resolvers; using namespace facter::testing; struct empty_zfs_resolver : zfs_resolver { protected: virtual string zfs_command() override { return ""; } virtual data collect_data(collection& facts) override { data result; return result; } }; struct test_zfs_resolver : zfs_resolver { protected: virtual string zfs_command() override { return ""; } virtual data collect_data(collection& facts) override { data result; result.version = "1"; result.versions = { "1", "2", "3" }; return result; } }; SCENARIO("using the ZFS resolver") { collection_fixture facts; WHEN("data is not present") { facts.add(make_shared()); THEN("facts should not be added") { REQUIRE(facts.size() == 0u); } } WHEN("data is present") { facts.add(make_shared()); THEN("flat facts are added") { REQUIRE(facts.size() == 2u); auto value = facts.get(fact::zfs_version); REQUIRE(value); REQUIRE(value->value() == "1"); value = facts.get(fact::zfs_versionnumbers); REQUIRE(value); REQUIRE(value->value() == "1,2,3"); } } } facter-3.14.12/lib/tests/facts/resolvers/zone_resolver.cc0000644005276200011600000001041613702047406023262 0ustar jenkinsjenkins#include #include #include #include #include #include #include "../../collection_fixture.hpp" using namespace std; using namespace facter::facts; using namespace facter::facts::resolvers; using namespace facter::testing; struct empty_zone_resolver : zone_resolver { protected: virtual data collect_data(collection& facts) override { data result; return result; } }; struct test_zone_resolver : zone_resolver { protected: virtual data collect_data(collection& facts) override { data result; result.current_zone_name = "current"; zone z; z.uuid = "uuid"; z.status = "status"; z.path = "path"; z.name = "name"; z.brand = "brand"; z.id = "id"; z.ip_type = "ip type"; result.zones.emplace_back(move(z)); return result; } }; SCENARIO("using the Solaris zone resolver") { collection_fixture facts; WHEN("data is not present") { facts.add(make_shared()); THEN("only the zone count should be added") { REQUIRE(facts.size() == 1u); auto value = facts.get(fact::zones); REQUIRE(value); REQUIRE(value->value() == 0); } } WHEN("data is present") { facts.add(make_shared()); THEN("a structured fact is added") { REQUIRE(facts.size() == 10u); auto mval = facts.get(fact::solaris_zones); REQUIRE(mval); REQUIRE(mval->size() == 2u); auto sval = mval->get("current"); REQUIRE(sval); REQUIRE(sval->value() == "current"); mval = mval->get("zones"); REQUIRE(mval); REQUIRE(mval->size() == 1u); mval = mval->get("name"); REQUIRE(mval); REQUIRE(mval->size() == 6u); sval = mval->get("uuid"); REQUIRE(sval); REQUIRE(sval->value() == "uuid"); sval = mval->get("status"); REQUIRE(sval); REQUIRE(sval->value() == "status"); sval = mval->get("path"); REQUIRE(sval); REQUIRE(sval->value() == "path"); sval = mval->get("brand"); REQUIRE(sval); REQUIRE(sval->value() == "brand"); sval = mval->get("id"); REQUIRE(sval); REQUIRE(sval->value() == "id"); sval = mval->get("ip_type"); REQUIRE(sval); REQUIRE(sval->value() == "ip type"); } THEN("flat facts are added") { REQUIRE(facts.size() == 10u); auto ival = facts.get(fact::zones); REQUIRE(ival); REQUIRE(ival->value() == 1); auto sval = facts.get(fact::zonename); REQUIRE(sval); REQUIRE(sval->value() == "current"); sval = facts.get(string("zone_name_") + fact::zone_iptype); REQUIRE(sval); REQUIRE(sval->value() == "ip type"); sval = facts.get(string("zone_name_") + fact::zone_brand); REQUIRE(sval); REQUIRE(sval->value() == "brand"); sval = facts.get(string("zone_name_") + fact::zone_uuid); REQUIRE(sval); REQUIRE(sval->value() == "uuid"); sval = facts.get(string("zone_name_") + fact::zone_id); REQUIRE(sval); REQUIRE(sval->value() == "id"); sval = facts.get(string("zone_name_") + fact::zone_name); REQUIRE(sval); REQUIRE(sval->value() == "name"); sval = facts.get(string("zone_name_") + fact::zone_path); REQUIRE(sval); REQUIRE(sval->value() == "path"); sval = facts.get(string("zone_name_") + fact::zone_status); REQUIRE(sval); REQUIRE(sval->value() == "status"); } } } facter-3.14.12/lib/tests/facts/resolvers/zpool_resolver.cc0000644005276200011600000000362013702047406023451 0ustar jenkinsjenkins#include #include #include #include #include #include "../../collection_fixture.hpp" using namespace std; using namespace facter::facts; using namespace facter::facts::resolvers; using namespace facter::testing; struct empty_zpool_resolver : zpool_resolver { protected: virtual string zpool_command() override { return ""; } virtual data collect_data(collection& facts) override { data result; return result; } }; struct test_zpool_resolver : zpool_resolver { protected: virtual string zpool_command() override { return ""; } virtual data collect_data(collection& facts) override { data result; result.version = "1"; result.versions = { "1", "2", "3" }; result.feature_flags = { "async_destroy", "lz4_compress", "enabled_txg" }; return result; } }; SCENARIO("using the zpool resolver") { collection_fixture facts; WHEN("data is not present") { facts.add(make_shared()); THEN("facts should not be added") { REQUIRE(facts.size() == 0u); } } WHEN("data is present") { facts.add(make_shared()); THEN("flat facts are added") { REQUIRE(facts.size() == 3u); auto value = facts.get(fact::zpool_version); REQUIRE(value); REQUIRE(value->value() == "1"); value = facts.get(fact::zpool_versionnumbers); REQUIRE(value); REQUIRE(value->value() == "1,2,3"); value = facts.get(fact::zpool_featureflags); REQUIRE(value); REQUIRE(value->value() == "async_destroy,lz4_compress,enabled_txg"); } } } facter-3.14.12/lib/tests/facts/schema.cc0000644005276200011600000006476013702047406017615 0ustar jenkinsjenkins#include #include #include #include #include #include #include #include #include #include #include #include "../fixtures.hpp" // Include all base resolvers here #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include using namespace std; using namespace boost::filesystem; using namespace facter::facts; using namespace leatherman::util; using namespace facter::testing; using Catch::Matchers::AnyOf; // For every base resolver, implement a resolver that outputs the minimum values to pass schema validation // We don't care about the actual data in the facts, only that it conforms to the schema struct augeas_resolver : resolvers::augeas_resolver { protected: virtual string get_version() override { return "1.1.0"; } }; struct disk_resolver : resolvers::disk_resolver { protected: virtual data collect_data(collection& facts) override { data result; result.disks.push_back({ "name", "vendor", "model", "product", 1234, "serial_number" }); return result; } }; struct dmi_resolver : resolvers::dmi_resolver { protected: virtual data collect_data(collection& facts) override { data result; result.bios_vendor = fact::bios_vendor; result.bios_version = fact::bios_version; result.bios_release_date = fact::bios_release_date; result.board_asset_tag = fact::board_asset_tag; result.board_manufacturer = fact::board_manufacturer; result.board_product_name = fact::board_product_name; result.board_serial_number = fact::board_serial_number; result.chassis_asset_tag = fact::chassis_asset_tag; result.manufacturer = fact::manufacturer; result.product_name = fact::product_name; result.serial_number = fact::serial_number; result.uuid = fact::uuid; result.chassis_type = fact::chassis_type; return result; } }; struct ec2_resolver : resolvers::ec2_resolver { void resolve(collection& facts) override { facts.add(fact::ec2_metadata, make_value()); facts.add(fact::ec2_userdata, make_value("user data")); } }; struct filesystem_resolver : resolvers::filesystem_resolver { protected: virtual data collect_data(collection& facts) override { data result; mountpoint mp; mp.name = "name"; mp.device = "device"; mp.filesystem = "filesystem"; mp.size = 1234; mp.available = 12345; mp.options.push_back("option"); result.mountpoints.emplace_back(move(mp)); result.filesystems.insert("filesystem"); partition p; p.name = "name"; p.filesystem = "filesystem"; p.size = 1234; p.uuid = "uuid"; p.partition_uuid = "partuuid"; p.label = "label"; p.partition_label = "partlabel"; p.mount = "mount"; p.backing_file = "/foo/bar"; result.partitions.emplace_back(move(p)); return result; } }; struct fips_resolver : resolvers::fips_resolver { protected: virtual data collect_data(collection& facts) override { data result; result.is_fips_mode_enabled = false; return result; } }; using hypervisor_data = std::unordered_map>>; struct hypervisors_resolver_test : resolvers::hypervisors_resolver_base { virtual hypervisor_data collect_data(collection& facts) { hypervisor_data results; unordered_map> metadata { {"string_value", string{"string"}}, // boost assumes const char* values are bools when bool is among the variants {"integer_value", 42}, {"boolean_value", true}, }; results.insert({"hypervisor_name", metadata}); return results; } }; struct identity_resolver : resolvers::identity_resolver { protected: virtual data collect_data(collection& facts) override { data result; result.group_id = 123; result.group_name = "group"; result.user_id = 456; result.user_name = "user"; result.privileged = false; return result; } }; struct kernel_resolver : resolvers::kernel_resolver { protected: virtual data collect_data(collection& facts) override { data result; result.name = "kernel"; result.release = "1.2.3-kernel"; result.version = "1.2.3"; return result; } }; struct load_average_resolver : resolvers::load_average_resolver { protected: virtual boost::optional > get_load_averages() override { return make_tuple(0.12, 3.45, 6.78); } }; struct memory_resolver : resolvers::memory_resolver { protected: virtual data collect_data(collection& facts) override { data result; result.swap_encryption = encryption_status::encrypted; result.mem_total = 10 * 1024 * 1024; result.mem_free = 5 * 1024 * 1024; result.swap_total = 20 * 1024 * 1024; result.swap_free = 4 * 1024 * 1024; return result; } }; struct networking_resolver : resolvers::networking_resolver { protected: virtual data collect_data(collection& facts) override { data result; result.hostname = "hostname"; result.domain = "domain"; result.fqdn = "hostname.domain"; result.primary_interface = "interface1"; interface iface; iface.name = "interface1"; iface.dhcp_server = "192.168.1.1"; iface.ipv4_bindings.emplace_back(binding { "127.0.0.1", "255.0.0.0", "127.0.0.0"}); iface.ipv4_bindings.emplace_back(binding { "123.123.123.123", "255.255.255.0", "123.123.123.0"}); iface.ipv6_bindings.emplace_back(binding { "fe80::1", "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff", "::1"}); iface.ipv6_bindings.emplace_back(binding { "fe80::2", "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff", "::2"}); iface.macaddress = "00:00:00:00:00:00"; iface.mtu = 12345; result.interfaces.emplace_back(move(iface)); return result; } }; struct operating_system_resolver : resolvers::operating_system_resolver { protected: virtual data collect_data(collection& facts) override { data result; result.name = "name"; result.family = "family"; result.release = "1.2.3"; result.major = "1.2"; result.minor = "3"; result.specification_version = "1.4"; result.distro.id = "id"; result.distro.release = "1.2.3"; result.distro.codename = "codename"; result.distro.description = "description"; result.freebsd.branch = "BRANCH"; result.freebsd.patchlevel = "4"; result.osx.product = "product"; result.osx.build = "build"; result.osx.version = "10.10"; result.win.release_id = "1904"; result.win.edition_id = "ServerStandard"; result.win.installation_type = "Server"; result.win.product_name = "Windows 2019 Standard Edition"; result.win.system32 = "system32"; result.architecture = "arch"; result.hardware = "hardware"; result.selinux.supported = true; result.selinux.enabled = true; result.selinux.enforced = true; result.selinux.current_mode = "current mode"; result.selinux.config_mode = "config mode"; result.selinux.config_policy = "config policy"; result.selinux.policy_version = "policy version"; return result; } }; struct processor_resolver : resolvers::processor_resolver { protected: virtual data collect_data(collection& facts) override { data result; result.isa = "isa"; result.logical_count = 4; result.physical_count = 2; result.models = { "processor1", "processor2", "processor3", "processor4" }; result.speed = 10 * 1000 * 1000 * 1000ull; return result; } }; struct ruby_resolver : resolvers::ruby_resolver { protected: virtual data collect_data(collection& facts) override { data result; result.platform = "platform"; result.sitedir = "sitedir"; result.version = "2.1.5"; return result; } }; struct ssh_resolver : resolvers::ssh_resolver { protected: data collect_data(collection& facts) override { data result; result.dsa.key = "dsa:key"; result.dsa.type = "dsa:type"; result.dsa.digest.sha1 = "dsa:sha1"; result.dsa.digest.sha256 = "dsa:sha256"; result.ecdsa.key = "ecdsa:key"; result.ecdsa.type = "ecdsa:type"; result.ecdsa.digest.sha1 = "ecdsa:sha1"; result.ecdsa.digest.sha256 = "ecdsa:sha256"; result.ed25519.key = "ed25519:key"; result.ed25519.type = "ed25519:type"; result.ed25519.digest.sha1 = "ed25519:sha1"; result.ed25519.digest.sha256 = "ed25519:sha256"; result.rsa.key = "rsa:key"; result.rsa.type = "rsa:type"; result.rsa.digest.sha1 = "rsa:sha1"; result.rsa.digest.sha256 = "rsa:sha256"; return result; } virtual path retrieve_key_file(std::string const& filename) override { return path(filename); } }; struct system_profiler_resolver : resolvers::system_profiler_resolver { protected: virtual data collect_data(collection& facts) override { data result; result.boot_mode = "boot_mode"; result.boot_rom_version = "boot_rom_version"; result.boot_volume = "boot_volume"; result.processor_name = "processor_name"; result.processor_speed = "processor_speed"; result.kernel_version = "kernel_version"; result.l2_cache_per_core = "l2_cache_per_core"; result.l3_cache = "l3_cache"; result.computer_name = "computer_name"; result.model_identifier = "model_identifier"; result.model_name = "model_name"; result.cores = "cores"; result.system_version = "system_version"; result.processors = "processors"; result.memory = "memory"; result.hardware_uuid = "hardware_uuid"; result.secure_virtual_memory = "secure_virtual_memory"; result.serial_number = "serial_number"; result.smc_version = "smc_version"; result.uptime = "uptime"; result.username = "username"; return result; } }; struct timezone_resolver : resolvers::timezone_resolver { protected: virtual string get_timezone() override { return "PDT"; } }; struct uptime_resolver : resolvers::uptime_resolver { protected: virtual int64_t get_uptime() override { return 1; } }; struct virtualization_resolver : resolvers::virtualization_resolver { protected: virtual string get_hypervisor(collection& facts) override { // The xen fact only resolves if virtualization is xen_privileged. return vm::xen_privileged; } virtual string get_cloud_provider(collection& facts) override { return "azure"; } }; struct xen_resolver : resolvers::xen_resolver { protected: virtual string xen_command() override { return ""; } virtual data collect_data(collection& facts) override { data result; result.domains = { "domain1", "domain2" }; return result; } }; struct zfs_resolver : resolvers::zfs_resolver { protected: virtual string zfs_command() override { return ""; } virtual data collect_data(collection& facts) override { data result; result.version = 1; result.versions = { "1", "2", "3" }; return result; } }; struct zone_resolver : resolvers::zone_resolver { protected: virtual data collect_data(collection& facts) override { data result; zone z; z.brand = "brand"; z.id = "id"; z.ip_type = "ip type"; z.name = "name"; z.path = "path"; z.status = "status"; z.uuid = "uuid"; result.zones.emplace_back(move(z)); result.current_zone_name = "name"; return result; } }; struct zpool_resolver : resolvers::zpool_resolver { protected: virtual string zpool_command() override { return ""; } virtual data collect_data(collection& facts) override { data result; result.version = 1; result.versions = { "1", "2", "3" }; result.feature_flags = { "async_destroy", "lz4_compress", "enabled_txg" }; return result; } }; void add_all_facts(collection& facts) { facts.add("env_windows_installdir", make_value("C:\\Program Files\\Some\\Path")); facts.add("facterversion", make_value("version")); facts.add("aio_agent_version", make_value("")); facts.add(make_shared()); facts.add(make_shared()); facts.add(make_shared()); facts.add(make_shared()); facts.add(make_shared()); // TODO: refactor the EC2 resolver to use the "collect_data" pattern facts.add(make_shared()); // TODO: refactor the GCE resolver to use the "collect_data" pattern facts.add(make_shared()); facts.add(fact::gce, make_value()); facts.add(make_shared()); facts.add(make_shared()); facts.add(fact::ldom, make_value()); facts.add("ldom_domainname", make_value("somedomain", true)); facts.add(make_shared()); facts.add(make_shared()); facts.add(make_shared()); facts.add(make_shared()); facts.add(make_shared()); facts.add(make_shared()); facts.add(make_shared()); facts.add(make_shared()); facts.add(make_shared()); facts.add(make_shared()); facts.add(make_shared()); facts.add(make_shared()); facts.add(make_shared()); facts.add(make_shared()); facts.add(make_shared()); facts.add(make_shared()); } void validate_attributes(YAML::Node const& node) { REQUIRE(node.IsMap()); for (auto const& attribute : node) { auto attribute_name = attribute.first.as(); CAPTURE(attribute_name); REQUIRE_THAT(attribute_name, Catch::Equals("pattern") || Catch::Equals("type") || Catch::Equals("hidden") || Catch::Equals("description") || Catch::Equals("resolution") || Catch::Equals("caveats") || Catch::Equals("elements") || Catch::Equals("validate") || Catch::Equals("blockgroup")); } // If pattern is present, it must be a non-empty string auto pattern_attribute = node["pattern"]; if (pattern_attribute) { REQUIRE(pattern_attribute.IsScalar()); auto pattern = pattern_attribute.as(); REQUIRE_FALSE(pattern.empty()); } // Node must have a type attribute auto type_attribute = node["type"]; REQUIRE(type_attribute); REQUIRE(type_attribute.IsScalar()); auto type = type_attribute.as(); REQUIRE_THAT(type, Catch::Equals("integer") || Catch::Equals("double") || Catch::Equals("string") || Catch::Equals("boolean") || Catch::Equals("array") || Catch::Equals("map") || Catch::Equals("ip") || Catch::Equals("ip6") || Catch::Equals("mac")); // Check map types auto elements = node["elements"]; if (type == "map") { // If the validate attribute is present, it must be true or false auto validate_attribute = node["validate"]; string validate = "true"; if (validate_attribute) { REQUIRE(validate_attribute.IsScalar()); validate = validate_attribute.as(); REQUIRE_THAT(validate, AnyOf(Catch::Equals("true"), Catch::Equals("false"))); } // Validated map values must have elements if (validate == "true") { REQUIRE(elements); REQUIRE(elements.IsMap()); } } else { REQUIRE_FALSE(elements); // There should not be a validate attribute auto validate_attribute = node["validate"]; REQUIRE_FALSE(validate_attribute); } // If hidden is present, it must be a boolean auto hidden_attribute = node["hidden"]; if (hidden_attribute) { REQUIRE(hidden_attribute.IsScalar()); auto hidden = hidden_attribute.as(); REQUIRE_THAT(hidden, AnyOf(Catch::Equals("true"), Catch::Equals("false"))); } // Node must have a description attribute auto description_attribute = node["description"]; REQUIRE(description_attribute); REQUIRE(description_attribute.IsScalar()); auto description = description_attribute.as(); REQUIRE_FALSE(description.empty()); // If the resolutions is present, it must be a non-empty string auto resolutions_attribute = node["resolutions"]; if (resolutions_attribute) { REQUIRE(resolutions_attribute.IsScalar()); auto resolutions = resolutions_attribute.as(); REQUIRE_FALSE(resolutions.empty()); } // If the caveats are present, it must be a non-empty string auto caveats_attribute = node["caveats"]; if (caveats_attribute) { REQUIRE(caveats_attribute.IsScalar()); auto caveats = caveats_attribute.as(); REQUIRE_FALSE(caveats.empty()); } auto blockgroup_attribute = node["blockgroup"]; if (blockgroup_attribute) { REQUIRE(blockgroup_attribute.IsScalar()); auto blockgroup = blockgroup_attribute.as(); REQUIRE_FALSE(blockgroup.empty()); } // Recurse on elements if (elements) { for (auto const& element : elements) { auto element_name = element.first.as(); CAPTURE(element_name); validate_attributes(element.second); } } } YAML::Node find_child(YAML::Node const& node, string const& name, set& found) { REQUIRE(node.IsMap()); for (auto const& child : node) { auto child_name = child.first.as(); auto pattern_attribute = child.second["pattern"]; if ((pattern_attribute && re_search(name, boost::regex(pattern_attribute.as()))) || child_name == name) { found.insert(move(child_name)); return child.second; } } return YAML::Node(YAML::NodeType::Undefined); } void validate_fact(YAML::Node const& node, value const* fact_value, bool require_all_elements) { REQUIRE(node.IsMap()); // Ensure the types match auto type_attribute = node["type"]; auto expected_type = type_attribute.as(); string type; string_value const* svalue = nullptr; map_value const* map = nullptr; if (dynamic_cast(fact_value)) { type = "integer"; } else if (dynamic_cast(fact_value)) { type = "double"; } else if ((svalue = dynamic_cast(fact_value))) { type = "string"; // Check for special string types; sourced from http://stackoverflow.com/a/17871737 static boost::regex ip_pattern("^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$"); static boost::regex ip6_pattern("^(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]))$"); static boost::regex mac_pattern("^(([0-9a-fA-F]){2}\\:){5}([0-9a-fA-F]){2}$"); if (expected_type == "ip" && re_search(svalue->value(), ip_pattern)) { type = "ip"; } else if (expected_type == "ip6" && re_search(svalue->value(), ip6_pattern)) { type = "ip6"; } else if (expected_type == "mac" && re_search(svalue->value(), mac_pattern)) { type = "mac"; } } else if (dynamic_cast(fact_value)) { type = "boolean"; } else if (dynamic_cast(fact_value)) { type = "array"; } else if ((map = dynamic_cast(fact_value))) { type = "map"; } else { FAIL("unexpected fact value type"); } REQUIRE(type == expected_type); // Ensure the value is hidden according to the schema auto hidden_attribute = node["hidden"]; bool expected_hidden = hidden_attribute && hidden_attribute.as() == "true"; bool hidden = fact_value->hidden(); REQUIRE(hidden == expected_hidden); // Recurse on map elements if (map) { auto elements = node["elements"]; // Validate the map's elements "validate" is unset or true auto validate_attribute = node["validate"]; if (!validate_attribute || validate_attribute.as() == "true") { set found; map->each([&](string const& element_name, value const* element_value) { if (!element_value) { return true; } CAPTURE(element_name); auto element = find_child(elements, element_name, found); REQUIRE(element); validate_fact(element, element_value, require_all_elements); return true; }); // Require all elements were found if (require_all_elements) { REQUIRE(found.size() == elements.size()); } } } } // TestRail C62454 SCENARIO("validating schema") { boost::nowide::ifstream stream(LIBFACTER_TESTS_DIRECTORY "/../schema/facter.yaml"); YAML::Node schema = YAML::Load(stream); collection_fixture facts; WHEN("validating the schema itself") { THEN("all attributes must be valid") { for (auto const& fact : schema) { auto fact_name = fact.first.as(); CAPTURE(fact_name); validate_attributes(fact.second); } } } WHEN("validating a fact collection") { THEN("all facts must conform to the schema") { add_all_facts(facts); set found; facts.each([&](string const& fact_name, value const* fact_value) { if (!fact_value) { return true; } CAPTURE(fact_name); auto fact = find_child(schema, fact_name, found); REQUIRE(fact); validate_fact(fact, fact_value, true); return true; }); // Require all elements in the schema were found REQUIRE(found.size() == schema.size()); } THEN("the current platform's facts must conform to the schema") { facts.add_default_facts(true); set found; facts.each([&](string const& fact_name, value const* fact_value) { if (!fact_value) { return true; } CAPTURE(fact_name); auto fact = find_child(schema, fact_name, found); REQUIRE(fact); validate_fact(fact, fact_value, false); return true; }); } THEN("blocked facts are not resolved") { set blocked_facts; set blockgroups; for (auto const& fact : schema) { auto fact_name = fact.first.as(); auto blockgroup = fact.second["blockgroup"]; if (blockgroup) { blockgroups.insert(blockgroup.as()); blocked_facts.insert(fact_name); } } collection_fixture with_blocked(blockgroups); add_all_facts(with_blocked); with_blocked.resolve_facts(); for (auto const& fact : blocked_facts) { CAPTURE(fact); REQUIRE_FALSE(with_blocked.get(fact)); } } } } facter-3.14.12/lib/tests/facts/string_value.cc0000644005276200011600000002214213702047406021043 0ustar jenkinsjenkins#include #include #include #include #include using namespace std; using namespace facter::facts; using namespace rapidjson; using namespace YAML; SCENARIO("using a string fact value") { GIVEN("a value to copy") { string s = "hello world"; string_value value(s); THEN("the value is copied") { REQUIRE(s == "hello world"); REQUIRE(value.value() == "hello world"); } } GIVEN("a value to move") { string s = "hello world"; string_value value(std::move(s)); THEN("the value is moved") { REQUIRE(s.empty()); REQUIRE(value.value() == "hello world"); } } GIVEN("a simple string value") { string_value value("foobar"); WHEN("serialized to JSON") { THEN("it should have the same value") { json_value json; json_allocator allocator; value.to_json(allocator, json); REQUIRE(json.IsString()); REQUIRE(json.GetString() == string("foobar")); } } WHEN("serialized to YAML") { THEN("it should have the same value") { Emitter emitter; value.write(emitter); REQUIRE(string(emitter.c_str()) == "foobar"); } } WHEN("serialized to text with quotes") { THEN("it should be quoted") { ostringstream stream; value.write(stream); REQUIRE(stream.str() == "\"foobar\""); } } WHEN("serialized to text without quotes") { THEN("it should not be quoted") { ostringstream stream; value.write(stream, false); REQUIRE(stream.str() == "foobar"); } } } GIVEN("an ipv6 address string value ending with ':'") { string_value value("fe80::"); WHEN("serialized to JSON") { THEN("it should have the same value") { json_value json; json_allocator allocator; value.to_json(allocator, json); REQUIRE(json.IsString()); REQUIRE(json.GetString() == string("fe80::")); } } WHEN("serialized to YAML") { THEN("it should be quoted") { Emitter emitter; value.write(emitter); REQUIRE(string(emitter.c_str()) == "\"fe80::\""); } } WHEN("serialized to text with quotes") { THEN("it should be quoted") { ostringstream stream; value.write(stream); REQUIRE(stream.str() == "\"fe80::\""); } } WHEN("serialized to text without quotes") { THEN("it should not be quoted") { ostringstream stream; value.write(stream, false); REQUIRE(stream.str() == "fe80::"); } } } GIVEN("an ipv4 address string value") { string_value value("127.254.3.0"); WHEN("serialized to JSON") { THEN("it should have the same value") { json_value json; json_allocator allocator; value.to_json(allocator, json); REQUIRE(json.IsString()); REQUIRE(json.GetString() == string("127.254.3.0")); } } WHEN("serialized to YAML") { THEN("it should have the same value") { Emitter emitter; value.write(emitter); REQUIRE(string(emitter.c_str()) == "127.254.3.0"); } } WHEN("serialized to text with quotes") { THEN("it should be quoted") { ostringstream stream; value.write(stream); REQUIRE(stream.str() == "\"127.254.3.0\""); } } WHEN("serialized to text without quotes") { THEN("it should not be quoted") { ostringstream stream; value.write(stream, false); REQUIRE(stream.str() == "127.254.3.0"); } } } GIVEN("a ':' prefixed string value") { string_value value("::1"); WHEN("serialized to JSON") { THEN("it should have the same value") { json_value json; json_allocator allocator; value.to_json(allocator, json); REQUIRE(json.IsString()); REQUIRE(json.GetString() == string("::1")); } } WHEN("serialized to YAML") { THEN("it should be quoted") { Emitter emitter; value.write(emitter); REQUIRE(string(emitter.c_str()) == "\"::1\""); } } WHEN("serialized to text with quotes") { THEN("it should be quoted") { ostringstream stream; value.write(stream); REQUIRE(stream.str() == "\"::1\""); } } WHEN("serialized to text without quotes") { THEN("it should not be quoted") { ostringstream stream; value.write(stream, false); REQUIRE(stream.str() == "::1"); } } } GIVEN("a valid mac address") { string_value value("00:50:56:55:42:45"); WHEN("serialized to JSON") { THEN("it should have the same value") { json_value json; json_allocator allocator; value.to_json(allocator, json); REQUIRE(json.IsString()); REQUIRE(json.GetString() == string("00:50:56:55:42:45")); } } WHEN("serialized to YAML") { THEN("it should be quoted") { Emitter emitter; value.write(emitter); REQUIRE(string(emitter.c_str()) == "\"00:50:56:55:42:45\""); } } WHEN("serialized to text with quotes") { THEN("it should be quoted") { ostringstream stream; value.write(stream); REQUIRE(stream.str() == "\"00:50:56:55:42:45\""); } } WHEN("serialized to text without quotes") { THEN("it should not be quoted") { ostringstream stream; value.write(stream, false); REQUIRE(stream.str() == "00:50:56:55:42:45"); } } } GIVEN("a list of numbers") { string_value value("1,2,3,4,5"); WHEN("serialized to JSON") { THEN("it should have the same value") { json_value json; json_allocator allocator; value.to_json(allocator, json); REQUIRE(json.IsString()); REQUIRE(json.GetString() == string("1,2,3,4,5")); } } WHEN("serialized to YAML") { THEN("it should be quoted") { Emitter emitter; value.write(emitter); REQUIRE(string(emitter.c_str()) == "\"1,2,3,4,5\""); } } WHEN("serialized to text with quotes") { THEN("it should be quoted") { ostringstream stream; value.write(stream); REQUIRE(stream.str() == "\"1,2,3,4,5\""); } } WHEN("serialized to text without quotes") { THEN("it should not be quoted") { ostringstream stream; value.write(stream, false); REQUIRE(stream.str() == "1,2,3,4,5"); } } } GIVEN("a boolean value") { for (auto literal : {string("true"), string("false"), string("yes"), string("no")}) { auto value = string_value(literal); WHEN("serialized to JSON") { THEN("it should have the same value") { json_value json; json_allocator allocator; value.to_json(allocator, json); REQUIRE(json.IsString()); REQUIRE(json.GetString() == literal); } } WHEN("serialized to YAML") { THEN("it should be quoted") { Emitter emitter; value.write(emitter); REQUIRE(string(emitter.c_str()) == "\""+literal+"\""); } } WHEN("serialized to text with quotes") { THEN("it should be quoted") { ostringstream stream; value.write(stream); REQUIRE(stream.str() == "\""+literal+"\""); } } WHEN("serialized to text without quotes") { THEN("it should not be quoted") { ostringstream stream; value.write(stream, false); REQUIRE(stream.str() == literal); } } } } } facter-3.14.12/lib/tests/facts/windows/0000755005276200011600000000000013702047635017527 5ustar jenkinsjenkinsfacter-3.14.12/lib/tests/facts/windows/collection.cc0000644005276200011600000000500013702047406022160 0ustar jenkinsjenkins#include #include #include #include #include #include #include "../../fixtures.hpp" #include using namespace std; using namespace facter::facts; using namespace facter::testing; SCENARIO("resolving external executable facts into a collection") { collection_fixture facts; REQUIRE(facts.size() == 0u); GIVEN("an absolute path") { facts.add_external_facts({ LIBFACTER_TESTS_DIRECTORY "/fixtures/facts/external/windows/execution", LIBFACTER_TESTS_DIRECTORY "/fixtures/facts/external/windows/powershell", }); THEN("facts should resolve") { REQUIRE(facts.size() == 19u); REQUIRE(facts.get("exe_fact1")); REQUIRE(facts.get("exe_fact2")); REQUIRE_FALSE(facts.get("exe_fact3")); REQUIRE(facts.get("exe_fact4")); REQUIRE(facts.get("ps1_fact1")); REQUIRE(facts.get("ps1_fact2")); REQUIRE_FALSE(facts.get("ps1_fact3")); REQUIRE(facts.get("ps1_fact4")); REQUIRE(facts.get("ps1_json_fact1")); REQUIRE(facts.get("ps1_json_fact2")); REQUIRE(facts.get("ps1_json_fact3")); REQUIRE(facts.get("ps1_json_fact4")); REQUIRE_FALSE(facts.get("ps1_json_fact5")); REQUIRE(facts.get("ps1_json_fact6")); REQUIRE(facts.get("ps1_yaml_fact1")); REQUIRE(facts.get("ps1_yaml_fact2")); REQUIRE(facts.get("ps1_yaml_fact3")); REQUIRE(facts.get("ps1_yaml_fact4")); REQUIRE(facts.get("ps1_yaml_fact5")); REQUIRE(facts.get("ps1_yaml_fact6")); REQUIRE(facts.get("ps1_yaml_fact7")); } } GIVEN("a relative path") { test_with_relative_path fixture("foo", "bar.bat", "@echo local_exec_fact=value"); facts.add_external_facts({ "foo" }); THEN("facts should resolve") { REQUIRE(facts.size() == 1u); REQUIRE(facts.get("local_exec_fact")); REQUIRE(facts.get("local_exec_fact")->value() == "value"); } } } facter-3.14.12/lib/tests/facts/windows/external_resolvers_factory.cc0000644005276200011600000000304613702047406025512 0ustar jenkinsjenkins#include #include #include "../../fixtures.hpp" using namespace std; using namespace facter::facts; SCENARIO("checking external file windows resolvers factory") { external_resolvers_factory erf; GIVEN("an executable file") { THEN("the file can be resolved") { REQUIRE(erf.get_resolver(LIBFACTER_TESTS_DIRECTORY "/fixtures/facts/external/windows/execution/facts.bat")); } } GIVEN("a PowerShell file extension") { THEN("the file can be resolved") { REQUIRE(erf.get_resolver(LIBFACTER_TESTS_DIRECTORY "/fixtures/facts/external/windows/powershell/facts.ps1")); } } GIVEN("a non executable file without extension") { THEN("should throw no resolver exception") { REQUIRE_THROWS_AS(erf.get_resolver(LIBFACTER_TESTS_DIRECTORY "/fixtures/facts/external/windows/execution/not_executable"), external::external_fact_no_resolver&); } } GIVEN("a non-executable ruby script") { THEN("the file cannot be resolved") { REQUIRE_THROWS_AS(erf.get_resolver(LIBFACTER_TESTS_DIRECTORY "/fixtures/facts/external/windows/execution/ruby_script.rb"), external::external_fact_no_resolver&); } } GIVEN("a relative path not on PATH") { THEN("the file cannot be resolved") { REQUIRE_THROWS_AS(erf.get_resolver("foo/bar.bat"), external::external_fact_no_resolver&); } } } facter-3.14.12/lib/tests/facts/windows/networking_resolver.cc0000644005276200011600000002154013702047406024144 0ustar jenkinsjenkins#include #include #include #include #include using namespace std; // Test address manipulation utilities. struct networking_utilities : facter::facts::windows::networking_resolver { public: using networking_resolver::create_ipv4_mask; using networking_resolver::create_ipv6_mask; using networking_resolver::mask_ipv4_address; using networking_resolver::mask_ipv6_address; template std::string address_to_string(T const& addr) { return winsock.address_to_string(const_cast(addr)); } template std::string address_to_string(T const* addr, T const* mask) { return {}; } facter::util::windows::wsa winsock; }; template <> std::string networking_utilities::address_to_string(sockaddr_in const* addr, sockaddr_in const* mask) { auto masked = mask_ipv4_address(reinterpret_cast(addr), *mask); return address_to_string(masked); } template <> std::string networking_utilities::address_to_string(sockaddr_in6 const* addr, sockaddr_in6 const* mask) { auto masked = mask_ipv6_address(reinterpret_cast(addr), *mask); return address_to_string(masked); } static constexpr sockaddr_in make_sockaddr_in(u_char a, u_char b, u_char c, u_char d) { return {AF_INET, 0u, in_addr{a, b, c, d}, {0, 0, 0, 0, 0, 0, 0, 0}}; } bool operator== (in_addr const& a, in_addr const& b) { return a.S_un.S_addr == b.S_un.S_addr; } bool operator!= (in_addr const& a, in_addr const& b) { return !(a == b); } bool operator== (sockaddr_in const& a, sockaddr_in const& b) { return a.sin_family == b.sin_family && a.sin_addr == b.sin_addr; } bool operator!= (sockaddr_in const& a, sockaddr_in const& b) { return !(a == b); } struct ipv4_case { uint8_t masklen; sockaddr_in addr; string str; }; static const ipv4_case ip4_masks[] = { {0u, make_sockaddr_in(0u, 0u, 0u, 0u), "0.0.0.0"}, {255u, make_sockaddr_in(255u, 255u, 255u, 255u), "255.255.255.255"}, {32u, make_sockaddr_in(255u, 255u, 255u, 255u), "255.255.255.255"}, {33u, make_sockaddr_in(255u, 255u, 255u, 255u), "255.255.255.255"}, {24u, make_sockaddr_in(255u, 255u, 255u, 0u), "255.255.255.0"}, {9u, make_sockaddr_in(255u, 128u, 0u, 0u), "255.128.0.0"}, {1u, make_sockaddr_in(128u, 0u, 0u, 0u), "128.0.0.0"}, {31u, make_sockaddr_in(255u, 255u, 255u, 254u), "255.255.255.254"} }; SCENARIO("create IPv4 masks") { networking_utilities util; // Test various valid masklen, too large masklen, verify output. for (auto const& item : ip4_masks) { auto mask = util.create_ipv4_mask(item.masklen); REQUIRE(mask == item.addr); } // Verify the boolean operator behaves as expected. REQUIRE(ip4_masks[0].addr != ip4_masks[1].addr); REQUIRE(ip4_masks[0].addr != ip4_masks[6].addr); } SCENARIO("IPv4 address to string") { networking_utilities util; static const pair ip4_cases[] = { {make_sockaddr_in(192u, 168u, 0u, 1u), "192.168.0.1"}, {make_sockaddr_in(200u, 0u, 154u, 12u), "200.0.154.12"}, {make_sockaddr_in(1u, 255u, 128u, 42u), "1.255.128.42"} }; // Test various valid addresses to string. for (auto const& item : ip4_cases) { REQUIRE(item.second == util.address_to_string(item.first)); } // Test various mask addresses to string. for (auto const& item : ip4_masks) { REQUIRE(item.str == util.address_to_string(item.addr)); } } SCENARIO("IPv4 address with mask to string") { networking_utilities util; // Test address_to_string with masks applied. auto min = make_sockaddr_in(0u, 0u, 0u, 0u); auto max = make_sockaddr_in(255u, 255u, 255u, 255u); auto zoro = make_sockaddr_in(255u, 255u, 128u, 0u); auto v = make_sockaddr_in(128u, 0u, 0u, 0u); auto local = make_sockaddr_in(192u, 168u, 0u, 1u); auto outer = make_sockaddr_in(200u, 0u, 154u, 12u); REQUIRE("0.0.0.0" == util.address_to_string(&local, &min)); REQUIRE("192.168.0.1" == util.address_to_string(&local, &max)); REQUIRE("192.168.0.0" == util.address_to_string(&local, &zoro)); REQUIRE("128.0.0.0" == util.address_to_string(&local, &v)); REQUIRE("0.0.0.0" == util.address_to_string(&outer, &min)); REQUIRE("200.0.154.12" == util.address_to_string(&outer, &max)); REQUIRE("200.0.128.0" == util.address_to_string(&outer, &zoro)); REQUIRE("128.0.0.0" == util.address_to_string(&outer, &v)); } static sockaddr_in6 make_sockaddr_in6(array x) { sockaddr_in6 addr = {AF_INET6}; memcpy(addr.sin6_addr.u.Byte, x.data(), 16*sizeof(u_char)); return addr; } bool operator== (in6_addr const& a, in6_addr const& b) { return 0 == memcmp(a.u.Word, b.u.Word, 8*sizeof(u_short)); } bool operator!= (in6_addr const& a, in6_addr const& b) { return !(a == b); } bool operator== (sockaddr_in6 const& a, sockaddr_in6 const& b) { return a.sin6_family == b.sin6_family && a.sin6_addr == b.sin6_addr; } bool operator!= (sockaddr_in6 const& a, sockaddr_in6 const& b) { return !(a == b); } struct ipv6_case { uint8_t masklen; string str; sockaddr_in6 addr; }; static const ipv6_case ip6_masks[] = { {0u, "::", make_sockaddr_in6({})}, {1u, "8000::", make_sockaddr_in6({0x80u})}, {4u, "f000::", make_sockaddr_in6({0xf0u})}, {64u, "ffff:ffff:ffff:ffff::", make_sockaddr_in6({0xffu, 0xffu, 0xffu, 0xffu, 0xffu, 0xffu, 0xffu, 0xffu})}, {65u, "ffff:ffff:ffff:ffff:8000::", make_sockaddr_in6({0xffu, 0xffu, 0xffu, 0xffu, 0xffu, 0xffu, 0xffu, 0xffu, 0x80u})}, {127u, "ffff:ffff:ffff:ffff:ffff:ffff:ffff:fffe", make_sockaddr_in6({0xffu, 0xffu, 0xffu, 0xffu, 0xffu, 0xffu, 0xffu, 0xffu, 0xffu, 0xffu, 0xffu, 0xffu, 0xffu, 0xffu, 0xffu, 0xfeu})}, {128u, "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff", make_sockaddr_in6({0xffu, 0xffu, 0xffu, 0xffu, 0xffu, 0xffu, 0xffu, 0xffu, 0xffu, 0xffu, 0xffu, 0xffu, 0xffu, 0xffu, 0xffu, 0xffu})}, {129u, "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff", make_sockaddr_in6({0xffu, 0xffu, 0xffu, 0xffu, 0xffu, 0xffu, 0xffu, 0xffu, 0xffu, 0xffu, 0xffu, 0xffu, 0xffu, 0xffu, 0xffu, 0xffu})} }; SCENARIO("create IPv6 mask") { networking_utilities util; // Test various valid masklen, too large masklen, verify output. for (auto const& item : ip6_masks) { auto mask = util.create_ipv6_mask(item.masklen); REQUIRE(item.addr == mask); } // Verify the boolean operator behaves as expected. REQUIRE(ip6_masks[0].addr != ip6_masks[1].addr); REQUIRE(ip6_masks[0].addr != ip6_masks[6].addr); } SCENARIO("IPv6 address to string") { networking_utilities util; static const pair ip6_cases[] = { {make_sockaddr_in6({0u, 0u, 0u, 0u, 0xffu, 0xe9u, 0xffu, 0xffu, 0xffu, 0xabu, 1u}), "::ffe9:ffff:ffab:100:0:0"}, {make_sockaddr_in6({0u, 0xffu, 0xe9u, 0xffu, 0xffu, 0xffu, 0xabu, 1u}), "ff:e9ff:ffff:ab01::"}, {make_sockaddr_in6({0xfeu, 0x80u, 0x01u, 0x23u, 0u, 0u, 0u, 0u, 0x45u, 0x67u, 0x89u, 0xabu}), "fe80:123::4567:89ab:0:0"}, {make_sockaddr_in6({0xfeu, 0x80u, 0x01u, 0x23u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0x45u, 0x67u, 0x89u, 0xabu}), "fe80:123::4567:89ab"}, {make_sockaddr_in6({0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 1u}), "::1"}, }; // Test various valid addresses to string. for (auto const& item : ip6_cases) { REQUIRE(item.second == util.address_to_string(item.first)); } // Test various mask addresses to string. for (auto const& item : ip6_masks) { REQUIRE(item.str == util.address_to_string(item.addr)); } } SCENARIO("IPv6 address with mask to string") { networking_utilities util; // Test address_to_string with masks applied. auto min = make_sockaddr_in6({}); auto max = make_sockaddr_in6({0xffu, 0xffu, 0xffu, 0xffu, 0xffu, 0xffu, 0xffu, 0xffu, 0xffu, 0xffu, 0xffu, 0xffu, 0xffu, 0xffu, 0xffu, 0xffu}); auto zoro = make_sockaddr_in6({0xffu, 0xffu, 0xffu, 0xffu, 0xffu, 0xffu, 0xffu, 0xffu}); auto v = make_sockaddr_in6({0xf8u}); auto local = make_sockaddr_in6({0xfeu, 0x80u, 0x01u, 0x23u, 0u, 0u, 0u, 0u, 0x45u, 0x67u, 0x89u, 0xabu}); auto outer = make_sockaddr_in6({0u, 0xffu, 0xe9u, 0xffu, 0xffu, 0xffu, 0xabu, 1u}); REQUIRE("::" == util.address_to_string(&local, &min)); REQUIRE("fe80:123::4567:89ab:0:0" == util.address_to_string(&local, &max)); REQUIRE("fe80:123::" == util.address_to_string(&local, &zoro)); REQUIRE("f800::" == util.address_to_string(&local, &v)); REQUIRE("::" == util.address_to_string(&outer, &min)); REQUIRE("ff:e9ff:ffff:ab01::" == util.address_to_string(&outer, &max)); REQUIRE("ff:e9ff:ffff:ab01::" == util.address_to_string(&outer, &zoro)); REQUIRE("::" == util.address_to_string(&outer, &v)); } facter-3.14.12/lib/tests/facts/windows/operating_system_resolver.cc0000644005276200011600000000106513702047406025351 0ustar jenkinsjenkins#include #include #include #include #include using namespace std; using namespace leatherman::util; SCENARIO("Read SYSTEMROOT OS environment variable") { GIVEN("Windows 32 and 64 bit OS") { string value; REQUIRE(environment::get("SystemRoot", value)); string required = "C:\\WINDOWS"; boost::algorithm::to_upper(value); REQUIRE(required == value); } } facter-3.14.12/lib/tests/fixtures.cc0000644005276200011600000000361113702047406017112 0ustar jenkinsjenkins#include "fixtures.hpp" #include #include #include #include #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wstrict-aliasing" #pragma GCC diagnostic ignored "-Wunused-variable" #include #include #pragma GCC diagnostic pop using namespace std; using namespace boost::filesystem; namespace facter { namespace testing { bool load_fixture(string const& name, string& data) { string path = string(LIBFACTER_TESTS_DIRECTORY) + "/fixtures/" + name; boost::nowide::ifstream in(path.c_str(), ios_base::in | ios_base::binary); if (!in) { return false; } ostringstream buffer; buffer << in.rdbuf(); data = buffer.str(); return true; } test_with_relative_path::test_with_relative_path(string const& dirname, string const& filename, string const& contents) { path dir(dirname); if (exists(dir)) { throw runtime_error(dir.string() + " already exists"); } if (!create_directory(dir)) { throw runtime_error(dir.string() + " could not be created"); } _dir = dir.string(); path exec = dir / filename; { boost::nowide::ofstream exec_file(exec.string().c_str()); exec_file << contents << endl; } permissions(exec, add_perms | owner_exe | group_exe); } test_with_relative_path::~test_with_relative_path() { if (!_dir.empty()) { remove_all(_dir); // Wait for at most 5 seconds to ensure the directory is destroyed. int count = 50; while (exists(_dir) && --count > 0) { boost::this_thread::sleep_for(boost::chrono::milliseconds(100)); } } } }} // namespace facter::testing facter-3.14.12/lib/tests/fixtures.hpp.in0000644005276200011600000000140213702047406017715 0ustar jenkinsjenkins#pragma once #include #include #include "collection_fixture.hpp" #define JAVA_EXECUTABLE "@Java_JAVA_EXECUTABLE@" #define BINARY_DIRECTORY "@CMAKE_BINARY_DIR@" #define LIBFACTER_TESTS_DIRECTORY "@CMAKE_CURRENT_LIST_DIR@" namespace facter { namespace testing { bool load_fixture(std::string const& name, std::string& data); // Creates a local directory and adds a file to it containing . // When destroyed, it deletes the directory. struct test_with_relative_path { test_with_relative_path(std::string const& dirname, std::string const& filename, std::string const& contents); ~test_with_relative_path(); private: std::string _dir; }; }} // namespace facter::testing facter-3.14.12/lib/tests/fixtures/0000755005276200011600000000000013702047635016606 5ustar jenkinsjenkinsfacter-3.14.12/lib/tests/fixtures/execution/0000755005276200011600000000000013702047635020611 5ustar jenkinsjenkinsfacter-3.14.12/lib/tests/fixtures/execution/with space/0000755005276200011600000000000013702047635022640 5ustar jenkinsjenkinsfacter-3.14.12/lib/tests/fixtures/execution/with space/command_with_space.bat0000755005276200011600000000002213702047406027145 0ustar jenkinsjenkins@echo off echo %1 facter-3.14.12/lib/tests/fixtures/facts/0000755005276200011600000000000013702047635017706 5ustar jenkinsjenkinsfacter-3.14.12/lib/tests/fixtures/facts/external/0000755005276200011600000000000013702047635021530 5ustar jenkinsjenkinsfacter-3.14.12/lib/tests/fixtures/facts/external/json/0000755005276200011600000000000013702047635022501 5ustar jenkinsjenkinsfacter-3.14.12/lib/tests/fixtures/facts/external/json/facts.json0000644005276200011600000000031113702047406024463 0ustar jenkinsjenkins{ "json_fact1": "foo", "json_fact2": 5, "json_fact3": true, "json_fact4": 5.1, "json_fact5": [1, 2, 3], "json_fact6": { "element1" : 1, "element2" : 2 }, "JSON_fact7" : "bar" } facter-3.14.12/lib/tests/fixtures/facts/external/json/invalid.json0000644005276200011600000000003413702047406025013 0ustar jenkinsjenkins!!!this is not valid json!!!facter-3.14.12/lib/tests/fixtures/facts/external/ordering/0000755005276200011600000000000013702047635023341 5ustar jenkinsjenkinsfacter-3.14.12/lib/tests/fixtures/facts/external/ordering/bar/0000755005276200011600000000000013702047635024105 5ustar jenkinsjenkinsfacter-3.14.12/lib/tests/fixtures/facts/external/ordering/bar/foo.yaml0000644005276200011600000000003113702047406025542 0ustar jenkinsjenkinsfoo: set in bar/foo.yaml facter-3.14.12/lib/tests/fixtures/facts/external/ordering/foo/0000755005276200011600000000000013702047635024124 5ustar jenkinsjenkinsfacter-3.14.12/lib/tests/fixtures/facts/external/ordering/foo/foo.yaml0000644005276200011600000000003113702047406025561 0ustar jenkinsjenkinsfoo: set in foo/foo.yaml facter-3.14.12/lib/tests/fixtures/facts/external/posix/0000755005276200011600000000000013702047635022672 5ustar jenkinsjenkinsfacter-3.14.12/lib/tests/fixtures/facts/external/posix/execution/0000755005276200011600000000000013702047635024675 5ustar jenkinsjenkinsfacter-3.14.12/lib/tests/fixtures/facts/external/posix/execution/error_message0000755005276200011600000000007113702047406027452 0ustar jenkinsjenkins#! /usr/bin/env sh echo error message! >&2 echo foo=bar facter-3.14.12/lib/tests/fixtures/facts/external/posix/execution/facts0000755005276200011600000000014513702047406025717 0ustar jenkinsjenkins#! /usr/bin/env sh echo 'exe_fact1=value1' echo 'exe_fact2=' echo 'exe_fact3' echo 'EXE_fact4=value2'facter-3.14.12/lib/tests/fixtures/facts/external/posix/execution/failed0000755005276200011600000000006313702047406026042 0ustar jenkinsjenkins#! /usr/bin/env sh echo 'this script fails' exit 1 facter-3.14.12/lib/tests/fixtures/facts/external/posix/execution/not_executable0000644005276200011600000000003413702047406027612 0ustar jenkinsjenkinsThis file is not executable.facter-3.14.12/lib/tests/fixtures/facts/external/text/0000755005276200011600000000000013702047635022514 5ustar jenkinsjenkinsfacter-3.14.12/lib/tests/fixtures/facts/external/text/facts.txt0000644005276200011600000000006713702047406024354 0ustar jenkinsjenkinstxt_fact1=value1 txt_fact2= not a fact TXT_Fact4=value2facter-3.14.12/lib/tests/fixtures/facts/external/windows/0000755005276200011600000000000013702047635023222 5ustar jenkinsjenkinsfacter-3.14.12/lib/tests/fixtures/facts/external/windows/execution/0000755005276200011600000000000013702047635025225 5ustar jenkinsjenkinsfacter-3.14.12/lib/tests/fixtures/facts/external/windows/execution/error_message.bat0000755005276200011600000000007113702047406030547 0ustar jenkinsjenkins@echo off echo error message! >&2 echo foo=bar exit /b 0 facter-3.14.12/lib/tests/fixtures/facts/external/windows/execution/facts.bat0000755005276200011600000000011613702047406027012 0ustar jenkinsjenkins@echo exe_fact1=value1 @echo exe_fact2= @echo exe_fact3 @echo EXE_fact4=value2facter-3.14.12/lib/tests/fixtures/facts/external/windows/execution/failed.cmd0000755005276200011600000000003613702047406027134 0ustar jenkinsjenkins@echo this script fails exit 1facter-3.14.12/lib/tests/fixtures/facts/external/windows/execution/not_executable0000644005276200011600000000003413702047406030142 0ustar jenkinsjenkinsThis file is not executable.facter-3.14.12/lib/tests/fixtures/facts/external/windows/execution/ruby_script.rb0000644005276200011600000000003413702047406030110 0ustar jenkinsjenkinsputs "rbver=#{RUBY_VERSION}"facter-3.14.12/lib/tests/fixtures/facts/external/windows/powershell/0000755005276200011600000000000013702047635025406 5ustar jenkinsjenkinsfacter-3.14.12/lib/tests/fixtures/facts/external/windows/powershell/error_message.ps10000644005276200011600000000010413702047406030657 0ustar jenkinsjenkins[Console]::Error.WriteLine('error message!') Write 'foo=bar' exit 0 facter-3.14.12/lib/tests/fixtures/facts/external/windows/powershell/facts.ps10000644005276200011600000000011313702047406027122 0ustar jenkinsjenkinsecho ps1_fact1=value1 echo ps1_fact2= echo ps1_fact3 echo PS1_fact4=value2 facter-3.14.12/lib/tests/fixtures/facts/external/windows/powershell/failed.ps10000644005276200011600000000003613702047406027252 0ustar jenkinsjenkinsecho this script fails exit 1 facter-3.14.12/lib/tests/fixtures/facts/external/windows/powershell/json.ps10000644005276200011600000000106713702047406027004 0ustar jenkinsjenkinsif (Get-Command ConvertTo-JSON -errorAction SilentlyContinue) { @{ 'PS1_JSON_FACT1' = 'value1' 'ps1_json_fact2' = 2 'ps1_json_fact3' = $True 'ps1_json_fact4' = @('first', 'second') 'ps1_json_fact5' = $Null 'ps1_json_fact6' = @{ 'a' = 'b'; 'c' = 'd' } } | ConvertTo-JSON -Depth 1 -Compress } else { @' { "PS1_JSON_FACT1": "value1", "ps1_json_fact2": 2, "ps1_json_fact3": true, "ps1_json_fact4": ["first", "second"], "ps1_json_fact5": null, "ps1_json_fact6": { "a": "b", "c": "d" } } '@ } facter-3.14.12/lib/tests/fixtures/facts/external/windows/powershell/not_executable0000644005276200011600000000003413702047406030323 0ustar jenkinsjenkinsThis file is not executable.facter-3.14.12/lib/tests/fixtures/facts/external/windows/powershell/yaml.ps10000644005276200011600000000040513702047406026770 0ustar jenkinsjenkins@' --- PS1_YAML_FACT1: yaml PS1_yaml_fact2: 2 ps1_yaml_fact3: | one value but many lines ps1_yaml_fact4: - one - two ps1_yaml_fact5: [first, second, third] ps1_yaml_fact6: red: green orange: blue yellow: purple ps1_yaml_fact7: { key: value } '@ facter-3.14.12/lib/tests/fixtures/facts/external/yaml/0000755005276200011600000000000013702047635022472 5ustar jenkinsjenkinsfacter-3.14.12/lib/tests/fixtures/facts/external/yaml/facts.yaml0000644005276200011600000000031313702047406024447 0ustar jenkinsjenkinsyaml_fact1: foo yaml_fact2: 5 yaml_fact3: true yaml_fact4: 5.1 yaml_fact5: - 1 - 2 - 3 yaml_fact6: element1: 1 element2: 2 YAML_faCt7: bar not_bool: 'true' not_int: '123' not_double: '123.456' facter-3.14.12/lib/tests/fixtures/facts/external/yaml/invalid.yaml0000644005276200011600000000003413702047406024775 0ustar jenkinsjenkins!!!this is not valid yaml!!!facter-3.14.12/lib/tests/fixtures/facts/external/zö/0000755005276200011600000000000013702047635022572 5ustar jenkinsjenkinsfacter-3.14.12/lib/tests/fixtures/facts/external/zö/facts.rb0000644005276200011600000000006613702047406024215 0ustar jenkinsjenkinsFacter.add "snowman_fact" do setcode { "olaf" } end facter-3.14.12/lib/tests/fixtures/facts/external/zö/facts.txt0000644005276200011600000000002213702047406024421 0ustar jenkinsjenkinssnowman_fact=olaf facter-3.14.12/lib/tests/fixtures/facts/linux/0000755005276200011600000000000013702047635021045 5ustar jenkinsjenkinsfacter-3.14.12/lib/tests/fixtures/facts/linux/cloud/0000755005276200011600000000000013702047635022153 5ustar jenkinsjenkinsfacter-3.14.12/lib/tests/fixtures/facts/linux/cloud/azure0000644005276200011600000000006113702047406023215 0ustar jenkinsjenkinsfirst line this has option 245 defined last line facter-3.14.12/lib/tests/fixtures/facts/linux/cloud/azure-unknown0000644005276200011600000000007113702047406024713 0ustar jenkinsjenkinsfirst line this has option unknown-245 defined last line facter-3.14.12/lib/tests/fixtures/facts/linux/cloud/not-azure0000644005276200011600000000000013702047406024004 0ustar jenkinsjenkinsfacter-3.14.12/lib/tests/fixtures/facts/linux/dmidecode/0000755005276200011600000000000013702047635022762 5ustar jenkinsjenkinsfacter-3.14.12/lib/tests/fixtures/facts/linux/dmidecode/full.txt0000644005276200011600000000430013702047406024456 0ustar jenkinsjenkins# dmidecode 2.12 SMBIOS 2.5 present. 10 structures occupying 450 bytes. Table at 0x000E1000. Handle 0x0000, DMI type 0, 20 bytes BIOS Information Vendor: innotek GmbH Version: VirtualBox Release Date: 12/01/2006 Address: 0xE0000 Runtime Size: 128 kB ROM Size: 128 kB Characteristics: ISA is supported PCI is supported Boot from CD is supported Selectable boot is supported 8042 keyboard services are supported (int 9h) CGA/mono video services are supported (int 10h) ACPI is supported Handle 0x0001, DMI type 1, 27 bytes System Information Manufacturer: innotek GmbH Product Name: VirtualBox Version: 1.2 Serial Number: 0 UUID: 735AE71B-8655-4AE2-9CA9-172C1BBEDAB5 Wake-up Type: Power Switch SKU Number: Not Specified Family: Virtual Machine Handle 0x0008, DMI type 2, 15 bytes Base Board Information Manufacturer: Oracle Corporation Product Name: VirtualBox Version: 1.2 Serial Number: 0 Asset Tag: Not Specified Features: Board is a hosting board Location In Chassis: Not Specified Chassis Handle: 0x0003 Type: Motherboard Contained Object Handles: 0 Handle 0x0003, DMI type 3, 13 bytes Chassis Information Manufacturer: Oracle Corporation Type: Other Lock: Not Present Version: Not Specified Serial Number: Not Specified Asset Tag: Not Specified Boot-up State: Safe Asset Tag: Not Specified Boot-up State: Safe Power Supply State: Safe Thermal State: Safe Security Status: None Handle 0x0007, DMI type 126, 42 bytes Inactive Handle 0x0005, DMI type 126, 15 bytes Inactive Handle 0x0006, DMI type 126, 28 bytes Inactive Handle 0x0002, DMI type 11, 7 bytes OEM Strings String 1: vboxVer_4.3.30 String 2: vboxRev_101610 Handle 0x0008, DMI type 128, 8 bytes OEM-specific Type Header and Data: 80 08 08 00 CA 1D 23 00 Handle 0xFEFF, DMI type 127, 4 bytes End Of Table facter-3.14.12/lib/tests/fixtures/facts/linux/dmidecode/full_alternative.txt0000644005276200011600000000427613702047406027070 0ustar jenkinsjenkins# dmidecode 2.12 SMBIOS 2.5 present. 10 structures occupying 450 bytes. Table at 0x000E1000. Handle 0x0000, DMI type 0, 20 bytes BIOS Information Vendor: innotek GmbH Version: VirtualBox Release Date: 12/01/2006 Address: 0xE0000 Runtime Size: 128 kB ROM Size: 128 kB Characteristics: ISA is supported PCI is supported Boot from CD is supported Selectable boot is supported 8042 keyboard services are supported (int 9h) CGA/mono video services are supported (int 10h) ACPI is supported Handle 0x0001, DMI type 1, 27 bytes System Information Manufacturer: innotek GmbH Product: VirtualBox Version: 1.2 Serial Number: 0 UUID: 735AE71B-8655-4AE2-9CA9-172C1BBEDAB5 Wake-up Type: Power Switch SKU Number: Not Specified Family: Virtual Machine Handle 0x0008, DMI type 2, 15 bytes Base Board Information Manufacturer: Oracle Corporation Product: VirtualBox Version: 1.2 Serial Number: 0 Asset Tag: Not Specified Features: Board is a hosting board Location In Chassis: Not Specified Chassis Handle: 0x0003 Type: Motherboard Contained Object Handles: 0 Handle 0x0003, DMI type 3, 13 bytes Chassis Information Manufacturer: Oracle Corporation Chassis Type: Other Lock: Not Present Version: Not Specified Serial Number: Not Specified Asset Tag: Not Specified Boot-up State: Safe Asset Tag: Not Specified Boot-up State: Safe Power Supply State: Safe Thermal State: Safe Security Status: None Handle 0x0007, DMI type 126, 42 bytes Inactive Handle 0x0005, DMI type 126, 15 bytes Inactive Handle 0x0006, DMI type 126, 28 bytes Inactive Handle 0x0002, DMI type 11, 7 bytes OEM Strings String 1: vboxVer_4.3.30 String 2: vboxRev_101610 Handle 0x0008, DMI type 128, 8 bytes OEM-specific Type Header and Data: 80 08 08 00 CA 1D 23 00 Handle 0xFEFF, DMI type 127, 4 bytes End Of Table facter-3.14.12/lib/tests/fixtures/facts/linux/dmidecode/none.txt0000644005276200011600000000007613702047406024461 0ustar jenkinsjenkins# dmidecode 2.12 # No SMBIOS nor DMI entry point found, sorry.facter-3.14.12/lib/tests/fixtures/ruby/0000755005276200011600000000000013702047635017567 5ustar jenkinsjenkinsfacter-3.14.12/lib/tests/fixtures/ruby/100_resolutions.rb0000644005276200011600000000014613702047406023057 0ustar jenkinsjenkins(1..100).each do Facter.add(:foo) do setcode do 'bar' end end end facter-3.14.12/lib/tests/fixtures/ruby/101_resolutions.rb0000644005276200011600000000014613702047406023060 0ustar jenkinsjenkins(0..100).each do Facter.add(:foo) do setcode do 'bar' end end end facter-3.14.12/lib/tests/fixtures/ruby/aggregate.rb0000644005276200011600000000020713702047406022035 0ustar jenkinsjenkinsFacter.add(:foo, :type => :aggregate) do chunk :first do ['foo'] end chunk :second do ['bar'] end end facter-3.14.12/lib/tests/fixtures/ruby/aggregate_invalid_require.rb0000644005276200011600000000025313702047406025300 0ustar jenkinsjenkinsFacter.add(:foo, :type => :aggregate) do chunk :first do ['foo'] end chunk :second, :require => ['first'] do |first| raise 'nope' end end facter-3.14.12/lib/tests/fixtures/ruby/aggregate_with_block.rb0000644005276200011600000000107413702047406024245 0ustar jenkinsjenkinsFacter.add(:foo, :type => :aggregate) do chunk(:one) do 1 end chunk(:two) do 2 end chunk(:three) do 3 end chunk(:four) do 4 end aggregate do |chunks| raise 'nope' unless chunks.size == 4 raise 'nope' unless chunks.has_key? :one raise 'nope' unless chunks.has_key? :two raise 'nope' unless chunks.has_key? :three raise 'nope' unless chunks.has_key? :four sum = 0 chunks.each_value do |i| sum += i end sum end end facter-3.14.12/lib/tests/fixtures/ruby/aggregate_with_cycle.rb0000644005276200011600000000031313702047406024245 0ustar jenkinsjenkinsFacter.add(:foo, :type => :aggregate) do chunk :first, :require => :second do |second| raise 'nope' end chunk :second, :require => :first do |first| raise 'nope' end end facter-3.14.12/lib/tests/fixtures/ruby/aggregate_with_invalid_merge.rb0000644005276200011600000000031213702047406025752 0ustar jenkinsjenkinsFacter.add(:foo, :type => :aggregate) do chunk :first do { 'foo' => 'hello', } end chunk :second do { 'foo' => 'world' } end end facter-3.14.12/lib/tests/fixtures/ruby/aggregate_with_merge.rb0000644005276200011600000000075113702047406024253 0ustar jenkinsjenkinsFacter.add(:foo, :type => :aggregate) do chunk :first do { 'foo' => 'bar', 'array' => [1, 2, 3], 'hash' => { 'jam' => 'cakes', 'subarray' => ['hello'] } } end chunk :second do { 'baz' => 'jam', 'array' => [4, 5, 6], 'hash' => { 'foo' => 'bar', 'subarray' => ['world'] } } end end facter-3.14.12/lib/tests/fixtures/ruby/aggregate_with_require.rb0000644005276200011600000000064713702047406024634 0ustar jenkinsjenkinsFacter.add(:foo, :type => :aggregate) do chunk :first do ['foo'] end chunk :second, :require => :first do |first| raise 'nope' unless first == ['foo'] ['bar'] + first end chunk :third, :require => [:first, :second] do |first, second| raise 'nope' unless first == ['foo'] raise 'nope' unless second == ['bar', 'foo'] ['baz'] + first + second end end facter-3.14.12/lib/tests/fixtures/ruby/array_confine.rb0000644005276200011600000000016413702047406022730 0ustar jenkinsjenkinsFacter.add(:foo) do confine 'fact' => [ 'value1', 'value2', 'value3' ] setcode do 'bar' end end facter-3.14.12/lib/tests/fixtures/ruby/array_fact.rb0000644005276200011600000000015513702047406022224 0ustar jenkinsjenkinsFacter.add(:foo) do setcode do [1, true, false, 'foo', 12.4, [1], { :foo => 'bar' }] end end facter-3.14.12/lib/tests/fixtures/ruby/bad_command.rb0000644005276200011600000000060413702047406022334 0ustar jenkinsjenkinsFacter.add(:foo) do setcode 'not_a_valid_command' end Facter.add(:foo) do setcode do Facter::Core::Execution.exec('not_a_valid_command') end end Facter.add(:foo) do setcode do begin Facter::Core::Execution.execute('not_a_valid_command') 'bar' rescue Facter::Core::Execution::ExecutionFailure => ex end end end facter-3.14.12/lib/tests/fixtures/ruby/bad_syntax.rb0000644005276200011600000000003013702047406022235 0ustar jenkinsjenkinsFacter.foo(:add) do end facter-3.14.12/lib/tests/fixtures/ruby/bignum_fact_value.rb0000644005276200011600000000010413702047406023555 0ustar jenkinsjenkinsFacter.add('bignum_fact') do setcode do 12345678901 end end facter-3.14.12/lib/tests/fixtures/ruby/block_confine.rb0000644005276200011600000000017613702047406022707 0ustar jenkinsjenkinsFacter.add(:foo) do confine :fact1 do |value| value == 'value1' end setcode do 'bar' end end facter-3.14.12/lib/tests/fixtures/ruby/block_false_confine.rb0000644005276200011600000000014313702047406024053 0ustar jenkinsjenkinsFacter.add(:foo) do confine do false end setcode do 'bar' end end facter-3.14.12/lib/tests/fixtures/ruby/block_nil_confine.rb0000644005276200011600000000014113702047406023541 0ustar jenkinsjenkinsFacter.add(:foo) do confine do nil end setcode do 'bar' end end facter-3.14.12/lib/tests/fixtures/ruby/block_true_confine.rb0000644005276200011600000000014213702047406023737 0ustar jenkinsjenkinsFacter.add(:foo) do confine do true end setcode do 'bar' end end facter-3.14.12/lib/tests/fixtures/ruby/boolean_false_confine.rb0000644005276200011600000000013113702047406024375 0ustar jenkinsjenkinsFacter.add(:foo) do confine 'fact' => false setcode do 'bar' end end facter-3.14.12/lib/tests/fixtures/ruby/boolean_false_fact.rb0000644005276200011600000000007513702047406023700 0ustar jenkinsjenkinsFacter.add(:foo) do setcode do false end end facter-3.14.12/lib/tests/fixtures/ruby/boolean_true_confine.rb0000644005276200011600000000013013702047406024261 0ustar jenkinsjenkinsFacter.add(:foo) do confine 'fact' => true setcode do 'bar' end end facter-3.14.12/lib/tests/fixtures/ruby/boolean_true_fact.rb0000644005276200011600000000007413702047406023564 0ustar jenkinsjenkinsFacter.add(:foo) do setcode do true end end facter-3.14.12/lib/tests/fixtures/ruby/command_with_space.rb0000644005276200011600000000015413702047406023734 0ustar jenkinsjenkinsFacter.add('foo') do setcode do Facter::Util::Resolution.exec('command_with_space.bat bar') end end facter-3.14.12/lib/tests/fixtures/ruby/confine_missing_fact.rb0000644005276200011600000000050713702047406024261 0ustar jenkinsjenkinsFacter.add(:foo) do confine :not_a_fact => 'foo' setcode do 'bar' end end Facter.add(:foo) do confine :kernel => 'Linux', :not_a_fact => 'foo' setcode do 'bar' end end Facter.add(:foo) do confine :not_a_fact do |value| true end setcode do 'bar' end end facter-3.14.12/lib/tests/fixtures/ruby/confine_weight.rb0000644005276200011600000000053313702047406023101 0ustar jenkinsjenkinsFacter.add(:foo) do confine :fact2 => 'value2' setcode do 'value1' end end Facter.add(:foo) do confine :fact1 => 'value1', :fact2 => 'value2', :fact3 => 'value3' setcode do 'value2' end end Facter.add(:foo) do confine :fact2 => 'value2', :fact3 => 'value3' setcode do 'value3' end end facter-3.14.12/lib/tests/fixtures/ruby/custom_dir/0000755005276200011600000000000013702047635021737 5ustar jenkinsjenkinsfacter-3.14.12/lib/tests/fixtures/ruby/custom_dir/expect_network_init.rb0000644005276200011600000000037013702047406026344 0ustar jenkinsjenkinsrequire 'net/http' Facter.add('sometest') do setcode do begin uri = URI("http://localhost:42000") if (Net::HTTP.get_response(uri)) 'Yay' else 'Nay' end rescue => e e.message end end end facter-3.14.12/lib/tests/fixtures/ruby/cycle.rb0000644005276200011600000000015113702047406021204 0ustar jenkinsjenkinsFacter.add('foo') do confine 'bar' => 'baz' end Facter.add('bar') do confine 'foo' => 'baz' end facter-3.14.12/lib/tests/fixtures/ruby/debug.rb0000644005276200011600000000017313702047406021177 0ustar jenkinsjenkinsFacter.add(:foo) do setcode do Facter.debug 'message1' Facter.debug 'message2' nil end end facter-3.14.12/lib/tests/fixtures/ruby/debugging.rb0000644005276200011600000000040213702047406022037 0ustar jenkinsjenkinsbegin # Log without debugging Facter.debugging false Facter.debug 'nope' # Can be set Facter.debugging true raise 'nope' unless Facter.debugging? # Log with debugging Facter.debug 'yep' ensure Facter.debugging false end facter-3.14.12/lib/tests/fixtures/ruby/debugonce.rb0000644005276200011600000000033713702047406022046 0ustar jenkinsjenkinsFacter.add(:foo) do setcode do Facter.debugonce 'unique debug1' Facter.debugonce 'unique debug1' Facter.debugonce 'unique debug2' Facter.debugonce 'unique debug2' nil end end facter-3.14.12/lib/tests/fixtures/ruby/define_aggregate_fact.rb0000644005276200011600000000036413702047406024350 0ustar jenkinsjenkinsFacter.define_fact(:foo) do raise 'nope' unless name == 'foo' define_resolution(nil, :type => :aggregate) do chunk :first do ['foo'] end chunk :second do ['bar'] end end end facter-3.14.12/lib/tests/fixtures/ruby/define_fact.rb0000644005276200011600000000023613702047406022340 0ustar jenkinsjenkinsFacter.define_fact(:foo) do raise 'nope' unless name == 'foo' define_resolution(nil) do setcode do 'bar' end end end facter-3.14.12/lib/tests/fixtures/ruby/double_fact.rb0000644005276200011600000000007513702047406022361 0ustar jenkinsjenkinsFacter.add(:foo) do setcode do 12.34 end end facter-3.14.12/lib/tests/fixtures/ruby/empty_command.rb0000644005276200011600000000004613702047406022744 0ustar jenkinsjenkinsFacter.add(:foo) do setcode '' endfacter-3.14.12/lib/tests/fixtures/ruby/empty_fact.rb0000644005276200011600000000002013702047406022233 0ustar jenkinsjenkinsFacter.add(:foo)facter-3.14.12/lib/tests/fixtures/ruby/empty_fact_with_value.rb0000644005276200011600000000021513702047406024470 0ustar jenkinsjenkinsFacter.add(:foo, :value => { :int => 1, :bool_true => true, :bool_false => false, :double => 12.34, :string => 'foo', :array => [1, 2, 3] }) facter-3.14.12/lib/tests/fixtures/ruby/empty_setcode_command.rb0000644005276200011600000000005713702047406024454 0ustar jenkinsjenkinsFacter.add(:foo) do setcode 'echo >&2' end facter-3.14.12/lib/tests/fixtures/ruby/exec.rb0000644005276200011600000000032013702047406021027 0ustar jenkinsjenkinsFacter.add(:foo) do setcode do result = Facter::Core::Execution.exec('echo bar baz') raise 'nope' unless result == Facter::Util::Resolution.exec('echo bar baz') result end end facter-3.14.12/lib/tests/fixtures/ruby/execute_on_fail_raise.rb0000644005276200011600000000112513702047406024423 0ustar jenkinsjenkins# Should raise by default begin Facter::Core::Execution.execute('the_most_interesting_command_in_the_world') raise 'did not raise' rescue Facter::Core::Execution::ExecutionFailure end # Should raise if given an option hash that does not contain :on_fail begin Facter::Core::Execution.execute('the_most_interesting_command_in_the_world', {}) raise 'did not raise' rescue Facter::Core::Execution::ExecutionFailure end # Should raise if directly given the option Facter::Core::Execution.execute('the_most_interesting_command_in_the_world', :on_fail => :raise) raise 'did not raise' facter-3.14.12/lib/tests/fixtures/ruby/execute_on_fail_value.rb0000644005276200011600000000023313702047406024433 0ustar jenkinsjenkinsFacter.add(:foo) do setcode do Facter::Core::Execution.execute('the_most_interesting_command_in_the_world', :on_fail => 'default') end end facter-3.14.12/lib/tests/fixtures/ruby/execute_timeout.rb0000644005276200011600000000012113702047406023312 0ustar jenkinsjenkinsFacter::Core::Execution.execute("#{RbConfig.ruby} -e 'sleep 15'", :timeout => 1) facter-3.14.12/lib/tests/fixtures/ruby/execution_failure.rb0000644005276200011600000000015113702047406023617 0ustar jenkinsjenkinsFacter.add(:foo) do setcode do Facter::Core::Execution.exec('echo bar && false') end end facter-3.14.12/lib/tests/fixtures/ruby/existing_aggregate_resolution.rb0000644005276200011600000000014413702047406026232 0ustar jenkinsjenkinsFacter.add(:foo, :name => :bar, :type => :aggregate) do end Facter.add(:foo, :name => :bar) do end facter-3.14.12/lib/tests/fixtures/ruby/existing_simple_resolution.rb0000644005276200011600000000014413702047406025575 0ustar jenkinsjenkinsFacter.add(:foo, :name => :bar) do end Facter.add(:foo, :name => :bar, :type => :aggregate) do end facter-3.14.12/lib/tests/fixtures/ruby/fact.rb0000644005276200011600000000025513702047406021027 0ustar jenkinsjenkinsFacter.add(:foo) do setcode do raise 'nope' unless Facter.fact('not_a_fact').nil? bar = Facter.fact('bar') bar.value unless bar.nil? end end facter-3.14.12/lib/tests/fixtures/ruby/facter.rb0000644005276200011600000000010613702047406021351 0ustar jenkinsjenkinsrequire 'facter' Facter.add(:foo) do setcode do 'bar' end endfacter-3.14.12/lib/tests/fixtures/ruby/facterversion.rb0000644005276200011600000000076613702047406022773 0ustar jenkinsjenkinsFacter.add(:facterversion) do setcode do # This tests a custom fact that attempts to override a built-in fact # but does not resolve to a value; the built-in fact should # not be overridden nil end end Facter.add(:facterversion) do setcode do # This tests a custom fact that attempts to override a built-in fact # but does not set a weight higher than 0; the built-in fact should not # be overridden 'overridden' end end facter-3.14.12/lib/tests/fixtures/ruby/hash_fact.rb0000644005276200011600000000025013702047406022025 0ustar jenkinsjenkinsFacter.add(:foo) do setcode do { :int => 1, :bool_true => true, :bool_false => false, :double => 12.34, :string => 'foo', :array => [1, 2, 3] } end end facter-3.14.12/lib/tests/fixtures/ruby/hash_with_non_string_key.rb0000644005276200011600000000007613702047406025201 0ustar jenkinsjenkinsFacter.add(:foo) do setcode do { foo: 'bar' } end end facter-3.14.12/lib/tests/fixtures/ruby/integer_fact.rb0000644005276200011600000000007413702047406022543 0ustar jenkinsjenkinsFacter.add(:foo) do setcode do 1234 end end facter-3.14.12/lib/tests/fixtures/ruby/log_exception.rb0000644005276200011600000000065113702047406022751 0ustar jenkinsjenkinsFacter.add(:foo) do setcode do begin raise "first" rescue Exception => ex Facter.log_exception ex end begin raise "second" rescue Exception => ex Facter.log_exception ex, :default end begin raise "nope" rescue Exception => ex Facter.log_exception ex, 'third' end end end facter-3.14.12/lib/tests/fixtures/ruby/lookup.rb0000644005276200011600000000024313702047406021420 0ustar jenkinsjenkinsFacter.add(:foo) do setcode do raise 'nope' unless Facter['not_a_fact'].nil? bar = Facter['bar'] bar.value unless bar.nil? end end facter-3.14.12/lib/tests/fixtures/ruby/multi_confine.rb0000644005276200011600000000020713702047406022742 0ustar jenkinsjenkinsFacter.add(:foo) do confine 'Fact1' => 'Value1', 'Fact2' => 'Value2', 'Fact3' => 'Value3' setcode do 'bar' end end facter-3.14.12/lib/tests/fixtures/ruby/named_resolution.rb0000644005276200011600000000035513702047406023462 0ustar jenkinsjenkinsFacter.add(:foo, :name => 'bar') do raise 'nope' unless name == 'bar' setcode do 'value1' end end Facter.add(:foo, :name => 'bar') do raise 'nope' unless name == 'bar' setcode do 'value2' end end facter-3.14.12/lib/tests/fixtures/ruby/negative_number.rb0000644005276200011600000000007413702047406023263 0ustar jenkinsjenkinsFacter.add(:foo) do setcode do -101 end end facter-3.14.12/lib/tests/fixtures/ruby/nil_fact.rb0000644005276200011600000000007313702047406021667 0ustar jenkinsjenkinsFacter.add(:foo) do setcode do nil end end facter-3.14.12/lib/tests/fixtures/ruby/nonexistent_command.rb0000644005276200011600000000073113702047406024165 0ustar jenkinsjenkinsFacter.add(:first) do setcode do next 'fail' unless Facter::Core::Execution.exec("does_not_exist || echo fail").nil? 'pass' end end Facter.add(:second) do setcode 'does_not_exist || echo fail' end Facter.add(:third) do setcode do begin Facter::Core::Execution.execute("does_not_exist || echo fail") rescue Facter::Core::Execution::ExecutionFailure next 'pass' end 'fail' end end facter-3.14.12/lib/tests/fixtures/ruby/on_message.rb0000644005276200011600000000063013702047406022227 0ustar jenkinsjenkinsdef test_message(level, message) Facter.on_message do |lvl, msg| raise 'nope' unless level == lvl raise 'nope' unless message = msg end begin Facter.debug message if level == :debug Facter.warn message if level == :warn rescue Exception => ex Facter.on_message end end test_message(:debug, "debug message") test_message(:warn, "warning message") facter-3.14.12/lib/tests/fixtures/ruby/range_confine.rb0000644005276200011600000000013113702047406022700 0ustar jenkinsjenkinsFacter.add(:foo) do confine :fact => (3..5) setcode do 'bar' end end facter-3.14.12/lib/tests/fixtures/ruby/regexp_confine.rb0000644005276200011600000000013013702047406023075 0ustar jenkinsjenkinsFacter.add(:foo) do confine :fact => /foo/ setcode do 'bar' end end facter-3.14.12/lib/tests/fixtures/ruby/ruby.rb0000644005276200011600000000012413702047406021066 0ustar jenkinsjenkinsFacter.add(:ruby) do has_weight 1 setcode do 'override' end end facter-3.14.12/lib/tests/fixtures/ruby/simple.rb0000644005276200011600000000017313702047406021402 0ustar jenkinsjenkinsFacter.add(:foo) do setcode do 'bar' end end Facter.add(:foo) do setcode do 'baz' end end facter-3.14.12/lib/tests/fixtures/ruby/simple_command.rb0000644005276200011600000000014313702047406023075 0ustar jenkinsjenkinsFacter.add(:foo) do setcode 'echo bar baz' end Facter.add(:foo) do setcode 'echo baz' end facter-3.14.12/lib/tests/fixtures/ruby/simple_confine.rb0000644005276200011600000000014313702047406023100 0ustar jenkinsjenkinsFacter.add(:foo) do confine 'SomeFact' => 'SomeValue' setcode do 'bar' end end facter-3.14.12/lib/tests/fixtures/ruby/simple_resolution.rb0000644005276200011600000000011713702047406023663 0ustar jenkinsjenkinsFacter.add(:foo, :type => :simple) do setcode do 'bar' end end facter-3.14.12/lib/tests/fixtures/ruby/single_allocation.rb0000644005276200011600000000040713702047406023577 0ustar jenkinsjenkinsFacter.add(:foo) do setcode do # Ensure that the same object is returned from Facter.value for built-in facts Facter.value(:facterversion) && Facter.value(:facterversion).object_id == Facter.value(:facterversion).object_id end end facter-3.14.12/lib/tests/fixtures/ruby/stderr_output.rb0000644005276200011600000000026713702047406023040 0ustar jenkinsjenkinsFacter.add(:first) do setcode do Facter::Core::Execution.exec("echo foo 1>&2 && echo bar") end end Facter.add(:second) do setcode 'echo foo 1>&2 && echo bar' end facter-3.14.12/lib/tests/fixtures/ruby/string_fact.rb0000644005276200011600000000010513702047406022407 0ustar jenkinsjenkinsFacter.add(:foo) do setcode do 'hello world' end end facter-3.14.12/lib/tests/fixtures/ruby/timeout.rb0000644005276200011600000000046713702047406021605 0ustar jenkinsjenkins# We should get a warning for using the timeout option Facter.add(:timeout, :name => 'bar', :timeout => 1000) do # And another warning for using timeout= self.timeout = 10 end # Try again to ensure only one warning each Facter.add(:timeout, :name => 'bar', :timeout => 100) do self.timeout = 1 end facter-3.14.12/lib/tests/fixtures/ruby/trace.rb0000644005276200011600000000060613702047406021210 0ustar jenkinsjenkinsbegin # Log without tracing Facter.trace false begin raise 'first' rescue Exception => ex Facter.log_exception ex end # Can be set Facter.trace true raise 'nope' unless Facter.trace? # Log with tracing begin raise 'second' rescue Exception => ex Facter.log_exception ex end ensure Facter.trace false end facter-3.14.12/lib/tests/fixtures/ruby/uniᐁdir/0000755005276200011600000000000013702047635022043 5ustar jenkinsjenkinsfacter-3.14.12/lib/tests/fixtures/ruby/uniᐁdir/customfacts™.rb0000644005276200011600000000012513702047406025725 0ustar jenkinsjenkins# encoding: utf-8 Facter.add('somefact™') do setcode do 'other™' end end facter-3.14.12/lib/tests/fixtures/ruby/uses_exit_code.rb0000644005276200011600000000025413702047406023113 0ustar jenkinsjenkinsFacter.add(:foo) do setcode do cmd = Gem.win_platform? ? 'cmd /k "exit 99"' : 'sh -c "exit 99"' Facter::Core::Execution.execute(cmd); $?.exitstatus end end facter-3.14.12/lib/tests/fixtures/ruby/value.rb0000644005276200011600000000020713702047406021223 0ustar jenkinsjenkinsFacter.add(:foo) do setcode do raise 'nope' unless Facter.value('not_a_fact').nil? Facter.value('bar') end end facter-3.14.12/lib/tests/fixtures/ruby/version.rb0000644005276200011600000000013013702047406021567 0ustar jenkinsjenkinsraise 'nope' unless Facter.version == Facter::FACTERVERSION Facter.debug Facter.version facter-3.14.12/lib/tests/fixtures/ruby/warn.rb0000644005276200011600000000017113702047406021056 0ustar jenkinsjenkinsFacter.add(:foo) do setcode do Facter.warn 'message1' Facter.warn 'message2' nil end end facter-3.14.12/lib/tests/fixtures/ruby/warnonce.rb0000644005276200011600000000034313702047406021724 0ustar jenkinsjenkinsFacter.add(:foo) do setcode do Facter.warnonce 'unique warning1' Facter.warnonce 'unique warning1' Facter.warnonce 'unique warning2' Facter.warnonce 'unique warning2' nil end end facter-3.14.12/lib/tests/fixtures/ruby/weight.rb0000644005276200011600000000037213702047406021401 0ustar jenkinsjenkinsFacter.add(:foo) do has_weight 100 setcode do 'value1' end end Facter.add(:foo) do has_weight 1000 setcode do 'value2' end end Facter.add(:foo) do has_weight 1 setcode do 'value3' end end facter-3.14.12/lib/tests/fixtures/ruby/weight_option.rb0000644005276200011600000000036113702047406022767 0ustar jenkinsjenkinsFacter.add(:foo, :weight => 100) do setcode do 'value1' end end Facter.add(:foo, :weight => 1000) do setcode do 'value2' end end Facter.add(:foo, :weight => 1) do setcode do 'value3' end end facter-3.14.12/lib/tests/fixtures/ruby/which.rb0000644005276200011600000000073013702047406021212 0ustar jenkinsjenkinsFacter.add(:foo) do setcode do raise 'nope' unless Facter::Core::Execution.which('not_a_command').nil? raise 'nope' if Facter::Core::Execution.which('sh').nil? && Facter::Core::Execution.which('cmd.exe').nil? raise 'nope' if (Facter::Core::Execution.which('sh') != Facter::Util::Resolution.which('sh')) || (Facter::Core::Execution.which('cmd.exe') != Facter::Util::Resolution.which('cmd.exe')) 'bar' end end facter-3.14.12/lib/tests/fixtures/ruby/windows/0000755005276200011600000000000013702047635021261 5ustar jenkinsjenkinsfacter-3.14.12/lib/tests/fixtures/ruby/windows/ole.rb0000644005276200011600000000023613702047406022362 0ustar jenkinsjenkinsFacter.add(:foo) do setcode do require 'win32ole' context = WIN32OLE.new('WbemScripting.SWbemNamedValueSet') 'bar' unless context.nil? end endfacter-3.14.12/lib/tests/java/0000755005276200011600000000000013702047635015656 5ustar jenkinsjenkinsfacter-3.14.12/lib/tests/java/facter.cc0000644005276200011600000000371513702047406017433 0ustar jenkinsjenkins#include #include #include #include #include #include "../fixtures.hpp" using namespace std; using namespace facter::facts; using namespace leatherman::execution; using namespace leatherman::util; using namespace boost::filesystem; using namespace facter::testing; SCENARIO("using libfacter from Java") { collection_fixture facts; facts.add_default_facts(true); path jar_path = path(BINARY_DIRECTORY) / "lib" / "facter.jar"; CAPTURE(JAVA_EXECUTABLE); CAPTURE(BINARY_DIRECTORY); CAPTURE(jar_path); GIVEN("the os fact") { try { auto exec = execute( JAVA_EXECUTABLE, { "-jar", jar_path.string(), "os" }, { { "FACTERDIR", BINARY_DIRECTORY } }, 0, { execution_options::trim_output, execution_options::merge_environment, execution_options::throw_on_failure }); CAPTURE(exec.output); CAPTURE(exec.error); THEN("the value should match") { REQUIRE(exec.success); ostringstream ss; auto value = facts["os"]; REQUIRE(value); value->write(ss); REQUIRE(exec.output == ss.str()); } } catch (child_exit_exception const& ex) { CAPTURE(ex.output()); CAPTURE(ex.error()); CAPTURE(ex.status_code()); FAIL("exception from child process."); } catch (child_signal_exception const& ex) { CAPTURE(ex.output()); CAPTURE(ex.error()); CAPTURE(ex.signal()); FAIL("signal from child process."); } } } facter-3.14.12/lib/tests/log_capture.cc0000644005276200011600000000114713702047406017547 0ustar jenkinsjenkins#include "log_capture.hpp" #include using namespace std; using namespace facter::logging; namespace facter { namespace testing { log_capture::log_capture(facter::logging::level level) { // Setup logging for capturing setup_logging(_stream); set_level(level); } log_capture::~log_capture() { // Cleanup setup_logging(boost::nowide::cout); set_level(level::none); clear_logged_errors(); } string log_capture::result() const { return _stream.str(); } }} // namespace facter::testing facter-3.14.12/lib/tests/log_capture.hpp0000644005276200011600000000144313702047406017750 0ustar jenkinsjenkins#pragma once #include #include #include namespace facter { namespace testing { /** * Utility class for capturing facter log output. */ struct log_capture { /** * Constructs the log capture and starts capturing log output. * @param level The log level to capture. */ explicit log_capture(facter::logging::level level); /** * Destructs the log capture and stops capturing log output. */ ~log_capture(); /** * Gets the captured log. * @return Returns the captured log as a single string. */ std::string result() const; private: std::ostringstream _stream; }; }} // namespace facter::testing facter-3.14.12/lib/tests/logging/0000755005276200011600000000000013702047635016363 5ustar jenkinsjenkinsfacter-3.14.12/lib/tests/logging/logging.cc0000644005276200011600000000457713702047406020331 0ustar jenkinsjenkins#include #include #include #include "../log_capture.hpp" using namespace std; using namespace facter::logging; using namespace leatherman::util; using namespace facter::testing; SCENARIO("logging with a TRACE level") { log_capture capture(level::trace); REQUIRE(is_enabled(level::trace)); log(level::trace, "testing %1% %2% %3%", 1, "2", 3.0); auto output = capture.result(); CAPTURE(output); REQUIRE(re_search(output, boost::regex("TRACE puppetlabs\\.facter - testing 1 2 3$"))); REQUIRE_FALSE(error_logged()); } SCENARIO("logging with a DEBUG level") { log_capture capture(level::debug); REQUIRE(is_enabled(level::debug)); log(level::debug, "testing %1% %2% %3%", 1, "2", 3.0); auto output = capture.result(); CAPTURE(output); REQUIRE(re_search(output, boost::regex("DEBUG puppetlabs\\.facter - testing 1 2 3$"))); REQUIRE_FALSE(error_logged()); } SCENARIO("logging with an INFO level") { log_capture capture(level::info); REQUIRE(is_enabled(level::info)); log(level::info, "testing %1% %2% %3%", 1, "2", 3.0); auto output = capture.result(); CAPTURE(output); REQUIRE(re_search(output, boost::regex("INFO puppetlabs\\.facter - testing 1 2 3$"))); REQUIRE_FALSE(error_logged()); } SCENARIO("logging with a WARNING level") { log_capture capture(level::warning); REQUIRE(is_enabled(level::warning)); log(level::warning, "testing %1% %2% %3%", 1, "2", 3.0); auto output = capture.result(); CAPTURE(output); REQUIRE(re_search(output, boost::regex("WARN puppetlabs\\.facter - testing 1 2 3"))); REQUIRE_FALSE(error_logged()); } SCENARIO("logging with an ERROR level") { log_capture capture(level::error); REQUIRE(is_enabled(level::error)); log(level::error, "testing %1% %2% %3%", 1, "2", 3.0); auto output = capture.result(); CAPTURE(output); REQUIRE(re_search(output, boost::regex("ERROR puppetlabs\\.facter - testing 1 2 3$"))); REQUIRE(error_logged()); } SCENARIO("logging with a FATAL level") { log_capture capture(level::fatal); REQUIRE(is_enabled(level::fatal)); log(level::fatal, "testing %1% %2% %3%", 1, "2", 3.0); auto output = capture.result(); CAPTURE(output); REQUIRE(re_search(output, boost::regex("FATAL puppetlabs\\.facter - testing 1 2 3$"))); REQUIRE(error_logged()); } facter-3.14.12/lib/tests/main.cc0000644005276200011600000000073313702047406016167 0ustar jenkinsjenkins#define CATCH_CONFIG_RUNNER #include #include #include #include using namespace std; using namespace facter::logging; int main(int argc, char **argv) { // Disable logging for tests setup_logging(boost::nowide::cout); set_level(level::none); // Before running tests, initialize Ruby facter::ruby::initialize(); return Catch::Session().run( argc, argv ); } facter-3.14.12/lib/tests/mock_server.cc0000644005276200011600000000233513702047406017562 0ustar jenkinsjenkins#include #include #include #include "mock_server.hpp" namespace facter { static void session(tcp::socket sock) { try { for (;;) { char data[1024]; boost::system::error_code error; sock.read_some(boost::asio::buffer(data), error); if (error == boost::asio::error::eof) { break; // Connection closed cleanly by peer. } else if (error) { throw boost::system::system_error(error); // Some other error. } std::string response = "HTTP/1.1 301 Moved Permanently\nContent-length: 0\nLocation: https://puppet.com/\nConnection: close\n\n"; boost::asio::write(sock, boost::asio::buffer(response)); } } catch (std::exception& e) { std::cerr << "Exception in thread: " << e.what() << "\n"; } } mock_server::mock_server(int port) : acceptor_(io_service_, tcp::endpoint(tcp::v4(), port)), socket_(io_service_) { acceptor_.async_accept(socket_, [this](boost::system::error_code ec) { if (!ec) session(std::move(socket_)); }); thread_ = boost::thread([this]() {io_service_.run_one();}); } mock_server::~mock_server() { thread_.join(); } } // namespace facter facter-3.14.12/lib/tests/mock_server.hpp0000644005276200011600000000105013702047406017755 0ustar jenkinsjenkins#pragma once #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wunused-variable" #pragma GCC diagnostic ignored "-Wstrict-aliasing" #include #include #pragma GCC diagnostic pop namespace facter { using boost::asio::ip::tcp; class mock_server { public: mock_server(int port); ~mock_server(); private: boost::asio::io_service io_service_; tcp::acceptor acceptor_; tcp::socket socket_; boost::thread thread_; }; } // namespace facter facter-3.14.12/lib/tests/ruby/0000755005276200011600000000000013702047635015716 5ustar jenkinsjenkinsfacter-3.14.12/lib/tests/ruby/ruby.cc0000644005276200011600000007343413702047406017215 0ustar jenkinsjenkins#include #include #include #include #include #include #include #include "./ruby_helper.hpp" #include "../collection_fixture.hpp" #include "../log_capture.hpp" using namespace std; using namespace facter::facts; using namespace facter::ruby; using namespace facter::logging; using namespace facter::testing; using namespace leatherman::util; using namespace leatherman::ruby; SCENARIO("custom facts written in Ruby") { collection_fixture facts; REQUIRE(facts.size() == 0u); // Setup ruby auto& ruby = api::instance(); REQUIRE(ruby.initialized()); ruby.include_stack_trace(true); GIVEN("a fact that resolves to nil") { REQUIRE(load_custom_fact("nil_fact.rb", facts)); THEN("the value should not be in the collection") { REQUIRE_FALSE(facts["foo"]); } } GIVEN("a fact that resolves to non-nil") { REQUIRE(load_custom_fact("simple.rb", facts)); THEN("the value should be in the collection") { REQUIRE(ruby_value_to_string(facts.get("foo")) == "\"bar\""); } } GIVEN("a fact with a simple resolution") { REQUIRE(load_custom_fact("simple_resolution.rb", facts)); THEN("the value should be in the collection") { REQUIRE(ruby_value_to_string(facts.get("foo")) == "\"bar\""); } } GIVEN("a fact without any resolutions") { WHEN("the fact has no explicit value") { REQUIRE(load_custom_fact("empty_fact.rb", facts)); THEN("the value should not be in the collection") { REQUIRE_FALSE(facts["foo"]); } } WHEN("the fact has an explicit value") { REQUIRE(load_custom_fact("empty_fact_with_value.rb", facts)); THEN("the value should be in the collection") { REQUIRE(ruby_value_to_string(facts.get("foo")) == "{\n int => 1,\n bool_true => true,\n bool_false => false,\n double => 12.34,\n string => \"foo\",\n array => [\n 1,\n 2,\n 3\n ]\n}"); } } } GIVEN("a fact with an empty command") { log_capture capture(level::error); REQUIRE_FALSE(load_custom_fact("empty_command.rb", facts)); THEN("an error is logged") { auto output = capture.result(); CAPTURE(output); REQUIRE(re_search(output, boost::regex("ERROR puppetlabs\\.facter - .* expected a non-empty String for first argument"))); } } GIVEN("a fact with a command") { REQUIRE(load_custom_fact("simple_command.rb", facts)); THEN("the value should be in the collection") { REQUIRE(ruby_value_to_string(facts.get("foo")) == "\"bar baz\""); } } GIVEN("a fact with a bad command") { THEN("the value should not be in the collection") { REQUIRE_FALSE(facts["foo"]); } } GIVEN("a fact with unicode characters in the path and name") { REQUIRE(load_custom_fact("uni\u1401dir/customfacts\u2122.rb", facts)); THEN("the value should be in the collection") { REQUIRE(ruby_value_to_string(facts.get("somefact\u2122")) == "\"other\u2122\""); } } GIVEN("a fact with a confine") { WHEN("the confine is met") { facts.add("somefact", make_value("SomeValue")); REQUIRE(load_custom_fact("simple_confine.rb", facts)); THEN("the value should be in the collection") { REQUIRE(ruby_value_to_string(facts.get("foo")) == "\"bar\""); } } WHEN("the confine is not met") { REQUIRE(load_custom_fact("simple_confine.rb", facts)); THEN("the value should not be in the collection") { REQUIRE_FALSE(facts["foo"]); } } WHEN("the multiple confines are present and one is not met") { facts.add("kernel", make_value("linux")); REQUIRE(load_custom_fact("confine_missing_fact.rb", facts)); THEN("the value should not be in the collection") { REQUIRE_FALSE(facts["foo"]); } } WHEN("multiple confines are met") { facts.add("fact1", make_value("VALUE1")); facts.add("fact2", make_value("Value2")); facts.add("fact3", make_value("value3")); REQUIRE(load_custom_fact("multi_confine.rb", facts)); THEN("the value should be in the collection") { REQUIRE(ruby_value_to_string(facts.get("foo")) == "\"bar\""); } } WHEN("none of the multiple confines are met") { REQUIRE(load_custom_fact("multi_confine.rb", facts)); THEN("the value should not be in the collection") { REQUIRE_FALSE(facts["foo"]); } } WHEN("the confine is a block that returns nil") { REQUIRE(load_custom_fact("block_nil_confine.rb", facts)); THEN("the value should not be in the collection") { REQUIRE_FALSE(facts["foo"]); } } WHEN("the confine is a block that evaluates to false") { REQUIRE(load_custom_fact("block_confine.rb", facts)); THEN("the value should not be in the collection") { REQUIRE_FALSE(facts["foo"]); } } WHEN("the confine is a block that simply returns false") { REQUIRE(load_custom_fact("block_false_confine.rb", facts)); THEN("the value should not be in the collection") { REQUIRE_FALSE(facts["foo"]); } } WHEN("the confine is a block that evaluates to true") { facts.add("fact1", make_value("value1")); REQUIRE(load_custom_fact("block_confine.rb", facts)); THEN("the value should be in the collection") { REQUIRE(ruby_value_to_string(facts.get("foo")) == "\"bar\""); } } WHEN("the confine is a block that simply returns true") { REQUIRE(load_custom_fact("block_true_confine.rb", facts)); THEN("the value should be in the collection") { REQUIRE(ruby_value_to_string(facts.get("foo")) == "\"bar\""); } } WHEN("the confine is an array and the value is not in the array") { facts.add("fact", make_value("foo")); REQUIRE(load_custom_fact("array_confine.rb", facts)); THEN("the value should not be in the collection") { REQUIRE_FALSE(facts["foo"]); } } WHEN("the confine is an array and the value is in the array") { facts.add("fact", make_value("value3")); REQUIRE(load_custom_fact("array_confine.rb", facts)); THEN("the value should be in the collection") { REQUIRE(ruby_value_to_string(facts.get("foo")) == "\"bar\""); } } WHEN("the confine is a regular expression that evaluates to true") { facts.add("fact", make_value("foo")); REQUIRE(load_custom_fact("regexp_confine.rb", facts)); THEN("the value should be in the collection") { REQUIRE(ruby_value_to_string(facts.get("foo")) == "\"bar\""); } } WHEN("the confine is a regular expression that evaluates to false") { facts.add("fact", make_value("baz")); REQUIRE(load_custom_fact("regexp_confine.rb", facts)); THEN("the value should not be in the collection") { REQUIRE_FALSE(facts["foo"]); } } WHEN("the confine is a range that evaluates to true") { facts.add("fact", make_value(4)); REQUIRE(load_custom_fact("range_confine.rb", facts)); THEN("the value should be in the collection") { REQUIRE(ruby_value_to_string(facts.get("foo")) == "\"bar\""); } } WHEN("the confine is a range that evaluates to false") { facts.add("fact", make_value(10)); REQUIRE(load_custom_fact("range_confine.rb", facts)); THEN("the value should not be in the collection") { REQUIRE_FALSE(facts["foo"]); } } WHEN("the confine evaluates to true") { facts.add("fact", make_value(true)); REQUIRE(load_custom_fact("boolean_true_confine.rb", facts)); THEN("the value should be in the collection") { REQUIRE(ruby_value_to_string(facts.get("foo")) == "\"bar\""); } } WHEN("the confine evaluates to false") { facts.add("fact", make_value(true)); REQUIRE(load_custom_fact("boolean_false_confine.rb", facts)); THEN("the value should not be in the collection") { REQUIRE_FALSE(facts["foo"]); } } THEN("resolution with the most confines wins") { facts.add("fact1", make_value("value1")); facts.add("fact2", make_value("value2")); facts.add("fact3", make_value("value3")); REQUIRE(load_custom_fact("confine_weight.rb", facts)); REQUIRE(ruby_value_to_string(facts.get("foo")) == "\"value2\""); } } GIVEN("a file with a syntax error") { log_capture capture(level::error); REQUIRE_FALSE(load_custom_fact("bad_syntax.rb", facts)); THEN("an error is logged") { auto output = capture.result(); CAPTURE(output); REQUIRE(re_search(output, boost::regex("ERROR puppetlabs\\.facter - .* undefined method `foo' for Facter:Module"))); } } GIVEN("a fact with weighted resolutions") { REQUIRE(load_custom_fact("weight.rb", facts)); THEN("the resolution with the highest weight wins") { REQUIRE(ruby_value_to_string(facts.get("foo")) == "\"value2\""); } } GIVEN("a fact with weight options") { REQUIRE(load_custom_fact("weight_option.rb", facts)); THEN("the resolution with the highest weight wins") { REQUIRE(ruby_value_to_string(facts.get("foo")) == "\"value2\""); } } GIVEN("a fact that resolves to a string value") { REQUIRE(load_custom_fact("string_fact.rb", facts)); THEN("the value is a string") { REQUIRE(ruby_value_to_string(facts.get("foo")) == "\"hello world\""); } } GIVEN("a fact that resolves to an integer value") { REQUIRE(load_custom_fact("integer_fact.rb", facts)); THEN("the value is an integer") { REQUIRE(ruby_value_to_string(facts.get("foo")) == "1234"); } } GIVEN("a fact that resolves to a true value") { REQUIRE(load_custom_fact("boolean_true_fact.rb", facts)); THEN("the value is true") { REQUIRE(ruby_value_to_string(facts.get("foo")) == "true"); } } GIVEN("a fact that resolves to a false value") { REQUIRE(load_custom_fact("boolean_false_fact.rb", facts)); THEN("the value is false") { REQUIRE(ruby_value_to_string(facts.get("foo")) == "false"); } } GIVEN("a fact that resolves to a double value") { REQUIRE(load_custom_fact("double_fact.rb", facts)); THEN("the value is a double") { REQUIRE(ruby_value_to_string(facts.get("foo")) == "12.34"); } } GIVEN("a fact that resolves to an array value") { REQUIRE(load_custom_fact("array_fact.rb", facts)); THEN("the value is an array") { REQUIRE(ruby_value_to_string(facts.get("foo")) == "[\n 1,\n true,\n false,\n \"foo\",\n 12.4,\n [\n 1\n ],\n {\n foo => \"bar\"\n }\n]"); } THEN("the members of the fact can be queried") { REQUIRE(ruby_value_to_string(facts.query("foo.5.0")) == "1"); } } GIVEN("a fact that resolves to a hash value") { REQUIRE(load_custom_fact("hash_fact.rb", facts)); THEN("the value is a hash") { REQUIRE(ruby_value_to_string(facts.get("foo")) == "{\n int => 1,\n bool_true => true,\n bool_false => false,\n double => 12.34,\n string => \"foo\",\n array => [\n 1,\n 2,\n 3\n ]\n}"); } THEN("the members of the fact can be queried") { REQUIRE(ruby_value_to_string(facts.query("foo.array.1")) == "2"); } } GIVEN("a fact that resolves using Facter.value") { facts.add("bar", make_value("baz")); REQUIRE(load_custom_fact("value.rb", facts)); THEN("the value should match") { REQUIRE(ruby_value_to_string(facts.get("foo")) == "\"baz\""); } } GIVEN("a fact that resolves using Facter.fact") { facts.add("bar", make_value("baz")); REQUIRE(load_custom_fact("fact.rb", facts)); THEN("the value should match") { REQUIRE(ruby_value_to_string(facts.get("foo")) == "\"baz\""); } } GIVEN("a fact that resolves using Facter[]") { facts.add("bar", make_value("baz")); REQUIRE(load_custom_fact("lookup.rb", facts)); THEN("the value should match") { REQUIRE(ruby_value_to_string(facts.get("foo")) == "\"baz\""); } } GIVEN("a fact that resolves when using Facter::Core::Execution#which") { REQUIRE(load_custom_fact("which.rb", facts)); THEN("the value should match") { REQUIRE(ruby_value_to_string(facts.get("foo")) == "\"bar\""); } } GIVEN("a fact that logs debug messages") { log_capture capture(level::debug); REQUIRE(load_custom_fact("debug.rb", facts)); THEN("the messages should be logged") { auto output = capture.result(); CAPTURE(output); REQUIRE(re_search(output, boost::regex("DEBUG puppetlabs\\.facter - message1"))); REQUIRE(re_search(output, boost::regex("DEBUG puppetlabs\\.facter - message2"))); } } GIVEN("a fact that logs debug messages only once") { log_capture capture(level::debug); REQUIRE(load_custom_fact("debugonce.rb", facts)); THEN("the messages should be logged") { auto output = capture.result(); CAPTURE(output); REQUIRE(re_search(output, boost::regex("DEBUG puppetlabs\\.facter - unique debug1"))); REQUIRE(re_search(output, boost::regex("DEBUG puppetlabs\\.facter - unique debug2"))); } } GIVEN("a fact that logs warning messages") { log_capture capture(level::warning); REQUIRE(load_custom_fact("warn.rb", facts)); THEN("the messages should be logged") { auto output = capture.result(); CAPTURE(output); REQUIRE(re_search(output, boost::regex("WARN puppetlabs\\.facter - message1"))); REQUIRE(re_search(output, boost::regex("WARN puppetlabs\\.facter - message2"))); } } GIVEN("a fact that logs warning messages only once") { log_capture capture(level::warning); REQUIRE(load_custom_fact("warnonce.rb", facts)); THEN("the messages should be logged") { auto output = capture.result(); CAPTURE(output); REQUIRE(re_search(output, boost::regex("WARN puppetlabs\\.facter - unique warning1"))); REQUIRE(re_search(output, boost::regex("WARN puppetlabs\\.facter - unique warning2"))); } } GIVEN("a fact that logs an exception") { log_capture capture(level::error); REQUIRE(load_custom_fact("log_exception.rb", facts)); THEN("an error should be logged") { auto output = capture.result(); CAPTURE(output); REQUIRE(re_search(output, boost::regex("ERROR puppetlabs\\.facter - first"))); REQUIRE(re_search(output, boost::regex("ERROR puppetlabs\\.facter - second"))); REQUIRE(re_search(output, boost::regex("ERROR puppetlabs\\.facter - third"))); } } GIVEN("a fact with a named resolution") { REQUIRE(load_custom_fact("named_resolution.rb", facts)); THEN("adding a resolution with the same name overrides the existing resolution") { REQUIRE(ruby_value_to_string(facts.get("foo")) == "\"value2\""); } } GIVEN("a fact added with define_fact and define_resolution") { REQUIRE(load_custom_fact("define_fact.rb", facts)); THEN("the value should be in the collection") { REQUIRE(ruby_value_to_string(facts.get("foo")) == "\"bar\""); } } GIVEN("a fact with a dependency cycle") { log_capture capture(level::error); REQUIRE(load_custom_fact("cycle.rb", facts)); THEN("an error is logged") { auto output = capture.result(); CAPTURE(output); REQUIRE(re_search(output, boost::regex("ERROR puppetlabs\\.facter - .* cycle detected while requesting value of fact \"bar\""))); } } GIVEN("an aggregate resolution with array chunks") { REQUIRE(load_custom_fact("aggregate.rb", facts)); THEN("the arrays are appended") { REQUIRE(ruby_value_to_string(facts.get("foo")) == "[\n \"foo\",\n \"bar\"\n]"); } } GIVEN("an aggregate resolution with required chunks") { REQUIRE(load_custom_fact("aggregate_with_require.rb", facts)); THEN("the arrays are appended in dependency order") { REQUIRE(ruby_value_to_string(facts.get("foo")) == "[\n \"foo\",\n \"bar\",\n \"foo\",\n \"baz\",\n \"foo\",\n \"bar\",\n \"foo\"\n]"); } } GIVEN("an aggregate resolution with an invalid require") { log_capture capture(level::error); REQUIRE_FALSE(load_custom_fact("aggregate_invalid_require.rb", facts)); THEN("the arrays are appended in dependency order") { auto output = capture.result(); CAPTURE(output); REQUIRE(re_search(output, boost::regex("ERROR puppetlabs\\.facter - .* expected a Symbol or Array of Symbol for require option"))); } } GIVEN("an aggregate resolution with a custom aggregator") { REQUIRE(load_custom_fact("aggregate_with_block.rb", facts)); THEN("the value should be what was returned from the block") { REQUIRE(ruby_value_to_string(facts.get("foo")) == "10"); } } GIVEN("an aggregate resolution with hashes to merge") { REQUIRE(load_custom_fact("aggregate_with_merge.rb", facts)); THEN("the value should be a deep merge of the hashes") { REQUIRE(ruby_value_to_string(facts.get("foo")) == "{\n foo => \"bar\",\n array => [\n 1,\n 2,\n 3,\n 4,\n 5,\n 6\n ],\n hash => {\n jam => \"cakes\",\n subarray => [\n \"hello\",\n \"world\"\n ],\n foo => \"bar\"\n },\n baz => \"jam\"\n}"); } } GIVEN("an aggregate resolution with an invalid require") { log_capture capture(level::error); REQUIRE(load_custom_fact("aggregate_with_invalid_merge.rb", facts)); THEN("an error is logged") { auto output = capture.result(); CAPTURE(output); REQUIRE(re_search(output, boost::regex("ERROR puppetlabs\\.facter - .* cannot merge \"hello\":String and \"world\":String"))); } } GIVEN("an aggregate resolution with a cycle") { log_capture capture(level::error); REQUIRE(load_custom_fact("aggregate_with_cycle.rb", facts)); THEN("an error is logged") { auto output = capture.result(); CAPTURE(output); REQUIRE(re_search(output, boost::regex("ERROR puppetlabs.facter - .* chunk dependency cycle detected"))); } } GIVEN("a fact with a defined aggregate resolution") { REQUIRE(load_custom_fact("define_aggregate_fact.rb", facts)); THEN("value should be in the collection") { REQUIRE(ruby_value_to_string(facts.get("foo")) == "[\n \"foo\",\n \"bar\"\n]"); } } GIVEN("an aggregate resolution when a simple resolution already exists") { log_capture capture(level::error); REQUIRE_FALSE(load_custom_fact("existing_simple_resolution.rb", facts)); THEN("an error is logged") { auto output = capture.result(); CAPTURE(output); REQUIRE(re_search(output, boost::regex("ERROR puppetlabs\\.facter - .* cannot define an aggregate resolution with name \"bar\": a simple resolution with the same name already exists"))); } } GIVEN("a simple resolution when an aggregate resolution already exists") { log_capture capture(level::error); REQUIRE_FALSE(load_custom_fact("existing_aggregate_resolution.rb", facts)); THEN("an error is logged") { auto output = capture.result(); CAPTURE(output); REQUIRE(re_search(output, boost::regex("ERROR puppetlabs\\.facter - .* cannot define a simple resolution with name \"bar\": an aggregate resolution with the same name already exists"))); } } GIVEN("a custom fact that logs the facter version") { log_capture capture(level::debug); REQUIRE(load_custom_fact("version.rb", facts)); THEN("the expected version is logged") { auto output = capture.result(); CAPTURE(output); REQUIRE(re_search(output, boost::regex("DEBUG puppetlabs\\.facter - " + (boost::format("%1%\\.%2%\\.%3%") % LIBFACTER_VERSION_MAJOR % LIBFACTER_VERSION_MINOR % LIBFACTER_VERSION_PATCH).str()))); } } GIVEN("a fact resolution that uses Facter::Core::Execution#exec") { REQUIRE(load_custom_fact("exec.rb", facts)); THEN("value should be in the collection") { REQUIRE(ruby_value_to_string(facts.get("foo")) == "\"bar baz\""); } } GIVEN("Facter::Core::Execution#execute with on_fail => :raise") { log_capture capture(level::error); REQUIRE_FALSE(load_custom_fact("execute_on_fail_raise.rb", facts)); THEN("an error is logged") { auto output = capture.result(); CAPTURE(output); REQUIRE(re_search(output, boost::regex("ERROR puppetlabs\\.facter - .* execution of command \"the_most_interesting_command_in_the_world\" failed"))); } } GIVEN("a fact resolution that uses Facter::Core::Execution#execute with a default value") { REQUIRE(load_custom_fact("execute_on_fail_value.rb", facts)); THEN("value should be in the collection") { REQUIRE(ruby_value_to_string(facts.get("foo")) == "\"default\""); } } GIVEN("a fact resolution that uses Facter::Core::Execution#execute with a timeout") { log_capture capture(level::error); REQUIRE_FALSE(load_custom_fact("execute_timeout.rb", facts)); THEN("an error is logged") { auto output = capture.result(); CAPTURE(output); REQUIRE(re_search(output, boost::regex("ERROR puppetlabs\\.facter - .* command timed out after 1 seconds"))); } } GIVEN("a fact that uses timeout") { log_capture capture(level::warning); REQUIRE(load_custom_fact("timeout.rb", facts)); THEN("a warning is logged") { auto output = capture.result(); CAPTURE(output); REQUIRE(re_search(output, boost::regex("WARN puppetlabs\\.facter - timeout option is not supported for custom facts and will be ignored.$"))); REQUIRE(re_search(output, boost::regex("WARN puppetlabs\\.facter - timeout= is not supported for custom facts and will be ignored.$"))); } } GIVEN("a fact that uses Facter#trace to enable backtraces") { log_capture capture(level::error); REQUIRE(load_custom_fact("trace.rb", facts)); THEN("backtraces are logged") { auto output = capture.result(); CAPTURE(output); REQUIRE(re_search(output, boost::regex("ERROR puppetlabs\\.facter - first"))); REQUIRE(re_search(output, boost::regex("ERROR puppetlabs\\.facter - second\\nbacktrace:"))); } } GIVEN("a fact that uses Facter#debugging to enable debug messages") { log_capture capture(level::debug); REQUIRE(load_custom_fact("debugging.rb", facts)); THEN("debug message is logged") { auto output = capture.result(); CAPTURE(output); REQUIRE(re_search(output, boost::regex("DEBUG puppetlabs\\.facter - yep"))); REQUIRE_FALSE(re_search(output, boost::regex("DEBUG puppetlabs\\.facter - nope"))); } } GIVEN("a custom on_message block") { log_capture capture(level::debug); REQUIRE(load_custom_fact("on_message.rb", facts)); THEN("no messages are logged") { REQUIRE_FALSE(re_search(capture.result(), boost::regex("debug message"))); } } GIVEN("a custom fact with a higher weight than a built-in fact") { REQUIRE(load_custom_fact("ruby.rb", facts)); THEN("the custom fact wins") { REQUIRE(ruby_value_to_string(facts.get("ruby")) == "\"override\""); } } GIVEN("a custom fact with the same weight as a built-in fact") { REQUIRE(load_custom_fact("facterversion.rb", facts)); THEN("the built-in fact wins") { REQUIRE(ruby_value_to_string(facts["facterversion"]) == "\"" LIBFACTER_VERSION "\""); } } GIVEN("a fact value from the environment") { scoped_env var("FACTER_RuBy", "from environment!"); REQUIRE(load_custom_fact("ruby.rb", facts)); THEN("the value from the environment wins") { REQUIRE(ruby_value_to_string(facts["ruby"]) == "\"from environment!\""); } } GIVEN("a hash value with non-string keys") { REQUIRE(load_custom_fact("hash_with_non_string_key.rb", facts)); THEN("the keys are converted to strings") { REQUIRE(ruby_value_to_string(facts.get("foo")) == "{\n foo => \"bar\"\n}"); } } GIVEN("a fact that requires facter") { REQUIRE(load_custom_fact("facter.rb", facts)); THEN("the require succeeds") { REQUIRE(ruby_value_to_string(facts.get("foo")) == "\"bar\""); } } GIVEN("a fact that has 100 resolutions") { REQUIRE(load_custom_fact("100_resolutions.rb", facts)); THEN("the fact evaluates") { REQUIRE(ruby_value_to_string(facts.get("foo")) == "\"bar\""); } } GIVEN("a fact that has 101 resolutions") { log_capture capture(level::error); REQUIRE_FALSE(load_custom_fact("101_resolutions.rb", facts)); THEN("an error is logged") { auto output = capture.result(); CAPTURE(output); REQUIRE(re_search(output, boost::regex("ERROR puppetlabs\\.facter - .* fact \"foo\" already has the maximum number of resolutions allowed \\(100\\)"))); } } GIVEN("a fact that runs a command outputting to stderr") { REQUIRE(load_custom_fact("stderr_output.rb", facts)); THEN("the values should only contain stdout output") { REQUIRE(ruby_value_to_string(facts.get("first")) == "\"bar\""); REQUIRE(ruby_value_to_string(facts.get("second")) == "\"bar\""); } } GIVEN("a fact that runs a setcode command that returns no output") { REQUIRE(load_custom_fact("empty_setcode_command.rb", facts)); THEN("the fact should not resolve") { REQUIRE_FALSE(facts["foo"]); } } GIVEN("a fact that runs executes nonexistent commands") { REQUIRE(load_custom_fact("nonexistent_command.rb", facts)); THEN("the fact should not resolve") { REQUIRE(ruby_value_to_string(facts.get("first")) == "\"pass\""); REQUIRE_FALSE(facts["second"]); REQUIRE(ruby_value_to_string(facts.get("third")) == "\"pass\""); } } GIVEN("a fact that executes a command that returns non-zero") { REQUIRE(load_custom_fact("execution_failure.rb", facts)); THEN("the fact value should be the command's output") { REQUIRE(ruby_value_to_string(facts.get("foo")) == "\"bar\""); } } GIVEN("a built-in fact requested multiple times") { REQUIRE(load_custom_fact("single_allocation.rb", facts)); THEN("the value should be properly cached between Facter.value calls") { REQUIRE(ruby_value_to_string(facts.get("foo")) == "true"); } } GIVEN("a fact that returns a negative number") { REQUIRE(load_custom_fact("negative_number.rb", facts)); THEN("the value should be output as a signed value") { REQUIRE(ruby_value_to_string(facts.get("foo")) == "-101"); } } GIVEN("a fact that returns the exit code of its command") { REQUIRE(load_custom_fact("uses_exit_code.rb", facts)); THEN("the value should be the exit code") { REQUIRE(ruby_value_to_string(facts.get("foo")) == "99"); } } GIVEN("a fact that returns a number larger than 32-bits") { REQUIRE(load_custom_fact("bignum_fact_value.rb", facts)); THEN("the value should be output correctly") { REQUIRE(ruby_value_to_string(facts.get("bignum_fact")) == "12345678901"); } } } facter-3.14.12/lib/tests/ruby/ruby_dirfacts.cc0000644005276200011600000000203413702047406021060 0ustar jenkinsjenkins#include #include #include #include #include #include "../fixtures.hpp" #include "../collection_fixture.hpp" #include "./ruby_helper.hpp" #include "../mock_server.hpp" using namespace std; using namespace facter::ruby; using namespace facter::testing; using namespace leatherman::ruby; SCENARIO("directories of custom facts written in Ruby") { collection_fixture facts; REQUIRE(facts.size() == 0u); // Setup ruby auto& ruby = api::instance(); REQUIRE(ruby.initialized()); ruby.include_stack_trace(true); string fixtures = LIBFACTER_TESTS_DIRECTORY "/fixtures/ruby/"; GIVEN("a fact that performs network activity") { facter::mock_server m(42000); load_custom_facts(facts, vector{fixtures+"custom_dir"}); THEN("the network location should resolve") { REQUIRE(ruby_value_to_string(facts.get("sometest")) == "\"Yay\""); } } } facter-3.14.12/lib/tests/ruby/ruby_helper.cc0000644005276200011600000000214713702047406020545 0ustar jenkinsjenkins#include "ruby_helper.hpp" #include #include #include #include "../fixtures.hpp" using namespace std; using namespace facter::ruby; using namespace facter::facts; using namespace leatherman::ruby; bool load_custom_fact(string const& filename, collection& facts) { auto& ruby = api::instance(); module mod(facts); string file = LIBFACTER_TESTS_DIRECTORY "/fixtures/ruby/" + filename; VALUE result = ruby.rescue([&]() { // Do not construct C++ objects in a rescue callback // C++ stack unwinding will not take place if a Ruby exception is thrown! ruby.rb_load(ruby.utf8_value(file), 0); return ruby.true_value(); }, [&](VALUE ex) { LOG_ERROR("error while resolving custom facts in {1}: {2}", file, ruby.exception_to_string(ex)); return ruby.false_value(); }); mod.resolve_facts(); return ruby.is_true(result); } string ruby_value_to_string(value const* value) { ostringstream ss; if (value) { value->write(ss); } return ss.str(); } facter-3.14.12/lib/tests/ruby/ruby_helper.hpp0000644005276200011600000000040513702047406020742 0ustar jenkinsjenkins#pragma once #include #include #include bool load_custom_fact(std::string const& filename, facter::facts::collection& facts); std::string ruby_value_to_string(facter::facts::value const* value); facter-3.14.12/lib/tests/ruby/windows/0000755005276200011600000000000013702047635017410 5ustar jenkinsjenkinsfacter-3.14.12/lib/tests/ruby/windows/ruby.cc0000644005276200011600000000327713702047406020705 0ustar jenkinsjenkins#include #include #include #include #include #include "../ruby_helper.hpp" #include "../../collection_fixture.hpp" #include "../../fixtures.hpp" using namespace std; using namespace facter::testing; using namespace facter::ruby; using namespace leatherman::ruby; using namespace leatherman::util; SCENARIO("Windows custom facts written in Ruby") { collection_fixture facts; REQUIRE(facts.size() == 0u); // Setup ruby auto& ruby = api::instance(); REQUIRE(ruby.initialized()); ruby.include_stack_trace(true); GIVEN("a fact that loads win32ole") { REQUIRE(load_custom_fact("windows/ole.rb", facts)); THEN("the value should be in the collection") { REQUIRE(ruby_value_to_string(facts.get("foo")) == "\"bar\""); } } } SCENARIO("Run command with space in path") { collection_fixture facts; REQUIRE(facts.size() == 0u); // Setup ruby auto& ruby = api::instance(); REQUIRE(ruby.initialized()); ruby.include_stack_trace(true); GIVEN("a directory with a space on the PATH") { string path; environment::get("PATH", path); scoped_env var("PATH", path + environment::get_path_separator() + LIBFACTER_TESTS_DIRECTORY "/fixtures/execution/with space"); environment::reload_search_paths(); REQUIRE(load_custom_fact("command_with_space.rb", facts)); THEN("the command should execute successfully") { REQUIRE(ruby_value_to_string(facts.get("foo")) == "\"bar\""); } } environment::reload_search_paths(); } facter-3.14.12/lib/tests/util/0000755005276200011600000000000013702047635015712 5ustar jenkinsjenkinsfacter-3.14.12/lib/tests/util/bsd/0000755005276200011600000000000013702047635016462 5ustar jenkinsjenkinsfacter-3.14.12/lib/tests/util/bsd/scoped_ifaddrs.cc0000644005276200011600000000036213702047406021737 0ustar jenkinsjenkins#include #include using namespace std; using namespace facter::util::bsd; SCENARIO("constructing a scoped_ifaddrs") { scoped_ifaddrs addrs; REQUIRE(static_cast(addrs)); } facter-3.14.12/lib/tests/util/posix/0000755005276200011600000000000013702047635017054 5ustar jenkinsjenkinsfacter-3.14.12/lib/tests/util/posix/scoped_addrinfo.cc0000644005276200011600000000044613702047406022506 0ustar jenkinsjenkins#include #include using namespace std; using namespace facter::util::posix; SCENARIO("constructing a scoped_addrinfo") { scoped_addrinfo info("localhost"); REQUIRE(info.result() == 0); REQUIRE(static_cast(info)); } facter-3.14.12/lib/tests/util/posix/scoped_descriptor.cc0000644005276200011600000000112013702047406023064 0ustar jenkinsjenkins#include #include #include #include using namespace std; using namespace facter::util::posix; SCENARIO("constructing a POSIX scoped descriptor") { int sock = socket(AF_INET, SOCK_DGRAM, 0); { scoped_descriptor scoped(sock); } // This check could theoretically fail if the OS reassigns the file // descriptor between the above destructor call and this line // This likely will not happen during testing. REQUIRE(fcntl(sock, F_GETFD) == -1); REQUIRE(errno == EBADF); } facter-3.14.12/lib/tests/util/scoped_bio.cc0000644005276200011600000000047513702047406020331 0ustar jenkinsjenkins#pragma clang diagnostic ignored "-Wdeprecated-declarations" #include #include #include using namespace std; using namespace facter::util; SCENARIO("constructing a scoped_bio") { scoped_bio b64((BIO_f_base64())); REQUIRE(static_cast(b64)); } facter-3.14.12/lib/tests/util/string.cc0000644005276200011600000002267013702047406017532 0ustar jenkinsjenkins#include #include using namespace std; using namespace facter::util; SCENARIO("converting bytes to hex strings") { uint8_t buffer[] = { 0xBA, 0xAD, 0xF0, 0x0D }; WHEN("specifying uppercase") { THEN("hex characters should be uppercase") { REQUIRE(to_hex(buffer, sizeof(buffer), true) == "BAADF00D"); } } WHEN("specifying the default lowercase") { THEN("hex characters should be lowercase") { REQUIRE(to_hex(buffer, sizeof(buffer)) == "baadf00d"); } } GIVEN("a null buffer") { THEN("an empty string should be returned") { REQUIRE(to_hex(nullptr, 0) == ""); } } GIVEN("an empty buffer") { THEN("an empty string should be returned") { REQUIRE(to_hex(buffer, 0) == ""); } } } SCENARIO("converting bytes to SI unit strings") { GIVEN("zero bytes") { THEN("the string should show 0 bytes") { REQUIRE(si_string(0) == "0 bytes"); } } GIVEN("less than 1 KiB") { WHEN("not close to 1 KiB") { THEN("the string should be in bytes") { REQUIRE(si_string(100) == "100 bytes"); } } WHEN("close to 1 KiB") { THEN("the string should be in bytes") { REQUIRE(si_string(1023) == "1023 bytes"); } } } GIVEN("exactly 1 KiB") { THEN("the string should be in KiB") { REQUIRE(si_string(1024) == "1.00 KiB"); } } GIVEN("less than 1 MiB") { WHEN("not close to 1 MiB") { THEN("the string should be in KiB") { REQUIRE(si_string(4097) == "4.00 KiB"); } } WHEN("almost 1 MiB") { THEN("the string should be in MiB") { REQUIRE(si_string((1024ull * 1024ull) - 1) == "1.00 MiB"); } } } GIVEN("exactly 1 MiB") { THEN("the string should be in MiB") { REQUIRE(si_string(1024ull * 1024ull) == "1.00 MiB"); } } GIVEN("less than 1 GiB") { WHEN("not close to 1 GiB") { THEN("the string should be in MiB") { REQUIRE(si_string(10ull * 1024ull * 1023ull) == "9.99 MiB"); } } WHEN("almost 1 GiB") { THEN("the string should be in GiB") { REQUIRE(si_string((1024ull * 1024ull * 1024ull) - 1) == "1.00 GiB"); } } } GIVEN("exactly 1 GiB") { THEN("the string should be in GiB") { REQUIRE(si_string(1024ull * 1024ull * 1024ull) == "1.00 GiB"); } } GIVEN("less than 1 TiB") { WHEN("not close to 1 TiB") { THEN("the string should be in GiB") { REQUIRE(si_string(12ull * 1024ull * 1024ull * 1023ull) == "11.99 GiB"); } } WHEN("almost 1 TiB") { THEN("the string should be in TiB") { REQUIRE(si_string((1024ull * 1024ull * 1024ull * 1024ull) - 1) == "1.00 TiB"); } } } GIVEN("exactly 1 TiB") { THEN("the string should be in TiB") { REQUIRE(si_string(1024ull * 1024ull * 1024ull * 1024ull) == "1.00 TiB"); } } GIVEN("less than 1 PiB") { WHEN("not close to 1 PiB") { THEN("the string should be in TiB") { REQUIRE(si_string(50ull * 1024ull * 1024ull * 1024ull * 1023ull) == "49.95 TiB"); } } WHEN("almost 1 PiB") { THEN("the string should be in PiB") { REQUIRE(si_string((1024ull * 1024ull * 1024ull * 1024ull * 1024ull) - 1) == "1.00 PiB"); } } } GIVEN("exactly 1 PiB") { THEN("the string should be in PiB") { REQUIRE(si_string(1024ull * 1024ull * 1024ull * 1024ull * 1024ull) == "1.00 PiB"); } } GIVEN("less than 1 EiB") { WHEN("not close to 1 EiB") { THEN("the string should be in PiB") { REQUIRE(si_string(100ull * 1024ull * 1024ull * 1024ull * 1024ull * 1023ull) == "99.90 PiB"); } } WHEN("almost 1 EiB") { THEN("the string should be in EiB") { REQUIRE(si_string((1024ull * 1024ull * 1024ull * 1024ull * 1024ull * 1024ull) - 1) == "1.00 EiB"); } } } GIVEN("exactly 1 EiB") { THEN("the string should be in PiB") { REQUIRE(si_string(1024ull * 1024ull * 1024ull * 1024ull * 1024ull * 1024ull) == "1.00 EiB"); } } GIVEN("the unsigned maximum 64-bit value") { THEN("the string should be in EiB") { REQUIRE(si_string(numeric_limits::max()) == "16.00 EiB"); } } } SCENARIO("converting percentages to strings") { GIVEN("any value out of zero") { THEN("it should be 100%") { REQUIRE(percentage(0, 0) == "100%"); REQUIRE(percentage(10000, 0) == "100%"); } } GIVEN("zero out of any value") { THEN("it should be 0%") { REQUIRE(percentage(0, 10) == "0%"); REQUIRE(percentage(0, 100) == "0%"); } } GIVEN("more than the maximum") { THEN("it should be 100%") { REQUIRE(percentage(1000, 100) == "100%"); } } GIVEN("small percentages") { THEN("it should round to the nearest hundred of a percent") { REQUIRE(percentage(1, 100) == "1.00%"); REQUIRE(percentage(11, 1000) == "1.10%"); REQUIRE(percentage(111, 10000) == "1.11%"); REQUIRE(percentage(1140000000ul, 50000000000ul) == "2.28%"); REQUIRE(percentage(1000, 10000) == "10.00%"); } } GIVEN("large percentages") { THEN("it should round to the nearest hundred of a percent, but never 100%") { REQUIRE(percentage(414906340801ul, 560007030104ul) == "74.09%"); REQUIRE(percentage(99984, 100000) == "99.98%"); REQUIRE(percentage(999899, 1000000) == "99.99%"); REQUIRE(percentage(99999, 100000) == "99.99%"); } } GIVEN("the maximum value") { WHEN("off by one") { THEN("it should not be 100%") { REQUIRE(percentage(numeric_limits::max() - 1, numeric_limits::max()) == "99.99%"); } } WHEN("both are maximum") { THEN("it should be 100%") { REQUIRE(percentage(numeric_limits::max(), numeric_limits::max()) == "100%"); } } } } SCENARIO("converting frequencies to strings") { GIVEN("a frequency of 0") { THEN("it should report in Hz") { REQUIRE(frequency(0) == "0 Hz"); } } GIVEN("a frequency of less than 1 kHz") { WHEN("not close to 1 kHz") { THEN("it should be in Hz") { REQUIRE(frequency(100) == "100 Hz"); } } WHEN("close to 1 kHz") { THEN("it should be in Hz") { REQUIRE(frequency(999) == "999 Hz"); } } } GIVEN("exactly 1 kHz") { THEN("it should be in kHz") { REQUIRE(frequency(1000) == "1.00 kHz"); } } GIVEN("a frequency of less than 1 MHz") { WHEN("not close to 1 MHz") { THEN("it should be in kHz") { REQUIRE(frequency(1000 * 999) == "999.00 kHz"); } } WHEN("close to 1 MHz") { THEN("it should be in MHz") { REQUIRE(frequency((1000 * 1000) - 1) == "1.00 MHz"); } } } GIVEN("exactly 1 MHz") { THEN("it should be in MHz") { REQUIRE(frequency(1000 * 1000) == "1.00 MHz"); } } GIVEN("a frequency of less than 1 GHz") { WHEN("not close to 1 GHz") { THEN("it should be in MHz") { REQUIRE(frequency(1000 * 1000 * 999) == "999.00 MHz"); } } WHEN("close to 1 GHz") { THEN("it should be in GHz") { REQUIRE(frequency((1000 * 1000 * 1000) - 1) == "1.00 GHz"); } } } GIVEN("exactly 1 GHz") { THEN("it should be in GHz") { REQUIRE(frequency(1000 * 1000 * 1000) == "1.00 GHz"); } } GIVEN("a frequency of less than 1 THz") { WHEN("not close to 1 THz") { THEN("it should be in GHz") { REQUIRE(frequency(1000ull * 1000 * 1000 * 999) == "999.00 GHz"); } } WHEN("close to 1 THz") { THEN("it should be in THz") { REQUIRE(frequency((1000ull * 1000 * 1000 * 1000) - 1) == "1.00 THz"); } } } GIVEN("exactly 1 THz") { THEN("it should be in THz") { REQUIRE(frequency(1000ull * 1000 * 1000 * 1000) == "1.00 THz"); } } GIVEN("the maximum value") { THEN("it should be in Hz") { REQUIRE(frequency(numeric_limits::max()) == "9223372036854775807 Hz"); } } } SCENARIO("converting strings to integers") { GIVEN("a string that is a valid integer") { THEN("it should be converted to its integer representation") { auto oint = maybe_stoi("12"); REQUIRE(oint.is_initialized()); REQUIRE(oint.get_value_or(0) == 12); } } GIVEN("a string that is not a valid integer") { THEN("nothing should be returned") { REQUIRE_FALSE(maybe_stoi("foo").is_initialized()); } } } facter-3.14.12/lib/version.h.in0000644005276200011600000000122313702047406016030 0ustar jenkinsjenkins/// /// @file /// Declares macros for the facter library version. /// #pragma once /// /// The facter library major version. /// #define LIBFACTER_VERSION_MAJOR @PROJECT_VERSION_MAJOR@ /// /// The facter library minor version. /// #define LIBFACTER_VERSION_MINOR @PROJECT_VERSION_MINOR@ /// /// The facter library patch version. /// #define LIBFACTER_VERSION_PATCH @PROJECT_VERSION_PATCH@ /// /// The facter library version as a string (without commit SHA1). /// #define LIBFACTER_VERSION "@PROJECT_VERSION@" /// /// The facter library version as a string (with commit SHA1). /// #define LIBFACTER_VERSION_WITH_COMMIT "@PROJECT_VERSION@@LIBFACTER_COMMIT@" facter-3.14.12/lib/Doxyfile0000644005276200011600000030473713702047406015313 0ustar jenkinsjenkins# Doxyfile 1.8.7 # This file describes the settings to be used by the documentation system # doxygen (www.doxygen.org) for a project. # # All text after a double hash (##) is considered a comment and is placed in # front of the TAG it is preceding. # # All text after a single hash (#) is considered a comment and will be ignored. # The format is: # TAG = value [value, ...] # For lists, items can also be appended using: # TAG += value [value, ...] # Values that contain spaces should be placed between quotes (\" \"). #--------------------------------------------------------------------------- # Project related configuration options #--------------------------------------------------------------------------- # This tag specifies the encoding used for all characters in the config file # that follow. The default is UTF-8 which is also the encoding used for all text # before the first occurrence of this tag. Doxygen uses libiconv (or the iconv # built into libc) for the transcoding. See http://www.gnu.org/software/libiconv # for the list of possible encodings. # The default value is: UTF-8. DOXYFILE_ENCODING = UTF-8 # The PROJECT_NAME tag is a single word (or a sequence of words surrounded by # double-quotes, unless you are using Doxywizard) that should identify the # project for which the documentation is generated. This name is used in the # title of most generated pages and in a few other places. # The default value is: My Project. PROJECT_NAME = facter # The PROJECT_NUMBER tag can be used to enter a project or revision number. This # could be handy for archiving the generated documentation or if some version # control system is used. PROJECT_NUMBER = 3.14.12 # Using the PROJECT_BRIEF tag one can provide an optional one line description # for a project that appears at the top of each page and should give viewer a # quick idea about the purpose of the project. Keep the description short. PROJECT_BRIEF = # With the PROJECT_LOGO tag one can specify an logo or icon that is included in # the documentation. The maximum height of the logo should not exceed 55 pixels # and the maximum width should not exceed 200 pixels. Doxygen will copy the logo # to the output directory. PROJECT_LOGO = # The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) path # into which the generated documentation will be written. If a relative path is # entered, it will be relative to the location where doxygen was started. If # left blank the current directory will be used. OUTPUT_DIRECTORY = # If the CREATE_SUBDIRS tag is set to YES, then doxygen will create 4096 sub- # directories (in 2 levels) under the output directory of each output format and # will distribute the generated files over these directories. Enabling this # option can be useful when feeding doxygen a huge amount of source files, where # putting all generated files in the same directory would otherwise causes # performance problems for the file system. # The default value is: NO. CREATE_SUBDIRS = NO # If the ALLOW_UNICODE_NAMES tag is set to YES, doxygen will allow non-ASCII # characters to appear in the names of generated files. If set to NO, non-ASCII # characters will be escaped, for example _xE3_x81_x84 will be used for Unicode # U+3044. # The default value is: NO. ALLOW_UNICODE_NAMES = NO # The OUTPUT_LANGUAGE tag is used to specify the language in which all # documentation generated by doxygen is written. Doxygen will use this # information to generate all constant output in the proper language. # Possible values are: Afrikaans, Arabic, Armenian, Brazilian, Catalan, Chinese, # Chinese-Traditional, Croatian, Czech, Danish, Dutch, English (United States), # Esperanto, Farsi (Persian), Finnish, French, German, Greek, Hungarian, # Indonesian, Italian, Japanese, Japanese-en (Japanese with English messages), # Korean, Korean-en (Korean with English messages), Latvian, Lithuanian, # Macedonian, Norwegian, Persian (Farsi), Polish, Portuguese, Romanian, Russian, # Serbian, Serbian-Cyrillic, Slovak, Slovene, Spanish, Swedish, Turkish, # Ukrainian and Vietnamese. # The default value is: English. OUTPUT_LANGUAGE = English # If the BRIEF_MEMBER_DESC tag is set to YES doxygen will include brief member # descriptions after the members that are listed in the file and class # documentation (similar to Javadoc). Set to NO to disable this. # The default value is: YES. BRIEF_MEMBER_DESC = YES # If the REPEAT_BRIEF tag is set to YES doxygen will prepend the brief # description of a member or function before the detailed description # # Note: If both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the # brief descriptions will be completely suppressed. # The default value is: YES. REPEAT_BRIEF = YES # This tag implements a quasi-intelligent brief description abbreviator that is # used to form the text in various listings. Each string in this list, if found # as the leading text of the brief description, will be stripped from the text # and the result, after processing the whole list, is used as the annotated # text. Otherwise, the brief description is used as-is. If left blank, the # following values are used ($name is automatically replaced with the name of # the entity):The $name class, The $name widget, The $name file, is, provides, # specifies, contains, represents, a, an and the. ABBREVIATE_BRIEF = # If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then # doxygen will generate a detailed section even if there is only a brief # description. # The default value is: NO. ALWAYS_DETAILED_SEC = YES # If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all # inherited members of a class in the documentation of that class as if those # members were ordinary class members. Constructors, destructors and assignment # operators of the base classes will not be shown. # The default value is: NO. INLINE_INHERITED_MEMB = YES # If the FULL_PATH_NAMES tag is set to YES doxygen will prepend the full path # before files name in the file list and in the header files. If set to NO the # shortest path that makes the file name unique will be used # The default value is: YES. FULL_PATH_NAMES = YES # The STRIP_FROM_PATH tag can be used to strip a user-defined part of the path. # Stripping is only done if one of the specified strings matches the left-hand # part of the path. The tag can be used to show relative paths in the file list. # If left blank the directory from which doxygen is run is used as the path to # strip. # # Note that you can specify absolute paths here, but also relative paths, which # will be relative from the directory where doxygen is started. # This tag requires that the tag FULL_PATH_NAMES is set to YES. STRIP_FROM_PATH = inc/ # The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of the # path mentioned in the documentation of a class, which tells the reader which # header file to include in order to use a class. If left blank only the name of # the header file containing the class definition is used. Otherwise one should # specify the list of include paths that are normally passed to the compiler # using the -I flag. STRIP_FROM_INC_PATH = # If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter (but # less readable) file names. This can be useful is your file systems doesn't # support long names like on DOS, Mac, or CD-ROM. # The default value is: NO. SHORT_NAMES = NO # If the JAVADOC_AUTOBRIEF tag is set to YES then doxygen will interpret the # first line (until the first dot) of a Javadoc-style comment as the brief # description. If set to NO, the Javadoc-style will behave just like regular Qt- # style comments (thus requiring an explicit @brief command for a brief # description.) # The default value is: NO. JAVADOC_AUTOBRIEF = YES # If the QT_AUTOBRIEF tag is set to YES then doxygen will interpret the first # line (until the first dot) of a Qt-style comment as the brief description. If # set to NO, the Qt-style will behave just like regular Qt-style comments (thus # requiring an explicit \brief command for a brief description.) # The default value is: NO. QT_AUTOBRIEF = NO # The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make doxygen treat a # multi-line C++ special comment block (i.e. a block of //! or /// comments) as # a brief description. This used to be the default behavior. The new default is # to treat a multi-line C++ comment block as a detailed description. Set this # tag to YES if you prefer the old behavior instead. # # Note that setting this tag to YES also means that rational rose comments are # not recognized any more. # The default value is: NO. MULTILINE_CPP_IS_BRIEF = NO # If the INHERIT_DOCS tag is set to YES then an undocumented member inherits the # documentation from any documented member that it re-implements. # The default value is: YES. INHERIT_DOCS = YES # If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce a # new page for each member. If set to NO, the documentation of a member will be # part of the file/class/namespace that contains it. # The default value is: NO. SEPARATE_MEMBER_PAGES = NO # The TAB_SIZE tag can be used to set the number of spaces in a tab. Doxygen # uses this value to replace tabs by spaces in code fragments. # Minimum value: 1, maximum value: 16, default value: 4. TAB_SIZE = 4 # This tag can be used to specify a number of aliases that act as commands in # the documentation. An alias has the form: # name=value # For example adding # "sideeffect=@par Side Effects:\n" # will allow you to put the command \sideeffect (or @sideeffect) in the # documentation, which will result in a user-defined paragraph with heading # "Side Effects:". You can put \n's in the value part of an alias to insert # newlines. ALIASES = # This tag can be used to specify a number of word-keyword mappings (TCL only). # A mapping has the form "name=value". For example adding "class=itcl::class" # will allow you to use the command class in the itcl::class meaning. TCL_SUBST = # Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources # only. Doxygen will then generate output that is more tailored for C. For # instance, some of the names that are used will be different. The list of all # members will be omitted, etc. # The default value is: NO. OPTIMIZE_OUTPUT_FOR_C = NO # Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java or # Python sources only. Doxygen will then generate output that is more tailored # for that language. For instance, namespaces will be presented as packages, # qualified scopes will look different, etc. # The default value is: NO. OPTIMIZE_OUTPUT_JAVA = NO # Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran # sources. Doxygen will then generate output that is tailored for Fortran. # The default value is: NO. OPTIMIZE_FOR_FORTRAN = NO # Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL # sources. Doxygen will then generate output that is tailored for VHDL. # The default value is: NO. OPTIMIZE_OUTPUT_VHDL = NO # Doxygen selects the parser to use depending on the extension of the files it # parses. With this tag you can assign which parser to use for a given # extension. Doxygen has a built-in mapping, but you can override or extend it # using this tag. The format is ext=language, where ext is a file extension, and # language is one of the parsers supported by doxygen: IDL, Java, Javascript, # C#, C, C++, D, PHP, Objective-C, Python, Fortran (fixed format Fortran: # FortranFixed, free formatted Fortran: FortranFree, unknown formatted Fortran: # Fortran. In the later case the parser tries to guess whether the code is fixed # or free formatted code, this is the default for Fortran type files), VHDL. For # instance to make doxygen treat .inc files as Fortran files (default is PHP), # and .f files as C (default is Fortran), use: inc=Fortran f=C. # # Note For files without extension you can use no_extension as a placeholder. # # Note that for custom extensions you also need to set FILE_PATTERNS otherwise # the files are not read by doxygen. EXTENSION_MAPPING = # If the MARKDOWN_SUPPORT tag is enabled then doxygen pre-processes all comments # according to the Markdown format, which allows for more readable # documentation. See http://daringfireball.net/projects/markdown/ for details. # The output of markdown processing is further processed by doxygen, so you can # mix doxygen, HTML, and XML commands with Markdown formatting. Disable only in # case of backward compatibilities issues. # The default value is: YES. MARKDOWN_SUPPORT = YES # When enabled doxygen tries to link words that correspond to documented # classes, or namespaces to their corresponding documentation. Such a link can # be prevented in individual cases by by putting a % sign in front of the word # or globally by setting AUTOLINK_SUPPORT to NO. # The default value is: YES. AUTOLINK_SUPPORT = YES # If you use STL classes (i.e. std::string, std::vector, etc.) but do not want # to include (a tag file for) the STL sources as input, then you should set this # tag to YES in order to let doxygen match functions declarations and # definitions whose arguments contain STL classes (e.g. func(std::string); # versus func(std::string) {}). This also make the inheritance and collaboration # diagrams that involve STL classes more complete and accurate. # The default value is: NO. BUILTIN_STL_SUPPORT = YES # If you use Microsoft's C++/CLI language, you should set this option to YES to # enable parsing support. # The default value is: NO. CPP_CLI_SUPPORT = NO # Set the SIP_SUPPORT tag to YES if your project consists of sip (see: # http://www.riverbankcomputing.co.uk/software/sip/intro) sources only. Doxygen # will parse them like normal C++ but will assume all classes use public instead # of private inheritance when no explicit protection keyword is present. # The default value is: NO. SIP_SUPPORT = NO # For Microsoft's IDL there are propget and propput attributes to indicate # getter and setter methods for a property. Setting this option to YES will make # doxygen to replace the get and set methods by a property in the documentation. # This will only work if the methods are indeed getting or setting a simple # type. If this is not the case, or you want to show the methods anyway, you # should set this option to NO. # The default value is: YES. IDL_PROPERTY_SUPPORT = YES # If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC # tag is set to YES, then doxygen will reuse the documentation of the first # member in the group (if any) for the other members of the group. By default # all members of a group must be documented explicitly. # The default value is: NO. DISTRIBUTE_GROUP_DOC = NO # Set the SUBGROUPING tag to YES to allow class member groups of the same type # (for instance a group of public functions) to be put as a subgroup of that # type (e.g. under the Public Functions section). Set it to NO to prevent # subgrouping. Alternatively, this can be done per class using the # \nosubgrouping command. # The default value is: YES. SUBGROUPING = YES # When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and unions # are shown inside the group in which they are included (e.g. using \ingroup) # instead of on a separate page (for HTML and Man pages) or section (for LaTeX # and RTF). # # Note that this feature does not work in combination with # SEPARATE_MEMBER_PAGES. # The default value is: NO. INLINE_GROUPED_CLASSES = NO # When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and unions # with only public data fields or simple typedef fields will be shown inline in # the documentation of the scope in which they are defined (i.e. file, # namespace, or group documentation), provided this scope is documented. If set # to NO, structs, classes, and unions are shown on a separate page (for HTML and # Man pages) or section (for LaTeX and RTF). # The default value is: NO. INLINE_SIMPLE_STRUCTS = NO # When TYPEDEF_HIDES_STRUCT tag is enabled, a typedef of a struct, union, or # enum is documented as struct, union, or enum with the name of the typedef. So # typedef struct TypeS {} TypeT, will appear in the documentation as a struct # with name TypeT. When disabled the typedef will appear as a member of a file, # namespace, or class. And the struct will be named TypeS. This can typically be # useful for C code in case the coding convention dictates that all compound # types are typedef'ed and only the typedef is referenced, never the tag name. # The default value is: NO. TYPEDEF_HIDES_STRUCT = YES # The size of the symbol lookup cache can be set using LOOKUP_CACHE_SIZE. This # cache is used to resolve symbols given their name and scope. Since this can be # an expensive process and often the same symbol appears multiple times in the # code, doxygen keeps a cache of pre-resolved symbols. If the cache is too small # doxygen will become slower. If the cache is too large, memory is wasted. The # cache size is given by this formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range # is 0..9, the default is 0, corresponding to a cache size of 2^16=65536 # symbols. At the end of a run doxygen will report the cache usage and suggest # the optimal cache size from a speed point of view. # Minimum value: 0, maximum value: 9, default value: 0. LOOKUP_CACHE_SIZE = 0 #--------------------------------------------------------------------------- # Build related configuration options #--------------------------------------------------------------------------- # If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in # documentation are documented, even if no documentation was available. Private # class members and static file members will be hidden unless the # EXTRACT_PRIVATE respectively EXTRACT_STATIC tags are set to YES. # Note: This will also disable the warnings about undocumented members that are # normally produced when WARNINGS is set to YES. # The default value is: NO. EXTRACT_ALL = NO # If the EXTRACT_PRIVATE tag is set to YES all private members of a class will # be included in the documentation. # The default value is: NO. EXTRACT_PRIVATE = NO # If the EXTRACT_PACKAGE tag is set to YES all members with package or internal # scope will be included in the documentation. # The default value is: NO. EXTRACT_PACKAGE = YES # If the EXTRACT_STATIC tag is set to YES all static members of a file will be # included in the documentation. # The default value is: NO. EXTRACT_STATIC = YES # If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) defined # locally in source files will be included in the documentation. If set to NO # only classes defined in header files are included. Does not have any effect # for Java sources. # The default value is: YES. EXTRACT_LOCAL_CLASSES = YES # This flag is only useful for Objective-C code. When set to YES local methods, # which are defined in the implementation section but not in the interface are # included in the documentation. If set to NO only methods in the interface are # included. # The default value is: NO. EXTRACT_LOCAL_METHODS = YES # If this flag is set to YES, the members of anonymous namespaces will be # extracted and appear in the documentation as a namespace called # 'anonymous_namespace{file}', where file will be replaced with the base name of # the file that contains the anonymous namespace. By default anonymous namespace # are hidden. # The default value is: NO. EXTRACT_ANON_NSPACES = YES # If the HIDE_UNDOC_MEMBERS tag is set to YES, doxygen will hide all # undocumented members inside documented classes or files. If set to NO these # members will be included in the various overviews, but no documentation # section is generated. This option has no effect if EXTRACT_ALL is enabled. # The default value is: NO. HIDE_UNDOC_MEMBERS = NO # If the HIDE_UNDOC_CLASSES tag is set to YES, doxygen will hide all # undocumented classes that are normally visible in the class hierarchy. If set # to NO these classes will be included in the various overviews. This option has # no effect if EXTRACT_ALL is enabled. # The default value is: NO. HIDE_UNDOC_CLASSES = NO # If the HIDE_FRIEND_COMPOUNDS tag is set to YES, doxygen will hide all friend # (class|struct|union) declarations. If set to NO these declarations will be # included in the documentation. # The default value is: NO. HIDE_FRIEND_COMPOUNDS = NO # If the HIDE_IN_BODY_DOCS tag is set to YES, doxygen will hide any # documentation blocks found inside the body of a function. If set to NO these # blocks will be appended to the function's detailed documentation block. # The default value is: NO. HIDE_IN_BODY_DOCS = NO # The INTERNAL_DOCS tag determines if documentation that is typed after a # \internal command is included. If the tag is set to NO then the documentation # will be excluded. Set it to YES to include the internal documentation. # The default value is: NO. INTERNAL_DOCS = NO # If the CASE_SENSE_NAMES tag is set to NO then doxygen will only generate file # names in lower-case letters. If set to YES upper-case letters are also # allowed. This is useful if you have classes or files whose names only differ # in case and if your file system supports case sensitive file names. Windows # and Mac users are advised to set this option to NO. # The default value is: system dependent. CASE_SENSE_NAMES = NO # If the HIDE_SCOPE_NAMES tag is set to NO then doxygen will show members with # their full class and namespace scopes in the documentation. If set to YES the # scope will be hidden. # The default value is: NO. HIDE_SCOPE_NAMES = NO # If the SHOW_INCLUDE_FILES tag is set to YES then doxygen will put a list of # the files that are included by a file in the documentation of that file. # The default value is: YES. SHOW_INCLUDE_FILES = NO # If the SHOW_GROUPED_MEMB_INC tag is set to YES then Doxygen will add for each # grouped member an include statement to the documentation, telling the reader # which file to include in order to use the member. # The default value is: NO. SHOW_GROUPED_MEMB_INC = YES # If the FORCE_LOCAL_INCLUDES tag is set to YES then doxygen will list include # files with double quotes in the documentation rather than with sharp brackets. # The default value is: NO. FORCE_LOCAL_INCLUDES = NO # If the INLINE_INFO tag is set to YES then a tag [inline] is inserted in the # documentation for inline members. # The default value is: YES. INLINE_INFO = YES # If the SORT_MEMBER_DOCS tag is set to YES then doxygen will sort the # (detailed) documentation of file and class members alphabetically by member # name. If set to NO the members will appear in declaration order. # The default value is: YES. SORT_MEMBER_DOCS = YES # If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the brief # descriptions of file, namespace and class members alphabetically by member # name. If set to NO the members will appear in declaration order. Note that # this will also influence the order of the classes in the class list. # The default value is: NO. SORT_BRIEF_DOCS = NO # If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen will sort the # (brief and detailed) documentation of class members so that constructors and # destructors are listed first. If set to NO the constructors will appear in the # respective orders defined by SORT_BRIEF_DOCS and SORT_MEMBER_DOCS. # Note: If SORT_BRIEF_DOCS is set to NO this option is ignored for sorting brief # member documentation. # Note: If SORT_MEMBER_DOCS is set to NO this option is ignored for sorting # detailed member documentation. # The default value is: NO. SORT_MEMBERS_CTORS_1ST = NO # If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the hierarchy # of group names into alphabetical order. If set to NO the group names will # appear in their defined order. # The default value is: NO. SORT_GROUP_NAMES = YES # If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be sorted by # fully-qualified names, including namespaces. If set to NO, the class list will # be sorted only by class name, not including the namespace part. # Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. # Note: This option applies only to the class list, not to the alphabetical # list. # The default value is: NO. SORT_BY_SCOPE_NAME = NO # If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to do proper # type resolution of all parameters of a function it will reject a match between # the prototype and the implementation of a member function even if there is # only one candidate or it is obvious which candidate to choose by doing a # simple string match. By disabling STRICT_PROTO_MATCHING doxygen will still # accept a match between prototype and implementation in such cases. # The default value is: NO. STRICT_PROTO_MATCHING = NO # The GENERATE_TODOLIST tag can be used to enable ( YES) or disable ( NO) the # todo list. This list is created by putting \todo commands in the # documentation. # The default value is: YES. GENERATE_TODOLIST = YES # The GENERATE_TESTLIST tag can be used to enable ( YES) or disable ( NO) the # test list. This list is created by putting \test commands in the # documentation. # The default value is: YES. GENERATE_TESTLIST = YES # The GENERATE_BUGLIST tag can be used to enable ( YES) or disable ( NO) the bug # list. This list is created by putting \bug commands in the documentation. # The default value is: YES. GENERATE_BUGLIST = YES # The GENERATE_DEPRECATEDLIST tag can be used to enable ( YES) or disable ( NO) # the deprecated list. This list is created by putting \deprecated commands in # the documentation. # The default value is: YES. GENERATE_DEPRECATEDLIST= YES # The ENABLED_SECTIONS tag can be used to enable conditional documentation # sections, marked by \if ... \endif and \cond # ... \endcond blocks. ENABLED_SECTIONS = # The MAX_INITIALIZER_LINES tag determines the maximum number of lines that the # initial value of a variable or macro / define can have for it to appear in the # documentation. If the initializer consists of more lines than specified here # it will be hidden. Use a value of 0 to hide initializers completely. The # appearance of the value of individual variables and macros / defines can be # controlled using \showinitializer or \hideinitializer command in the # documentation regardless of this setting. # Minimum value: 0, maximum value: 10000, default value: 30. MAX_INITIALIZER_LINES = 30 # Set the SHOW_USED_FILES tag to NO to disable the list of files generated at # the bottom of the documentation of classes and structs. If set to YES the list # will mention the files that were used to generate the documentation. # The default value is: YES. SHOW_USED_FILES = YES # Set the SHOW_FILES tag to NO to disable the generation of the Files page. This # will remove the Files entry from the Quick Index and from the Folder Tree View # (if specified). # The default value is: YES. SHOW_FILES = YES # Set the SHOW_NAMESPACES tag to NO to disable the generation of the Namespaces # page. This will remove the Namespaces entry from the Quick Index and from the # Folder Tree View (if specified). # The default value is: YES. SHOW_NAMESPACES = YES # The FILE_VERSION_FILTER tag can be used to specify a program or script that # doxygen should invoke to get the current version for each file (typically from # the version control system). Doxygen will invoke the program by executing (via # popen()) the command command input-file, where command is the value of the # FILE_VERSION_FILTER tag, and input-file is the name of an input file provided # by doxygen. Whatever the program writes to standard output is used as the file # version. For an example see the documentation. FILE_VERSION_FILTER = # The LAYOUT_FILE tag can be used to specify a layout file which will be parsed # by doxygen. The layout file controls the global structure of the generated # output files in an output format independent way. To create the layout file # that represents doxygen's defaults, run doxygen with the -l option. You can # optionally specify a file name after the option, if omitted DoxygenLayout.xml # will be used as the name of the layout file. # # Note that if you run doxygen from a directory containing a file called # DoxygenLayout.xml, doxygen will parse it automatically even if the LAYOUT_FILE # tag is left empty. LAYOUT_FILE = # The CITE_BIB_FILES tag can be used to specify one or more bib files containing # the reference definitions. This must be a list of .bib files. The .bib # extension is automatically appended if omitted. This requires the bibtex tool # to be installed. See also http://en.wikipedia.org/wiki/BibTeX for more info. # For LaTeX the style of the bibliography can be controlled using # LATEX_BIB_STYLE. To use this feature you need bibtex and perl available in the # search path. Do not use file names with spaces, bibtex cannot handle them. See # also \cite for info how to create references. CITE_BIB_FILES = #--------------------------------------------------------------------------- # Configuration options related to warning and progress messages #--------------------------------------------------------------------------- # The QUIET tag can be used to turn on/off the messages that are generated to # standard output by doxygen. If QUIET is set to YES this implies that the # messages are off. # The default value is: NO. QUIET = YES # The WARNINGS tag can be used to turn on/off the warning messages that are # generated to standard error ( stderr) by doxygen. If WARNINGS is set to YES # this implies that the warnings are on. # # Tip: Turn warnings on while writing the documentation. # The default value is: YES. WARNINGS = YES # If the WARN_IF_UNDOCUMENTED tag is set to YES, then doxygen will generate # warnings for undocumented members. If EXTRACT_ALL is set to YES then this flag # will automatically be disabled. # The default value is: YES. WARN_IF_UNDOCUMENTED = YES # If the WARN_IF_DOC_ERROR tag is set to YES, doxygen will generate warnings for # potential errors in the documentation, such as not documenting some parameters # in a documented function, or documenting parameters that don't exist or using # markup commands wrongly. # The default value is: YES. WARN_IF_DOC_ERROR = YES # This WARN_NO_PARAMDOC option can be enabled to get warnings for functions that # are documented, but have no documentation for their parameters or return # value. If set to NO doxygen will only warn about wrong or incomplete parameter # documentation, but not about the absence of documentation. # The default value is: NO. WARN_NO_PARAMDOC = YES # The WARN_FORMAT tag determines the format of the warning messages that doxygen # can produce. The string should contain the $file, $line, and $text tags, which # will be replaced by the file and line number from which the warning originated # and the warning text. Optionally the format may contain $version, which will # be replaced by the version of the file (if it could be obtained via # FILE_VERSION_FILTER) # The default value is: $file:$line: $text. WARN_FORMAT = "$file:$line: $text" # The WARN_LOGFILE tag can be used to specify a file to which warning and error # messages should be written. If left blank the output is written to standard # error (stderr). WARN_LOGFILE = html/warnings.txt #--------------------------------------------------------------------------- # Configuration options related to the input files #--------------------------------------------------------------------------- # The INPUT tag is used to specify the files and/or directories that contain # documented source files. You may enter file names like myfile.cpp or # directories like /usr/src/myproject. Separate the files or directories with # spaces. # Note: If this tag is empty the current directory is searched. INPUT = ../README.md \ ../Extensibility.md \ inc \ docs # This tag can be used to specify the character encoding of the source files # that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses # libiconv (or the iconv built into libc) for the transcoding. See the libiconv # documentation (see: http://www.gnu.org/software/libiconv) for the list of # possible encodings. # The default value is: UTF-8. INPUT_ENCODING = UTF-8 # If the value of the INPUT tag contains directories, you can use the # FILE_PATTERNS tag to specify one or more wildcard patterns (like *.cpp and # *.h) to filter out the source-files in the directories. If left blank the # following patterns are tested:*.c, *.cc, *.cxx, *.cpp, *.c++, *.java, *.ii, # *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h, *.hh, *.hxx, *.hpp, # *.h++, *.cs, *.d, *.php, *.php4, *.php5, *.phtml, *.inc, *.m, *.markdown, # *.md, *.mm, *.dox, *.py, *.f90, *.f, *.for, *.tcl, *.vhd, *.vhdl, *.ucf, # *.qsf, *.as and *.js. FILE_PATTERNS = # The RECURSIVE tag can be used to specify whether or not subdirectories should # be searched for input files as well. # The default value is: NO. RECURSIVE = YES # The EXCLUDE tag can be used to specify files and/or directories that should be # excluded from the INPUT source files. This way you can easily exclude a # subdirectory from a directory tree whose root is specified with the INPUT tag. # # Note that relative paths are relative to the directory from which doxygen is # run. EXCLUDE = # The EXCLUDE_SYMLINKS tag can be used to select whether or not files or # directories that are symbolic links (a Unix file system feature) are excluded # from the input. # The default value is: NO. EXCLUDE_SYMLINKS = NO # If the value of the INPUT tag contains directories, you can use the # EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude # certain files from those directories. # # Note that the wildcards are matched against the file with absolute path, so to # exclude all test directories for example use the pattern */test/* EXCLUDE_PATTERNS = # The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names # (namespaces, classes, functions, etc.) that should be excluded from the # output. The symbol name can be a fully qualified name, a word, or if the # wildcard * is used, a substring. Examples: ANamespace, AClass, # AClass::ANamespace, ANamespace::*Test # # Note that the wildcards are matched against the file with absolute path, so to # exclude all test directories use the pattern */test/* EXCLUDE_SYMBOLS = rapidjson* # The EXAMPLE_PATH tag can be used to specify one or more files or directories # that contain example code fragments that are included (see the \include # command). EXAMPLE_PATH = # If the value of the EXAMPLE_PATH tag contains directories, you can use the # EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp and # *.h) to filter out the source-files in the directories. If left blank all # files are included. EXAMPLE_PATTERNS = # If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be # searched for input files to be used with the \include or \dontinclude commands # irrespective of the value of the RECURSIVE tag. # The default value is: NO. EXAMPLE_RECURSIVE = NO # The IMAGE_PATH tag can be used to specify one or more files or directories # that contain images that are to be included in the documentation (see the # \image command). IMAGE_PATH = # The INPUT_FILTER tag can be used to specify a program that doxygen should # invoke to filter for each input file. Doxygen will invoke the filter program # by executing (via popen()) the command: # # # # where is the value of the INPUT_FILTER tag, and is the # name of an input file. Doxygen will then use the output that the filter # program writes to standard output. If FILTER_PATTERNS is specified, this tag # will be ignored. # # Note that the filter must not add or remove lines; it is applied before the # code is scanned, but not when the output code is generated. If lines are added # or removed, the anchors will not be placed correctly. INPUT_FILTER = # The FILTER_PATTERNS tag can be used to specify filters on a per file pattern # basis. Doxygen will compare the file name with each pattern and apply the # filter if there is a match. The filters are a list of the form: pattern=filter # (like *.cpp=my_cpp_filter). See INPUT_FILTER for further information on how # filters are used. If the FILTER_PATTERNS tag is empty or if none of the # patterns match the file name, INPUT_FILTER is applied. FILTER_PATTERNS = # If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using # INPUT_FILTER ) will also be used to filter the input files that are used for # producing the source files to browse (i.e. when SOURCE_BROWSER is set to YES). # The default value is: NO. FILTER_SOURCE_FILES = NO # The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file # pattern. A pattern will override the setting for FILTER_PATTERN (if any) and # it is also possible to disable source filtering for a specific pattern using # *.ext= (so without naming a filter). # This tag requires that the tag FILTER_SOURCE_FILES is set to YES. FILTER_SOURCE_PATTERNS = # If the USE_MDFILE_AS_MAINPAGE tag refers to the name of a markdown file that # is part of the input, its contents will be placed on the main page # (index.html). This can be useful if you have a project on for instance GitHub # and want to reuse the introduction page also for the doxygen output. USE_MDFILE_AS_MAINPAGE = README.md #--------------------------------------------------------------------------- # Configuration options related to source browsing #--------------------------------------------------------------------------- # If the SOURCE_BROWSER tag is set to YES then a list of source files will be # generated. Documented entities will be cross-referenced with these sources. # # Note: To get rid of all source code in the generated output, make sure that # also VERBATIM_HEADERS is set to NO. # The default value is: NO. SOURCE_BROWSER = YES # Setting the INLINE_SOURCES tag to YES will include the body of functions, # classes and enums directly into the documentation. # The default value is: NO. INLINE_SOURCES = NO # Setting the STRIP_CODE_COMMENTS tag to YES will instruct doxygen to hide any # special comment blocks from generated source code fragments. Normal C, C++ and # Fortran comments will always remain visible. # The default value is: YES. STRIP_CODE_COMMENTS = YES # If the REFERENCED_BY_RELATION tag is set to YES then for each documented # function all documented functions referencing it will be listed. # The default value is: NO. REFERENCED_BY_RELATION = NO # If the REFERENCES_RELATION tag is set to YES then for each documented function # all documented entities called/used by that function will be listed. # The default value is: NO. REFERENCES_RELATION = NO # If the REFERENCES_LINK_SOURCE tag is set to YES and SOURCE_BROWSER tag is set # to YES, then the hyperlinks from functions in REFERENCES_RELATION and # REFERENCED_BY_RELATION lists will link to the source code. Otherwise they will # link to the documentation. # The default value is: YES. REFERENCES_LINK_SOURCE = YES # If SOURCE_TOOLTIPS is enabled (the default) then hovering a hyperlink in the # source code will show a tooltip with additional information such as prototype, # brief description and links to the definition and documentation. Since this # will make the HTML file larger and loading of large files a bit slower, you # can opt to disable this feature. # The default value is: YES. # This tag requires that the tag SOURCE_BROWSER is set to YES. SOURCE_TOOLTIPS = YES # If the USE_HTAGS tag is set to YES then the references to source code will # point to the HTML generated by the htags(1) tool instead of doxygen built-in # source browser. The htags tool is part of GNU's global source tagging system # (see http://www.gnu.org/software/global/global.html). You will need version # 4.8.6 or higher. # # To use it do the following: # - Install the latest version of global # - Enable SOURCE_BROWSER and USE_HTAGS in the config file # - Make sure the INPUT points to the root of the source tree # - Run doxygen as normal # # Doxygen will invoke htags (and that will in turn invoke gtags), so these # tools must be available from the command line (i.e. in the search path). # # The result: instead of the source browser generated by doxygen, the links to # source code will now point to the output of htags. # The default value is: NO. # This tag requires that the tag SOURCE_BROWSER is set to YES. USE_HTAGS = NO # If the VERBATIM_HEADERS tag is set the YES then doxygen will generate a # verbatim copy of the header file for each class for which an include is # specified. Set to NO to disable this. # See also: Section \class. # The default value is: YES. VERBATIM_HEADERS = YES #--------------------------------------------------------------------------- # Configuration options related to the alphabetical class index #--------------------------------------------------------------------------- # If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index of all # compounds will be generated. Enable this if the project contains a lot of # classes, structs, unions or interfaces. # The default value is: YES. ALPHABETICAL_INDEX = YES # The COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns in # which the alphabetical index list will be split. # Minimum value: 1, maximum value: 20, default value: 5. # This tag requires that the tag ALPHABETICAL_INDEX is set to YES. COLS_IN_ALPHA_INDEX = 5 # In case all classes in a project start with a common prefix, all classes will # be put under the same header in the alphabetical index. The IGNORE_PREFIX tag # can be used to specify a prefix (or a list of prefixes) that should be ignored # while generating the index headers. # This tag requires that the tag ALPHABETICAL_INDEX is set to YES. IGNORE_PREFIX = #--------------------------------------------------------------------------- # Configuration options related to the HTML output #--------------------------------------------------------------------------- # If the GENERATE_HTML tag is set to YES doxygen will generate HTML output # The default value is: YES. GENERATE_HTML = YES # The HTML_OUTPUT tag is used to specify where the HTML docs will be put. If a # relative path is entered the value of OUTPUT_DIRECTORY will be put in front of # it. # The default directory is: html. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_OUTPUT = html # The HTML_FILE_EXTENSION tag can be used to specify the file extension for each # generated HTML page (for example: .htm, .php, .asp). # The default value is: .html. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_FILE_EXTENSION = .html # The HTML_HEADER tag can be used to specify a user-defined HTML header file for # each generated HTML page. If the tag is left blank doxygen will generate a # standard header. # # To get valid HTML the header file that includes any scripts and style sheets # that doxygen needs, which is dependent on the configuration options used (e.g. # the setting GENERATE_TREEVIEW). It is highly recommended to start with a # default header using # doxygen -w html new_header.html new_footer.html new_stylesheet.css # YourConfigFile # and then modify the file new_header.html. See also section "Doxygen usage" # for information on how to generate the default header that doxygen normally # uses. # Note: The header is subject to change so you typically have to regenerate the # default header when upgrading to a newer version of doxygen. For a description # of the possible markers and block names see the documentation. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_HEADER = # The HTML_FOOTER tag can be used to specify a user-defined HTML footer for each # generated HTML page. If the tag is left blank doxygen will generate a standard # footer. See HTML_HEADER for more information on how to generate a default # footer and what special commands can be used inside the footer. See also # section "Doxygen usage" for information on how to generate the default footer # that doxygen normally uses. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_FOOTER = # The HTML_STYLESHEET tag can be used to specify a user-defined cascading style # sheet that is used by each HTML page. It can be used to fine-tune the look of # the HTML output. If left blank doxygen will generate a default style sheet. # See also section "Doxygen usage" for information on how to generate the style # sheet that doxygen normally uses. # Note: It is recommended to use HTML_EXTRA_STYLESHEET instead of this tag, as # it is more robust and this tag (HTML_STYLESHEET) will in the future become # obsolete. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_STYLESHEET = # The HTML_EXTRA_STYLESHEET tag can be used to specify an additional user- # defined cascading style sheet that is included after the standard style sheets # created by doxygen. Using this option one can overrule certain style aspects. # This is preferred over using HTML_STYLESHEET since it does not replace the # standard style sheet and is therefor more robust against future updates. # Doxygen will copy the style sheet file to the output directory. For an example # see the documentation. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_EXTRA_STYLESHEET = # The HTML_EXTRA_FILES tag can be used to specify one or more extra images or # other source files which should be copied to the HTML output directory. Note # that these files will be copied to the base HTML output directory. Use the # $relpath^ marker in the HTML_HEADER and/or HTML_FOOTER files to load these # files. In the HTML_STYLESHEET file, use the file name only. Also note that the # files will be copied as-is; there are no commands or markers available. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_EXTRA_FILES = # The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen # will adjust the colors in the stylesheet and background images according to # this color. Hue is specified as an angle on a colorwheel, see # http://en.wikipedia.org/wiki/Hue for more information. For instance the value # 0 represents red, 60 is yellow, 120 is green, 180 is cyan, 240 is blue, 300 # purple, and 360 is red again. # Minimum value: 0, maximum value: 359, default value: 220. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_COLORSTYLE_HUE = 220 # The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of the colors # in the HTML output. For a value of 0 the output will use grayscales only. A # value of 255 will produce the most vivid colors. # Minimum value: 0, maximum value: 255, default value: 100. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_COLORSTYLE_SAT = 100 # The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to the # luminance component of the colors in the HTML output. Values below 100 # gradually make the output lighter, whereas values above 100 make the output # darker. The value divided by 100 is the actual gamma applied, so 80 represents # a gamma of 0.8, The value 220 represents a gamma of 2.2, and 100 does not # change the gamma. # Minimum value: 40, maximum value: 240, default value: 80. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_COLORSTYLE_GAMMA = 80 # If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML # page will contain the date and time when the page was generated. Setting this # to NO can help when comparing the output of multiple runs. # The default value is: YES. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_TIMESTAMP = YES # If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML # documentation will contain sections that can be hidden and shown after the # page has loaded. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_DYNAMIC_SECTIONS = NO # With HTML_INDEX_NUM_ENTRIES one can control the preferred number of entries # shown in the various tree structured indices initially; the user can expand # and collapse entries dynamically later on. Doxygen will expand the tree to # such a level that at most the specified number of entries are visible (unless # a fully collapsed tree already exceeds this amount). So setting the number of # entries 1 will produce a full collapsed tree by default. 0 is a special value # representing an infinite number of entries and will result in a full expanded # tree by default. # Minimum value: 0, maximum value: 9999, default value: 100. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_INDEX_NUM_ENTRIES = 100 # If the GENERATE_DOCSET tag is set to YES, additional index files will be # generated that can be used as input for Apple's Xcode 3 integrated development # environment (see: http://developer.apple.com/tools/xcode/), introduced with # OSX 10.5 (Leopard). To create a documentation set, doxygen will generate a # Makefile in the HTML output directory. Running make will produce the docset in # that directory and running make install will install the docset in # ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find it at # startup. See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html # for more information. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. GENERATE_DOCSET = NO # This tag determines the name of the docset feed. A documentation feed provides # an umbrella under which multiple documentation sets from a single provider # (such as a company or product suite) can be grouped. # The default value is: Doxygen generated docs. # This tag requires that the tag GENERATE_DOCSET is set to YES. DOCSET_FEEDNAME = "Doxygen generated docs" # This tag specifies a string that should uniquely identify the documentation # set bundle. This should be a reverse domain-name style string, e.g. # com.mycompany.MyDocSet. Doxygen will append .docset to the name. # The default value is: org.doxygen.Project. # This tag requires that the tag GENERATE_DOCSET is set to YES. DOCSET_BUNDLE_ID = org.doxygen.Project # The DOCSET_PUBLISHER_ID tag specifies a string that should uniquely identify # the documentation publisher. This should be a reverse domain-name style # string, e.g. com.mycompany.MyDocSet.documentation. # The default value is: org.doxygen.Publisher. # This tag requires that the tag GENERATE_DOCSET is set to YES. DOCSET_PUBLISHER_ID = org.doxygen.Publisher # The DOCSET_PUBLISHER_NAME tag identifies the documentation publisher. # The default value is: Publisher. # This tag requires that the tag GENERATE_DOCSET is set to YES. DOCSET_PUBLISHER_NAME = Publisher # If the GENERATE_HTMLHELP tag is set to YES then doxygen generates three # additional HTML index files: index.hhp, index.hhc, and index.hhk. The # index.hhp is a project file that can be read by Microsoft's HTML Help Workshop # (see: http://www.microsoft.com/en-us/download/details.aspx?id=21138) on # Windows. # # The HTML Help Workshop contains a compiler that can convert all HTML output # generated by doxygen into a single compiled HTML file (.chm). Compiled HTML # files are now used as the Windows 98 help format, and will replace the old # Windows help format (.hlp) on all Windows platforms in the future. Compressed # HTML files also contain an index, a table of contents, and you can search for # words in the documentation. The HTML workshop also contains a viewer for # compressed HTML files. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. GENERATE_HTMLHELP = NO # The CHM_FILE tag can be used to specify the file name of the resulting .chm # file. You can add a path in front of the file if the result should not be # written to the html output directory. # This tag requires that the tag GENERATE_HTMLHELP is set to YES. CHM_FILE = # The HHC_LOCATION tag can be used to specify the location (absolute path # including file name) of the HTML help compiler ( hhc.exe). If non-empty # doxygen will try to run the HTML help compiler on the generated index.hhp. # The file has to be specified with full path. # This tag requires that the tag GENERATE_HTMLHELP is set to YES. HHC_LOCATION = # The GENERATE_CHI flag controls if a separate .chi index file is generated ( # YES) or that it should be included in the master .chm file ( NO). # The default value is: NO. # This tag requires that the tag GENERATE_HTMLHELP is set to YES. GENERATE_CHI = NO # The CHM_INDEX_ENCODING is used to encode HtmlHelp index ( hhk), content ( hhc) # and project file content. # This tag requires that the tag GENERATE_HTMLHELP is set to YES. CHM_INDEX_ENCODING = # The BINARY_TOC flag controls whether a binary table of contents is generated ( # YES) or a normal table of contents ( NO) in the .chm file. Furthermore it # enables the Previous and Next buttons. # The default value is: NO. # This tag requires that the tag GENERATE_HTMLHELP is set to YES. BINARY_TOC = NO # The TOC_EXPAND flag can be set to YES to add extra items for group members to # the table of contents of the HTML help documentation and to the tree view. # The default value is: NO. # This tag requires that the tag GENERATE_HTMLHELP is set to YES. TOC_EXPAND = NO # If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and # QHP_VIRTUAL_FOLDER are set, an additional index file will be generated that # can be used as input for Qt's qhelpgenerator to generate a Qt Compressed Help # (.qch) of the generated HTML documentation. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. GENERATE_QHP = NO # If the QHG_LOCATION tag is specified, the QCH_FILE tag can be used to specify # the file name of the resulting .qch file. The path specified is relative to # the HTML output folder. # This tag requires that the tag GENERATE_QHP is set to YES. QCH_FILE = # The QHP_NAMESPACE tag specifies the namespace to use when generating Qt Help # Project output. For more information please see Qt Help Project / Namespace # (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#namespace). # The default value is: org.doxygen.Project. # This tag requires that the tag GENERATE_QHP is set to YES. QHP_NAMESPACE = # The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating Qt # Help Project output. For more information please see Qt Help Project / Virtual # Folders (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#virtual- # folders). # The default value is: doc. # This tag requires that the tag GENERATE_QHP is set to YES. QHP_VIRTUAL_FOLDER = doc # If the QHP_CUST_FILTER_NAME tag is set, it specifies the name of a custom # filter to add. For more information please see Qt Help Project / Custom # Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom- # filters). # This tag requires that the tag GENERATE_QHP is set to YES. QHP_CUST_FILTER_NAME = # The QHP_CUST_FILTER_ATTRS tag specifies the list of the attributes of the # custom filter to add. For more information please see Qt Help Project / Custom # Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom- # filters). # This tag requires that the tag GENERATE_QHP is set to YES. QHP_CUST_FILTER_ATTRS = # The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this # project's filter section matches. Qt Help Project / Filter Attributes (see: # http://qt-project.org/doc/qt-4.8/qthelpproject.html#filter-attributes). # This tag requires that the tag GENERATE_QHP is set to YES. QHP_SECT_FILTER_ATTRS = # The QHG_LOCATION tag can be used to specify the location of Qt's # qhelpgenerator. If non-empty doxygen will try to run qhelpgenerator on the # generated .qhp file. # This tag requires that the tag GENERATE_QHP is set to YES. QHG_LOCATION = # If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files will be # generated, together with the HTML files, they form an Eclipse help plugin. To # install this plugin and make it available under the help contents menu in # Eclipse, the contents of the directory containing the HTML and XML files needs # to be copied into the plugins directory of eclipse. The name of the directory # within the plugins directory should be the same as the ECLIPSE_DOC_ID value. # After copying Eclipse needs to be restarted before the help appears. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. GENERATE_ECLIPSEHELP = NO # A unique identifier for the Eclipse help plugin. When installing the plugin # the directory name containing the HTML and XML files should also have this # name. Each documentation set should have its own identifier. # The default value is: org.doxygen.Project. # This tag requires that the tag GENERATE_ECLIPSEHELP is set to YES. ECLIPSE_DOC_ID = org.doxygen.Project # If you want full control over the layout of the generated HTML pages it might # be necessary to disable the index and replace it with your own. The # DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs) at top # of each HTML page. A value of NO enables the index and the value YES disables # it. Since the tabs in the index contain the same information as the navigation # tree, you can set this option to YES if you also set GENERATE_TREEVIEW to YES. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. DISABLE_INDEX = NO # The GENERATE_TREEVIEW tag is used to specify whether a tree-like index # structure should be generated to display hierarchical information. If the tag # value is set to YES, a side panel will be generated containing a tree-like # index structure (just like the one that is generated for HTML Help). For this # to work a browser that supports JavaScript, DHTML, CSS and frames is required # (i.e. any modern browser). Windows users are probably better off using the # HTML help feature. Via custom stylesheets (see HTML_EXTRA_STYLESHEET) one can # further fine-tune the look of the index. As an example, the default style # sheet generated by doxygen has an example that shows how to put an image at # the root of the tree instead of the PROJECT_NAME. Since the tree basically has # the same information as the tab index, you could consider setting # DISABLE_INDEX to YES when enabling this option. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. GENERATE_TREEVIEW = NO # The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values that # doxygen will group on one line in the generated HTML documentation. # # Note that a value of 0 will completely suppress the enum values from appearing # in the overview section. # Minimum value: 0, maximum value: 20, default value: 4. # This tag requires that the tag GENERATE_HTML is set to YES. ENUM_VALUES_PER_LINE = 4 # If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be used # to set the initial width (in pixels) of the frame in which the tree is shown. # Minimum value: 0, maximum value: 1500, default value: 250. # This tag requires that the tag GENERATE_HTML is set to YES. TREEVIEW_WIDTH = 250 # When the EXT_LINKS_IN_WINDOW option is set to YES doxygen will open links to # external symbols imported via tag files in a separate window. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. EXT_LINKS_IN_WINDOW = NO # Use this tag to change the font size of LaTeX formulas included as images in # the HTML documentation. When you change the font size after a successful # doxygen run you need to manually remove any form_*.png images from the HTML # output directory to force them to be regenerated. # Minimum value: 8, maximum value: 50, default value: 10. # This tag requires that the tag GENERATE_HTML is set to YES. FORMULA_FONTSIZE = 10 # Use the FORMULA_TRANPARENT tag to determine whether or not the images # generated for formulas are transparent PNGs. Transparent PNGs are not # supported properly for IE 6.0, but are supported on all modern browsers. # # Note that when changing this option you need to delete any form_*.png files in # the HTML output directory before the changes have effect. # The default value is: YES. # This tag requires that the tag GENERATE_HTML is set to YES. FORMULA_TRANSPARENT = YES # Enable the USE_MATHJAX option to render LaTeX formulas using MathJax (see # http://www.mathjax.org) which uses client side Javascript for the rendering # instead of using prerendered bitmaps. Use this if you do not have LaTeX # installed or if you want to formulas look prettier in the HTML output. When # enabled you may also need to install MathJax separately and configure the path # to it using the MATHJAX_RELPATH option. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. USE_MATHJAX = NO # When MathJax is enabled you can set the default output format to be used for # the MathJax output. See the MathJax site (see: # http://docs.mathjax.org/en/latest/output.html) for more details. # Possible values are: HTML-CSS (which is slower, but has the best # compatibility), NativeMML (i.e. MathML) and SVG. # The default value is: HTML-CSS. # This tag requires that the tag USE_MATHJAX is set to YES. MATHJAX_FORMAT = HTML-CSS # When MathJax is enabled you need to specify the location relative to the HTML # output directory using the MATHJAX_RELPATH option. The destination directory # should contain the MathJax.js script. For instance, if the mathjax directory # is located at the same level as the HTML output directory, then # MATHJAX_RELPATH should be ../mathjax. The default value points to the MathJax # Content Delivery Network so you can quickly see the result without installing # MathJax. However, it is strongly recommended to install a local copy of # MathJax from http://www.mathjax.org before deployment. # The default value is: http://cdn.mathjax.org/mathjax/latest. # This tag requires that the tag USE_MATHJAX is set to YES. MATHJAX_RELPATH = http://cdn.mathjax.org/mathjax/latest # The MATHJAX_EXTENSIONS tag can be used to specify one or more MathJax # extension names that should be enabled during MathJax rendering. For example # MATHJAX_EXTENSIONS = TeX/AMSmath TeX/AMSsymbols # This tag requires that the tag USE_MATHJAX is set to YES. MATHJAX_EXTENSIONS = # The MATHJAX_CODEFILE tag can be used to specify a file with javascript pieces # of code that will be used on startup of the MathJax code. See the MathJax site # (see: http://docs.mathjax.org/en/latest/output.html) for more details. For an # example see the documentation. # This tag requires that the tag USE_MATHJAX is set to YES. MATHJAX_CODEFILE = # When the SEARCHENGINE tag is enabled doxygen will generate a search box for # the HTML output. The underlying search engine uses javascript and DHTML and # should work on any modern browser. Note that when using HTML help # (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets (GENERATE_DOCSET) # there is already a search function so this one should typically be disabled. # For large projects the javascript based search engine can be slow, then # enabling SERVER_BASED_SEARCH may provide a better solution. It is possible to # search using the keyboard; to jump to the search box use + S # (what the is depends on the OS and browser, but it is typically # , /