技术控

    今日:136| 主题:49552
收藏本版 (1)
最新软件应用技术尽在掌握

[其他] Using Puppet Strings to Generate Great Documentation for Puppet Modules

[复制链接]
花落满茵席 发表于 2016-11-28 16:35:25
66 1

立即注册CoLaBug.com会员,免费获得投稿人的专业资料,享用更多功能,玩转个人品牌!

您需要 登录 才可以下载或查看,没有帐号?立即注册

x
Great documentation is vitally important to the quality and usability of any software, and Puppet modules are certainly no exception. While this may sound like a no-brainer, the real challenge lies in maintaining docs that don’t lag behind the latest release of a project.
   We created Puppet Strings to help module authors deal with this challenge by rendering user-friendly documentation from Puppet source code. We’ve just released a major revision of Puppet Strings with new features and fixes for many issues reported by early users.
   Even if you don’t consider yourself a Puppet module developer, read on. Higher-quality documentation through Puppet Strings is valuable to everyone in the worldwide Puppet community. An easy way to contribute back to the modules you use everyday is to add Strings content to them. (Speaking of contributing, #puppethack, the online Puppet community hack day , is happening on December 13, and that would be a great place to start.)
  Strings is a YARD-based documentation tool for Puppet code and extensions that are written in Puppet and Ruby. Given some simple in-code comments containing YARD tags, Strings generates consistent HTML or JSON documentation for:
  
       
  • All of your classes   
  • Puppet 3.x and 4.x API functions   
  • Puppet language functions   
  • Resource types   
  • Providers   
  • Ruby classes and Ruby methods  
  This post will walk you through the basics of using Strings to document all the pieces of a Puppet module.
  Setup: Installing Strings

   In this example, we’ll install the Strings Rubygem with bundler. (Note that the gem can also be installed system-wide using the puppet_gem or gem providers.)
   To use Puppet Strings in your module, simply add the following to your module’s Gemfile, and then run bundle install :
  [code]source ENV['GEM_SOURCE'] || "https://rubygems.org"
gem "puppet", ENV['PUPPET_GEM_VERSION'] || '~> 4.7.0'
gem 'puppet-strings'
gem 'rake'[/code]  Strings is compatible with Puppet 3.8 and above, and in this example we’ll be using the latest release, Puppet 4.8. Notes about differences with Puppet 3.8 will be specifically called out throughout this post.
  Documenting Puppet Classes and Defined Types, and Running Strings

  It is straightforward to document classes and user-defined types using Puppet Strings.
   As is the case with anything that can be documented with YARD, we’ll be working with a series of comments that make up the YARD docstring . This can include free-form text that is treated as a high-level overview for the class, as well as any number of YARD tags that hold semantic metadata for various aspects of the code. These tags allow us to add this data to the code without worrying about presentation.
  [code]# An example class.
#
# This is an example of how to document a Puppet class:
#
# @example Declaring the class
#   include example_class
#
# @param first The first parameter for this class.
# @param second The second parameter for this class.
class example_class(
  String $first  = $example_class::params::first_arg,
  Integer $second = $example_class::params::second_arg,
) inherits example_class::params {
  # ...
}[/code]  The first few lines of this block of comments, which are not prefixed with any tags, constitute the description of the class.
   Next, we have our first YARD tag. The @example tag can be used to add usage examples to any Puppet or Ruby code.
  [code]# @example Declaring the class
#    include example_class[/code]  The string following the tag is an optional title, which is displayed prominently with the example in the final output.
   Finally, we have @param tags for each of the parameters of the class.
  [code]# @param first The first parameter for this class.
# @param second The second parameter for this class.[/code]   The first word after the tag is the name of the parameter, and the following string describes its purpose. Since Puppet 4.x is a typed language, Strings automatically uses the parameter type information from the code to document the parameter types. If no type is specified in code, the parameter defaults to the type Any .
   Since Puppet 3.x does not support typed parameters, the @param tags should include the expected type of the parameter, like so:
  [code]# @param [String] first The first parameter for this class.
# @param [Integer] second The second parameter for this class.[/code]  Defined types are documented in exactly the same way as classes:
  [code]# An example defined type.
#
# This is an example of how to document a defined type.
# @param ports The array of port numbers to use.
define example_type(
   Array[Integer] $ports = []
) {
  # ...
}[/code]   Now that we’ve got some documented code, we can run Strings to generate the documentation in either HTML or JSON. I’ve separated this code into two files in my module: class.pp and defined_type.pp :
  [code][email protected] > tree
  .
  |----- manifests
        |----- class.pp
         ----- defined_type.pp[/code]  To generate HTML documentation, we’ll invoke the following command from the top level of the module:
  [code]bundle exec puppet strings generate ./manifests/*.pp[/code]   This results in the creation of a docs directory and an index.html file, which we can view in a browser. Using the sidebar on the opened page to view the generated documentation for the class, we see:
   
Using Puppet Strings to Generate Great Documentation for Puppet Modules-1 (certainly,challenge,developer,happening,important)

  Strings automatically groups documented code by category, allowing each category to be browsed separately. Here we see that we have Puppet classes and defined types available to view.
  Alternatively, you can generate the same documentation as JSON. This can be useful for handling or displaying the data with your own custom applications. To generate JSON, run the following command:
  [code]bundle exec puppet strings generate ./manifests/*.pp --emit-json output.json[/code]   This results in a file, output.json , populated with all of the parsed data organized similarly to the HTML navigation categories above:
  [code]{
    “Puppet_classes”: [
        “name”: “example_class”,
        “file”: “manifests/class.pp”,
        “line”: 10,
        “inherits”: “example_class::params”,
        “docstring”: {
            “text”: “An example class.\n\nThis is an example of how to document a Puppet class.”
            “tags”: [
         {
             “tag_name”: “example”,
             “text”: “include example_class”,
             “name”: “Declaring the class”,
                 },
        ...[/code]   See the Strings JSON schema for more information.
  Documenting Puppet Functions

  The syntax for documenting Puppet functions is very similar to our above examples of documenting Puppet classes, with a few key differences. We’ll start with a function written in the Puppet language:
  [code]# An example class.
#
# This is an example of how to document a Puppet class:
#
# @example Declaring the class
#   include example_class
#
# @param first The first parameter for this class.
# @param second The second parameter for this class.
class example_class(
  String $first  = $example_class::params::first_arg,
  Integer $second = $example_class::params::second_arg,
) inherits example_class::params {
  # ...
}0[/code]  To document such a function, provide a docstring before the function definition, like in the above example. Strings automatically uses the parameter type information from the function’s parameter list to document the parameter type.
   In addition, notice the @return tag, which should always be included to document what a function returns.
   Documentation can be added to functions using the Puppet 4.x API by adding a docstring before the create_function call and any dispatch calls (see the end of this post to learn more about the Puppet 4.x API).
  [code]# An example class.
#
# This is an example of how to document a Puppet class:
#
# @example Declaring the class
#   include example_class
#
# @param first The first parameter for this class.
# @param second The second parameter for this class.
class example_class(
  String $first  = $example_class::params::first_arg,
  Integer $second = $example_class::params::second_arg,
) inherits example_class::params {
  # ...
}1[/code]   The first comment before the call to create_function , “ Subtracts two things ,” acts as the top-level docstring for the entire function. This provides a general description for the function as a whole.
  Next, we have the two dispatches, which are signature overloads. These can be documented separately by adding a docstring with tags above each. Strings displays each as a separate signature, both in the HTML and JSON output.
   Note that Strings automatically uses the parameter and return type information from the dispatch block to document the parameter types. You should document your parameter types only when the Puppet 4.x function contains no dispatch calls.
   Each overload can include text to describe its purpose, as shown in the example above with subtracts two integers and subtracts two arrays .
  3.x functions are documented differently:
  [code]# An example class.
#
# This is an example of how to document a Puppet class:
#
# @example Declaring the class
#   include example_class
#
# @param first The first parameter for this class.
# @param second The second parameter for this class.
class example_class(
  String $first  = $example_class::params::first_arg,
  Integer $second = $example_class::params::second_arg,
) inherits example_class::params {
  # ...
}2[/code]   The YARD docstring must be written inside of a heredoc within the :doc parameter of the Puppet::Parser::Functions::newfunction call. While clunkier in this respect, the documentation markup syntax is otherwise the same. Because 3.x functions do not have dispatches or allow multiple overloads, there will be only one set of parameters and one return type.
   Assuming we’ve placed these functions in lib/puppet/functions/4x_function.rb and lib/puppet/parser/functions/3x_function.rb respectively, we can generate documentation for them by running the following command:
  [code]# An example class.
#
# This is an example of how to document a Puppet class:
#
# @example Declaring the class
#   include example_class
#
# @param first The first parameter for this class.
# @param second The second parameter for this class.
class example_class(
  String $first  = $example_class::params::first_arg,
  Integer $second = $example_class::params::second_arg,
) inherits example_class::params {
  # ...
}3[/code]   This will run Strings against all files ending with the .rb extension anywhere under ./lib/puppet on the filesystem.
  Documenting Resource Types and Providers

  The last two Puppet constructs we’ll document are types and providers. These are fairly easy to document, as Strings automatically detects most of the important bits. We’ll start with a simple resource type:
  [code]# An example class.
#
# This is an example of how to document a Puppet class:
#
# @example Declaring the class
#   include example_class
#
# @param first The first parameter for this class.
# @param second The second parameter for this class.
class example_class(
  String $first  = $example_class::params::first_arg,
  Integer $second = $example_class::params::second_arg,
) inherits example_class::params {
  # ...
}4[/code]   Perhaps the most interesting bits here are the first comments before the call to newtype :
  [code]# An example class.
#
# This is an example of how to document a Puppet class:
#
# @example Declaring the class
#   include example_class
#
# @param first The first parameter for this class.
# @param second The second parameter for this class.
class example_class(
  String $first  = $example_class::params::first_arg,
  Integer $second = $example_class::params::second_arg,
) inherits example_class::params {
  # ...
}5[/code]   If your resource type includes parameters or properties which are dynamically created at runtime, you must document them with the @!puppet.type.param and @!puppet.type.property directives (see the end of this post to learn more ). This is necessary because Strings does not evaluate Ruby code, so it cannot detect dynamic attributes.
   Apart from dynamic attributes, the only other necessary code for complete documentation are descriptions for each parameter, property, and the resource type itself. These must be passed to the desc method. Each description can include other tags as well, including examples.
   Every other method call present in the type is automatically included and documented by Strings, and each parameter or property is updated accordingly in the final documentation. This includes calls to defaultto , newvalue , aliasvalue and so on.
  Providers are processed in a similar way:
  [code]# An example class.
#
# This is an example of how to document a Puppet class:
#
# @example Declaring the class
#   include example_class
#
# @param first The first parameter for this class.
# @param second The second parameter for this class.
class example_class(
  String $first  = $example_class::params::first_arg,
  Integer $second = $example_class::params::second_arg,
) inherits example_class::params {
  # ...
}6[/code]   All provider method calls, including confine , defaultfor , and commands , are automatically parsed and documented by Strings. The desc method is used to generate the docstring, and can include tags such as @example if written as a heredoc.
  Generating Documentation for an Entire Module

   We now have a module full of manifests, functions, types, and providers. By running the following command, we can instruct Strings to generate documentation for every file ending with the extension .pp or .rb :
  [code]# An example class.
#
# This is an example of how to document a Puppet class:
#
# @example Declaring the class
#   include example_class
#
# @param first The first parameter for this class.
# @param second The second parameter for this class.
class example_class(
  String $first  = $example_class::params::first_arg,
  Integer $second = $example_class::params::second_arg,
) inherits example_class::params {
  # ...
}7[/code]   This results in a browsable \_index.html file in the docs directory which can be navigated to view each of the files that we’ve just documented. Hurray!
   Of course, the --emit-json or --emit-json-stdout options could also be used to produce JSON rather than HTML. In either case, with these simple steps and minimal code changes, we’ve fully documented our module!
  Since the documentation is embedded with the code itself, it’s much easier to remember to update it in step with the code as the code changes. No more out-of-date documentation! In addition, by using Strings, we’ve also gained a free way to generate aesthetically pleasing HTML documentation. Strings can even run a web server to serve your Puppet docs for you!
   For more in-depth information about Puppet Strings, check out the readme . The YARD getting started guide and tag overview guides are also recommended reading for advanced users. In addition, we’re working on a few more blog posts and a comprehensive style guide for the project, so stay tuned!
  William Hopper is a software engineer at Puppet.
友荐云推荐




上一篇:Xamarin.Forms: Java.Lang.IllegalStateException
下一篇:可替代商用产品的四款最佳开源管理工具
酷辣虫提示酷辣虫禁止发表任何与中华人民共和国法律有抵触的内容!所有内容由用户发布,并不代表酷辣虫的观点,酷辣虫无法对用户发布内容真实性提供任何的保证,请自行验证并承担风险与后果。如您有版权、违规等问题,请通过"联系我们"或"违规举报"告知我们处理。

杜浩 发表于 2016-11-29 17:56:21
路过的帮顶
回复 支持 反对

使用道具 举报

*滑动验证:
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

我要投稿

推荐阅读

扫码访问 @iTTTTT瑞翔 的微博
回页顶回复上一篇下一篇回列表手机版
手机版/CoLaBug.com ( 粤ICP备05003221号 | 文网文[2010]257号 )|网站地图 酷辣虫

© 2001-2016 Comsenz Inc. Design: Dean. DiscuzFans.

返回顶部 返回列表