.erb 파일 변수에 대해 퍼펫에서 리소스를 내보냈습니까?


8

시나리오 : 구성 파일은 .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파일 에서 변수 루프와 함께 내 보낸 리소스를 사용할 수있는 방법이 있습니까?


그들은 실제로 같은 파일로 끝나야합니까? 각 호스트를 별도의 파일로 만들고 싶습니다. /etc/bacula/clientdefs/*.conf 와 같은 . 다루기가 더 쉬워야합니다.
Zoredache

답변:


5

따라서 귀하의 질문에 직접 대답하기 위해 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 -%>

이제 이틀 전에 스크립트 작성을 마치고 나름대로 기분이 나 빠지고 형식이 매우 비슷합니다. 즉, 귀하가 귀하의 답변을 느끼는지 아니면 내 대답이 더 적합한지를 선택하도록하겠습니다.
Jeff Ferland 2016 년

응용 프로그램이 구성 디렉토리 또는 와일드 카드로 포함을 지원하는 경우 (bacula가 표시하는 것처럼) 귀하의 답변이 더 적절하다고 말하고 싶습니다. 필자는 내 환경에서 파일을 일련의 대상 호스트로 이동시키는 스크립트에 사용했습니다. 따라서 bash 스크립트는 간단하게 수행 ls /path/to/flag/files|while read hostname; do ssh $hostname ..; done합니다.
Kyle Smith

4

글쎄, 먼저 @@실제 파일 형식을 포기하고 설정했습니다 . 단점은 이것이 여전히 클라이언트 호스트에서 변수를 사용하고 있다는 것입니다.

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 유형이 포함될 수 있습니다. 그래도 질문에서 찾고 있던 것은 포함되어 있지 않습니다.


1

나는이 상황에서 상당히 잘 작동하는 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이 대상 파일의 완전한 경로 인 것으로 가정합니다. 더 복잡한 논리가 필요합니다. 또한 이것은 내 보낸 리소스와 로컬 리소스를 모두 반환합니다. 반환 된 데이터에는 필요한 경우 더 복잡한 논리에 사용할 수있는 많은 속성이 있습니다.

약간 해 키지 만 잘 작동합니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.