我想在定义的类型中创建文件。我已经尝试了几种方法,但无法解决问题。让我解释一下我的情况。
我正在使用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
我无法意识到这个问题的原因。前一个模板工作的原因是什么,后一个模板不起作用。
感谢您对此的了解
答案 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代码。