Problems with custom type and provider, resulting file doesn't get updated

33 views
Skip to first unread message

Michael K

unread,
Mar 28, 2012, 7:54:41 AM3/28/12
to puppet...@googlegroups.com
Hello Everyone,

I've implemented a custom type and provider to generate a file, but am having some trouble with getting it to work right. Googling, reading the docs and searching the group here haven't led to a solution, so I decided to ask for help.

As I said I've created a custom type and provided, it's purpose is to generate a site specific Oracle tnsnames.ora. It allows you to specify a fully qualified path and an array of Oracle databases. As is, it works, but only during the "first" puppet run. If I make changes to either the path, or list of Oracle databases, the file doesn't get updated. Can anyone tell me what I'm doing wrong, or point me in the right direction? Any help will be appreciated.

Thanx, Michael

The type is implemented as follows:

Puppet::Type.newtype(:tnsnames) do
 
  ensurable

  newparam(:path) do

    isnamevar

    validate do |value|
      raise ArgumentError, "Empty values are not allowed" if value == ""
    end
  end

  newparam(:dbnames, :array_matching => :all) do

    validate do |value|
      raise ArgumentError, "Empty values are not allowed" if value == ""
    end
  end

end

The provider looks like this:

require 'fileutils'

Puppet::Type.type(:tnsnames).provide(:tnsnames) do

  def create
    tnsnames_content=""

    # code to fill tnsnames_content deleted to protect the innocent
      
    begin   
      if tnsnames_content != "":
        FileUtils.rm_rf resource[:path]
        f = File.new(resource[:path], 'w')
        f.write(tnsnames_content)
        f.close()
      end
    rescue Puppet::ExecutionFailure => detail
      raise Puppet::Error, "Could not create tnsnames file: #{detail}"
    end
  end

  def destroy
    FileUtils.rm_rf resource[:path]
  end

  def exists?
    File.file? resource[:path]
  end
end

deet

unread,
Mar 28, 2012, 11:27:27 AM3/28/12
to Puppet Users

>   def exists?
>     File.file? resource[:path]
>   end
> end


Michael.
It looks like in your exists? method you are just checking that the
tnsnames.ora file exists. So if that file is present the exists?
method returns a true which is saying that the resource is present and
accurate. In the exists? method you would need to parse the
tnsnames.ora file and compare the contents against what is desired.
If the contents of the tnsnames.ora are accurate then return true.

I'm not an expert in types/providers so you may want to validate my
input by inspecting existing types that kind of work the same way like
host or ssh_authorized_keys.
HTH. Derek.

Michael K

unread,
Mar 28, 2012, 11:42:32 AM3/28/12
to puppet...@googlegroups.com
Hello Derek,

Thanks for the quick reply. I've been thinking along those lines as well, create a md5 sum or something of both the file and my newly created content string. Problem is: is this the correct way to do it? I've found multiple type & provider examples on github which DO NOT do this. Are they all inherently broken? Could someone confirm or deny this?

I'll have a look and see if I can find the types (host and ssh_authorized_keys) you are referring to.

Many thanks,

Michael

Nan Liu

unread,
Mar 28, 2012, 12:36:30 PM3/28/12
to puppet...@googlegroups.com
On Wed, Mar 28, 2012 at 8:42 AM, Michael K <mkie...@googlemail.com> wrote:
> Hello Derek,
>
> Thanks for the quick reply. I've been thinking along those lines as well,
> create a md5 sum or something of both the file and my newly created content
> string. Problem is: is this the correct way to do it? I've found multiple
> type & provider examples on github which DO NOT do this. Are they all
> inherently broken? Could someone confirm or deny this?

I'm not familiar with the format of this file, so I'm not sure why
custom provider is preferable over a native file type in puppet or
concat file using templates.

self.exists? is correct. In this case you are just checking if the
file exists to determine whether to invoke create/destroy method. If
you ensure=>present and the file does not exist it will invoke create,
and if you ensure=>absent, and the file exist it will invoke destroy.
The reason the content of the file is not managed is because dbnames
is a parameter and not a property. If you want to manage the content
of the file you need specify dbnames as a property and implement def
dbnames in the provider to retrieve the file content for comparison
and def dbnames=(value) to update the content of the file if it no
longer matches your desired content value.

See Brice blog for more in depth explanation:
http://www.masterzen.fr/2011/11/02/puppet-extension-point-part-2/

Thanks,

Nan

deet

unread,
Mar 28, 2012, 12:37:41 PM3/28/12
to Puppet Users

> create a md5 sum or something of both the file and my newly created content

I think what you would want to do is pull out the dbnames from the
tnsname.ora file and then compare that list against what the resource
is trying to set. If the desired dbnames list and the list currently
in the tnsnames.ora file match then exists? would return true. If not
then you would update the file content to match the desired results.

If you think of the 'host' type which updates records in the systems
hosts file. It's not going to tell you the resource is up to date
if /etc/hosts is present. I think it pulls the hosts file into an
array and then does a comparison of each host resource host/ip against
what is in the array.

For example this resource would check to see that loopback2 is in the
hosts file and associated with 127.0.0.2.

host { 'loopback2':
ip => '127.0.0.2',
}

I can't comment on what's correct or not since I've no clue:)
Good Luck! Derek.

Michael K

unread,
Mar 28, 2012, 1:32:51 PM3/28/12
to puppet...@googlegroups.com
Hello Nan,

Ok, the article by Brice gives me some pointers. I'll see if I can get it working using properties, and write back with my findings tomorrow. If it works, I'll provide a complete working example for others to learn from.

Many thanks!

Michael
Reply all
Reply to author
Forward
0 new messages