自定义木偶类型提供者 - 存在吗?返回true会导致'undefined method'异常

时间:2013-06-18 16:29:16

标签: puppet

我正在尝试基于puppetlabs rabbitmq module中存在的现有提供程序为RabbitMQ开发自定义类型提供程序。 如果exists?方法返回false - 一切正常。 但是,如果exists?返回true,则puppet将失败并显示undefined method 'pattern'异常(stacktrace bellow)。 请注意,pattern是我类型的参数之一。 我在CentOS上使用Puppet 3.1.1。

stacktrace:

Error: /Stage[main]//Node[rabbitmq]/Rabbitmq_policy[ha-all@DMITRY_CBMS]: Could not evaluate: undefined method `pattern' for #<Puppet::Type::Rabbitmq_policy::ProviderRabbitmqctl:0x7f5e647471f0>

/usr/lib/ruby/site_ruby/1.8/puppet/property.rb:462:in `send'
/usr/lib/ruby/site_ruby/1.8/puppet/property.rb:462:in `retrieve'
/usr/lib/ruby/site_ruby/1.8/puppet/type.rb:1027:in `retrieve'
/usr/lib/ruby/site_ruby/1.8/puppet/type.rb:1022:in `each'
/usr/lib/ruby/site_ruby/1.8/puppet/type.rb:1022:in `retrieve'
/usr/lib/ruby/site_ruby/1.8/puppet/type.rb:1041:in `retrieve_resource'
/usr/lib/ruby/site_ruby/1.8/puppet/transaction/resource_harness.rb:32:in `perform_changes'
/usr/lib/ruby/site_ruby/1.8/puppet/transaction/resource_harness.rb:133:in `evaluate'
/usr/lib/ruby/site_ruby/1.8/puppet/transaction.rb:48:in `apply'
/usr/lib/ruby/site_ruby/1.8/puppet/transaction.rb:83:in `eval_resource'
/usr/lib/ruby/site_ruby/1.8/puppet/transaction.rb:103:in `evaluate'
/usr/lib/ruby/site_ruby/1.8/puppet/util.rb:351:in `thinmark'
/usr/lib/ruby/1.8/benchmark.rb:308:in `realtime'
/usr/lib/ruby/site_ruby/1.8/puppet/util.rb:350:in `thinmark'
/usr/lib/ruby/site_ruby/1.8/puppet/transaction.rb:103:in `evaluate'
/usr/lib/ruby/site_ruby/1.8/puppet/transaction.rb:382:in `traverse'
/usr/lib/ruby/site_ruby/1.8/puppet/transaction.rb:98:in `evaluate'
/usr/lib/ruby/site_ruby/1.8/puppet/resource/catalog.rb:144:in `apply'
/usr/lib/ruby/site_ruby/1.8/puppet/configurer.rb:122:in `apply_catalog'
/usr/lib/ruby/site_ruby/1.8/puppet/util.rb:179:in `benchmark'
/usr/lib/ruby/1.8/benchmark.rb:308:in `realtime'
/usr/lib/ruby/site_ruby/1.8/puppet/util.rb:178:in `benchmark'
/usr/lib/ruby/site_ruby/1.8/puppet/configurer.rb:121:in `apply_catalog'
/usr/lib/ruby/site_ruby/1.8/puppet/configurer.rb:179:in `run'
/usr/lib/ruby/site_ruby/1.8/puppet/agent.rb:45:in `run'
/usr/lib/ruby/site_ruby/1.8/puppet/agent/locker.rb:20:in `lock'
/usr/lib/ruby/site_ruby/1.8/puppet/agent.rb:45:in `run'
/usr/lib/ruby/1.8/sync.rb:230:in `synchronize'
/usr/lib/ruby/site_ruby/1.8/puppet/agent.rb:45:in `run'
/usr/lib/ruby/site_ruby/1.8/puppet/agent.rb:119:in `with_client'
/usr/lib/ruby/site_ruby/1.8/puppet/agent.rb:42:in `run'
/usr/lib/ruby/site_ruby/1.8/puppet/agent.rb:89:in `run_in_fork'
/usr/lib/ruby/site_ruby/1.8/puppet/agent.rb:86:in `fork'
/usr/lib/ruby/site_ruby/1.8/puppet/agent.rb:86:in `run_in_fork'
/usr/lib/ruby/site_ruby/1.8/puppet/agent.rb:41:in `run'
/usr/lib/ruby/site_ruby/1.8/puppet/application.rb:179:in `call'
/usr/lib/ruby/site_ruby/1.8/puppet/application.rb:179:in `controlled_run'
/usr/lib/ruby/site_ruby/1.8/puppet/agent.rb:39:in `run'
/usr/lib/ruby/site_ruby/1.8/puppet/daemon.rb:205:in `run_event_loop'
/usr/lib/ruby/site_ruby/1.8/puppet/daemon.rb:167:in `loop'
/usr/lib/ruby/site_ruby/1.8/puppet/daemon.rb:167:in `run_event_loop'
/usr/lib/ruby/site_ruby/1.8/puppet/daemon.rb:145:in `start'
/usr/lib/ruby/site_ruby/1.8/puppet/application/agent.rb:357:in `main'
/usr/lib/ruby/site_ruby/1.8/puppet/application/agent.rb:313:in `run_command'
/usr/lib/ruby/site_ruby/1.8/puppet/application.rb:364:in `run'
/usr/lib/ruby/site_ruby/1.8/puppet/application.rb:456:in `plugin_hook'
/usr/lib/ruby/site_ruby/1.8/puppet/application.rb:364:in `run'
/usr/lib/ruby/site_ruby/1.8/puppet/util.rb:504:in `exit_on_fail'
/usr/lib/ruby/site_ruby/1.8/puppet/application.rb:364:in `run'
/usr/lib/ruby/site_ruby/1.8/puppet/util/command_line.rb:132:in `run'
/usr/lib/ruby/site_ruby/1.8/puppet/util/command_line.rb:86:in `execute'

类型定义:

Puppet::Type.newtype(:rabbitmq_policy) do
  desc 'Type for defining rabbitmq policies'

  ensurable do
    defaultto(:present)
    newvalue(:present) do
      provider.create
    end
    newvalue(:absent) do
      provider.destroy
    end
  end

  newparam(:name, :namevar => true) do
    desc 'combination of policy-name@vhost to setup the policy'
    newvalues(/^\S+@\S+$/)
  end

  newproperty(:pattern) do
    desc 'regexp representing configuration permissions'
    validate do |value|
      resource.validate_permissions(value)
    end
  end

  newproperty(:definition) do
    desc 'definition of this policit, e.g: {"ha-mode":"all"}'
  end

  autorequire(:rabbitmq_vhost) do
    [self[:name].split('@')[1]]
  end

  autorequire(:rabbitmq_policy) do
    [self[:name].split('@')[0]]
  end

  # I may want to dissalow whitespace
  def validate_permissions(value)
    begin
      Regexp.new(value)
    rescue RegexpError
      raise ArgumentError, "Invalid regexp #{value}"
    end
  end

end

提供商定义:

 Puppet::Type.type(:rabbitmq_policy).provide(:rabbitmqctl) do

  commands :rabbitmqctl => 'rabbitmqctl'
  defaultfor :feature => :posix

  def policy_name
    if @cached_policy_name
      @cached_policy_name
    else
      @cached_policy_name = resource[:name].split('@')[0]
    end
  end

  def vhost
    if @cached_vhost
      @cached_vhost
    else
      @cached_vhost = resource[:name].split('@')[1]
    end
  end

  def create
    Puppet.debug "rabbitmq_policy.create"
    rabbitmqctl('set_policy','-p', vhost, policy_name, resource[:pattern], resource[:definition])
  end

  def destroy
    Puppet.debug "rabbitmq_policy.destroy"
    rabbitmqctl('clear_policy', '-p', vhost, policy_name)
  end

  def exists?
    out = rabbitmqctl('list_policies', '-p', vhost).split(/\n/)[1..-2].collect do |line|
      parts = line.split(/\s+/)
      Puppet.debug "rabbitmq_policy::list_policies line: #{line}| #{parts[1]} == #{policy_name} => #{parts[1] == policy_name} "
      if parts[1] == policy_name
         true
      else
         false
      end
     end
     out = out.detect do |obj| obj end
     Puppet.debug "rabbitmq_policy.exists: #{out.to_s}"
     out
  end

  #def exists?
  #  false
  #end

end

非常感谢任何帮助。

谢谢

1 个答案:

答案 0 :(得分:1)

找到答案(感谢Daniel在ask.puppetlabs.com)。 在类型定义中使用newproperty定义的每个属性都必须在提供程序中具有相应的getter和setter。并且属性仅对其属性可以单独更新的类型有意义。 对于简单的情况,应该使用newparam