We use the `bin/ci` script to execute our E2E tests. However, this script is solely for E2E, and the 'CI' label is potentially misleading, given that we also have CI for rspec tests, rubocop, and so on. To clarify its purpose, I've renamed it to `bin/e2e`. Moreover, the environment variable `CI_HETZNER_SACRIFICIAL_SERVER_ID` can be somewhat confusing. Considering that we have several environment variables starting with `E2E`, renaming it to `E2E_HETZNER_SERVER_ID` would make it more understandable for new contributors.
97 lines
3.6 KiB
Ruby
Executable File
97 lines
3.6 KiB
Ruby
Executable File
#!/usr/bin/env ruby
|
|
# frozen_string_literal: true
|
|
|
|
require_relative "../loader"
|
|
require "time"
|
|
require "optparse"
|
|
|
|
@started_at = Time.now
|
|
|
|
def main(options)
|
|
all_test_cases = YAML.load_file("config/e2e_test_cases.yml").to_h { [it["name"], it] }
|
|
boot_images = all_test_cases.values_at(*options[:test_cases]).flat_map { it["images"] }.uniq
|
|
|
|
hetzner_server_st = Prog::Test::HetznerServer.assemble(vm_host_id: options[:vm_host_id], default_boot_images: boot_images)
|
|
wait_until(hetzner_server_st, "wait")
|
|
|
|
tests_to_wait = []
|
|
if options[:test_cases].include?("vm") && (test_case = all_test_cases["vm"])
|
|
# Testing slices is not parallel with other tests as it requires a specific host state
|
|
|
|
# This tests encrypted VMs with slices, which will create both standard and
|
|
# burstable VMs. The test will also test host reboot.
|
|
encrypted_vms_st = Prog::Test::VmGroup.assemble(boot_images: test_case["images"], storage_encrypted: true, test_reboot: true, test_slices: true)
|
|
log(encrypted_vms_st, "storage_encrypted: true")
|
|
# Not running in parallel but waiting, since host is rebooted during test.
|
|
# Rebooting makes the next test to test reboot practically as well depending
|
|
# on when the host is rebooted and can cause flaky issues for github runner tests.
|
|
wait_until(encrypted_vms_st)
|
|
|
|
# YYY: Remove this when all hosts use slices
|
|
Semaphore.incr(hetzner_server_st.id, "disallow_slices")
|
|
wait_until(hetzner_server_st, "wait")
|
|
|
|
unencrypted_vms_st = Prog::Test::VmGroup.assemble(boot_images: test_case["images"], storage_encrypted: false, test_reboot: false, verify_host_capacity: false)
|
|
log(unencrypted_vms_st, "storage_encrypted: false")
|
|
tests_to_wait << unencrypted_vms_st
|
|
end
|
|
|
|
if (gh_test_cases = all_test_cases.values_at(*options[:test_cases].select { it.include?("github_runner") }))
|
|
tests_to_wait << Prog::Test::GithubRunner.assemble(gh_test_cases)
|
|
end
|
|
|
|
if options[:test_cases].include?("postgres_standard")
|
|
tests_to_wait << Prog::Test::PostgresResource.assemble
|
|
end
|
|
if options[:test_cases].include?("postgres_ha")
|
|
tests_to_wait << Prog::Test::HaPostgresResource.assemble
|
|
end
|
|
|
|
# Although wait_until will be blocked while checking the first one
|
|
# it won't affect the total time as other strands will continue in parallel.
|
|
# No need to make it parallel.
|
|
tests_to_wait.each { |st| wait_until(st) }
|
|
|
|
Semaphore.incr(hetzner_server_st.id, "verify_cleanup_and_destroy")
|
|
wait_until(hetzner_server_st)
|
|
end
|
|
|
|
def wait_until(st, label = nil)
|
|
while (loaded_st = Strand[st.id]) && loaded_st.label != label
|
|
if loaded_st.label == "failed"
|
|
log(st.reload, "FAILED: #{loaded_st.exitval.fetch("msg")}")
|
|
st.destroy
|
|
exit 1
|
|
end
|
|
log(st.reload, "waiting for #{label || "exit"}")
|
|
sleep 10
|
|
end
|
|
log(st, "reached")
|
|
end
|
|
|
|
def log(st, msg)
|
|
resources = case st.prog
|
|
when "Test::HetznerServer"
|
|
"VmHost.#{Strand[st.stack.first["vm_host_id"]]&.label}"
|
|
when "Test::VmGroup"
|
|
st.stack.first["vms"].map { "Vm.#{Strand[it]&.label}" }.join(", ")
|
|
when "Test::Vm"
|
|
"Vm.#{Strand[st.stack.first["subject_id"]]&.label}"
|
|
else
|
|
"#{st.prog}.#{st.label}"
|
|
end
|
|
$stdout.write "#{((Time.now - @started_at) / 60).round(2)}m | #{st.id} | #{st.prog}.#{st.label} | #{msg} | #{resources}\n"
|
|
end
|
|
|
|
options = {test_cases: ["vm"]}
|
|
OptionParser.new do |opts|
|
|
opts.on("--vm-host-id VM_HOST_ID", "Use existing vm host") { |v| options[:vm_host_id] = (v.length == 26) ? UBID.to_uuid(v) : v }
|
|
opts.on("--test-cases TEST_CASES", Array, "List of test cases to run separated by comma") { |v| options[:test_cases] = v }
|
|
end.parse!
|
|
|
|
clover_freeze
|
|
|
|
$stdout.sync = true
|
|
|
|
main(options)
|