시나리오 : 구성 파일은 .erb
아래 스 니펫이 포함 된 파일로 정의됩니다 .
<% backupclients.each do |backup_files| -%>
Job {
Name = "Server"
JobDefs = "DefaultJob"
Client = <%= backup_files %>-fd
Pool = TeraMonth
Write Bootstrap = "/var/lib/bacula/<%= backup_files %>.bsr"
}
<% end -%>
서버의 구성 파일에는 각 클라이언트 호스트에 대해 반복 된 항목이 필요합니다. 간단한 배열을 만들면 문제없이 작동합니다. 그러나 내가하고 싶은 것은 각 호스트 자체를 등록 한 다음 유형으로 <<| |>>
수행하는 것과 비슷한 pragma를 사용하여 데이터를 수집하는 것 nagios_*
입니다.
이에 대한 표준 예 는 유형 내보내기입니다.
class ssh {
@@sshkey { $hostname: type => dsa, key => $sshdsakey }
Sshkey <<| |>>
}
그러나 .erb
템플릿 에서 해당 값의 배열을 읽을 수있는 방식으로 형식을 작성하거나 참조하는 방법을 알 수 없습니다 . .erb
파일 에서 변수 루프와 함께 내 보낸 리소스를 사용할 수있는 방법이 있습니까?
답변
따라서 귀하의 질문에 직접 대답하기 위해 erb에서 직접 내 보낸 리소스 목록을 얻는 것이 가능하다고 생각하지 않습니다 . 이는 내 보낸 자원의 특성 때문입니다. Puppet에게는 호스트에서 생성해야하는 더 많은 리소스 일뿐입니다.
그러나 원하는 것을 성취 할 수있는 방법이 있습니다. 나는 내 환경의 몇 곳에서 그것을합니다.
여기서는 “bacula_client”로 플래그를 지정하려는 각 호스트마다 하나씩 파일 디렉토리를 만듭니다. 우리는 사용 purge
, force
그리고 recurse
(이 “목록”에서 시스템을 제거하려면 예) 인형에서 관리하지 않는 파일을 제거 할 수있는 옵션.
class bacula::client {
@@file { "/etc/bacula_clients/$fqdn":
ensure => present,
content => "",
require => File['/etc/bacula_clients'],
tag => "bacula_client",
}
}
class bacula::server {
#
# .. include whatever else the server requires, like package {} file {} service {}
#
file { "/etc/bacula_clients":
ensure => directory,
purge => true,
recurse => true,
force => true,
}
# Populate directory of client files.
File <<| tag == "bacula_client" |>>
}
다음으로, .erb에있는 일부 Ruby 코드를 사용하여이 디렉토리에서 파일을 스캔하고 이에 대해 조치를 취하십시오.
<%
bacula_clients_dir = '/etc/bacula_clients'
d = Dir.open(bacula_clients_dir)
# Remove directories from the list of entries in the directory (specifically '.' and '..'):
backupclients = d.entries.delete_if { |e| File.directory? "#{bacula_clients_dir}/#{e}" }
backupclients.each do |backup_files|
-%>
Job {
Name = "Server"
JobDefs = "DefaultJob"
Client = <%= backup_files %>-fd
Pool = TeraMonth
Write Bootstrap = "/var/lib/bacula/<%= backup_files %>.bsr"
}
<% end -%>
답변
글쎄, 먼저 @@
실제 파일 형식을 포기하고 설정했습니다 . 단점은 이것이 여전히 클라이언트 호스트에서 변수를 사용하고 있다는 것입니다.
class bacula-client ($database = false) {
@@file { "${hostname}-bacula-client.conf":
mode => 600,
owner => bacula,
group => root,
path => "/etc/bacula/conf.d/${hostname}-client.conf",
content => template("bacula-dir-cliententry.erb"),
tag => 'bacula-client',
notify => Service[bacula-director]
}
...
}
이를 통해 erb 파일에서 다음과 같은 항목을 사용할 수 있습니다.
<% if has_variable?("database") and database== "true" %>
...
<% end -%>
내 site.pp 파일의 선언 : class { bacula-client: database => "true" }
디렉토리 자체를 처리하려면 다음을 수행하십시오.
class bacula-director {
file { '/etc/bacula/conf.d':
ensure => directory,
owner => bacula,
group => root,
mode => 600,
purge => true,
recurse => true
}
...
}
제거 및 재귀는 정의되지 않은 것을 정리합니다. 호스트를 오프라인 상태로 puppetstoredconfigclean $hostname
만들면 팩트가 정리되고 다음 번 퍼펫 실행으로 구성이 적절하게 재설정됩니다.
마지막으로 Bacula director 소프트웨어 자체로 bacula-dir.conf 파일의 끝에서 다음을 수행 할 수 있습니다.
@|"sh -c 'for f in /etc/bacula/conf.d/*.conf ; do echo @${f} ; done'"
따라서 수집 된 리소스 집합에서 ERB 템플릿을 사용하는 직접적인 방법은 아직 보이지 않지만 유형을 수집 할 수 있습니다. 여기에는 모든 파일을 하나의 파일로 채우거나 파일을 구성으로 수집하는 핵을 포함하는 Augeas 유형이 포함될 수 있습니다. 그래도 질문에서 찾고 있던 것은 포함되어 있지 않습니다.
답변
나는이 상황에서 상당히 잘 작동하는 PuppetDB 서비스를 사용하는 방법을 강타했지만 약간 해킹입니다. 이를 사용하려면 PuppetDB가 작동해야하며 (내 보낸 리소스를 사용하면서 이미 가지고 있어야 함) PuppetDB API는 꼭두각시 마스터 (localhost)에서 제공 할 수 있어야합니다.
그런 다음 수집하려는 모든 리소스를 파일 시스템의 전용 디렉토리에있는 배열로 내 보냅니다. 이 디렉토리 경로는 대상 자원을 고유하게 식별하는 데 사용됩니다.
그런 다음 템플릿에서 다음과 같이하십시오.
require 'rest_client'
require 'json'
resources=JSON.parse(RestClient.get("http://localhost:8080/v2/nodes/#{nodename}/resources", {:accept => :json}))
retVal = Array.new
resources.each do |resource|
if resource["title"] =~ /^#{pathRegex}$/
retVal.push(resource["title"])
end
end
nodename이 서버의 FQDN 인 경우 pathRegex는 위에서 언급 한 검색 경로이며 Ruby 정규식으로 형식이 지정되고 retVal은 완성 된 배열입니다. 이렇게하면 템플릿이 꼭두각시 마스터에서 처리되므로 특별한 API 자격 증명이 필요하지 않습니다. 또한 복잡한 namevar이 있고 path 속성을 사용하는 경우 자원 namevar이 대상 파일의 완전한 경로 인 것으로 가정합니다. 더 복잡한 논리가 필요합니다. 또한 이것은 내 보낸 리소스와 로컬 리소스를 모두 반환합니다. 반환 된 데이터에는 필요한 경우 더 복잡한 논리에 사용할 수있는 많은 속성이 있습니다.
약간 해 키지 만 잘 작동합니다.