Puppetは.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 -%>

サーバーの構成ファイルには、クライアントホストごとにエントリを繰り返す必要があります。単純な配列を作成する場合、これは問題なく機能します。しかし、私がやりたいことは、各ホストにそれ自体を登録さ<<| |>>せ、nagios_*タイプで行うのと同様のプラグマを使用してデータを収集することです。

この標準的な例には、タイプのエクスポートが含まれます。

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

ただし、型を記述したり、.erbテンプレートから値の配列を読み取れるように参照したりする方法を完全に理解することはできません。.erbファイル内の変数ループと組み合わせてエクスポートされたリソースを使用する方法はありますか?


彼らは本当に同じファイルになる必要がありますか?各ホストを別々のファイルにしたい。/etc/bacula/clientdefs/*.confのようなもの。これは扱いやすいはずです。
Zoredache

回答:


5

したがって、あなたの質問に直接答えるために、エクスポートされたリソースのリストをerbから直接取得することは不可能だと思います。これは、エクスポートされたリソースの性質によるものです。Puppetにとって、これらはホスト上で作成する必要があるより多くのリソースです。

しかし、あなたが望んでいることを達成する方法があります。私は自分の環境のいくつかの場所でそれを行います。

ここでは、「bacula_client」としてフラグを設定するホストごとに1つずつ、ファイルのディレクトリを作成します。、、およびオプションを使用してpurge、Puppetで管理されていないファイルを削除します(つまり、この「リスト」からシステムを削除する場合)。forcerecurse

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

さて、2日前にスクリプトの作成を終え、形式が非常に近いために気分が悪くなりました。
ジェフファーランド2012年

アプリケーションがconfigディレクトリまたはワイルドカードによるインクルードをサポートしている場合(バキュラがそうであるように)、あなたの答えはより適切だと思います。私の環境では、ファイルを一連のターゲットホストに移動するスクリプト用にこれを使用しました。したがって、bashスクリプトは単純に実行しますls /path/to/flag/files|while read hostname; do ssh $hostname ..; done
カイルスミス

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すると、事実が消去され、Directorでの次のパペットの実行により、構成が適切にリセットされます。

最後に、Bacula directorソフトウェア自体により、bacula-dir.confファイルの最後で以下を実行できます。

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

したがって、収集されたリソースのセットに対してERBテンプレートを使用する直接的な方法はまだないようですが、タイプを収集できます。これには、すべてを1つのファイルに詰め込むAugeasタイプや、構成にファイルを収集するハックを含めることができます。ただし、質問で探していた内容はまだ含まれていません。


1

PuppetDBサービスを使用して、この状況でかなりうまくいく方法を思いつきましたが、少しハックです。これを使用するには、PuppetDBが動作可能である必要があります(エクスポートされたリソースを使用しているため、これが既に必要です)。PuppetDBAPIは、puppetmaster(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 Regexとしてフォーマットされた上記の検索パスであり、retValは完成した配列です。これにより、テンプレートがpuppetmasterで処理されるため、特別なAPI資格情報は必要ありません。これは、リソースnamevarがターゲットファイルの完全修飾パスであることも前提としています。複雑なnamevarがあり、path属性を使用する場合、より複雑なロジックが必要になります。また、これにより、エクスポートされたリソースとローカルのリソースの両方がすべて返されます。返されたデータには、必要に応じてより複雑なロジックに使用できる多くの属性があります。

少しハッキーですが、うまく機能します。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.