Commit c2bf31ed authored by Rémy Coutable's avatar Rémy Coutable

Merge branch 'qa/gb/add-geo-integration-tests' into 'master'

Integration tests for GitLab Geo

Closes #3765

See merge request gitlab-org/gitlab-ee!3294
parents a3f3b243 6495180e
......@@ -49,6 +49,10 @@ module QA
module Sandbox
autoload :Prepare, 'qa/scenario/gitlab/sandbox/prepare'
end
module Admin
autoload :HashedStorage, 'qa/scenario/gitlab/admin/hashed_storage'
end
end
end
......@@ -64,9 +68,11 @@ module QA
autoload :Entry, 'qa/page/main/entry'
autoload :Login, 'qa/page/main/login'
autoload :Menu, 'qa/page/main/menu'
autoload :OAuth, 'qa/page/main/oauth'
end
module Dashboard
autoload :Projects, 'qa/page/dashboard/projects'
autoload :Groups, 'qa/page/dashboard/groups'
end
......@@ -82,6 +88,7 @@ module QA
module Admin
autoload :Menu, 'qa/page/admin/menu'
autoload :Settings, 'qa/page/admin/settings'
end
module Mattermost
......@@ -97,6 +104,13 @@ module QA
autoload :Repository, 'qa/git/repository'
end
##
# Classes describing shell interaction with GitLab
#
module Shell
autoload :Omnibus, 'qa/shell/omnibus'
end
##
# Classes that make it possible to execute features tests.
#
......
......@@ -6,10 +6,19 @@ module QA
module Page
module Admin
autoload :License, 'qa/ee/page/admin/license'
autoload :GeoNodes, 'qa/ee/page/admin/geo_nodes'
end
end
module Scenario
module Geo
autoload :Node, 'qa/ee/scenario/geo/node'
end
module Test
autoload :Geo, 'qa/ee/scenario/test/geo'
end
module License
autoload :Add, 'qa/ee/scenario/license/add'
end
......
module QA
module EE
module Page
module Admin
class GeoNodes < QA::Page::Base
def set_node_address(address)
fill_in 'URL', with: address
end
def add_node!
click_button 'Add Node'
end
end
end
end
end
end
module QA
module EE
module Scenario
module Geo
class Node < QA::Scenario::Template
attr_accessor :address
def perform
QA::Page::Main::Entry.act { visit_login_page }
QA::Page::Main::Login.act { sign_in_using_credentials }
QA::Page::Main::Menu.act { go_to_admin_area }
QA::Page::Admin::Menu.act { go_to_geo_nodes }
EE::Page::Admin::GeoNodes.perform do |page|
raise ArgumentError if @address.nil?
page.set_node_address(@address)
page.add_node!
end
QA::Page::Main::Menu.act { sign_out }
end
end
end
end
end
end
module QA
module EE
module Scenario
module Test
class Geo < QA::Scenario::Template
include QA::Scenario::Bootable
attribute :geo_primary_address, '--primary-address PRIMARY'
attribute :geo_primary_name, '--primary-name PRIMARY_NAME'
attribute :geo_secondary_address, '--secondary-address SECONDARY'
attribute :geo_secondary_name, '--secondary-name SECONDARY_NAME'
attribute :geo_skip_setup?, '--without-setup'
def perform(**args)
QA::Specs::Config.act { configure_capybara! }
unless args[:geo_skip_setup?]
# TODO, Factory::License -> gitlab-org/gitlab-qa#86
#
QA::Runtime::Scenario.define(:gitlab_address, args[:geo_primary_address])
Geo::Primary.act do
add_license
enable_hashed_storage
set_replication_password
set_primary_node
add_secondary_node
end
Geo::Secondary.act { replicate_database }
end
Specs::Runner.perform do |specs|
specs.tty = true
specs.tags = %w[geo]
end
end
class Primary
include QA::Scenario::Actable
def initialize
@address = QA::Runtime::Scenario.geo_primary_address
@name = QA::Runtime::Scenario.geo_primary_name
end
def add_license
# TODO EE license to Runtime.license, gitlab-org/gitlab-qa#86
#
puts 'Adding GitLab EE license ...'
Scenario::License::Add.perform(ENV['EE_LICENSE'])
end
def enable_hashed_storage
# TODO, Factory::HashedStorage - gitlab-org/gitlab-qa#86
#
puts 'Enabling hashed repository storage setting ...'
QA::Scenario::Gitlab::Admin::HashedStorage.perform(:enabled)
end
def add_secondary_node
# TODO, Factory::Geo::Node - gitlab-org/gitlab-qa#86
#
puts 'Adding new Geo secondary node ...'
Scenario::Geo::Node.perform do |node|
node.address = QA::Runtime::Scenario.geo_secondary_address
end
end
def set_replication_password
puts 'Setting replication password on primary node ...'
QA::Shell::Omnibus.new(@name).act do
gitlab_ctl 'set-replication-password', input: 'echo mypass'
end
end
def set_primary_node
puts 'Making this node a primary node ...'
Shell::Omnibus.new(@name).act do
gitlab_ctl 'set-geo-primary-node'
end
end
end
class Secondary
include QA::Scenario::Actable
def initialize
@name = QA::Runtime::Scenario.geo_secondary_name
end
def replicate_database
puts 'Starting Geo replication on secondary node ...'
Shell::Omnibus.new(@name).act do
require 'uri'
host = URI(QA::Runtime::Scenario.geo_primary_address).host
slot = QA::Runtime::Scenario.geo_primary_name.tr('-', '_')
gitlab_ctl "replicate-geo-database --host=#{host} --slot-name=#{slot} " \
"--sslmode=disable --no-wait --force", input: 'echo mypass'
end
puts 'Waiting until secondary node services are restarted ...'
sleep 60 # Wait until services are restarted correctly
end
end
end
end
end
end
end
......@@ -7,6 +7,11 @@ module QA
require 'qa/ee'
end
##
# TODO generic solution for screenshot in factories
#
# gitlab-org/gitlab-qa#86
#
def perform_before_hooks
return unless ENV['EE_LICENSE']
......
......@@ -2,9 +2,16 @@ module QA
module Page
module Admin
class Menu < Page::Base
def go_to_geo_nodes
click_link 'Geo Nodes'
end
def go_to_license
link = find_link 'License'
link.click
click_link 'License'
end
def go_to_settings
click_link 'Settings'
end
end
end
......
module QA
module Page
module Admin
class Settings < Page::Base
def enable_hashed_storage
scroll_to 'legend', text: 'Repository Storage'
check 'Create new projects using hashed storage paths'
end
def save_settings
scroll_to '.form-actions' do
click_button 'Save'
end
end
end
end
end
end
require 'capybara/dsl'
module QA
module Page
class Base
......@@ -7,6 +9,21 @@ module QA
def refresh
visit current_url
end
def scroll_to(selector, text: nil)
page.execute_script <<~JS
var elements = Array.from(document.querySelectorAll('#{selector}'));
var text = '#{text}';
if (text.length > 0) {
elements.find(e => e.textContent === text).scrollIntoView();
} else {
elements[0].scrollIntoView();
}
JS
page.within(selector) { yield } if block_given?
end
end
end
end
module QA
module Page
module Dashboard
class Projects < Page::Base
def go_to_project(name)
find_link(text: name).click
end
end
end
end
end
......@@ -14,7 +14,7 @@ module QA
#
start = Time.now
while Time.now - start < 240
while Time.now - start < 1000
break if page.has_css?('.application', wait: 10)
refresh
......
......@@ -7,7 +7,10 @@ module QA
end
def go_to_projects
within_top_menu { click_link 'Projects' }
within_top_menu do
click_link 'Projects'
click_link 'Your projects'
end
end
def go_to_admin_area
......
module QA
module Page
module Main
class OAuth < Page::Base
def needs_authorization?
page.current_url.include?('/oauth')
end
def authorize!
click_button 'Authorize'
end
end
end
end
end
......@@ -14,6 +14,10 @@ module QA
find('#project_clone').value
end
def project_name
find('.project-title').text
end
def wait_for_push
sleep 5
end
......
......@@ -28,7 +28,7 @@ module QA
private
def attribute(name, arg, desc)
def attribute(name, arg, desc = '')
options.push(Option.new(name, arg, desc))
end
......
module QA
module Scenario
module Gitlab
module Admin
class HashedStorage < Scenario::Template
def perform(*traits)
raise ArgumentError unless traits.include?(:enabled)
Page::Main::Entry.act { visit_login_page }
Page::Main::Login.act { sign_in_using_credentials }
Page::Main::Menu.act { go_to_admin_area }
Page::Admin::Menu.act { go_to_settings }
Page::Admin::Settings.act do
enable_hashed_storage
save_settings
end
QA::Page::Main::Menu.act { sign_out }
end
end
end
end
end
end
require 'open3'
module QA
module Shell
class Omnibus
include Scenario::Actable
def initialize(container)
@name = container
end
def gitlab_ctl(command, input: nil)
if input.nil?
shell "docker exec #{@name} gitlab-ctl #{command}"
else
shell "docker exec #{@name} bash -c '#{input} | gitlab-ctl #{command}'"
end
end
private
##
# TODO, make it possible to use generic QA framework classes
# as a library - gitlab-org/gitlab-qa#94
#
def shell(command)
puts "Executing `#{command}`"
Open3.popen2e(command) do |_in, out, wait|
out.each { |line| puts line }
if wait.value.exited? && wait.value.exitstatus.nonzero?
raise "Docker command `#{command}` failed!"
end
end
end
end
end
end
......@@ -9,6 +9,8 @@ require 'selenium-webdriver'
module QA
module Specs
class Config < Scenario::Template
include Scenario::Actable
def perform
configure_rspec!
configure_capybara!
......
module QA
feature 'GitLab Geo replication', :geo do
scenario 'users pushes code to the primary node' do
Page::Main::Entry.act { visit(Runtime::Scenario.geo_primary_address) }
Page::Main::Login.act { sign_in_using_credentials }
Scenario::Gitlab::Project::Create.perform do |scenario|
scenario.name = 'geo-project'
scenario.description = 'Geo test project'
end
geo_project_name = Page::Project::Show.act { project_name }
expect(geo_project_name).to include 'geo-project'
Git::Repository.perform do |repository|
repository.location = Page::Project::Show.act do
choose_repository_clone_http
repository_location
end
repository.use_default_credentials
repository.act do
clone
configure_identity('GitLab QA', 'root@gitlab.com')
add_file('README.md', '# This is Geo project!')
commit('Add README.md')
push_changes
end
end
Page::Main::Entry.act { visit(Runtime::Scenario.geo_secondary_address) }
Page::Main::OAuth.act do
authorize! if needs_authorization?
end
expect(page).to have_content 'You are on a secondary (read-only) Geo node'
Page::Main::Menu.perform do |menu|
menu.go_to_projects
expect(page).to have_content(geo_project_name)
end
sleep 10 # wait for repository replication
Page::Dashboard::Projects.perform do |dashboard|
dashboard.go_to_project(geo_project_name)
end
Page::Project::Show.perform do
expect(page).to have_content 'README.md'
expect(page).to have_content 'This is Geo project!'
end
end
end
end
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment