无法将“每个”中的元素与节点属性结合起来

Posted

技术标签:

【中文标题】无法将“每个”中的元素与节点属性结合起来【英文标题】:Trouble combining element in 'each' do block with node attribute 【发布时间】:2014-12-23 23:47:43 【问题描述】:

我正在使用在 AWS Opsworks 中运行的 Chef 11.10.4。

我不知道如何将元素 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 食谱以使用 node['aws-tag']['tags'] 中的标签标记所有 ec2 实例,并且除了标记每个 ec2 实例 opsworks 层特定标签之外,这些标签包含在按层传递给 opsworks 的自定义 JSON 中,在此一般情况下node['aws-tag']['mongodb']node['aws-tag']['LAYER'] 的内容。

如果我运行上面的代码,我会收到一个配方编译错误:“unexpected keyword_do_block, expecting ']'”——请参阅下面的 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)

【问题讨论】:

这是哪里出了问题?例如,您甚至到达了第 09 行还是第 08 行评估为假并结束您的执行? 我们需要一个显示问题的真实代码的最小示例,而不是伪代码。否则我们并没有真正解决这个问题,我们正在解决一个伪问题。 我很抱歉@TejayCardon - 错误在第 9 行:意外的关键字_do_block,期待 ']'。我在帖子中添加了详细的输出。 我很抱歉@theTinMan -- 这是真正的代码,但我知道它会中断,因为我使用的是没有字符串的字符串函数。我在帖子中添加了详细的输出。 【参考方案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

我在 chef-shell 中交互地测试了它,但它没有工作,但我猜在运行时执行它时会有一些不同,因为它确实在那里工作。这是我在 chef-shell 中失败的测试的输出,我认为是同一件事:

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 ubuntu@mongodb2.localdomain!
chef > lyr=node['opsworks']['instance']['layers']
 => ["mongodb"]
chef > lyr
 => ["mongodb"]
chef > node['aws-tag'][lyr]
 => nil
chef >

【讨论】:

lyr=node['opsworks']['instance']['layers']node['opsworks']['instance']['layers'].each do |lyr| 不同 @TejayCardon 我知道我的测试不够充分。在 shell 测试中,数组 node['opsworks']['instance']['layers'] 中只有一项,所以我认为它是相同的。但是,在我的 chef-shell 示例中不是 lyr 字符串,如果是,那么为什么 node['aws-tag'][lyr] 不工作,如果 node['aws-tag']['mongodb'] 可以在同一个 shell 中工作? 这就是我的意思。在 shell 测试中,lyr 不是字符串,它是一个数组。['mongodb'] 仅仅因为数组只有一个元素并不意味着它不是仍然是一个数组。如果你想避免循环,你可以在测试中使用lyr[0] @TejayCardon -- 非常感谢您抽出时间来上学,抱歉这么密集。这很有效,非常有帮助。我也可以在测试的时候直接做 node['aws-tag'][node['opsworks']['instance']['layers'][0]] 。 有一个学习曲线。我来自 Java 背景,我花了 2 年的扎实的 Chef 编码来达到我在 Ruby 和 Chef 方面的舒适度。你会到达那里的。

以上是关于无法将“每个”中的元素与节点属性结合起来的主要内容,如果未能解决你的问题,请参考以下文章

setAttribute()

如何获取每个节点的 href 元素和属性?

JavaScript Dom节点

DOM中节点

如何使用 jQuery 选择文本节点?

Dom Document