Merge branch '44597-auto-devops-rbac-qa-spec' into 'master'
Add a QA spec for RBAC cluster and auto devops See merge request gitlab-org/gitlab-ce!22025
This commit is contained in:
commit
9e44c1b3cf
|
@ -27,7 +27,7 @@
|
||||||
|
|
||||||
.form-group
|
.form-group
|
||||||
.form-check
|
.form-check
|
||||||
= platform_kubernetes_field.check_box :authorization_type, { class: 'form-check-input' }, 'rbac', 'abac'
|
= platform_kubernetes_field.check_box :authorization_type, { class: 'form-check-input qa-rbac-checkbox' }, 'rbac', 'abac'
|
||||||
= platform_kubernetes_field.label :authorization_type, s_('ClusterIntegration|RBAC-enabled cluster (experimental)'), class: 'form-check-label label-bold'
|
= platform_kubernetes_field.label :authorization_type, s_('ClusterIntegration|RBAC-enabled cluster (experimental)'), class: 'form-check-label label-bold'
|
||||||
.form-text.text-muted
|
.form-text.text-muted
|
||||||
= s_('ClusterIntegration|Enable this setting if using role-based access control (RBAC).')
|
= s_('ClusterIntegration|Enable this setting if using role-based access control (RBAC).')
|
||||||
|
|
|
@ -31,6 +31,7 @@ module QA
|
||||||
page.set_api_url(@cluster.api_url)
|
page.set_api_url(@cluster.api_url)
|
||||||
page.set_ca_certificate(@cluster.ca_certificate)
|
page.set_ca_certificate(@cluster.ca_certificate)
|
||||||
page.set_token(@cluster.token)
|
page.set_token(@cluster.token)
|
||||||
|
page.check_rbac! if @cluster.rbac
|
||||||
page.add_cluster!
|
page.add_cluster!
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -10,6 +10,7 @@ module QA
|
||||||
element :ca_certificate, 'text_area :ca_cert'
|
element :ca_certificate, 'text_area :ca_cert'
|
||||||
element :token, 'text_field :token'
|
element :token, 'text_field :token'
|
||||||
element :add_cluster_button, "submit s_('ClusterIntegration|Add Kubernetes cluster')"
|
element :add_cluster_button, "submit s_('ClusterIntegration|Add Kubernetes cluster')"
|
||||||
|
element :rbac_checkbox
|
||||||
end
|
end
|
||||||
|
|
||||||
def set_cluster_name(name)
|
def set_cluster_name(name)
|
||||||
|
@ -31,6 +32,10 @@ module QA
|
||||||
def add_cluster!
|
def add_cluster!
|
||||||
click_on 'Add Kubernetes cluster'
|
click_on 'Add Kubernetes cluster'
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def check_rbac!
|
||||||
|
check_element :rbac_checkbox
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,12 +1,17 @@
|
||||||
require 'securerandom'
|
require 'securerandom'
|
||||||
require 'mkmf'
|
require 'mkmf'
|
||||||
|
require 'pathname'
|
||||||
|
|
||||||
module QA
|
module QA
|
||||||
module Service
|
module Service
|
||||||
class KubernetesCluster
|
class KubernetesCluster
|
||||||
include Service::Shellout
|
include Service::Shellout
|
||||||
|
|
||||||
attr_reader :api_url, :ca_certificate, :token
|
attr_reader :api_url, :ca_certificate, :token, :rbac
|
||||||
|
|
||||||
|
def initialize(rbac: false)
|
||||||
|
@rbac = rbac
|
||||||
|
end
|
||||||
|
|
||||||
def cluster_name
|
def cluster_name
|
||||||
@cluster_name ||= "qa-cluster-#{SecureRandom.hex(4)}-#{Time.now.utc.strftime("%Y%m%d%H%M%S")}"
|
@cluster_name ||= "qa-cluster-#{SecureRandom.hex(4)}-#{Time.now.utc.strftime("%Y%m%d%H%M%S")}"
|
||||||
|
@ -19,7 +24,7 @@ module QA
|
||||||
shell <<~CMD.tr("\n", ' ')
|
shell <<~CMD.tr("\n", ' ')
|
||||||
gcloud container clusters
|
gcloud container clusters
|
||||||
create #{cluster_name}
|
create #{cluster_name}
|
||||||
--enable-legacy-authorization
|
#{auth_options}
|
||||||
--zone #{Runtime::Env.gcloud_zone}
|
--zone #{Runtime::Env.gcloud_zone}
|
||||||
&& gcloud container clusters
|
&& gcloud container clusters
|
||||||
get-credentials
|
get-credentials
|
||||||
|
@ -28,8 +33,21 @@ module QA
|
||||||
CMD
|
CMD
|
||||||
|
|
||||||
@api_url = `kubectl config view --minify -o jsonpath='{.clusters[].cluster.server}'`
|
@api_url = `kubectl config view --minify -o jsonpath='{.clusters[].cluster.server}'`
|
||||||
@ca_certificate = Base64.decode64(`kubectl get secrets -o jsonpath="{.items[0].data['ca\\.crt']}"`)
|
if rbac
|
||||||
@token = Base64.decode64(`kubectl get secrets -o jsonpath='{.items[0].data.token}'`)
|
create_service_account
|
||||||
|
|
||||||
|
secrets = JSON.parse(`kubectl get secrets -o json`)
|
||||||
|
gitlab_account = secrets['items'].find do |item|
|
||||||
|
item['metadata']['annotations']['kubernetes.io/service-account.name'] == 'gitlab-account'
|
||||||
|
end
|
||||||
|
|
||||||
|
@ca_certificate = Base64.decode64(gitlab_account['data']['ca.crt'])
|
||||||
|
@token = Base64.decode64(gitlab_account['data']['token'])
|
||||||
|
else
|
||||||
|
@ca_certificate = Base64.decode64(`kubectl get secrets -o jsonpath="{.items[0].data['ca\\.crt']}"`)
|
||||||
|
@token = Base64.decode64(`kubectl get secrets -o jsonpath='{.items[0].data.token}'`)
|
||||||
|
end
|
||||||
|
|
||||||
self
|
self
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -44,6 +62,42 @@ module QA
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
|
def create_service_account
|
||||||
|
shell('kubectl create -f -', stdin_data: service_account)
|
||||||
|
shell('kubectl create -f -', stdin_data: service_account_role_binding)
|
||||||
|
end
|
||||||
|
|
||||||
|
def service_account
|
||||||
|
<<~YAML
|
||||||
|
apiVersion: v1
|
||||||
|
kind: ServiceAccount
|
||||||
|
metadata:
|
||||||
|
name: gitlab-account
|
||||||
|
namespace: default
|
||||||
|
YAML
|
||||||
|
end
|
||||||
|
|
||||||
|
def service_account_role_binding
|
||||||
|
<<~YAML
|
||||||
|
kind: ClusterRoleBinding
|
||||||
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
|
metadata:
|
||||||
|
name: gitlab-account-binding
|
||||||
|
subjects:
|
||||||
|
- kind: ServiceAccount
|
||||||
|
name: gitlab-account
|
||||||
|
namespace: default
|
||||||
|
roleRef:
|
||||||
|
kind: ClusterRole
|
||||||
|
name: cluster-admin
|
||||||
|
apiGroup: rbac.authorization.k8s.io
|
||||||
|
YAML
|
||||||
|
end
|
||||||
|
|
||||||
|
def auth_options
|
||||||
|
"--enable-legacy-authorization" unless rbac
|
||||||
|
end
|
||||||
|
|
||||||
def validate_dependencies
|
def validate_dependencies
|
||||||
find_executable('gcloud') || raise("You must first install `gcloud` executable to run these tests.")
|
find_executable('gcloud') || raise("You must first install `gcloud` executable to run these tests.")
|
||||||
find_executable('kubectl') || raise("You must first install `kubectl` executable to run these tests.")
|
find_executable('kubectl') || raise("You must first install `kubectl` executable to run these tests.")
|
||||||
|
|
|
@ -11,10 +11,12 @@ module QA
|
||||||
# TODO, make it possible to use generic QA framework classes
|
# TODO, make it possible to use generic QA framework classes
|
||||||
# as a library - gitlab-org/gitlab-qa#94
|
# as a library - gitlab-org/gitlab-qa#94
|
||||||
#
|
#
|
||||||
def shell(command)
|
def shell(command, stdin_data: nil)
|
||||||
puts "Executing `#{command}`"
|
puts "Executing `#{command}`"
|
||||||
|
|
||||||
Open3.popen2e(*command) do |_in, out, wait|
|
Open3.popen2e(*command) do |stdin, out, wait|
|
||||||
|
stdin.puts(stdin_data) if stdin_data
|
||||||
|
stdin.close if stdin_data
|
||||||
out.each { |line| puts line }
|
out.each { |line| puts line }
|
||||||
|
|
||||||
if wait.value.exited? && wait.value.exitstatus.nonzero?
|
if wait.value.exited? && wait.value.exitstatus.nonzero?
|
||||||
|
|
|
@ -9,59 +9,63 @@ module QA
|
||||||
@cluster&.remove!
|
@cluster&.remove!
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'user creates a new project and runs auto devops' do
|
[true, false].each do |rbac|
|
||||||
Runtime::Browser.visit(:gitlab, Page::Main::Login)
|
context "when rbac is #{rbac ? 'enabled' : 'disabled'}" do
|
||||||
Page::Main::Login.act { sign_in_using_credentials }
|
it 'user creates a new project and runs auto devops' do
|
||||||
|
Runtime::Browser.visit(:gitlab, Page::Main::Login)
|
||||||
|
Page::Main::Login.act { sign_in_using_credentials }
|
||||||
|
|
||||||
project = Factory::Resource::Project.fabricate! do |p|
|
project = Factory::Resource::Project.fabricate! do |p|
|
||||||
p.name = 'project-with-autodevops'
|
p.name = 'project-with-autodevops'
|
||||||
p.description = 'Project with Auto Devops'
|
p.description = 'Project with Auto Devops'
|
||||||
end
|
end
|
||||||
|
|
||||||
# Disable code_quality check in Auto DevOps pipeline as it takes
|
# Disable code_quality check in Auto DevOps pipeline as it takes
|
||||||
# too long and times out the test
|
# too long and times out the test
|
||||||
Factory::Resource::SecretVariable.fabricate! do |resource|
|
Factory::Resource::SecretVariable.fabricate! do |resource|
|
||||||
resource.project = project
|
resource.project = project
|
||||||
resource.key = 'CODE_QUALITY_DISABLED'
|
resource.key = 'CODE_QUALITY_DISABLED'
|
||||||
resource.value = '1'
|
resource.value = '1'
|
||||||
end
|
end
|
||||||
|
|
||||||
# Create Auto Devops compatible repo
|
# Create Auto Devops compatible repo
|
||||||
Factory::Repository::ProjectPush.fabricate! do |push|
|
Factory::Repository::ProjectPush.fabricate! do |push|
|
||||||
push.project = project
|
push.project = project
|
||||||
push.directory = Pathname
|
push.directory = Pathname
|
||||||
.new(__dir__)
|
.new(__dir__)
|
||||||
.join('../../../../../fixtures/auto_devops_rack')
|
.join('../../../../../fixtures/auto_devops_rack')
|
||||||
push.commit_message = 'Create Auto DevOps compatible rack application'
|
push.commit_message = 'Create Auto DevOps compatible rack application'
|
||||||
end
|
end
|
||||||
|
|
||||||
Page::Project::Show.act { wait_for_push }
|
Page::Project::Show.act { wait_for_push }
|
||||||
|
|
||||||
# Create and connect K8s cluster
|
# Create and connect K8s cluster
|
||||||
@cluster = Service::KubernetesCluster.new.create!
|
@cluster = Service::KubernetesCluster.new(rbac: rbac).create!
|
||||||
kubernetes_cluster = Factory::Resource::KubernetesCluster.fabricate! do |cluster|
|
kubernetes_cluster = Factory::Resource::KubernetesCluster.fabricate! do |cluster|
|
||||||
cluster.project = project
|
cluster.project = project
|
||||||
cluster.cluster = @cluster
|
cluster.cluster = @cluster
|
||||||
cluster.install_helm_tiller = true
|
cluster.install_helm_tiller = true
|
||||||
cluster.install_ingress = true
|
cluster.install_ingress = true
|
||||||
cluster.install_prometheus = true
|
cluster.install_prometheus = true
|
||||||
cluster.install_runner = true
|
cluster.install_runner = true
|
||||||
end
|
end
|
||||||
|
|
||||||
project.visit!
|
project.visit!
|
||||||
Page::Menu::Side.act { click_ci_cd_settings }
|
Page::Menu::Side.act { click_ci_cd_settings }
|
||||||
Page::Project::Settings::CICD.perform do |p|
|
Page::Project::Settings::CICD.perform do |p|
|
||||||
p.enable_auto_devops_with_domain("#{kubernetes_cluster.ingress_ip}.nip.io")
|
p.enable_auto_devops_with_domain("#{kubernetes_cluster.ingress_ip}.nip.io")
|
||||||
end
|
end
|
||||||
|
|
||||||
project.visit!
|
project.visit!
|
||||||
Page::Menu::Side.act { click_ci_cd_pipelines }
|
Page::Menu::Side.act { click_ci_cd_pipelines }
|
||||||
Page::Project::Pipeline::Index.act { go_to_latest_pipeline }
|
Page::Project::Pipeline::Index.act { go_to_latest_pipeline }
|
||||||
|
|
||||||
Page::Project::Pipeline::Show.perform do |pipeline|
|
Page::Project::Pipeline::Show.perform do |pipeline|
|
||||||
expect(pipeline).to have_build('build', status: :success, wait: 600)
|
expect(pipeline).to have_build('build', status: :success, wait: 600)
|
||||||
expect(pipeline).to have_build('test', status: :success, wait: 600)
|
expect(pipeline).to have_build('test', status: :success, wait: 600)
|
||||||
expect(pipeline).to have_build('production', status: :success, wait: 1200)
|
expect(pipeline).to have_build('production', status: :success, wait: 1200)
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in New Issue