web-dev-qa-db-ja.com

API呼び出しを使用したPuppet書き込みホスト

ホスティング環境(rackspace cloud atm)を呼び出してサーバーを一覧表示し、hostsファイルを更新するpuppet関数を作成しようとしています。

私のget_hosts関数は現在これです:

require 'rubygems'
require 'cloudservers'

module Puppet::Parser::Functions
  newfunction(:get_hosts, :type => :rvalue) do |args|
    unless args.length == 1
      raise Puppet::ParseError, "Must provide the datacenter"
    end

    DC       = args[0] 
    USERNAME = DC == "us" ? "..." : "..."
    API_KEY  = DC == "us" ? "..." : "..."
    AUTH_URL = DC == "us" ? CloudServers::AUTH_USA : CloudServers::AUTH_UK
    DOMAIN   = "..."

    cs = CloudServers::Connection.new(:username => USERNAME, :api_key => API_KEY, :auth_url => AUTH_URL)

    cs.list_servers_detail.map {|server|
      server.map {|s| { s[:name] + "." + DC + DOMAIN => {
                          :ip      => s[:addresses][:private][0],
                          :aliases => s[:name]
      }}}
    }
  end
end

そして、これを呼び出すhosts.ppがあり、/ etc/hostsに書き込む必要があります。

class hosts::us {
    $hosts = get_hosts("us")

    hostentry { $hosts: }
}

define hostentry() {
  Host{ $name: ip => $name[ip], Host_aliases => $name[aliases] }
}

ご想像のとおり、これは現在機能しておらず、 '/ etc/puppet/manifests/hosts.pp:2の配列インデックスとしてのシンボル'エラーが発生しています。私が現在間違っていることに気づいたら、さらに多くのエラーが来ると思います。

これは良い考えですか?誰かが私がこれを行う方法を理解するのを手伝ってくれる?

更新

ついにこれを機能させることができました(コメントの助けを借りて)!これが私のget_hosts.rbです:

require 'rubygems'
require 'cloudservers'

module Puppet::Parser::Functions
  newfunction(:get_hosts, :type => :rvalue) do |args|
    unless args.length == 1
      raise Puppet::ParseError, "Must provide the datacenter"
    end

    dc       = args[0] 
    username = dc == "us" ? "..." : "..."
    api_key  = dc == "us" ? "..." : "..."
    auth_url = dc == "us" ? CloudServers::AUTH_USA : CloudServers::AUTH_UK
    domain   = "...."

    cs = CloudServers::Connection.new(:username => username, :api_key => api_key, :auth_url => auth_url)

    cs.list_servers_detail.map {|server|
      server[:name] + "." + dc + domain + "," + 
          server[:addresses][:private][0] + "," + 
          server[:name]
    }
  end
end

およびhosts.pp

class hosts::us {
    $hosts = get_hosts("us")

    hostentry { $hosts: }
}

define hostentry() {
  $parts   = split($name, ',')
  $address = $parts[0]
  $ip      = $parts[1]
  $aliases = $parts[2]
  Host{ $address: ip => $ip, Host_aliases => $aliases }
}

このようにnamevarをマーシャリングするのはかなり厄介ですが、それが機能するように見える唯一の方法でした。どんな改善も歓迎します。

3
Ben Smith

私はそれを悪い考えとは言いませんが、コード内のどこでも定数の使用をやめる必要があります(Rubyは定数です)の大文字で始まるものはすべて)。

問題をデバッグするには、puppetmasterの呼び出しに--traceオプションを使用することをお勧めします。これにより、実際の例外を食べて役に立たないエラーメッセージを表示する代わりに、バックトレースが出力されます。 map呼び出しで間接参照が山積みになっています。私の推測では、APIから出力されるデータ構造の一部を誤解していて、コードがその誤解につまずいていると思います。デバッガーを起動する(またはコードにputsをたっぷりと振りかける)と、何が間違っているかがかなり短い順序で表示されます。

1
womble

この機能を別の方法で分離します。

関数を使用して、ホストリソースのリストを表すハッシュのハッシュに純粋なデータを構築します。

次に、create_resources関数を使用して、そのデータから実際のホストリソースを作成します。

http://docs.puppetlabs.com/references/2.7.12/function.html#createresources

そこにある例は、始めるのに十分なものになるはずです。

    # A hash of user resources:
    $myusers = {
      'nick' => { uid    => '1330',
                  group  => allstaff,
                  groups => ['developers', 'operations', 'release'], }
      'dan'  => { uid    => '1308',
                  group  => allstaff,
                  groups => ['developers', 'prosvc', 'release'], }
    }

    create_resources(user, $myusers)

それは理にかなっていますか?

次に、定義された型を回避でき、関数呼び出しですべてのデータ変更を実行してハッシュのハッシュを取得できます。また、データを収集する関数とリソースをインスタンス化する関数を適切に分離できます。

私があなたの問題を正しく理解していれば、これは古典的な反復の必要性を解決するはずです。

0
Nigel Kersten