【问题标题】:Chef, ruby hashes and templates厨师、红宝石哈希和模板
【发布时间】:2017-10-05 21:07:31
【问题描述】:

我知道这是一个ruby 的问题,而不是chef,但是...

我有一些属性,例如:

default['my_cookbook']['some_namespace1']['some_attribute1'] = 'some_value1'
default['my_cookbook']['some_namespace1']['some_attribute2'] = 'some_value2'
default['my_cookbook']['some_namespace1']['some_attribute2'] = 'some_value3'
...
default['my_cookbook']['some_namespace2']['some_attribute1'] = 'some_value1'
default['my_cookbook']['some_namespace2']['some_attribute2'] = 'some_value2'
default['my_cookbook']['some_namespace2']['some_attribute2'] = 'some_value3'
...

另一方面,我正在创建这样的模板资源:

template 'template_name' do
  source 'template_source.erb'
  variables (
    my_namespace_1: node['my_cookbook']['some_namespace1'],
    my_namespace_2: node['my_cookbook']['some_namespace2']
  )
end

然后在template_source.erb我试试:

...
<%= @my_namespace_1['some_attribute1'] %> #=> 'some_value1'
...

但是,当我运行 Kitchen 时,我得到了这个,而不是 'some_value1'

Chef::Mixin::Template::TemplateError
------------------------------------
undefined method `[]' for nil:NilClass

我应该如何发送模板变量以这样使用它?

【问题讨论】:

    标签: ruby-on-rails ruby chef-infra


    【解决方案1】:

    编辑:这仅适用于一般的 Ruby,而不是特别适用于 Chef。

    传递嵌套哈希:

    template 'template_name' do
      source 'template_source.erb'
      variables (
        my_namespace_1: {
          some_attribute1: node['my_cookbook']['some_namespace1']['some_attribute1']
        }
      )
    end
    

    但您可以使用Hash class 的全部功能来切片、切块和合并任何您想要的东西,而不是逐字复制值:

    template 'template_name' do
      source 'template_source.erb'
      variables (
        node['my_cookbook'].slice('some_namespace1', 'some_namespace2')
      )
    end
    

    您在 Ruby 中遇到的一个问题是符号通常用作哈希键:

    # newer literal syntax
    a_hash = {
      foo: 'bar'
    }
    
    # or with the older hash-rocket syntax
    a_hash = {
      :foo => 'bar'
    }
    

    符号是非常有效的,因为它们是存储在表中的内部字符串 - 比较符号时,您比较对象 ID 而不是比较字符串中的每个字符。

    事实上,只有当你想要哈希中的键不是有效的 Ruby 符号时才真正使用字符串——比如在构建 HTTP 标头的哈希时。

    Ruby 不会冷漠对待符号和字符串键:

    {
      foo: 'bar'
    }[:foo] 
    # => bar
    
    {
      foo: 'bar'
    }['foo'] 
    # => nil
    

    所以要访问模板中传递的变量,您将使用:

    <%= @my_namespace_1[:some_attribute1] %>
    

    【讨论】:

    • 非常感谢您提供的信息!只是嵌套的哈希就可以了,但是知道所有其他信息也很好。
    • Chef 可能会使用来自 ActiveSupport (Rails) 的 HashWithIndifferentAccess,它是哈希的子类,它对字符串和符号键的处理方式相同。否则,如果它只是一个普通的 Ruby 哈希,你会得到 nil。
    • 我们不使用它,但我们有类似的东西。
    • 事实上,这整个答案在 Chef 的上下文中基本上是不正确的。
    • 我们不建议在节点属性中使用符号键,将部分属性树传递给模板是 100% 可以的。
    【解决方案2】:

    您在示例中的内容应该可以正常工作。我猜你在对代码进行通用化时纠正了原始配方中的某个错字。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-10-19
      • 1970-01-01
      • 2012-12-19
      • 1970-01-01
      • 2013-02-03
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多