diff --git a/lib/puppet-strings.rb b/lib/puppet-strings.rb index b8b84bb..3c7958d 100644 --- a/lib/puppet-strings.rb +++ b/lib/puppet-strings.rb @@ -7,6 +7,7 @@ module PuppetStrings types/**/*.pp lib/**/*.rb tasks/*.json + plans/*.pp ).freeze # Generates documentation. @@ -62,6 +63,10 @@ module PuppetStrings end end + def self.puppet_5? + Puppet::Util::Package.versioncmp(Puppet.version, "5.0.0") >= 0 + end + def self.render_json(path) require 'puppet-strings/json' PuppetStrings::Json.render(path) diff --git a/lib/puppet-strings/json.rb b/lib/puppet-strings/json.rb index 85491e5..e0ac1fb 100644 --- a/lib/puppet-strings/json.rb +++ b/lib/puppet-strings/json.rb @@ -13,6 +13,7 @@ module PuppetStrings::Json providers: YARD::Registry.all(:puppet_provider).sort_by!(&:name).map!(&:to_hash), puppet_functions: YARD::Registry.all(:puppet_function).sort_by!(&:name).map!(&:to_hash), puppet_tasks: YARD::Registry.all(:puppet_task).sort_by!(&:name).map!(&:to_hash), + puppet_plans: YARD::Registry.all(:puppet_plan).sort_by!(&:name).map!(&:to_hash) # TODO: Need Ruby documentation? } diff --git a/lib/puppet-strings/markdown.rb b/lib/puppet-strings/markdown.rb index e5b0d49..c3cebee 100644 --- a/lib/puppet-strings/markdown.rb +++ b/lib/puppet-strings/markdown.rb @@ -7,6 +7,7 @@ module PuppetStrings::Markdown require_relative 'markdown/defined_types' require_relative 'markdown/resource_types' require_relative 'markdown/puppet_tasks' + require_relative 'markdown/puppet_plans' require_relative 'markdown/table_of_contents' # generates markdown documentation @@ -19,6 +20,7 @@ module PuppetStrings::Markdown final << PuppetStrings::Markdown::ResourceTypes.render final << PuppetStrings::Markdown::Functions.render final << PuppetStrings::Markdown::PuppetTasks.render + final << PuppetStrings::Markdown::PuppetPlans.render final end diff --git a/lib/puppet-strings/markdown/puppet_plan.rb b/lib/puppet-strings/markdown/puppet_plan.rb new file mode 100644 index 0000000..e4e62e3 --- /dev/null +++ b/lib/puppet-strings/markdown/puppet_plan.rb @@ -0,0 +1,14 @@ +require 'puppet-strings/markdown/base' + +module PuppetStrings::Markdown + class PuppetPlan < Base + def initialize(registry) + @template = 'classes_and_defines.erb' + super(registry, 'plan') + end + + def render + super(@template) + end + end +end diff --git a/lib/puppet-strings/markdown/puppet_plans.rb b/lib/puppet-strings/markdown/puppet_plans.rb new file mode 100644 index 0000000..71ffa2e --- /dev/null +++ b/lib/puppet-strings/markdown/puppet_plans.rb @@ -0,0 +1,37 @@ +require_relative 'puppet_plan' + +module PuppetStrings::Markdown + module PuppetPlans + + # @return [Array] list of classes + def self.in_plans + arr = YARD::Registry.all(:puppet_plan).sort_by!(&:name).map!(&:to_hash) + arr.map! { |a| PuppetStrings::Markdown::PuppetPlan.new(a) } + end + + def self.contains_private? + result = false + unless in_plans.nil? + in_plans.find { |plan| plan.private? }.nil? ? false : true + end + end + + def self.render + final = in_plans.length > 0 ? "## Plans\n\n" : "" + in_plans.each do |plan| + final << plan.render unless plan.private? + end + final + end + + def self.toc_info + final = ["Plans"] + + in_classes.each do |plan| + final.push(plan.toc_info) + end + + final + end + end +end diff --git a/lib/puppet-strings/yard.rb b/lib/puppet-strings/yard.rb index 256b69b..48cf1c6 100644 --- a/lib/puppet-strings/yard.rb +++ b/lib/puppet-strings/yard.rb @@ -49,7 +49,8 @@ class YARD::CLI::Yardoc :puppet_type, :puppet_provider, :puppet_function, - :puppet_task + :puppet_task, + :puppet_plan ) end end @@ -82,6 +83,11 @@ class YARD::CLI::Stats output 'Puppet Tasks', *type_statistics_all(:puppet_task) end + def stats_for_puppet_plans + return unless PuppetStrings.puppet_5? + output 'Puppet Plans', *type_statistics_all(:puppet_plan) + end + def output(name, data, undoc = nil) # Monkey patch output to accommodate our larger header widths @total += data if data.is_a?(Integer) && undoc diff --git a/lib/puppet-strings/yard/code_objects.rb b/lib/puppet-strings/yard/code_objects.rb index 70f511a..0d3ecd4 100644 --- a/lib/puppet-strings/yard/code_objects.rb +++ b/lib/puppet-strings/yard/code_objects.rb @@ -6,4 +6,5 @@ module PuppetStrings::Yard::CodeObjects require 'puppet-strings/yard/code_objects/provider' require 'puppet-strings/yard/code_objects/function' require 'puppet-strings/yard/code_objects/task' + require 'puppet-strings/yard/code_objects/plan' end diff --git a/lib/puppet-strings/yard/code_objects/plan.rb b/lib/puppet-strings/yard/code_objects/plan.rb new file mode 100644 index 0000000..13ef8ce --- /dev/null +++ b/lib/puppet-strings/yard/code_objects/plan.rb @@ -0,0 +1,56 @@ +require 'puppet-strings/yard/code_objects/group' + +class PuppetStrings::Yard::CodeObjects::Plans < PuppetStrings::Yard::CodeObjects::Group + # Gets the singleton instance of the group. + # @return Returns the singleton instance of the group. + def self.instance + super(:puppet_plans) + end + + # Gets the display name of the group. + # @param [Boolean] prefix whether to show a prefix. Ignored for Puppet group namespaces. + # @return [String] Returns the display name of the group. + def name(prefix = false) + 'Puppet Plans' + end +end + +class PuppetStrings::Yard::CodeObjects::Plan < PuppetStrings::Yard::CodeObjects::Base + attr_reader :statement + attr_reader :parameters + + # Initializes a Puppet plan code object. + # @param [PuppetStrings::Parsers::PlanStatement] statement The plan statement that was parsed. + # @return [void] + def initialize(statement) + @statement = statement + @parameters = statement.parameters.map { |p| [p.name, p.value] } + super(PuppetStrings::Yard::CodeObjects::Plans.instance, statement.name) + end + + # Gets the type of the code object. + # @return Returns the type of the code object. + def type + :puppet_plan + end + + # Gets the source of the code object. + # @return Returns the source of the code object. + def source + @statement.source + end + + # Converts the code object to a hash representation. + # @return [Hash] Returns a hash representation of the code object. + def to_hash + hash = {} + hash[:name] = name + hash[:file] = file + hash[:line] = line + hash[:docstring] = PuppetStrings::Json.docstring_to_hash(docstring) + defaults = Hash[*parameters.select{ |p| !p[1].nil? }.flatten] + hash[:defaults] = defaults unless defaults.empty? + hash[:source] = source unless source && source.empty? + hash + end +end diff --git a/lib/puppet-strings/yard/handlers.rb b/lib/puppet-strings/yard/handlers.rb index 7471a28..081e2a2 100644 --- a/lib/puppet-strings/yard/handlers.rb +++ b/lib/puppet-strings/yard/handlers.rb @@ -18,5 +18,6 @@ module PuppetStrings::Yard::Handlers require 'puppet-strings/yard/handlers/puppet/class_handler' require 'puppet-strings/yard/handlers/puppet/defined_type_handler' require 'puppet-strings/yard/handlers/puppet/function_handler' + require 'puppet-strings/yard/handlers/puppet/plan_handler' end end diff --git a/lib/puppet-strings/yard/handlers/puppet/plan_handler.rb b/lib/puppet-strings/yard/handlers/puppet/plan_handler.rb new file mode 100644 index 0000000..54d241e --- /dev/null +++ b/lib/puppet-strings/yard/handlers/puppet/plan_handler.rb @@ -0,0 +1,27 @@ +require 'puppet-strings/yard/handlers/helpers' +require 'puppet-strings/yard/handlers/puppet/base' +require 'puppet-strings/yard/parsers' +require 'puppet-strings/yard/code_objects' + +# Implements the handler for Puppet classes. +class PuppetStrings::Yard::Handlers::Puppet::PlanHandler < PuppetStrings::Yard::Handlers::Puppet::Base + handles PuppetStrings::Yard::Parsers::Puppet::PlanStatement + + process do + # Register the object + object = PuppetStrings::Yard::CodeObjects::Plan.new(statement) + register object + + # Log a warning if missing documentation + log.warn "Missing documentation for Puppet plan '#{object.name}' at #{statement.file}:#{statement.line}." if object.docstring.empty? && object.tags.empty? + + # Set the parameter types + set_parameter_types(object) + + # Mark the class as public if it doesn't already have an api tag + object.add_tag YARD::Tags::Tag.new(:api, 'public') unless object.has_tag? :api + + # Warn if a summary longer than 140 characters was provided + PuppetStrings::Yard::Handlers::Helpers.validate_summary_tag(object) if object.has_tag? :summary + end +end diff --git a/lib/puppet-strings/yard/parsers/puppet/parser.rb b/lib/puppet-strings/yard/parsers/puppet/parser.rb index a74675b..6c91826 100644 --- a/lib/puppet-strings/yard/parsers/puppet/parser.rb +++ b/lib/puppet-strings/yard/parsers/puppet/parser.rb @@ -20,6 +20,11 @@ class PuppetStrings::Yard::Parsers::Puppet::Parser < YARD::Parser::Base # @return [void] def parse begin + Puppet[:tasks] = true if Puppet.settings.include?(:tasks) + if Puppet::Util::Package.versioncmp(Puppet.version, "5.0.0") < 0 && @file.to_s.match(/^plans\//) + log.warn "Skipping #{@file}: Puppet Plans require Puppet 5 or greater." + return + end @statements ||= (@visitor.visit(::Puppet::Pops::Parser::Parser.new.parse_string(source)) || []).compact rescue ::Puppet::ParseError => ex log.error "Failed to parse #{@file}: #{ex.message}" @@ -64,6 +69,12 @@ class PuppetStrings::Yard::Parsers::Puppet::Parser < YARD::Parser::Base statement end + def transform_PlanDefinition(o) + statement = PuppetStrings::Yard::Parsers::Puppet::PlanStatement.new(o, @file) + statement.extract_docstring(@lines) + statement + end + def transform_Object(o) # Ignore anything else (will be compacted out of the resulting array) end diff --git a/lib/puppet-strings/yard/parsers/puppet/statement.rb b/lib/puppet-strings/yard/parsers/puppet/statement.rb index 89ae1fa..eea04a7 100644 --- a/lib/puppet-strings/yard/parsers/puppet/statement.rb +++ b/lib/puppet-strings/yard/parsers/puppet/statement.rb @@ -151,4 +151,18 @@ module PuppetStrings::Yard::Parsers::Puppet end end end + + # Implements the Puppet plan statement. + class PlanStatement < ParameterizedStatement + attr_reader :name + + # Initializes the Puppet plan statement. + # @param [Puppet::Pops::Model::PlanDefinition] object The model object for the plan statement. + # @param [String] file The file containing the statement. + def initialize(object, file) + super(object, file) + @name = object.name + end + end + end diff --git a/lib/puppet-strings/yard/templates/default/fulldoc/html/full_list_puppet_plan.erb b/lib/puppet-strings/yard/templates/default/fulldoc/html/full_list_puppet_plan.erb new file mode 100644 index 0000000..095188f --- /dev/null +++ b/lib/puppet-strings/yard/templates/default/fulldoc/html/full_list_puppet_plan.erb @@ -0,0 +1,9 @@ +<% even = false %> +<% @items.each do |item| %> +
  • +
    + <%= linkify item, h(item.name(true)) %> +
    +
  • + <% even = !even %> +<% end %> diff --git a/lib/puppet-strings/yard/templates/default/fulldoc/html/setup.rb b/lib/puppet-strings/yard/templates/default/fulldoc/html/setup.rb index e178613..5a3425f 100644 --- a/lib/puppet-strings/yard/templates/default/fulldoc/html/setup.rb +++ b/lib/puppet-strings/yard/templates/default/fulldoc/html/setup.rb @@ -71,3 +71,12 @@ def generate_puppet_task_list @list_type = 'puppet_task' generate_list_contents end + +# Generates the searchable Puppet Plan list. +# @return [void] +def generate_puppet_plan_list + @items = Registry.all(:puppet_plan).sort_by {|t| t.name.to_s } + @list_title = 'Puppet Plan List' + @list_type = 'puppet_plan' + generate_list_contents +end diff --git a/lib/puppet-strings/yard/templates/default/layout/html/setup.rb b/lib/puppet-strings/yard/templates/default/layout/html/setup.rb index 7b237a8..8a5aaa1 100644 --- a/lib/puppet-strings/yard/templates/default/layout/html/setup.rb +++ b/lib/puppet-strings/yard/templates/default/layout/html/setup.rb @@ -4,7 +4,7 @@ def init case object when '_index.html' @page_title = options.title - sections :layout, [:index, [:listing, [:classes, :defined_types, :types, :providers, :functions, :tasks, :files, :objects]]] + sections :layout, [:index, [:listing, [:classes, :defined_types, :types, :providers, :functions, :tasks, :plans, :files, :objects]]] else super end @@ -50,6 +50,10 @@ def layout @nav_url = url_for_list('puppet_task') @page_title = "Puppet Task: #{object.name}" @path = object.path + when PuppetStrings::Yard::CodeObjects::Plan + @nav_url = url_for_list('puppet_plan') + @page_title = "Puppet Plan: #{object.name}" + @path = object.path else @path = object.path end @@ -97,6 +101,11 @@ def create_menu_lists title: 'Puppet Tasks', search_totle: 'Puppet Tasks' }, + { + type: 'puppet_plan', + title: 'Puppet Plans', + search_totle: 'Puppet Plans' + }, { type: 'class', title: 'Ruby Classes', @@ -186,6 +195,14 @@ def tasks erb(:objects) end +# Renders the plans section. +# @return [String] Returns the rendered section. +def plans + @title = 'Puppet Plan Listing A-Z' + @objects_by_letter = objects_by_letter(:puppet_plan) + erb(:objects) +end + # Renders the objects section. # @return [String] Returns the rendered section. def objects diff --git a/lib/puppet-strings/yard/templates/default/puppet_plan/html/box_info.erb b/lib/puppet-strings/yard/templates/default/puppet_plan/html/box_info.erb new file mode 100644 index 0000000..49a6460 --- /dev/null +++ b/lib/puppet-strings/yard/templates/default/puppet_plan/html/box_info.erb @@ -0,0 +1,10 @@ +
    +
    +
    Defined in:
    +
    + <%= object.file %><% if object.files.size > 1 %>,
    + <%= object.files[1..-1].map {|f| f.first }.join(",
    ") %>
    + <% end %> + + + diff --git a/lib/puppet-strings/yard/templates/default/puppet_plan/html/header.erb b/lib/puppet-strings/yard/templates/default/puppet_plan/html/header.erb new file mode 100644 index 0000000..9085f70 --- /dev/null +++ b/lib/puppet-strings/yard/templates/default/puppet_plan/html/header.erb @@ -0,0 +1 @@ +

    Puppet Plan: <%= object.name %>

    diff --git a/lib/puppet-strings/yard/templates/default/puppet_plan/html/overview.erb b/lib/puppet-strings/yard/templates/default/puppet_plan/html/overview.erb new file mode 100644 index 0000000..a5b527a --- /dev/null +++ b/lib/puppet-strings/yard/templates/default/puppet_plan/html/overview.erb @@ -0,0 +1,6 @@ +

    Overview

    +
    +
    + <%= htmlify(object.docstring) %> +
    +
    diff --git a/lib/puppet-strings/yard/templates/default/puppet_plan/html/setup.rb b/lib/puppet-strings/yard/templates/default/puppet_plan/html/setup.rb new file mode 100644 index 0000000..0db700d --- /dev/null +++ b/lib/puppet-strings/yard/templates/default/puppet_plan/html/setup.rb @@ -0,0 +1,11 @@ +# Initializes the template. +# @return [void] +def init + sections :header, :box_info, :summary, :overview, T('tags'), :source +end + +# Renders the box_info section. +# @return [String] Returns the rendered section. +def box_info + erb(:box_info) +end diff --git a/lib/puppet-strings/yard/templates/default/puppet_plan/html/source.erb b/lib/puppet-strings/yard/templates/default/puppet_plan/html/source.erb new file mode 100644 index 0000000..0fd3c5e --- /dev/null +++ b/lib/puppet-strings/yard/templates/default/puppet_plan/html/source.erb @@ -0,0 +1,12 @@ +
    + + + + + +
    +
    <%= "\n\n\n" %><%= h format_lines(object) %>
    +
    +
    # File '<%= h object.file %>'<% if object.line %>, line <%= object.line %><% end %><%= "\n\n" %><%= html_syntax_highlight object.source %>
    +
    +
    diff --git a/lib/puppet-strings/yard/templates/default/puppet_plan/html/summary.erb b/lib/puppet-strings/yard/templates/default/puppet_plan/html/summary.erb new file mode 100644 index 0000000..75e9867 --- /dev/null +++ b/lib/puppet-strings/yard/templates/default/puppet_plan/html/summary.erb @@ -0,0 +1,4 @@ +<% if object.docstring.has_tag?(:summary) %> +

    Summary

    + <%= object.docstring.tag(:summary).text %> +<% end %> diff --git a/lib/puppet-strings/yard/templates/default/tags/setup.rb b/lib/puppet-strings/yard/templates/default/tags/setup.rb index 99a3777..4e3f281 100644 --- a/lib/puppet-strings/yard/templates/default/tags/setup.rb +++ b/lib/puppet-strings/yard/templates/default/tags/setup.rb @@ -6,7 +6,8 @@ def param object.type == :puppet_class || object.type == :puppet_defined_type || object.type == :puppet_function || - object.type == :puppet_task + object.type == :puppet_task || + object.type == :puppet_plan end # Renders the overload section. diff --git a/spec/fixtures/unit/json/output.json b/spec/fixtures/unit/json/output.json index 73815d8..e874489 100644 --- a/spec/fixtures/unit/json/output.json +++ b/spec/fixtures/unit/json/output.json @@ -645,5 +645,8 @@ "supports_noop": false, "input_method": "stdin" } + ], + "puppet_plans": [ + ] } diff --git a/spec/fixtures/unit/json/output_with_plan.json b/spec/fixtures/unit/json/output_with_plan.json new file mode 100644 index 0000000..dbff7f1 --- /dev/null +++ b/spec/fixtures/unit/json/output_with_plan.json @@ -0,0 +1,689 @@ +{ + "puppet_classes": [ + { + "name": "klass", + "file": "(stdin)", + "line": 5, + "inherits": "foo::bar", + "docstring": { + "text": "A simple class.", + "tags": [ + { + "tag_name": "param", + "text": "First param.", + "types": [ + "Integer" + ], + "name": "param1" + }, + { + "tag_name": "param", + "text": "Second param.", + "types": [ + "Any" + ], + "name": "param2" + }, + { + "tag_name": "param", + "text": "Third param.", + "types": [ + "String" + ], + "name": "param3" + } + ] + }, + "defaults": { + "param3": "hi" + }, + "source": "class klass(Integer $param1, $param2, String $param3 = hi) inherits foo::bar {\n}" + } + ], + "defined_types": [ + { + "name": "dt", + "file": "(stdin)", + "line": 12, + "docstring": { + "text": "A simple defined type.", + "tags": [ + { + "tag_name": "param", + "text": "First param.", + "types": [ + "Integer" + ], + "name": "param1" + }, + { + "tag_name": "param", + "text": "Second param.", + "types": [ + "Any" + ], + "name": "param2" + }, + { + "tag_name": "param", + "text": "Third param.", + "types": [ + "String" + ], + "name": "param3" + } + ] + }, + "defaults": { + "param3": "hi" + }, + "source": "define dt(Integer $param1, $param2, String $param3 = hi) {\n}" + } + ], + "resource_types": [ + { + "name": "apt_key", + "file": "(stdin)", + "line": 92, + "docstring": { + "text": "This type provides Puppet with the capabilities to manage GPG keys needed\nby apt to perform package validation. Apt has it's own GPG keyring that can\nbe manipulated through the `apt-key` command.\n**Autorequires**:\nIf Puppet is given the location of a key file which looks like an absolute\npath this type will autorequire that file.", + "tags": [ + { + "tag_name": "summary", + "text": "Example resource type using the new API." + }, + { + "tag_name": "raise", + "text": "SomeError" + }, + { + "tag_name": "example", + "text": "apt_key { '6F6B15509CF8E59E6E469F327F438280EF8D349F':\n source => 'http://apt.puppetlabs.com/pubkey.gpg'\n}", + "name": "here's an example" + } + ] + }, + "properties": [ + { + "name": "ensure", + "description": "Whether this apt key should be present or absent on the target system.", + "data_type": "Enum[present, absent]" + }, + { + "name": "created", + "description": "Date the key was created, in ISO format.", + "data_type": "String" + } + ], + "parameters": [ + { + "name": "id", + "description": "The ID of the key you want to manage.", + "data_type": "Variant[Pattern[/A(0x)?[0-9a-fA-F]{8}Z/], Pattern[/A(0x)?[0-9a-fA-F]{16}Z/], Pattern[/A(0x)?[0-9a-fA-F]{40}Z/]]", + "isnamevar": true + } + ] + }, + { + "name": "database", + "file": "(stdin)", + "line": 54, + "docstring": { + "text": "An example database server resource type." + }, + "properties": [ + { + "name": "ensure", + "description": "What state the database should be in.", + "values": [ + "present", + "absent", + "up", + "down" + ], + "aliases": { + "up": "present", + "down": "absent" + }, + "default": "up" + }, + { + "name": "file", + "description": "The database file to use." + }, + { + "name": "log_level", + "description": "The log level to use.", + "values": [ + "debug", + "warn", + "error" + ], + "default": "warn" + } + ], + "parameters": [ + { + "name": "address", + "description": "The database server name.", + "isnamevar": true + }, + { + "name": "encryption_key", + "description": "The encryption key to use." + }, + { + "name": "encrypt", + "description": "Whether or not to encrypt the database.", + "values": [ + "true", + "false", + "yes", + "no" + ], + "default": "false" + } + ], + "features": [ + { + "name": "encryption", + "description": "The provider supports encryption." + } + ] + } + ], + "providers": [ + { + "name": "linux", + "type_name": "database", + "file": "(stdin)", + "line": 43, + "docstring": { + "text": "An example provider on Linux." + }, + "confines": { + "kernel": "Linux", + "osfamily": "RedHat" + }, + "features": [ + "implements_some_feature", + "some_other_feature" + ], + "defaults": [ + [ + [ + "kernel", + "Linux" + ] + ], + [ + [ + "osfamily", + "RedHat" + ], + [ + "operatingsystemmajrelease", + "7" + ] + ] + ], + "commands": { + "foo": "/usr/bin/foo" + } + } + ], + "puppet_functions": [ + { + "name": "func", + "file": "(stdin)", + "line": 6, + "type": "puppet", + "signatures": [ + { + "signature": "func(Integer $param1, Any $param2, String $param3 = hi)", + "docstring": { + "text": "A simple function.", + "tags": [ + { + "tag_name": "param", + "text": "First param.", + "types": [ + "Integer" + ], + "name": "param1" + }, + { + "tag_name": "param", + "text": "Second param.", + "types": [ + "Any" + ], + "name": "param2" + }, + { + "tag_name": "param", + "text": "Third param.", + "types": [ + "String" + ], + "name": "param3" + }, + { + "tag_name": "return", + "text": "Returns nothing.", + "types": [ + "Undef" + ] + } + ] + } + } + ], + "docstring": { + "text": "A simple function.", + "tags": [ + { + "tag_name": "param", + "text": "First param.", + "types": [ + "Integer" + ], + "name": "param1" + }, + { + "tag_name": "param", + "text": "Second param.", + "types": [ + "Any" + ], + "name": "param2" + }, + { + "tag_name": "param", + "text": "Third param.", + "types": [ + "String" + ], + "name": "param3" + }, + { + "tag_name": "return", + "text": "Returns nothing.", + "types": [ + "Undef" + ] + } + ] + }, + "defaults": { + "param3": "hi" + }, + "source": "function func(Integer $param1, $param2, String $param3 = hi) {\n}" + }, + { + "name": "func3x", + "file": "(stdin)", + "line": 1, + "type": "ruby3x", + "signatures": [ + { + "signature": "func3x(String $first, Any $second)", + "docstring": { + "text": "An example 3.x function.", + "tags": [ + { + "tag_name": "param", + "text": "The first parameter.", + "types": [ + "String" + ], + "name": "first" + }, + { + "tag_name": "param", + "text": "The second parameter.", + "types": [ + "Any" + ], + "name": "second" + }, + { + "tag_name": "return", + "text": "Returns nothing.", + "types": [ + "Undef" + ] + } + ] + } + } + ], + "docstring": { + "text": "An example 3.x function.", + "tags": [ + { + "tag_name": "param", + "text": "The first parameter.", + "types": [ + "String" + ], + "name": "first" + }, + { + "tag_name": "param", + "text": "The second parameter.", + "types": [ + "Any" + ], + "name": "second" + }, + { + "tag_name": "return", + "text": "Returns nothing.", + "types": [ + "Undef" + ] + } + ] + }, + "source": "Puppet::Parser::Functions.newfunction(:func3x, doc: <<-DOC\nAn example 3.x function.\n@param [String] first The first parameter.\n@param second The second parameter.\n@return [Undef] Returns nothing.\nDOC\n) do |*args|\nend" + }, + { + "name": "func4x", + "file": "(stdin)", + "line": 11, + "type": "ruby4x", + "signatures": [ + { + "signature": "func4x(Integer $param1, Any $param2, Optional[Array[String]] $param3)", + "docstring": { + "text": "The first overload.", + "tags": [ + { + "tag_name": "param", + "text": "The first parameter.", + "types": [ + "Integer" + ], + "name": "param1" + }, + { + "tag_name": "param", + "text": "The second parameter.", + "types": [ + "Any" + ], + "name": "param2" + }, + { + "tag_name": "param", + "text": "The third parameter.", + "types": [ + "Optional[Array[String]]" + ], + "name": "param3" + }, + { + "tag_name": "return", + "text": "Returns nothing.", + "types": [ + "Undef" + ] + } + ] + } + }, + { + "signature": "func4x(Boolean $param, Callable &$block)", + "docstring": { + "text": "", + "tags": [ + { + "tag_name": "param", + "text": "The first parameter.", + "types": [ + "Boolean" + ], + "name": "param" + }, + { + "tag_name": "param", + "text": "The block parameter.", + "types": [ + "Callable" + ], + "name": "&block" + }, + { + "tag_name": "return", + "text": "Returns a string.", + "types": [ + "String" + ] + } + ] + } + } + ], + "docstring": { + "text": "An example 4.x function.", + "tags": [ + { + "tag_name": "overload", + "signature": "func4x(Integer $param1, Any $param2, Optional[Array[String]] $param3)", + "docstring": { + "text": "The first overload.", + "tags": [ + { + "tag_name": "param", + "text": "The first parameter.", + "types": [ + "Integer" + ], + "name": "param1" + }, + { + "tag_name": "param", + "text": "The second parameter.", + "types": [ + "Any" + ], + "name": "param2" + }, + { + "tag_name": "param", + "text": "The third parameter.", + "types": [ + "Optional[Array[String]]" + ], + "name": "param3" + }, + { + "tag_name": "return", + "text": "Returns nothing.", + "types": [ + "Undef" + ] + } + ] + }, + "name": "func4x" + }, + { + "tag_name": "overload", + "signature": "func4x(Boolean $param, Callable &$block)", + "docstring": { + "text": "", + "tags": [ + { + "tag_name": "param", + "text": "The first parameter.", + "types": [ + "Boolean" + ], + "name": "param" + }, + { + "tag_name": "param", + "text": "The block parameter.", + "types": [ + "Callable" + ], + "name": "&block" + }, + { + "tag_name": "return", + "text": "Returns a string.", + "types": [ + "String" + ] + } + ] + }, + "name": "func4x" + } + ] + }, + "source": "Puppet::Functions.create_function(:func4x) do\n # The first overload.\n # @param param1 The first parameter.\n # @param param2 The second parameter.\n # @param param3 The third parameter.\n # @return Returns nothing.\n dispatch :foo do\n param 'Integer', :param1\n param 'Any', :param2\n optional_param 'Array[String]', :param3\n return_type 'Undef'\n end\n\n # @param param The first parameter.\n # @param block The block parameter.\n # @return Returns a string.\n dispatch :other do\n param 'Boolean', :param\n block_param\n return_type 'String'\n end\nend" + }, + { + "name": "func4x_1", + "file": "(stdin)", + "line": 35, + "type": "ruby4x", + "signatures": [ + { + "signature": "func4x_1(Integer $param1)", + "docstring": { + "text": "An example 4.x function with only one signature.", + "tags": [ + { + "tag_name": "param", + "text": "The first parameter.", + "types": [ + "Integer" + ], + "name": "param1" + }, + { + "tag_name": "return", + "text": "Returns nothing.", + "types": [ + "Undef" + ] + } + ] + } + } + ], + "docstring": { + "text": "An example 4.x function with only one signature.", + "tags": [ + { + "tag_name": "param", + "text": "The first parameter.", + "types": [ + "Integer" + ], + "name": "param1" + }, + { + "tag_name": "return", + "text": "Returns nothing.", + "types": [ + "Undef" + ] + } + ] + }, + "source": "Puppet::Functions.create_function(:func4x_1) do\n # @param param1 The first parameter.\n # @return [Undef] Returns nothing.\n dispatch :foobarbaz do\n param 'Integer', :param1\n end\nend" + } + ], + "puppet_tasks": [ + { + "name": "(stdin)", + "file": "(stdin)", + "line": 0, + "docstring": { + "text": "Allows you to backup your database to local file.", + "tags": [ + { + "name": "database", + "tag_name": "param", + "text": "Database to connect to", + "types": [ + "Optional[String[1]]" + ] + }, + { + "name": "user", + "tag_name": "param", + "text": "The user", + "types": [ + "Optional[String[1]]" + ] + }, + { + "name": "password", + "tag_name": "param", + "text": "The password", + "types": [ + "Optional[String[1]]" + ] + }, + { + "name": "sql", + "tag_name": "param", + "text": "Path to file you want backup to", + "types": [ + "String[1]" + ] + } + ] + }, + "source": "{\n \"description\": \"Allows you to backup your database to local file.\",\n \"input_method\": \"stdin\",\n \"parameters\": {\n \"database\": {\n \"description\": \"Database to connect to\",\n \"type\": \"Optional[String[1]]\"\n },\n \"user\": {\n \"description\": \"The user\",\n \"type\": \"Optional[String[1]]\"\n },\n \"password\": {\n \"description\": \"The password\",\n \"type\": \"Optional[String[1]]\"\n },\n \"sql\": {\n \"description\": \"Path to file you want backup to\",\n \"type\": \"String[1]\"\n }\n }\n}\n", + "supports_noop": false, + "input_method": "stdin" + } + ], + "puppet_plans": [ + { + "name": "plann", + "file": "(stdin)", + "line": 5, + "docstring": { + "text": "A simple plan.", + "tags": [ + { + "tag_name": "param", + "text": "First param.", + "types": [ + "String" + ], + "name": "param1" + }, + { + "tag_name": "param", + "text": "Second param.", + "types": [ + "Any" + ], + "name": "param2" + }, + { + "tag_name": "param", + "text": "Third param.", + "types": [ + "Integer" + ], + "name": "param3" + } + ] + }, + "defaults": { + "param3": "1" + }, + "source": "plan plann(String $param1, $param2, Integer $param3 = 1) {\n}" + } + ] +} diff --git a/spec/fixtures/unit/markdown/output_with_plan.md b/spec/fixtures/unit/markdown/output_with_plan.md new file mode 100644 index 0000000..4b08b94 --- /dev/null +++ b/spec/fixtures/unit/markdown/output_with_plan.md @@ -0,0 +1,451 @@ +# Reference + +## Classes +### Public Classes +* [`klass`](#klass): A simple class. +### Private Classes +* `noparams`: Overview for class noparams +## Defined types +* [`klass::dt`](#klassdt): A simple defined type. +## Resource types +* [`apt_key`](#apt_key): Example resource type using the new API. +* [`database`](#database): An example database server type. +## Functions +* [`func`](#func): A simple Puppet function. +* [`func3x`](#func3x): Documentation for an example 3.x function. +* [`func4x`](#func4x): An example 4.x function. +* [`func4x_1`](#func4x_1): An example 4.x function with only one signature. +## Tasks +* [`(stdin)`](#(stdin)): Allows you to backup your database to local file. +## Classes + +### klass + +An overview for a simple class. + +* **Since** 1.0.0 + +* **See also** +www.puppet.com + + +#### Examples +##### This is an example +```puppet +class { 'klass': + param1 => 1, + param3 => 'foo', +} +``` + +##### This is another example +```puppet +class { 'klass': + param1 => 1, + param3 => 'foo', +} +``` + + +#### Parameters + +The following parameters are available in the `klass` class. + +##### `param1` + +Data type: `Integer` + +First param. + +Default value: 1 + +##### `param2` + +Data type: `Any` + +Second param. + +Options: + +* **:opt1** `String`: something about opt1 +* **:opt2** `Hash`: a hash of stuff + +Default value: `undef` + +##### `param3` + +Data type: `String` + +Third param. + +Default value: 'hi' + + +## Defined types + +### klass::dt + +An overview for a simple defined type. + +* **Since** 1.1.0 + +* **See also** +www.puppet.com + + +#### Examples +##### Here's an example of this type: +```puppet +klass::dt { 'foo': + param1 => 33, + param4 => false, +} +``` + + +#### Parameters + +The following parameters are available in the `klass::dt` defined type. + +##### `param1` + +Data type: `Integer` + +First param. + +Default value: 44 + +##### `param2` + +Data type: `Any` + +Second param. + +Options: + +* **:opt1** `String`: something about opt1 +* **:opt2** `Hash`: a hash of stuff + +##### `param3` + +Data type: `String` + +Third param. + +Default value: 'hi' + +##### `param4` + +Data type: `Boolean` + +Fourth param. + +Default value: `true` + + +## Resource types + +### apt_key + +This type provides Puppet with the capabilities to manage GPG keys needed +by apt to perform package validation. Apt has it's own GPG keyring that can +be manipulated through the `apt-key` command. +**Autorequires**: +If Puppet is given the location of a key file which looks like an absolute +path this type will autorequire that file. + +#### Examples +##### here's an example +```puppet +apt_key { '6F6B15509CF8E59E6E469F327F438280EF8D349F': + source => 'http://apt.puppetlabs.com/pubkey.gpg' +} +``` + +#### Properties + +The following properties are available in the `apt_key` type. + +##### `ensure` + +Data type: `Enum[present, absent]` + +Whether this apt key should be present or absent on the target system. + +##### `created` + +Data type: `String` + +Date the key was created, in ISO format. + +#### Parameters + +The following parameters are available in the `apt_key` type. + +##### `id` + +namevar + +Data type: `Variant[Pattern[/A(0x)?[0-9a-fA-F]{8}Z/], Pattern[/A(0x)?[0-9a-fA-F]{16}Z/], Pattern[/A(0x)?[0-9a-fA-F]{40}Z/]]` +_*this data type contains a regex that may not be accurately reflected in generated documentation_ + +The ID of the key you want to manage. + + +### database + +An example database server type. + +#### Examples +##### here's an example +```puppet +database { 'foo': + address => 'qux.baz.bar', +} +``` + +#### Properties + +The following properties are available in the `database` type. + +##### `ensure` + +Valid values: present, absent, up, down + +Aliases: "up"=>"present", "down"=>"absent" + +What state the database should be in. + +Default value: up + +##### `file` + +The database file to use. + +##### `log_level` + +Valid values: debug, warn, error + +The log level to use. + +Default value: warn + +#### Parameters + +The following parameters are available in the `database` type. + +##### `address` + +namevar + +The database server name. + +##### `encryption_key` + +The encryption key to use. + +##### `encrypt` + +Valid values: `true`, `false`, yes, no + +Whether or not to encrypt the database. + +Default value: `false` + + +## Functions + +### func +Type: Puppet Language + +A simple Puppet function. + +#### `func(Integer $param1, Any $param2, String $param3 = hi)` + +A simple Puppet function. + +Returns: `Undef` Returns nothing. + +Raises: +* `SomeError` this is some error + +##### `param1` + +Data type: `Integer` + +First param. + +##### `param2` + +Data type: `Any` + +Second param. + +##### `param3` + +Data type: `String` + +Third param. + +Options: + +* **:param3opt** `Array`: Something about this option + +### func3x +Type: Ruby 3.x API + +Documentation for an example 3.x function. + +#### `func3x(String $param1, Integer $param2)` + +Documentation for an example 3.x function. + +Returns: `Undef` + +##### `param1` + +Data type: `String` + +The first parameter. + +##### `param2` + +Data type: `Integer` + +The second parameter. + +### func4x +Type: Ruby 4.x API + +An example 4.x function. + +#### `func4x(Integer $param1, Any $param2, Optional[Array[String]] $param3)` + +An overview for the first overload. + +Returns: `Undef` Returns nothing. + +##### `param1` + +Data type: `Integer` + +The first parameter. + +##### `param2` + +Data type: `Any` + +The second parameter. + +Options: + +* **:option** `String`: an option +* **:option2** `String`: another option + +##### `param3` + +Data type: `Optional[Array[String]]` + +The third parameter. + +#### `func4x(Boolean $param, Callable &$block)` + +An overview for the second overload. + +Returns: `String` Returns a string. + +##### `param` + +Data type: `Boolean` + +The first parameter. + +##### `&block` + +Data type: `Callable` + +The block parameter. + +### func4x_1 +Type: Ruby 4.x API + +An example 4.x function with only one signature. + +#### `func4x_1(Integer $param1)` + +An example 4.x function with only one signature. + +Returns: `Undef` Returns nothing. + +##### `param1` + +Data type: `Integer` + +The first parameter. + +## Tasks + +### (stdin) + +Allows you to backup your database to local file. + +**Supports noop?** false + +#### Parameters + +##### `database` + +Data type: `Optional[String[1]]` + +Database to connect to + +##### `user` + +Data type: `Optional[String[1]]` + +The user + +##### `password` + +Data type: `Optional[String[1]]` + +The password + +##### `sql` + +Data type: `String[1]` + +Path to file you want backup to + +## Plans + +### plann + +A simple plan. + + +#### Parameters + +The following parameters are available in the `plann` plan. + +##### `param1` + +Data type: `String` + +First param. + +##### `param2` + +Data type: `Any` + +Second param. + +##### `param3` + +Data type: `Integer` + +Third param. + +Default value: 1 + + diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 32b6351..5378af8 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -27,10 +27,13 @@ require 'puppet-strings/yard' PuppetStrings::Yard.setup! # Enable testing of Puppet functions if running against 4.1+ -TEST_PUPPET_FUNCTIONS = Gem::Dependency.new('', '>= 4.1.0').match?('', Puppet::PUPPETVERSION) +TEST_PUPPET_FUNCTIONS = Puppet::Util::Package.versioncmp(Puppet.version, "4.1.0") >= 0 # Enable testing of Puppet language functions declared with return type if running against 4.8+ -TEST_FUNCTION_RETURN_TYPE = Gem::Dependency.new('', '>= 4.8.0').match?('', Puppet::PUPPETVERSION) +TEST_FUNCTION_RETURN_TYPE = Puppet::Util::Package.versioncmp(Puppet.version, "4.8.0") >= 0 + +# Enable testing of Plans if Puppet version is greater than 5.0.0 +TEST_PUPPET_PLANS = Puppet::Util::Package.versioncmp(Puppet.version, "5.0.0") >= 0 RSpec.configure do |config| config.mock_with :mocha diff --git a/spec/unit/puppet-strings/json_spec.rb b/spec/unit/puppet-strings/json_spec.rb index a6d9a7e..d9fe243 100644 --- a/spec/unit/puppet-strings/json_spec.rb +++ b/spec/unit/puppet-strings/json_spec.rb @@ -19,6 +19,15 @@ class klass(Integer $param1, $param2, String $param3 = hi) inherits foo::bar { # @param param3 Third param. define dt(Integer $param1, $param2, String $param3 = hi) { } +SOURCE + + YARD::Parser::SourceParser.parse_string(<<-SOURCE, :puppet) if TEST_PUPPET_PLANS +# A simple plan. +# @param param1 First param. +# @param param2 Second param. +# @param param3 Third param. +plan plann(String $param1, $param2, Integer $param3 = 1) { +} SOURCE # Only include Puppet functions for 4.1+ @@ -191,7 +200,13 @@ path this type will autorequire that file. SOURCE end - let(:filename) { TEST_PUPPET_FUNCTIONS ? 'output.json' : 'output_without_puppet_function.json' } + let(:filename) do + if TEST_PUPPET_PLANS + 'output_with_plan.json' + else + TEST_PUPPET_FUNCTIONS ? 'output.json' : 'output_without_puppet_function.json' + end + end let(:baseline_path) { File.join(File.dirname(__FILE__), "../../fixtures/unit/json/#{filename}") } let(:baseline) { File.read(baseline_path) } diff --git a/spec/unit/puppet-strings/markdown_spec.rb b/spec/unit/puppet-strings/markdown_spec.rb index a8bda64..c03b202 100644 --- a/spec/unit/puppet-strings/markdown_spec.rb +++ b/spec/unit/puppet-strings/markdown_spec.rb @@ -64,28 +64,12 @@ define klass::dt ( ) { } SOURCE - YARD::Parser::SourceParser.parse_string(<<-SOURCE, :json) -{ - "description": "Allows you to backup your database to local file.", - "input_method": "stdin", - "parameters": { - "database": { - "description": "Database to connect to", - "type": "Optional[String[1]]" - }, - "user": { - "description": "The user", - "type": "Optional[String[1]]" - }, - "password": { - "description": "The password", - "type": "Optional[String[1]]" - }, - "sql": { - "description": "Path to file you want backup to", - "type": "String[1]" - } - } + YARD::Parser::SourceParser.parse_string(<<-SOURCE, :puppet) if TEST_PUPPET_PLANS +# A simple plan. +# @param param1 First param. +# @param param2 Second param. +# @param param3 Third param. +plan plann(String $param1, $param2, Integer $param3 = 1) { } SOURCE @@ -276,7 +260,13 @@ path this type will autorequire that file. SOURCE end - let(:filename) { 'output.md' } + let(:filename) do + if TEST_PUPPET_PLANS + 'output_with_plan.md' + else + 'output.md' + end + end let(:baseline_path) { File.join(File.dirname(__FILE__), "../../fixtures/unit/markdown/#{filename}") } let(:baseline) { File.read(baseline_path) }