简体   繁体   English

通过Ruby Recipe错误使用Chef Data_bag吗?

[英]Chef Data_bag usage via Ruby Recipe error?

I have a Chef DataBag that I'm trying to read and use inside of a chef recipe, and its kicking my ass. 我有一个Chef DataBag,我正在尝试在厨师食谱中阅读和使用它,这让我大吃一惊。 Please note: I'm not a programmer, and the use of Chef is my first entry into Ruby. 请注意:我不是程序员,而使用Chef是我第一次进入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: 根据我在网上找到的示例,这是数据包“ AWSProd”的内容,该数据包位于Chef服务器上data_bags文件夹下的WEB文件夹中:

{
  "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: 在我的食谱中,我使用以下方法来获取Databag以便使用:

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... 然后我基本上想遍历每个站点(siteA,siteB等),并获取site_name,site_doc_root_folder等的各个值。

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 ##. 但是我在双倍##的行上收到“无法将String转换为Integer”错误。

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. 但是然后我在那一行上得到了“ nil:NilClass的未定义方法'[]'”错误。

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. 我知道我在这里缺少Ruby的一些基本知识,并且我一直在寻找一个清晰的解释一个小时,却找不到一个。 Help me Ruby-Won-Kenobi... 帮我Ruby-Won-Kenobi ...

In your data bag item, each site is an array of hashes. 在您的数据袋项目中,每个站点都是一个哈希数组。 I don't think this is what you intended, since you would need to access it like: 我认为这不是您想要的,因为您需要像这样访问它:

site[0]["site_name"]

What you probably wanted was a data bag item like: 您可能想要的是一个数据袋物品,例如:

{
  "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" : ""
      }
  }
}

Ok, so I got it! 好的,我明白了! Took a little education on Hash Vs Arrays... 对Hash Vs Arrays进行了一些教育...

Below is the correct ruby block: 以下是正确的红宝石块:

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

You are using the .each method on a Hash , but only capturing the key. 您在Hash上使用.each方法,但仅捕获密钥。 WEB_env_globals['hosted_sites'].each do |key, value| - but you only gave it a name for the key. -但您只给它起了钥匙的名字。

each_sitename = site[....] - remember that site is the key (a String), so you're calling the [] method on String which expects an Integer and returns the char at that index. each_sitename = site[....] -请记住,站点是键(一个String),因此您要在String上调用[]方法,该方法需要一个Integer并在该索引处返回char。

* You can call .class on any ruby object to find out what type it is. * 您可以在任何ruby对象上调用.class来找出它是什么类型。 This is very helpful for troublshooting 这对于故障排除非常有帮助

So you can change your databag to use an array of hashes: 因此,您可以更改数据包以使用哈希数组:

change your databag: 更改您的数据包:

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

Or leave it alone and try this for your code: (note I also don't use an execute block for my debugging) 或不理会它,并为您的代码尝试一下:(请注意,我也没有使用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

end 结束

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM