yard-chefdoc 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|