diff options
Diffstat (limited to 'qa/qa/resource')
-rw-r--r-- | qa/qa/resource/api_fabricator.rb | 33 | ||||
-rw-r--r-- | qa/qa/resource/kubernetes_cluster.rb | 68 | ||||
-rw-r--r-- | qa/qa/resource/kubernetes_cluster/base.rb | 40 | ||||
-rw-r--r-- | qa/qa/resource/kubernetes_cluster/project_cluster.rb | 72 | ||||
-rw-r--r-- | qa/qa/resource/pipeline.rb | 53 | ||||
-rw-r--r-- | qa/qa/resource/project.rb | 34 | ||||
-rw-r--r-- | qa/qa/resource/runner.rb | 27 | ||||
-rw-r--r-- | qa/qa/resource/ssh_key.rb | 10 | ||||
-rw-r--r-- | qa/qa/resource/visibility.rb | 17 |
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 |