无法在定义的类型中创建文件

时间:2014-08-17 16:45:28

标签: ruby puppet puppetlabs-apache

我想在定义的类型中创建文件。我已经尝试了几种方法,但无法解决问题。让我解释一下我的情况。

我正在使用temapltes创建一些文件,我可以完美地完成该操作。我使用下面的ruby函数来收集文件名,位置类型的数据

require 'rexml/document'
include REXML
module Puppet::Parser::Functions
newfunction(:getConfigFileDetails, :type => :rvalue ) do |args|
    fileDetails= []
    doc = REXML::Document.new args[0]
    doc.elements.each("node/congfigurations/config") {
     |config|
            fileName= config.elements["@fileName"].value
            fileLocation= config.elements["@location"].value
            fileDetails << {'filename' => fileName, 'filelocation'=> fileLocation}
    }
    return fileDetails
  end
end

我在我的木偶课中使用这个功能,它对我来说很好用

define fill_templates() {
  $fileName = $name["filename"]
  $fileLocation = $name['filelocation']
  file { "${fileLocation}/${fileName}/":
    ensure  => present,
    owner   => 'root',
    group   => 'root',
    mode    => '0777',
    content => template("config/${fileName}.erb"),
    require => Exec["unzip_pack"],
 }

}

$configFileDetails = getConfigFileDetails($allConfigurations['configurations'])
fill_templates { $configFileDetails: }

然后我尝试使用我自己的内容创建文件而不是从模板中获取数据。以下是我的红宝石功能

 require 'rexml/document'
 include REXML
 module Puppet::Parser::Functions
    newfunction(:getCreateFileDetails, :type => :rvalue ) do |args|
            fileDetails= []
            doc = REXML::Document.new args[0]
            doc.elements.each("node/create/file") {
            |filedata|
                    fileName= filedata.elements["filename"].text
                    fileLocation= filedata.elements["location"].text
                    fileContent= filedata.elements["content"].text
                    fileDetails << {'filename' => fileName, 'filelocation'=> fileLocation, 'filecontent'=> fileContent }
            }
            return fileDetails
    end
end

我在我的木偶课中使用它如下

define create_files() {
$fileName = $name["filename"]
$fileLocation = $name['filelocation']
$fileContent = $name['filecontent']
file { "${fileLocation}/${fileName}/":
    ensure  => present,
    owner   => 'root',
    group   => 'root',
    content => "$fileContent",
   }
  }
   $createFileDetails = getCreateFileDetails($allConfigurations['configurations'])
   create_files { $createFileDetails: }

但它总是给我错误

Could not retrieve catalog from remote server: Could not intern from pson: Could not convert from pson: Could not find relationship target

我无法意识到这个问题的原因。前一个模板工作的原因是什么,后一个模板不起作用。

感谢您对此的了解

1 个答案:

答案 0 :(得分:2)

我甚至不想了解你的第一种方法是如何运作的。它违背了Puppet清单语义的一些基本规则。

基本上,如果你想导入一个数据结构(从任何地方,真的)并从中生成资源(通过已定义或本机类型),它应该被构造为一个哈希:

{
  'resource-name1' => {
    'attribute-name1' => 'value',
    'attribute-name2' => 'value',
    ...
  },
  'resource-name2' => {
    ...
  }
}, ...

构建类似

的数组
[
  { attribute1 => value, attribute2 => value, ... },
  { ... },
]

将每个作为资源的名称传递给远程无效。

要解决您的问题,请使自定义函数返回适当的哈希值。 (重命名以避免骆驼案例 - 不是Puppet自定义。)

require 'rexml/document'
include REXML
module Puppet::Parser::Functions
  newfunction(:get_config_file_details, :type => :rvalue ) do |args|
    result = {}
    doc = REXML::Document.new args[0]
    doc.elements.each("node/create/file") { |filedata|
      name     = filedata.elements["filename"].text
      location = filedata.elements["location"].text
      conent   = filedata.elements["content"].text
      result[name] = {
        'fileLocation' => location,
        'fileContent'  => content,
      }
    }
    result
  end
end

您定义的类型需要接受实际参数。 (旁白:create_files是一个非常糟糕的类型名称 - 类型名称应该是单数,并描述每个资源实例代表的内容。)

define my_config_file($fileName=$name, $fileLocation, $fileContent) {
    file { "${fileLocation}/${fileName}/":
    ...
}

最后,要从哈希创建适当的实例,请使用create_resources函数。

$my_config_file_data = get_config_file_details($xml)
create_resources('my_config_files', $my_config_file_data)

最终建议:如果可能的话,请以适当的YAML或JSON格式而不是XML序列化数据。您可以将它们提供给Hiera并通过hiera()函数直接加载它们 - 无需自定义Ruby代码。