0
votes

I'm trying to create a new custom type/provider but not ensurable.

I've already checked the exec and augeas types, but I couldn't figure out clearly how exactly the integration between type and provider work when we don't define the ensurable mode.

Type:

Puppet::Type.newtype(:ptemplates) do

  newparam(:name) do

    desc ""

    isnamevar

  end

  newproperty(:run) do

    defaultto 'now'

    # Actually execute the command.
    def sync
      provider.run
    end

  end

end

Provider:

require 'logger'

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

    desc ""

    def run

      log = Logger.new(STDOUT)
      log.level = Logger::INFO

      log.info("x.....................................")

    end

But I don't know why the provider is being executed twice

root@puppet:/# puppet apply -e "ptemplates { '/tmp': }" --environment=production
Notice: Compiled catalog for puppet.localhost in environment production in 0.12 seconds
I, [2017-07-30T11:00:15.827103 #800]  INFO -- : x.....................................
I, [2017-07-30T11:00:15.827492 #800]  INFO -- : x.....................................
Notice: /Stage[main]/Main/Ptemplates[/tmp]/run: run changed 'true' to 'now'
Notice: Applied catalog in 4.84 seconds

Also, I had to define the defaultto to force the execution of the provider.run method.

What am I missing ?

Best Regards.

1
Why not use normal methods for forcing execution, like setting idempotent to false or using exists/creates? - Matt Schuchard
Why do you think (not) being ensurable has anything to do with your problem? - John Bollinger

1 Answers

0
votes

First you should spend some time reading this blog http://garylarizza.com/blog/2013/11/25/fun-with-providers/ and the two following by Gary Larizza. It gives a very good introduction to puppet type/providers.

Your log is being executed twice because of your def sync in the type that calls the run define, second when puppet tries to determine the value of your run property.

In order to write a type/provider that is not ensurable you need to do something like:

Type:

Puppet::Type.newtype(:ptemplates) do
  @doc = ""

  newparam(:name, :namevar => true) do
    desc ""
  end

  newproperty(:run) do
    desc ""
    newvalues(:now, :notnow)
    defaultto :now
  end
end

Provider:

Puppet::Type.type(:ptemplates).provide(:ruby) do
  desc ""

  def run
    #Do something to determine if run value and is now or notnow and return it
  end

  def run= value
    #Do something to set the value of run
  end
end

Note that all type providers must be able to determine the value of the property and be able to set it. The difference between an ensurable and a not ensurable type/provider is that the ensurable type/prover is able to create and destroy it, fx remove an user or add an user. A type/provider that is not ensurable is not able to create and destroy the property, fx selinux, you can set its value, but you cannot remove selinux.