From 42666642e29c6f96cabe53933ea985864fd947fd Mon Sep 17 00:00:00 2001 From: Josh Cooper Date: Thu, 29 Aug 2024 09:36:02 -0700 Subject: [PATCH 1/2] (PUP-12075) Refactor how application summaries are generated Add common_app_summaries and specialized_app_summaries methods and refactor help face to call them. --- lib/puppet/face/help.rb | 66 +++++++++++++++++++++++++++-------------- 1 file changed, 43 insertions(+), 23 deletions(-) diff --git a/lib/puppet/face/help.rb b/lib/puppet/face/help.rb index 0e49758ac35..70a1826cfa2 100644 --- a/lib/puppet/face/help.rb +++ b/lib/puppet/face/help.rb @@ -151,6 +151,33 @@ def legacy_applications end.sort end + def generate_summary(appname) + if is_face_app?(appname) + begin + face = Puppet::Face[appname, :current] + # Add deprecation message to summary if the face is deprecated + summary = face.deprecated? ? face.summary + ' ' + _("(Deprecated)") : face.summary + [appname, summary, ' '] + rescue StandardError, LoadError + error_message = _("!%{sub_command}! Subcommand unavailable due to error.") % { sub_command: appname } + error_message += ' ' + _("Check error logs.") + [error_message, '', ' '] + end + else + begin + summary = Puppet::Application[appname].summary + if summary.empty? + summary = horribly_extract_summary_from(appname) + end + [appname, summary, ' '] + rescue StandardError, LoadError + error_message = _("!%{sub_command}! Subcommand unavailable due to error.") % { sub_command: appname } + error_message += ' ' + _("Check error logs.") + [error_message, '', ' '] + end + end + end + # Return a list of all applications (both legacy and Face applications), along with a summary # of their functionality. # @return [Array] An Array of Arrays. The outer array contains one entry per application; each @@ -162,29 +189,8 @@ def all_application_summaries if appname == COMMON || appname == SPECIALIZED || appname == BLANK result << appname - elsif is_face_app?(appname) - begin - face = Puppet::Face[appname, :current] - # Add deprecation message to summary if the face is deprecated - summary = face.deprecated? ? face.summary + ' ' + _("(Deprecated)") : face.summary - result << [appname, summary, ' '] - rescue StandardError, LoadError - error_message = _("!%{sub_command}! Subcommand unavailable due to error.") % { sub_command: appname } - error_message += ' ' + _("Check error logs.") - result << [error_message, '', ' '] - end else - begin - summary = Puppet::Application[appname].summary - if summary.empty? - summary = horribly_extract_summary_from(appname) - end - result << [appname, summary, ' '] - rescue StandardError, LoadError - error_message = _("!%{sub_command}! Subcommand unavailable due to error.") % { sub_command: appname } - error_message += ' ' + _("Check error logs.") - result << [error_message, '', ' '] - end + result << generate_summary(appname) end end end @@ -192,15 +198,29 @@ def all_application_summaries COMMON = 'Common:' SPECIALIZED = 'Specialized:' BLANK = "\n" + COMMON_APPS = %w[apply agent config help lookup module resource] def available_application_names_special_sort full_list = Puppet::Application.available_application_names - a_list = full_list & %w[apply agent config help lookup module resource] + a_list = full_list & COMMON_APPS a_list = a_list.sort also_ran = full_list - a_list also_ran = also_ran.sort [[COMMON], a_list, [BLANK], [SPECIALIZED], also_ran].flatten(1) end + def common_app_summaries + COMMON_APPS.map do |appname| + generate_summary(appname) + end + end + + def specialized_app_summaries + specialized_apps = Puppet::Application.available_application_names - COMMON_APPS + specialized_apps.filter_map do |appname| + generate_summary(appname) unless exclude_from_docs?(appname) + end + end + def horribly_extract_summary_from(appname) help = Puppet::Application[appname].help.split("\n") # Now we find the line with our summary, extract it, and return it. This From 653439191e3a624f11c074c8ca0edc40ea551891 Mon Sep 17 00:00:00 2001 From: Josh Cooper Date: Wed, 28 Aug 2024 18:07:13 -0700 Subject: [PATCH 2/2] (PUP-12075) Render puppet man page correctly Previously, the man/man8/puppet.8 man page wasn't formatted correctly with each subcommand and summary on a new line. This was because `puppet --help` doesn't output ronn format, just raw text. So generate `puppet.8.ronn` in valid ronn format so that it can be converted to roff. Use `man --local-file man/man8/puppet.8` to verify the results. Also don't blindly run `/ --help` for every app. That's left over from when puppet had multiple bin stubs. Since ronn shells out to groff, abort if the latter is not installed. Hardcode the http_user_agent value so it's not sensitive to the puppet version or the ruby version/architecture the user is running. --- lib/puppet/reference/configuration.rb | 2 + man/man5/puppet.conf.5 | 2 +- man/man8/puppet.8 | 129 ++++++++++++++++++++++++-- rakelib/man/puppet.erb | 34 +++++++ rakelib/manpages.rake | 24 +++-- 5 files changed, 174 insertions(+), 17 deletions(-) create mode 100644 rakelib/man/puppet.erb diff --git a/lib/puppet/reference/configuration.rb b/lib/puppet/reference/configuration.rb index 33117c6ce6f..bd91adf441a 100644 --- a/lib/puppet/reference/configuration.rb +++ b/lib/puppet/reference/configuration.rb @@ -43,6 +43,8 @@ val = "the Host's fully qualified domain name, as determined by Facter" when 'srv_domain' val = 'example.com' + when 'http_user_agent' + val = 'Puppet/ Ruby/ ()' end # Leave out the section information; it was apparently confusing people. diff --git a/man/man5/puppet.conf.5 b/man/man5/puppet.conf.5 index 7afec651036..c78ffee770d 100644 --- a/man/man5/puppet.conf.5 +++ b/man/man5/puppet.conf.5 @@ -973,7 +973,7 @@ The time to wait for data to be read from an HTTP connection\. If nothing is rea The HTTP User\-Agent string to send when making network requests\. . .IP "\(bu" 4 -\fIDefault\fR: \fBPuppet/8\.9\.0 Ruby/3\.1\.1\-p18 (x86_64\-linux)\fR +\fIDefault\fR: \fBPuppet/ Ruby/ ()\fR . .IP "" 0 . diff --git a/man/man8/puppet.8 b/man/man8/puppet.8 index c9296f616a3..e3c022c74ba 100644 --- a/man/man8/puppet.8 +++ b/man/man8/puppet.8 @@ -4,25 +4,138 @@ .TH "PUPPET" "8" "August 2024" "Puppet, Inc." "Puppet manual" . .SH "NAME" -\fBpuppet\fR +\fBpuppet\fR \- an automated configuration management tool +. +.SH "SYNOPSIS" +\fBpuppet\fR \fIsubcommand\fR [options] \fIaction\fR [options] +. +.SH "DESCRIPTION" +Puppet, an automated administrative engine for your Linux, Unix, and Windows systems, performs administrative tasks (such as adding users, installing packages, and updating server configurations) based on a centralized specification\. +. +.SH "COMMANDS" +. +.SS "Common" +\fBapply\fR +. +.br +\~\~\~\~Apply Puppet manifests locally +. +.P +\fBagent\fR +. +.br +\~\~\~\~The puppet agent daemon +. +.P +\fBconfig\fR +. +.br +\~\~\~\~Interact with Puppet\'s settings\. +. +.P +\fBhelp\fR +. +.br +\~\~\~\~Display Puppet help\. +. +.P +\fBlookup\fR +. +.br +\~\~\~\~Interactive Hiera lookup +. +.P +\fBmodule\fR +. +.br +\~\~\~\~Creates, installs and searches for modules on the Puppet Forge\. +. +.P +\fBresource\fR +. +.br +\~\~\~\~The resource abstraction layer shell +. +.SS "Specialized" +\fBcatalog\fR +. +.br +\~\~\~\~Compile, save, view, and convert catalogs\. +. +.P +\fBdescribe\fR +. +.br +\~\~\~\~Display help about resource types +. +.P +\fBdevice\fR +. +.br +\~\~\~\~Manage remote network devices +. +.P +\fBdoc\fR +. +.br +\~\~\~\~Generate Puppet references . .P -Usage: puppet \fIsubcommand\fR [options] \fIaction\fR [options] +\fBepp\fR +. +.br +\~\~\~\~Interact directly with the EPP template parser/renderer\. . .P -Available subcommands: +\fBfacts\fR +. +.br +\~\~\~\~Retrieve and store facts\. +. +.P +\fBfilebucket\fR +. +.br +\~\~\~\~Store and retrieve files in a filebucket . .P -Common: +\fBgenerate\fR . .br -agent The puppet agent daemon apply Apply Puppet manifests locally config Interact with Puppet\'s settings\. help Display Puppet help\. lookup Interactive Hiera lookup module Creates, installs and searches for modules on the Puppet Forge\. resource The resource abstraction layer shell +\~\~\~\~Generates Puppet code from Ruby definitions\. . .P -Specialized: +\fBnode\fR . .br -catalog Compile, save, view, and convert catalogs\. describe Display help about resource types device Manage remote network devices doc Generate Puppet references epp Interact directly with the EPP template parser/renderer\. facts Retrieve and store facts\. filebucket Store and retrieve files in a filebucket generate Generates Puppet code from Ruby definitions\. node View and manage node definitions\. parser Interact directly with the parser\. plugin Interact with the Puppet plugin system\. script Run a puppet manifests as a script without compiling a catalog ssl Manage SSL keys and certificates for puppet SSL clients +\~\~\~\~View and manage node definitions\. +. +.P +\fBparser\fR +. +.br +\~\~\~\~Interact directly with the parser\. +. +.P +\fBplugin\fR +. +.br +\~\~\~\~Interact with the Puppet plugin system\. +. +.P +\fBscript\fR +. +.br +\~\~\~\~Run a puppet manifests as a script without compiling a catalog +. +.P +\fBssl\fR +. +.br +\~\~\~\~Manage SSL keys and certificates for puppet SSL clients +. +.SH "SEE ALSO" +See \fBpuppet help \fR for help on a specific subcommand\. . .P -See \'puppet help \fIsubcommand\fR \fIaction\fR\' for help on a specific subcommand action\. See \'puppet help \fIsubcommand\fR\' for help on a specific subcommand\. Puppet v8\.9\.0 +See \fBpuppet help \fR for help on a specific subcommand action\. diff --git a/rakelib/man/puppet.erb b/rakelib/man/puppet.erb new file mode 100644 index 00000000000..3df008c12bf --- /dev/null +++ b/rakelib/man/puppet.erb @@ -0,0 +1,34 @@ +puppet(8) - an automated configuration management tool +========= + +## SYNOPSIS + +`puppet` [options] [options] + +## DESCRIPTION + +Puppet, an automated administrative engine for your Linux, Unix, and Windows systems, performs administrative tasks +(such as adding users, installing packages, and updating server configurations) based on a centralized specification. + +## COMMANDS + +### Common + +<% common.each do |appname, summary, _| -%> +`<%= appname.to_s %>`
+    <%= summary %> + +<% end -%> + +### Specialized + +<% specialized.each do |appname, summary, _| -%> +`<%= appname.to_s %>`
+    <%= summary %> + +<% end -%> + +## SEE ALSO +See `puppet help ` for help on a specific subcommand. + +See `puppet help ` for help on a specific subcommand action. diff --git a/rakelib/manpages.rake b/rakelib/manpages.rake index c98fd0f3371..73acacce1b7 100644 --- a/rakelib/manpages.rake +++ b/rakelib/manpages.rake @@ -6,7 +6,6 @@ task :gen_manpages do Puppet.initialize_settings helpface = Puppet::Face[:help, '0.0.1'] - bins = Dir.glob(%w{bin/*}) non_face_applications = helpface.legacy_applications faces = Puppet::Face.faces.map(&:to_s) apps = non_face_applications + faces @@ -30,19 +29,28 @@ task :gen_manpages do abort("Ronn does not appear to be installed") end + # ronn shells out to groff + groff = %x{which groff}.chomp + unless File.executable?(groff) + abort("Groff does not appear to be installed") + end + %x{mkdir -p ./man/man5 ./man/man8} %x{RUBYLIB=./lib:$RUBYLIB bin/puppet doc --reference configuration > ./man/man5/puppetconf.5.ronn} %x{#{ronn} #{ronn_args} ./man/man5/puppetconf.5.ronn} FileUtils.mv("./man/man5/puppetconf.5", "./man/man5/puppet.conf.5") FileUtils.rm("./man/man5/puppetconf.5.ronn") - # Create LEGACY binary man pages (i.e. delete me for 2.8.0) - bins.each do |bin| - b = bin.gsub( /^s?bin\//, "") - %x{RUBYLIB=./lib:$RUBYLIB #{bin} --help > ./man/man8/#{b}.8.ronn} - %x{#{ronn} #{ronn_args} ./man/man8/#{b}.8.ronn} - FileUtils.rm("./man/man8/#{b}.8.ronn") - end + # Create puppet binary man page + # puppet --help outputs raw text, not ronn, so trying to convert that to roff + # fails miserably. Render valid ronn so we can convert to roff + common = helpface.common_app_summaries + specialized = helpface.specialized_app_summaries + template_binding = OpenStruct.new(common: common, specialized: specialized).instance_eval {binding} + content = ERB.new(File.read(File.join(__dir__, 'man/puppet.erb')), trim_mode: '-').result(template_binding) + File.write("./man/man8/puppet.8.ronn", content) + %x{#{ronn} #{ronn_args} ./man/man8/puppet.8.ronn} + FileUtils.rm("./man/man8/puppet.8.ronn") apps.each do |app| %x{RUBYLIB=./lib:$RUBYLIB bin/puppet help #{app} --ronn > ./man/man8/puppet-#{app}.8.ronn}