0

I have a Chef DataBag that I'm trying to read and use inside of a chef recipe, and its kicking my ass. Please note: I'm not a programmer, and the use of Chef is my first entry into Ruby.

Based off of the examples I've found online, here is the contents of the databag "AWSProd" that lives in a folder called WEB under the data_bags folder on my Chef server:

{
  "id" : "AWSProd",
  "hosted_sites" : {
    "siteA" : [
      {
        "site_name" : "siteA",
        "site_doc_root_folder" : "siteA",
        "site_simlink" : ""
     }
     ],
     "siteB" : [
      {
        "site_name" : "siteB",
        "site_doc_root_folder" : "siteB",
        "site_simlink" : ""
      }
      ]
  }
}

In my recipe, I'm using the following to grab the Databag for use:

WEB = data_bag("WEB")
WEB_env_globals = data_bag_item("WEB", node.chef_environment)

Then I basically want to iterate each site (siteA, siteB, etc) and grab those individual values for site_name, site_doc_root_folder, etc...

I'm trying to just echo the values so I know they work. I tried this:

WEB_env_globals["hosted_sites"].each do |site|
  each_sitename = site["site_name"] ## can't convert String into Integer
  each_site_doc_root_folder = site["site_doc_root_folder"]
  each_site_simlink = site["site_simlink"]

  execute "echo each site" do
    command "echo #{each_sitename} #{each_site_doc_root_folder} #{each_site_simlink}"
    action :run
  end

end

But I received a "can't convert String into Integer" error on the line where I have the double ##.

Then I tried replacing that line with something like this:

each_sitename = WEB_env_globals["hosted_sites"][site]["site_name"]

But then I get an "undefined method `[]' for nil:NilClass" error on that line.

I know I'm missing something completely basic with Ruby here, and I've been looking for about an hour for a clear explanation and cant find one. Help me Ruby-Won-Kenobi...

4

3 回答 3

1

在您的数据包项中,每个站点都是一个哈希数组。我认为这不是您想要的,因为您需要像这样访问它:

site[0]["site_name"]

您可能想要的是一个数据包项目,例如:

{
  "id" : "AWSProd",
  "hosted_sites" : {
    "siteA" : {
        "site_name" : "siteA",
        "site_doc_root_folder" : "siteA",
        "site_simlink" : ""
     },
     "siteB" : {
        "site_name" : "siteB",
        "site_doc_root_folder" : "siteB",
        "site_simlink" : ""
      }
  }
}
于 2014-10-23T17:10:38.313 回答
0

好的,所以我明白了!对哈希与数组进行了一些教育......

下面是正确的红宝石块:

WEB_env_globals["hosted_sites"].each do |site,data|

  data.each do |hash|
    each_sitename = hash["site_name"]
    each_site_doc_root_folder = hash["site_doc_root_folder"]
    each_site_simlink = hash["site_simlink"]

      execute "echo each site #{site}" do
        command "echo #{each_sitename} #{each_site_doc_root_folder} #{each_site_simlink}"
        action :run
      end
    end
  end
于 2014-10-23T17:09:59.893 回答
0

.each在 a 上使用该方法Hash,但仅捕获密钥。 WEB_env_globals['hosted_sites'].each do |key, value|- 但你只给了它一个钥匙的名字。

each_sitename = site[....]- 请记住,该站点是键(字符串),因此您调用的[]方法String需要一个整数并返回该索引处的字符。

*你可以调用.class任何 ruby​​ 对象来找出它是什么类型。这对于故障排除非常有帮助

因此,您可以更改数据包以使用哈希数组:

更改您的数据包:

{
  "id" : "AWSProd",
  "hosted_sites" : [
    {
      "site_name" : "siteA",
      "site_doc_root_folder" : "siteA",
      "site_simlink" : ""
    },
    {
      "site_name" : "siteB",
      "site_doc_root_folder" : "siteB",
      "site_simlink" : ""
    }
  ]
}

或者不理会它,并为您的代码尝试这个:(请注意,我也没有使用execute块进行调试)

WEB_env_globals["hosted_sites"].each do |sitename, site_array|
  site_array.each do |site|
    each_sitename = site["site_name"]
    each_site_doc_root_folder = site["site_doc_root_folder"]
    each_site_simlink = site["site_simlink"]

     Chef::Log.debug "#{each_sitename} #{each_site_doc_root_folder} #{each_site_simlink}"
     # you could use puts or a higher level log message to make this easier to see in your output.
  end

结尾

于 2014-10-23T17:14:27.833 回答