Hi, I have a custom provider that seems to run ok in isolation by itself. In addition, puppet does not complain at all when it runs. However, when I ensure => installed a package the desired package is never installed. There are a few differences between this and something such as the gem provider, most importantly, I couldn''t find anyway to get the provider to run as a different user without doing direct system call. Here''s the provider Puppet::Type.type(:package).provide :npm, :parent => Puppet::Provider::Package do desc "node.js package management with npm" commands :npm_cmd => "/home/node/opt/bin/npm" raise Puppet::Error, "The npm provider can only be used as root" if Process.euid != 0 def self.npm_list(hash) begin s = `sudo -u node sh -c \"export PATH=/home/node/opt/bin:$ {PATH}; npm ls installed\"` list = s.split("\n").collect do |set| if npm_hash = npm_split(set) npm_hash[:provider] = :npm if npm_hash[:name] == hash[:justme] npm_hash else nil end else nil end end.compact rescue Puppet::ExecutionFailure => detail raise Puppet::Error, "Could not list npm packages: #{detail}" end list.shift end def self.npm_split(desc) split_desc = desc.split(/ /) installed = split_desc[0] name = installed.split(/@/)[0] version = installed.split(/@/)[1] if (name.nil? || version.nil?) Puppet.warning "Could not match #{desc}" nil else return { :name => name, :ensure => version } end end def install output = `sudo -u node sh -c \"export PATH=/home/node/opt/bin:$ {PATH}; npm install http-console\"` if output =~ /npm not ok/ raise Puppet::ExecutionFailure, "Failed to install #{resource[:name]}" end end def uninstall output = `sudo -u node sh -c \"export PATH=/home/node/opt/bin:$ {PATH}; npm uninstall #{resource[:name]}\"` if output =~ /npm not ok/ raise Puppet::ExecutionFailure, "Failed to uninstall #{resource[:name]}" end end def query version = nil self.class.npm_list(:justme => resource[:name]) end end Does anybody have an idea what''s going wrong? The other problem I''m having is that I have to manually copy the provider to puppet lib from the module lib. Thanks. -- You received this message because you are subscribed to the Google Groups "Puppet Users" group. To post to this group, send email to puppet-users@googlegroups.com. To unsubscribe from this group, send email to puppet-users+unsubscribe@googlegroups.com. For more options, visit this group at http://groups.google.com/group/puppet-users?hl=en.
On Jan 6, 4:01 pm, pl <patrick.b....@gmail.com> wrote:> def install > output = `sudo -u node sh -c \"export PATH=/home/node/opt/bin:$ > {PATH}; npm install http-console\"` > if output =~ /npm not ok/ > raise Puppet::ExecutionFailure, "Failed to install > #{resource[:name]}" > end > endNote that this was a hard-coded package (http-console) I added just to see if it would install. It didn''t. -- You received this message because you are subscribed to the Google Groups "Puppet Users" group. To post to this group, send email to puppet-users@googlegroups.com. To unsubscribe from this group, send email to puppet-users+unsubscribe@googlegroups.com. For more options, visit this group at http://groups.google.com/group/puppet-users?hl=en.
Hi, So, after setting pluginsync = true I manage to get this working, but only executing correctly as puppetd --test Except that it only functions correctly when run as puppetd --test, when I run it as the puppet service the custom provider does not do anything. This seems odd. The only notice I have in /var/log/messages is "Provider npm has not defined the ''instances'' class method" Is that required? On Jan 6, 4:10 pm, pl <patrick.b....@gmail.com> wrote:> On Jan 6, 4:01 pm, pl <patrick.b....@gmail.com> wrote: > > > def install > > output = `sudo -u node sh -c \"export PATH=/home/node/opt/bin:$ > > {PATH}; npm install http-console\"` > > if output =~ /npm not ok/ > > raise Puppet::ExecutionFailure, "Failed to install > > #{resource[:name]}" > > end > > end > > Note that this was a hard-coded package (http-console) I added just to > see if it would install. It didn''t.-- You received this message because you are subscribed to the Google Groups "Puppet Users" group. To post to this group, send email to puppet-users@googlegroups.com. To unsubscribe from this group, send email to puppet-users+unsubscribe@googlegroups.com. For more options, visit this group at http://groups.google.com/group/puppet-users?hl=en.
On Sun, Jan 09, 2011 at 09:29:00PM -0800, pl wrote:> Hi, > > So, after setting pluginsync = true I manage to get this working, but > only executing correctly as puppetd --test > > Except that it only functions correctly when run as puppetd --test, > when I run it as the puppet service the custom provider does not do > anything. > > This seems odd. > > The only notice I have in /var/log/messages is > > "Provider npm has not defined the ''instances'' class method" > > Is that required?Puppet::Provider::Package defines the prefetch class method. This is called at the beginning of the puppet run to find matches between existing packages and the one you described in your manifest. Prefetch calls instances which should return an array of provider instances. One provider instance for each package with the appropiate property_hash {ensure => "whatever-version"}. If you dont know how to implement it try with returning an empty array like hpux.rb does. The reason for instances is you can use the resource type to purge not managed packages and prefetech is useful when you can run one command to query all packages. When the user specified 200 packages you dont want to run the same query command 200 times to check if the packges is installed or not when you can easily parse ONE command at the beginning that lists all packages. -Stefan -Stefan
Hi,> Puppet::Provider::Package defines the prefetch class method. This is > called at the beginning of the puppet run to find matches between existing > packages and the one you described in your manifest. Prefetch calls > instances which should return an array of provider instances. One > provider instance for each package with the appropiate property_hash > {ensure => "whatever-version"}. If you dont know how to implement it try > with returning an empty array like hpux.rb does.Thanks. I still have this problem that I can''t run puppet as a daemon and install packages as any other user. Trying to sudo inside the custom provider fails if puppet is running as a daemon. Is there no way around that? -- You received this message because you are subscribed to the Google Groups "Puppet Users" group. To post to this group, send email to puppet-users@googlegroups.com. To unsubscribe from this group, send email to puppet-users+unsubscribe@googlegroups.com. For more options, visit this group at http://groups.google.com/group/puppet-users?hl=en.
On Mon, Jan 10, 2011 at 05:06:04PM -0800, pl wrote:> Hi, > > > Puppet::Provider::Package defines the prefetch class method. This is > > called at the beginning of the puppet run to find matches between existing > > packages and the one you described in your manifest. Prefetch calls > > instances which should return an array of provider instances. One > > provider instance for each package with the appropiate property_hash > > {ensure => "whatever-version"}. If you dont know how to implement it try > > with returning an empty array like hpux.rb does. > > Thanks. > > I still have this problem that I can''t run puppet as a daemon and > install packages as any other user. Trying to sudo inside the custom > provider fails if puppet is running as a daemon. > > Is there no way around that?Yes there is. And you will probably dont want to use backticks. You can browse the functions in puppet/lib/util.rb for alternatives. There are different ways to run commands. If you have defined a command like you already did: commands :npm_cmd => "/home/node/opt/bin/npm" This will mean that puppet will only use the provider if the command is there and you will get a method for free that will run that command. npm_cmd(''argument1'',''argument2'') I''m not sure if this will have the output as a return value or just success/failure. To parse output I find execpipe convenient. (You can use command(:my_own_defined_command) to return your command as a string value) execpipe("#{command(:npm_cmd)} list_or_whatever_argument") do |output| output.each_line do |line| # do parsing here end end To run all these as a different user you should (although I never tried it) wrap them in Puppet::Util::SUIDManager.asuser("username", "group") do # do stuff here as different user end Just grep for SUIDManager in the sources and you will find examples. You may have to use userids and groupids for that to work i dont know. Hope this helps. -Stefan -- You received this message because you are subscribed to the Google Groups "Puppet Users" group. To post to this group, send email to puppet-users@googlegroups.com. To unsubscribe from this group, send email to puppet-users+unsubscribe@googlegroups.com. For more options, visit this group at http://groups.google.com/group/puppet-users?hl=en.
Hi,> Puppet::Util::SUIDManager.asuser("username", "group") do > # do stuff here as different user > endNot sure this works how you suggested as this Puppet::Util::SUIDManager.asuser("userx", "userx") do execpipe("whoami") do |output| Will report root, not userx. I''ll check the source. -- You received this message because you are subscribed to the Google Groups "Puppet Users" group. To post to this group, send email to puppet-users@googlegroups.com. To unsubscribe from this group, send email to puppet-users+unsubscribe@googlegroups.com. For more options, visit this group at http://groups.google.com/group/puppet-users?hl=en.
On Sun, Jan 16, 2011 at 20:00, pl <patrick.b.lee@gmail.com> wrote:>> Puppet::Util::SUIDManager.asuser("username", "group") do >> # do stuff here as different user >> end > > Not sure this works how you suggested as thisIn the current codebase, it will silently ignore the request if you are either on Windows, or not running as root. Otherwise it juts delegates everything except the extended group list operations to the Ruby Process class, and should follow the semantics of that; we also verify that we can find the user by name or UID on the way and raise an exception if it doesn''t work. So, yeah: I don''t doubt you are seeing that behaviour, but I can''t understand how from code inspection. Can you instrument your code to dump Process.uid and Process.gid from Ruby-space in the block? That way we can help narrow down where things are going wrong. Regards, Daniel -- ✉ Daniel Pittman <daniel@rimspace.net> ⌨ daniel@rimspace.net (XMPP) ☎ +1 503 893 2285 ♻ made with 100 percent post-consumer electrons -- You received this message because you are subscribed to the Google Groups "Puppet Users" group. To post to this group, send email to puppet-users@googlegroups.com. To unsubscribe from this group, send email to puppet-users+unsubscribe@googlegroups.com. For more options, visit this group at http://groups.google.com/group/puppet-users?hl=en.
Hi,> Can you instrument your code to > dump Process.uid and Process.gid from Ruby-space in the block? That > way we can help narrow down where things are going wrong.Process.uid was telling me 500, which was the intended user. whoami inside the execpipe was root though. I''ve ended up doing this def self.exec_as_user(op, pkg) Puppet::Util::SUIDManager.asuser("node", "node") do s = execute ["my", "command", "and", "args"] s.split("\n").collect do | line | yield line end end end which is doing what I want -- You received this message because you are subscribed to the Google Groups "Puppet Users" group. To post to this group, send email to puppet-users@googlegroups.com. To unsubscribe from this group, send email to puppet-users+unsubscribe@googlegroups.com. For more options, visit this group at http://groups.google.com/group/puppet-users?hl=en.
On Mon, Jan 17, 2011 at 19:26, pl <patrick.b.lee@gmail.com> wrote:>> Can you instrument your code to >> dump Process.uid and Process.gid from Ruby-space in the block? That >> way we can help narrow down where things are going wrong. > > Process.uid was telling me 500, which was the intended user. whoami > inside the execpipe was root though.Hmmmm. I wonder what was convincing whoami that you were root, not UID 500, then.> I''ve ended up doing this > > def self.exec_as_user(op, pkg) > > Puppet::Util::SUIDManager.asuser("node", "node") do > s = execute ["my", "command", "and", "args"] > s.split("\n").collect do | line | > yield line > end > end > endIt might be worth looking at puppet/util.rb to see the handful of "run this command" helpers hidden away in there, just to make sure you are not duplicating effort. Anyway, sounds like you got it working, so glad to hear that. Regards, Daniel -- ✉ Daniel Pittman <daniel@rimspace.net> ⌨ daniel@rimspace.net (XMPP) ☎ +1 503 893 2285 ♻ made with 100 percent post-consumer electrons -- You received this message because you are subscribed to the Google Groups "Puppet Users" group. To post to this group, send email to puppet-users@googlegroups.com. To unsubscribe from this group, send email to puppet-users+unsubscribe@googlegroups.com. For more options, visit this group at http://groups.google.com/group/puppet-users?hl=en.
On Mon, Jan 17, 2011 at 07:26:36PM -0800, pl wrote:> Process.uid was telling me 500, which was the intended user. whoami > inside the execpipe was root though. > > I''ve ended up doing this > > def self.exec_as_user(op, pkg) > > Puppet::Util::SUIDManager.asuser("node", "node") do > s = execute ["my", "command", "and", "args"] > s.split("\n").collect do | line | > yield line > end > end > end > > > which is doing what I wantYou can also pass arguments to execute to run the command as a different user. It should work like that output = execute([''command'',''arg1], {uid => ''node'', gid => ''node''}) What operatingsystem are you running? Looking at the source asuser will just change euid and egid and from the manpage of whoami it should return the euid. So I dont really understand why whoami is reporting root and I dont really see why execute should behave differently from execpipe. -Stefan