Puppet ha esportato risorse per le variabili di file .erb?


8

Scenario: il mio file di configurazione è definito da un .erbfile che include lo snippet di seguito.

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

Il file di configurazione del server richiede una voce ripetuta per ciascun host client. Se dovessi creare un array semplice, questo funzionerebbe senza problemi. Quello che voglio fare, tuttavia, è avere ogni registro host stesso e quindi raccogliere i dati usando il <<| |>>pragma simile a quello che si farebbe con i nagios_*tipi.

L' esempio standard prevede l'esportazione di un tipo.

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

Tuttavia, non riesco a capire come scrivere un tipo o fare riferimento a esso in un modo che mi consentirebbe di leggere quella matrice di valori dal .erbmodello. Esiste un modo per utilizzare le risorse esportate in combinazione con un ciclo variabile in un .erbfile?


Devono davvero finire nello stesso file? Mi piace avere ogni host in un file separato. Qualcosa come /etc/bacula/clientdefs/*.conf . Questo dovrebbe essere più facile da gestire.
Zoredache,

Risposte:


5

Quindi, per rispondere direttamente alla tua domanda, non credo sia possibile ottenere un elenco di risorse esportate direttamente da ERB. Ciò è dovuto alla natura delle risorse esportate. Per Puppet, sono solo più risorse che devono essere create sull'host.

Ma c'è un modo per realizzare ciò che stai cercando di fare. Lo faccio in alcuni punti del mio ambiente.

Qui creiamo una directory di file, una per ogni host che vogliamo contrassegnare come "bacula_client". Usiamo i purge, forcee recursele opzioni per rimuovere i file che non sono gestiti da Puppet (cioè se si desidera rimuovere un sistema da questa "lista").

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

}

Quindi, usiamo un po 'di codice Ruby in .erb per scansionare questa directory alla ricerca di file e agire su di essi:

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

Ora mi sento male perché ho finito di scrivere i miei script due giorni fa ed è molto vicino nel formato ... detto questo, ti lascerò scegliere se ritieni che la tua risposta o la mia risposta sia più appropriata per me da accettare.
Jeff Ferland,

Direi che la tua risposta è più appropriata se l'applicazione ha il supporto per una directory di configurazione o un'inclusione tramite carattere jolly (come sembra bacula). L'ho usato nel mio ambiente per gli script che spostano i file in un set di host di destinazione. Quindi gli script bash semplicemente lo fanno ls /path/to/flag/files|while read hostname; do ssh $hostname ..; done.
Kyle Smith,

4

Bene, prima ho rinunciato e impostato il mio @@sul tipo di file effettivo. Il lato positivo è che questo sta ancora usando le variabili sull'host client.

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

    ...
}

Questo mi permette di usare voci nel file erb come:

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

e dichiarazioni nei miei file site.pp come: class { bacula-client: database => "true" }

Per gestire la directory stessa:

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

        ...
}

Lo spurgo e la ricorrenza puliscono tutto ciò che non è definito. Quando porto offline un host, puppetstoredconfigclean $hostnamepulirò i fatti e la prossima corsa di marionette sul regista ripristinerà la configurazione in modo appropriato.

Alla fine, il software del regista Bacula stesso mi permette di fare quanto segue alla fine del mio file bacula-dir.conf:

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

Quindi, non sembra ancora esserci un modo diretto per utilizzare un modello ERB su un insieme di risorse raccolte, ma si possono raccogliere tipi. Ciò può includere i tipi Augeas per riporre tutto in un unico file o un hack di raccolta di file in una configurazione. Tuttavia, non include ancora ciò che stavo cercando sulla domanda.


1

Ho provato un metodo che utilizza il servizio PuppetDB che funziona abbastanza bene in questa situazione, anche se è un po 'hacker. Per usarlo dovrai avere PuppetDB operativo (cosa che dovresti già avere mentre stai usando le risorse esportate) e l'API PuppetDB dovrà essere più silenziosa dal Puppetmaster (localhost).

Quindi, vorrai esportare tutte le risorse che desideri raccogliere nel tuo array in una directory dedicata sul filesystem. Questo percorso di directory verrà utilizzato per identificare in modo univoco le risorse di destinazione.

Quindi, nel tuo modello, fai qualcosa del genere:

    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

Dove nodename è il nome FQDN del server, pathRegex è il percorso di ricerca sopra menzionato, formattato come Ruby Regex e retVal è l'array completo. Ciò sfrutta il fatto che il modello viene elaborato su Puppetmaster, pertanto non sono richieste credenziali API speciali. Ciò presuppone anche che il namevar della risorsa sia il percorso completo dei file di destinazione, se si dispone di namevar complessi e si utilizza l'attributo path sarà necessaria una logica più complessa. Si noti inoltre che questo sta restituendo tutte le risorse, sia esportate che locali. I dati restituiti hanno molti attributi che possono essere utilizzati per una logica più complessa, se necessario.

Un po 'confuso, ma funziona bene.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.