diff --git a/lib/bolt/plugin/cache.rb b/lib/bolt/plugin/cache.rb index 64b1766c48..122c90acac 100644 --- a/lib/bolt/plugin/cache.rb +++ b/lib/bolt/plugin/cache.rb @@ -21,7 +21,7 @@ def read_and_clean_cache # Luckily we don't need to use a serious hash algorithm require 'digest/bubblebabble' - r = reference.select { |k, _| k == '_cache' }.sort.to_s + r = reference.reject { |k, _| k == '_cache' }.sort.to_s @id = Digest::SHA2.bubblebabble(r)[0..20] unmodified = true diff --git a/spec/bolt/plugin/cache_spec.rb b/spec/bolt/plugin/cache_spec.rb index 0c2fc015f8..fa2e461670 100644 --- a/spec/bolt/plugin/cache_spec.rb +++ b/spec/bolt/plugin/cache_spec.rb @@ -4,11 +4,12 @@ require 'bolt/plugin/cache' describe Bolt::Plugin::Cache do - let(:reference) { - { '_plugin' => 'task', - 'task' => 'env_plugin::resolve_reference', + let(:env_var) { 'BOLT_TEST_PLUGIN_VALUE' } + let(:reference) do + { '_plugin' => 'env_var', + 'var' => env_var, '_cache' => { 'ttl' => 120 } } - } + end let(:plugin_cache) { Bolt::Plugin::Cache.new(reference, @tmpfile, {}) } around :each do |example| @@ -21,8 +22,8 @@ context "#validate" do context "if _cache is not a Hash" do let(:reference) { - { '_plugin' => 'task', - 'task' => 'env_plugin::resolve_reference', + { '_plugin' => 'env_var', + 'var' => env_var, '_cache' => 120 } } it "fails" do @@ -33,8 +34,8 @@ context "if _cache does not have a ttl key" do let(:reference) { - { '_plugin' => 'task', - 'task' => 'env_plugin::resolve_reference', + { '_plugin' => 'env_var', + 'var' => env_var, '_cache' => { 'tl' => 120 } } } it "fails" do @@ -47,8 +48,8 @@ context "#read_and_clean_cache" do context "with ttl 0" do let(:reference) { - { '_plugin' => 'task', - 'task' => 'env_plugin::resolve_reference', + { '_plugin' => 'env_var', + 'var' => env_var, '_cache' => { 'ttl' => 0 } } } diff --git a/spec/fixtures/plugin_modules/env_plugin/bolt_plugin.json b/spec/fixtures/plugin_modules/env_plugin/bolt_plugin.json deleted file mode 100644 index ffcd4415b0..0000000000 --- a/spec/fixtures/plugin_modules/env_plugin/bolt_plugin.json +++ /dev/null @@ -1 +0,0 @@ -{ } diff --git a/spec/fixtures/plugin_modules/env_plugin/tasks/resolve_reference.json b/spec/fixtures/plugin_modules/env_plugin/tasks/resolve_reference.json deleted file mode 100644 index af0d67d5b2..0000000000 --- a/spec/fixtures/plugin_modules/env_plugin/tasks/resolve_reference.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "description": "Bolt plugin that returns env var BOLT_TEST_PLUGIN_VALUE, used for testing" -} diff --git a/spec/fixtures/plugin_modules/env_plugin/tasks/resolve_reference.rb b/spec/fixtures/plugin_modules/env_plugin/tasks/resolve_reference.rb deleted file mode 100755 index 7682f656bb..0000000000 --- a/spec/fixtures/plugin_modules/env_plugin/tasks/resolve_reference.rb +++ /dev/null @@ -1,6 +0,0 @@ -# frozen_string_literal: true - -require 'json' - -a = { "value" => ENV['BOLT_TEST_PLUGIN_VALUE'] }.to_json -puts a diff --git a/spec/integration/cache_spec.rb b/spec/integration/cache_spec.rb index 4cef3ee906..60a4f71080 100644 --- a/spec/integration/cache_spec.rb +++ b/spec/integration/cache_spec.rb @@ -10,9 +10,11 @@ include BoltSpec::Integration include BoltSpec::Project - let(:project) { @project } - let(:project_path) { @project.path } - let(:inventory) { nil } + let(:project) { @project } + let(:project_path) { @project.path } + let(:inventory) { nil } + let(:user_env_var) { 'BOLT_USER_PLUGIN_VALUE' } + let(:tmpdir_env_var) { 'BOLT_PORT_PLUGIN_VALUE' } let(:mpath) { fixtures_path('plugin_modules') } let(:plan) do <<~PLAN @@ -22,30 +24,72 @@ PLAN end + def plugin(ttl: 120, env_var: user_env_var) + { + '_plugin' => 'env_var', + 'var' => env_var, + '_cache' => { 'ttl' => ttl } + } + end + around(:each) do |example| with_project('cache_test', inventory: inventory) do |project| @project = project - ENV['BOLT_TEST_PLUGIN_VALUE'] = 'player_one' - if plan - FileUtils.mkdir_p(File.join(project_path, 'plans')) - File.write(File.join(project_path, 'plans', 'init.pp'), plan) - end + ENV[user_env_var] = 'player_one' + ENV[tmpdir_env_var] = '/tmp' + FileUtils.mkdir_p(File.join(project_path, 'plans')) + File.write(File.join(project_path, 'plans', 'init.pp'), plan) example.run end end - context 'refreshing cache' do - let(:plugin) { - { - '_plugin' => 'task', - 'task' => 'env_plugin::resolve_reference', - '_cache' => { 'ttl' => 120 } - } - } + context 'setting cache' do + let(:inventory) do + { 'targets' => [ + { 'uri' => 'node1', + 'config' => { + 'ssh' => { + 'user' => plugin, + 'password' => plugin(ttl: 20) + } + } } + ] } + end - let(:inventory) { + it 'sets a unique ID based on the plugin hash minus the _cache' do + run_cli(%W[plan run cache_test --project #{project_path} -m #{mpath}]) + # This should set a unique ID for each different `env_var`, but not + # different `cache` values + expect(JSON.parse(File.read(project.cache_file)).keys) + .to eq(%w[xihev-zaper-kerel-hyl]) + end + + context 'with plugins with different parameters' do + let(:inventory) do + { 'targets' => [ + { 'uri' => 'node1', + 'config' => { + 'ssh' => { + 'user' => plugin, + 'password' => plugin(ttl: 20), + 'tmpdir' => plugin(env_var: tmpdir_env_var) + } + } } + ] } + end + + it 'sets a unique ID based on the plugin hash minus the _cache' do + run_cli(%W[plan run cache_test --project #{project_path} -m #{mpath}]) + expect(JSON.parse(File.read(project.cache_file)).keys) + .to eq(%w[xihev-zaper-kerel-hyl xekin-reryb-tacuf-dis]) + end + end + end + + context 'refreshing cache' do + let(:inventory) do { 'targets' => [ { 'uri' => 'node1', 'config' => { @@ -54,14 +98,14 @@ } } } ] } - } + end it 'removes the existing cache file with --clear-cache' do run_cli(%W[plan run cache_test --project #{project_path} -m #{mpath}]) expect(JSON.parse(File.read(project.cache_file)).values.first) .to include({ 'result' => 'player_one' }) - ENV['BOLT_TEST_PLUGIN_VALUE'] = 'player_two' + ENV[user_env_var] = 'player_two' result = run_cli(%W[plan run cache_test --project #{project_path} -m #{mpath} --clear-cache]) expect(JSON.parse(result)).to eq('player_two') @@ -72,26 +116,29 @@ expect(JSON.parse(File.read(project.cache_file)).values.first) .to include({ 'result' => 'player_one' }) - ENV['BOLT_TEST_PLUGIN_VALUE'] = 'player_two' + ENV[user_env_var] = 'player_two' result = run_cli(%W[plan run cache_test --project #{project_path} -m #{mpath}]) expect(JSON.parse(result)).to eq('player_one') end context 'with a short ttl' do - let(:plugin) { - { - '_plugin' => 'task', - 'task' => 'env_plugin::resolve_reference', - '_cache' => { 'ttl' => 0 } - } - } + let(:inventory) do + { 'targets' => [ + { 'uri' => 'node1', + 'config' => { + 'ssh' => { + 'user' => plugin(ttl: 0) + } + } } + ] } + end it 'removes cache entries once the ttl has expired' do run_cli(%W[plan run cache_test --project #{project_path} -m #{mpath}]) expect(JSON.parse(File.read(project.cache_file)).values.first) .to include({ 'result' => 'player_one' }) - ENV['BOLT_TEST_PLUGIN_VALUE'] = 'player_two' + ENV[user_env_var] = 'player_two' result = run_cli(%W[plan run cache_test --project #{project_path} -m #{mpath}]) expect(JSON.parse(result)).to eq('player_two') end