2014-10-23 3 views
0

У меня есть DataBag для шеф-повара, который я пытаюсь прочитать и использовать внутри рецепта шеф-повара, и его ногами мою задницу. Обратите внимание: я не программист, и использование Chef - это моя первая запись в Ruby.Использование Chef Data_bag через Ruby Recipe error?

Основа из примеров, которые я нашел в Интернете, вот содержимое databag «AWSProd», который живет в папке под названием WEB в папке data_bags на моем Chef сервере:

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

В моем рецепт, я использую следующие захватить Databag для использования:

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

Тогда я в основном хочу перебирать каждый сайт (SiteA, SITEB, и т.д.) и захватить эти индивидуальные значения для SITE_NAME, site_doc_root_folder и т.д .. .

Я пытаюсь просто отозвать ценности, чтобы я знал, что они работают. Я попытался это:

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 

Но я получил «не может преобразовать строку в Integer» Ошибка в строке, где у меня есть двойной ##.

Тогда я попытался заменить эту строку с чем-то вроде этого:

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

Но тогда я получаю «неопределенный метод` []»для ноль: NilClass» ошибка в этой строке.

Я знаю, что здесь отсутствует что-то совершенно базовое с Ruby, и я искал около часа для ясного объяснения и не могу найти его. Помогите мне Ruby-Won-Kenobi ...

ответ

0

Хорошо, так что я понял! Взял немного образования на Hash Vs Массивы ...

Ниже приводится правильный блок рубин:

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 
+0

Да, это работает, но я бы предложил вам изменить структуру вашего баз данных. Например, вы указываете имя файла дважды, что на самом деле не нужно. –

+0

Спасибо Tejay, у нас есть несколько сайтов, у которых есть sitenames, которые смешны, поэтому нам нужен тег «простой английский» для сайта. Хотя я думаю, что это может быть просто еще одно значение в списке ... Хорошая пища для размышлений! – HeavyObjectLifter

+0

Если в этом случае, я предлагаю вам пойти с подходом, который указал кодерангер. Это позволяет использовать идентификатор и имя, сохраняя при этом чистую (и более рубинообразную) структуру данных. –

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

Вы используете .each метод на Hash, но только захват ключа. WEB_env_globals['hosted_sites'].each do |key, value| - но вы только дали ему имя для ключа.

each_sitename = site[....] - помните, что сайт является ключом (String), так что вы звоните в [] метод на String который использует целое число и возвращает символ по этому индексу.

* Вы можете позвонить по номеру .class на любой объект ruby, чтобы узнать, какой тип он есть.Это очень полезно для troublshooting

Таким образом, вы можете изменить свой databag использовать массив хэшей:

изменение ваш 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" : "" 
    } 
    ] 
} 

Или оставить его в покое и попробовать это для вашего кода: (обратите внимание, я также не использовать 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 

конец

Смежные вопросы