From e11b4ac7d7c82cef15cbc50dd5d0fe6242259e0c Mon Sep 17 00:00:00 2001 From: Florin Dragos Date: Tue, 21 Jul 2020 13:20:29 +0300 Subject: [PATCH] (FACT-2708) Add man pages --- Gemfile | 4 + agent/facter-ng.gemspec | 3 +- facter.gemspec | 3 +- install.rb | 26 ++- lib/facter/framework/cli/cli.rb | 21 ++- lib/facter/templates/man.erb | 122 ++++++++++++++ man/man8/facter.8 | 288 ++++++++++++++++++++++++++++++++ tasks/manpages.rake | 25 +++ 8 files changed, 474 insertions(+), 18 deletions(-) create mode 100644 lib/facter/templates/man.erb create mode 100644 man/man8/facter.8 create mode 100644 tasks/manpages.rake diff --git a/Gemfile b/Gemfile index 73f15bdae5..a3ae294645 100644 --- a/Gemfile +++ b/Gemfile @@ -10,3 +10,7 @@ end local_gemfile = File.expand_path('Gemfile.local', __dir__) eval_gemfile(local_gemfile) if File.exist?(local_gemfile) + +group(:documentation) do + gem 'ronn', '~> 0.7.3', require: false, platforms: [:ruby] +end diff --git a/agent/facter-ng.gemspec b/agent/facter-ng.gemspec index a56a304c6e..2bbe8621d0 100644 --- a/agent/facter-ng.gemspec +++ b/agent/facter-ng.gemspec @@ -18,7 +18,8 @@ Gem::Specification.new do |spec| Dir['lib/**/*.rb'] + Dir['lib/**/*.json'] + Dir['lib/**/*.conf'] + - Dir['agent/**/*'] + Dir['agent/**/*'] + + Dir['lib/**/*.erb'] spec.required_ruby_version = '~> 2.3' diff --git a/facter.gemspec b/facter.gemspec index 619431df43..96498148fe 100644 --- a/facter.gemspec +++ b/facter.gemspec @@ -17,7 +17,8 @@ Gem::Specification.new do |spec| spec.files = Dir['bin/facter'] + Dir['lib/**/*.rb'] + Dir['lib/**/*.json'] + - Dir['lib/**/*.conf'] + Dir['lib/**/*.conf'] + + Dir['lib/**/*.erb'] spec.required_ruby_version = '~> 2.3' spec.bindir = 'bin' diff --git a/install.rb b/install.rb index 2302ad5c22..8f279067a9 100755 --- a/install.rb +++ b/install.rb @@ -126,11 +126,11 @@ def prepare_installation 'overrides RbConfig::CONFIG["sitelibdir"]') do |sitelibdir| InstallOptions.sitelibdir = sitelibdir end - # opts.on('--mandir[=OPTIONAL]', - # 'Installation directory for man pages', - # 'overrides RbConfig::CONFIG["mandir"]') do |mandir| - # InstallOptions.mandir = mandir - # end + opts.on('--mandir[=OPTIONAL]', + 'Installation directory for man pages', + 'overrides RbConfig::CONFIG["mandir"]') do |mandir| + InstallOptions.mandir = mandir + end opts.on('--full', 'Performs a full installation. All', 'optional installation steps are run.') do |_full| InstallOptions.configs = true end @@ -182,30 +182,26 @@ def prepare_installation end end - # if InstallOptions.mandir - # mandir = InstallOptions.mandir - # else - # mandir = RbConfig::CONFIG['mandir'] - # end + mandir = InstallOptions.mandir || RbConfig::CONFIG['mandir'] # This is the new way forward destdir = InstallOptions.destdir || '' # configdir = join(destdir, configdir) bindir = join(destdir, bindir) - # mandir = join(destdir, mandir) + mandir = join(destdir, mandir) sitelibdir = join(destdir, sitelibdir) # makedirs(configdir) if InstallOptions.configs makedirs(bindir) - # makedirs(mandir) + makedirs(mandir) makedirs(sitelibdir) InstallOptions.site_dir = sitelibdir # InstallOptions.config_dir = configdir InstallOptions.bin_dir = bindir InstallOptions.lib_dir = libdir - # InstallOptions.man_dir = mandir + InstallOptions.man_dir = mandir end ## @@ -281,12 +277,14 @@ def run cd File.dirname(__FILE__) do # Set these values to what you want installed. bins = glob(%w[bin/facter]) - libs = glob(%w[lib/**/*.rb lib/facter/os_hierarchy.json lib/facter/fact_groups.conf]) + libs = glob(%w[lib/**/*.rb lib/facter/os_hierarchy.json lib/facter/fact_groups.conf lib/facter/templates/*]) + man = glob(%w{man/man[0-9]/*}) prepare_installation do_bins(bins, InstallOptions.bin_dir) do_libs(libs) + do_man(man) unless windows? end end end diff --git a/lib/facter/framework/cli/cli.rb b/lib/facter/framework/cli/cli.rb index 4463004e9e..01b14c92d7 100755 --- a/lib/facter/framework/cli/cli.rb +++ b/lib/facter/framework/cli/cli.rb @@ -35,6 +35,11 @@ class Cli < Thor type: :boolean, desc: 'Print this help message.' + class_option :man, + hide: true, + type: :boolean, + desc: 'Display manual.' + class_option :hocon, type: :boolean, desc: 'Output in Hocon format.' @@ -103,6 +108,18 @@ class Cli < Thor aliases: '-p', desc: 'Load the Puppet libraries, thus allowing Facter to load Puppet-specific facts.' + desc '--man', 'Manual', hide: true + map ['--man'] => :man + def man(*args) + require 'erb' + negate_options = %w[block cache custom_facts external_facts] + + template = File.join(File.dirname(__FILE__), '..', '..', 'templates', 'man.erb') + erb = ERB.new(File.read(template), nil, '-') + erb.filename = template + puts erb.result(binding) + end + desc 'query', 'Default method', hide: true desc '[options] [query] [query] [...]', '' def query(*args) @@ -119,13 +136,13 @@ def version puts Facter::VERSION end - desc '--list-block-groups', 'List block groups' + desc '--list-block-groups', 'List block groups', hide: true map ['--list-block-groups'] => :list_block_groups def list_block_groups(*_args) puts Facter::FactGroups.new.groups.to_yaml.lines[1..-1].join end - desc '--list-cache-groups', 'List cache groups' + desc '--list-cache-groups', 'List cache groups', hide: true map ['--list-cache-groups'] => :list_cache_groups def list_cache_groups(*_args) puts Facter::FactGroups.new.groups.to_yaml.lines[1..-1].join diff --git a/lib/facter/templates/man.erb b/lib/facter/templates/man.erb new file mode 100644 index 0000000000..64b6489056 --- /dev/null +++ b/lib/facter/templates/man.erb @@ -0,0 +1,122 @@ +<%# encoding: UTF-8%> +SYNOPSIS +-------- + facter [options] [query] [query] [...] + +DESCRIPTION +----------- +Collect and display facts about the current system. The library behind Facter is easy to extend, making Facter an easy way to collect information about a system. + +If no queries are given, then all facts will be returned. + +Many of the command line options can also be set via the HOCON config file. This file can also be used to block or cache certain fact groups. + +OPTIONS +------- +<% @Facter::Cli.class_options.each do |name, option| -%><% next if option.hide%> + * `<%= option.aliases[0] + '`, `' if option.aliases.any? %>--<%= 'no-' if negate_options.include?(name.to_s)%><%= name.to_s.gsub('_','-') %>`: + + <%= option.description %> + +<% end -%> + +FILES +----- +/etc/puppetlabs/facter/facter.conf + +A HOCON config file that can be used to specify directories for custom and external facts, set various command line options, and specify facts to block. See example below for details, or visit the GitHub README. + +EXAMPLES +-------- +Display all facts: + +``` +$ facter +disks => { + sda => { + model => "Virtual disk", + size => "8.00 GiB", + size_bytes => 8589934592, + vendor => "ExampleVendor" + } +} +dmi => { + bios => { + release_date => "06/23/2013", + vendor => "Example Vendor", + version => "6.00" + } +} +[\.\.\.] +``` + +Display a single structured fact: + +``` +$ facter processors +{ + count => 2, + isa => "x86_64", + models => [ + "Intel(R) Xeon(R) CPU E5-2680 v2 @ 2.80GHz", + "Intel(R) Xeon(R) CPU E5-2680 v2 @ 2.80GHz" + ], + physicalcount => 2 +} +``` + +Display a single fact nested within a structured fact: + +``` +$ facter processors.isa +x86_64 +``` + +Display a single legacy fact. Note that non-structured facts existing in previous versions of Facter are still available, +but are not displayed by default due to redundancy with newer structured facts: + +``` +$ facter processorcount +2 +``` + +Format facts as JSON: + +``` +$ facter \-\-json os.name os.release.major processors.isa +{ + "os.name": "Ubuntu", + "os.release.major": "14.04", + "processors.isa": "x86_64" +} +``` + +An example config file. + +``` +# always loaded (CLI and as Ruby module) +global : { + external-dir : "~/external/facts", + custom-dir : [ + "~/custom/facts", + "~/custom/facts/more-facts" + ], + no-external-facts : false, + no-custom-facts : false, + no-ruby : false +} +# loaded when running from the command line +cli : { + debug : false, + trace : true, + verbose : false, + log-level : "info" +} +# always loaded, fact-sepcific configuration +facts : { + # for valid blocklist entries, use --list-block-groups + blocklist : [ "file system", "EC2" ], + # for valid time-to-live entries, use --list-cache-groups + ttls : [ { "timezone" : 30 days } ] +} +``` diff --git a/man/man8/facter.8 b/man/man8/facter.8 new file mode 100644 index 0000000000..a95ae2888d --- /dev/null +++ b/man/man8/facter.8 @@ -0,0 +1,288 @@ +.\" generated with Ronn/v0.7.3 +.\" http://github.com/rtomayko/ronn/tree/0.7.3 +. +.TH "FACTER" "8" "July 2020" "Puppet, Inc." "Facter manual" +. +.SH "NAME" +\fBfacter\fR +. +.SH "SYNOPSIS" +facter [options] [query] [query] [\.\.\.] +. +.SH "DESCRIPTION" +Collect and display facts about the current system\. The library behind Facter is easy to extend, making Facter an easy way to collect information about a system\. +. +.P +If no queries are given, then all facts will be returned\. +. +.P +Many of the command line options can also be set via the HOCON config file\. This file can also be used to block or cache certain fact groups\. +. +.SH "OPTIONS" +. +.TP +\fB\-\-color\fR: +. +.IP +Enable color output\. +. +.TP +\fB\-c\fR, \fB\-\-config\fR: +. +.IP +The location of the config file\. +. +.TP +\fB\-\-custom\-dir\fR: +. +.IP +A directory to use for custom facts\. +. +.TP +\fB\-d\fR, \fB\-\-debug\fR: +. +.IP +Enable debug output\. +. +.TP +\fB\-\-external\-dir\fR: +. +.IP +A directory to use for external facts\. +. +.TP +\fB\-\-hocon\fR: +. +.IP +Output in Hocon format\. +. +.TP +\fB\-j\fR, \fB\-\-json\fR: +. +.IP +Output in JSON format\. +. +.TP +\fB\-\-list\-block\-groups\fR: +. +.IP +List the names of all blockable fact groups\. +. +.TP +\fB\-\-list\-cache\-groups\fR: +. +.IP +List the names of all cacheable fact groups\. +. +.TP +\fB\-l\fR, \fB\-\-log\-level\fR: +. +.IP +Set logging level\. Supported levels are: none, trace, debug, info, warn, error, and fatal\. +. +.TP +\fB\-\-no\-block\fR: +. +.IP +Disable fact blocking\. +. +.TP +\fB\-\-no\-cache\fR: +. +.IP +Disable loading and refreshing facts from the cache +. +.TP +\fB\-\-no\-custom\-facts\fR: +. +.IP +Disable custom facts\. +. +.TP +\fB\-\-no\-external\-facts\fR: +. +.IP +Disable external facts\. +. +.TP +\fB\-\-ruby\fR: +. +.IP +Disable loading Ruby, facts requiring Ruby, and custom facts\. +. +.TP +\fB\-\-trace\fR: +. +.IP +Enable backtraces for custom facts\. +. +.TP +\fB\-\-verbose\fR: +. +.IP +Enable verbose (info) output\. +. +.TP +\fB\-\-show\-legacy\fR: +. +.IP +Show legacy facts when querying all facts\. +. +.TP +\fB\-y\fR, \fB\-\-yaml\fR: +. +.IP +Output in YAML format\. +. +.TP +\fB\-\-strict\fR: +. +.IP +Enable more aggressive error reporting\. +. +.TP +\fB\-p\fR, \fB\-\-puppet\fR: +. +.IP +Load the Puppet libraries, thus allowing Facter to load Puppet\-specific facts\. +. +.SH "FILES" +\fI/etc/puppetlabs/facter/facter\.conf\fR +. +.P +A HOCON config file that can be used to specify directories for custom and external facts, set various command line options, and specify facts to block\. See example below for details, or visit the GitHub README\. +. +.SH "EXAMPLES" +Display all facts: +. +.IP "" 4 +. +.nf + +$ facter +disks => { + sda => { + model => "Virtual disk", + size => "8\.00 GiB", + size_bytes => 8589934592, + vendor => "ExampleVendor" + } +} +dmi => { + bios => { + release_date => "06/23/2013", + vendor => "Example Vendor", + version => "6\.00" + } +} +[\e\.\e\.\e\.] +. +.fi +. +.IP "" 0 +. +.P +Display a single structured fact: +. +.IP "" 4 +. +.nf + +$ facter processors +{ + count => 2, + isa => "x86_64", + models => [ + "Intel(R) Xeon(R) CPU E5\-2680 v2 @ 2\.80GHz", + "Intel(R) Xeon(R) CPU E5\-2680 v2 @ 2\.80GHz" + ], + physicalcount => 2 +} +. +.fi +. +.IP "" 0 +. +.P +Display a single fact nested within a structured fact: +. +.IP "" 4 +. +.nf + +$ facter processors\.isa +x86_64 +. +.fi +. +.IP "" 0 +. +.P +Display a single legacy fact\. Note that non\-structured facts existing in previous versions of Facter are still available, but are not displayed by default due to redundancy with newer structured facts: +. +.IP "" 4 +. +.nf + +$ facter processorcount +2 +. +.fi +. +.IP "" 0 +. +.P +Format facts as JSON: +. +.IP "" 4 +. +.nf + +$ facter \e\-\e\-json os\.name os\.release\.major processors\.isa +{ + "os\.name": "Ubuntu", + "os\.release\.major": "14\.04", + "processors\.isa": "x86_64" +} +. +.fi +. +.IP "" 0 +. +.P +An example config file\. +. +.IP "" 4 +. +.nf + +# always loaded (CLI and as Ruby module) +global : { + external\-dir : "~/external/facts", + custom\-dir : [ + "~/custom/facts", + "~/custom/facts/more\-facts" + ], + no\-external\-facts : false, + no\-custom\-facts : false, + no\-ruby : false +} +# loaded when running from the command line +cli : { + debug : false, + trace : true, + verbose : false, + log\-level : "info" +} +# always loaded, fact\-sepcific configuration +facts : { + # for valid blocklist entries, use \-\-list\-block\-groups + blocklist : [ "file system", "EC2" ], + # for valid time\-to\-live entries, use \-\-list\-cache\-groups + ttls : [ { "timezone" : 30 days } ] +} +. +.fi +. +.IP "" 0 + diff --git a/tasks/manpages.rake b/tasks/manpages.rake new file mode 100644 index 0000000000..a42e136ff9 --- /dev/null +++ b/tasks/manpages.rake @@ -0,0 +1,25 @@ +# frozen_string_literal: true + +desc 'Build Facter manpages' +task :gen_manpages do + require 'fileutils' + + ronn_args = '--manual="Facter manual" --organization="Puppet, Inc." --roff' + + # Locate ronn + begin + require 'ronn' + rescue LoadError + abort('Run `bundle install --with documentation` to install the `ronn` gem.') + end + + ronn = `which ronn`.chomp + + abort('Ronn does not appear to be installed') unless File.executable?(ronn) + + FileUtils.mkdir_p('./man/man8') + + `bin/facter --man > ./man/man8/facter.8.ronn` + `#{ronn} #{ronn_args} ./man/man8/facter.8.ronn` + FileUtils.rm('./man/man8/facter.8.ronn') +end