chef_attrdoc 0.9.2 → 1.0.0.pre
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.
- data/.travis.yml +7 -0
- data/Gemfile +3 -0
- data/Gemfile.lock +30 -0
- data/README.md +51 -6
- data/Rakefile +11 -1
- data/bin/chef_attrdoc +5 -13
- data/chef_attrdoc.gemspec +3 -0
- data/lib/chef_attrdoc/version.rb +1 -1
- data/lib/chef_attrdoc.rb +56 -19
- data/spec/attributes_file_spec.rb +276 -0
- data/spec/chef_attrdoc_spec.rb +63 -194
- data/spec/fixtures/cookbook-example/README.md +13 -0
- data/spec/fixtures/cookbook-example/attributes/default.rb +17 -0
- data/spec/fixtures/file1.rb +1 -0
- data/spec/fixtures/file2 +1 -0
- data/spec/fixtures/file3.rb +1 -0
- data/spec/readme_example_spec.rb +45 -0
- metadata +55 -6
data/.travis.yml
ADDED
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
chef_attrdoc (0.9.2)
|
5
|
+
|
6
|
+
GEM
|
7
|
+
remote: https://rubygems.org/
|
8
|
+
specs:
|
9
|
+
diff-lcs (1.2.5)
|
10
|
+
rake (10.3.2)
|
11
|
+
rspec (3.0.0)
|
12
|
+
rspec-core (~> 3.0.0)
|
13
|
+
rspec-expectations (~> 3.0.0)
|
14
|
+
rspec-mocks (~> 3.0.0)
|
15
|
+
rspec-core (3.0.2)
|
16
|
+
rspec-support (~> 3.0.0)
|
17
|
+
rspec-expectations (3.0.2)
|
18
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
19
|
+
rspec-support (~> 3.0.0)
|
20
|
+
rspec-mocks (3.0.2)
|
21
|
+
rspec-support (~> 3.0.0)
|
22
|
+
rspec-support (3.0.2)
|
23
|
+
|
24
|
+
PLATFORMS
|
25
|
+
ruby
|
26
|
+
|
27
|
+
DEPENDENCIES
|
28
|
+
chef_attrdoc!
|
29
|
+
rake
|
30
|
+
rspec
|
data/README.md
CHANGED
@@ -1,29 +1,74 @@
|
|
1
1
|
chef_attrdoc
|
2
2
|
============
|
3
3
|
[](http://badge.fury.io/rb/chef_attrdoc)
|
4
|
+
[](https://travis-ci.org/mapleoin/chef_attrdoc)
|
4
5
|
[](https://codeclimate.com/github/mapleoin/chef_attrdoc)
|
5
6
|
|
6
7
|
Extract documentation from chef cookbooks' attributes files and output it to the cookbook's README.md file.
|
7
8
|
|
8
|
-
|
9
9
|
`chef_attrdoc` groups attribute initialization lines together with the comments immediately above them. Any lines containing an attribute initialization which are not separated by an empty line are considered a group. The comment immediately above them is assumed to describe the group of attributes below. Groups of attribute initialization lines which are not immediately preceded by a comment line are ignored and will not show up in the output.
|
10
10
|
|
11
11
|
chef_attrdoc currently ignores *TODO*, *XXX*, *NOTE* and *foodcritic* comments.
|
12
12
|
|
13
13
|
### Usage:
|
14
14
|
|
15
|
-
```
|
16
|
-
|
17
|
-
|
15
|
+
```bash
|
16
|
+
$ gem install chef_attrdoc
|
17
|
+
$ chef_attrdoc ~/cookbooks/mycookbook
|
18
18
|
```
|
19
19
|
|
20
|
-
`chef_attrdoc` will try to find an Attributes heading in the README.md file in that directory and replace its contents with the generated `attributes
|
20
|
+
`chef_attrdoc` will try to find an Attributes heading in the README.md file in that directory and replace its contents with the generated attributes documentation. The attributes documentation is compiled from all the files in the cookbook's `attributes/` directory. All the files ending in `.rb` in that directory are considered to be attributes files.
|
21
21
|
|
22
22
|
`chef_attrdoc` uses ruby's stdlib `ripper` module and so does not have any dependencies.
|
23
23
|
|
24
|
+
`chef_attrdoc` currently requires `ruby >= 1.9`.
|
25
|
+
|
24
26
|
### Examples
|
25
27
|
|
26
|
-
|
28
|
+
```bash
|
29
|
+
$ cat cookbook-example/attributes/default.rb
|
30
|
+
```
|
31
|
+
# Copyright 1970, nobody
|
32
|
+
|
33
|
+
# this is the attribute
|
34
|
+
default['some']['attribute'] = 'foo'
|
35
|
+
|
36
|
+
default['this']['will']['be'] = 'ignored'
|
37
|
+
|
38
|
+
# NOTE code blocks without a comment are ignored as are those beginning
|
39
|
+
# NOTE with 'NOTE', 'XXX', 'TODO' or foodcritic comments
|
40
|
+
|
41
|
+
# a longer block of code
|
42
|
+
case something
|
43
|
+
when 'foo'
|
44
|
+
default['some']['foo'] = 'baz'
|
45
|
+
else
|
46
|
+
default['some']['foo'] = 'qux'
|
47
|
+
end
|
48
|
+
```bash
|
49
|
+
$ chef_attrdoc cookbook-example --stdout
|
50
|
+
```
|
51
|
+
```
|
52
|
+
## default.rb
|
53
|
+
|
54
|
+
this is the attribute
|
55
|
+
|
56
|
+
```ruby
|
57
|
+
default['some']['attribute'] = 'foo'
|
58
|
+
```
|
59
|
+
|
60
|
+
a longer block of code
|
61
|
+
|
62
|
+
```ruby
|
63
|
+
case something
|
64
|
+
when 'foo'
|
65
|
+
default['some']['foo'] = 'baz'
|
66
|
+
else
|
67
|
+
default['some']['foo'] = 'qux'
|
68
|
+
end
|
69
|
+
```
|
70
|
+
|
71
|
+
Here are some longer examples from openstack chef cookbooks:
|
27
72
|
|
28
73
|
[openstack-compute attributes file](https://github.com/stackforge/cookbook-openstack-compute/blob/aa42f5c09a445cde7267e4b4d00a6ce893aa481e/attributes/default.rb) - [output](https://gist.github.com/mapleoin/6886586)
|
29
74
|
|
data/Rakefile
CHANGED
@@ -1 +1,11 @@
|
|
1
|
-
require
|
1
|
+
require 'bundler/gem_tasks'
|
2
|
+
require 'rspec/core/rake_task'
|
3
|
+
|
4
|
+
RSpec::Core::RakeTask.new(:test) do |t|
|
5
|
+
t.rspec_opts = [].tap do |a|
|
6
|
+
a.push('--color')
|
7
|
+
a.push('--format progress')
|
8
|
+
end.join(' ')
|
9
|
+
end
|
10
|
+
|
11
|
+
task :default => [:test]
|
data/bin/chef_attrdoc
CHANGED
@@ -31,28 +31,20 @@ opt_parser = OptionParser.new do |opts|
|
|
31
31
|
end
|
32
32
|
end.parse!
|
33
33
|
|
34
|
-
|
34
|
+
dir_path = ["attributes"]
|
35
35
|
unless ARGV.empty?
|
36
|
-
|
36
|
+
dir_path.unshift ARGV[0]
|
37
37
|
unless options[:stdout]
|
38
38
|
options[:readme] = File.join(ARGV[0], options[:readme])
|
39
39
|
end
|
40
40
|
end
|
41
|
-
file_path = File.join file_path
|
42
41
|
|
43
42
|
begin
|
44
|
-
|
45
|
-
rescue Exception => e
|
46
|
-
puts e.message
|
47
|
-
exit
|
48
|
-
end
|
49
|
-
|
50
|
-
begin
|
51
|
-
attrs = ChefAttrdoc::AttributesFile.new contents
|
43
|
+
attrs = ChefAttrdoc.process_attributes dir_path
|
52
44
|
if options[:stdout]
|
53
|
-
puts attrs
|
45
|
+
puts attrs
|
54
46
|
else
|
55
|
-
|
47
|
+
ChefAttrdoc.write_readme options[:readme], attrs
|
56
48
|
end
|
57
49
|
rescue Exception => e
|
58
50
|
if options[:debug]
|
data/chef_attrdoc.gemspec
CHANGED
@@ -17,4 +17,7 @@ Gem::Specification.new do |spec|
|
|
17
17
|
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
18
|
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
19
|
spec.require_paths = ["lib"]
|
20
|
+
|
21
|
+
spec.add_development_dependency 'rake'
|
22
|
+
spec.add_development_dependency 'rspec'
|
20
23
|
end
|
data/lib/chef_attrdoc/version.rb
CHANGED
data/lib/chef_attrdoc.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# -*- coding: utf-8 -*-
|
2
2
|
|
3
|
-
# Copyright 2013, Ionuț Arțăriși <ionut@artarisi.eu>
|
3
|
+
# Copyright 2013-2014, Ionuț Arțăriși <ionut@artarisi.eu>
|
4
4
|
#
|
5
5
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
6
6
|
# you may not use this file except in compliance with the License.
|
@@ -130,28 +130,65 @@ module ChefAttrdoc
|
|
130
130
|
end
|
131
131
|
strings.join
|
132
132
|
end
|
133
|
+
end
|
133
134
|
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
135
|
+
# open the :readme: Markdown file and replace the 'Attributes' section
|
136
|
+
# with the contents of :parsed:
|
137
|
+
def self.write_readme(readme, parsed)
|
138
|
+
File.open(readme, File::RDWR) do |f|
|
139
|
+
# TODO find a cleaner way and do this in one step
|
140
|
+
content = f.read
|
141
|
+
if content =~ /\nAttributes\s*=+\s*\n/
|
142
|
+
updated = content.gsub(/(?<before>.*\nAttributes\s*=+\s*\n)(?m:.+?)(?<after>\n.+\s*\n=+.*)/,
|
143
|
+
'\k<before>CHEF_ATTRDOC_UPDATING_TEMPLATE\k<after>')
|
144
|
+
|
145
|
+
# XXX hack because I couldn't figure out how to get another
|
146
|
+
# newline in between the <before> and the content
|
147
|
+
updated.sub!('CHEF_ATTRDOC_UPDATING_TEMPLATE',
|
148
|
+
"\nCHEF_ATTRDOC_UPDATING_TEMPLATE")
|
149
|
+
elsif content =~ /\n\#+\s*Attributes\s*\n/
|
150
|
+
updated = content.gsub(/(?<before>.*\n\#+\s*Attributes\s*\n)(.+?)(?<after>\n\#+.*)/m,
|
151
|
+
'\k<before>CHEF_ATTRDOC_UPDATING_TEMPLATE\k<after>')
|
152
|
+
else
|
153
|
+
raise StandardError, "Could not find Attributes heading in #{readme}. Please make sure your README file has proper markdown formatting and includes an Attributes heading."
|
154
|
+
end
|
155
|
+
|
156
|
+
updated.sub! 'CHEF_ATTRDOC_UPDATING_TEMPLATE', parsed
|
157
|
+
f.rewind
|
158
|
+
f.write(updated)
|
159
|
+
f.flush
|
160
|
+
f.truncate(f.pos)
|
161
|
+
end
|
162
|
+
end
|
147
163
|
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
164
|
+
# return a list of [filename, file-contents] for each ruby file in :dir:
|
165
|
+
def self.attrs_contents(dir)
|
166
|
+
files_contents = []
|
167
|
+
filenames = Dir.glob(File.join(dir, '*.rb')).sort
|
168
|
+
|
169
|
+
filenames.each do |f|
|
170
|
+
begin
|
171
|
+
files_contents << [File.basename(f), IO.read(f)]
|
172
|
+
rescue Exception => e
|
173
|
+
abort e.message
|
153
174
|
end
|
154
175
|
end
|
176
|
+
|
177
|
+
files_contents
|
178
|
+
end
|
179
|
+
|
180
|
+
# takes a directory of attributes files and returns a string with
|
181
|
+
# Markdown content with the output of processing all the attributes
|
182
|
+
def self.process_attributes(dir)
|
183
|
+
files_contents = ChefAttrdoc.attrs_contents dir
|
184
|
+
|
185
|
+
output = []
|
186
|
+
files_contents.each do |filename, contents|
|
187
|
+
attrs = ChefAttrdoc::AttributesFile.new contents
|
188
|
+
output << "## #{filename}\n\n#{attrs}"
|
189
|
+
end
|
190
|
+
|
191
|
+
output.join("\n")
|
155
192
|
end
|
156
193
|
end
|
157
194
|
|
@@ -0,0 +1,276 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
|
3
|
+
# Copyright 2014, Ionuț Arțăriși <ionut@artarisi.eu>
|
4
|
+
#
|
5
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
6
|
+
# you may not use this file except in compliance with the License.
|
7
|
+
# You may obtain a copy of the License at
|
8
|
+
#
|
9
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
10
|
+
#
|
11
|
+
# Unless required by applicable law or agreed to in writing, software
|
12
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
13
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
14
|
+
# See the License for the specific language governing permissions and
|
15
|
+
# limitations under the License.
|
16
|
+
#
|
17
|
+
|
18
|
+
require 'chef_attrdoc'
|
19
|
+
|
20
|
+
|
21
|
+
describe ChefAttrdoc::AttributesFile do
|
22
|
+
["TODO bar", "XXX foo bar", "NOTE(me) nasty bug",
|
23
|
+
":pragma-foodcritic: ~FC024 - won't fix this"].each do |comm|
|
24
|
+
it "ignores \"#{comm}\" comment" do
|
25
|
+
text = <<END
|
26
|
+
# #{comm}
|
27
|
+
# good comment
|
28
|
+
default[good] = 'comment'
|
29
|
+
END
|
30
|
+
ca = ChefAttrdoc::AttributesFile.new(text)
|
31
|
+
expect(ca.to_s).to eq(<<-OUTPUT)
|
32
|
+
good comment
|
33
|
+
|
34
|
+
```ruby
|
35
|
+
default[good] = 'comment'
|
36
|
+
```
|
37
|
+
|
38
|
+
OUTPUT
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
it 'groups comments and several lines of code together' do
|
43
|
+
text = <<END
|
44
|
+
# first block
|
45
|
+
default[foo] = 'bar'
|
46
|
+
default[bar] = 'baz'
|
47
|
+
|
48
|
+
# second block
|
49
|
+
node.set[baz] = 'qux'
|
50
|
+
node.set[foo] = 'qux'
|
51
|
+
node.set[bar] = 'qux'
|
52
|
+
END
|
53
|
+
ca = ChefAttrdoc::AttributesFile.new(text)
|
54
|
+
expect(ca.to_s).to eq(<<-OUTPUT)
|
55
|
+
first block
|
56
|
+
|
57
|
+
```ruby
|
58
|
+
default[foo] = 'bar'
|
59
|
+
default[bar] = 'baz'
|
60
|
+
```
|
61
|
+
|
62
|
+
second block
|
63
|
+
|
64
|
+
```ruby
|
65
|
+
node.set[baz] = 'qux'
|
66
|
+
node.set[foo] = 'qux'
|
67
|
+
node.set[bar] = 'qux'
|
68
|
+
```
|
69
|
+
|
70
|
+
OUTPUT
|
71
|
+
end
|
72
|
+
|
73
|
+
it 'ignores code without comments' do
|
74
|
+
text = <<END
|
75
|
+
# first block
|
76
|
+
default[foo] = 'bar'
|
77
|
+
default[bar] = 'baz'
|
78
|
+
|
79
|
+
default[ignored] = false
|
80
|
+
|
81
|
+
# second block
|
82
|
+
node.set[baz] = 'qux'
|
83
|
+
END
|
84
|
+
ca = ChefAttrdoc::AttributesFile.new(text)
|
85
|
+
expect(ca.to_s).to eq(<<-OUTPUT)
|
86
|
+
first block
|
87
|
+
|
88
|
+
```ruby
|
89
|
+
default[foo] = 'bar'
|
90
|
+
default[bar] = 'baz'
|
91
|
+
```
|
92
|
+
|
93
|
+
second block
|
94
|
+
|
95
|
+
```ruby
|
96
|
+
node.set[baz] = 'qux'
|
97
|
+
```
|
98
|
+
|
99
|
+
OUTPUT
|
100
|
+
end
|
101
|
+
|
102
|
+
it 'ignores the first comments in a file' do
|
103
|
+
ca = ChefAttrdoc::AttributesFile.new(<<-INPUT)
|
104
|
+
#!/she/bang
|
105
|
+
|
106
|
+
# Copyright
|
107
|
+
# foo
|
108
|
+
|
109
|
+
# this is important
|
110
|
+
default[foo] = 'bar'
|
111
|
+
INPUT
|
112
|
+
|
113
|
+
expect(ca.to_s).to eq(<<-OUTPUT)
|
114
|
+
this is important
|
115
|
+
|
116
|
+
```ruby
|
117
|
+
default[foo] = 'bar'
|
118
|
+
```
|
119
|
+
|
120
|
+
OUTPUT
|
121
|
+
end
|
122
|
+
|
123
|
+
it 'handles platform group with lots of branches and hashes' do
|
124
|
+
text = <<END
|
125
|
+
# platform specific attributes
|
126
|
+
case platform
|
127
|
+
when "fedora", "redhat", "centos"
|
128
|
+
default["openstack"]["identity"]["user"] = "keystone"
|
129
|
+
default["openstack"]["identity"]["group"] = "keystone"
|
130
|
+
default["openstack"]["identity"]["platform"] = {
|
131
|
+
"memcache_python_packages" => [ "python-memcached" ],
|
132
|
+
"keystone_packages" => [ "openstack-keystone" ],
|
133
|
+
"keystone_process_name" => "keystone-all",
|
134
|
+
"package_options" => ""
|
135
|
+
}
|
136
|
+
when "suse"
|
137
|
+
default["openstack"]["identity"]["user"] = "openstack-keystone"
|
138
|
+
default["openstack"]["identity"]["platform"] = {
|
139
|
+
"mysql_python_packages" => [ "python-mysql" ],
|
140
|
+
"memcache_python_packages" => [ "python-python-memcached" ],
|
141
|
+
"keystone_process_name" => "keystone-all",
|
142
|
+
"package_options" => ""
|
143
|
+
}
|
144
|
+
END
|
145
|
+
ca = ChefAttrdoc::AttributesFile.new(text)
|
146
|
+
expect(ca.to_s).to eq(<<-END)
|
147
|
+
platform specific attributes
|
148
|
+
|
149
|
+
```ruby
|
150
|
+
case platform
|
151
|
+
when "fedora", "redhat", "centos"
|
152
|
+
default["openstack"]["identity"]["user"] = "keystone"
|
153
|
+
default["openstack"]["identity"]["group"] = "keystone"
|
154
|
+
default["openstack"]["identity"]["platform"] = {
|
155
|
+
"memcache_python_packages" => [ "python-memcached" ],
|
156
|
+
"keystone_packages" => [ "openstack-keystone" ],
|
157
|
+
"keystone_process_name" => "keystone-all",
|
158
|
+
"package_options" => ""
|
159
|
+
}
|
160
|
+
when "suse"
|
161
|
+
default["openstack"]["identity"]["user"] = "openstack-keystone"
|
162
|
+
default["openstack"]["identity"]["platform"] = {
|
163
|
+
"mysql_python_packages" => [ "python-mysql" ],
|
164
|
+
"memcache_python_packages" => [ "python-python-memcached" ],
|
165
|
+
"keystone_process_name" => "keystone-all",
|
166
|
+
"package_options" => ""
|
167
|
+
}
|
168
|
+
```
|
169
|
+
|
170
|
+
END
|
171
|
+
end
|
172
|
+
|
173
|
+
it 'handles comments over several lines which include blank lines' do
|
174
|
+
text = <<END
|
175
|
+
# my comment
|
176
|
+
#
|
177
|
+
# continued comment
|
178
|
+
#
|
179
|
+
default["some"]["actual"]["code"] = 42
|
180
|
+
END
|
181
|
+
ca = ChefAttrdoc::AttributesFile.new(text)
|
182
|
+
expect(ca.to_s).to eq(<<-END)
|
183
|
+
my comment
|
184
|
+
|
185
|
+
continued comment
|
186
|
+
|
187
|
+
|
188
|
+
```ruby
|
189
|
+
default["some"]["actual"]["code"] = 42
|
190
|
+
```
|
191
|
+
|
192
|
+
END
|
193
|
+
end
|
194
|
+
|
195
|
+
it 'keeps good inline comments' do
|
196
|
+
ca = ChefAttrdoc::AttributesFile.new(<<-INPUT)
|
197
|
+
# my comment
|
198
|
+
default["ignored"]["thing"] = 33 # a useful inline comment
|
199
|
+
default["foo"] = "bar"
|
200
|
+
INPUT
|
201
|
+
expect(ca.to_s).to eq(<<-OUTPUT)
|
202
|
+
my comment
|
203
|
+
|
204
|
+
```ruby
|
205
|
+
default["ignored"]["thing"] = 33 # a useful inline comment
|
206
|
+
default["foo"] = "bar"
|
207
|
+
```
|
208
|
+
|
209
|
+
OUTPUT
|
210
|
+
end
|
211
|
+
|
212
|
+
it 'discards ignored inline comments' do
|
213
|
+
ca = ChefAttrdoc::AttributesFile.new(<<-INPUT)
|
214
|
+
# my comment
|
215
|
+
default["ignored"]["thing"] = 33 # TODO(tommy) an ignored inline comment
|
216
|
+
default["foo"] = "bar"
|
217
|
+
INPUT
|
218
|
+
expect(ca.to_s).to eq(<<-OUTPUT)
|
219
|
+
my comment
|
220
|
+
|
221
|
+
```ruby
|
222
|
+
default["ignored"]["thing"] = 33
|
223
|
+
default["foo"] = "bar"
|
224
|
+
```
|
225
|
+
|
226
|
+
OUTPUT
|
227
|
+
end
|
228
|
+
|
229
|
+
it 'ignores inline comments on code with no leading comments' do
|
230
|
+
ca = ChefAttrdoc::AttributesFile.new(<<-INPUT)
|
231
|
+
# something good
|
232
|
+
foo = bar
|
233
|
+
|
234
|
+
default['something'] = 'bad' # foo
|
235
|
+
default['just']['more'] = 'code'
|
236
|
+
INPUT
|
237
|
+
expect(ca.to_s).to eq(<<-OUTPUT)
|
238
|
+
something good
|
239
|
+
|
240
|
+
```ruby
|
241
|
+
foo = bar
|
242
|
+
```
|
243
|
+
|
244
|
+
OUTPUT
|
245
|
+
end
|
246
|
+
|
247
|
+
it 'uses isolated comment blocks' do
|
248
|
+
ca = ChefAttrdoc::AttributesFile.new(<<-INPUT)
|
249
|
+
# foo bar
|
250
|
+
foo = bar
|
251
|
+
|
252
|
+
# comment we want to keep
|
253
|
+
# still good
|
254
|
+
|
255
|
+
# foo bar
|
256
|
+
foo = bar
|
257
|
+
INPUT
|
258
|
+
expect(ca.to_s).to eq(<<-OUTPUT)
|
259
|
+
foo bar
|
260
|
+
|
261
|
+
```ruby
|
262
|
+
foo = bar
|
263
|
+
```
|
264
|
+
|
265
|
+
comment we want to keep
|
266
|
+
still good
|
267
|
+
|
268
|
+
foo bar
|
269
|
+
|
270
|
+
```ruby
|
271
|
+
foo = bar
|
272
|
+
```
|
273
|
+
|
274
|
+
OUTPUT
|
275
|
+
end
|
276
|
+
end
|
data/spec/chef_attrdoc_spec.rb
CHANGED
@@ -19,227 +19,96 @@ require 'chef_attrdoc'
|
|
19
19
|
|
20
20
|
|
21
21
|
describe ChefAttrdoc do
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
# good comment
|
28
|
-
default[good] = 'comment'
|
29
|
-
END
|
30
|
-
ca = ChefAttrdoc::AttributesFile.new(text)
|
31
|
-
expect(ca.groups).to eq([["default[good] = 'comment'\n", "# good comment\n"]])
|
32
|
-
end
|
33
|
-
end
|
22
|
+
describe '#write_readme' do
|
23
|
+
context 'using Attributes\n========== syntax' do
|
24
|
+
it 'handles an Attributes section followed by a multiword header' do
|
25
|
+
readme = double('file').as_null_object
|
26
|
+
allow(readme).to receive(:read).and_return(<<-README)
|
34
27
|
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
default[foo] = 'bar'
|
39
|
-
default[bar] = 'baz'
|
40
|
-
|
41
|
-
# second block
|
42
|
-
node.set[baz] = 'qux'
|
43
|
-
node.set[foo] = 'qux'
|
44
|
-
node.set[bar = 'qux'
|
45
|
-
END
|
46
|
-
ca = ChefAttrdoc::AttributesFile.new(text)
|
47
|
-
expect(ca.groups).to eq([
|
48
|
-
["default[foo] = 'bar'\ndefault[bar] = 'baz'\n",
|
49
|
-
"# first block\n"],
|
50
|
-
["node.set[baz] = 'qux'\nnode.set[foo] = 'qux'\nnode.set[bar = 'qux'\n",
|
51
|
-
"# second block\n"]])
|
52
|
-
end
|
28
|
+
Attributes
|
29
|
+
==========
|
30
|
+
my attributes
|
53
31
|
|
54
|
-
|
55
|
-
text = <<END
|
56
|
-
# first block
|
57
|
-
default[foo] = 'bar'
|
58
|
-
default[bar] = 'baz'
|
59
|
-
|
60
|
-
default[ignored] = false
|
61
|
-
|
62
|
-
# second block
|
63
|
-
node.set[baz] = 'qux'
|
64
|
-
END
|
65
|
-
ca = ChefAttrdoc::AttributesFile.new(text)
|
66
|
-
expect(ca.groups).to eq([
|
67
|
-
["default[foo] = 'bar'\ndefault[bar] = 'baz'\n", "# first block\n"],
|
68
|
-
["node.set[baz] = 'qux'\n", "# second block\n"]])
|
69
|
-
end
|
32
|
+
are nice
|
70
33
|
|
71
|
-
|
72
|
-
|
73
|
-
#!/she/bang
|
34
|
+
Another header
|
35
|
+
==============
|
74
36
|
|
75
|
-
|
76
|
-
# foo
|
37
|
+
doc we won't touch
|
77
38
|
|
78
|
-
|
79
|
-
|
80
|
-
|
39
|
+
README
|
40
|
+
allow(::File).to receive(:open).and_yield(readme)
|
41
|
+
expect(readme).to receive(:write).with(<<-README)
|
81
42
|
|
82
|
-
|
83
|
-
|
43
|
+
Attributes
|
44
|
+
==========
|
84
45
|
|
85
|
-
|
86
|
-
default[foo] = 'bar'
|
87
|
-
```
|
46
|
+
foo
|
88
47
|
|
89
|
-
|
90
|
-
|
48
|
+
Another header
|
49
|
+
==============
|
91
50
|
|
92
|
-
|
93
|
-
text = <<END
|
94
|
-
# platform specific attributes
|
95
|
-
case platform
|
96
|
-
when "fedora", "redhat", "centos"
|
97
|
-
default["openstack"]["identity"]["user"] = "keystone"
|
98
|
-
default["openstack"]["identity"]["group"] = "keystone"
|
99
|
-
default["openstack"]["identity"]["platform"] = {
|
100
|
-
"memcache_python_packages" => [ "python-memcached" ],
|
101
|
-
"keystone_packages" => [ "openstack-keystone" ],
|
102
|
-
"keystone_process_name" => "keystone-all",
|
103
|
-
"package_options" => ""
|
104
|
-
}
|
105
|
-
when "suse"
|
106
|
-
default["openstack"]["identity"]["user"] = "openstack-keystone"
|
107
|
-
default["openstack"]["identity"]["platform"] = {
|
108
|
-
"mysql_python_packages" => [ "python-mysql" ],
|
109
|
-
"memcache_python_packages" => [ "python-python-memcached" ],
|
110
|
-
"keystone_process_name" => "keystone-all",
|
111
|
-
"package_options" => ""
|
112
|
-
}
|
113
|
-
END
|
114
|
-
ca = ChefAttrdoc::AttributesFile.new(text)
|
115
|
-
expect(ca.to_s).to eq(<<-END)
|
116
|
-
platform specific attributes
|
117
|
-
|
118
|
-
```ruby
|
119
|
-
case platform
|
120
|
-
when "fedora", "redhat", "centos"
|
121
|
-
default["openstack"]["identity"]["user"] = "keystone"
|
122
|
-
default["openstack"]["identity"]["group"] = "keystone"
|
123
|
-
default["openstack"]["identity"]["platform"] = {
|
124
|
-
"memcache_python_packages" => [ "python-memcached" ],
|
125
|
-
"keystone_packages" => [ "openstack-keystone" ],
|
126
|
-
"keystone_process_name" => "keystone-all",
|
127
|
-
"package_options" => ""
|
128
|
-
}
|
129
|
-
when "suse"
|
130
|
-
default["openstack"]["identity"]["user"] = "openstack-keystone"
|
131
|
-
default["openstack"]["identity"]["platform"] = {
|
132
|
-
"mysql_python_packages" => [ "python-mysql" ],
|
133
|
-
"memcache_python_packages" => [ "python-python-memcached" ],
|
134
|
-
"keystone_process_name" => "keystone-all",
|
135
|
-
"package_options" => ""
|
136
|
-
}
|
137
|
-
```
|
138
|
-
|
139
|
-
END
|
140
|
-
end
|
51
|
+
doc we won't touch
|
141
52
|
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
ca = ChefAttrdoc::AttributesFile.new(text)
|
151
|
-
expect(ca.to_s).to eq(<<-END)
|
152
|
-
my comment
|
53
|
+
README
|
54
|
+
ChefAttrdoc.write_readme('filename', "foo\n")
|
55
|
+
end
|
56
|
+
end
|
57
|
+
context 'using ### Attributes syntax' do
|
58
|
+
it 'handles an Attributes section followed by a multiword header' do
|
59
|
+
readme = double('file').as_null_object
|
60
|
+
allow(readme).to receive(:read).and_return(<<-README)
|
153
61
|
|
154
|
-
|
62
|
+
## Attributes
|
155
63
|
|
64
|
+
my attributes
|
156
65
|
|
157
|
-
|
158
|
-
default["some"]["actual"]["code"] = 42
|
159
|
-
```
|
66
|
+
are nice
|
160
67
|
|
161
|
-
|
162
|
-
end
|
68
|
+
## Another header
|
163
69
|
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
default["foo"] = "bar"
|
169
|
-
INPUT
|
170
|
-
expect(ca.to_s).to eq(<<-OUTPUT)
|
171
|
-
my comment
|
70
|
+
doc we won't touch
|
71
|
+
README
|
72
|
+
allow(::File).to receive(:open).and_yield(readme)
|
73
|
+
expect(readme).to receive(:write).with(<<-README)
|
172
74
|
|
173
|
-
|
174
|
-
default["ignored"]["thing"] = 33 # a useful inline comment
|
175
|
-
default["foo"] = "bar"
|
176
|
-
```
|
75
|
+
## Attributes
|
177
76
|
|
178
|
-
|
179
|
-
end
|
77
|
+
foo
|
180
78
|
|
181
|
-
|
182
|
-
ca = ChefAttrdoc::AttributesFile.new(<<-INPUT)
|
183
|
-
# my comment
|
184
|
-
default["ignored"]["thing"] = 33 # TODO(tommy) an ignored inline comment
|
185
|
-
default["foo"] = "bar"
|
186
|
-
INPUT
|
187
|
-
expect(ca.to_s).to eq(<<-OUTPUT)
|
188
|
-
my comment
|
79
|
+
## Another header
|
189
80
|
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
OUTPUT
|
81
|
+
doc we won't touch
|
82
|
+
README
|
83
|
+
ChefAttrdoc.write_readme('filename', "foo\n")
|
84
|
+
end
|
85
|
+
end
|
196
86
|
end
|
197
87
|
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
foo
|
202
|
-
|
203
|
-
default['something'] = 'bad' # foo
|
204
|
-
default['just']['more'] = 'code'
|
205
|
-
INPUT
|
206
|
-
expect(ca.to_s).to eq(<<-OUTPUT)
|
207
|
-
something good
|
208
|
-
|
209
|
-
```ruby
|
210
|
-
foo = bar
|
211
|
-
```
|
212
|
-
|
213
|
-
OUTPUT
|
88
|
+
describe '#attrs_contents' do
|
89
|
+
it 'reads the files in the directory and returns their contents' do
|
90
|
+
expect(ChefAttrdoc.attrs_contents(['spec', 'fixtures']))
|
91
|
+
.to eq([["file1.rb", "foo\n"], ["file3.rb", "baz\n"]])
|
92
|
+
end
|
214
93
|
end
|
215
94
|
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
foo
|
220
|
-
|
221
|
-
# comment we want to keep
|
222
|
-
# still good
|
95
|
+
describe '#process_attributes' do
|
96
|
+
it 'reads the files in the directory and processes them' do
|
97
|
+
allow(ChefAttrdoc).to receive(:attrs_contents).with('foodir')
|
98
|
+
.and_return([["file1.rb", "foo\n"], ["file3.rb", "baz\n"]])
|
223
99
|
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
100
|
+
allow_any_instance_of(ChefAttrdoc::AttributesFile).to receive(:to_s)
|
101
|
+
.and_return("qux\n")
|
102
|
+
expect(ChefAttrdoc.process_attributes('foodir'))
|
103
|
+
.to eq(<<-OUTPUT)
|
104
|
+
## file1.rb
|
229
105
|
|
230
|
-
|
231
|
-
foo = bar
|
232
|
-
```
|
106
|
+
qux
|
233
107
|
|
234
|
-
|
235
|
-
still good
|
236
|
-
|
237
|
-
foo bar
|
238
|
-
|
239
|
-
```ruby
|
240
|
-
foo = bar
|
241
|
-
```
|
108
|
+
## file3.rb
|
242
109
|
|
110
|
+
qux
|
243
111
|
OUTPUT
|
112
|
+
end
|
244
113
|
end
|
245
114
|
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# Copyright 1970, nobody
|
2
|
+
|
3
|
+
# this is the attribute
|
4
|
+
default['some']['attribute'] = 'foo'
|
5
|
+
|
6
|
+
default['this']['will']['be'] = 'ignored'
|
7
|
+
|
8
|
+
# NOTE code blocks without a comment are ignored as are those beginning
|
9
|
+
# NOTE with 'NOTE', 'XXX', 'TODO' or foodcritic comments
|
10
|
+
|
11
|
+
# a longer block of code
|
12
|
+
case something
|
13
|
+
when 'foo'
|
14
|
+
default['some']['foo'] = 'baz'
|
15
|
+
else
|
16
|
+
default['some']['foo'] = 'qux'
|
17
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
foo
|
data/spec/fixtures/file2
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
bar
|
@@ -0,0 +1 @@
|
|
1
|
+
baz
|
@@ -0,0 +1,45 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
|
3
|
+
# Copyright 2014, Ionuț Arțăriși <ionut@artarisi.eu>
|
4
|
+
#
|
5
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
6
|
+
# you may not use this file except in compliance with the License.
|
7
|
+
# You may obtain a copy of the License at
|
8
|
+
#
|
9
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
10
|
+
#
|
11
|
+
# Unless required by applicable law or agreed to in writing, software
|
12
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
13
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
14
|
+
# See the License for the specific language governing permissions and
|
15
|
+
# limitations under the License.
|
16
|
+
#
|
17
|
+
|
18
|
+
require 'chef_attrdoc'
|
19
|
+
|
20
|
+
describe 'This is the example from chef_attrdoc\'s README.md' do
|
21
|
+
it 'has the a fixed output' do
|
22
|
+
output = `ruby -Ilib bin/chef_attrdoc spec/fixtures/cookbook-example/ -s`
|
23
|
+
expect(output).to eq(<<-OUTPUT)
|
24
|
+
## default.rb
|
25
|
+
|
26
|
+
this is the attribute
|
27
|
+
|
28
|
+
```ruby
|
29
|
+
default['some']['attribute'] = 'foo'
|
30
|
+
```
|
31
|
+
|
32
|
+
a longer block of code
|
33
|
+
|
34
|
+
```ruby
|
35
|
+
case something
|
36
|
+
when 'foo'
|
37
|
+
default['some']['foo'] = 'baz'
|
38
|
+
else
|
39
|
+
default['some']['foo'] = 'qux'
|
40
|
+
end
|
41
|
+
```
|
42
|
+
|
43
|
+
OUTPUT
|
44
|
+
end
|
45
|
+
end
|
metadata
CHANGED
@@ -1,16 +1,48 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: chef_attrdoc
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
5
|
-
prerelease:
|
4
|
+
version: 1.0.0.pre
|
5
|
+
prerelease: 6
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
8
8
|
- Ionuț Arțăriși
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2014-
|
13
|
-
dependencies:
|
12
|
+
date: 2014-08-20 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: rake
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '0'
|
22
|
+
type: :development
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ! '>='
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '0'
|
30
|
+
- !ruby/object:Gem::Dependency
|
31
|
+
name: rspec
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
33
|
+
none: false
|
34
|
+
requirements:
|
35
|
+
- - ! '>='
|
36
|
+
- !ruby/object:Gem::Version
|
37
|
+
version: '0'
|
38
|
+
type: :development
|
39
|
+
prerelease: false
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ! '>='
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: '0'
|
14
46
|
description: Generate README.md docs from Chef cookbook attributes files
|
15
47
|
email:
|
16
48
|
- ionut@artarisi.eu
|
@@ -20,6 +52,9 @@ extensions: []
|
|
20
52
|
extra_rdoc_files: []
|
21
53
|
files:
|
22
54
|
- .rspec
|
55
|
+
- .travis.yml
|
56
|
+
- Gemfile
|
57
|
+
- Gemfile.lock
|
23
58
|
- LICENSE
|
24
59
|
- README.md
|
25
60
|
- Rakefile
|
@@ -27,7 +62,14 @@ files:
|
|
27
62
|
- chef_attrdoc.gemspec
|
28
63
|
- lib/chef_attrdoc.rb
|
29
64
|
- lib/chef_attrdoc/version.rb
|
65
|
+
- spec/attributes_file_spec.rb
|
30
66
|
- spec/chef_attrdoc_spec.rb
|
67
|
+
- spec/fixtures/cookbook-example/README.md
|
68
|
+
- spec/fixtures/cookbook-example/attributes/default.rb
|
69
|
+
- spec/fixtures/file1.rb
|
70
|
+
- spec/fixtures/file2
|
71
|
+
- spec/fixtures/file3.rb
|
72
|
+
- spec/readme_example_spec.rb
|
31
73
|
- spec/spec_helper.rb
|
32
74
|
homepage: https://github.com/mapleoin/chef_attrdoc
|
33
75
|
licenses:
|
@@ -45,9 +87,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
45
87
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
46
88
|
none: false
|
47
89
|
requirements:
|
48
|
-
- - ! '
|
90
|
+
- - ! '>'
|
49
91
|
- !ruby/object:Gem::Version
|
50
|
-
version:
|
92
|
+
version: 1.3.1
|
51
93
|
requirements: []
|
52
94
|
rubyforge_project:
|
53
95
|
rubygems_version: 1.8.23
|
@@ -55,6 +97,13 @@ signing_key:
|
|
55
97
|
specification_version: 3
|
56
98
|
summary: Generate README.md docs from Chef cookbook attributes files
|
57
99
|
test_files:
|
100
|
+
- spec/attributes_file_spec.rb
|
58
101
|
- spec/chef_attrdoc_spec.rb
|
102
|
+
- spec/fixtures/cookbook-example/README.md
|
103
|
+
- spec/fixtures/cookbook-example/attributes/default.rb
|
104
|
+
- spec/fixtures/file1.rb
|
105
|
+
- spec/fixtures/file2
|
106
|
+
- spec/fixtures/file3.rb
|
107
|
+
- spec/readme_example_spec.rb
|
59
108
|
- spec/spec_helper.rb
|
60
109
|
has_rdoc:
|