summaryrefslogtreecommitdiff
path: root/qa/qa/resource
diff options
context:
space:
mode:
Diffstat (limited to 'qa/qa/resource')
-rw-r--r--qa/qa/resource/api_fabricator.rb33
-rw-r--r--qa/qa/resource/kubernetes_cluster.rb68
-rw-r--r--qa/qa/resource/kubernetes_cluster/base.rb40
-rw-r--r--qa/qa/resource/kubernetes_cluster/project_cluster.rb72
-rw-r--r--qa/qa/resource/pipeline.rb53
-rw-r--r--qa/qa/resource/project.rb34
-rw-r--r--qa/qa/resource/runner.rb27
-rw-r--r--qa/qa/resource/ssh_key.rb10
-rw-r--r--qa/qa/resource/visibility.rb17
9 files changed, 257 insertions, 97 deletions
diff --git a/qa/qa/resource/api_fabricator.rb b/qa/qa/resource/api_fabricator.rb
index cac58c599ea..591aa449219 100644
--- a/qa/qa/resource/api_fabricator.rb
+++ b/qa/qa/resource/api_fabricator.rb
@@ -14,6 +14,7 @@ module QA
ResourceQueryError = Class.new(RuntimeError)
ResourceUpdateFailedError = Class.new(RuntimeError)
ResourceURLMissingError = Class.new(RuntimeError)
+ InternalServerError = Class.new(RuntimeError)
attr_reader :api_resource, :api_response
attr_writer :api_client
@@ -54,11 +55,23 @@ module QA
end
end
- private
-
include Support::Api
attr_writer :api_resource, :api_response
+ def api_put(body = api_put_body)
+ response = put(
+ Runtime::API::Request.new(api_client, api_put_path).url,
+ body)
+
+ unless response.code == HTTP_STATUS_OK
+ raise ResourceFabricationFailedError, "Updating #{self.class.name} using the API failed (#{response.code}) with `#{response}`."
+ end
+
+ process_api_response(parse_body(response))
+ end
+
+ private
+
def resource_web_url(resource)
resource.fetch(:web_url) do
raise ResourceURLMissingError, "API resource for #{self.class.name} does not expose a `web_url` property: `#{resource}`."
@@ -73,7 +86,9 @@ module QA
url = Runtime::API::Request.new(api_client, get_path).url
response = get(url)
- unless response.code == HTTP_STATUS_OK
+ if response.code == HTTP_STATUS_SERVER_ERROR
+ raise InternalServerError, "Failed to GET #{url} - (#{response.code}): `#{response}`."
+ elsif response.code != HTTP_STATUS_OK
raise ResourceNotFoundError, "Resource at #{url} could not be found (#{response.code}): `#{response}`."
end
@@ -92,18 +107,6 @@ module QA
process_api_response(parse_body(response))
end
- def api_put
- response = put(
- Runtime::API::Request.new(api_client, api_put_path).url,
- api_put_body)
-
- unless response.code == HTTP_STATUS_OK
- raise ResourceFabricationFailedError, "Updating #{self.class.name} using the API failed (#{response.code}) with `#{response}`."
- end
-
- process_api_response(parse_body(response))
- end
-
def api_delete
url = Runtime::API::Request.new(api_client, api_delete_path).url
response = delete(url)
diff --git a/qa/qa/resource/kubernetes_cluster.rb b/qa/qa/resource/kubernetes_cluster.rb
deleted file mode 100644
index 7306acfe2a4..00000000000
--- a/qa/qa/resource/kubernetes_cluster.rb
+++ /dev/null
@@ -1,68 +0,0 @@
-# frozen_string_literal: true
-
-require 'securerandom'
-
-module QA
- module Resource
- class KubernetesCluster < Base
- attr_writer :project, :cluster,
- :install_helm_tiller, :install_ingress, :install_prometheus, :install_runner, :domain
-
- attribute :ingress_ip do
- Page::Project::Operations::Kubernetes::Show.perform(&:ingress_ip)
- end
-
- def fabricate!
- @project.visit!
-
- Page::Project::Menu.perform(
- &:go_to_operations_kubernetes)
-
- Page::Project::Operations::Kubernetes::Index.perform(
- &:add_kubernetes_cluster)
-
- Page::Project::Operations::Kubernetes::Add.perform(
- &:add_existing_cluster)
-
- Page::Project::Operations::Kubernetes::AddExisting.perform do |cluster_page|
- cluster_page.set_cluster_name(@cluster.cluster_name)
- cluster_page.set_api_url(@cluster.api_url)
- cluster_page.set_ca_certificate(@cluster.ca_certificate)
- cluster_page.set_token(@cluster.token)
- cluster_page.uncheck_rbac! unless @cluster.rbac
- cluster_page.add_cluster!
- end
-
- if @install_helm_tiller
- Page::Project::Operations::Kubernetes::Show.perform do |show|
- # We must wait a few seconds for permissions to be set up correctly for new cluster
- sleep 10
-
- # Open applications tab
- show.open_applications
-
- # Helm must be installed before everything else
- show.install!(:helm)
- show.await_installed(:helm)
-
- show.install!(:ingress) if @install_ingress
- show.install!(:prometheus) if @install_prometheus
- show.install!(:runner) if @install_runner
-
- show.await_installed(:ingress) if @install_ingress
- show.await_installed(:prometheus) if @install_prometheus
- show.await_installed(:runner) if @install_runner
-
- if @install_ingress
- populate(:ingress_ip)
-
- show.open_details
- show.set_domain("#{ingress_ip}.nip.io")
- show.save_domain
- end
- end
- end
- end
- end
- end
-end
diff --git a/qa/qa/resource/kubernetes_cluster/base.rb b/qa/qa/resource/kubernetes_cluster/base.rb
new file mode 100644
index 00000000000..38bca48be17
--- /dev/null
+++ b/qa/qa/resource/kubernetes_cluster/base.rb
@@ -0,0 +1,40 @@
+# frozen_string_literal: true
+
+require 'securerandom'
+
+module QA
+ module Resource
+ module KubernetesCluster
+ class Base < Resource::Base
+ attr_writer :add_name_uuid
+
+ attribute :id
+ attribute :name
+ attribute :domain
+ attribute :enabled
+ attribute :managed
+ attribute :management_project_id
+
+ attribute :api_url
+ attribute :token
+ attribute :ca_cert
+ attribute :namespace
+
+ attribute :authorization_type
+ attribute :environment_scope
+
+ def initialize
+ @add_name_uuid = true
+ @enabled = true
+ @managed = true
+ @authorization_type = :rbac
+ @environment_scope = :*
+ end
+
+ def name=(new_name)
+ @name = @add_name_uuid ? "#{new_name}-#{SecureRandom.hex(5)}" : new_name
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/resource/kubernetes_cluster/project_cluster.rb b/qa/qa/resource/kubernetes_cluster/project_cluster.rb
new file mode 100644
index 00000000000..5c61cc29236
--- /dev/null
+++ b/qa/qa/resource/kubernetes_cluster/project_cluster.rb
@@ -0,0 +1,72 @@
+# frozen_string_literal: true
+
+module QA
+ module Resource
+ module KubernetesCluster
+ class ProjectCluster < Base
+ attr_writer :cluster,
+ :install_helm_tiller, :install_ingress, :install_prometheus, :install_runner, :domain
+
+ attribute :project do
+ Resource::Project.fabricate!
+ end
+
+ attribute :ingress_ip do
+ Page::Project::Operations::Kubernetes::Show.perform(&:ingress_ip)
+ end
+
+ def fabricate!
+ project.visit!
+
+ Page::Project::Menu.perform(
+ &:go_to_operations_kubernetes)
+
+ Page::Project::Operations::Kubernetes::Index.perform(
+ &:add_kubernetes_cluster)
+
+ Page::Project::Operations::Kubernetes::Add.perform(
+ &:add_existing_cluster)
+
+ Page::Project::Operations::Kubernetes::AddExisting.perform do |cluster_page|
+ cluster_page.set_cluster_name(@cluster.cluster_name)
+ cluster_page.set_api_url(@cluster.api_url)
+ cluster_page.set_ca_certificate(@cluster.ca_certificate)
+ cluster_page.set_token(@cluster.token)
+ cluster_page.uncheck_rbac! unless @cluster.rbac
+ cluster_page.add_cluster!
+ end
+
+ if @install_helm_tiller
+ Page::Project::Operations::Kubernetes::Show.perform do |show|
+ # We must wait a few seconds for permissions to be set up correctly for new cluster
+ sleep 10
+
+ # Open applications tab
+ show.open_applications
+
+ # Helm must be installed before everything else
+ show.install!(:helm)
+ show.await_installed(:helm)
+
+ show.install!(:ingress) if @install_ingress
+ show.install!(:prometheus) if @install_prometheus
+ show.install!(:runner) if @install_runner
+
+ show.await_installed(:ingress) if @install_ingress
+ show.await_installed(:prometheus) if @install_prometheus
+ show.await_installed(:runner) if @install_runner
+
+ if @install_ingress
+ populate(:ingress_ip)
+
+ show.open_details
+ show.set_domain("#{ingress_ip}.nip.io")
+ show.save_domain
+ end
+ end
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/resource/pipeline.rb b/qa/qa/resource/pipeline.rb
new file mode 100644
index 00000000000..a115de3e825
--- /dev/null
+++ b/qa/qa/resource/pipeline.rb
@@ -0,0 +1,53 @@
+# frozen_string_literal: true
+
+module QA
+ module Resource
+ class Pipeline < Base
+ attribute :project do
+ Resource::Project.fabricate! do |project|
+ project.name = 'project-with-pipeline'
+ end
+ end
+
+ attribute :id
+ attribute :status
+ attribute :ref
+ attribute :sha
+
+ # array in form
+ # [
+ # { key: 'UPLOAD_TO_S3', variable_type: 'file', value: true },
+ # { key: 'SOMETHING', variable_type: 'env_var', value: 'yes' }
+ # ]
+ attribute :variables
+
+ def initialize
+ @ref = 'master'
+ @variables = []
+ end
+
+ def fabricate!
+ project.visit!
+
+ Page::Project::Menu.perform(&:click_ci_cd_pipelines)
+ Page::Project::Pipeline::Index.perform(&:click_run_pipeline_button)
+ Page::Project::Pipeline::New.perform(&:click_run_pipeline_button)
+ end
+
+ def api_get_path
+ "/projects/#{project.id}/pipelines/#{id}"
+ end
+
+ def api_post_path
+ "/projects/#{project.id}/pipeline"
+ end
+
+ def api_post_body
+ {
+ ref: ref,
+ variables: variables
+ }
+ end
+ end
+ end
+end
diff --git a/qa/qa/resource/project.rb b/qa/qa/resource/project.rb
index cb047f81d02..78e2ba8a248 100644
--- a/qa/qa/resource/project.rb
+++ b/qa/qa/resource/project.rb
@@ -7,11 +7,11 @@ module QA
class Project < Base
include Events::Project
include Members
+ include Visibility
attr_accessor :repository_storage # requires admin access
attr_writer :initialize_with_readme
attr_writer :auto_devops_enabled
- attr_writer :visibility
attribute :id
attribute :name
@@ -19,6 +19,8 @@ module QA
attribute :description
attribute :standalone
attribute :runners_token
+ attribute :visibility
+ attribute :template_name
attribute :group do
Group.fabricate!
@@ -50,7 +52,8 @@ module QA
@description = 'My awesome project'
@initialize_with_readme = false
@auto_devops_enabled = false
- @visibility = 'public'
+ @visibility = :public
+ @template_name = nil
end
def name=(raw_name)
@@ -63,6 +66,13 @@ module QA
Page::Group::Show.perform(&:go_to_new_project)
end
+ if @template_name
+ Page::Project::New.perform do |new_page|
+ new_page.click_create_from_template_tab
+ new_page.use_template_for_project(@template_name)
+ end
+ end
+
Page::Project::New.perform do |new_page|
new_page.choose_test_namespace
new_page.choose_name(@name)
@@ -83,6 +93,10 @@ module QA
"/projects/#{CGI.escape(path_with_namespace)}"
end
+ def api_visibility_path
+ "/projects/#{id}"
+ end
+
def api_get_archive_path(type = 'tar.gz')
"#{api_get_path}/repository/archive.#{type}"
end
@@ -95,6 +109,10 @@ module QA
"#{api_get_path}/runners"
end
+ def api_pipelines_path
+ "#{api_get_path}/pipelines"
+ end
+
def api_put_path
"/projects/#{id}"
end
@@ -118,6 +136,7 @@ module QA
end
post_body[:repository_storage] = repository_storage if repository_storage
+ post_body[:template_name] = @template_name if @template_name
post_body
end
@@ -152,10 +171,19 @@ module QA
end
def runners(tag_list: nil)
- response = get Runtime::API::Request.new(api_client, "#{api_runners_path}?tag_list=#{tag_list.compact.join(',')}").url
+ response = if tag_list
+ get Runtime::API::Request.new(api_client, "#{api_runners_path}?tag_list=#{tag_list.compact.join(',')}").url
+ else
+ get Runtime::API::Request.new(api_client, "#{api_runners_path}").url
+ end
+
parse_body(response)
end
+ def pipelines
+ parse_body(get(Runtime::API::Request.new(api_client, api_pipelines_path).url))
+ end
+
def share_with_group(invitee, access_level = Resource::Members::AccessLevel::DEVELOPER)
post Runtime::API::Request.new(api_client, "/projects/#{id}/share").url, { group_id: invitee.id, group_access: access_level }
end
diff --git a/qa/qa/resource/runner.rb b/qa/qa/resource/runner.rb
index f1f72c9cacd..b2a36f92ffe 100644
--- a/qa/qa/resource/runner.rb
+++ b/qa/qa/resource/runner.rb
@@ -5,8 +5,8 @@ require 'securerandom'
module QA
module Resource
class Runner < Base
- attr_writer :name, :tags, :image
- attr_accessor :config, :token
+ attr_writer :name, :tags, :image, :executor, :executor_image
+ attr_accessor :config, :token, :run_untagged
attribute :id
attribute :project do
@@ -20,35 +20,42 @@ module QA
@name || "qa-runner-#{SecureRandom.hex(4)}"
end
- def tags
- @tags || %w[qa e2e]
- end
-
def image
@image || 'gitlab/gitlab-runner:alpine'
end
+ def executor
+ @executor || :shell
+ end
+
+ def executor_image
+ @executor_image || 'registry.gitlab.com/gitlab-org/gitlab-build-images:gitlab-qa-alpine-ruby-2.6'
+ end
+
def fabricate_via_api!
Service::DockerRun::GitlabRunner.new(name).tap do |runner|
runner.pull
runner.token = @token ||= project.runners_token
runner.address = Runtime::Scenario.gitlab_address
- runner.tags = tags
+ runner.tags = @tags if @tags
runner.image = image
runner.config = config if config
+ runner.executor = executor
+ runner.executor_image = executor_image if executor == :docker
+ runner.run_untagged = run_untagged if run_untagged
runner.register!
end
end
def remove_via_api!
- runners = project.runners(tag_list: tags)
+ runners = project.runners(tag_list: @tags)
unless runners && !runners.empty?
- raise "Project #{project.path_with_namespace} has no runners with tags #{tags}."
+ raise "Project #{project.path_with_namespace} has no runners#{" with tags #{@tags}." if @tags&.any?}"
end
this_runner = runners.find { |runner| runner[:description] == name }
unless this_runner
- raise "Project #{project.path_with_namespace} does not have a runner with a description matching #{name} and tags #{tags}. Runners available: #{runners}"
+ raise "Project #{project.path_with_namespace} does not have a runner with a description matching #{name} #{"or tags #{@tags}" if @tags&.any?}. Runners available: #{runners}"
end
@id = this_runner[:id]
diff --git a/qa/qa/resource/ssh_key.rb b/qa/qa/resource/ssh_key.rb
index 3e130aef9e4..b948bf3969b 100644
--- a/qa/qa/resource/ssh_key.rb
+++ b/qa/qa/resource/ssh_key.rb
@@ -5,12 +5,16 @@ module QA
class SSHKey < Base
extend Forwardable
- attr_accessor :title
+ attr_reader :title
attribute :id
def_delegators :key, :private_key, :public_key, :md5_fingerprint
+ def initialize
+ self.title = Time.now.to_f
+ end
+
def key
@key ||= Runtime::Key::RSA.new
end
@@ -28,6 +32,10 @@ module QA
api_post
end
+ def title=(title)
+ @title = "E2E test key: #{title}"
+ end
+
def api_delete
QA::Runtime::Logger.debug("Deleting SSH key with title '#{title}' and fingerprint '#{md5_fingerprint}'")
diff --git a/qa/qa/resource/visibility.rb b/qa/qa/resource/visibility.rb
new file mode 100644
index 00000000000..b31bd3fca49
--- /dev/null
+++ b/qa/qa/resource/visibility.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+module QA
+ module Resource
+ module Visibility
+ def set_visibility(visibility)
+ put Runtime::API::Request.new(api_client, api_visibility_path).url, { visibility: visibility }
+ end
+
+ class VisibilityLevel
+ %i(public internal private).each do |level|
+ const_set(level.upcase, level)
+ end
+ end
+ end
+ end
+end