So, found another wrinkle in this:

If the resource doesn't exist on the system yet, and I leave the servers 
attribute out, my validate doesn't catch it:

mytype{'test type':
# servers => ['server1','server2']
}

That should fail the catalog compile since servers is required and it isn't 
set.  My validate code looks like:

validate do
     if(self[:servers])
           fail("Servers must be an array with at least one member") unless 
self[:servers].is_a?(Array) and self[:servers].size > 0
      end
end

I found out that isrequired in the newproperty block doesn't actually do 
anything, so I need some way to detect that the resource doesn't exist yet, 
but the catalog specified by the user is wrong.


On Tuesday, August 11, 2015 at 3:35:13 PM UTC-4, [email protected] wrote:
>
> Okay, so if I understand you right, validate gets called twice:  once 
> without the self hash initialized and once with it initialized.   Seems 
> weird, but I can follow that.    So, I might want to do something like:
>
> if(self[:servers])
>    fail("Servers must be an array with at least one member") unless 
> self[:servers].is_a?(Array) and self[:servers].size > 0
> end
>
> Here's a follow-up then:  how can you tell the difference between self 
> just not being initialized and the user failing to specify the value for a 
> particular property?  I guess I'm mitigating it somewhat by doing:
>
> newproperty(:servers,:array_matching=>:all) do
>     desc "List of database servers; first server in the list will be 
> considered the primary server"
>
>    * isrequired*
>     def insync?(is)
>       return false unless is == should
>       true
>     end
>
>   end
>
> And properties that aren't required wouldn't need to differentiate between 
> not being set and just not initialized yet.
>
> On Tuesday, August 11, 2015 at 2:27:06 PM UTC-4, Hunter Haugen wrote:
>>
>>
>>
>> On Fri, Aug 7, 2015 at 1:48 PM <[email protected]> wrote:
>>
>>> Hi all!
>>>
>>> I'm having trouble with a custom type's type-wide validate call.  I've 
>>> done a lot of digging into the Puppet documentation and a lot of Googling 
>>> and haven't found a lot of guidance.   My Puppet version is 3.7.5.
>>>
>>> Basically, I have a property defined like this in my type:
>>>
>>> newproperty(:servers,:array_matching=>:all) do
>>>     desc "List of database servers; first server in the list will be 
>>> considered the primary server"
>>>
>>>     isrequired
>>>     def insync?(is)
>>>       return false unless is == should
>>>       true
>>>     end
>>>
>>> end
>>>
>>> I want to check that the array is non-empty.   I figured out if I 
>>> specify a validate block inside of the newproperty block then I'll just get 
>>> each individual array member, one at a time, which isn't what I want.   So, 
>>> instead, I implemented a type-wide validate call like this:
>>>
>>> Puppet::Type.newtype(:my_type) do
>>>
>>>     validate do
>>>                fail("servers should have at least one member")  if 
>>> self[:servers].size == 0
>>>     done
>>>
>>
>> It's kind of awkward, but if your type uses self.instances, then in the 
>> validate block is run after self.instances runs and has 
>> resource.provider.servers but not self[:servers]. So I usually just do 
>> something like `if self[:servers] and self[:servers].size == 0` to avoid 
>> validating self.instances stuff.
>>
>> The validate block is then run again when each resource is evaluated, and 
>> that is when self's hash is populated with values from the catalog.
>>
>>>
>>>
>>> When I try to run puppet resource my_type, I get:
>>>
>>> Error: Could not run: undefined method `size' for nil:NilClass
>>>
>>> When I do a pp on self, I get something that looks like (in part):
>>>
>>> #<Puppet::Type::My_type:0x000000035f7528
>>>  @managed=false,
>>>  @name_var_cache=:name,
>>>  @original_parameters=
>>>   {:provider=>
>>>     #<Puppet::Type::My_type::ProviderMy_type:0x000000035d1350
>>>      @property_flush={},
>>>      @property_hash=
>>>       {
>>>        :servers=>["db1"],
>>>        },
>>>      @resource=#<Puppet::Type::My_type:0x000000035f7528 ...>>},
>>>  @parameters=
>>>   {
>>>    *snip*
>>> },
>>>  @provider=
>>>   #<Puppet::Type::My_type::ProviderMy_type:0x000000035d1350
>>>    @property_flush={},
>>>    @property_hash=
>>>     {
>>>      :servers=>["db1"],
>>>      },
>>>    @resource=#<Puppet::Type::My_type:0x000000035f7528 ...>>,
>>>  @tags=
>>>   #<Puppet::Util::TagSet: {"my_type",
>>>    "mytitle"}>,
>>>  @title="mytitle">
>>>
>>> I poked around the types provided by Puppet and it looks like I should 
>>> be able to do
>>>
>>> self[:servers]   
>>>
>>> to access the property, but in practice that doesn't seem to work.  It 
>>> looks like the data I want is buried in the object, but I'm not sure of the 
>>> correct means to get at it.  
>>>
>>>
>>>
>>> -- 
>>> You received this message because you are subscribed to the Google 
>>> Groups "Puppet Users" group.
>>> To unsubscribe from this group and stop receiving emails from it, send 
>>> an email to [email protected].
>>> To view this discussion on the web visit 
>>> https://groups.google.com/d/msgid/puppet-users/5d8ea6d1-1afd-4983-a059-832d238eb6fa%40googlegroups.com
>>>  
>>> <https://groups.google.com/d/msgid/puppet-users/5d8ea6d1-1afd-4983-a059-832d238eb6fa%40googlegroups.com?utm_medium=email&utm_source=footer>
>>> .
>>> For more options, visit https://groups.google.com/d/optout.
>>>
>>

-- 
You received this message because you are subscribed to the Google Groups 
"Puppet Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/puppet-users/02a71e3b-e118-4d25-9535-411d9d610e55%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to