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:
Rémy Coutable 2018-10-04 11:25:03 +00:00
commit 9e44c1b3cf
6 changed files with 118 additions and 52 deletions

View File

@ -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).')

View File

@ -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

View File

@ -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

View File

@ -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.")

View File

@ -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?

View File

@ -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