Modifying property names

51 views
Skip to first unread message

Geoffrey Gardella

unread,
Dec 2, 2014, 12:06:29 AM12/2/14
to puppe...@googlegroups.com
I am working on updating types/providers for new functionality in Solaris. I need to take a list of properties (not their values) and modify them before any operations (checking current values, etc). Specifically, I will need to substitute '-' for '_' in the property names. What is the proper place for me to do this? In the provider or type? I am very new to Puppet, and don't want to implement a solution that isn't done the right way.

I know I'm being a bit vague, but this is in response to functional changes in Solaris, which aren't even integrated yet.

Thanks,
Geoffrey

Josh Cooper

unread,
Dec 2, 2014, 1:09:47 AM12/2/14
to puppe...@googlegroups.com
On Mon, Dec 1, 2014 at 9:06 PM, Geoffrey Gardella <gard...@gmail.com> wrote:
I am working on updating types/providers for new functionality in Solaris. I need to take a list of properties (not their values) and modify them before any operations (checking current values, etc). Specifically, I will need to substitute '-' for '_' in the property names. What is the proper place for me to do this? In the provider or type? I am very new to Puppet, and don't want to implement a solution that isn't done the right way.

I know I'm being a bit vague, but this is in response to functional changes in Solaris, which aren't even integrated yet.

Assuming this is a static list of properties, then you would define the list of properties in the type, e.g. newproperty(:property_one), and then define getter and setters in the provider:

def property_one
  # retrieve the value
end

def property_one=(value)
  # set the new value
end

That assumes each property can be independently managed. If you need both property_one and property_two to be set before you apply the changes to the underlying native resource, then you'd want the setters to store the new values:

def property_one=(value)
  @one = value
end

def property_two=(value)
  @two = value
end

and implement a `flush` method to update the resource with all of the new values.

def flush
  # save resource using @one & @two
end

Josh

--
Josh Cooper
Developer, Puppet Labs

Join us at PuppetConf 2015, October 5-9 in Portland, OR - http://2015.puppetconf.com.  
Register early to save 40%!

Geoffrey Gardella

unread,
Dec 2, 2014, 5:53:42 PM12/2/14
to puppe...@googlegroups.com
Hey Josh, thanks for the reply.

I'm still struggling with this. I have a hash of the values passed in from the manifest with the keys including '_' which need to be re-written.

  properties => {'john_wayne' => '1', 'liberty_valance' => '0', ...}

this needs to become:

  properties => {'john-wayne' => '1', 'liberty-valance' => '0', ...}

I believe this is where they are defined in my type:

newproperty(:properties) do
   desc "A hash table of propname=propvalue entries to apply to the link"
end

So, I should write a method in the type to re-write the keys? Something like (forgive my ruby too):

       def modify_keys(h)
          h.keys.each do |k|
              if(k.include? '_') then
                h[k.gsub(/_/, '-')] = h[k]
                h.delete(k)
              end
          end
       end

Can I add a method like this to my property? How is such a method then called in the provider?

Thanks,
Geoffrey

John Bollinger

unread,
Dec 3, 2014, 3:39:32 PM12/3/14
to puppe...@googlegroups.com


On Tuesday, December 2, 2014 4:53:42 PM UTC-6, Geoffrey Gardella wrote:
Hey Josh, thanks for the reply.

I'm still struggling with this. I have a hash of the values passed in from the manifest with the keys including '_' which need to be re-written.

  properties => {'john_wayne' => '1', 'liberty_valance' => '0', ...}

this needs to become:

  properties => {'john-wayne' => '1', 'liberty-valance' => '0', ...}

I believe this is where they are defined in my type:

newproperty(:properties) do
   desc "A hash table of propname=propvalue entries to apply to the link"
end

So, I should write a method in the type to re-write the keys? Something like (forgive my ruby too):

       def modify_keys(h)
          h.keys.each do |k|
              if(k.include? '_') then
                h[k.gsub(/_/, '-')] = h[k]
                h.delete(k)
              end
          end
       end

Can I add a method like this to my property? How is such a method then called in the provider?



It looks like you want to use the munge hook.  Though the docs are a bit unclear, I think it works for property definitions (not just for parameter definitions).  You would put something like this inside your property definition:

      munge do |value|
        value.inject({}) do |xlated, kv|
k, v = kv
xlated[
k.gsub(/_/, '-')] = v
end
end

Note that that assumes the value is a hash; you may want to use the validation hook as well to ensure that (or else munge more flexibly).


John

Geoffrey Gardella

unread,
Dec 10, 2014, 3:26:13 PM12/10/14
to puppe...@googlegroups.com
Hi John,
thanks for the pointer. That has gotten me a bit farther. I'm running into a new set of problems. The keys of a hash are frozen, so doing:

         munge do |value_hash|
            value_hash.inject(value_hash) do |memo,(key,value)|
                key.gsub!(/_/, '-')
                memo
            end
         end

Gives me:

Munging failed for value {...} in class properties: can't modify frozen String

I see you are setting a new key=>value pair (and I guess I'd delete the old), but when I try that I get:

Munging failed for value {...} in class properties: can't add a new key into hash during iteration

I can't imagine this is the first time somebody has tried this, but haven't found anything in the code base.

Geoffrey

Geoffrey Gardella

unread,
Dec 11, 2014, 11:22:41 AM12/11/14
to puppe...@googlegroups.com
Okay, I see. I can't add new keys while I am iterating, which makes sense. So, I need to create a new hash and then do a .merge when I'm done.

John Bollinger

unread,
Dec 11, 2014, 4:10:10 PM12/11/14
to puppe...@googlegroups.com


On Thursday, December 11, 2014 10:22:41 AM UTC-6, Geoffrey Gardella wrote:
Okay, I see. I can't add new keys while I am iterating, which makes sense. So, I need to create a new hash and then do a .merge when I'm done.



No, you don't quite see.  Puppet variables cannot (should not) be modified once set.  You are not out to modify the existing hash or its keys; instead, you are creating a new one to your specification.  The code I offered you is right (or very close to it) exactly as it is.


John

Reply all
Reply to author
Forward
0 new messages