Re: [Puppet Users] Custom type and provider development

2013-03-08 Thread Josh Cooper
On Thu, Mar 7, 2013 at 6:42 PM, Nan Liu nan@gmail.com wrote:

 On Thu, Mar 7, 2013 at 1:38 PM, Nan Liu nan@gmail.com wrote:

 On Thu, Mar 7, 2013 at 8:47 AM, damian.folw...@gmail.com wrote:


 Hi,

 I'm very new to Ruby, and pretty new to Puppet so apologies if this is a
 bit Puppet custom type development 101.

 We currently have a whole bunch of Windows services that are written in
 .Net.  They are really simple and so we don't bother creating MSI installs
 for them and just use InstallUtil.exe called from a script.
 I'm looking at creating a simple Puppet type and provider that will
 allow me to install the service (via InstallUtil) if it doesn't already
 exist (as opposed to using an exec resource in which it is hard to
 determine if the service exists as a conditional).

 Now, there are many different flavours of .Net in use, and some are
 32bit, some 64 bit.  This means that I need to be able to specify what
 version of installutil.exe to use.
 Currently the type has a bunch of parameters (not properties) to specify
 this.  E.g.
 dotnetwinservice {'MyService':
 ensure= present,
 dotnetversion = '4.0.30319',
 sixtyfourbit  = false,
 path  = 'c:\program files(x86)\myapp\myapp.exe',
 }

 My question is, in the provider code what is the best way to dynamically
 determine the installutil path?  All of the examples i can find setting a
 command are not dynamic (i.e. the full command path is known without
 looking at parameter values).

 My provider code looks like the below...
 The INSTALLUTIL value is currently hard coded. I'd like to do something
 like the commented out code but it doesn't appear as though either
 @property_hash or @resource have values at the time of execution (I get
 undefined method [] for nil:nilClass error).

 Puppet::Type.type(:dotnetwinservice).provide(:dotnetwinservice) do
 desc DotNet Windows Service

   confine :operatingsystem = :windows
   defaultfor  :operatingsystem = :windows

   #dotnetframeworkversion = @resource[:sixtyfourbit] ? 'Framework64' :
 'Framework'
   #installutilpath =
 #{ENV['SYSTEMROOT']}\\Microsoft.NET\\Framework\\#{@resource[:dotnetversion]}\\InstallUtil.exe

   #INSTALLUTIL =
   #  if File.exists?(installutilpath)
   #installutilpath
   #  else
   #raise Puppet::Error.new(Cannot find installutil.exe for
 dotnetversion #{@property_hash[:dotnetversion]} at #{installutilpath}  )
   #  end

   INSTALLUTIL =
 #{ENV['SYSTEMROOT']}\\Microsoft.NET\\Framework\\v4.0.30319\\InstallUtil.exe

   commands :installutil = INSTALLUTIL


   def create
   installutil(/unattended, @resource[:path])
   end

   def destroy
   installutil(/u, /unattended, @resource[:path])
   end

   def exists?
   Win32::Service.exists?( @resource[:name] )
   end

 end


 See example here, you should be able to do something similar:

 https://github.com/puppetlabs/puppetlabs-dism/blob/master/lib/puppet/provider/dism/dism.rb#L7-L13


 Rethinking a bit more since you need access to a provider parameter, you
 may need to do something closer to this:

 commands :default_installutil = INSTALLUTIL

 def installutil(*args)
   if @resource[:dotnetversion]
 args.unshift #{ENV['SYSTEMROOT']}\\Microsoft.NET\\Framework\\#{@
 resource[:dotnetversion]}\\InstallUtil.exe
 Puppet.debug(Executing '#{args.inspect}')
 execute(args, :failonfail = true)
   else
 default_installutil *args
   end
 end

 def create
   installutil(/unattended, @resource[:path])
 end

 HTH,

 Nan

 --
 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 puppet-users+unsubscr...@googlegroups.com.
 To post to this group, send email to puppet-users@googlegroups.com.
 Visit this group at http://groups.google.com/group/puppet-users?hl=en.
 For more options, visit https://groups.google.com/groups/opt_out.





Some background on why this is necessary. When you declare:

Puppet::Type.type(:dotnetwinservice).provide(:dotnetwinservice)

Puppet uses metaprogramming to define a new class named
Puppet::Type::Dotnetwinservice::ProviderDotnetwinservice,
and it adds instance methods to the class, e.g. `def create`. Within the
body of an instance method, you have access to instance variables, e.g.
@resource, and methods, e.g. Puppet::Provider#set, #get, #resource, etc.

However, statements that are not within an instance method such as:

   dotnetframeworkversion = @resource[:sixtyfourbit] ? 'Framework64' :
'Framework'

are being evaluated in the context of your class, not an instance of your
class. So you don't have access to instance variables like @resource, and
that's why you need to create a helper method like Nan suggested.

Unfortunately, you as a provider author have to know in which context your
code is being evaluated, as that will determine what methods and variables
you have access to.

HTH,
Josh

-- 
Josh Cooper
Developer, 

Re: [Puppet Users] Custom type and provider development

2013-03-08 Thread damian . folwell
Thanks Nan and Josh. 
Your help is much appreciated. 

Once I've finished first draft I'll upload to GitHub / Forge and ask for 
comments!

-- 
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 puppet-users+unsubscr...@googlegroups.com.
To post to this group, send email to puppet-users@googlegroups.com.
Visit this group at http://groups.google.com/group/puppet-users?hl=en.
For more options, visit https://groups.google.com/groups/opt_out.




[Puppet Users] Custom type and provider development

2013-03-07 Thread damian . folwell

Hi,

I'm very new to Ruby, and pretty new to Puppet so apologies if this is a 
bit Puppet custom type development 101.

We currently have a whole bunch of Windows services that are written in 
.Net.  They are really simple and so we don't bother creating MSI installs 
for them and just use InstallUtil.exe called from a script.
I'm looking at creating a simple Puppet type and provider that will allow 
me to install the service (via InstallUtil) if it doesn't already exist (as 
opposed to using an exec resource in which it is hard to determine if the 
service exists as a conditional).

Now, there are many different flavours of .Net in use, and some are 32bit, 
some 64 bit.  This means that I need to be able to specify what version of 
installutil.exe to use.
Currently the type has a bunch of parameters (not properties) to specify 
this.  E.g.
dotnetwinservice {'MyService':
ensure= present,
dotnetversion = '4.0.30319',
sixtyfourbit  = false,
path  = 'c:\program files(x86)\myapp\myapp.exe',
}

My question is, in the provider code what is the best way to dynamically 
determine the installutil path?  All of the examples i can find setting a 
command are not dynamic (i.e. the full command path is known without 
looking at parameter values).

My provider code looks like the below...
The INSTALLUTIL value is currently hard coded. I'd like to do something 
like the commented out code but it doesn't appear as though either 
@property_hash or @resource have values at the time of execution (I get 
undefined method [] for nil:nilClass error).

Puppet::Type.type(:dotnetwinservice).provide(:dotnetwinservice) do
desc DotNet Windows Service

  confine :operatingsystem = :windows
  defaultfor  :operatingsystem = :windows

  #dotnetframeworkversion = @resource[:sixtyfourbit] ? 'Framework64' : 
'Framework'
  #installutilpath = 
#{ENV['SYSTEMROOT']}\\Microsoft.NET\\Framework\\#{@resource[:dotnetversion]}\\InstallUtil.exe

  #INSTALLUTIL = 
  #  if File.exists?(installutilpath)
  #installutilpath
  #  else
  #raise Puppet::Error.new(Cannot find installutil.exe for 
dotnetversion #{@property_hash[:dotnetversion]} at #{installutilpath}  )
  #  end
  
  INSTALLUTIL = 
#{ENV['SYSTEMROOT']}\\Microsoft.NET\\Framework\\v4.0.30319\\InstallUtil.exe
  
  commands :installutil = INSTALLUTIL

  
  def create
  installutil(/unattended, @resource[:path])
  end

  def destroy
  installutil(/u, /unattended, @resource[:path])
  end

  def exists?
  Win32::Service.exists?( @resource[:name] )
  end

end

-- 
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 puppet-users+unsubscr...@googlegroups.com.
To post to this group, send email to puppet-users@googlegroups.com.
Visit this group at http://groups.google.com/group/puppet-users?hl=en.
For more options, visit https://groups.google.com/groups/opt_out.




Re: [Puppet Users] Custom type and provider development

2013-03-07 Thread Jakov Sosic
On 03/07/2013 05:47 PM, damian.folw...@gmail.com wrote:

 My question is, in the provider code what is the best way to dynamically
 determine the installutil path?  All of the examples i can find setting
 a command are not dynamic (i.e. the full command path is known without
 looking at parameter values).

Really interesting question... I don't know the answer but am looking
forward to hearing :) Maybe Nan Liu can help?

-- 
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 puppet-users+unsubscr...@googlegroups.com.
To post to this group, send email to puppet-users@googlegroups.com.
Visit this group at http://groups.google.com/group/puppet-users?hl=en.
For more options, visit https://groups.google.com/groups/opt_out.




Re: [Puppet Users] Custom type and provider development

2013-03-07 Thread Nan Liu
On Thu, Mar 7, 2013 at 8:47 AM, damian.folw...@gmail.com wrote:


 Hi,

 I'm very new to Ruby, and pretty new to Puppet so apologies if this is a
 bit Puppet custom type development 101.

 We currently have a whole bunch of Windows services that are written in
 .Net.  They are really simple and so we don't bother creating MSI installs
 for them and just use InstallUtil.exe called from a script.
 I'm looking at creating a simple Puppet type and provider that will allow
 me to install the service (via InstallUtil) if it doesn't already exist (as
 opposed to using an exec resource in which it is hard to determine if the
 service exists as a conditional).

 Now, there are many different flavours of .Net in use, and some are 32bit,
 some 64 bit.  This means that I need to be able to specify what version of
 installutil.exe to use.
 Currently the type has a bunch of parameters (not properties) to specify
 this.  E.g.
 dotnetwinservice {'MyService':
 ensure= present,
 dotnetversion = '4.0.30319',
 sixtyfourbit  = false,
 path  = 'c:\program files(x86)\myapp\myapp.exe',
 }

 My question is, in the provider code what is the best way to dynamically
 determine the installutil path?  All of the examples i can find setting a
 command are not dynamic (i.e. the full command path is known without
 looking at parameter values).

 My provider code looks like the below...
 The INSTALLUTIL value is currently hard coded. I'd like to do something
 like the commented out code but it doesn't appear as though either
 @property_hash or @resource have values at the time of execution (I get
 undefined method [] for nil:nilClass error).

 Puppet::Type.type(:dotnetwinservice).provide(:dotnetwinservice) do
 desc DotNet Windows Service

   confine :operatingsystem = :windows
   defaultfor  :operatingsystem = :windows

   #dotnetframeworkversion = @resource[:sixtyfourbit] ? 'Framework64' :
 'Framework'
   #installutilpath =
 #{ENV['SYSTEMROOT']}\\Microsoft.NET\\Framework\\#{@resource[:dotnetversion]}\\InstallUtil.exe

   #INSTALLUTIL =
   #  if File.exists?(installutilpath)
   #installutilpath
   #  else
   #raise Puppet::Error.new(Cannot find installutil.exe for
 dotnetversion #{@property_hash[:dotnetversion]} at #{installutilpath}  )
   #  end

   INSTALLUTIL =
 #{ENV['SYSTEMROOT']}\\Microsoft.NET\\Framework\\v4.0.30319\\InstallUtil.exe

   commands :installutil = INSTALLUTIL


   def create
   installutil(/unattended, @resource[:path])
   end

   def destroy
   installutil(/u, /unattended, @resource[:path])
   end

   def exists?
   Win32::Service.exists?( @resource[:name] )
   end

 end


See example here, you should be able to do something similar:
https://github.com/puppetlabs/puppetlabs-dism/blob/master/lib/puppet/provider/dism/dism.rb#L7-L13

HTH,

Nan

-- 
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 puppet-users+unsubscr...@googlegroups.com.
To post to this group, send email to puppet-users@googlegroups.com.
Visit this group at http://groups.google.com/group/puppet-users?hl=en.
For more options, visit https://groups.google.com/groups/opt_out.




Re: [Puppet Users] Custom type and provider development

2013-03-07 Thread Nan Liu
On Thu, Mar 7, 2013 at 1:38 PM, Nan Liu nan@gmail.com wrote:

 On Thu, Mar 7, 2013 at 8:47 AM, damian.folw...@gmail.com wrote:


 Hi,

 I'm very new to Ruby, and pretty new to Puppet so apologies if this is a
 bit Puppet custom type development 101.

 We currently have a whole bunch of Windows services that are written in
 .Net.  They are really simple and so we don't bother creating MSI installs
 for them and just use InstallUtil.exe called from a script.
 I'm looking at creating a simple Puppet type and provider that will allow
 me to install the service (via InstallUtil) if it doesn't already exist (as
 opposed to using an exec resource in which it is hard to determine if the
 service exists as a conditional).

 Now, there are many different flavours of .Net in use, and some are
 32bit, some 64 bit.  This means that I need to be able to specify what
 version of installutil.exe to use.
 Currently the type has a bunch of parameters (not properties) to specify
 this.  E.g.
 dotnetwinservice {'MyService':
 ensure= present,
 dotnetversion = '4.0.30319',
 sixtyfourbit  = false,
 path  = 'c:\program files(x86)\myapp\myapp.exe',
 }

 My question is, in the provider code what is the best way to dynamically
 determine the installutil path?  All of the examples i can find setting a
 command are not dynamic (i.e. the full command path is known without
 looking at parameter values).

 My provider code looks like the below...
 The INSTALLUTIL value is currently hard coded. I'd like to do something
 like the commented out code but it doesn't appear as though either
 @property_hash or @resource have values at the time of execution (I get
 undefined method [] for nil:nilClass error).

 Puppet::Type.type(:dotnetwinservice).provide(:dotnetwinservice) do
 desc DotNet Windows Service

   confine :operatingsystem = :windows
   defaultfor  :operatingsystem = :windows

   #dotnetframeworkversion = @resource[:sixtyfourbit] ? 'Framework64' :
 'Framework'
   #installutilpath =
 #{ENV['SYSTEMROOT']}\\Microsoft.NET\\Framework\\#{@resource[:dotnetversion]}\\InstallUtil.exe

   #INSTALLUTIL =
   #  if File.exists?(installutilpath)
   #installutilpath
   #  else
   #raise Puppet::Error.new(Cannot find installutil.exe for
 dotnetversion #{@property_hash[:dotnetversion]} at #{installutilpath}  )
   #  end

   INSTALLUTIL =
 #{ENV['SYSTEMROOT']}\\Microsoft.NET\\Framework\\v4.0.30319\\InstallUtil.exe

   commands :installutil = INSTALLUTIL


   def create
   installutil(/unattended, @resource[:path])
   end

   def destroy
   installutil(/u, /unattended, @resource[:path])
   end

   def exists?
   Win32::Service.exists?( @resource[:name] )
   end

 end


 See example here, you should be able to do something similar:

 https://github.com/puppetlabs/puppetlabs-dism/blob/master/lib/puppet/provider/dism/dism.rb#L7-L13


Rethinking a bit more since you need access to a provider parameter, you
may need to do something closer to this:

commands :default_installutil = INSTALLUTIL

def installutil(*args)
  if @resource[:dotnetversion]
args.unshift #{ENV['SYSTEMROOT']}\\Microsoft.NET\\Framework\\#{@
resource[:dotnetversion]}\\InstallUtil.exe
Puppet.debug(Executing '#{args.inspect}')
execute(args, :failonfail = true)
  else
default_installutil *args
  end
end

def create
  installutil(/unattended, @resource[:path])
end

HTH,

Nan

-- 
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 puppet-users+unsubscr...@googlegroups.com.
To post to this group, send email to puppet-users@googlegroups.com.
Visit this group at http://groups.google.com/group/puppet-users?hl=en.
For more options, visit https://groups.google.com/groups/opt_out.