Проблема с объединением элемента в блоке «каждый» с атрибутом узла

Я использую Chef 11.10.4, работающий в AWS Opsworks.

Я не могу понять, как объединить элемент lyr с атрибутом узла node['aws-tag'][#{lyr}] в строках 07-14 ниже.

Я использую подстановку строк в качестве псевдокода, чтобы показать, что я пытаюсь сделать, но в данной ситуации это явно не работает. Строки 02-06 работают отлично, я просто пытаюсь заставить работать строки 07-14, и я не знаю, как это сделать.

include_recipe "aws"
unless node['aws-tag']['tags'].empty? || node['aws-tag']['tags'].nil?
   aws_resource_tag node['ec2']['instance_id'] do
       tags(node['aws-tag']['tags'])
       action :update
   end
   node['opsworks']['instance']['layers'].each do |lyr|
       unless node['aws-tag'][#{lyr}].empty? || node['aws-tag'][#{lyr}].nil?
           aws_resource_tag node['ec2']['instance_id'] do
               tags(node['aws-tag'][#{lyr}])
               action :update
           end
       end
   end
end

Вот результаты от chef-shell, показывающие значения атрибутов, упомянутых в приведенном выше коде:

chef > node['opsworks']['instance']['layers']
 => ["mongodb"]

chef > node['aws-tag']
 => {"tags"=>{"application"=>"app1", "environment"=>"dev"}, "mongodb"=>{"service"=>"mongodb"}}

Я изменяю кулинарную книгу chef-aws-tag, чтобы пометить все экземпляры ec2 с помощью теги в node['aws-tag']['tags'] и в дополнение к тегам каждого экземпляра ec2, специфичные теги уровня opsworks, которые включены в пользовательский JSON, передаваемый в opsworks по уровням, в данном случае содержимое node['aws-tag']['mongodb'] или node['aws-tag']['LAYER'], как правило.

Если я запускаю приведенный выше код, я получаю сообщение об ошибке компиляции рецепта: «неожиданное ключевое слово_do_block, ожидающее ']'» — подробное сообщение об ошибке от opsworks см. ниже:

================================================================================
Recipe Compile Error in /var/lib/aws/opsworks/cache.stage2/cookbooks/chef-aws-tag/recipes/ec2.rb
================================================================================


SyntaxError
-----------
/var/lib/aws/opsworks/cache.stage2/cookbooks/chef-aws-tag/recipes/ec2.rb:9: syntax error, unexpected keyword_do_block, expecting ']'
/var/lib/aws/opsworks/cache.stage2/cookbooks/chef-aws-tag/recipes/ec2.rb:12: syntax error, unexpected keyword_end, expecting ']'


Cookbook Trace:
---------------
/opt/aws/opsworks/releases/20141010064749_328/vendor/bundle/ruby/2.0.0/gems/chef-11.10.4/lib/chef/mixin/from_file.rb:30:in `instance_eval'
/opt/aws/opsworks/releases/20141010064749_328/vendor/bundle/ruby/2.0.0/gems/chef-11.10.4/lib/chef/mixin/from_file.rb:30:in `from_file'
/opt/aws/opsworks/releases/20141010064749_328/vendor/bundle/ruby/2.0.0/gems/chef-11.10.4/lib/chef/cookbook_version.rb:237:in `load_recipe'
/opt/aws/opsworks/releases/20141010064749_328/vendor/bundle/ruby/2.0.0/gems/chef-11.10.4/lib/chef/run_context.rb:151:in `load_recipe'
/opt/aws/opsworks/releases/20141010064749_328/vendor/bundle/ruby/2.0.0/gems/chef-11.10.4/lib/chef/run_context/cookbook_compiler.rb:139:in `block in compile_recipes'
/opt/aws/opsworks/releases/20141010064749_328/vendor/bundle/ruby/2.0.0/gems/chef-11.10.4/lib/chef/run_context/cookbook_compiler.rb:137:in `each'
/opt/aws/opsworks/releases/20141010064749_328/vendor/bundle/ruby/2.0.0/gems/chef-11.10.4/lib/chef/run_context/cookbook_compiler.rb:137:in `compile_recipes'
/opt/aws/opsworks/releases/20141010064749_328/vendor/bundle/ruby/2.0.0/gems/chef-11.10.4/lib/chef/run_context/cookbook_compiler.rb:74:in `compile'
/opt/aws/opsworks/releases/20141010064749_328/vendor/bundle/ruby/2.0.0/gems/chef-11.10.4/lib/chef/run_context.rb:86:in `load'
/opt/aws/opsworks/releases/20141010064749_328/vendor/bundle/ruby/2.0.0/gems/chef-11.10.4/lib/chef/policy_builder/expand_node_object.rb:75:in `setup_run_context'
/opt/aws/opsworks/releases/20141010064749_328/vendor/bundle/ruby/2.0.0/gems/chef-11.10.4/lib/chef/client.rb:252:in `setup_run_context'
/opt/aws/opsworks/releases/20141010064749_328/vendor/bundle/ruby/2.0.0/gems/chef-11.10.4/lib/chef/client.rb:413:in `do_run'
/opt/aws/opsworks/releases/20141010064749_328/vendor/bundle/ruby/2.0.0/gems/chef-11.10.4/lib/chef/client.rb:200:in `block in run'
/opt/aws/opsworks/releases/20141010064749_328/vendor/bundle/ruby/2.0.0/gems/chef-11.10.4/lib/chef/client.rb:194:in `fork'
/opt/aws/opsworks/releases/20141010064749_328/vendor/bundle/ruby/2.0.0/gems/chef-11.10.4/lib/chef/client.rb:194:in `run'
/opt/aws/opsworks/releases/20141010064749_328/vendor/bundle/ruby/2.0.0/gems/chef-11.10.4/lib/chef/application.rb:215:in `run_chef_client'
/opt/aws/opsworks/releases/20141010064749_328/vendor/bundle/ruby/2.0.0/gems/chef-11.10.4/lib/chef/application/client.rb:314:in `block in run_application'
/opt/aws/opsworks/releases/20141010064749_328/vendor/bundle/ruby/2.0.0/gems/chef-11.10.4/lib/chef/application/client.rb:306:in `loop'
/opt/aws/opsworks/releases/20141010064749_328/vendor/bundle/ruby/2.0.0/gems/chef-11.10.4/lib/chef/application/client.rb:306:in `run_application'
/opt/aws/opsworks/releases/20141010064749_328/vendor/bundle/ruby/2.0.0/gems/chef-11.10.4/lib/chef/application.rb:66:in `run'
/opt/aws/opsworks/releases/20141010064749_328/vendor/bundle/ruby/2.0.0/gems/chef-11.10.4/bin/chef-client:26:in `<top (required)>'
/opt/aws/opsworks/current/bin/chef-client:16:in `load'
/opt/aws/opsworks/current/bin/chef-client:16:in `<main>'


Relevant File Content:
----------------------
/opt/aws/opsworks/releases/20141010064749_328/vendor/bundle/ruby/2.0.0/gems/chef-11.10.4/lib/chef/mixin/from_file.rb:

23: 
24:        # Loads a given ruby file, and runs instance_eval against it in the context of the current
25:        # object.
26:        #
27:        # Raises an IOError if the file cannot be found, or is not readable.
28:        def from_file(filename)
29:          if File.exists?(filename) && File.readable?(filename)
30>>           self.instance_eval(IO.read(filename), filename, 1)
31:          else
32:            raise IOError, "Cannot open or read #{filename}!"
33:          end
34:        end
35: 
36:        # Loads a given ruby file, and runs class_eval against it in the context of the current
37:        # object.
38:        #
39:        # Raises an IOError if the file cannot be found, or is not readable.



[2014-10-28T17:43:22+00:00] ERROR: Running exception handlers
[2014-10-28T17:43:22+00:00] ERROR: Exception handlers complete
[2014-10-28T17:43:22+00:00] FATAL: Stacktrace dumped to /var/lib/aws/opsworks/cache.stage2/chef-stacktrace.out
[2014-10-28T17:43:22+00:00] ERROR: /var/lib/aws/opsworks/cache.stage2/cookbooks/chef-aws-tag/recipes/ec2.rb:9: syntax error, unexpected keyword_do_block, expecting ']'
/var/lib/aws/opsworks/cache.stage2/cookbooks/chef-aws-tag/recipes/ec2.rb:12: syntax error, unexpected keyword_end, expecting ']'
[2014-10-28T17:43:22+00:00] FATAL: Chef::Exceptions::ChildConvergeError: Chef run process exited unsuccessfully (exit code 1)

person Peter M    schedule 28.10.2014    source источник
comment
Где это ломается? Например, вы даже достигли строки 09 или строка 08 оценивается как ложная и завершает ваше выполнение?   -  person Tejay Cardon    schedule 28.10.2014
comment
Вместо псевдокода нам нужен минимальный пример реального кода, отображающего проблему. В противном случае мы на самом деле не работаем над проблемой, мы работаем над псевдопроблемой.   -  person the Tin Man    schedule 28.10.2014
comment
Мои извинения @TejayCardon - ошибка в строке 9: неожиданное keyword_do_block, ожидание ']'. Я добавил подробный вывод в пост.   -  person Peter M    schedule 28.10.2014
comment
Мои извинения @theTinMan - это настоящий код, но я знаю, что он ломается, потому что я использую строковую функцию, в которой нет строки. Я добавил подробный вывод в пост.   -  person Peter M    schedule 28.10.2014


Ответы (1)


lyr уже является строкой, поэтому работает следующее:

node['opsworks']['instance']['layers'].each do |lyr|
    unless node['aws-tag'][lyr].empty? || node['aws-tag'][lyr].nil?
        aws_resource_tag node['ec2']['instance_id'] do
            tags(node['aws-tag'][lyr])
            action :update
        end
    end
end

Я тестировал это в интерактивном режиме в шеф-оболочке, и это не сработало, но я думаю, что есть некоторая разница при выполнении во время выполнения, потому что там это работает. Вот результат моего теста, который провалился в шеф-оболочке, и я думал, что это то же самое:

root@mongodb2:/opt/aws/opsworks/current/bin# ./chef-shell -j /var/lib/aws/opsworks/chef/2014-10-28-17-15-30-01.json
loading configuration: none (standalone session)
Session type: standalone
Loading.......done.

This is the chef-shell.
 Chef Version: 11.10.4
 http://www.opscode.com/chef
 http://docs.opscode.com/

run `help' for help, `exit' or ^D to quit.

Ohai2u [email protected]!
chef > lyr=node['opsworks']['instance']['layers']
 => ["mongodb"]
chef > lyr
 => ["mongodb"]
chef > node['aws-tag'][lyr]
 => nil
chef >
person Peter M    schedule 28.10.2014
comment
lyr=node['opsworks']['instance']['layers'] не то же самое, что node['opsworks']['instance']['layers'].each do |lyr| - person Tejay Cardon; 28.10.2014
comment
@TejayCardon Я понимаю, что мой тест был неадекватным. В тесте оболочки есть только один элемент в узле массива ['opsworks']['instance']['layers'], поэтому я подумал, что это то же самое. Однако в моем примере с шеф-оболочкой lyr не является строкой, и если да, то почему node['aws-tag'][lyr] не работает, если node['aws-tag']['mongodb'] работает работать в одной оболочке? - person Peter M; 28.10.2014
comment
Вот что я говорю. В тесте оболочки lyr — это не строка, а массив. ['mongodb'] Тот факт, что массив состоит только из одного элемента, еще не означает, что он не является массивом. Вы можете использовать lyr[0] в своем тесте, если хотите избежать цикла. - person Tejay Cardon; 29.10.2014
comment
@TejayCardon - большое спасибо, что нашли время, чтобы научить меня, извините за то, что я такой тугой. Это работает и очень помогает. Я также могу сделать node['aws-tag'][node['opsworks']['instance']['layers'][0]] непосредственно во время тестирования. - person Peter M; 31.10.2014
comment
есть кривая обучения. Я пришел из Java, и мне потребовалось 2 года серьезного кодирования Chef, чтобы добраться до того уровня, в котором я чувствую себя комфортно в Ruby и Chef. Вы доберетесь туда. - person Tejay Cardon; 31.10.2014