diff --git a/spec/acceptance/tests/acceptance_spec.rb b/spec/acceptance/tests/acceptance_spec.rb index e48a8c7..c942c9d 100644 --- a/spec/acceptance/tests/acceptance_spec.rb +++ b/spec/acceptance/tests/acceptance_spec.rb @@ -1,92 +1,92 @@ require 'spec_helper_acceptance' require 'helpers/acceptance/tests/basic_shared_examples.rb' require 'helpers/acceptance/tests/template_shared_examples.rb' require 'helpers/acceptance/tests/removal_shared_examples.rb' require 'helpers/acceptance/tests/pipeline_shared_examples.rb' require 'helpers/acceptance/tests/plugin_shared_examples.rb' require 'helpers/acceptance/tests/plugin_upgrade_shared_examples.rb' require 'helpers/acceptance/tests/snapshot_repository_shared_examples.rb' require 'helpers/acceptance/tests/datadir_shared_examples.rb' require 'helpers/acceptance/tests/package_url_shared_examples.rb' require 'helpers/acceptance/tests/hiera_shared_examples.rb' require 'helpers/acceptance/tests/usergroup_shared_examples.rb' require 'helpers/acceptance/tests/security_shared_examples.rb' describe "elasticsearch v#{v[:elasticsearch_full_version]} class" do es_config = { 'http.port' => 9200, 'node.name' => 'elasticsearch01' } let(:elastic_repo) { not v[:is_snapshot] } let(:manifest) do package = if not v[:is_snapshot] <<-MANIFEST # Hard version set here due to plugin incompatibilities. version => '#{v[:elasticsearch_full_version]}', MANIFEST else <<-MANIFEST manage_repo => false, package_url => '#{v[:snapshot_package]}', MANIFEST end <<-MANIFEST api_timeout => 60, config => { 'cluster.name' => '#{v[:cluster_name]}', 'http.bind_host' => '0.0.0.0', #{es_config.map { |k, v| " '#{k}' => '#{v}'," }.join("\n")} }, jvm_options => [ '-Xms128m', '-Xmx128m', ], oss => #{v[:oss]}, #{package} MANIFEST end context 'testing with' do describe 'simple config' do include_examples('basic acceptance tests', es_config) end include_examples('module removal', es_config) end include_examples('template operations', es_config, v[:template]) include_examples('pipeline operations', es_config, v[:pipeline]) - # include_examples('plugin acceptance tests', v[:elasticsearch_plugins]) unless v[:elasticsearch_plugins].empty? + include_examples('plugin acceptance tests', es_config, v[:elasticsearch_plugins]) unless v[:elasticsearch_plugins].empty? # # Only pre-5.x versions supported versions differing from core ES # if semver(v[:elasticsearch_full_version]) < semver('5.0.0') # include_examples( # 'plugin upgrade acceptance tests', # :name => 'kopf', # :initial => '2.0.1', # :upgraded => '2.1.2', # :repository => 'lmenezes/elasticsearch' # ) # end # include_examples 'snapshot repository acceptance tests' # include_examples 'datadir acceptance tests' # # Skip this for snapshot testing, as we only have package files anyway. # include_examples 'package_url acceptance tests' unless v[:is_snapshot] # include_examples 'hiera acceptance tests', v[:elasticsearch_plugins] # include_examples 'user/group acceptance tests' # # Security-related tests (shield/x-pack). # # # # Skip OSS-only distributions since they do not bundle x-pack, and skip # # snapshots since we they don't recognize prod licenses. # include_examples 'security acceptance tests', instances unless v[:oss] or v[:is_snapshot] end diff --git a/spec/helpers/acceptance/tests/bad_manifest_shared_examples.rb b/spec/helpers/acceptance/tests/bad_manifest_shared_examples.rb index 9fc1a4b..c6dc2de 100644 --- a/spec/helpers/acceptance/tests/bad_manifest_shared_examples.rb +++ b/spec/helpers/acceptance/tests/bad_manifest_shared_examples.rb @@ -1,18 +1,18 @@ shared_examples 'invalid manifest application' do context 'bad manifest' do let(:applied_manifest) do <<-MANIFEST class { 'elasticsearch' : #{manifest} #{defined?(manifest_class_parameters) && manifest_class_parameters} } #{defined?(extra_manifest) && extra_manifest} MANIFEST end it 'fails to apply' do - apply_manifest applied_manifest, :expect_failures => true + apply_manifest(applied_manifest, :expect_failures => true, :debug => v[:puppet_debug]) end end end diff --git a/spec/helpers/acceptance/tests/plugin_api_shared_examples.rb b/spec/helpers/acceptance/tests/plugin_api_shared_examples.rb index 91c44f2..d61cc12 100644 --- a/spec/helpers/acceptance/tests/plugin_api_shared_examples.rb +++ b/spec/helpers/acceptance/tests/plugin_api_shared_examples.rb @@ -1,23 +1,21 @@ require 'json' -shared_examples 'plugin API response' do |instances, desc, val| - instances.each_pair do |_instance, i| - describe port(i['config']['http.port']) do - it 'open', :with_retries do - should be_listening - end +shared_examples 'plugin API response' do |es_config, desc, val| + describe port(es_config['http.port']) do + it 'open', :with_retries do + should be_listening end + end - describe server :container do - describe http( - "http://localhost:#{i['config']['http.port']}/_cluster/stats" - ) do - it desc, :with_retries do - expect( - JSON.parse(response.body)['nodes']['plugins'] - ).to include(include(val)) - end + describe server :container do + describe http( + "http://localhost:#{es_config['http.port']}/_cluster/stats" + ) do + it desc, :with_retries do + expect( + JSON.parse(response.body)['nodes']['plugins'] + ).to include(include(val)) end end end end diff --git a/spec/helpers/acceptance/tests/plugin_shared_examples.rb b/spec/helpers/acceptance/tests/plugin_shared_examples.rb index 87c9894..6628998 100644 --- a/spec/helpers/acceptance/tests/plugin_shared_examples.rb +++ b/spec/helpers/acceptance/tests/plugin_shared_examples.rb @@ -1,125 +1,98 @@ require 'json' require 'helpers/acceptance/tests/bad_manifest_shared_examples' require 'helpers/acceptance/tests/manifest_shared_examples' require 'helpers/acceptance/tests/plugin_api_shared_examples' -shared_examples 'plugin acceptance tests' do |plugins| +shared_examples 'plugin acceptance tests' do |es_config, plugins| describe 'elasticsearch::plugin' do - instances = { - 'es-01' => { - 'config' => { - 'http.port' => 9200, - 'node.name' => 'elasticsearch001' - } - } - } - describe 'invalid plugins', :with_cleanup do let(:extra_manifest) do <<-MANIFEST - elasticsearch::plugin { 'elastic/non-existing': - instances => 'es-01', - } + elasticsearch::plugin { 'elastic/non-existing': } MANIFEST end - include_examples( - 'invalid manifest application', - instances - ) + include_examples('invalid manifest application') end before :all do shell "mkdir -p #{default['distmoduledir']}/another/files" end plugins.each_pair do |plugin, meta| describe plugin do # Ensure that instances are restarted to include plugins let(:manifest_class_parameters) { 'restart_on_change => true' } describe 'installation' do describe 'using simple names', :with_cleanup do let(:extra_manifest) do <<-MANIFEST - elasticsearch::plugin { '#{plugin}': - instances => 'es-01', - } + elasticsearch::plugin { '#{plugin}': } MANIFEST end - include_examples( - 'manifest application', - instances - ) + include_examples('manifest application', es_config) describe file("/usr/share/elasticsearch/plugins/#{plugin}/") do it { should be_directory } end include_examples( 'plugin API response', - instances, + es_config, 'reports the plugin as installed', 'name' => plugin ) end describe 'offline via puppet://', :with_cleanup do before :all do scp_to( default, meta[:path], "#{default['distmoduledir']}/another/files/#{plugin}.zip" ) end let(:extra_manifest) do <<-MANIFEST elasticsearch::plugin { '#{plugin}': - instances => 'es-01', - source => 'puppet:///modules/another/#{plugin}.zip', + source => 'puppet:///modules/another/#{plugin}.zip', } MANIFEST end - include_examples( - 'manifest application', - instances - ) + include_examples('manifest application', es_config) include_examples( 'plugin API response', - instances, + es_config, 'reports the plugin as installed', 'name' => plugin ) end describe 'via url', :with_cleanup do let(:extra_manifest) do <<-MANIFEST elasticsearch::plugin { '#{plugin}': - instances => 'es-01', - url => '#{meta[:url]}', + url => '#{meta[:url]}', } MANIFEST end - include_examples( - 'manifest application', - instances - ) + include_examples('manifest application', es_config) include_examples( 'plugin API response', - instances, + es_config, 'reports the plugin as installed', 'name' => plugin ) end end end end end end diff --git a/spec/spec_helper_acceptance.rb b/spec/spec_helper_acceptance.rb index 25cc657..e22289a 100644 --- a/spec/spec_helper_acceptance.rb +++ b/spec/spec_helper_acceptance.rb @@ -1,256 +1,255 @@ require 'beaker-rspec' require 'beaker/puppet_install_helper' require 'securerandom' require 'thread' require 'infrataster/rspec' require 'rspec/retry' require 'vault' require 'simp/beaker_helpers' include Simp::BeakerHelpers require_relative 'spec_helper_tls' require_relative 'spec_utilities' require_relative '../lib/puppet_x/elastic/deep_to_i' require_relative '../lib/puppet_x/elastic/deep_to_s' # def f # RSpec.configuration.fact # end run_puppet_install_helper('agent') unless ENV['BEAKER_provision'] == 'no' RSpec.configure do |c| # General-purpose spec-global variables c.add_setting :v, :default => {} # Puppet debug logging v[:puppet_debug] = ENV['BEAKER_debug'] ? true : false unless ENV['snapshot_version'].nil? v[:snapshot_version] = ENV['snapshot_version'] v[:is_snapshot] = ENV['SNAPSHOT_TEST'] == 'true' end unless ENV['ELASTICSEARCH_VERSION'].nil? and v[:snapshot_version].nil? v[:elasticsearch_full_version] = ENV['ELASTICSEARCH_VERSION'] || v[:snapshot_version] v[:elasticsearch_major_version] = v[:elasticsearch_full_version].split('.').first.to_i v[:elasticsearch_package] = {} v[:template] = if v[:elasticsearch_major_version] < 6 JSON.load(File.new('spec/fixtures/templates/pre_6.0.json')) elsif v[:elasticsearch_major_version] >= 8 JSON.load(File.new('spec/fixtures/templates/post_8.0.json')) else JSON.load(File.new('spec/fixtures/templates/post_6.0.json')) end v[:template] = Puppet_X::Elastic.deep_to_i(Puppet_X::Elastic.deep_to_s(v[:template])) v[:pipeline] = JSON.load(File.new('spec/fixtures/pipelines/example.json')) v[:elasticsearch_plugins] = Dir[ artifact("*#{v[:elasticsearch_full_version]}.zip", ['plugins']) ].map do |plugin| plugin_filename = File.basename(plugin) plugin_name = plugin_filename.match(/^(?.+)-#{v[:elasticsearch_full_version]}.zip/)[:name] [ plugin_name, { :path => plugin, :url => derive_plugin_urls_for(v[:elasticsearch_full_version], [plugin_name]).keys.first } ] end.to_h end v[:oss] = (not ENV['OSS_PACKAGE'].nil?) and ENV['OSS_PACKAGE'] == 'true' v[:cluster_name] = SecureRandom.hex(10) # rspec-retry c.display_try_failure_messages = true c.default_sleep_interval = 10 # General-case retry keyword for unstable tests c.around :each, :with_retries do |example| example.run_with_retry retry: 10 end # Helper hook for module cleanup c.after :context, :with_cleanup do apply_manifest <<-EOS class { 'elasticsearch': ensure => 'absent', manage_repo => true, oss => #{v[:oss]}, } - elasticsearch::instance { 'es-01': ensure => 'absent' } file { '/usr/share/elasticsearch/plugin': ensure => 'absent', force => true, recurse => true, require => Class['elasticsearch'], } EOS end c.before :context, :with_certificates do @keystore_password = SecureRandom.hex @role = [*('a'..'z')].sample(8).join # Setup TLS cert placement @tls = gen_certs(2, '/tmp') create_remote_file hosts, @tls[:ca][:cert][:path], @tls[:ca][:cert][:pem] @tls[:clients].each do |node| node.each do |_type, params| create_remote_file hosts, params[:path], params[:pem] end end end c.before :context, :with_license do Vault.address = ENV['VAULT_ADDR'] Vault.auth.approle ENV['VAULT_APPROLE_ROLE_ID'], ENV['VAULT_APPROLE_SECRET_ID'] licenses = Vault.with_retries(Vault::HTTPConnectionError) do Vault.logical.read(ENV['VAULT_PATH']) end.data raise 'No license found!' unless licenses license = case v[:elasticsearch_major_version] when 2 licenses[:v2] else licenses[:v5] end create_remote_file hosts, '/tmp/license.json', license v[:elasticsearch_license_path] = '/tmp/license.json' end c.after :context, :then_purge do shell 'rm -rf {/usr/share,/etc,/var/lib}/elasticsearch*' end c.before :context, :first_purge do shell 'rm -rf {/usr/share,/etc,/var/lib}/elasticsearch*' end # Provide a hook filter to spit out some ES logs if the example fails. c.after(:example, :logs_on_failure) do |example| if example.exception hosts.each do |host| on host, "find / -name '#{v[:cluster_name]}.log' | xargs cat || true" do |result| puts result.formatted_output end end end end end files_dir = ENV['files_dir'] || './spec/fixtures/artifacts' # General bootstrapping steps for each host hosts.each do |host| # # Set the host to 'aio' in order to adopt the puppet-agent style of # # installation, and configure paths/etc. # host[:type] = 'aio' # configure_defaults_on host, 'aio' if fact('os.family') == 'Suse' install_package host, '--force-resolution augeas-devel libxml2-devel ruby-devel' on host, 'gem install ruby-augeas --no-ri --no-rdoc' end v[:ext] = case fact('os.family') when 'Debian' 'deb' else 'rpm' end if v[:elasticsearch_package] v[:elasticsearch_package].merge!( derive_full_package_url( v[:elasticsearch_full_version], [v[:ext]] ).flat_map do |url, filename| [[:url, url], [:filename, filename], [:path, artifact(filename)]] end.to_h ) end Infrataster::Server.define(:docker) do |server| server.address = host[:ip] server.ssh = host[:ssh].tap { |s| s.delete :forward_agent } end Infrataster::Server.define(:container) do |server| server.address = host[:vm_ip] # this gets ignored anyway server.from = :docker end end RSpec.configure do |c| if v[:is_snapshot] c.before :suite do scp_to default, "#{files_dir}/elasticsearch-snapshot.#{v[:ext]}", "/tmp/elasticsearch-snapshot.#{v[:ext]}" v[:snapshot_package] = "file:/tmp/elasticsearch-snapshot.#{v[:ext]}" end end c.before :suite do # Install module and dependencies install_dev_puppet_module :ignore_list => [ 'junit' ] + Beaker::DSL::InstallUtils::ModuleUtils::PUPPET_MODULE_INSTALL_IGNORE hosts.each do |host| modules = %w[archive augeas_core datacat java java_ks stdlib elastic_stack] dist_module = { 'Debian' => ['apt'], 'Suse' => ['zypprepo'], 'RedHat' => %w[concat yumrepo_core] }[fact('os.family')] modules += dist_module unless dist_module.nil? modules.each do |mod| copy_module_to( host, :module_name => mod, :source => "spec/fixtures/modules/#{mod}" ) end on(host, 'mkdir -p etc/puppet/modules/another/files/') # Apt doesn't update package caches sometimes, ensure we're caught up. shell 'apt-get update' if fact('os.family') == 'Debian' end # Use the Java class once before the suite of tests unless shell('command -v java', :accept_all_exit_codes => true).exit_code.zero? java = case fact('os.name') when 'OpenSuSE' 'package => "java-1_8_0-openjdk-headless",' else '' end apply_manifest <<-MANIFEST class { "java" : distribution => "jre", #{java} } MANIFEST end end end # # Java 8 is only easy to manage on recent distros # def v5x_capable? # (fact('os.family') == 'RedHat' and \ # not (fact('os.name') == 'OracleLinux' and \ # f['os']['release']['major'] == '6')) or \ # f.dig 'os', 'distro', 'codename' == 'xenial' # end