Commit 9e44c1b3 authored by Rémy Coutable's avatar Rémy Coutable

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
parents d1f7b0cc c9078e3d
...@@ -27,7 +27,7 @@ ...@@ -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 ...@@ -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 ...@@ -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 ...@@ -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
......
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 ...@@ -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 ...@@ -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 ...@@ -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 ...@@ -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 ...@@ -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
......
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