diff --git a/.github/workflows/integration-tests.yml b/.github/workflows/integration-tests.yml index 4074552..663ae12 100644 --- a/.github/workflows/integration-tests.yml +++ b/.github/workflows/integration-tests.yml @@ -13,10 +13,35 @@ jobs: matrix: ${{ steps.generate-matrix.outputs.matrix }} steps: - uses: actions/checkout@v2 + with: + fetch-depth: 0 + - name: Set up libvirt for test generation + run: | + sudo apt-get update + sudo apt-get install -y \ + libvirt-dev \ + libz-dev \ + ; + - uses: actions/cache@v2 + with: + path: vendor/bundle + key: ${{ runner.os }}-gems-${{ hashFiles('**/Gemfile.lock') }} + restore-keys: | + ${{ runner.os }}-gems- + - name: Set up Ruby + uses: ruby/setup-ruby@v1 + with: + ruby-version: 2.6.6 + - name: Run bundler using cached path + run: | + bundle config path vendor/bundle + bundle install --jobs 4 --retry 3 - name: Generate matrix id: generate-matrix run: | - tests="$(awk -f tests/parse_tests.awk < tests/runtests.bats)" + bundle exec rspec --color --format json --fail-fast --dry-run --tag acceptance --out report.json + tests="$(jq -c '[.examples[].full_description]' report.json)" + echo "::set-output name=matrix::${tests}" run-tests: @@ -51,14 +76,10 @@ jobs: qemu-kvm \ qemu-utils \ ; - sudo apt-get install \ + sudo apt-get install -y \ libvirt-dev \ libz-dev \ ; - sudo apt-get install \ - bats \ - fping \ - ; # start daemon sudo systemctl start libvirtd @@ -81,22 +102,14 @@ jobs: uses: ruby/setup-ruby@v1 with: ruby-version: 2.6.6 - - name: Set up rubygems - run: | - gem update --system --conservative || (gem i "rubygems-update:~>2.7" --no-document && update_rubygems) - gem update bundler --conservative - name: Run bundler using cached path run: | bundle config path vendor/bundle bundle install --jobs 4 --retry 3 - - name: Install binstubs - run: | - bundle binstubs --all --path=./bin 1>/dev/null - ./bin/vagrant --version - name: Run tests run: | mkdir -p $HOME/.vagrant.d/ - # use export with full path to avoid needing to resolve ~ + # tell integration tests to use boxes from the cached location export VAGRANT_HOME=$HOME/.vagrant.d # use software emulation due to lack of nested emulation cat < $HOME/.vagrant.d/Vagrantfile @@ -105,6 +118,5 @@ jobs: libvirt.driver = "qemu" end end - EOF # run under libvirt group - sg libvirt -c "bats -f '${{ matrix.test_name }}' ./tests/runtests.bats" + sg libvirt -c "bundle exec rspec --color --fail-fast --tag acceptance -e '${{ matrix.test_name }}'" diff --git a/.gitignore b/.gitignore index 6689d63..1c714e4 100644 --- a/.gitignore +++ b/.gitignore @@ -16,9 +16,7 @@ spec/reports test/tmp test/version_tmp tmp -Vagrantfile -!tests/*/Vagrantfile -!example_box/Vagrantfile +/Vagrantfile .vagrant *.swp .deps diff --git a/spec/acceptance/additional_storage_spec.rb b/spec/acceptance/additional_storage_spec.rb new file mode 100644 index 0000000..11a5eae --- /dev/null +++ b/spec/acceptance/additional_storage_spec.rb @@ -0,0 +1,32 @@ +# frozen_string_literal: true + +require 'spec_helper' + +describe 'additional storage configured', acceptance: true do + include_context 'libvirt_acceptance' + + before do + environment.skeleton('additional_storage') + end + + after do + assert_execute('vagrant', 'destroy', '--force') + end + + it 'should succeed' do + status('Test: machine is created successfully') + result = environment.execute('vagrant', 'up') + expect(result).to exit_with(0) + + status('Test: additional storage configured') + expect(result.stdout).to match(/\(vda\).*work_default.img/) + expect(result.stdout).to match(/\(vdb\).*work_default-vdb\.qcow2/) + + status('Test: reload handles additional storage correctly') + result = environment.execute('vagrant', 'reload') + expect(result).to exit_with(0) + + status('Test: additional storage reported correctly') + expect(result.stdout).to match(/\(vdb\).*work_default-vdb\.qcow2/) + end +end diff --git a/spec/acceptance/package_domain_spec.rb b/spec/acceptance/package_domain_spec.rb new file mode 100644 index 0000000..3d574b9 --- /dev/null +++ b/spec/acceptance/package_domain_spec.rb @@ -0,0 +1,90 @@ +# frozen_string_literal: true + +require 'spec_helper' + +describe 'package domain', acceptance: true do + include_context 'libvirt_acceptance' + + before(:all) do + expect(Vagrant::Util::Which.which('virt-sysprep')).to be_truthy, + 'packaging tests require virt-sysprep, please install' + expect(Vagrant::Util::Which.which('virt-sparsify')).to be_truthy, + 'packaging tests require virt-sparsify, please install' + + result = (File.exist?('C:\\') ? `dir /-C #{Dir.tmpdir}` : `df #{Dir.tmpdir}`).split("\n").last + expect(result.split[3].to_i).to be > 6 * 1024 * 1024, + "packaging tests require more than 6GiB of space under #{Dir.tmpdir}" + end + + after(:each) do + assert_execute('vagrant', 'destroy', '--force') + end + + let(:testbox_envvars) { { VAGRANT_VAGRANTFILE: 'Vagrantfile.testbox' } } + + context 'simple' do + before do + environment.skeleton('package_simple') + end + + after do + result = environment.execute('vagrant', 'destroy', '--force', extra_env: testbox_envvars) + expect(result).to exit_with(0) + + assert_execute('vagrant', 'box', 'remove', '--force', 'test-package-simple-domain') + end + + it 'should succeed' do + status('Test: machine is created successfully') + expect(environment.execute('vagrant', 'up')).to exit_with(0) + + status('Test: package machine successfully') + expect(environment.execute('vagrant', 'package')).to exit_with(0) + + status('Test: add packaged box') + expect(environment.execute( + 'vagrant', 'box', 'add', '--force', '--name', 'test-package-simple-domain', 'package.box' + )).to exit_with(0) + + status('Test: machine from packaged box is created successfully') + result = environment.execute('vagrant', 'up', extra_env: testbox_envvars) + expect(result).to exit_with(0) + expect(result.stdout).to match(/test-package-complex-domain/) + end + end + + context 'complex' do + before do + environment.skeleton('package_complex') + extra_env.merge!( + { + VAGRANT_LIBVIRT_VIRT_SYSPREP_OPERATIONS: 'defaults,-ssh-userdir,customize', + VAGRANT_LIBVIRT_VIRT_SYSPREP_OPTIONS: '--run $(pwd)/scripts/sysprep.sh', + } + ) + end + + after do + expect(environment.execute('vagrant', 'destroy', '--force', extra_env: testbox_envvars)).to exit_with(0) + assert_execute('vagrant', 'box', 'remove', '--force', 'test-package-complex-domain') + end + + it 'should succeed' do + status('Test: machine is created successfully') + expect(environment.execute('vagrant', 'up')).to exit_with(0) + + status('Test: package machine successfully') + expect(environment.execute('vagrant', 'package')).to exit_with(0) + + status('Test: add packaged box') + expect(environment.execute( + 'vagrant', 'box', 'add', '--force', '--name', 'test-package-complex-domain', 'package.box' + )).to exit_with(0) + + status('Test: machine from packaged box is created successfully') + result = environment.execute('vagrant', 'up', extra_env: testbox_envvars) + expect(result).to exit_with(0) + expect(result.stdout).to match(/test-package-complex-domain/) + end + end +end diff --git a/spec/acceptance/provider_settings_spec.rb b/spec/acceptance/provider_settings_spec.rb new file mode 100644 index 0000000..a46ed2c --- /dev/null +++ b/spec/acceptance/provider_settings_spec.rb @@ -0,0 +1,54 @@ +# frozen_string_literal: true + +require 'spec_helper' + +describe 'provider settings', acceptance: true do + include_context 'libvirt_acceptance' + + after do + assert_execute('vagrant', 'destroy', '--force') + end + + context 'with defaults' do + before do + environment.skeleton('default_settings') + end + + it 'should succeed' do + status('Test: machine is created successfully') + result = environment.execute('vagrant', 'up') + expect(result).to exit_with(0) + + status('Test: CPU matches default') + expect(result.stdout).to match(/Cpus:\s+1$/) + + status('Test: memory matches default') + expect(result.stdout).to match(/Memory:\s+512M/) + + status('Test: default prefix is used') + expect(result.stdout).to match(/Name:\s+work_default$/) + end + end + + context 'with modified config' do + before do + environment.skeleton('adjusted_settings') + end + + it 'should succeed' do + status('Test: machine is created successfully') + result = environment.execute('vagrant', 'up') + expect(result).to exit_with(0) + + status('Test: CPUs are changed') + expect(result.stdout).to match(/Cpus:\s+2$/) + + status('Test: memory is changed') + expect(result.stdout).to match(/Memory:\s+1000M$/) + + status('Test: default prefix is changed') + expect(result.stdout).to match(/Name:\s+changed_default_prefixdefault$/) + expect(result.stdout).to match(/\(vda\).*changed_default_prefixdefault\.img/) + end + end +end diff --git a/spec/acceptance/simple_vm_provision_via_shell_spec.rb b/spec/acceptance/simple_vm_provision_via_shell_spec.rb new file mode 100644 index 0000000..d392fd1 --- /dev/null +++ b/spec/acceptance/simple_vm_provision_via_shell_spec.rb @@ -0,0 +1,31 @@ +# frozen_string_literal: true + +require 'spec_helper' + +describe 'simple vm provision via shell', acceptance: true do + include_context 'libvirt_acceptance' + + before do + environment.skeleton('simple_vm_provision') + end + + after do + assert_execute('vagrant', 'destroy', '--force') + end + + it 'should succeed' do + status('Test: machine is created successfully') + result = environment.execute('vagrant', 'up') + expect(result).to exit_with(0) + + status('Test: provision script executed') + expect(result.stdout).to match(/Hello, World/) + + status('Test: reload') + result = environment.execute('vagrant', 'reload') + expect(result).to exit_with(0) + + status('Test: provision checked if already executed') + expect(result.stdout).to match(/Machine already provisioned/) + end +end diff --git a/spec/acceptance/snapshots_spec.rb b/spec/acceptance/snapshots_spec.rb new file mode 100644 index 0000000..c476b19 --- /dev/null +++ b/spec/acceptance/snapshots_spec.rb @@ -0,0 +1,41 @@ +# frozen_string_literal: true + +require 'spec_helper' + +describe 'snapshots', acceptance: true do + include_context 'libvirt_acceptance' + + after(:each) do + assert_execute('vagrant', 'destroy', '--force') + end + + before do + environment.skeleton('snapshots') + end + + it 'should succeed' do + status('Test: machine is created successfully') + expect(environment.execute('vagrant', 'up')).to exit_with(0) + + status('Test: add test file') + expect(environment.execute('vagrant', 'ssh', '--', '-t', 'touch a.txt')).to exit_with(0) + + status('Test: create snapshot') + expect(environment.execute('vagrant', 'snapshot', 'save', 'default', 'test')).to exit_with(0) + + status('Test: modify files') + expect(environment.execute('vagrant', 'ssh', '--', '-t', 'rm a.txt')).to exit_with(0) + expect(environment.execute('vagrant', 'ssh', '--', '-t', 'ls a.txt')).to exit_with(1) + expect(environment.execute('vagrant', 'ssh', '--', '-t', 'touch b.txt')).to exit_with(0) + + status('Test: restore snapshot') + expect(environment.execute('vagrant', 'snapshot', 'restore', 'test')).to exit_with(0) + + status('Test: files are as expected') + expect(environment.execute('vagrant', 'ssh', '--', '-t', 'ls a.txt')).to exit_with(0) + expect(environment.execute('vagrant', 'ssh', '--', '-t', 'ls b.txt')).to exit_with(1) + + status('Test: snapshot removal works') + expect(environment.execute('vagrant', 'snapshot', 'delete', 'test')).to exit_with(0) + end +end diff --git a/tests/second_disk/Vagrantfile b/spec/acceptance/support-skeletons/additional_storage/Vagrantfile similarity index 100% rename from tests/second_disk/Vagrantfile rename to spec/acceptance/support-skeletons/additional_storage/Vagrantfile diff --git a/tests/default_prefix/Vagrantfile b/spec/acceptance/support-skeletons/adjusted_settings/Vagrantfile similarity index 88% rename from tests/default_prefix/Vagrantfile rename to spec/acceptance/support-skeletons/adjusted_settings/Vagrantfile index 9746738..9a7c7a9 100644 --- a/tests/default_prefix/Vagrantfile +++ b/spec/acceptance/support-skeletons/adjusted_settings/Vagrantfile @@ -8,6 +8,8 @@ Vagrant.configure("2") do |config| config.ssh.shell = "/bin/sh" config.vm.synced_folder ".", "/vagrant", disabled: true config.vm.provider :libvirt do |libvirt| + libvirt.cpu = 2 + libvirt.memory = 1000 libvirt.default_prefix = "changed_default_prefix" end end diff --git a/tests/simple/Vagrantfile b/spec/acceptance/support-skeletons/default_settings/Vagrantfile similarity index 100% rename from tests/simple/Vagrantfile rename to spec/acceptance/support-skeletons/default_settings/Vagrantfile diff --git a/tests/package_complex_example/Vagrantfile b/spec/acceptance/support-skeletons/package_complex/Vagrantfile similarity index 100% rename from tests/package_complex_example/Vagrantfile rename to spec/acceptance/support-skeletons/package_complex/Vagrantfile diff --git a/tests/package_complex_example/Vagrantfile.testbox b/spec/acceptance/support-skeletons/package_complex/Vagrantfile.testbox similarity index 75% rename from tests/package_complex_example/Vagrantfile.testbox rename to spec/acceptance/support-skeletons/package_complex/Vagrantfile.testbox index e88e599..787833f 100644 --- a/tests/package_complex_example/Vagrantfile.testbox +++ b/spec/acceptance/support-skeletons/package_complex/Vagrantfile.testbox @@ -2,7 +2,8 @@ # vi: set ft=ruby : Vagrant.configure("2") do |config| - config.vm.box = "test-package-complex-example" + config.vm.box = "test-package-complex-domain" + config.vm.define 'package-complex' config.vm.synced_folder ".", "/vagrant", disabled: true config.vm.provider :libvirt do |libvirt| diff --git a/tests/package_complex_example/scripts/sysprep.sh b/spec/acceptance/support-skeletons/package_complex/scripts/sysprep.sh similarity index 100% rename from tests/package_complex_example/scripts/sysprep.sh rename to spec/acceptance/support-skeletons/package_complex/scripts/sysprep.sh diff --git a/tests/package_simple/Vagrantfile b/spec/acceptance/support-skeletons/package_simple/Vagrantfile similarity index 100% rename from tests/package_simple/Vagrantfile rename to spec/acceptance/support-skeletons/package_simple/Vagrantfile diff --git a/tests/package_simple/Vagrantfile.testbox b/spec/acceptance/support-skeletons/package_simple/Vagrantfile.testbox similarity index 87% rename from tests/package_simple/Vagrantfile.testbox rename to spec/acceptance/support-skeletons/package_simple/Vagrantfile.testbox index 4124024..c4cf8c8 100644 --- a/tests/package_simple/Vagrantfile.testbox +++ b/spec/acceptance/support-skeletons/package_simple/Vagrantfile.testbox @@ -3,6 +3,7 @@ Vagrant.configure("2") do |config| config.vm.box = "test-package-simple-domain" + config.vm.define 'package-simple' config.ssh.shell = "/bin/sh" config.ssh.insert_key = false config.vm.synced_folder ".", "/vagrant", disabled: true diff --git a/tests/qemu_agent/Vagrantfile b/spec/acceptance/support-skeletons/qemu_agent/Vagrantfile similarity index 100% rename from tests/qemu_agent/Vagrantfile rename to spec/acceptance/support-skeletons/qemu_agent/Vagrantfile diff --git a/tests/simple_provision_shell/Vagrantfile b/spec/acceptance/support-skeletons/simple_vm_provision/Vagrantfile similarity index 90% rename from tests/simple_provision_shell/Vagrantfile rename to spec/acceptance/support-skeletons/simple_vm_provision/Vagrantfile index cd0a956..b4837fc 100644 --- a/tests/simple_provision_shell/Vagrantfile +++ b/spec/acceptance/support-skeletons/simple_vm_provision/Vagrantfile @@ -6,6 +6,7 @@ Vagrant.configure("2") do |config| config.vm.box = "infernix/tinycore" config.ssh.shell = "/bin/sh" + config.ssh.insert_key = false config.vm.synced_folder ".", "/vagrant", disabled: true config.vm.provision "shell", inline: "echo Hello, World", privileged: false end diff --git a/tests/cpus/Vagrantfile b/spec/acceptance/support-skeletons/snapshots/Vagrantfile similarity index 100% rename from tests/cpus/Vagrantfile rename to spec/acceptance/support-skeletons/snapshots/Vagrantfile diff --git a/tests/two_disks/Vagrantfile b/spec/acceptance/support-skeletons/two_disks/Vagrantfile similarity index 100% rename from tests/two_disks/Vagrantfile rename to spec/acceptance/support-skeletons/two_disks/Vagrantfile diff --git a/spec/acceptance/two_disks_spec.rb b/spec/acceptance/two_disks_spec.rb new file mode 100644 index 0000000..e04ace3 --- /dev/null +++ b/spec/acceptance/two_disks_spec.rb @@ -0,0 +1,29 @@ +# frozen_string_literal: true + +require 'spec_helper' + +describe 'handle two disk machine', acceptance: true do + include_context 'libvirt_acceptance' + + after do + assert_execute('vagrant', 'destroy', '--force') + end + + before do + environment.skeleton('two_disks') + environment.execute(File.expand_path('../../tools/create_box_with_two_disks.sh', __dir__), + environment.homedir.to_s, 'vagrant') + end + + it 'should succeed' do + status('Test: machine is created successfully') + result = environment.execute('vagrant', 'up') + expect(result).to exit_with(0) + + status('Test: disk one referenced') + expect(result.stdout).to match(/Image\(vda\):.*work_default.img, virtio, 2G/) + + status('Test: disk two referenced') + expect(result.stdout).to match(/Image\(vdb\):.*work_default_1.img, virtio, 10G/) + end +end diff --git a/spec/acceptance/use_qemu_agent_for_connectivity_spec.rb b/spec/acceptance/use_qemu_agent_for_connectivity_spec.rb new file mode 100644 index 0000000..8efe4de --- /dev/null +++ b/spec/acceptance/use_qemu_agent_for_connectivity_spec.rb @@ -0,0 +1,34 @@ +# frozen_string_literal: true + +require 'spec_helper' + +describe 'use qemu agent to determine machine private address', acceptance: true do + include_context 'libvirt_acceptance' + + before do + environment.skeleton('qemu_agent') + end + + after do + assert_execute('vagrant', 'destroy', '--force') + end + + it 'should succeed' do + status('Test: machine is created successfully') + expect(environment.execute('vagrant', 'up')).to exit_with(0) + + # extract SSH IP address emitted as it should be the private network since + # the mgmt network has not been attached + hostname = result.stdout.each_line.find { |line| line.include?('SSH address:') } + expect(hostname).to_not be_nil + ip_address = hostname.strip.split.last.split(':').first + # default private network for vagrant-libvirt unless explicitly configured + expect(IPAddr.new('172.28.128.0/255.255.255.0')).to include(IPAddr.new(ip_address)) + + # ssh'ing successfully means that the private network is accessible + status('Test: machine private network is accessible') + result = environment.execute('vagrant', 'ssh', '-c', 'echo "hello, world"') + expect(result).to exit_with(0) + expect(result.stdout).to match(/hello, world/) + end +end diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 01fd91b..b161c28 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -55,4 +55,7 @@ RSpec.configure do |config| config.mock_with :rspec do |mocks| mocks.verify_partial_doubles = true end + + # don't run acceptance tests by default + config.filter_run_excluding :acceptance => true end diff --git a/spec/support/acceptance/configuration.rb b/spec/support/acceptance/configuration.rb new file mode 100644 index 0000000..ba5d5d9 --- /dev/null +++ b/spec/support/acceptance/configuration.rb @@ -0,0 +1,21 @@ +# frozen_string_literal: true + +require 'vagrant-spec/acceptance/configuration' + +module VagrantPlugins + module VagrantLibvirt + module Spec + module Acceptance + class Configuration < Vagrant::Spec::Acceptance::Configuration + attr_accessor :clean_on_fail + + def initialize + super + + @clean_on_fail = true + end + end + end + end + end +end diff --git a/spec/support/acceptance/context.rb b/spec/support/acceptance/context.rb new file mode 100644 index 0000000..e59599f --- /dev/null +++ b/spec/support/acceptance/context.rb @@ -0,0 +1,70 @@ +# frozen_string_literal: true + +require 'vagrant-spec/acceptance/configuration' +require "vagrant-spec/acceptance/rspec/matcher_exit_with" + +require_relative 'isolated_environment' + +shared_context "acceptance" do + # Setup the environment so that we have an isolated area + # to run Vagrant. We do some configuration here as well in order + # to replace "vagrant" with the proper path to Vagrant as well + # as tell the isolated environment about custom environmental + # variables to pass in. + let!(:environment) { new_environment } + + let(:config) { Vagrant::Spec::Acceptance::Configuration.new } + + let(:extra_env) { {} } + + # The skeleton paths that will be used to configure environments. + let(:skeleton_paths) do + root = Vagrant::Spec.source_root.join("acceptance", "support-skeletons") + config.skeleton_paths.dup.unshift(root) + end + + after(:each) do |example| + if example.exception.nil? || config.clean_on_fail + environment.close + else + example.reporter.message("Temporary work and home dirs (#{environment.workdir} and #{environment.homedir}) not removed to allow debug") + end + end + + # Creates a new isolated environment instance each time it is called. + # + # @return [Acceptance::IsolatedEnvironment] + def new_environment(env=nil) + apps = { "vagrant" => config.vagrant_path } + env = config.env.merge(env || {}) + env.merge!(extra_env) + + VagrantPlugins::VagrantLibvirt::Spec::AcceptanceIsolatedEnvironment.new( + apps: apps, + env: env, + skeleton_paths: skeleton_paths, + ) + end + + # Executes the given command in the context of the isolated environment. + # + # @return [Object] + def execute(*args, env: nil, log: true, &block) + env ||= environment + status("Execute: #{args.join(" ")}") if log + env.execute(*args, &block) + end + + # This method is an assertion helper for asserting that a process + # succeeds. It is a wrapper around `execute` that asserts that the + # exit status was successful. + def assert_execute(*args, env: nil, &block) + result = execute(*args, env: env, &block) + expect(result).to exit_with(0) + result + end + + def status(message) + RSpec.world.reporter.message(message) + end +end diff --git a/spec/support/acceptance/isolated_environment.rb b/spec/support/acceptance/isolated_environment.rb new file mode 100644 index 0000000..e8abde1 --- /dev/null +++ b/spec/support/acceptance/isolated_environment.rb @@ -0,0 +1,41 @@ +# frozen_string_literal: true + +require 'vagrant-spec/acceptance/isolated_environment' +require 'vagrant-spec/subprocess' +require 'vagrant-spec/which' + +module VagrantPlugins + module VagrantLibvirt + module Spec + class AcceptanceIsolatedEnvironment < Vagrant::Spec::AcceptanceIsolatedEnvironment + # Executes a command in the context of this isolated environment. + # Any command executed will therefore see our temporary directory + # as the home directory. + # + # If the command has been defined with a special path, then the + # command will be replaced with the full path to that command. + def execute(command, *args, **options) + # Create the command + command = replace_command(command) + # Use provided command if it is a valid executable + if !File.executable?(command) + # If it's not a valid executable, search for vagrant + command = Vagrant::Spec::Which.which(command) + end + + # Build up the options + options[:env] = @env.merge(options.delete(:extra_env) || {}) + options[:notify] = [:stdin, :stderr, :stdout] + options[:workdir] = @workdir.to_s + + # Execute, logging out the stdout/stderr as we get it + @logger.info("Executing: #{[command].concat(args).inspect}") + Vagrant::Spec::Subprocess.execute(command, *args, **options) do |type, data| + @logger.debug("#{type}: #{data}") if type == :stdout || type == :stderr + yield type, data if block_given? + end + end + end + end + end +end diff --git a/spec/support/libvirt_acceptance_context.rb b/spec/support/libvirt_acceptance_context.rb new file mode 100644 index 0000000..028c05a --- /dev/null +++ b/spec/support/libvirt_acceptance_context.rb @@ -0,0 +1,64 @@ +# frozen_string_literal: true + +require_relative 'acceptance/context' + +FALSEY_VALUES = %w[f false no n 0].freeze + +shared_context 'libvirt_acceptance' do + include_context 'acceptance' + + # The skeleton paths that will be used to configure environments. + let(:skeleton_paths) do + root = File.expand_path('../acceptance/support-skeletons', __dir__) + config.skeleton_paths.dup.unshift(root) + end + + let(:config) do + c = VagrantPlugins::VagrantLibvirt::Spec::Acceptance::Configuration.new + c.clean_on_fail = FALSEY_VALUES.include?(ENV.fetch('VAGRANT_SPEC_SKIP_CLEANUP', 'false').to_s.downcase) + + c + end + + before(:each) do + # allow execution environment to cache boxes used + symlink_boxes(ENV.fetch('VAGRANT_HOME', nil), environment) + end + + after(:each) do + # ensure we remove the symlink + boxes_symlink = File.join(environment.homedir, 'boxes') + File.delete(boxes_symlink) if File.symlink?(boxes_symlink) + end + + around do |example| + vagrant_cwd = ENV.delete('VAGRANT_CWD') + env_provider_before = ENV.fetch('VAGRANT_DEFAULT_PROVIDER', nil) + ENV['VAGRANT_DEFAULT_PROVIDER'] = 'libvirt' + + begin + example.run + ensure + ENV['VAGRANT_CWD'] = vagrant_cwd if vagrant_cwd + if env_provider_before.nil? + ENV.delete('VAGRANT_DEFAULT_PROVIDER') + else + ENV['VAGRANT_DEFAULT_PROVIDER'] = env_provider_before + end + end + end + + def duplicate_environment(env, *args) + dup_env = new_environment(*args) + symlink_boxes(env.homedir, dup_env) + + dup_env + end + + def symlink_boxes(vagrant_home, target_env) + return if vagrant_home.nil? + + # allow use the same boxes location as source environment + File.symlink File.realpath(File.join(vagrant_home, 'boxes')), File.join(target_env.homedir, 'boxes') + end +end diff --git a/tests/memory/Vagrantfile b/tests/memory/Vagrantfile deleted file mode 100644 index 2c872a0..0000000 --- a/tests/memory/Vagrantfile +++ /dev/null @@ -1,13 +0,0 @@ -# -*- mode: ruby -*- -# vi: set ft=ruby : -# -# frozen_string_literal: true - -Vagrant.configure("2") do |config| - config.vm.box = "infernix/tinycore" - config.ssh.shell = "/bin/sh" - config.vm.synced_folder ".", "/vagrant", disabled: true - config.vm.provider :libvirt do |libvirt| - libvirt.memory = 1000 - end -end diff --git a/tests/parse_tests.awk b/tests/parse_tests.awk deleted file mode 100644 index 06a10b7..0000000 --- a/tests/parse_tests.awk +++ /dev/null @@ -1,14 +0,0 @@ -BEGIN { - printf "[" - previous="" -} -match($0, /@test "(.*)" \{/, arr) { - if ( previous != "" ) { - printf "%s, ",previous - } - previous = sprintf("\"%s\"", arr[1]) -} -END { - printf "%s",previous - print "]" -} diff --git a/tests/private_network/Vagrantfile b/tests/private_network/Vagrantfile deleted file mode 100644 index 114d6c1..0000000 --- a/tests/private_network/Vagrantfile +++ /dev/null @@ -1,14 +0,0 @@ -# -*- mode: ruby -*- -# vi: set ft=ruby : -# -# frozen_string_literal: true - -Vagrant.configure("2") do |config| - # private network doesnt work with tinycore, use - # debian10 box for test - config.vm.box = "generic/debian10" - config.vm.synced_folder ".", "/vagrant", disabled: true - config.vm.define :test_vm1 do |test_vm1| - test_vm1.vm.network :private_network, :ip => "10.20.30.40" - end -end diff --git a/tests/runtests.bats b/tests/runtests.bats deleted file mode 100644 index 18b8b86..0000000 --- a/tests/runtests.bats +++ /dev/null @@ -1,275 +0,0 @@ -SCRIPT_DIR="$( cd "$BATS_TEST_DIRNAME" &> /dev/null && pwd )" -export PATH=$(dirname ${SCRIPT_DIR})/bin:${PATH} - -VAGRANT_CMD="vagrant" -VAGRANT_OPT="--provider=libvirt" - -TEMPDIR= - - -setup_file() { - # set VAGRANT_HOME to something else to reuse for tests to avoid clashes with - # user installed plugins when running tests locally. - if [ -z "${VAGRANT_HOME:-}" ] - then - TEMPDIR=$(mktemp -d 2>/dev/null) - - export VAGRANT_HOME=${TEMPDIR}/.vagrant.d - echo "# Using ${VAGRANT_HOME} for VAGRANT_HOME" >&3 - fi -} - -teardown_file() { - if [ -n "${TEMPDIR:-}" ] && [ -d "${TEMPDIR:-}" ] - then - rm -rf ${TEMPDIR:-} - fi -} - -cleanup() { - ${VAGRANT_CMD} destroy -f - if [ $? == "0" ]; then - return 0 - else - return 1 - fi -} - -@test "destroy simple vm" { - export VAGRANT_LOG=debug - export VAGRANT_CWD=tests/simple - run ${VAGRANT_CMD} up ${VAGRANT_OPT} - echo "${output}" - echo "status = ${status}" - [ "$status" -eq 0 ] - cleanup -} - -@test "simple vm provision via shell" { - export VAGRANT_CWD=tests/simple_provision_shell - cleanup - run ${VAGRANT_CMD} up ${VAGRANT_OPT} - echo "status = ${status}" - echo "${output}" - [ "$status" -eq 0 ] - [ $(expr "$output" : ".*Hello.*") -ne 0 ] - echo "${output}" - cleanup -} - -@test "bring up with custom default prefix" { - export VAGRANT_CWD=tests/default_prefix - cleanup - run ${VAGRANT_CMD} up ${VAGRANT_OPT} - [ "$status" -eq 0 ] - echo "${output}" - echo "status = ${status}" - [ $(expr "$output" : ".*changed_default_prefixdefault.*") -ne 0 ] - echo "${output}" - cleanup -} - -@test "bring up with second disk" { - export VAGRANT_CWD=tests/second_disk - cleanup - run ${VAGRANT_CMD} up ${VAGRANT_OPT} - echo "${output}" - echo "status = ${status}" - [ "$status" -eq 0 ] - echo "${output}" - [ $(expr "$output" : ".*second_disk_default-vdb.*") -ne 0 ] - run ${VAGRANT_CMD} halt - echo "${output}" - echo "status = ${status}" - [ "$status" -eq 0 ] - run ${VAGRANT_CMD} up ${VAGRANT_OPT} - echo "${output}" - echo "status = ${status}" - [ "$status" -eq 0 ] - cleanup -} - -@test "bring up with two disks" { - export VAGRANT_CWD=tests/two_disks - cleanup - tools/create_box_with_two_disks.sh ${VAGRANT_HOME} ${VAGRANT_CMD} - run ${VAGRANT_CMD} up ${VAGRANT_OPT} - echo "${output}" - echo "status = ${status}" - [ "$status" -eq 0 ] - echo "${output}" - [ $(expr "$output" : ".*Image.*2G") -ne 0 ] - [ $(expr "$output" : ".*Image.*10G") -ne 0 ] - cleanup -} - -@test "bring up with adjusted memory settings" { - export VAGRANT_CWD=tests/memory - cleanup - run ${VAGRANT_CMD} up ${VAGRANT_OPT} - echo "${output}" - echo "status = ${status}" - [ "$status" -eq 0 ] - echo "${output}" - [ $(expr "$output" : ".*Memory.*1000M.*") -ne 0 ] - cleanup -} - -@test "bring up with adjusted cpu settings" { - export VAGRANT_CWD=tests/cpus - cleanup - run ${VAGRANT_CMD} up ${VAGRANT_OPT} - echo "${output}" - echo "status = ${status}" - [ "$status" -eq 0 ] - echo "${output}" - [ $(expr "$output" : ".*Cpus.*2.*") -ne 0 ] - cleanup -} - -@test "bring up and use qemu agent for connectivity" { - export VAGRANT_CWD=tests/qemu_agent - cleanup - run ${VAGRANT_CMD} up ${VAGRANT_OPT} - echo "${output}" - echo "status = ${status}" - [ "$status" -eq 0 ] - echo "${output}" - cleanup -} - -@test "ip is reachable with private network" { - export VAGRANT_CWD=tests/private_network - cleanup - run ${VAGRANT_CMD} up ${VAGRANT_OPT} - echo "${output}" - echo "status = ${status}" - [ "$status" -eq 0 ] - echo "${output}" - [ $(expr "$output" : ".*Cpus.*2.*") -ne 0 ] - run fping 10.20.30.40 - [ "$status" -eq 0 ] - echo "${output}" - [ $(expr "$output" : ".*alive.*") -ne 0 ] - cleanup -} - -@test "package simple domain" { - export VAGRANT_CWD=tests/package_simple - cleanup - run ${VAGRANT_CMD} up ${VAGRANT_OPT} - echo "${output}" - echo "status = ${status}" - [ "$status" -eq 0 ] - rm -f package.box - run ${VAGRANT_CMD} package - echo "${output}" - echo "status = ${status}" - [ "$status" -eq 0 ] - run ${VAGRANT_CMD} destroy -f - echo "${output}" - echo "status = ${status}" - [ "$status" -eq 0 ] - run ${VAGRANT_CMD} box add --force package.box --name test-package-simple-domain - echo "${output}" - echo "status = ${status}" - [ "$status" -eq 0 ] - VAGRANT_VAGRANTFILE=Vagrantfile.testbox run ${VAGRANT_CMD} up ${VAGRANT_OPT} - echo "${output}" - echo "status = ${status}" - [ "$status" -eq 0 ] - run ${VAGRANT_CMD} box remove --force test-package-simple-domain - echo "${output}" - echo "status = ${status}" - [ "$status" -eq 0 ] - rm -f package.box - - cleanup -} - -@test "package complex example" { - export VAGRANT_CWD=tests/package_complex_example - # this will allow the host keys to be removed, and part of the sysprep script - # adds a step to trigger the regeneration. - export VAGRANT_LIBVIRT_VIRT_SYSPREP_OPERATIONS='defaults,-ssh-userdir,customize' - export VAGRANT_LIBVIRT_VIRT_SYSPREP_OPTIONS="--run $(pwd)/tests/package_complex_example/scripts/sysprep.sh" - cleanup - run ${VAGRANT_CMD} up ${VAGRANT_OPT} - echo "${output}" - echo "status = ${status}" - [ "$status" -eq 0 ] - rm -f package.box - run ${VAGRANT_CMD} package - echo "${output}" - echo "status = ${status}" - [ "$status" -eq 0 ] - run ${VAGRANT_CMD} destroy -f - echo "${output}" - echo "status = ${status}" - [ "$status" -eq 0 ] - run ${VAGRANT_CMD} box add --force package.box --name test-package-complex-example - echo "${output}" - echo "status = ${status}" - [ "$status" -eq 0 ] - VAGRANT_VAGRANTFILE=Vagrantfile.testbox run ${VAGRANT_CMD} up ${VAGRANT_OPT} - echo "${output}" - echo "status = ${status}" - [ "$status" -eq 0 ] - run ${VAGRANT_CMD} box remove --force test-package-complex-example - echo "${output}" - echo "status = ${status}" - [ "$status" -eq 0 ] - rm -f package.box - - cleanup -} - -@test "bring up and save a snapshot and restore it" { - export VAGRANT_CWD=tests/snapshot - - cleanup - run ${VAGRANT_CMD} up ${VAGRANT_OPT} - echo "${output}" - echo "status = ${status}" - [ "$status" -eq 0 ] - run ${VAGRANT_CMD} ssh -- -t 'touch a.txt' - echo "${output}" - echo "status = ${status}" - [ "$status" -eq 0 ] - run ${VAGRANT_CMD} snapshot save default test - echo "${output}" - echo "status = ${status}" - [ "$status" -eq 0 ] - run ${VAGRANT_CMD} ssh -- -t 'rm a.txt' - echo "${output}" - echo "status = ${status}" - [ "$status" -eq 0 ] - run ${VAGRANT_CMD} ssh -- -t 'ls a.txt' - echo "${output}" - echo "status = ${status}" - # This means that the file does not exist on the box. - [ "$status" -eq 1 ] - run ${VAGRANT_CMD} ssh -- -t 'touch b.txt' - echo "${output}" - echo "status = ${status}" - [ "$status" -eq 0 ] - run ${VAGRANT_CMD} snapshot restore default test - echo "${output}" - echo "status = ${status}" - [ "$status" -eq 0 ] - run ${VAGRANT_CMD} ssh -- -t 'ls b.txt' - echo "${output}" - echo "status = ${status}" - # This means that the file does not exist on the box. - [ "$status" -eq 1 ] - run ${VAGRANT_CMD} ssh -- -t 'ls a.txt' - echo "${output}" - echo "status = ${status}" - [ "$status" -eq 0 ] - run ${VAGRANT_CMD} snapshot delete default test - echo "${output}" - echo "status = ${status}" - [ "$status" -eq 0 ] - - cleanup -} diff --git a/tests/snapshot/Vagrantfile b/tests/snapshot/Vagrantfile deleted file mode 100644 index 150dfc7..0000000 --- a/tests/snapshot/Vagrantfile +++ /dev/null @@ -1,13 +0,0 @@ -# -*- mode: ruby -*- -# vi: set ft=ruby : -# -# frozen_string_literal: true - -Vagrant.configure("2") do |config| - config.vm.box = "infernix/tinycore" - config.ssh.shell = "/bin/sh" - config.vm.synced_folder ".", "/vagrant", disabled: true - config.vm.provider :libvirt do |libvirt| - libvirt.cpus = 2 - end -end