diff options
author | Dylan Griffith <dyl.griffith@gmail.com> | 2018-10-01 16:58:47 +0300 |
---|---|---|
committer | Dylan Griffith <dyl.griffith@gmail.com> | 2018-10-04 12:38:51 +0300 |
commit | c9078e3d9d19c22a2718e6c71459a83c4dd58c64 (patch) | |
tree | 009d23d672abe8f6c537e398ba033cb4f29fca9f | |
parent | 0e1fc6e04c96ce989062e02d9e706031cea87c36 (diff) |
Add a QA spec for RBAC cluster and auto devops
This fails now because we have not yet implemented support for this
6 files changed, 118 insertions, 52 deletions
diff --git a/app/views/projects/clusters/user/_form.html.haml b/app/views/projects/clusters/user/_form.html.haml index 30513d0f91b..56551ed4d65 100644 --- a/app/views/projects/clusters/user/_form.html.haml +++ b/app/views/projects/clusters/user/_form.html.haml @@ -27,7 +27,7 @@ .form-group .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' .form-text.text-muted = s_('ClusterIntegration|Enable this setting if using role-based access control (RBAC).') diff --git a/qa/qa/factory/resource/kubernetes_cluster.rb b/qa/qa/factory/resource/kubernetes_cluster.rb index 94d7df7128b..ed9d0329081 100644 --- a/qa/qa/factory/resource/kubernetes_cluster.rb +++ b/qa/qa/factory/resource/kubernetes_cluster.rb @@ -31,6 +31,7 @@ module QA page.set_api_url(@cluster.api_url) page.set_ca_certificate(@cluster.ca_certificate) page.set_token(@cluster.token) + page.check_rbac! if @cluster.rbac page.add_cluster! end diff --git a/qa/qa/page/project/operations/kubernetes/add_existing.rb b/qa/qa/page/project/operations/kubernetes/add_existing.rb index eef82b5f329..38f8527b9b4 100644 --- a/qa/qa/page/project/operations/kubernetes/add_existing.rb +++ b/qa/qa/page/project/operations/kubernetes/add_existing.rb @@ -10,6 +10,7 @@ module QA element :ca_certificate, 'text_area :ca_cert' element :token, 'text_field :token' element :add_cluster_button, "submit s_('ClusterIntegration|Add Kubernetes cluster')" + element :rbac_checkbox end def set_cluster_name(name) @@ -31,6 +32,10 @@ module QA def add_cluster! click_on 'Add Kubernetes cluster' end + + def check_rbac! + check_element :rbac_checkbox + end end end end diff --git a/qa/qa/service/kubernetes_cluster.rb b/qa/qa/service/kubernetes_cluster.rb index abd9d53554f..d868515555c 100644 --- a/qa/qa/service/kubernetes_cluster.rb +++ b/qa/qa/service/kubernetes_cluster.rb @@ -1,12 +1,17 @@ require 'securerandom' require 'mkmf' +require 'pathname' module QA module Service class KubernetesCluster 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 @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", ' ') gcloud container clusters create #{cluster_name} - --enable-legacy-authorization + #{auth_options} --zone #{Runtime::Env.gcloud_zone} && gcloud container clusters get-credentials @@ -28,8 +33,21 @@ module QA CMD @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']}"`) - @token = Base64.decode64(`kubectl get secrets -o jsonpath='{.items[0].data.token}'`) + if rbac + 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 end @@ -44,6 +62,42 @@ module QA 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 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.") diff --git a/qa/qa/service/shellout.rb b/qa/qa/service/shellout.rb index 1ca9504bb33..43dc0851571 100644 --- a/qa/qa/service/shellout.rb +++ b/qa/qa/service/shellout.rb @@ -11,10 +11,12 @@ module QA # TODO, make it possible to use generic QA framework classes # as a library - gitlab-org/gitlab-qa#94 # - def shell(command) + def shell(command, stdin_data: nil) 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 } if wait.value.exited? && wait.value.exitstatus.nonzero? diff --git a/qa/qa/specs/features/browser_ui/7_configure/auto_devops/create_project_with_auto_devops_spec.rb b/qa/qa/specs/features/browser_ui/7_configure/auto_devops/create_project_with_auto_devops_spec.rb index 844cc1236c7..4604936916b 100644 --- a/qa/qa/specs/features/browser_ui/7_configure/auto_devops/create_project_with_auto_devops_spec.rb +++ b/qa/qa/specs/features/browser_ui/7_configure/auto_devops/create_project_with_auto_devops_spec.rb @@ -9,59 +9,63 @@ module QA @cluster&.remove! end - 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 } + [true, false].each do |rbac| + context "when rbac is #{rbac ? 'enabled' : 'disabled'}" do + 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| - p.name = 'project-with-autodevops' - p.description = 'Project with Auto Devops' - end + project = Factory::Resource::Project.fabricate! do |p| + p.name = 'project-with-autodevops' + p.description = 'Project with Auto Devops' + end - # Disable code_quality check in Auto DevOps pipeline as it takes - # too long and times out the test - Factory::Resource::SecretVariable.fabricate! do |resource| - resource.project = project - resource.key = 'CODE_QUALITY_DISABLED' - resource.value = '1' - end + # Disable code_quality check in Auto DevOps pipeline as it takes + # too long and times out the test + Factory::Resource::SecretVariable.fabricate! do |resource| + resource.project = project + resource.key = 'CODE_QUALITY_DISABLED' + resource.value = '1' + end - # Create Auto Devops compatible repo - Factory::Repository::ProjectPush.fabricate! do |push| - push.project = project - push.directory = Pathname - .new(__dir__) - .join('../../../../../fixtures/auto_devops_rack') - push.commit_message = 'Create Auto DevOps compatible rack application' - end + # Create Auto Devops compatible repo + Factory::Repository::ProjectPush.fabricate! do |push| + push.project = project + push.directory = Pathname + .new(__dir__) + .join('../../../../../fixtures/auto_devops_rack') + push.commit_message = 'Create Auto DevOps compatible rack application' + end - Page::Project::Show.act { wait_for_push } + Page::Project::Show.act { wait_for_push } - # Create and connect K8s cluster - @cluster = Service::KubernetesCluster.new.create! - kubernetes_cluster = Factory::Resource::KubernetesCluster.fabricate! do |cluster| - cluster.project = project - cluster.cluster = @cluster - cluster.install_helm_tiller = true - cluster.install_ingress = true - cluster.install_prometheus = true - cluster.install_runner = true - end + # Create and connect K8s cluster + @cluster = Service::KubernetesCluster.new(rbac: rbac).create! + kubernetes_cluster = Factory::Resource::KubernetesCluster.fabricate! do |cluster| + cluster.project = project + cluster.cluster = @cluster + cluster.install_helm_tiller = true + cluster.install_ingress = true + cluster.install_prometheus = true + cluster.install_runner = true + end - project.visit! - Page::Menu::Side.act { click_ci_cd_settings } - Page::Project::Settings::CICD.perform do |p| - p.enable_auto_devops_with_domain("#{kubernetes_cluster.ingress_ip}.nip.io") - end + project.visit! + Page::Menu::Side.act { click_ci_cd_settings } + Page::Project::Settings::CICD.perform do |p| + p.enable_auto_devops_with_domain("#{kubernetes_cluster.ingress_ip}.nip.io") + end - project.visit! - Page::Menu::Side.act { click_ci_cd_pipelines } - Page::Project::Pipeline::Index.act { go_to_latest_pipeline } + project.visit! + Page::Menu::Side.act { click_ci_cd_pipelines } + Page::Project::Pipeline::Index.act { go_to_latest_pipeline } - Page::Project::Pipeline::Show.perform do |pipeline| - 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('production', status: :success, wait: 1200) + Page::Project::Pipeline::Show.perform do |pipeline| + 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('production', status: :success, wait: 1200) + end + end end end end |