无法在定义的类型中创建文件
我想在定义的类型中创建文件。 我已经尝试了几种方法,但无法解决问题。 让我解释一下我的情况。
我正在使用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, 'filelocation'=> fileLocation} } return fileDetails end end
我在我的puppet类中使用这个函数,它对我来说很好
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: }
然后我尝试使用我自己的内容创建文件,而不是从模板中获取数据。 以下是我的rubyfunction
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, '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
我无法意识到这个问题的原因。 前一个模板工作的原因是什么,后一个模板不工作的原因是什么。
谢谢你对此的了解
我甚至不会试图了解你的第一种方法是如何工作的。 它违背了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代码。