summaryrefslogtreecommitdiff
path: root/qa/qa/tools
diff options
context:
space:
mode:
Diffstat (limited to 'qa/qa/tools')
-rw-r--r--qa/qa/tools/delete_test_resources.rb87
-rw-r--r--qa/qa/tools/initialize_gitlab_auth.rb2
-rw-r--r--qa/qa/tools/reliable_report.rb2
-rw-r--r--qa/qa/tools/test_resource_data_processor.rb107
4 files changed, 117 insertions, 81 deletions
diff --git a/qa/qa/tools/delete_test_resources.rb b/qa/qa/tools/delete_test_resources.rb
index 917cb2fa992..6f63c56f736 100644
--- a/qa/qa/tools/delete_test_resources.rb
+++ b/qa/qa/tools/delete_test_resources.rb
@@ -1,8 +1,8 @@
# frozen_string_literal: true
-# This script reads from test_resources.txt file to collect data about resources to delete
-# Deletes all deletable resources that E2E tests created
-# Resource type: Sandbox, User, Fork and RSpec::Mocks::Double are not included
+# This script reads from test-resources JSON file to collect data about resources to delete
+# Filter out resources that cannot be deleted
+# Then deletes all deletable resources that E2E tests created
#
# Required environment variables: GITLAB_QA_ACCESS_TOKEN and GITLAB_ADDRESS
# When in CI also requires: QA_TEST_RESOURCES_FILE_PATTERN
@@ -13,7 +13,15 @@ module QA
class DeleteTestResources
include Support::API
- def initialize(file_pattern = nil)
+ IGNORED_RESOURCES = [
+ 'QA::Resource::PersonalAccessToken',
+ 'QA::Resource::CiVariable',
+ 'QA::Resource::Repository::Commit',
+ 'QA::EE::Resource::GroupIteration',
+ 'QA::EE::Resource::Settings::Elasticsearch'
+ ].freeze
+
+ def initialize(file_pattern = Runtime::Env.test_resources_created_filepath)
raise ArgumentError, "Please provide GITLAB_ADDRESS" unless ENV['GITLAB_ADDRESS']
raise ArgumentError, "Please provide GITLAB_QA_ACCESS_TOKEN" unless ENV['GITLAB_QA_ACCESS_TOKEN']
@@ -22,45 +30,58 @@ module QA
end
def run
- puts 'Deleting test created resources...'
-
- if Runtime::Env.running_in_ci?
- raise ArgumentError, 'Please provide QA_TEST_RESOURCES_FILE_PATTERN' unless ENV['QA_TEST_RESOURCES_FILE_PATTERN']
-
- Dir.glob(@file_pattern).each do |file|
- delete_resources(load_file(file))
- end
- else
- file = Runtime::Env.test_resources_created_filepath
- raise ArgumentError, "'#{file}' either does not exist or empty." if !File.exist?(file) || File.zero?(file)
-
- delete_resources(load_file(file))
+ failures = files.flat_map do |file|
+ resources = read_file(file)
+ filtered_resources = filter_resources(resources)
+ delete_resources(filtered_resources)
end
- puts "\nDone"
+ return puts "\nDone" if failures.empty?
+
+ puts "\nFailed to delete #{failures.size} resources:\n"
+ puts failures
end
private
- def load_file(json)
- JSON.parse(File.read(json))
+ def files
+ puts "Gathering JSON files...\n"
+ files = Dir.glob(@file_pattern)
+ abort("There is no file with this pattern #{@file_pattern}") if files.empty?
+
+ files.reject { |file| File.zero?(file) }
+
+ files
end
- def delete_resources(resources)
- failures = []
+ def read_file(file)
+ JSON.parse(File.read(file))
+ end
- resources.each_key do |type|
- next if resources[type].empty?
+ def filter_resources(resources)
+ puts "Filtering resources - Only keep deletable resources...\n"
- resources[type].each do |resource|
- next if resource_not_found?(resource['api_path'])
+ transformed_values = resources.transform_values! do |v|
+ v.reject do |attributes|
+ attributes['info'] == "with full_path 'gitlab-qa-sandbox-group'" ||
+ attributes['http_method'] == 'get' && !attributes['info']&.include?("with username 'qa-") ||
+ attributes['api_path'] == 'Cannot find resource API path'
+ end
+ end
+
+ transformed_values.reject! { |k, v| v.empty? || IGNORED_RESOURCES.include?(k) }
+ end
- msg = resource['info'] ? "#{type} - #{resource['info']}" : "#{type} at #{resource['api_path']}"
+ def delete_resources(resources)
+ resources.each_with_object([]) do |(key, value), failures|
+ value.each do |resource|
+ next if resource_not_found?(resource['api_path'])
+ msg = resource['info'] ? "#{key} - #{resource['info']}" : "#{key} at #{resource['api_path']}"
puts "\nDeleting #{msg}..."
delete_response = delete(Runtime::API::Request.new(@api_client, resource['api_path']).url)
- if delete_response.code == 202
+ if delete_response.code == 202 || delete_response.code == 204
print "\e[32m.\e[0m"
else
print "\e[31mF\e[0m"
@@ -68,17 +89,11 @@ module QA
end
end
end
-
- unless failures.empty?
- puts "\nFailed to delete #{failures.length} resources:\n"
- puts failures
- end
end
def resource_not_found?(api_path)
- get_response = get Runtime::API::Request.new(@api_client, api_path).url
-
- get_response.code.eql? 404
+ # if api path contains param "?hard_delete=<boolean>", remove it
+ get(Runtime::API::Request.new(@api_client, api_path.split('?').first).url).code.eql? 404
end
end
end
diff --git a/qa/qa/tools/initialize_gitlab_auth.rb b/qa/qa/tools/initialize_gitlab_auth.rb
index 86791f1f624..18e90f0d739 100644
--- a/qa/qa/tools/initialize_gitlab_auth.rb
+++ b/qa/qa/tools/initialize_gitlab_auth.rb
@@ -16,7 +16,7 @@ module QA
def run
Runtime::Scenario.define(:gitlab_address, address)
- puts "Signing in and creating the default password for the root user if it's not set already..."
+ QA::Runtime::Logger.info("Signing in and creating the default password for the root user if it's not set already...")
QA::Runtime::Browser.visit(:gitlab, QA::Page::Main::Login)
Flow::Login.sign_in
diff --git a/qa/qa/tools/reliable_report.rb b/qa/qa/tools/reliable_report.rb
index b99b97c1ea6..27e54c2d8bf 100644
--- a/qa/qa/tools/reliable_report.rb
+++ b/qa/qa/tools/reliable_report.rb
@@ -58,7 +58,7 @@ module QA
{
title: "Reliable e2e test report",
description: report_issue_body,
- labels: "Quality,test,type::maintenance,reliable test report"
+ labels: "Quality,test,type::maintenance,reliable test report,automation:devops-mapping-disable"
},
headers: { "PRIVATE-TOKEN" => gitlab_access_token }
)
diff --git a/qa/qa/tools/test_resource_data_processor.rb b/qa/qa/tools/test_resource_data_processor.rb
index 78fb6ef6cd0..965919dc516 100644
--- a/qa/qa/tools/test_resource_data_processor.rb
+++ b/qa/qa/tools/test_resource_data_processor.rb
@@ -6,60 +6,81 @@
module QA
module Tools
class TestResourceDataProcessor
- @resources ||= Hash.new { |hsh, key| hsh[key] = [] }
+ include Singleton
+
+ def initialize
+ @resources = Hash.new { |hsh, key| hsh[key] = [] }
+ end
class << self
- # Ignoring rspec-mocks, sandbox, user and fork resources
- # TODO: Will need to figure out which user resources can be collected, ignore for now
- #
- # Collecting resources created in E2E tests
- # Data is a Hash of resources with keys as resource type (group, project, issue, etc.)
- # Each type contains an array of resource object (hash) of the same type
- # E.g: { "QA::Resource::Project": [ { info: 'foo', api_path: '/foo'}, {...} ] }
- def collect(resource, info)
- return if resource.api_response.nil? ||
- resource.is_a?(RSpec::Mocks::Double) ||
- resource.is_a?(Resource::Sandbox) ||
- resource.is_a?(Resource::User) ||
- resource.is_a?(Resource::Fork)
+ delegate :collect, :write_to_file, :resources, to: :instance
+ end
- api_path = if resource.respond_to?(:api_delete_path)
- resource.api_delete_path.gsub('%2F', '/')
- elsif resource.respond_to?(:api_get_path)
- resource.api_get_path.gsub('%2F', '/')
- else
- 'Cannot find resource API path'
- end
+ # @return [Hash<String, Array>]
+ attr_reader :resources
- type = resource.class.name
+ # Collecting resources created in E2E tests
+ # Data is a Hash of resources with keys as resource type (group, project, issue, etc.)
+ # Each type contains an array of resource object (hash) of the same type
+ # E.g: { "QA::Resource::Project": [ { info: 'foo', api_path: '/foo'}, {...} ] }
+ #
+ # @param [QA::Resource::Base] resource fabricated resource
+ # @param [String] info resource info
+ # @param [Symbol] method fabrication method, api or browser_ui
+ # @param [Integer] time fabrication time
+ # @return [Hash]
+ def collect(resource:, info:, fabrication_method:, fabrication_time:)
+ api_path = resource_api_path(resource)
+ type = resource.class.name
- @resources[type] << { info: info, api_path: api_path }
- end
+ resources[type] << {
+ info: info,
+ api_path: api_path,
+ fabrication_method: fabrication_method,
+ fabrication_time: fabrication_time,
+ http_method: resource.api_fabrication_http_method,
+ timestamp: Time.now.to_s
+ }
+ end
+
+ # If JSON file exists and not empty, read and load file content
+ # Merge what is saved in @resources into the content from file
+ # Overwrite file content with the new data hash
+ # Otherwise create file and write data hash to file for the first time
+ #
+ # @return [void]
+ def write_to_file
+ return if resources.empty?
- # If JSON file exists and not empty, read and load file content
- # Merge what is saved in @resources into the content from file
- # Overwrite file content with the new data hash
- # Otherwise create file and write data hash to file for the first time
- def write_to_file
- return if @resources.empty?
+ file = Pathname.new(Runtime::Env.test_resources_created_filepath)
+ FileUtils.mkdir_p(file.dirname)
- file = Runtime::Env.test_resources_created_filepath
- FileUtils.mkdir_p('tmp/')
- FileUtils.touch(file)
- data = nil
+ data = resources.deep_dup
+ # merge existing json if present
+ JSON.parse(File.read(file)).deep_merge!(data) { |key, val, other_val| val + other_val } if file.exist?
+
+ File.write(file, JSON.pretty_generate(data))
+ end
- if File.zero?(file)
- data = @resources
- else
- data = JSON.parse(File.read(file))
+ private
- @resources.each_pair do |key, val|
- data[key].nil? ? data[key] = val : val.each { |item| data[key] << item }
- end
- end
+ # Determine resource api path or return default value
+ # Some resources fabricated via UI can raise no attribute error
+ #
+ # @param [QA::Resource::Base] resource
+ # @return [String]
+ def resource_api_path(resource)
+ default = 'Cannot find resource API path'
- File.open(file, 'w') { |f| f.write(JSON.pretty_generate(data.each_value(&:uniq!))) }
+ if resource.respond_to?(:api_delete_path)
+ resource.api_delete_path.gsub('%2F', '/')
+ elsif resource.respond_to?(:api_get_path)
+ resource.api_get_path.gsub('%2F', '/')
+ else
+ default
end
+ rescue QA::Resource::Base::NoValueError
+ default
end
end
end