require 'spec_helper' require 'puppet_spec/files' require 'puppet_spec/compiler' require 'deep_merge/core' describe 'lookup' do include PuppetSpec::Files context 'with an environment' do let(:env_name) { 'spec' } let(:env_dir) { tmpdir('environments') } let(:environment_files) do { env_name => { 'modules' => {}, 'hiera.yaml' => <<-YAML.unindent, --- version: 5 hierarchy: - name: "Common" data_hash: yaml_data path: "common.yaml" YAML 'data' => { 'common.yaml' => <<-YAML.unindent --- a: value a mod_a::a: value mod_a::a (from environment) mod_a::hash_a: a: value mod_a::hash_a.a (from environment) mod_a::hash_b: a: value mod_a::hash_b.a (from environment) lookup_options: mod_a::hash_b: merge: hash YAML } }, 'someother' => { } } end let(:app) { Puppet::Application[:lookup] } let(:env) { Puppet::Node::Environment.create(env_name.to_sym, [File.join(populated_env_dir, env_name, 'modules')]) } let(:environments) { Puppet::Environments::Directories.new(populated_env_dir, []) } let(:populated_env_dir) do dir_contained_in(env_dir, environment_files) env_dir end def lookup(key, options = {}, explain = false) key = [key] unless key.is_a?(Array) allow(app.command_line).to receive(:args).and_return(key) if explain app.options[:explain] = true app.options[:render_as] = :s else app.options[:render_as] = :json end options.each_pair { |k, v| app.options[k] = v } capture = StringIO.new saved_stdout = $stdout begin $stdout = capture expect { app.run_command }.to exit_with(0) ensure $stdout = saved_stdout end out = capture.string.strip if explain out else out.empty? ? nil : JSON.parse("[#{out}]")[0] end end def explain(key, options = {}) lookup(key, options, true) end around(:each) do |example| Puppet.override(:environments => environments, :current_environment => env) do example.run end end it 'finds data in the environment' do expect(lookup('a')).to eql('value a') end context 'uses node_terminus' do require 'puppet/indirector/node/exec' require 'puppet/indirector/node/plain' let(:node) { Puppet::Node.new('testnode', :environment => env) } it ':plain without --compile' do Puppet.settings[:node_terminus] = 'exec' expect_any_instance_of(Puppet::Node::Plain).to receive(:find).and_return(node) expect_any_instance_of(Puppet::Node::Exec).not_to receive(:find) expect(lookup('a')).to eql('value a') end it 'configured in Puppet settings with --compile' do Puppet.settings[:node_terminus] = 'exec' expect_any_instance_of(Puppet::Node::Plain).not_to receive(:find) expect_any_instance_of(Puppet::Node::Exec).to receive(:find).and_return(node) expect(lookup('a', :compile => true)).to eql('value a') end end context 'configured with the wrong environment' do let(:env) { Puppet::Node::Environment.create(env_name.to_sym, [File.join(populated_env_dir, env_name, 'modules')]) } it 'does not find data in non-existing environment' do Puppet.override(:environments => environments, :current_environment => 'someother') do expect(lookup('a', {}, true)).to match(/did not find a value for the name 'a'/) end end end context 'and a module' do let(:mod_a_files) do { 'mod_a' => { 'data' => { 'common.yaml' => <<-YAML.unindent --- mod_a::a: value mod_a::a (from mod_a) mod_a::b: value mod_a::b (from mod_a) mod_a::hash_a: a: value mod_a::hash_a.a (from mod_a) b: value mod_a::hash_a.b (from mod_a) mod_a::hash_b: a: value mod_a::hash_b.a (from mod_a) b: value mod_a::hash_b.b (from mod_a) mod_a::interpolated: "-- %{lookup('mod_a::a')} --" mod_a::a_a: "-- %{lookup('mod_a::hash_a.a')} --" mod_a::a_b: "-- %{lookup('mod_a::hash_a.b')} --" mod_a::b_a: "-- %{lookup('mod_a::hash_b.a')} --" mod_a::b_b: "-- %{lookup('mod_a::hash_b.b')} --" 'mod_a::a.quoted.key': 'value mod_a::a.quoted.key (from mod_a)' YAML }, 'hiera.yaml' => <<-YAML.unindent, --- version: 5 hierarchy: - name: "Common" data_hash: yaml_data path: "common.yaml" YAML } } end let(:populated_env_dir) do dir_contained_in(env_dir, DeepMerge.deep_merge!(environment_files, env_name => { 'modules' => mod_a_files })) env_dir end it 'finds data in the module' do expect(lookup('mod_a::b')).to eql('value mod_a::b (from mod_a)') end it 'finds quoted keys in the module' do expect(lookup('"mod_a::a.quoted.key"')).to eql('value mod_a::a.quoted.key (from mod_a)') end it 'merges hashes from environment and module when merge strategy hash is used' do expect(lookup('mod_a::hash_a', :merge => 'hash')).to eql({'a' => 'value mod_a::hash_a.a (from environment)', 'b' => 'value mod_a::hash_a.b (from mod_a)'}) end end end end