rspec, type, provider ...where to put which code

49 views
Skip to first unread message

Johan De Wit

unread,
Nov 19, 2013, 5:09:55 AM11/19/13
to puppe...@googlegroups.com
Hi,

I should have payed much more attention in the programming lessons, or
maybe it is because I took them too long ago ...

I'm trying to write a custom type, and I started with writing the rspec
first, then the type definition, and somewhere in the future, i will
have to write the providers.

I'm currently struggling with the following property : (it is openldap
related)

I want to manage the configuration settings : 'olcAllow' witch contains
a space separated list of keywords like "bind_v2 bind_anon_cred"

in the manifest it should say :

class myldap {

ldapconfig { 'config0':
allow => ['bind_v2', 'bind_anon_cred'],
...
}

In the rspec file, i defined :

it "should accept property allow" do
@test = Puppet::Type.type(:ldapconfig).new(:name => 'config',
property => ['bind_v2', 'bind_anon_cred'] )
@test[property].should == ['bind_v2', 'bind_anon_cred']
end

And in the type code :

newproperty(:allows, :array_matching => :all) do
desc "Specify a set of features to be allowed."
newvalues(:bind_v2, :bind_anon_cred, :bind_anon_dn, :update_anon,
:none)
defaultto(:none)
.....
end


Running the unit test in this case will fail, because the array strings
are converted to labels.

My question now, what is the proper way to solve this ?

a: the rspec should test for the array with labels, and postpone
conversion to the provider code.
b. Already translate the value provided in the manifest to the final
required output, in this case, the array will be converted to a sorted
string of space separated allowed keyboards.

I'm leaning towards b. This gives the possibility to do more accurate
value checking of the parameters, and error will be catched during
catalog compilation. On the other hand, the provider could validate the
values using in this case the installed ldap utilities for testing, and
errors will generate a runtime error when executing the catalog on the
client. But i don't like the possibility to misconfigure, and break the
ldap configuration by a puppet run.

I still have not a clue what should go in the provider code, and what
should be handled by the type definition. But it feels right to me too
do all validation and data transformation.

Grts

johan

--
Johan De Wit

Open Source Consultant

Red Hat Certified Engineer (805008667232363)
Puppet Certified Professional 2013 (PCP0000006)
_________________________________________________________

Open-Future Phone +32 (0)2/255 70 70
Zavelstraat 72 Fax +32 (0)2/255 70 71
3071 KORTENBERG Mobile +32 (0)474/42 40 73
BELGIUM http://www.open-future.be
_________________________________________________________


Next Events:
Puppet Advanced Training | https://www.open-future.be/puppet-advanced-training-12-till-14th-november
Zabbix Certified Training | http://www.open-future.be/zabbix-certified-training-18-till-20th-november
Zabbix Large Environments Training | http://www.open-future.be/zabbix-large-environments-training-21-till-22nd-november
Puppet Fundamentals Training | http://www.open-future.be/puppet-fundamentals-training-10-till-12th-december
Subscribe to our newsletter | http://eepurl.com/BUG8H

Stefan Schulte

unread,
Nov 21, 2013, 4:16:57 PM11/21/13
to puppe...@googlegroups.com
I'd go with a) here. If the list of possible values is not provider
specific but specific to the resource type, the `newvalues` function is
the way to go. And as you already noticed your type spec would then read
something like

it "should allow bind_v2" do
described_class.new(:name => 'config',:allow =>
'bind_v2')[:allow].should == [ :bind_v2 ]
end

it "should not allow foo" do
expect { described_class.new(:name => 'config',:allow => 'foo')
}.to raise_error Puppet::Error, /some error message/
end

So you would expect the value to turn into an array of symbols, even
though the user passed strings or an array of strings. This makes also
sense to test because you know what the provider will receive.

e.g. if you write a provider to receive the current value

def allow
# has to return the current value as an array of symbols
# because you know the current value will be compared
# against the should-value of the resource and that is always
# an array of symbols (as shown in your tests)
end

and set a new value

def allow=(new_value)
# because of your test above you already know that new_value
# (the should-value) is always an array of symbols, eventhough the
# user may have passed a single value, e.g. `allow => bind_v2`
end

> I'm leaning towards b. This gives the possibility to do more accurate
> value checking of the parameters, and error will be catched during
> catalog compilation.

b) will also lead to a compilation error if the user specifies an
invalid value. And if your provider has to transform the data (e.g. turn
the array of symbols into a space seperated list) you should test the
correct behaviour and write tests for your setter methods of your provider
Reply all
Reply to author
Forward
0 new messages