require 'puppet/face' # Implements the 'puppet strings' interface. Puppet::Face.define(:strings, '0.0.1') do summary 'Generate Puppet documentation with YARD.' action(:generate) do default option '--format OUTPUT_FORMAT' do summary 'Designate output format, JSON or markdown.' end option '--out PATH' do summary 'Write selected format to PATH. If no path is designated, strings prints to STDOUT.' end option '--markup FORMAT' do summary "The markup format to use for docstring text (defaults to 'markdown')." end option '--emit-json-stdout' do summary 'DEPRECATED: Print JSON representation of the documentation to stdout.' end option '--emit-json PATH' do summary 'DEPRECATED: Write JSON representation of the documentation to the given file.' end summary 'Generate documentation from files.' arguments '[[search_pattern] ...]' when_invoked do |*args| check_required_features require 'puppet-strings' PuppetStrings::generate( args.count > 1 ? args[0..-2] : PuppetStrings::DEFAULT_SEARCH_PATTERNS, build_generate_options(args.last) ) nil end end action(:server) do option '--markup FORMAT' do summary "The markup format to use for docstring text (defaults to 'markdown')." end summary 'Runs a local documentation server for the modules in the current Puppet environment.' arguments '[[module_name] ...]' when_invoked do |*args| check_required_features require 'puppet-strings' modules = args.count > 1 ? args[0..-2] : [] # Generate documentation for all (or the given) modules module_docs = [] environment = Puppet.lookup(:current_environment) environment.modules.each do |mod| next unless modules.empty? || modules.include?(mod.name) db = File.join(mod.path, '.yardoc') patterns = PuppetStrings::DEFAULT_SEARCH_PATTERNS.map do |p| File.join(mod.path, p) end puts "Generating documentation for Puppet module '#{mod.name}'." PuppetStrings.generate(patterns, build_generate_options(args.last, '--db', db)) # Clear the registry so that the next call to generate has a clean database YARD::Registry.clear module_docs << mod.name module_docs << db end if module_docs.empty? puts 'No Puppet modules were found to serve documentation for.' return end puts 'Starting YARD documentation server.' PuppetStrings::run_server('-m', *module_docs) nil end end action(:describe) do #This is Kris' experiment with string based describe option "--list" do summary "list types" end option "--providers" do summary "provide details on providers" end #TODO: Implement the rest of describe behavior # * --help: # Print this help text # * --providers: # Describe providers in detail for each type # * --list: # List all types # * --meta: # List all metaparameters # * --short: # List only parameters without detail when_invoked do |*args| check_required_features require 'puppet-strings' options = args.last options[:describe] = true options[:stdout] = true options[:format] = 'json' if args.length > 1 if options[:list] $stderr.puts "WARNING: ignoring types when listing all types." else options[:describe_types] = args[0..-2] end end #TODO: Set up search_patterns and whatever else needed to collect data for describe - currently missing some # manifests/**/*.pp # functions/**/*.pp # tasks/*.json # plans/*.pp search_patterns = %w( types/**/*.pp lib/**/*.rb ) PuppetStrings::generate( search_patterns, build_generate_options(options) ) nil end end # Checks that the required features are installed. # @return [void] def check_required_features raise RuntimeError, "The 'yard' gem must be installed in order to use this face." unless Puppet.features.yard? raise RuntimeError, "The 'rgen' gem must be installed in order to use this face." unless Puppet.features.rgen? raise RuntimeError, 'This face requires Ruby 1.9 or greater.' if RUBY_VERSION =~ /^1\.8/ end # Builds the options to PuppetStrings.generate. # @param [Hash] options The Puppet face options hash. # @param [Array] yard_args The additional arguments to pass to YARD. # @return [Hash] Returns the PuppetStrings.generate options hash. def build_generate_options(options = nil, *yard_args) generate_options = {} generate_options[:debug] = Puppet[:debug] generate_options[:backtrace] = Puppet[:trace] generate_options[:yard_args] = yard_args unless yard_args.empty? if options if options[:emit_json] $stderr.puts "WARNING: '--emit-json PATH' is deprecated. Use '--format json --out PATH' instead." end if options[:emit_json_stdout] $stderr.puts "WARNING: '--emit-json-stdout' is deprecated. Use '--format json' instead." end markup = options[:markup] generate_options[:markup] = markup if markup generate_options[:path] = options[:out] if options[:out] generate_options[:stdout] = options[:stdout] if options[:describe] generate_options[:describe] = true generate_options[:describe_types] = options[:describe_types] generate_options[:describe_list] = options[:list] end format = options[:format] if format if format.casecmp('markdown').zero? generate_options[:markdown] = true elsif format.casecmp('json').zero? || options[:emit_json] || options[:emit_json_stdout] generate_options[:json] = true generate_options[:path] ||= options[:emit_json] if options[:emit_json] else raise RuntimeError, "Invalid format #{options[:format]}. Please select 'json' or 'markdown'." end elsif options[:emit_json] || options[:emit_json_stdout] generate_options[:json] = true generate_options[:path] ||= options[:emit_json] if options[:emit_json] end end generate_options end end