Puppet 中的 TDD Hiera 哈希

TDD a Hiera hash in Puppet

spec/classes/test_spec.rb

require 'spec_helper'

describe 'test' do
  let(:hiera_data) { { :a => 'hello' } }

  it { should contain_file('/tmp/hello') }
end

manifests/init.pp

class test {
  $a = hiera('a')

  file {"/tmp/$a":}
}

结果:

[vagrant@vm-one test]$ rspec
.

Finished in 1.11 seconds (files took 3 seconds to load)
1 example, 0 failures

问题

TDD Rspec-puppet 中的 Hiera 哈希失败。

尝试次数

let(:hiera_data) { { :a => 'hello', :b => :c => 'world' } }

结果:

[vagrant@vm-one test]$ rspec
/usr/local/share/gems/gems/rspec-core-3.2.3/lib/rspec/core/configuration.rb:1226:in `load': /etc/puppet/modules/test/spec/classes/test_spec.rb:4: syntax error, unexpected =>, expecting '}' (SyntaxError)
        let(:hiera_data) { { :a => 'hello', :b => :c => 'world' } }
                                                       ^
/etc/puppet/modules/test/spec/classes/test_spec.rb:4: syntax error, unexpected '}', expecting keyword_end
        from /usr/local/share/gems/gems/rspec-core-3.2.3/lib/rspec/core/configuration.rb:1226:in `block in load_spec_files'
        from /usr/local/share/gems/gems/rspec-core-3.2.3/lib/rspec/core/configuration.rb:1224:in `each'
        from /usr/local/share/gems/gems/rspec-core-3.2.3/lib/rspec/core/configuration.rb:1224:in `load_spec_files'
        from /usr/local/share/gems/gems/rspec-core-3.2.3/lib/rspec/core/runner.rb:97:in `setup'
        from /usr/local/share/gems/gems/rspec-core-3.2.3/lib/rspec/core/runner.rb:85:in `run'
        from /usr/local/share/gems/gems/rspec-core-3.2.3/lib/rspec/core/runner.rb:70:in `run'
        from /usr/local/share/gems/gems/rspec-core-3.2.3/lib/rspec/core/runner.rb:38:in `invoke'
        from /usr/local/share/gems/gems/rspec-core-3.2.3/exe/rspec:4:in `<top (required)>'
        from /usr/local/bin/rspec:23:in `load'
        from /usr/local/bin/rspec:23:in `<main>'

let(:hiera_data) { { :a => 'hello', :b => 'world' } }

结果:

[vagrant@vm-one test]$ rspec
F

Failures:

  1) test should contain File[/tmp/hello]
     Failure/Error: it { should contain_file('/tmp/hello') }
     Exception:
       Hiera type mismatch: expected Hash and got String
     # /usr/local/share/gems/gems/hiera-puppet-helper-1.0.1/lib/hiera/backend/rspec_backend.rb:47:in `block in lookup'
     # /usr/share/ruby/vendor_ruby/hiera/backend.rb:76:in `block in datasources'
     # /usr/share/ruby/vendor_ruby/hiera/backend.rb:74:in `map'
     # /usr/share/ruby/vendor_ruby/hiera/backend.rb:74:in `datasources'
     # /usr/local/share/gems/gems/hiera-puppet-helper-1.0.1/lib/hiera/backend/rspec_backend.rb:13:in `lookup'
     # /usr/share/ruby/vendor_ruby/hiera/backend.rb:206:in `block in lookup'
     # /usr/share/ruby/vendor_ruby/hiera/backend.rb:203:in `each'
     # /usr/share/ruby/vendor_ruby/hiera/backend.rb:203:in `lookup'
     # /usr/share/ruby/vendor_ruby/hiera.rb:60:in `lookup'
     # /usr/local/share/gems/gems/hiera-puppet-helper-1.0.1/lib/hiera-puppet-helper/puppet.rb:109:in `block in register_function_hiera_hash'
     # /usr/share/ruby/vendor_ruby/puppet/parser/functions.rb:164:in `block (2 levels) in newfunction'
     # /usr/share/ruby/vendor_ruby/puppet/util/profiler/around_profiler.rb:58:in `profile'
     # /usr/share/ruby/vendor_ruby/puppet/util/profiler.rb:51:in `profile'
     # /usr/share/ruby/vendor_ruby/puppet/parser/functions.rb:157:in `block in newfunction'
     # /usr/share/ruby/vendor_ruby/puppet/parser/ast/function.rb:42:in `evaluate'
     # /usr/share/ruby/vendor_ruby/puppet/parser/ast.rb:61:in `safeevaluate'
     # /usr/share/ruby/vendor_ruby/puppet/parser/ast/vardef.rb:14:in `evaluate'
     # /usr/share/ruby/vendor_ruby/puppet/parser/ast.rb:61:in `safeevaluate'
     # /usr/share/ruby/vendor_ruby/puppet/parser/ast/block_expression.rb:11:in `block in evaluate'
     # /usr/share/ruby/vendor_ruby/puppet/parser/ast/block_expression.rb:10:in `each'
     # /usr/share/ruby/vendor_ruby/puppet/parser/ast/block_expression.rb:10:in `evaluate'
     # /usr/share/ruby/vendor_ruby/puppet/parser/ast.rb:61:in `safeevaluate'
     # /usr/share/ruby/vendor_ruby/puppet/resource/type.rb:127:in `evaluate_code'
     # /usr/share/ruby/vendor_ruby/puppet/parser/resource.rb:79:in `evaluate'
     # /usr/share/ruby/vendor_ruby/puppet/parser/compiler.rb:233:in `each'
     # /usr/share/ruby/vendor_ruby/puppet/parser/compiler.rb:233:in `evaluate_classes'
     # /usr/share/ruby/vendor_ruby/puppet/parser/functions/include.rb:31:in `block in <top (required)>'
     # /usr/share/ruby/vendor_ruby/puppet/parser/functions.rb:164:in `block (2 levels) in newfunction'
     # /usr/share/ruby/vendor_ruby/puppet/util/profiler/around_profiler.rb:58:in `profile'
     # /usr/share/ruby/vendor_ruby/puppet/util/profiler.rb:51:in `profile'
     # /usr/share/ruby/vendor_ruby/puppet/parser/functions.rb:157:in `block in newfunction'
     # /usr/share/ruby/vendor_ruby/puppet/parser/ast/function.rb:42:in `evaluate'
     # /usr/share/ruby/vendor_ruby/puppet/parser/ast.rb:61:in `safeevaluate'
     # /usr/share/ruby/vendor_ruby/puppet/parser/ast/block_expression.rb:11:in `block in evaluate'
     # /usr/share/ruby/vendor_ruby/puppet/parser/ast/block_expression.rb:10:in `each'
     # /usr/share/ruby/vendor_ruby/puppet/parser/ast/block_expression.rb:10:in `evaluate'
     # /usr/share/ruby/vendor_ruby/puppet/parser/ast.rb:61:in `safeevaluate'
     # /usr/share/ruby/vendor_ruby/puppet/resource/type.rb:127:in `evaluate_code'
     # /usr/share/ruby/vendor_ruby/puppet/parser/resource.rb:79:in `evaluate'
     # /usr/share/ruby/vendor_ruby/puppet/parser/compiler.rb:425:in `evaluate_main'
     # /usr/share/ruby/vendor_ruby/puppet/parser/compiler.rb:131:in `block (2 levels) in compile'
     # /usr/share/ruby/vendor_ruby/puppet/util/profiler/around_profiler.rb:58:in `profile'
     # /usr/share/ruby/vendor_ruby/puppet/util/profiler.rb:51:in `profile'
     # /usr/share/ruby/vendor_ruby/puppet/parser/compiler.rb:131:in `block in compile'
     # /usr/share/ruby/vendor_ruby/puppet/context.rb:64:in `override'
     # /usr/share/ruby/vendor_ruby/puppet.rb:244:in `override'
     # /usr/share/ruby/vendor_ruby/puppet/parser/compiler.rb:117:in `compile'
     # /usr/local/share/gems/gems/hiera-puppet-helper-1.0.1/lib/hiera-puppet-helper/puppet.rb:16:in `compile'
     # /usr/share/ruby/vendor_ruby/puppet/parser/compiler.rb:34:in `compile'
     # /usr/share/ruby/vendor_ruby/puppet/indirector/catalog/compiler.rb:95:in `block (2 levels) in compile'
     # /usr/share/ruby/vendor_ruby/puppet/util/profiler/around_profiler.rb:58:in `profile'
     # /usr/share/ruby/vendor_ruby/puppet/util/profiler.rb:51:in `profile'
     # /usr/share/ruby/vendor_ruby/puppet/indirector/catalog/compiler.rb:93:in `block in compile'
     # /usr/share/ruby/vendor_ruby/puppet/util.rb:161:in `block in benchmark'
     # /usr/share/ruby/benchmark.rb:296:in `realtime'
     # /usr/share/ruby/vendor_ruby/puppet/util.rb:160:in `benchmark'
     # /usr/share/ruby/vendor_ruby/puppet/indirector/catalog/compiler.rb:92:in `compile'
     # /usr/share/ruby/vendor_ruby/puppet/indirector/catalog/compiler.rb:52:in `find'
     # /usr/share/ruby/vendor_ruby/puppet/indirector/indirection.rb:201:in `find'
     # /usr/local/share/gems/gems/rspec-puppet-2.1.0/lib/rspec-puppet/support.rb:184:in `build_catalog_without_cache'
     # /usr/local/share/gems/gems/rspec-puppet-2.1.0/lib/rspec-puppet/support.rb:193:in `build_catalog'
     # /usr/local/share/gems/gems/rspec-puppet-2.1.0/lib/rspec-puppet/support.rb:25:in `load_catalogue'
     # /usr/local/share/gems/gems/rspec-puppet-2.1.0/lib/rspec-puppet/example/class_example_group.rb:7:in `catalogue'
     # /usr/local/share/gems/gems/rspec-puppet-2.1.0/lib/rspec-puppet/support.rb:7:in `block in subject'
     # /usr/local/share/gems/gems/rspec-puppet-2.1.0/lib/rspec-puppet/matchers/create_generic.rb:82:in `call'
     # /usr/local/share/gems/gems/rspec-puppet-2.1.0/lib/rspec-puppet/matchers/create_generic.rb:82:in `matches?'
     # ./spec/classes/test_spec.rb:6:in `block (2 levels) in <top (required)>'

Finished in 1.11 seconds (files took 2.76 seconds to load)
1 example, 1 failure

Failed examples:

rspec ./spec/classes/test_spec.rb:6 # test should contain File[/tmp/hello]

let(:hiera_data) { { :a => 'hello', :b => 'world','blabla' } }

结果:

[vagrant@vm-one test]$ rspec
/usr/local/share/gems/gems/rspec-core-3.2.3/lib/rspec/core/configuration.rb:1226:in `load': /etc/puppet/modules/test/spec/classes/test_spec.rb:4: syntax error, unexpected '}', expecting => (SyntaxError)
        let(:hiera_data) { { :a => 'hello', :b => 'world','blabla' } }
                                                                    ^
/etc/puppet/modules/test/spec/classes/test_spec.rb:10: syntax error, unexpected keyword_end, expecting '}'
        from /usr/local/share/gems/gems/rspec-core-3.2.3/lib/rspec/core/configuration.rb:1226:in `block in load_spec_files'
        from /usr/local/share/gems/gems/rspec-core-3.2.3/lib/rspec/core/configuration.rb:1224:in `each'
        from /usr/local/share/gems/gems/rspec-core-3.2.3/lib/rspec/core/configuration.rb:1224:in `load_spec_files'
        from /usr/local/share/gems/gems/rspec-core-3.2.3/lib/rspec/core/runner.rb:97:in `setup'
        from /usr/local/share/gems/gems/rspec-core-3.2.3/lib/rspec/core/runner.rb:85:in `run'
        from /usr/local/share/gems/gems/rspec-core-3.2.3/lib/rspec/core/runner.rb:70:in `run'
        from /usr/local/share/gems/gems/rspec-core-3.2.3/lib/rspec/core/runner.rb:38:in `invoke'
        from /usr/local/share/gems/gems/rspec-core-3.2.3/exe/rspec:4:in `<top (required)>'
        from /usr/local/bin/rspec:23:in `load'
        from /usr/local/bin/rspec:23:in `<main>'

let(:hiera_data) { { :a => 'hello', :b => {'world','blabla'} } }

结果:

[vagrant@vm-one test]$ rspec
/usr/local/share/gems/gems/rspec-core-3.2.3/lib/rspec/core/configuration.rb:1226:in `load': /etc/puppet/modules/test/spec/classes/test_spec.rb:4: syntax error, unexpected ',', expecting => (SyntaxError)
        let(:hiera_data) { { :a => 'hello', :b => {'world','blabla'} } }
                                                           ^
/etc/puppet/modules/test/spec/classes/test_spec.rb:4: syntax error, unexpected '}', expecting keyword_end
        let(:hiera_data) { { :a => 'hello', :b => {'world','blabla'} } }
                                                                      ^
        from /usr/local/share/gems/gems/rspec-core-3.2.3/lib/rspec/core/configuration.rb:1226:in `block in load_spec_files'
        from /usr/local/share/gems/gems/rspec-core-3.2.3/lib/rspec/core/configuration.rb:1224:in `each'
        from /usr/local/share/gems/gems/rspec-core-3.2.3/lib/rspec/core/configuration.rb:1224:in `load_spec_files'
        from /usr/local/share/gems/gems/rspec-core-3.2.3/lib/rspec/core/runner.rb:97:in `setup'
        from /usr/local/share/gems/gems/rspec-core-3.2.3/lib/rspec/core/runner.rb:85:in `run'
        from /usr/local/share/gems/gems/rspec-core-3.2.3/lib/rspec/core/runner.rb:70:in `run'
        from /usr/local/share/gems/gems/rspec-core-3.2.3/lib/rspec/core/runner.rb:38:in `invoke'
        from /usr/local/share/gems/gems/rspec-core-3.2.3/exe/rspec:4:in `<top (required)>'
        from /usr/local/bin/rspec:23:in `load'
        from /usr/local/bin/rspec:23:in `<main>'

限制 rspec-puppet 的测试也不起作用:

spec/fixtures/hiera/test.yaml

[vagrant@vm-one test]$ cat spec/fixtures/hiera/test.yaml
---
a: hello
b: world
  c: alloallo

失败

[vagrant@vm-one test]$ rspec
F

Failures:

  1) test should contain File[/tmp/hello]
     Failure/Error: it { should contain_file('/tmp/hello') }
     Puppet::Error:
       (<unknown>): mapping values are not allowed in this context at line 4 column 4 at /etc/puppet/modules/test/spec/fixtures/modules/test/manifests/init.pp:2 on node vm-one.domain
     # /usr/share/ruby/psych.rb:205:in `parse'
     # /usr/share/ruby/psych.rb:205:in `parse_stream'
     # /usr/share/ruby/psych.rb:153:in `parse'
     # /usr/share/ruby/psych.rb:129:in `load'
     # /usr/share/ruby/vendor_ruby/puppet/vendor/safe_yaml/lib/safe_yaml.rb:144:in `load_with_options'
     # /usr/share/ruby/vendor_ruby/hiera/backend/yaml_backend.rb:18:in `block (2 levels) in lookup'
     # /usr/share/ruby/vendor_ruby/hiera/filecache.rb:53:in `read_file'
     # /usr/share/ruby/vendor_ruby/hiera/backend/yaml_backend.rb:17:in `block in lookup'
     # /usr/share/ruby/vendor_ruby/hiera/backend.rb:104:in `block in datasourcefiles'
     # /usr/share/ruby/vendor_ruby/hiera/backend.rb:76:in `block in datasources'
     # /usr/share/ruby/vendor_ruby/hiera/backend.rb:74:in `map'
     # /usr/share/ruby/vendor_ruby/hiera/backend.rb:74:in `datasources'
     # /usr/share/ruby/vendor_ruby/hiera/backend.rb:99:in `datasourcefiles'
     # /usr/share/ruby/vendor_ruby/hiera/backend/yaml_backend.rb:16:in `lookup'
     # /usr/share/ruby/vendor_ruby/hiera/backend.rb:206:in `block in lookup'
     # /usr/share/ruby/vendor_ruby/hiera/backend.rb:203:in `each'
     # /usr/share/ruby/vendor_ruby/hiera/backend.rb:203:in `lookup'
     # /usr/share/ruby/vendor_ruby/hiera.rb:60:in `lookup'
     # /usr/share/ruby/vendor_ruby/hiera_puppet.rb:11:in `lookup'
     # /usr/share/ruby/vendor_ruby/puppet/parser/functions/hiera.rb:32:in `block in <module:Functions>'
     # /usr/share/ruby/vendor_ruby/puppet/parser/functions.rb:164:in `block (2 levels) in newfunction'
     # /usr/share/ruby/vendor_ruby/puppet/util/profiler/around_profiler.rb:58:in `profile'
     # /usr/share/ruby/vendor_ruby/puppet/util/profiler.rb:51:in `profile'
     # /usr/share/ruby/vendor_ruby/puppet/parser/functions.rb:157:in `block in newfunction'
     # /usr/share/ruby/vendor_ruby/puppet/parser/ast/function.rb:42:in `evaluate'
     # /usr/share/ruby/vendor_ruby/puppet/parser/ast.rb:61:in `safeevaluate'
     # /usr/share/ruby/vendor_ruby/puppet/parser/ast/vardef.rb:14:in `evaluate'
     # /usr/share/ruby/vendor_ruby/puppet/parser/ast.rb:61:in `safeevaluate'
     # /usr/share/ruby/vendor_ruby/puppet/parser/ast/block_expression.rb:11:in `block in evaluate'
     # /usr/share/ruby/vendor_ruby/puppet/parser/ast/block_expression.rb:10:in `each'
     # /usr/share/ruby/vendor_ruby/puppet/parser/ast/block_expression.rb:10:in `evaluate'
     # /usr/share/ruby/vendor_ruby/puppet/parser/ast.rb:61:in `safeevaluate'
     # /usr/share/ruby/vendor_ruby/puppet/resource/type.rb:127:in `evaluate_code'
     # /usr/share/ruby/vendor_ruby/puppet/parser/resource.rb:79:in `evaluate'
     # /usr/share/ruby/vendor_ruby/puppet/parser/compiler.rb:233:in `each'
     # /usr/share/ruby/vendor_ruby/puppet/parser/compiler.rb:233:in `evaluate_classes'
     # /usr/share/ruby/vendor_ruby/puppet/parser/functions/include.rb:31:in `block in <top (required)>'
     # /usr/share/ruby/vendor_ruby/puppet/parser/functions.rb:164:in `block (2 levels) in newfunction'
     # /usr/share/ruby/vendor_ruby/puppet/util/profiler/around_profiler.rb:58:in `profile'
     # /usr/share/ruby/vendor_ruby/puppet/util/profiler.rb:51:in `profile'
     # /usr/share/ruby/vendor_ruby/puppet/parser/functions.rb:157:in `block in newfunction'
     # /usr/share/ruby/vendor_ruby/puppet/parser/ast/function.rb:42:in `evaluate'
     # /usr/share/ruby/vendor_ruby/puppet/parser/ast.rb:61:in `safeevaluate'
     # /usr/share/ruby/vendor_ruby/puppet/parser/ast/block_expression.rb:11:in `block in evaluate'
     # /usr/share/ruby/vendor_ruby/puppet/parser/ast/block_expression.rb:10:in `each'
     # /usr/share/ruby/vendor_ruby/puppet/parser/ast/block_expression.rb:10:in `evaluate'
     # /usr/share/ruby/vendor_ruby/puppet/parser/ast.rb:61:in `safeevaluate'
     # /usr/share/ruby/vendor_ruby/puppet/resource/type.rb:127:in `evaluate_code'
     # /usr/share/ruby/vendor_ruby/puppet/parser/resource.rb:79:in `evaluate'
     # /usr/share/ruby/vendor_ruby/puppet/parser/compiler.rb:425:in `evaluate_main'
     # /usr/share/ruby/vendor_ruby/puppet/parser/compiler.rb:131:in `block (2 levels) in compile'
     # /usr/share/ruby/vendor_ruby/puppet/util/profiler/around_profiler.rb:58:in `profile'
     # /usr/share/ruby/vendor_ruby/puppet/util/profiler.rb:51:in `profile'
     # /usr/share/ruby/vendor_ruby/puppet/parser/compiler.rb:131:in `block in compile'
     # /usr/share/ruby/vendor_ruby/puppet/context.rb:64:in `override'
     # /usr/share/ruby/vendor_ruby/puppet.rb:244:in `override'
     # /usr/share/ruby/vendor_ruby/puppet/parser/compiler.rb:117:in `compile'
     # /usr/share/ruby/vendor_ruby/puppet/parser/compiler.rb:34:in `compile'
     # /usr/share/ruby/vendor_ruby/puppet/indirector/catalog/compiler.rb:95:in `block (2 levels) in compile'
     # /usr/share/ruby/vendor_ruby/puppet/util/profiler/around_profiler.rb:58:in `profile'
     # /usr/share/ruby/vendor_ruby/puppet/util/profiler.rb:51:in `profile'
     # /usr/share/ruby/vendor_ruby/puppet/indirector/catalog/compiler.rb:93:in `block in compile'
     # /usr/share/ruby/vendor_ruby/puppet/util.rb:161:in `block in benchmark'
     # /usr/share/ruby/benchmark.rb:296:in `realtime'
     # /usr/share/ruby/vendor_ruby/puppet/util.rb:160:in `benchmark'
     # /usr/share/ruby/vendor_ruby/puppet/indirector/catalog/compiler.rb:92:in `compile'
     # /usr/share/ruby/vendor_ruby/puppet/indirector/catalog/compiler.rb:52:in `find'
     # /usr/share/ruby/vendor_ruby/puppet/indirector/indirection.rb:201:in `find'
     # /usr/local/share/gems/gems/rspec-puppet-2.1.0/lib/rspec-puppet/support.rb:184:in `build_catalog_without_cache'
     # /usr/local/share/gems/gems/rspec-puppet-2.1.0/lib/rspec-puppet/support.rb:193:in `build_catalog'
     # /usr/local/share/gems/gems/rspec-puppet-2.1.0/lib/rspec-puppet/support.rb:25:in `load_catalogue'
     # /usr/local/share/gems/gems/rspec-puppet-2.1.0/lib/rspec-puppet/example/class_example_group.rb:7:in `catalogue'
     # /usr/local/share/gems/gems/rspec-puppet-2.1.0/lib/rspec-puppet/support.rb:7:in `block in subject'
     # /usr/local/share/gems/gems/rspec-puppet-2.1.0/lib/rspec-puppet/matchers/create_generic.rb:82:in `call'
     # /usr/local/share/gems/gems/rspec-puppet-2.1.0/lib/rspec-puppet/matchers/create_generic.rb:82:in `matches?'
     # ./spec/classes/test_spec.rb:18:in `block (2 levels) in <top (required)>'

Finished in 0.31976 seconds (files took 2.69 seconds to load)
1 example, 1 failure

Failed examples:

rspec ./spec/classes/test_spec.rb:18 # test should contain File[/tmp/hello]

看起来 所有 你的散列文字格式不正确。

尝试

let(:hiera_data) do
  { :a => 'hello', :b => { :c => 'world' } }
end

现在 hiera('b') 应该 return 一个散列值。