Sumberdaya yang diekspor boneka untuk variabel file .erb?

8

Skenario: file konfigurasi saya ditentukan oleh .erbfile yang menyertakan cuplikan di bawah ini.

<% 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 -%>

File konfigurasi server memerlukan entri berulang untuk setiap host klien. Jika saya membuat array sederhana, ini akan berhasil tanpa masalah. Namun yang ingin saya lakukan adalah meminta setiap host mendaftar sendiri dan kemudian mengumpulkan data menggunakan <<| |>>pragma yang mirip dengan apa yang akan dilakukan seseorang dengan nagios_*tipenya.

Contoh standar untuk ini melibatkan mengekspor tipe.

class ssh {
  @@sshkey { $hostname: type => dsa, key => $sshdsakey }
  Sshkey <<| |>>
}

Namun, saya tidak tahu bagaimana cara menulis jenis atau referensi dengan cara yang memungkinkan saya untuk membaca array nilai dari .erbtemplate. Apakah ada cara saya bisa menggunakan sumber daya yang diekspor dalam kombinasi dengan loop variabel dalam .erbfile?

Jeff Ferland
sumber
Apakah mereka benar-benar harus berakhir di file yang sama? Saya suka memiliki setiap host dalam file terpisah. Sesuatu seperti /etc/bacula/clientdefs/*.conf . Ini harus lebih mudah untuk ditangani.
Zoredache

Jawaban:

5

Jadi, untuk menjawab pertanyaan Anda secara langsung, saya tidak percaya mendapatkan daftar sumber daya yang diekspor langsung dari erb adalah mungkin. Ini karena sifat sumber daya yang diekspor. Bagi Puppet, mereka hanyalah lebih banyak sumber daya yang perlu dibuat di host.

Tapi, ada cara untuk mencapai apa yang ingin Anda lakukan. Saya melakukannya di beberapa tempat di lingkungan saya.

Di sini kita membuat direktori file, satu untuk setiap host yang ingin kita panji sebagai "bacula_client". Kami menggunakan opsi purge,, forcedan recurseuntuk menghapus file yang tidak dikelola oleh Wayang (yaitu jika Anda ingin menghapus sistem dari "daftar" ini).

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" |>>

}

Selanjutnya, kami menggunakan beberapa kode Ruby di .erb untuk memindai direktori ini untuk mencari file, dan menindaklanjutinya:

<% 
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 -%>
Kyle Smith
sumber
Sekarang saya merasa tidak enak karena saya selesai menulis skrip saya dua hari yang lalu dan itu sangat dekat dalam format ... yang mengatakan, saya akan membiarkan Anda memilih apakah Anda merasakan jawaban Anda atau jawaban saya lebih tepat untuk saya terima.
Jeff Ferland
Saya akan mengatakan jawaban Anda lebih tepat jika aplikasi memiliki dukungan untuk direktori config atau sertakan oleh wildcard (seperti yang terlihat pada bacula). Saya telah menggunakan ini di lingkungan saya untuk skrip yang memindahkan file ke sekumpulan host target. Jadi skrip bash cukup lakukan ls /path/to/flag/files|while read hostname; do ssh $hostname ..; done.
Kyle Smith
4

Yah, pertama saya menyerah dan mengatur @@jenis file saya yang sebenarnya. Sisi baiknya adalah ini masih menggunakan variabel pada host klien.

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]
    }

    ...
}

Ini memungkinkan saya menggunakan entri dalam file erb seperti:

<% if has_variable?("database") and database== "true" %>
    ...
<% end -%>

dan deklarasi di file site.pp saya seperti: class { bacula-client: database => "true" }

Untuk menangani direktori itu sendiri:

class bacula-director {
        file { '/etc/bacula/conf.d':
            ensure => directory,
            owner => bacula,
            group => root,
            mode => 600,
            purge => true,
            recurse => true
        }

        ...
}

Bersihkan dan rekursi membersihkan apa pun yang tidak ditentukan. Ketika saya mengambil host offline, puppetstoredconfigclean $hostnameakan membersihkan fakta dan menjalankan wayang pada sutradara akan mengatur ulang konfigurasi dengan tepat.

Akhirnya, perangkat lunak direktur Bacula sendiri memungkinkan saya melakukan hal berikut di akhir file bacula-dir.conf saya:

@|"sh -c 'for f in /etc/bacula/conf.d/*.conf ; do echo @${f} ; done'"

Jadi, tampaknya tidak ada cara langsung untuk menggunakan templat ERB pada kumpulan sumber daya yang terkumpul, tetapi orang dapat mengumpulkan suatu jenis. Itu bisa mencakup tipe Augeas untuk memasukkan semuanya ke dalam satu file, atau retasan mengumpulkan file ke dalam konfigurasi. Itu belum termasuk apa yang saya cari pada pertanyaan itu.

Jeff Ferland
sumber
1

Saya telah menemukan metode menggunakan layanan PuppetDB yang bekerja cukup baik untuk situasi ini, meskipun agak sedikit meretas. Untuk menggunakan ini, Anda harus memiliki PuppetDB operasional (yang seharusnya sudah Anda miliki saat Anda menggunakan sumber daya yang diekspor) dan PuppetDB API harus dapat quierable dari puppetmaster (localhost).

Kemudian, Anda akan ingin mengekspor semua sumber daya yang ingin Anda kumpulkan ke dalam array Anda di direktori khusus pada sistem file. Jalur direktori ini akan digunakan untuk mengidentifikasi secara unik sumber daya target.

Kemudian, di templat Anda, lakukan sesuatu seperti ini:

    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

Dimana nodename adalah FQDN server, pathRegex adalah jalur pencarian yang disebutkan di atas, diformat sebagai Ruby Regex, dan retVal adalah array yang lengkap. Ini memanfaatkan bahwa templat diproses pada puppetmaster sehingga kredensial API khusus tidak diperlukan. Ini juga mengasumsikan resource namevar adalah jalur yang sepenuhnya memenuhi syarat dari file target, jika Anda memiliki namevars yang kompleks dan menggunakan atribut path, logika yang lebih kompleks akan diperlukan. Juga perhatikan ini mengembalikan semua sumber daya, baik yang diekspor maupun lokal. Data yang dikembalikan memiliki banyak atribut yang dapat digunakan untuk logika yang lebih kompleks jika diperlukan.

Agak hacky, tetapi bekerja dengan baik.

TJNII
sumber