Skip to content

Commit 8236b37

Browse files
committed
(maint) implement desc/docs fallback
This implements the changes specified in puppetlabs/puppet-specifications#141 > The text and examples have been inconsistent with how `desc` vs `docs` > has been handled. This change fixes the text and examples to all show > and require `desc`, but accept `docs` in places where we showed it > previously.
1 parent 6e155bb commit 8236b37

File tree

8 files changed

+111
-39
lines changed

8 files changed

+111
-39
lines changed

lib/puppet/resource_api.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,8 @@ def register_type(definition)
3535
end
3636

3737
Puppet::Type.newtype(definition[:name].to_sym) do
38-
@docs = definition[:docs]
3938
@type_definition = type_def
39+
@docs = type_def.desc
4040

4141
# Keeps a copy of the provider around. Weird naming to avoid clashes with puppet's own `provider` member
4242
define_singleton_method(:my_provider) do

lib/puppet/resource_api/transport.rb

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,16 @@ module Puppet::ResourceApi; end # rubocop:disable Style/Documentation
33
# Remote target transport API
44
module Puppet::ResourceApi::Transport
55
def register(schema)
6-
unless transports[schema[:name]].nil?
6+
definition = Puppet::ResourceApi::TransportSchemaDef.new(schema)
7+
8+
unless transports[definition.name].nil?
79
raise Puppet::DevError, 'Transport `%{name}` is already registered for `%{environment}`' % {
8-
name: schema[:name],
10+
name: definition.name,
911
environment: current_environment,
1012
}
1113
end
12-
transports[schema[:name]] = Puppet::ResourceApi::TransportSchemaDef.new(schema)
14+
15+
transports[schema[:name]] = definition
1316
end
1417
module_function :register # rubocop:disable Style/AccessModifierDeclarations
1518

lib/puppet/resource_api/type_definition.rb

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -90,11 +90,27 @@ def namevars
9090
}.keys
9191
end
9292

93+
def desc
94+
definition[:desc]
95+
end
96+
9397
def validate_schema(definition, attr_key)
9498
raise Puppet::DevError, '%{type_class} must be a Hash, not `%{other_type}`' % { type_class: self.class.name, other_type: definition.class } unless definition.is_a?(Hash)
95-
@attributes = definition[attr_key]
9699
raise Puppet::DevError, '%{type_class} must have a name' % { type_class: self.class.name } unless definition.key? :name
97-
raise Puppet::DevError, '%{type_class} must have `%{attr_key}`' % { type_class: self.class.name, attrs: attr_key } unless definition.key? attr_key
100+
raise Puppet::DevError, '`%{name}` must have `%{attrs}`' % { name: definition[:name], attrs: attr_key } unless definition.key? attr_key
101+
102+
# fixup desc/docs backwards compatibility
103+
if definition.key? :docs
104+
if definition[:desc]
105+
raise Puppet::DevError, '`%{name}` has both `desc` and `docs`, prefer using `desc`' % { name: definition[:name] }
106+
end
107+
definition[:desc] = definition[:docs]
108+
definition.delete(:docs)
109+
end
110+
111+
Puppet.warning('`%{name}` has no documentation, add it using a `desc` key' % { name: definition[:name] }) unless definition.key? :desc
112+
113+
@attributes = definition[attr_key]
98114
unless attributes.is_a?(Hash)
99115
raise Puppet::DevError, '`%{name}.%{attrs}` must be a hash, not `%{other_type}`' % {
100116
name: definition[:name], attrs: attr_key, other_type: attributes.class
@@ -104,7 +120,7 @@ def validate_schema(definition, attr_key)
104120
attributes.each do |key, attr|
105121
raise Puppet::DevError, "`#{definition[:name]}.#{key}` must be a Hash, not a #{attr.class}" unless attr.is_a? Hash
106122
raise Puppet::DevError, "`#{definition[:name]}.#{key}` has no type" unless attr.key? :type
107-
Puppet.warning("`#{definition[:name]}.#{key}` has no docs") unless attr.key? :desc
123+
Puppet.warning("`#{definition[:name]}.#{key}` has no documentation, add it using a `desc` key") unless attr.key? :desc
108124

109125
# validate the type by attempting to parse into a puppet type
110126
@data_type_cache[attributes[key][:type]] ||=

spec/puppet/resource_api/base_context_spec.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ def send_log(log, msg)
1313
TestContext.new(definition)
1414
end
1515

16-
let(:definition_hash) { { name: 'some_resource', attributes: { name: { type: 'String', desc: 'message' } }, features: feature_support } }
16+
let(:definition_hash) { { name: 'some_resource', desc: 'a test resource', attributes: { name: { type: 'String', desc: 'message' } }, features: feature_support } }
1717
let(:definition) { Puppet::ResourceApi::TypeDefinition.new(definition_hash) }
1818
let(:feature_support) { [] }
1919

spec/puppet/resource_api/base_type_definition_spec.rb

Lines changed: 60 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -4,22 +4,25 @@
44
subject(:type) { described_class.new(definition, :attributes) }
55

66
let(:definition) do
7-
{ name: 'some_resource', attributes: {
8-
ensure: {
9-
type: 'Enum[present, absent]',
10-
desc: 'Whether this resource should be present or absent on the target system.',
11-
default: 'present',
7+
{ name: 'some_resource',
8+
desc: 'a test type',
9+
attributes: {
10+
ensure: {
11+
type: 'Enum[present, absent]',
12+
desc: 'Whether this resource should be present or absent on the target system.',
13+
default: 'present',
14+
},
15+
name: {
16+
type: 'String',
17+
desc: 'The name of the resource you want to manage.',
18+
behaviour: :namevar,
19+
},
20+
prop: {
21+
type: 'Integer',
22+
desc: 'A mandatory property, that MUST NOT be validated on deleting.',
23+
},
1224
},
13-
name: {
14-
type: 'String',
15-
desc: 'The name of the resource you want to manage.',
16-
behaviour: :namevar,
17-
},
18-
prop: {
19-
type: 'Integer',
20-
desc: 'A mandatory property, that MUST NOT be validated on deleting.',
21-
},
22-
}, features: feature_support }
25+
features: feature_support }
2326
end
2427
let(:feature_support) { [] }
2528

@@ -76,6 +79,7 @@
7679
let(:definition) do
7780
{
7881
name: 'some_transport',
82+
desc: 'a test transport',
7983
connection_info: {
8084
username: {
8185
type: 'String',
@@ -191,49 +195,80 @@
191195
end
192196

193197
describe '#validate_schema' do
198+
let(:definition) { { name: 'some_resource', desc: 'a test resource', attributes: attributes } }
199+
194200
context 'when the type definition does not have a name' do
195-
let(:definition) { { attributes: 'some_string' } }
201+
let(:definition) { { desc: 'a test resource', attributes: {} } }
196202

197203
it { expect { type }.to raise_error Puppet::DevError, %r{must have a name} }
198204
end
199205

206+
context 'when the type definition does not have a desc' do
207+
let(:definition) { { name: 'some_resource', attributes: {} } }
208+
209+
it {
210+
expect(Puppet).to receive(:warning).with('`some_resource` has no documentation, add it using a `desc` key')
211+
type
212+
}
213+
end
214+
200215
context 'when attributes is not a hash' do
201-
let(:definition) { { name: 'some_resource', attributes: 'some_string' } }
216+
let(:attributes) { 'some_string' }
202217

203218
it { expect { type }.to raise_error Puppet::DevError, %r{`some_resource.attributes` must be a hash} }
204219
end
205220

206221
context 'when an attribute is not a hash' do
207-
let(:definition) { { name: 'some_resource', attributes: { name: 'some_string' } } }
222+
let(:attributes) { { name: 'some_string' } }
208223

209224
it { expect { type }.to raise_error Puppet::DevError, %r{`some_resource.name` must be a Hash} }
210225
end
211226

212227
context 'when an attribute has no type' do
213-
let(:definition) { { name: 'some_resource', attributes: { name: { desc: 'message' } } } }
228+
let(:attributes) { { name: { desc: 'message' } } }
214229

215230
it { expect { type }.to raise_error Puppet::DevError, %r{has no type} }
216231
end
217232

218-
context 'when an attribute has no descrption' do
219-
let(:definition) { { name: 'some_resource', attributes: { name: { type: 'String' } } } }
233+
context 'when an attribute has no description' do
234+
let(:attributes) { { name: { type: 'String' } } }
220235

221-
it 'Raises a warning message' do
222-
expect(Puppet).to receive(:warning).with('`some_resource.name` has no docs')
236+
it 'raises a warning message' do
237+
expect(Puppet).to receive(:warning).with('`some_resource.name` has no documentation, add it using a `desc` key')
223238
type
224239
end
225240
end
226241

227242
context 'when an attribute has an unsupported type' do
228-
let(:definition) { { name: 'some_resource', attributes: { name: { type: 'basic' } } } }
243+
let(:definition) { { name: 'some_resource', desc: 'a test resource', attributes: { name: { type: 'basic' } } } }
229244

230245
it { expect { type }.to raise_error %r{<basic> is not a valid type specification} }
231246
end
232247

248+
context 'with deprecated `docs` key' do
249+
let(:definition) { { name: 'some_resource', docs: 'a test resource', attributes: {} } }
250+
251+
it 'does not raise a warning message' do
252+
expect(Puppet).not_to receive(:warning)
253+
type
254+
end
255+
256+
it 'exposes the documentation as `desc`' do
257+
expect(type.desc).to eq 'a test resource'
258+
end
259+
end
260+
261+
context 'with both `docs` and `desc` key' do
262+
let(:definition) { { name: 'some_resource', desc: 'the real description', docs: 'an oversight', attributes: {} } }
263+
264+
it { expect { type }.to raise_error Puppet::DevError, %r{`some_resource` has both `desc` and `docs`, prefer using `desc`} }
265+
end
266+
233267
context 'with both behavior and behaviour' do
234268
let(:definition) do
235269
{
236270
name: 'bad_behaviour',
271+
desc: 'a test type',
237272
attributes: {
238273
name: {
239274
type: 'String',
@@ -251,6 +286,7 @@
251286
let(:definition) do
252287
{
253288
name: 'bad_syntax',
289+
desc: 'a test type',
254290
attributes: {
255291
name: {
256292
type: 'Optional[String',

spec/puppet/resource_api/puppet_context_spec.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
RSpec.describe Puppet::ResourceApi::PuppetContext do
44
subject(:context) { described_class.new(definition) }
55

6-
let(:definition) { { name: 'some_resource', attributes: {} } }
6+
let(:definition) { { name: 'some_resource', desc: 'a test resource', attributes: {} } }
77

88
describe '#device' do
99
context 'when a NetworkDevice is configured' do

spec/puppet/resource_api/transport_spec.rb

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -36,11 +36,18 @@ def change_environment(name = nil)
3636

3737
describe '#register(schema)' do
3838
context 'when registering a schema with missing keys' do
39-
it { expect { described_class.register([]) }.to raise_error(Puppet::DevError, %r{requires a hash as schema}) }
40-
it { expect { described_class.register({}) }.to raise_error(Puppet::DevError, %r{requires a `:name`}) }
41-
it { expect { described_class.register(name: 'no connection info', desc: 'some description') }.to raise_error(Puppet::DevError, %r{requires `:connection_info`}) }
42-
it { expect { described_class.register(name: 'no description') }.to raise_error(Puppet::DevError, %r{requires `:desc`}) }
43-
it { expect { described_class.register(name: 'no hash attributes', desc: 'some description', connection_info: []) }.to raise_error(Puppet::DevError, %r{`:connection_info` must be a hash, not}) }
39+
it { expect { described_class.register([]) }.to raise_error(Puppet::DevError, %r{must be a Hash, not `Array`}) }
40+
it { expect { described_class.register({}) }.to raise_error(Puppet::DevError, %r{must have a name}) }
41+
it { expect { described_class.register(name: 'no connection info', desc: 'some description') }.to raise_error(Puppet::DevError, %r{`no connection info` must have `connection_info`}) }
42+
it do
43+
expect {
44+
described_class.register(name: 'no hash attributes', desc: 'some description', connection_info: [])
45+
}.to raise_error(Puppet::DevError, %r{`no hash attributes.connection_info` must be a hash, not `Array})
46+
end
47+
it 'warns if there is no documentation ' do
48+
expect(Puppet).to receive(:warning).with(%r{has no documentation, add it using a `desc` key})
49+
described_class.register(name: 'no description', connection_info: {})
50+
end
4451
end
4552

4653
context 'when registering a minimal transport' do
@@ -300,6 +307,7 @@ class Wibble; end
300307

301308
it 'validates the connection_info' do
302309
allow(Puppet::ResourceApi::TransportSchemaDef).to receive(:new).with(schema).and_return(schema_def)
310+
allow(schema_def).to receive(:name).with(no_args).and_return('validate')
303311

304312
described_class.register(schema)
305313

@@ -330,6 +338,7 @@ class Wibble; end
330338

331339
before(:each) do
332340
allow(Puppet::ResourceApi::TransportSchemaDef).to receive(:new).with(schema).and_return(schema_def)
341+
allow(schema_def).to receive(:name).with(no_args).and_return('sensitive_transport')
333342
described_class.register(schema)
334343
end
335344

spec/puppet/resource_api_spec.rb

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@
4444
let(:definition) do
4545
{
4646
name: type_name,
47+
desc: 'a test resource',
4748
attributes: {
4849
name: {
4950
type: 'String',
@@ -747,6 +748,7 @@ def set(_context, _changes); end
747748
let(:definition) do
748749
{
749750
name: 'init_behaviour',
751+
desc: 'a test resource',
750752
attributes: {
751753
ensure: {
752754
type: 'Enum[present, absent]',
@@ -1172,7 +1174,7 @@ def set(_context, _changes); end
11721174
context 'when loading a provider that doesn\'t create the correct class' do
11731175
let(:definition) { { name: 'no_class', attributes: {} } }
11741176

1175-
it { expect { described_class.load_provider('no_class') }.to raise_error Puppet::DevError, %r{Puppet::Provider::NoClass::NoClass} }
1177+
it { expect { described_class.load_provider('no_class') }.to raise_error Puppet::DevError, %r{provider class Puppet::Provider::NoClass::NoClass not found} }
11761178
end
11771179

11781180
context 'when loading a provider that creates the correct class' do
@@ -1792,6 +1794,7 @@ def set(_context, changes) end
17921794
let(:definition) do
17931795
{
17941796
name: 'test_noop_support',
1797+
desc: 'a test resource',
17951798
features: ['no such feature'],
17961799
attributes: {},
17971800
}
@@ -1808,6 +1811,7 @@ def set(_context, changes) end
18081811
let(:definition) do
18091812
{
18101813
name: 'test_behaviour',
1814+
desc: 'a test resource',
18111815
attributes: {
18121816
id: {
18131817
type: 'String',
@@ -1824,6 +1828,7 @@ def set(_context, changes) end
18241828
let(:definition) do
18251829
{
18261830
name: 'test_behaviour',
1831+
desc: 'a test resource',
18271832
attributes: {
18281833
param: {
18291834
type: 'String',
@@ -1840,6 +1845,7 @@ def set(_context, changes) end
18401845
let(:definition) do
18411846
{
18421847
name: 'test_behaviour',
1848+
desc: 'a test resource',
18431849
attributes: {
18441850
param_ro: {
18451851
type: 'String',
@@ -1856,6 +1862,7 @@ def set(_context, changes) end
18561862
let(:definition) do
18571863
{
18581864
name: 'test_behaviour',
1865+
desc: 'a test resource',
18591866
attributes: {
18601867
param_ro: {
18611868
type: 'String',
@@ -1872,6 +1879,7 @@ def set(_context, changes) end
18721879
let(:definition) do
18731880
{
18741881
name: 'test_behaviour',
1882+
desc: 'a test resource',
18751883
attributes: {
18761884
source: {
18771885
type: 'String',

0 commit comments

Comments
 (0)