-
Notifications
You must be signed in to change notification settings - Fork 86
/
Copy pathjson_spec.rb
326 lines (283 loc) · 10.6 KB
/
json_spec.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
# frozen_string_literal: true
require 'spec_helper'
require 'puppet-strings/json'
require 'tempfile'
describe PuppetStrings::Json do
before do
# Populate the YARD registry with both Puppet and Ruby source
expect(YARD::Parser::SourceParser.parse_string(<<~SOURCE, :puppet).enumerator.length).to eq(2)
# A simple class.
# @todo Do a thing
# @deprecated No longer supported and will be removed in a future release
# @note Some note
# @param param1 First param.
# @param param2 Second param.
# @param param3 Third param.
class klass(Integer $param1, $param2, String $param3 = hi) inherits foo::bar {
}
# A simple defined type.
# @param param1 First param.
# @param param2 Second param.
# @param param3 Third param.
define dt(Integer $param1, $param2, String $param3 = hi) {
}
SOURCE
expect(YARD::Parser::SourceParser.parse_string(<<~SOURCE, :puppet).enumerator.length).to eq(1) if TEST_PUPPET_PLANS
# A simple plan.
# @param param1 First param.
# @param param2 Second param.
# @param param3 Third param.
plan plann(String $param1, $param2, Integer $param3 = 1) {
}
SOURCE
# Only include Puppet functions for 4.1+
expect(YARD::Parser::SourceParser.parse_string(<<~SOURCE, :puppet).enumerator.length).to eq(1) if TEST_PUPPET_FUNCTIONS
# A simple function.
# @param param1 First param.
# @param param2 Second param.
# @param param3 Third param.
# @return [Undef] Returns nothing.
function func(Integer $param1, $param2, String $param3 = hi) {
}
SOURCE
# Only include Puppet types for 5.0+
expect(YARD::Parser::SourceParser.parse_string(<<~SOURCE, :ruby).enumerator.length).to eq(1) if TEST_PUPPET_DATATYPES
# Basic Puppet Data Type in Ruby
#
# @param msg A message parameter
# @!method func1(param1, param2)
# func1 documentation
# @param [String] param1 param1 documentation
# @param [Integer] param2 param2 documentation
# @return [Optional[String]]
Puppet::DataTypes.create_type('RubyDataType') do
interface <<~'PUPPET'
attributes => {
msg => String[1]
},
functions => {
func1 => Callable[[String, Integer], Optional[String]]
}
PUPPET
end
SOURCE
expect(YARD::Parser::SourceParser.parse_string(<<~SOURCE, :json).enumerator.length).to eq(1)
{
"description": "Allows you to backup your database to local file.",
"input_method": "stdin",
"parameters": {
"database": {
"description": "Database to connect to",
"type": "Optional[String[1]]"
},
"user": {
"description": "The user",
"type": "Optional[String[1]]"
},
"password": {
"description": "The password",
"type": "Optional[String[1]]"
},
"sql": {
"description": "Path to file you want backup to",
"type": "String[1]"
}
}
}
SOURCE
expect(YARD::Parser::SourceParser.parse_string(<<~'SOURCE', :ruby).enumerator.length).to eq(6)
Puppet::Parser::Functions.newfunction(:func3x, doc: <<~'DOC') do |*args|
An example 3.x function.
@param [String] first The first parameter.
@param second The second parameter.
@return [Undef] Returns nothing.
DOC
end
# An example 4.x function.
Puppet::Functions.create_function(:func4x) do
# The first overload.
# @param param1 The first parameter.
# @param param2 The second parameter.
# @param param3 The third parameter.
# @return Returns nothing.
dispatch :foo do
param 'Integer', :param1
param 'Any', :param2
optional_param 'Array[String]', :param3
return_type 'Undef'
end
# @param param The first parameter.
# @param block The block parameter.
# @return Returns a string.
dispatch :other do
param 'Boolean', :param
block_param
return_type 'String'
end
end
# An example 4.x function with only one signature.
Puppet::Functions.create_function(:func4x_1) do
# @param param1 The first parameter.
# @return [Undef] Returns nothing.
dispatch :foobarbaz do
param 'Integer', :param1
end
end
Puppet::Type.type(:database).provide :linux do
desc 'An example provider on Linux.'
confine kernel: 'Linux'
confine osfamily: 'RedHat'
defaultfor :kernel => 'Linux'
defaultfor :osfamily => 'RedHat', :operatingsystemmajrelease => '7'
has_feature :implements_some_feature
has_feature :some_other_feature
commands foo: '/usr/bin/foo'
end
Puppet::Type.newtype(:database) do
desc 'An example database server resource type.'
feature :encryption, 'The provider supports encryption.', methods: [:encrypt]
ensurable do
desc 'What state the database should be in.'
defaultvalues
aliasvalue(:up, :present)
aliasvalue(:down, :absent)
defaultto :up
end
newparam(:address) do
isnamevar
desc 'The database server name.'
end
newparam(:encryption_key, required_features: :encryption) do
desc 'The encryption key to use.'
end
newparam(:encrypt, :parent => Puppet::Parameter::Boolean) do
desc 'Whether or not to encrypt the database.'
defaultto false
end
newproperty(:file) do
desc 'The database file to use.'
end
newproperty(:log_level) do
desc 'The log level to use.'
newvalue(:debug)
newvalue(:warn)
newvalue(:error)
defaultto 'warn'
end
end
Puppet::ResourceApi.register_type(
name: 'apt_key',
docs: <<~'EOS',
@summary Example resource type using the new API.
@raise SomeError
This type provides Puppet with the capabilities to manage GPG keys needed
by apt to perform package validation. Apt has it's own GPG keyring that can
be manipulated through the `apt-key` command.
@example here's an example
apt_key { '6F6B15509CF8E59E6E469F327F438280EF8D349F':
source => 'http://apt.puppetlabs.com/pubkey.gpg'
}
**Autorequires**:
If Puppet is given the location of a key file which looks like an absolute
path this type will autorequire that file.
EOS
attributes: {
ensure: {
type: 'Enum[present, absent]',
desc: 'Whether this apt key should be present or absent on the target system.'
},
id: {
type: 'Variant[Pattern[/\A(0x)?[0-9a-fA-F]{8}\Z/], Pattern[/\A(0x)?[0-9a-fA-F]{16}\Z/], Pattern[/\A(0x)?[0-9a-fA-F]{40}\Z/]]',
behaviour: :namevar,
desc: 'The ID of the key you want to manage.',
},
# ...
created: {
type: 'String',
behaviour: :read_only,
desc: 'Date the key was created, in ISO format.',
},
},
autorequires: {
file: '$source', # will evaluate to the value of the `source` attribute
package: 'apt',
},
)
SOURCE
end
RSpec.shared_examples 'correct JSON' do
it 'includes data for Puppet Classes' do
expected = YARD::Registry.all(:puppet_class).sort_by!(&:name).map!(&:to_hash).to_json
actual = capture_output { described_class.render(nil) }
expect(actual[:stdout]).to include_json(expected)
end
it 'includes data for Puppet Data Types' do
expected = YARD::Registry.all(:puppet_data_type).sort_by!(&:name).map!(&:to_hash).to_json
actual = capture_output { described_class.render(nil) }
expect(actual[:stdout]).to include_json(expected)
end
it 'includes data for Puppet Defined Types' do
expected = YARD::Registry.all(:puppet_defined_type).sort_by!(&:name).map!(&:to_hash).to_json
actual = capture_output { described_class.render(nil) }
expect(actual[:stdout]).to include_json(expected)
end
it 'includes data for Puppet Resource Types' do
expected = YARD::Registry.all(:puppet_type).sort_by!(&:name).map!(&:to_hash).to_json
actual = capture_output { described_class.render(nil) }
expect(actual[:stdout]).to include_json(expected)
end
it 'includes data for Puppet Providers' do
expected = YARD::Registry.all(:puppet_provider).sort_by!(&:name).map!(&:to_hash).to_json
actual = capture_output { described_class.render(nil) }
expect(actual[:stdout]).to include_json(expected)
end
it 'includes data for Puppet Functions', if: TEST_PUPPET_FUNCTIONS do
expected = YARD::Registry.all(:puppet_function).sort_by!(&:name).map!(&:to_hash).to_json
actual = capture_output { described_class.render(nil) }
expect(actual[:stdout]).to include_json(expected)
end
it 'includes data for Puppet Tasks' do
expected = YARD::Registry.all(:puppet_task).sort_by!(&:name).map!(&:to_hash).to_json
actual = capture_output { described_class.render(nil) }
expect(actual[:stdout]).to include_json(expected)
end
it 'includes data for Puppet Plans', if: TEST_PUPPET_PLANS do
expected = YARD::Registry.all(:puppet_plan).sort_by!(&:name).map!(&:to_hash).to_json
actual = capture_output { described_class.render(nil) }
expect(actual[:stdout]).to include_json(expected)
end
end
describe 'rendering JSON to a file' do
let(:json_output) do
json_output = nil
Tempfile.open('json') do |file|
described_class.render(file.path)
json_output = File.read(file.path)
end
json_output
end
include_examples 'correct JSON'
end
describe 'rendering JSON to stdout' do
include_examples 'correct JSON'
end
end
# Helper method to capture stdout and stderr from a block
# Source: https://gist.github.com/herrphon/2d2ebbf23c86a10aa955
#
# @param [Proc] block The block to capture output from
# @return [Hash] A hash containing the captured output
def capture_output(&)
begin
$stdout = StringIO.new
$stderr = StringIO.new
yield
result = {}
result[:stdout] = $stdout.string
result[:stderr] = $stderr.string
ensure
$stdout = STDOUT
$stderr = STDERR
end
result
end