yard-chefdoc 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/Gemfile +15 -0
- data/LICENSE +20 -0
- data/README.md +103 -0
- data/Rakefile +30 -0
- data/lib/yard/cli/stats.rb +142 -0
- data/lib/yard-chefdoc/code_objects/attribute.rb +43 -0
- data/lib/yard-chefdoc/code_objects/chef.rb +116 -0
- data/lib/yard-chefdoc/code_objects/cookbook.rb +55 -0
- data/lib/yard-chefdoc/code_objects/recipe.rb +29 -0
- data/lib/yard-chefdoc/code_objects/resource.rb +70 -0
- data/lib/yard-chefdoc/handlers/attribute.rb +32 -0
- data/lib/yard-chefdoc/handlers/base.rb +36 -0
- data/lib/yard-chefdoc/handlers/cookbook.rb +40 -0
- data/lib/yard-chefdoc/handlers/recipe.rb +15 -0
- data/lib/yard-chefdoc/handlers/resource_action.rb +31 -0
- data/lib/yard-chefdoc/handlers/resource_default_action.rb +16 -0
- data/lib/yard-chefdoc/handlers/resource_property.rb +54 -0
- data/lib/yard-chefdoc/handlers/resource_resource_name.rb +16 -0
- data/lib/yard-chefdoc/template_helpers/chef.rb +24 -0
- data/lib/yard-chefdoc/version.rb +9 -0
- data/lib/yard-chefdoc.rb +50 -0
- data/spec/attributes_spec.rb +19 -0
- data/spec/home_spec.rb +42 -0
- data/spec/recipes_spec.rb +15 -0
- data/spec/resources_spec.rb +11 -0
- data/spec/spec_helper.rb +32 -0
- data/templates/default/attribute/html/attribute.erb +30 -0
- data/templates/default/attribute/html/setup.rb +5 -0
- data/templates/default/cookbook/html/attributes.erb +14 -0
- data/templates/default/cookbook/html/cookbook_title.erb +2 -0
- data/templates/default/cookbook/html/docstring.erb +1 -0
- data/templates/default/cookbook/html/element_details.erb +3 -0
- data/templates/default/cookbook/html/generated_docs.erb +2 -0
- data/templates/default/cookbook/html/libraries.erb +13 -0
- data/templates/default/cookbook/html/metadata.erb +86 -0
- data/templates/default/cookbook/html/recipes.erb +14 -0
- data/templates/default/cookbook/html/resources.erb +14 -0
- data/templates/default/cookbook/html/setup.rb +9 -0
- data/templates/default/fulldoc/html/css/chefdoc.css +52 -0
- data/templates/default/fulldoc/html/full_list_attributes.erb +14 -0
- data/templates/default/fulldoc/html/full_list_libraries.erb +6 -0
- data/templates/default/fulldoc/html/full_list_recipes.erb +13 -0
- data/templates/default/fulldoc/html/full_list_resources.erb +13 -0
- data/templates/default/fulldoc/html/setup.rb +117 -0
- data/templates/default/layout/html/layout.erb +24 -0
- data/templates/default/layout/html/setup.rb +81 -0
- data/templates/default/layout/html/title.erb +1 -0
- data/templates/default/recipe/html/recipe.erb +8 -0
- data/templates/default/recipe/html/setup.rb +8 -0
- data/templates/default/recipe/html/source.erb +10 -0
- data/templates/default/resource/html/actions.erb +19 -0
- data/templates/default/resource/html/properties.erb +18 -0
- data/templates/default/resource/html/resource.erb +3 -0
- data/templates/default/resource/html/setup.rb +15 -0
- metadata +111 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 7c1b1b7c7d48d1fdfe371a9bc0e3208157ea869e
|
4
|
+
data.tar.gz: 48ae1a4b57dd8655ac6924dfab4583bb2bf413b6
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: c9ae7cb39a84734379f979d5adda5a25567b319b5de254f986aba5b4b5e1eae6366c455a69129634dcff5e615c71b42176da96c8ec023f82039cc49b4e666126
|
7
|
+
data.tar.gz: f445225e242f27dbe83dd4d5b0ab9a106190d2a5938e3314fdef0fb6541935ef215bde5104a88d6d761eb058adda8ccb5422427b7197913c35eeedaa3d8a5132
|
data/Gemfile
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2012 RightScale, Inc.
|
2
|
+
Copyright (c) 2017 Jörg Herzinger
|
3
|
+
|
4
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
5
|
+
of this software and associated documentation files (the "Software"), to deal
|
6
|
+
in the Software without restriction, including without limitation the rights
|
7
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
8
|
+
copies of the Software, and to permit persons to whom the Software is
|
9
|
+
furnished to do so, subject to the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be included in all
|
12
|
+
copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
15
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
16
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
17
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
18
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
19
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
20
|
+
SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,103 @@
|
|
1
|
+
# YARD-Chef
|
2
|
+
|
3
|
+
Disclaimer: This YARD plugin is still in the early development stages. Please use with care and expect things to break.
|
4
|
+
|
5
|
+
## Description
|
6
|
+
|
7
|
+
yard-chefdoc is a [YARD](http://yardoc.org/) plugin for that adds support for documenting [Chef](http://www.chef.io/) cookbooks.
|
8
|
+
|
9
|
+
## Installation
|
10
|
+
|
11
|
+
This project is still in early development, so it has not yet been released on rubygems.org.
|
12
|
+
|
13
|
+
## How to document your Cookbooks
|
14
|
+
|
15
|
+
The cookbook to be documented has to be vendored, which can be done using Berkshelfs `vendor` command or by downloading the released cookbook from a Chef Supermarket or Chef Server.
|
16
|
+
|
17
|
+
For yard-chefdoc the most important part about the vendor process is that your metadata.rb gets evaluated to a static metadata.json.
|
18
|
+
|
19
|
+
### Cookbook README
|
20
|
+
|
21
|
+
The cookbook README.md in markdown format will be the landing page. Additionally a list of all all other objects with their short description will be added.
|
22
|
+
|
23
|
+
### Cookbook Metadata
|
24
|
+
|
25
|
+
Metadata information will be included in the documentation automatically. This requires a `metadata.json` to be present, not a `metadata.rb`. Check "cookbook vendoring" for more info.
|
26
|
+
|
27
|
+
### Libraries and standard YARD functionality
|
28
|
+
|
29
|
+
Your libraries will be documented out of the box by YARD. See the [YARD Documentation](http://yardoc.org/) on how to document them.
|
30
|
+
|
31
|
+
### File headers and descriptions
|
32
|
+
|
33
|
+
With Chefs special cookbook directory structure is makes sense to add descriptions for certain files rather than for Classes, Modules etc. like Ruby. For recipe and attribute files yard-chefdoc will try to find a header which is defined by a comment block starting at the first line and ending at the first blank line.
|
34
|
+
|
35
|
+
Within this header a description can be given. This is defined to start by a comment line containing the single word `Description` and ending at the end of the comment block/header. A working example is:
|
36
|
+
|
37
|
+
```
|
38
|
+
#
|
39
|
+
# Cookbook Name:: my-cookbook
|
40
|
+
# Attribute:: default
|
41
|
+
#
|
42
|
+
# Copyright (c) 2016 The Authors, All Rights Reserved.
|
43
|
+
#
|
44
|
+
# Description
|
45
|
+
# Here are some default attributes
|
46
|
+
|
47
|
+
default['my-cookbook']['brokkoli'] = %(delicious healthy)
|
48
|
+
```
|
49
|
+
|
50
|
+
In this example the description for the file `attributes/default.rb` would be `Here are some default attributes`. This description can of course also span multiple lines. Mind the blank line after the header, without this the header would serve as a description for the attribute `['my-cookbook']['brokkoli']`.
|
51
|
+
|
52
|
+
### Attributes
|
53
|
+
|
54
|
+
Attributes are automatically parsed and added to the documentation. Each attribute can have its own description which is simply the comment block above the attribute. Example:
|
55
|
+
|
56
|
+
```
|
57
|
+
# Set this attribute to define which plugins should be installed
|
58
|
+
default['my-application']['plugins'] = %w(github slack ldap)
|
59
|
+
```
|
60
|
+
|
61
|
+
### Resources
|
62
|
+
|
63
|
+
Modern Chef custom resources are automatically documented. Comments on properties and actions are added accordingly.
|
64
|
+
|
65
|
+
## Generating Cookbook Docs
|
66
|
+
|
67
|
+
To generate documentation you can either use the command line or create a rake task.
|
68
|
+
|
69
|
+
Command line:
|
70
|
+
```
|
71
|
+
cd /path/to/cookbook
|
72
|
+
yardoc --plugin chefdoc "**/*.{rb,json}"
|
73
|
+
```
|
74
|
+
|
75
|
+
Rake task:
|
76
|
+
```
|
77
|
+
require 'yard'
|
78
|
+
|
79
|
+
YARD::Config.load_plugin 'chefdoc'
|
80
|
+
YARD::Rake::YardocTask.new do |t|
|
81
|
+
t.files = ['<path_to_cookbooks_repo>/**/*.{rb,json}']
|
82
|
+
# t.options = ['--debug']
|
83
|
+
end
|
84
|
+
```
|
85
|
+
|
86
|
+
Then just run `rake yard`.
|
87
|
+
|
88
|
+
## Viewing Cookbook Docs
|
89
|
+
|
90
|
+
YARD output will be present in a directory named `doc` which will be located in the same folder from where the command was run. The will also be a cache directory with all the information necessary to render the documentation pages in a directory name `.yardoc`.
|
91
|
+
|
92
|
+
It is recommended to view these pages from a running YARD server. To start a local YARD server you should be in the same directory that contains your generated `.yardoc` directory. Once there run:
|
93
|
+
|
94
|
+
`yard server --plugin chefdoc --cache`
|
95
|
+
|
96
|
+
For more information about YARD server see [YARD documentation](http://rubydoc.info/docs/yard/file/docs/GettingStarted.md#yard_Executable)
|
97
|
+
|
98
|
+
# License and Thanks
|
99
|
+
|
100
|
+
This project was originally a fork of yard-chef by RightScale, Inc. Special thanks goes to them for providing the base for this.
|
101
|
+
|
102
|
+
Copyright (c) 2017 Jörg Herzinger. This code is distributed under the MIT license, see LICENSE for details.<br>
|
103
|
+
Copyright (c) 2012 RightScale, Inc.
|
data/Rakefile
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
require 'bundler/setup'
|
2
|
+
require 'rubygems/tasks'
|
3
|
+
require 'rspec/core/rake_task'
|
4
|
+
require 'rubocop/rake_task'
|
5
|
+
|
6
|
+
RuboCop::RakeTask.new
|
7
|
+
|
8
|
+
desc 'Create test docs'
|
9
|
+
task :doc_fixtures do
|
10
|
+
FileList.new('test/fixtures/*').each do |cb|
|
11
|
+
FileUtils.cd(cb) do
|
12
|
+
sh 'rm -rf .yardoc doc'
|
13
|
+
sh 'bundle exec yardoc --safe --plugin chefdoc --debug "**/*.{rb,json}"'
|
14
|
+
sh 'bundle exec yard server --plugin chefdoc --debug'
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
Gem::Tasks.new
|
20
|
+
|
21
|
+
RSpec::Core::RakeTask.new(:spec, %i[tag trigger] => ['gen_yardoc'])
|
22
|
+
|
23
|
+
desc 'Generate yard documentation of all test cookbook'
|
24
|
+
task :gen_yardoc do
|
25
|
+
FileList.new('test/fixtures/*').each do |cb|
|
26
|
+
FileUtils.cd(cb) do
|
27
|
+
sh 'bundle exec yardoc --debug --plugin chefdoc "**/*.{rb,json}"'
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,142 @@
|
|
1
|
+
require 'json'
|
2
|
+
|
3
|
+
module YARD
|
4
|
+
module CLI
|
5
|
+
class Stats < Yardoc
|
6
|
+
STATS_ORDER = %i[files modules classes constants attributes methods
|
7
|
+
chef_attribute_files chef_attributes chef_recipes chef_resources
|
8
|
+
chef_resource_properties chef_resource_actions]
|
9
|
+
|
10
|
+
def stats_for_chef_recipes
|
11
|
+
objs = all_objects.select { |m| m.type == :recipe }
|
12
|
+
undoc = objs.select { |m| !m.docstring.nil? && m.docstring.blank? }
|
13
|
+
@undoc_list |= undoc if @undoc_list
|
14
|
+
output 'Chef Recipes', objs.size, undoc.size
|
15
|
+
end
|
16
|
+
|
17
|
+
def stats_for_chef_attribute_files
|
18
|
+
objs = all_objects.select { |m| m.type == :attribute }
|
19
|
+
undoc = objs.select { |m| !m.docstring.nil? && m.docstring.empty? }
|
20
|
+
@undoc_list |= undoc if @undoc_list
|
21
|
+
output 'Chef Attribute files', objs.size, undoc.size
|
22
|
+
end
|
23
|
+
|
24
|
+
def stats_for_chef_attributes
|
25
|
+
objs = all_objects.select { |m| m.type == :attribute }
|
26
|
+
objs.map!(&:attributes).flatten!
|
27
|
+
undoc = objs.select { |m| !m.docstring.nil? && m.docstring.empty? }
|
28
|
+
@undoc_list |= undoc if @undoc_list
|
29
|
+
output 'Chef Attributes', objs.size, undoc.size
|
30
|
+
end
|
31
|
+
|
32
|
+
def stats_for_chef_resources
|
33
|
+
objs = all_objects.select { |m| m.type == :resource }
|
34
|
+
undoc = objs.select { |m| !m.docstring.nil? && m.docstring.blank? }
|
35
|
+
@undoc_list |= undoc if @undoc_list
|
36
|
+
output 'Chef Resources', objs.size, undoc.size
|
37
|
+
end
|
38
|
+
|
39
|
+
def stats_for_chef_resource_properties
|
40
|
+
objs = all_objects.select { |m| m.type == :resource }
|
41
|
+
objs.map!(&:properties).flatten!
|
42
|
+
undoc = objs.select { |m| !m.docstring.nil? && m.docstring.empty? }
|
43
|
+
@undoc_list |= undoc if @undoc_list
|
44
|
+
output 'Chef Resource properties', objs.size, undoc.size
|
45
|
+
end
|
46
|
+
|
47
|
+
def stats_for_chef_resource_actions
|
48
|
+
objs = all_objects.select { |m| m.type == :resource }
|
49
|
+
objs.map!(&:actions).flatten!
|
50
|
+
undoc = objs.select { |m| !m.docstring.nil? && m.docstring.empty? }
|
51
|
+
@undoc_list |= undoc if @undoc_list
|
52
|
+
output 'Chef Resource actions', objs.size, undoc.size
|
53
|
+
end
|
54
|
+
|
55
|
+
# We don't need the file stats, so remove it
|
56
|
+
remove_method :stats_for_files
|
57
|
+
|
58
|
+
# Overrides the output from Yard itself for better indentation
|
59
|
+
# Prints a statistic to standard out. This method is optimized for
|
60
|
+
# getting Integer values, though it allows any data to be printed.
|
61
|
+
#
|
62
|
+
# @param [String] name the statistic name
|
63
|
+
# @param [Integer, String] data the numeric (or any) data representing
|
64
|
+
# the statistic. If +data+ is an Integer, it should represent the
|
65
|
+
# total objects of a type.
|
66
|
+
# @param [Integer, nil] undoc number of undocumented objects for the type
|
67
|
+
# @return [void]
|
68
|
+
def output(name, data, undoc = nil)
|
69
|
+
@total += data if data.is_a?(Integer) && undoc
|
70
|
+
@undocumented += undoc if undoc.is_a?(Integer)
|
71
|
+
data = if undoc
|
72
|
+
"#{format('%5s', data)} (#{format('%5d', undoc)} undocumented)"
|
73
|
+
else
|
74
|
+
format('%5s', data)
|
75
|
+
end
|
76
|
+
log.puts("#{format('%-25s', name + ':')} #{format('%s', data)}")
|
77
|
+
end
|
78
|
+
|
79
|
+
# Returns statistics for machine readable output generation
|
80
|
+
#
|
81
|
+
# @param [String] name the statistic name
|
82
|
+
# @param [Integer, String] data the numeric (or any) data representing
|
83
|
+
# the statistic. If +data+ is an Integer, it should represent the
|
84
|
+
# total objects of a type.
|
85
|
+
# @param [Integer, nil] undoc number of undocumented objects for the type
|
86
|
+
# @return [Hash] Number of documented and undocumented items
|
87
|
+
def output_hash(name, data, undoc = nil)
|
88
|
+
@total += data if data.is_a?(Integer) && undoc
|
89
|
+
@undocumented += undoc if undoc.is_a?(Integer)
|
90
|
+
percent = data.to_i.zero? ? '100' : ((data.to_i - undoc.to_i) / data.to_f) * 100
|
91
|
+
{ name.tr(' ', '_').downcase => { 'name' => name,
|
92
|
+
'items' => data.to_i,
|
93
|
+
'undocumented' => undoc.to_i,
|
94
|
+
'percentage' => percent } }
|
95
|
+
end
|
96
|
+
|
97
|
+
# Prints statistics for different object types in JSON format
|
98
|
+
#
|
99
|
+
# To add statistics for a specific type, add a method +#stats_for_TYPE+
|
100
|
+
# to this class that calls {#output}.
|
101
|
+
def print_statistics_json
|
102
|
+
log.puts JSON.pretty_generate(statistics_hash)
|
103
|
+
end
|
104
|
+
|
105
|
+
def statistics_hash
|
106
|
+
# Use JSON output for the following stats_for_* calls
|
107
|
+
alias output output_hash
|
108
|
+
# This is necessary so we get full access to the stats from the templates. Probably a
|
109
|
+
# bad patch, but for now this is ok.
|
110
|
+
# TODO: Refactor
|
111
|
+
options.verifier = YARD::Verifier.new('[:public].include?(object.visibility)')
|
112
|
+
|
113
|
+
collection = {}
|
114
|
+
@total = 0
|
115
|
+
@undocumented = 0
|
116
|
+
meths = methods.map(&:to_s).grep(/^stats_for_/)
|
117
|
+
|
118
|
+
meths.each { |m| collection.merge!(send(m)) }
|
119
|
+
|
120
|
+
collection['total_percentage'] = total_percentage
|
121
|
+
|
122
|
+
collection
|
123
|
+
end
|
124
|
+
|
125
|
+
# Always use JSON output by default
|
126
|
+
# alias output output_hash
|
127
|
+
# alias print_statistics print_statistics_json
|
128
|
+
|
129
|
+
private
|
130
|
+
|
131
|
+
def total_percentage
|
132
|
+
if @undocumented.zero?
|
133
|
+
100
|
134
|
+
elsif @total.zero?
|
135
|
+
0
|
136
|
+
else
|
137
|
+
(@total - @undocumented).to_f / @total.to_f * 100
|
138
|
+
end
|
139
|
+
end
|
140
|
+
end
|
141
|
+
end
|
142
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
require 'yard'
|
2
|
+
|
3
|
+
module YARD::CodeObjects
|
4
|
+
module Chef
|
5
|
+
class AttributeObject < ChefObject
|
6
|
+
register_element :attribute
|
7
|
+
attr_accessor :attributes
|
8
|
+
|
9
|
+
# Creates a new instance of the AttributeObject which represents a file in
|
10
|
+
# the attributes directory.
|
11
|
+
#
|
12
|
+
# @param namespace [NamespaceObject] namespace to which the attribute belongs
|
13
|
+
# @param name [String] name of the attribute file
|
14
|
+
#
|
15
|
+
# @return [AttributeObject] the newly created AttribteObject
|
16
|
+
#
|
17
|
+
def initialize(namespace, name)
|
18
|
+
super(namespace, name)
|
19
|
+
@attributes = []
|
20
|
+
end
|
21
|
+
|
22
|
+
# Add a single attribute as an Attribute object (see below)
|
23
|
+
#
|
24
|
+
# @param h [Hash] The attribute hash to add
|
25
|
+
#
|
26
|
+
def add(h)
|
27
|
+
@attributes.push(Attribute.new(h))
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
# Simple class to handle Attributes and their specifics
|
32
|
+
class Attribute
|
33
|
+
attr_accessor :default, # The default value
|
34
|
+
:path, # The attributes Hash path. Something like ['cookbook']['one']['two']
|
35
|
+
:docstring, # The attrbitues docstring
|
36
|
+
:precedence # The precedence the attribute is set with
|
37
|
+
|
38
|
+
def initialize(h)
|
39
|
+
h.each { |k, v| instance_variable_set("@#{k}", v) }
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,116 @@
|
|
1
|
+
require 'yard'
|
2
|
+
|
3
|
+
module YARD::CodeObjects
|
4
|
+
module Chef
|
5
|
+
# The chef object will be the root of your namespace
|
6
|
+
class ChefObject < YARD::CodeObjects::NamespaceObject
|
7
|
+
attr_accessor :file # The file the object appears in
|
8
|
+
attr_accessor :header # The header found in the source file
|
9
|
+
|
10
|
+
# Creates a new ChefObject object.
|
11
|
+
#
|
12
|
+
# @param namespace [NamespaceObject] namespace to which the object belongs
|
13
|
+
# @param name [String] name of the ChefObject
|
14
|
+
#
|
15
|
+
# @return [ChefObject] the newly created ChefObject
|
16
|
+
#
|
17
|
+
def initialize(namespace, name)
|
18
|
+
super(namespace, name)
|
19
|
+
end
|
20
|
+
|
21
|
+
# Register a chef element class.
|
22
|
+
#
|
23
|
+
# @param element [Class] chef element class
|
24
|
+
#
|
25
|
+
def self.register_element(element)
|
26
|
+
@@chef_elements ||= {}
|
27
|
+
@@chef_elements[element] = self
|
28
|
+
end
|
29
|
+
|
30
|
+
# Factory for creating and registering chef element object in
|
31
|
+
# YARD::Registry.
|
32
|
+
#
|
33
|
+
# @param namespace [NamespaceObject] namespace to which the object must
|
34
|
+
# belong
|
35
|
+
# @param name [String] name of the chef element
|
36
|
+
# @param type [Symbol, String] type of the chef element
|
37
|
+
#
|
38
|
+
# @return [<type>Object] the element object
|
39
|
+
#
|
40
|
+
def self.register(name, type, file)
|
41
|
+
element = @@chef_elements[type]
|
42
|
+
raise "Invalid chef element type #{type}" unless element
|
43
|
+
element_obj = YARD::Registry.resolve(:root, "#{type}::#{name}")
|
44
|
+
if element_obj.nil?
|
45
|
+
element_obj = element.new(:root, "#{type}::#{name}")
|
46
|
+
log.info "Created [#{type.to_s.capitalize}] #{element_obj.name} => #{element_obj.namespace}"
|
47
|
+
element_obj.chef_init(file)
|
48
|
+
end
|
49
|
+
element_obj
|
50
|
+
end
|
51
|
+
|
52
|
+
# Returns children of an object of a particular type.
|
53
|
+
#
|
54
|
+
# @param type [Symbol] type of ChefObject to be selected
|
55
|
+
#
|
56
|
+
# @return [Array<ChefObject>] list of ChefObjects
|
57
|
+
#
|
58
|
+
def children_by_type(type)
|
59
|
+
children = YARD::Registry.all(type)
|
60
|
+
children.select { |child| child.parent == self }
|
61
|
+
end
|
62
|
+
|
63
|
+
# Does chef specific initalization tasks
|
64
|
+
#
|
65
|
+
# @param file [String] The file of the object thas is being initialized
|
66
|
+
#
|
67
|
+
# @return [ChefObject] The (chef) initialized object
|
68
|
+
#
|
69
|
+
def chef_init(file)
|
70
|
+
self.file = file
|
71
|
+
self.source = IO.read(File.expand_path(file))
|
72
|
+
self.header = find_header_in(source)
|
73
|
+
self.docstring = find_description_in(header)
|
74
|
+
end
|
75
|
+
|
76
|
+
# Gets the file header if available
|
77
|
+
# The header is defined by a every comment line starting at the beginning of the file
|
78
|
+
# Until the first blank line. If no blank line is found then the comment is considered
|
79
|
+
# the following resource's/blocks docstring.
|
80
|
+
#
|
81
|
+
# @return [String] The header of the file. Empty if no header is found
|
82
|
+
#
|
83
|
+
def find_header_in(src)
|
84
|
+
h = []
|
85
|
+
src.each_line do |line|
|
86
|
+
comment = line[/^\s*#\s?(.*)$/, 1]
|
87
|
+
break if comment.nil?
|
88
|
+
|
89
|
+
h.push comment
|
90
|
+
end
|
91
|
+
|
92
|
+
h.join("\n")
|
93
|
+
end
|
94
|
+
|
95
|
+
# Gets the description from the file header.
|
96
|
+
# Currently the docstring of recipes, attributes etc. is looked up in the file
|
97
|
+
# header and starts with a single line containing the keyword "Description".
|
98
|
+
#
|
99
|
+
# @return [String] The description
|
100
|
+
#
|
101
|
+
def find_description_in(header)
|
102
|
+
desc_found = false
|
103
|
+
docstring = []
|
104
|
+
header.each_line do |line|
|
105
|
+
if desc_found
|
106
|
+
docstring.push line
|
107
|
+
elsif line.chomp == 'Description'
|
108
|
+
desc_found = true
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
docstring.join("\n")
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
require 'yard'
|
2
|
+
|
3
|
+
module YARD::CodeObjects
|
4
|
+
module Chef
|
5
|
+
# A CookbookObject represents a Chef cookbook.
|
6
|
+
# See http://wiki.opscode.com/display/chef/Cookbooks for more information
|
7
|
+
# about cookbooks.
|
8
|
+
#
|
9
|
+
class CookbookObject < ChefObject
|
10
|
+
register_element :cookbook
|
11
|
+
|
12
|
+
attr_accessor :docstring_type
|
13
|
+
|
14
|
+
# Cookbook metadata
|
15
|
+
attr_accessor :dependencies
|
16
|
+
attr_accessor :version
|
17
|
+
attr_accessor :source_url
|
18
|
+
attr_accessor :issues_url
|
19
|
+
attr_accessor :maintainer
|
20
|
+
attr_accessor :maintainer_email
|
21
|
+
attr_accessor :license
|
22
|
+
attr_accessor :platforms
|
23
|
+
attr_accessor :gems
|
24
|
+
|
25
|
+
# Creates a new CookbookObject instance.
|
26
|
+
# @param namespace [NamespaceObject] namespace to which the cookbook
|
27
|
+
# belongs
|
28
|
+
# @param name [String] name of the cookbook
|
29
|
+
#
|
30
|
+
# @return [CookbookObject] the newly created CookbookObject
|
31
|
+
#
|
32
|
+
def initialize(namespace, name)
|
33
|
+
super(namespace, name)
|
34
|
+
@docstring_type = :markdown
|
35
|
+
end
|
36
|
+
|
37
|
+
# Libraries defined in the cookbook.
|
38
|
+
# Catches all classes, modules and defintion directly defined without a namespace
|
39
|
+
#
|
40
|
+
# @return [Array] libraries in the cookbook
|
41
|
+
#
|
42
|
+
def libraries
|
43
|
+
modules = YARD::Registry.all(:module)
|
44
|
+
classes = YARD::Registry.all(:class)
|
45
|
+
root_definitions = YARD::Registry.all(:method).select { |m| m.path =~ /^root#/ }
|
46
|
+
|
47
|
+
classes + modules + root_definitions
|
48
|
+
end
|
49
|
+
|
50
|
+
def metadata
|
51
|
+
[@version, @maintainer, @dependencies]
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require 'yard'
|
2
|
+
|
3
|
+
module YARD::CodeObjects
|
4
|
+
module Chef
|
5
|
+
class RecipeObject < ChefObject
|
6
|
+
register_element :recipe
|
7
|
+
|
8
|
+
# Creates a new instance of RecipeObject.
|
9
|
+
#
|
10
|
+
# @param namespace [NamespaceObject] namespace to which the recipe belongs
|
11
|
+
# @param name [String] name of the recipe
|
12
|
+
#
|
13
|
+
# @return [RecipeObject] the newly created RecipeObject
|
14
|
+
#
|
15
|
+
def initialize(namespace, name)
|
16
|
+
super(namespace, name)
|
17
|
+
end
|
18
|
+
|
19
|
+
# Needed by the template to render recipe source code.
|
20
|
+
# Since we always display the full source we start with 1
|
21
|
+
#
|
22
|
+
# @return [Integer] 1
|
23
|
+
#
|
24
|
+
def line
|
25
|
+
1
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,70 @@
|
|
1
|
+
require 'yard'
|
2
|
+
|
3
|
+
module YARD::CodeObjects
|
4
|
+
module Chef
|
5
|
+
class ResourceObject < ChefObject
|
6
|
+
register_element :resource
|
7
|
+
attr_accessor :properties,
|
8
|
+
:actions,
|
9
|
+
:default_action,
|
10
|
+
:resource_name,
|
11
|
+
:load_current_value
|
12
|
+
|
13
|
+
# Creates a new instance of the ResourceObject
|
14
|
+
#
|
15
|
+
# @param namespace [NamespaceObject] namespace to which the resource belongs
|
16
|
+
# @param name [String] name of the resource. This is the base name which chef
|
17
|
+
# automatically generates.
|
18
|
+
#
|
19
|
+
# @return [ResourceObject] the newly created ResourceObject
|
20
|
+
#
|
21
|
+
def initialize(namespace, name)
|
22
|
+
super(namespace, name)
|
23
|
+
@resource_name = name
|
24
|
+
@properties = []
|
25
|
+
@actions = []
|
26
|
+
end
|
27
|
+
|
28
|
+
# Add a single property as an Property object (see below)
|
29
|
+
#
|
30
|
+
# @param h [Hash] The property hash to add
|
31
|
+
#
|
32
|
+
def add_property(h)
|
33
|
+
@properties.push(Property.new(h))
|
34
|
+
end
|
35
|
+
|
36
|
+
# Add an action as an Action object (see below)
|
37
|
+
#
|
38
|
+
# @param h [Hash] The action hash to add
|
39
|
+
#
|
40
|
+
def add_action(h)
|
41
|
+
@actions.push(Action.new(h))
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
# Simple class to handle Properties and their specifics
|
46
|
+
# Full docs here http://www.rubydoc.info/gems/chef/Chef%2FMixin%2FProperties%2FClassMethods:property
|
47
|
+
class Property
|
48
|
+
attr_accessor :identifier, # The name of the property
|
49
|
+
:docstring, # The attrbitues docstring
|
50
|
+
:type, # The ruby type of the property
|
51
|
+
:options # The various property options
|
52
|
+
|
53
|
+
def initialize(h)
|
54
|
+
h.each { |k, v| instance_variable_set("@#{k}", v) }
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
# Simple class to handle actions
|
59
|
+
class Action
|
60
|
+
attr_accessor :identifier, # The name of the action
|
61
|
+
:source, # The source of the action block
|
62
|
+
:docstring, # The actions docstring
|
63
|
+
:line # The line number of the first line of the block needed for the output formatting
|
64
|
+
|
65
|
+
def initialize(h)
|
66
|
+
h.each { |k, v| instance_variable_set("@#{k}", v) }
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
require 'yard'
|
2
|
+
|
3
|
+
module YARD::Handlers
|
4
|
+
module Chef
|
5
|
+
# Handles attributes in cookbook
|
6
|
+
class AttributeHandler < Base
|
7
|
+
MATCH = /^\s*(node\.)?(default|force_default|normal|override|force_override)(\[.+?\])\s*=\s*(.+)/m
|
8
|
+
in_file(%r{^attributes\/.*\.rb$})
|
9
|
+
handles MATCH
|
10
|
+
|
11
|
+
def process
|
12
|
+
attrib_obj = ChefObject.register(filename, :attribute, statement.file)
|
13
|
+
|
14
|
+
docstring_is_header = (statement.docstring == attrib_obj.header)
|
15
|
+
attrib_obj.add attr_hash(docstring_is_header) if statement.type == :assign
|
16
|
+
end
|
17
|
+
|
18
|
+
# Creates the hash to initialize the single attribute object
|
19
|
+
#
|
20
|
+
# @return [Hash] the hash to initialize the attribute in the attribute code object
|
21
|
+
#
|
22
|
+
def attr_hash(nodoc)
|
23
|
+
{
|
24
|
+
precedence: statement.jump(:ident).source,
|
25
|
+
default: statement.jump(:assign)[1].source,
|
26
|
+
docstring: nodoc ? '' : statement.docstring,
|
27
|
+
path: statement.source.match(MATCH)[3]
|
28
|
+
}
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|