From 8ff73614a1466ffc39e4464462719e7456c03e29 Mon Sep 17 00:00:00 2001 From: Mayra Cabrera Date: Wed, 23 Jan 2019 10:28:19 -0600 Subject: [PATCH 1/5] Moves domain setting to Cluster setting Changes domain field to be on the Cluster page show, removing it from Auto DevOps setting. Also injects the new environment variable KUBE_INGRESS_BASE_DOMAIN into kubernetes#predefined_variables. Migration to move the information from ProjectAutoDevops#domain to Clusters::Cluster#domain. As well as necessary modifications to qa selectors Closes https://gitlab.com/gitlab-org/gitlab-ce/issues/52363 --- .../clusters/clusters_controller.rb | 2 + app/helpers/auto_devops_helper.rb | 11 -- app/models/clusters/cluster.rb | 19 +++- app/models/clusters/platforms/kubernetes.rb | 2 + app/models/project_auto_devops.rb | 3 + app/views/clusters/clusters/_form.html.haml | 18 +++- .../settings/ci_cd/_autodevops_form.html.haml | 13 +-- ...63-ui-changes-to-cluster-and-ado-pages.yml | 5 + ...e_auto_dev_ops_domain_to_cluster_domain.rb | 78 ++++++++++++++ locale/gitlab.pot | 20 +++- qa/qa/page/project/settings/ci_cd.rb | 5 +- qa/qa/resource/kubernetes_cluster.rb | 14 ++- .../create_project_with_auto_devops_spec.rb | 6 +- .../groups/clusters_controller_spec.rb | 21 +++- .../clusters/cluster_detail_page_spec.rb | 69 ++++++++++++ .../settings/pipelines_settings_spec.rb | 25 ----- ...o_dev_ops_domain_to_cluster_domain_spec.rb | 100 ++++++++++++++++++ spec/models/clusters/cluster_spec.rb | 59 +++++++++++ .../clusters/platforms/kubernetes_spec.rb | 13 +++ 19 files changed, 421 insertions(+), 62 deletions(-) create mode 100644 changelogs/unreleased/52363-ui-changes-to-cluster-and-ado-pages.yml create mode 100644 db/migrate/20190129165720_migrate_auto_dev_ops_domain_to_cluster_domain.rb create mode 100644 spec/features/clusters/cluster_detail_page_spec.rb create mode 100644 spec/migrations/migrate_auto_dev_ops_domain_to_cluster_domain_spec.rb diff --git a/app/controllers/clusters/clusters_controller.rb b/app/controllers/clusters/clusters_controller.rb index b9717b97640..483842fe456 100644 --- a/app/controllers/clusters/clusters_controller.rb +++ b/app/controllers/clusters/clusters_controller.rb @@ -127,6 +127,7 @@ def update_params params.require(:cluster).permit( :enabled, :environment_scope, + :domain, platform_kubernetes_attributes: [ :namespace ] @@ -136,6 +137,7 @@ def update_params :enabled, :name, :environment_scope, + :domain, platform_kubernetes_attributes: [ :api_url, :token, diff --git a/app/helpers/auto_devops_helper.rb b/app/helpers/auto_devops_helper.rb index 516c8a353ea..8628c90dc51 100644 --- a/app/helpers/auto_devops_helper.rb +++ b/app/helpers/auto_devops_helper.rb @@ -26,17 +26,6 @@ def auto_devops_warning_message(project) end end - # rubocop: disable CodeReuse/ActiveRecord - def cluster_ingress_ip(project) - project - .cluster_ingresses - .where("external_ip is not null") - .limit(1) - .pluck(:external_ip) - .first - end - # rubocop: enable CodeReuse/ActiveRecord - private def missing_auto_devops_domain?(project) diff --git a/app/models/clusters/cluster.rb b/app/models/clusters/cluster.rb index a2c48973fa5..2b677961df5 100644 --- a/app/models/clusters/cluster.rb +++ b/app/models/clusters/cluster.rb @@ -49,7 +49,7 @@ class Cluster < ActiveRecord::Base validates :name, cluster_name: true validates :cluster_type, presence: true - validates :domain, allow_nil: true, hostname: { allow_numeric_hostname: true, require_valid_tld: true } + validates :domain, allow_blank: true, hostname: { allow_numeric_hostname: true, require_valid_tld: true } validate :restrict_modification, on: :update validate :no_groups, unless: :group_type? @@ -65,6 +65,7 @@ class Cluster < ActiveRecord::Base delegate :available?, to: :application_ingress, prefix: true, allow_nil: true delegate :available?, to: :application_prometheus, prefix: true, allow_nil: true delegate :available?, to: :application_knative, prefix: true, allow_nil: true + delegate :external_ip, to: :application_ingress, prefix: true, allow_nil: true enum cluster_type: { instance_type: 1, @@ -193,8 +194,24 @@ def allow_user_defined_namespace? project_type? end + def has_domain? + domain.present? || instance_domain.present? + end + + def predefined_variables + Gitlab::Ci::Variables::Collection.new.tap do |variables| + break variables unless has_domain? + + variables.append(key: 'KUBE_INGRESS_BASE_DOMAIN', value: domain.presence || instance_domain) + end + end + private + def instance_domain + Gitlab::CurrentSettings.auto_devops_domain + end + def restrict_modification if provider&.on_creation? errors.add(:base, "cannot modify during creation") diff --git a/app/models/clusters/platforms/kubernetes.rb b/app/models/clusters/platforms/kubernetes.rb index 8f3424db295..c8969351ed9 100644 --- a/app/models/clusters/platforms/kubernetes.rb +++ b/app/models/clusters/platforms/kubernetes.rb @@ -98,6 +98,8 @@ def predefined_variables(project:) .append(key: 'KUBE_NAMESPACE', value: actual_namespace) .append(key: 'KUBECONFIG', value: kubeconfig, public: false, file: true) end + + variables.concat(cluster.predefined_variables) end end diff --git a/app/models/project_auto_devops.rb b/app/models/project_auto_devops.rb index 2253ad7b543..d254ec158ca 100644 --- a/app/models/project_auto_devops.rb +++ b/app/models/project_auto_devops.rb @@ -24,6 +24,9 @@ def has_domain? domain.present? || instance_domain.present? end + # From 11.8, AUTO_DEVOPS_DOMAIN has been replaced by KUBE_INGRESS_BASE_DOMAIN. + # See Clusters::Cluster#predefined_variables and https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/24580 + # for more info. Support for AUTO_DEVOPS_DOMAIN support will be dropped on 12.0. def predefined_variables Gitlab::Ci::Variables::Collection.new.tap do |variables| if has_domain? diff --git a/app/views/clusters/clusters/_form.html.haml b/app/views/clusters/clusters/_form.html.haml index 4c47e11927e..068f14364ec 100644 --- a/app/views/clusters/clusters/_form.html.haml +++ b/app/views/clusters/clusters/_form.html.haml @@ -20,12 +20,28 @@ .form-text.text-muted= s_("ClusterIntegration|Choose which of your environments will use this cluster.") - else = text_field_tag :environment_scope, '*', class: 'col-md-6 form-control disabled', placeholder: s_('ClusterIntegration|Environment scope'), disabled: true - - environment_scope_url = 'https://docs.gitlab.com/ee/user/project/clusters/#setting-the-environment-scope-premium' + - environment_scope_url = 'https://docs.gitlab.com/ee/user/project/clusters/#base-domain' - environment_scope_start = ''.html_safe % { url: environment_scope_url } .form-text.text-muted %code * = s_("ClusterIntegration| is the default environment scope for this cluster. This means that all jobs, regardless of their environment, will use this cluster. %{environment_scope_start}More information%{environment_scope_end}").html_safe % { environment_scope_start: environment_scope_start, environment_scope_end: ''.html_safe } + .form-group + %h5= s_('ClusterIntegration|Base domain') + = field.text_field :domain, class: 'col-md-6 form-control js-select-on-focus' + .form-text.text-muted + - if @cluster.application_ingress_external_ip.present? + - auto_devops_url = 'https://docs.gitlab.com/ee/topics/autodevops/' + - auto_devops_start = ''.html_safe % { url: auto_devops_url } + = s_('ClusterIntegration|Specifying a domain will allow you to use Auto Review Apps and Auto Deploy stages for %{auto_devops_start}Auto DevOps%{auto_devops_end}. The domain should have a wildcard DNS configured to the Ingress IP Address below.').html_safe % { auto_devops_start: auto_devops_start, auto_devops_end: ''.html_safe } + = s_('ClusterIntegration|Alternatively') + %code #{@cluster.application_ingress_external_ip}.nip.io + - custom_domain_url = 'https://docs.gitlab.com/ee/user/project/clusters/#pointing-your-dns-at-the-cluster-ip' + - custom_domain_start = ''.html_safe % { url: custom_domain_url } + = s_('ClusterIntegration| can be used instead of a custom domain. %{custom_domain_start}More information%{custom_domain_end}').html_safe % { custom_domain_start: custom_domain_start, custom_domain_end: ''.html_safe } + - else + = s_('ClusterIntegration|Before setting a domain, you must first install Ingress on your cluster below.') + - if can?(current_user, :update_cluster, @cluster) .form-group = field.submit _('Save changes'), class: 'btn btn-success' diff --git a/app/views/projects/settings/ci_cd/_autodevops_form.html.haml b/app/views/projects/settings/ci_cd/_autodevops_form.html.haml index 5ec5a06396e..c2bbcf8fcaf 100644 --- a/app/views/projects/settings/ci_cd/_autodevops_form.html.haml +++ b/app/views/projects/settings/ci_cd/_autodevops_form.html.haml @@ -21,15 +21,10 @@ = s_('CICD|The Auto DevOps pipeline will run if no alternative CI configuration file is found.') = link_to _('More information'), help_page_path('topics/autodevops/index.md'), target: '_blank' .card-footer.js-extra-settings{ class: @project.auto_devops_enabled? || 'hidden' } - = form.label :domain do - %strong= _('Domain') - = form.text_field :domain, class: 'form-control', placeholder: 'domain.com' - .form-text.text-muted - = s_('CICD|You need to specify a domain if you want to use Auto Review Apps and Auto Deploy stages.') - - if cluster_ingress_ip = cluster_ingress_ip(@project) - = s_('%{nip_domain} can be used as an alternative to a custom domain.').html_safe % { nip_domain: "#{cluster_ingress_ip}.nip.io".html_safe } - = link_to icon('question-circle'), help_page_path('topics/autodevops/index.md', anchor: 'auto-devops-base-domain'), target: '_blank' - + %p.settings-message.text-center + - kubernetes_cluster_link = 'https://docs.gitlab.com/ee/user/project/clusters/' + - kubernetes_cluster_start = ''.html_safe % { url: kubernetes_cluster_link } + = s_('CICD|You must add a %{kubernetes_cluster_start}Kubernetes cluster integration%{kubernetes_cluster_end} to this project with a domain in order for your deployment strategy to work correctly.').html_safe % { kubernetes_cluster_start: kubernetes_cluster_start, kubernetes_cluster_end: ''.html_safe } %label.prepend-top-10 %strong= s_('CICD|Deployment strategy') %p.settings-message.text-center diff --git a/changelogs/unreleased/52363-ui-changes-to-cluster-and-ado-pages.yml b/changelogs/unreleased/52363-ui-changes-to-cluster-and-ado-pages.yml new file mode 100644 index 00000000000..25f01f95177 --- /dev/null +++ b/changelogs/unreleased/52363-ui-changes-to-cluster-and-ado-pages.yml @@ -0,0 +1,5 @@ +--- +title: Moves domain setting to cluster page +merge_request: 24580 +author: +type: added diff --git a/db/migrate/20190129165720_migrate_auto_dev_ops_domain_to_cluster_domain.rb b/db/migrate/20190129165720_migrate_auto_dev_ops_domain_to_cluster_domain.rb new file mode 100644 index 00000000000..2d3e9acaa62 --- /dev/null +++ b/db/migrate/20190129165720_migrate_auto_dev_ops_domain_to_cluster_domain.rb @@ -0,0 +1,78 @@ +# frozen_string_literal: true + +class MigrateAutoDevOpsDomainToClusterDomain < ActiveRecord::Migration[5.0] + include Gitlab::Database::MigrationHelpers + + DOWNTIME = false + + def up + domains_info = connection.exec_query(project_auto_devops_query).rows + domains_info.each_slice(1_000) do |batch| + update_clusters_query = build_clusters_query(Hash[*batch.flatten]) + + connection.exec_query(update_clusters_query) + end + end + + def down + # no-op + end + + private + + def project_auto_devops_table + @project_auto_devops_table ||= ProjectAutoDevops.arel_table + end + + def cluster_projects_table + @cluster_projects_table ||= Clusters::Project.arel_table + end + + # Fetches ProjectAutoDevops records with: + # - A domain set + # - With a Clusters::Project related to Project + # + # Returns an array of arrays like: + # => [ + # [177, "104.198.38.135.nip.io"], + # [178, "35.232.213.111.nip.io"], + # ... + # ] + # Where the first element is the Cluster ID and + # the second element is the domain. + def project_auto_devops_query + project_auto_devops_table.join(cluster_projects_table, Arel::Nodes::OuterJoin) + .on(project_auto_devops_table[:project_id].eq(cluster_projects_table[:project_id])) + .where(project_auto_devops_table[:domain].not_eq(nil).and(project_auto_devops_table[:domain].not_eq(''))) + .project(cluster_projects_table[:cluster_id], project_auto_devops_table[:domain]) + .to_sql + end + + # Returns an SQL UPDATE query using a CASE statement + # to update multiple cluster rows with different values. + # + # Example: + # UPDATE clusters + # SET domain = (CASE + # WHEN id = 177 then '104.198.38.135.nip.io' + # WHEN id = 178 then '35.232.213.111.nip.io' + # WHEN id = 179 then '35.232.168.149.nip.io' + # WHEN id = 180 then '35.224.116.88.nip.io' + # END) + # WHERE id IN (177,178,179,180); + def build_clusters_query(cluster_domains_info) + <<~HEREDOC + UPDATE clusters + SET domain = (CASE + #{cluster_when_statements(cluster_domains_info)} + END) + WHERE id IN (#{cluster_domains_info.keys.join(",")}); + HEREDOC + end + + def cluster_when_statements(cluster_domains_info) + cluster_domains_info.map do |cluster_id, domain| + "WHEN id = #{cluster_id} then '#{domain}'" + end.join("\n") + end +end diff --git a/locale/gitlab.pot b/locale/gitlab.pot index ccdbc63c51e..8600e6fa394 100644 --- a/locale/gitlab.pot +++ b/locale/gitlab.pot @@ -138,9 +138,6 @@ msgstr "" msgid "%{lock_path} is locked by GitLab User %{lock_user_id}" msgstr "" -msgid "%{nip_domain} can be used as an alternative to a custom domain." -msgstr "" - msgid "%{number_commits_behind} commits behind %{default_branch}, %{number_commits_ahead} commits ahead" msgstr "" @@ -1236,7 +1233,7 @@ msgstr "" msgid "CICD|The Auto DevOps pipeline will run if no alternative CI configuration file is found." msgstr "" -msgid "CICD|You need to specify a domain if you want to use Auto Review Apps and Auto Deploy stages." +msgid "CICD|You must add a %{kubernetes_cluster_start}Kubernetes cluster integration%{kubernetes_cluster_end} to this project with a domain in order for your deployment strategy to work correctly." msgstr "" msgid "CICD|instance enabled" @@ -1509,6 +1506,9 @@ msgstr "" msgid "Closed (moved)" msgstr "" +msgid "ClusterIntegration| can be used instead of a custom domain. %{custom_domain_start}More information%{custom_domain_end}" +msgstr "" + msgid "ClusterIntegration| is the default environment scope for this cluster. This means that all jobs, regardless of their environment, will use this cluster. %{environment_scope_start}More information%{environment_scope_end}" msgstr "" @@ -1539,6 +1539,9 @@ msgstr "" msgid "ClusterIntegration|After installing Ingress, you will need to point your wildcard DNS at the generated external IP address in order to view your app after it is deployed. %{ingressHelpLink}" msgstr "" +msgid "ClusterIntegration|Alternatively" +msgstr "" + msgid "ClusterIntegration|An error occured while trying to fetch project zones: %{error}" msgstr "" @@ -1560,6 +1563,12 @@ msgstr "" msgid "ClusterIntegration|Are you sure you want to remove this Kubernetes cluster's integration? This will not delete your actual Kubernetes cluster." msgstr "" +msgid "ClusterIntegration|Base domain" +msgstr "" + +msgid "ClusterIntegration|Before setting a domain, you must first install Ingress on your cluster below." +msgstr "" + msgid "ClusterIntegration|CA Certificate" msgstr "" @@ -1884,6 +1893,9 @@ msgstr "" msgid "ClusterIntegration|Something went wrong while installing %{title}" msgstr "" +msgid "ClusterIntegration|Specifying a domain will allow you to use Auto Review Apps and Auto Deploy stages for %{auto_devops_start}Auto DevOps%{auto_devops_end}. The domain should have a wildcard DNS configured to the Ingress IP Address below." +msgstr "" + msgid "ClusterIntegration|The IP address is in the process of being assigned. Please check your Kubernetes cluster or Quotas on Google Kubernetes Engine if it takes a long time." msgstr "" diff --git a/qa/qa/page/project/settings/ci_cd.rb b/qa/qa/page/project/settings/ci_cd.rb index 12c2409a5a7..2de39b8ebf5 100644 --- a/qa/qa/page/project/settings/ci_cd.rb +++ b/qa/qa/page/project/settings/ci_cd.rb @@ -13,9 +13,7 @@ class CICD < Page::Base view 'app/views/projects/settings/ci_cd/_autodevops_form.html.haml' do element :enable_auto_devops_field, 'check_box :enabled' # rubocop:disable QA/ElementWithPattern - element :domain_field, 'text_field :domain' # rubocop:disable QA/ElementWithPattern element :enable_auto_devops_button, "%strong= s_('CICD|Default to Auto DevOps pipeline')" # rubocop:disable QA/ElementWithPattern - element :domain_input, "%strong= _('Domain')" # rubocop:disable QA/ElementWithPattern element :save_changes_button, "submit _('Save changes')" # rubocop:disable QA/ElementWithPattern end @@ -31,10 +29,9 @@ def expand_ci_variables(&block) end end - def enable_auto_devops_with_domain(domain) + def enable_auto_devops expand_section(:autodevops_settings) do check 'Default to Auto DevOps pipeline' - fill_in 'Domain', with: domain click_on 'Save changes' end end diff --git a/qa/qa/resource/kubernetes_cluster.rb b/qa/qa/resource/kubernetes_cluster.rb index d67e5f6da20..19c6dc8890d 100644 --- a/qa/qa/resource/kubernetes_cluster.rb +++ b/qa/qa/resource/kubernetes_cluster.rb @@ -6,10 +6,14 @@ module QA module Resource class KubernetesCluster < Base attr_writer :project, :cluster, - :install_helm_tiller, :install_ingress, :install_prometheus, :install_runner + :install_helm_tiller, :install_ingress, :install_prometheus, :install_runner, :domain attribute :ingress_ip do - Page::Project::Operations::Kubernetes::Show.perform(&:ingress_ip) + ingress_ip_value + end + + attribute :domain do + "#{ingress_ip_value}.nip.io" end def fabricate! @@ -52,6 +56,12 @@ def fabricate! end end end + + private + + def ingress_ip_value + @ingress_ip_value ||= Page::Project::Operations::Kubernetes::Show.perform(&:ingress_ip) + end end end end 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 b0ff83db86b..5c8ec465143 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 @@ -52,13 +52,13 @@ def login end kubernetes_cluster.populate(:ingress_ip) - @project.visit! Page::Project::Menu.act { click_ci_cd_settings } Page::Project::Settings::CICD.perform do |p| - p.enable_auto_devops_with_domain( - "#{kubernetes_cluster.ingress_ip}.nip.io") + p.enable_auto_devops end + + kubernetes_cluster.populate(:domain) end after(:all) do diff --git a/spec/controllers/groups/clusters_controller_spec.rb b/spec/controllers/groups/clusters_controller_spec.rb index 0f28499194e..d5a149a57df 100644 --- a/spec/controllers/groups/clusters_controller_spec.rb +++ b/spec/controllers/groups/clusters_controller_spec.rb @@ -429,12 +429,14 @@ def go(format: :html) end let(:cluster) { create(:cluster, :provided_by_user, cluster_type: :group_type, groups: [group]) } + let(:domain) { 'test-domain.com' } let(:params) do { cluster: { enabled: false, - name: 'my-new-cluster-name' + name: 'my-new-cluster-name', + domain: domain } } end @@ -447,6 +449,20 @@ def go(format: :html) expect(flash[:notice]).to eq('Kubernetes cluster was successfully updated.') expect(cluster.enabled).to be_falsey expect(cluster.name).to eq('my-new-cluster-name') + expect(cluster.domain).to eq('test-domain.com') + end + + context 'when domain is invalid' do + let(:domain) { 'not-a-valid-domain' } + + it 'should not update cluster attributes' do + go + + cluster.reload + expect(response).to render_template(:show) + expect(cluster.name).not_to eq('my-new-cluster-name') + expect(cluster.domain).not_to eq('test-domain.com') + end end context 'when format is json' do @@ -456,7 +472,8 @@ def go(format: :html) { cluster: { enabled: false, - name: 'my-new-cluster-name' + name: 'my-new-cluster-name', + domain: domain } } end diff --git a/spec/features/clusters/cluster_detail_page_spec.rb b/spec/features/clusters/cluster_detail_page_spec.rb new file mode 100644 index 00000000000..844008f841a --- /dev/null +++ b/spec/features/clusters/cluster_detail_page_spec.rb @@ -0,0 +1,69 @@ +# frozen_string_literal: true + +require 'spec_helper' + +describe 'Clusterable > Show page' do + let(:current_user) { create(:user) } + + before do + sign_in(current_user) + end + + shared_examples 'editing domain' do + before do + clusterable.add_maintainer(current_user) + end + + it 'allow the user to set domain' do + visit cluster_path + + within '#cluster-integration' do + fill_in('cluster_domain', with: 'test.com') + click_on 'Save changes' + end + + expect(page.status_code).to eq(200) + expect(page).to have_content('Kubernetes cluster was successfully updated.') + end + + context 'when there is a cluster with ingress and external ip' do + before do + cluster.create_application_ingress!(external_ip: '192.168.1.100') + + visit cluster_path + end + + it 'shows help text with the domain as an alternative to custom domain' do + within '#cluster-integration' do + expect(page).to have_content('Alternatively 192.168.1.100.nip.io can be used instead of a custom domain') + end + end + end + + context 'when there is no ingress' do + it 'alternative to custom domain is not shown' do + visit cluster_path + + within '#cluster-integration' do + expect(page).to have_content('Before setting a domain, you must first install Ingress on your cluster below.') + end + end + end + end + + context 'when clusterable is a project' do + it_behaves_like 'editing domain' do + let(:clusterable) { create(:project) } + let(:cluster) { create(:cluster, :provided_by_gcp, :project, projects: [clusterable]) } + let(:cluster_path) { project_cluster_path(clusterable, cluster) } + end + end + + context 'when clusterable is a group' do + it_behaves_like 'editing domain' do + let(:clusterable) { create(:group) } + let(:cluster) { create(:cluster, :provided_by_gcp, :group, groups: [clusterable]) } + let(:cluster_path) { group_cluster_path(clusterable, cluster) } + end + end +end diff --git a/spec/features/projects/settings/pipelines_settings_spec.rb b/spec/features/projects/settings/pipelines_settings_spec.rb index 6f8ec0015ad..4c85abe9971 100644 --- a/spec/features/projects/settings/pipelines_settings_spec.rb +++ b/spec/features/projects/settings/pipelines_settings_spec.rb @@ -98,14 +98,12 @@ expect(page).not_to have_content('instance enabled') expect(find_field('project_auto_devops_attributes_enabled')).not_to be_checked check 'Default to Auto DevOps pipeline' - fill_in('project_auto_devops_attributes_domain', with: 'test.com') click_on 'Save changes' end expect(page.status_code).to eq(200) expect(project.auto_devops).to be_present expect(project.auto_devops).to be_enabled - expect(project.auto_devops.domain).to eq('test.com') page.within '#autodevops-settings' do expect(find_field('project_auto_devops_attributes_enabled')).to be_checked @@ -113,29 +111,6 @@ end end end - - context 'when there is a cluster with ingress and external_ip' do - before do - cluster = create(:cluster, projects: [project]) - cluster.create_application_ingress!(external_ip: '192.168.1.100') - end - - it 'shows the help text with the nip.io domain as an alternative to custom domain' do - visit project_settings_ci_cd_path(project) - expect(page).to have_content('192.168.1.100.nip.io can be used as an alternative to a custom domain') - end - end - - context 'when there is no ingress' do - before do - create(:cluster, projects: [project]) - end - - it 'alternative to custom domain is not shown' do - visit project_settings_ci_cd_path(project) - expect(page).not_to have_content('can be used as an alternative to a custom domain') - end - end end describe 'runners registration token' do diff --git a/spec/migrations/migrate_auto_dev_ops_domain_to_cluster_domain_spec.rb b/spec/migrations/migrate_auto_dev_ops_domain_to_cluster_domain_spec.rb new file mode 100644 index 00000000000..09013ee4bd0 --- /dev/null +++ b/spec/migrations/migrate_auto_dev_ops_domain_to_cluster_domain_spec.rb @@ -0,0 +1,100 @@ +# frozen_string_literal: true + +require 'spec_helper' +require Rails.root.join('db', 'migrate', '20190129165720_migrate_auto_dev_ops_domain_to_cluster_domain.rb') + +describe MigrateAutoDevOpsDomainToClusterDomain, :migration do + include MigrationHelpers::ClusterHelpers + + let(:migration) { described_class.new } + let(:project_auto_devops_table) { table(:project_auto_devops) } + let(:clusters_table) { table(:clusters) } + let(:cluster_projects_table) { table(:cluster_projects) } + + # Following lets are needed by MigrationHelpers::ClusterHelpers + let(:cluster_kubernetes_namespaces_table) { table(:clusters_kubernetes_namespaces) } + let(:projects_table) { table(:projects) } + let(:namespaces_table) { table(:namespaces) } + let(:provider_gcp_table) { table(:cluster_providers_gcp) } + let(:platform_kubernetes_table) { table(:cluster_platforms_kubernetes) } + + before do + setup_cluster_projects_with_domain(quantity: 20, domain: domain) + end + + context 'with ProjectAutoDevOps with no domain' do + let(:domain) { nil } + + it 'should not update cluster project' do + migrate! + + expect(clusters_without_domain.count).to eq(clusters_table.count) + end + end + + context 'with ProjectAutoDevOps with domain' do + let(:domain) { 'example-domain.com' } + + it 'should update all cluster projects' do + migrate! + + expect(clusters_with_domain.count).to eq(clusters_table.count) + end + end + + context 'when only some ProjectAutoDevOps have domain set' do + let(:domain) { 'example-domain.com' } + + before do + setup_cluster_projects_with_domain(quantity: 20, domain: nil) + end + + it 'should only update specific cluster projects' do + migrate! + + project_auto_devops_with_domain.each do |project_auto_devops| + cluster_project = Clusters::Project.find_by(project_id: project_auto_devops.project_id) + cluster = Clusters::Cluster.find(cluster_project.cluster_id) + + expect(cluster.domain).to be_present + end + + project_auto_devops_without_domain.each do |project_auto_devops| + cluster_project = Clusters::Project.find_by(project_id: project_auto_devops.project_id) + cluster = Clusters::Cluster.find(cluster_project.cluster_id) + + expect(cluster.domain).not_to be_present + end + end + end + + def setup_cluster_projects_with_domain(quantity:, domain:) + create_cluster_project_list(quantity) + + cluster_projects = cluster_projects_table.last(quantity) + + cluster_projects.each do |cluster_project| + project_auto_devops_table.create( + project_id: cluster_project.project_id, + enabled: true, + domain: domain + ) + end + end + + def project_auto_devops_with_domain + project_auto_devops_table.where.not("domain IS NULL OR domain = ''") + end + + def project_auto_devops_without_domain + project_auto_devops_table.where("domain IS NULL OR domain = ''") + end + + def clusters_with_domain + clusters_table.where.not("domain IS NULL OR domain = ''") + end + + def clusters_without_domain + clusters_table.where("domain IS NULL OR domain = ''") + end +end diff --git a/spec/models/clusters/cluster_spec.rb b/spec/models/clusters/cluster_spec.rb index 0161db740ee..abef586d258 100644 --- a/spec/models/clusters/cluster_spec.rb +++ b/spec/models/clusters/cluster_spec.rb @@ -30,6 +30,7 @@ it { is_expected.to delegate_method(:available?).to(:application_ingress).with_prefix } it { is_expected.to delegate_method(:available?).to(:application_prometheus).with_prefix } it { is_expected.to delegate_method(:available?).to(:application_knative).with_prefix } + it { is_expected.to delegate_method(:external_ip).to(:application_ingress).with_prefix } it { is_expected.to respond_to :project } @@ -514,4 +515,62 @@ it { is_expected.to be_falsey } end end + + describe '#has_domain?' do + subject { cluster.has_domain? } + + context 'with domain set at instance level' do + let(:cluster) { create(:cluster, :provided_by_gcp) } + + before do + stub_application_setting(auto_devops_domain: 'global_domain.com') + end + + it { is_expected.to be_truthy } + end + + context 'with domain set in cluster' do + let(:cluster) { create(:cluster, :provided_by_gcp, :with_domain) } + + it { is_expected.to be_truthy } + end + + context 'when domain is not set at instance level nor in cluster' do + let(:cluster) { create(:cluster, :provided_by_gcp) } + + it { is_expected.to be_falsy } + end + end + + describe '#predefined_variables' do + subject { cluster.predefined_variables } + + context 'with an instance domain' do + let(:cluster) { create(:cluster, :provided_by_gcp) } + + before do + stub_application_setting(auto_devops_domain: 'global_domain.com') + end + + it 'should include KUBE_INGRESS_BASE_DOMAIN' do + expect(subject.to_hash).to include(KUBE_INGRESS_BASE_DOMAIN: 'global_domain.com') + end + end + + context 'with a cluster domain' do + let(:cluster) { create(:cluster, :provided_by_gcp, domain: 'example.com') } + + it 'should include KUBE_INGRESS_BASE_DOMAIN' do + expect(subject.to_hash).to include(KUBE_INGRESS_BASE_DOMAIN: 'example.com') + end + end + + context 'with no domain' do + let(:cluster) { create(:cluster) } + + it 'should return an empty array' do + expect(subject.to_hash).to be_empty + end + end + end end diff --git a/spec/models/clusters/platforms/kubernetes_spec.rb b/spec/models/clusters/platforms/kubernetes_spec.rb index 6c8a223092e..c273fa7e164 100644 --- a/spec/models/clusters/platforms/kubernetes_spec.rb +++ b/spec/models/clusters/platforms/kubernetes_spec.rb @@ -297,6 +297,19 @@ end end end + + context 'with a domain' do + let!(:cluster) do + create(:cluster, :provided_by_gcp, :with_domain, + platform_kubernetes: kubernetes) + end + + it 'sets KUBE_INGRESS_BASE_DOMAIN' do + expect(subject).to include( + { key: 'KUBE_INGRESS_BASE_DOMAIN', value: cluster.domain, public: true } + ) + end + end end describe '#terminals' do -- GitLab From 6fe15fdc5205700f5c31cdd0a4ca2d420840911e Mon Sep 17 00:00:00 2001 From: Mayra Cabrera Date: Mon, 28 Jan 2019 14:27:23 -0600 Subject: [PATCH 2/5] Modifies ADO script to include new variable Ensure KUBE_INGRESS_BASE_DOMAIN existence by setting his value to AUTO_DEVOPS_DOMAIN if the first one doesnt exists. Also made corresponding changes throughout the whole script Related to https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/24580 --- .../ci/templates/Auto-DevOps.gitlab-ci.yml | 37 +++++++++++++------ 1 file changed, 25 insertions(+), 12 deletions(-) diff --git a/lib/gitlab/ci/templates/Auto-DevOps.gitlab-ci.yml b/lib/gitlab/ci/templates/Auto-DevOps.gitlab-ci.yml index 75a5bf142d2..a0015c958fe 100644 --- a/lib/gitlab/ci/templates/Auto-DevOps.gitlab-ci.yml +++ b/lib/gitlab/ci/templates/Auto-DevOps.gitlab-ci.yml @@ -21,8 +21,8 @@ # # In order to deploy, you must have a Kubernetes cluster configured either # via a project integration, or via group/project variables. -# AUTO_DEVOPS_DOMAIN must also be set as a variable at the group or project -# level, or manually added below. +# KUBE_INGRESS_BASE_DOMAIN must also be set on the cluster settings, +# as a variable at the group or project level, or manually added below. # # Continuous deployment to production is enabled by default. # If you want to deploy to staging first, set STAGING_ENABLED environment variable. @@ -41,8 +41,8 @@ image: alpine:latest variables: - # AUTO_DEVOPS_DOMAIN is the application deployment domain and should be set as a variable at the group or project level. - # AUTO_DEVOPS_DOMAIN: domain.example.com + # KUBE_INGRESS_BASE_DOMAIN is the application deployment domain and should be set as a variable at the group or project level. + # KUBE_INGRESS_BASE_DOMAIN: domain.example.com POSTGRES_USER: user POSTGRES_PASSWORD: testing-password @@ -251,7 +251,7 @@ review: - persist_environment_url environment: name: review/$CI_COMMIT_REF_NAME - url: http://$CI_PROJECT_PATH_SLUG-$CI_ENVIRONMENT_SLUG.$AUTO_DEVOPS_DOMAIN + url: http://$CI_PROJECT_PATH_SLUG-$CI_ENVIRONMENT_SLUG.$KUBE_INGRESS_BASE_DOMAIN on_stop: stop_review artifacts: paths: [environment_url.txt] @@ -306,7 +306,7 @@ staging: - deploy environment: name: staging - url: http://$CI_PROJECT_PATH_SLUG-staging.$AUTO_DEVOPS_DOMAIN + url: http://$CI_PROJECT_PATH_SLUG-staging.$KUBE_INGRESS_BASE_DOMAIN only: refs: - master @@ -330,7 +330,7 @@ canary: - deploy canary environment: name: production - url: http://$CI_PROJECT_PATH_SLUG.$AUTO_DEVOPS_DOMAIN + url: http://$CI_PROJECT_PATH_SLUG.$KUBE_INGRESS_BASE_DOMAIN when: manual only: refs: @@ -354,7 +354,7 @@ canary: - persist_environment_url environment: name: production - url: http://$CI_PROJECT_PATH_SLUG.$AUTO_DEVOPS_DOMAIN + url: http://$CI_PROJECT_PATH_SLUG.$KUBE_INGRESS_BASE_DOMAIN artifacts: paths: [environment_url.txt] @@ -403,7 +403,7 @@ production_manual: - persist_environment_url environment: name: production - url: http://$CI_PROJECT_PATH_SLUG.$AUTO_DEVOPS_DOMAIN + url: http://$CI_PROJECT_PATH_SLUG.$KUBE_INGRESS_BASE_DOMAIN artifacts: paths: [environment_url.txt] @@ -823,11 +823,24 @@ rollout 100%: kubectl describe namespace "$KUBE_NAMESPACE" || kubectl create namespace "$KUBE_NAMESPACE" } + + # Function to ensure backwards compatibility with AUTO_DEVOPS_DOMAIN + function ensure_kube_ingress_base_domain() { + if [ -z ${KUBE_INGRESS_BASE_DOMAIN+x} ]; then + export KUBE_INGRESS_BASE_DOMAIN=$AUTO_DEVOPS_DOMAIN + fi + } + function check_kube_domain() { - if [ -z ${AUTO_DEVOPS_DOMAIN+x} ]; then - echo "In order to deploy or use Review Apps, AUTO_DEVOPS_DOMAIN variable must be set" - echo "You can do it in Auto DevOps project settings or defining a variable at group or project level" + ensure_kube_ingress_base_domain + + if [ -z ${KUBE_INGRESS_BASE_DOMAIN+x} ]; then + echo "In order to deploy or use Review Apps," + echo "AUTO_DEVOPS_DOMAIN or KUBE_INGRESS_BASE_DOMAIN variables must be set" + echo "From 11.8, you can set KUBE_INGRESS_BASE_DOMAIN in cluster settings" + echo "or by defining a variable at group or project level." echo "You can also manually add it in .gitlab-ci.yml" + echo "AUTO_DEVOPS_DOMAIN support will be dropped on 12.0" false else true -- GitLab From 8b5553daa43d48fdef42f0f2a3f700580dea770b Mon Sep 17 00:00:00 2001 From: Mayra Cabrera Date: Wed, 30 Jan 2019 09:39:48 -0600 Subject: [PATCH 3/5] Use a single sql statement for ADO query Since cluster_projects table does not have a lot of records, currently it has 11,638, it seems better to use a single sql statement to update all the records --- ...e_auto_dev_ops_domain_to_cluster_domain.rb | 77 ++++++------------- ...o_dev_ops_domain_to_cluster_domain_spec.rb | 10 ++- 2 files changed, 32 insertions(+), 55 deletions(-) diff --git a/db/migrate/20190129165720_migrate_auto_dev_ops_domain_to_cluster_domain.rb b/db/migrate/20190129165720_migrate_auto_dev_ops_domain_to_cluster_domain.rb index 2d3e9acaa62..392e64eeade 100644 --- a/db/migrate/20190129165720_migrate_auto_dev_ops_domain_to_cluster_domain.rb +++ b/db/migrate/20190129165720_migrate_auto_dev_ops_domain_to_cluster_domain.rb @@ -6,12 +6,7 @@ class MigrateAutoDevOpsDomainToClusterDomain < ActiveRecord::Migration[5.0] DOWNTIME = false def up - domains_info = connection.exec_query(project_auto_devops_query).rows - domains_info.each_slice(1_000) do |batch| - update_clusters_query = build_clusters_query(Hash[*batch.flatten]) - - connection.exec_query(update_clusters_query) - end + execute(update_clusters_domain_query) end def down @@ -20,59 +15,35 @@ def down private - def project_auto_devops_table - @project_auto_devops_table ||= ProjectAutoDevops.arel_table - end - - def cluster_projects_table - @cluster_projects_table ||= Clusters::Project.arel_table + def update_clusters_domain_query + if Gitlab::Database.mysql? + mysql_query + else + postgresql_query + end end - # Fetches ProjectAutoDevops records with: - # - A domain set - # - With a Clusters::Project related to Project - # - # Returns an array of arrays like: - # => [ - # [177, "104.198.38.135.nip.io"], - # [178, "35.232.213.111.nip.io"], - # ... - # ] - # Where the first element is the Cluster ID and - # the second element is the domain. - def project_auto_devops_query - project_auto_devops_table.join(cluster_projects_table, Arel::Nodes::OuterJoin) - .on(project_auto_devops_table[:project_id].eq(cluster_projects_table[:project_id])) - .where(project_auto_devops_table[:domain].not_eq(nil).and(project_auto_devops_table[:domain].not_eq(''))) - .project(cluster_projects_table[:cluster_id], project_auto_devops_table[:domain]) - .to_sql + def mysql_query + <<~HEREDOC + UPDATE clusters, project_auto_devops, cluster_projects + SET + clusters.domain = project_auto_devops.domain + WHERE + cluster_projects.cluster_id = clusters.id + AND project_auto_devops.project_id = cluster_projects.project_id + AND project_auto_devops.domain != '' + HEREDOC end - # Returns an SQL UPDATE query using a CASE statement - # to update multiple cluster rows with different values. - # - # Example: - # UPDATE clusters - # SET domain = (CASE - # WHEN id = 177 then '104.198.38.135.nip.io' - # WHEN id = 178 then '35.232.213.111.nip.io' - # WHEN id = 179 then '35.232.168.149.nip.io' - # WHEN id = 180 then '35.224.116.88.nip.io' - # END) - # WHERE id IN (177,178,179,180); - def build_clusters_query(cluster_domains_info) + def postgresql_query <<~HEREDOC UPDATE clusters - SET domain = (CASE - #{cluster_when_statements(cluster_domains_info)} - END) - WHERE id IN (#{cluster_domains_info.keys.join(",")}); + SET domain = project_auto_devops.domain + FROM cluster_projects, project_auto_devops + WHERE + cluster_projects.cluster_id = clusters.id + AND project_auto_devops.project_id = cluster_projects.project_id + AND project_auto_devops.domain != '' HEREDOC end - - def cluster_when_statements(cluster_domains_info) - cluster_domains_info.map do |cluster_id, domain| - "WHEN id = #{cluster_id} then '#{domain}'" - end.join("\n") - end end diff --git a/spec/migrations/migrate_auto_dev_ops_domain_to_cluster_domain_spec.rb b/spec/migrations/migrate_auto_dev_ops_domain_to_cluster_domain_spec.rb index 09013ee4bd0..c7fd27588a5 100644 --- a/spec/migrations/migrate_auto_dev_ops_domain_to_cluster_domain_spec.rb +++ b/spec/migrations/migrate_auto_dev_ops_domain_to_cluster_domain_spec.rb @@ -46,12 +46,14 @@ let(:domain) { 'example-domain.com' } before do - setup_cluster_projects_with_domain(quantity: 20, domain: nil) + setup_cluster_projects_with_domain(quantity: 25, domain: nil) end it 'should only update specific cluster projects' do migrate! + expect(clusters_with_domain.count).to eq(20) + project_auto_devops_with_domain.each do |project_auto_devops| cluster_project = Clusters::Project.find_by(project_id: project_auto_devops.project_id) cluster = Clusters::Cluster.find(cluster_project.cluster_id) @@ -59,6 +61,8 @@ expect(cluster.domain).to be_present end + expect(clusters_without_domain.count).to eq(25) + project_auto_devops_without_domain.each do |project_auto_devops| cluster_project = Clusters::Project.find_by(project_id: project_auto_devops.project_id) cluster = Clusters::Cluster.find(cluster_project.cluster_id) @@ -74,10 +78,12 @@ def setup_cluster_projects_with_domain(quantity:, domain:) cluster_projects = cluster_projects_table.last(quantity) cluster_projects.each do |cluster_project| + specific_domain = "#{cluster_project.id}-#{domain}" if domain + project_auto_devops_table.create( project_id: cluster_project.project_id, enabled: true, - domain: domain + domain: specific_domain ) end end -- GitLab From 087af654bbae1e4a843029b33e1aab546f4d7d61 Mon Sep 17 00:00:00 2001 From: Mayra Cabrera Date: Thu, 31 Jan 2019 08:58:58 -0600 Subject: [PATCH 4/5] Addresses backend/db review comments - Fixes multiple typos on AutoDevops script - Add an alias to Clusters::Cluster#domain as base_domain, so it's more descriptive - Removes unnecessary memoization on qa specs - Changes migration to a post migration to deal better with traffic on big instances (like gitlab.com) --- app/controllers/clusters/clusters_controller.rb | 4 ++-- app/models/clusters/cluster.rb | 2 ++ app/models/project_auto_devops.rb | 4 +++- app/views/clusters/clusters/_form.html.haml | 8 ++++---- .../projects/settings/ci_cd/_autodevops_form.html.haml | 2 +- .../52363-ui-changes-to-cluster-and-ado-pages.yml | 2 +- ...0_migrate_auto_dev_ops_domain_to_cluster_domain.rb} | 0 db/schema.rb | 2 +- lib/gitlab/ci/templates/Auto-DevOps.gitlab-ci.yml | 6 +++--- qa/qa/resource/kubernetes_cluster.rb | 10 ++-------- spec/controllers/groups/clusters_controller_spec.rb | 2 +- spec/features/clusters/cluster_detail_page_spec.rb | 2 +- ...grate_auto_dev_ops_domain_to_cluster_domain_spec.rb | 2 +- 13 files changed, 22 insertions(+), 24 deletions(-) rename db/{migrate/20190129165720_migrate_auto_dev_ops_domain_to_cluster_domain.rb => post_migrate/20190204115450_migrate_auto_dev_ops_domain_to_cluster_domain.rb} (100%) diff --git a/app/controllers/clusters/clusters_controller.rb b/app/controllers/clusters/clusters_controller.rb index 483842fe456..3bd91b71d92 100644 --- a/app/controllers/clusters/clusters_controller.rb +++ b/app/controllers/clusters/clusters_controller.rb @@ -127,7 +127,7 @@ def update_params params.require(:cluster).permit( :enabled, :environment_scope, - :domain, + :base_domain, platform_kubernetes_attributes: [ :namespace ] @@ -137,7 +137,7 @@ def update_params :enabled, :name, :environment_scope, - :domain, + :base_domain, platform_kubernetes_attributes: [ :api_url, :token, diff --git a/app/models/clusters/cluster.rb b/app/models/clusters/cluster.rb index 2b677961df5..bf339c935cf 100644 --- a/app/models/clusters/cluster.rb +++ b/app/models/clusters/cluster.rb @@ -67,6 +67,8 @@ class Cluster < ActiveRecord::Base delegate :available?, to: :application_knative, prefix: true, allow_nil: true delegate :external_ip, to: :application_ingress, prefix: true, allow_nil: true + alias_attribute :base_domain, :domain + enum cluster_type: { instance_type: 1, group_type: 2, diff --git a/app/models/project_auto_devops.rb b/app/models/project_auto_devops.rb index d254ec158ca..b6c5c7c4c87 100644 --- a/app/models/project_auto_devops.rb +++ b/app/models/project_auto_devops.rb @@ -26,7 +26,9 @@ def has_domain? # From 11.8, AUTO_DEVOPS_DOMAIN has been replaced by KUBE_INGRESS_BASE_DOMAIN. # See Clusters::Cluster#predefined_variables and https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/24580 - # for more info. Support for AUTO_DEVOPS_DOMAIN support will be dropped on 12.0. + # for more info. + # Support for AUTO_DEVOPS_DOMAIN support will be dropped on 12.0 on + # https://gitlab.com/gitlab-org/gitlab-ce/issues/52363 def predefined_variables Gitlab::Ci::Variables::Collection.new.tap do |variables| if has_domain? diff --git a/app/views/clusters/clusters/_form.html.haml b/app/views/clusters/clusters/_form.html.haml index 068f14364ec..e0d3b7e1aec 100644 --- a/app/views/clusters/clusters/_form.html.haml +++ b/app/views/clusters/clusters/_form.html.haml @@ -20,7 +20,7 @@ .form-text.text-muted= s_("ClusterIntegration|Choose which of your environments will use this cluster.") - else = text_field_tag :environment_scope, '*', class: 'col-md-6 form-control disabled', placeholder: s_('ClusterIntegration|Environment scope'), disabled: true - - environment_scope_url = 'https://docs.gitlab.com/ee/user/project/clusters/#base-domain' + - environment_scope_url = help_page_path('user/project/clusters', anchor: 'base-domain') - environment_scope_start = ''.html_safe % { url: environment_scope_url } .form-text.text-muted %code * @@ -28,15 +28,15 @@ .form-group %h5= s_('ClusterIntegration|Base domain') - = field.text_field :domain, class: 'col-md-6 form-control js-select-on-focus' + = field.text_field :base_domain, class: 'col-md-6 form-control js-select-on-focus' .form-text.text-muted - if @cluster.application_ingress_external_ip.present? - - auto_devops_url = 'https://docs.gitlab.com/ee/topics/autodevops/' + - auto_devops_url = help_page_path('topics/autodevops/') - auto_devops_start = ''.html_safe % { url: auto_devops_url } = s_('ClusterIntegration|Specifying a domain will allow you to use Auto Review Apps and Auto Deploy stages for %{auto_devops_start}Auto DevOps%{auto_devops_end}. The domain should have a wildcard DNS configured to the Ingress IP Address below.').html_safe % { auto_devops_start: auto_devops_start, auto_devops_end: ''.html_safe } = s_('ClusterIntegration|Alternatively') %code #{@cluster.application_ingress_external_ip}.nip.io - - custom_domain_url = 'https://docs.gitlab.com/ee/user/project/clusters/#pointing-your-dns-at-the-cluster-ip' + - custom_domain_url = help_page_path('user/project/clusters/', anchor: 'pointing-your-dns-at-the-cluster-ip') - custom_domain_start = ''.html_safe % { url: custom_domain_url } = s_('ClusterIntegration| can be used instead of a custom domain. %{custom_domain_start}More information%{custom_domain_end}').html_safe % { custom_domain_start: custom_domain_start, custom_domain_end: ''.html_safe } - else diff --git a/app/views/projects/settings/ci_cd/_autodevops_form.html.haml b/app/views/projects/settings/ci_cd/_autodevops_form.html.haml index c2bbcf8fcaf..d905d015c22 100644 --- a/app/views/projects/settings/ci_cd/_autodevops_form.html.haml +++ b/app/views/projects/settings/ci_cd/_autodevops_form.html.haml @@ -22,7 +22,7 @@ = link_to _('More information'), help_page_path('topics/autodevops/index.md'), target: '_blank' .card-footer.js-extra-settings{ class: @project.auto_devops_enabled? || 'hidden' } %p.settings-message.text-center - - kubernetes_cluster_link = 'https://docs.gitlab.com/ee/user/project/clusters/' + - kubernetes_cluster_link = help_page_path('user/project/clusters/') - kubernetes_cluster_start = ''.html_safe % { url: kubernetes_cluster_link } = s_('CICD|You must add a %{kubernetes_cluster_start}Kubernetes cluster integration%{kubernetes_cluster_end} to this project with a domain in order for your deployment strategy to work correctly.').html_safe % { kubernetes_cluster_start: kubernetes_cluster_start, kubernetes_cluster_end: ''.html_safe } %label.prepend-top-10 diff --git a/changelogs/unreleased/52363-ui-changes-to-cluster-and-ado-pages.yml b/changelogs/unreleased/52363-ui-changes-to-cluster-and-ado-pages.yml index 25f01f95177..eb4851971fb 100644 --- a/changelogs/unreleased/52363-ui-changes-to-cluster-and-ado-pages.yml +++ b/changelogs/unreleased/52363-ui-changes-to-cluster-and-ado-pages.yml @@ -1,5 +1,5 @@ --- -title: Moves domain setting to cluster page +title: Moves domain setting from Auto DevOps to Cluster's page merge_request: 24580 author: type: added diff --git a/db/migrate/20190129165720_migrate_auto_dev_ops_domain_to_cluster_domain.rb b/db/post_migrate/20190204115450_migrate_auto_dev_ops_domain_to_cluster_domain.rb similarity index 100% rename from db/migrate/20190129165720_migrate_auto_dev_ops_domain_to_cluster_domain.rb rename to db/post_migrate/20190204115450_migrate_auto_dev_ops_domain_to_cluster_domain.rb diff --git a/db/schema.rb b/db/schema.rb index 4b6e4992056..68d1240dc73 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,7 +10,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 20190131122559) do +ActiveRecord::Schema.define(version: 20190204115450) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" diff --git a/lib/gitlab/ci/templates/Auto-DevOps.gitlab-ci.yml b/lib/gitlab/ci/templates/Auto-DevOps.gitlab-ci.yml index a0015c958fe..e369d26f22f 100644 --- a/lib/gitlab/ci/templates/Auto-DevOps.gitlab-ci.yml +++ b/lib/gitlab/ci/templates/Auto-DevOps.gitlab-ci.yml @@ -689,7 +689,7 @@ rollout 100%: --set application.database_url="$DATABASE_URL" \ --set application.secretName="$APPLICATION_SECRET_NAME" \ --set application.secretChecksum="$APPLICATION_SECRET_CHECKSUM" \ - --set service.commonName="le.$AUTO_DEVOPS_DOMAIN" \ + --set service.commonName="le.$KUBE_INGRESS_BASE_DOMAIN" \ --set service.url="$CI_ENVIRONMENT_URL" \ --set service.additionalHosts="$additional_hosts" \ --set replicaCount="$replicas" \ @@ -725,7 +725,7 @@ rollout 100%: --set application.database_url="$DATABASE_URL" \ --set application.secretName="$APPLICATION_SECRET_NAME" \ --set application.secretChecksum="$APPLICATION_SECRET_CHECKSUM" \ - --set service.commonName="le.$AUTO_DEVOPS_DOMAIN" \ + --set service.commonName="le.$KUBE_INGRESS_BASE_DOMAIN" \ --set service.url="$CI_ENVIRONMENT_URL" \ --set service.additionalHosts="$additional_hosts" \ --set replicaCount="$replicas" \ @@ -827,7 +827,7 @@ rollout 100%: # Function to ensure backwards compatibility with AUTO_DEVOPS_DOMAIN function ensure_kube_ingress_base_domain() { if [ -z ${KUBE_INGRESS_BASE_DOMAIN+x} ]; then - export KUBE_INGRESS_BASE_DOMAIN=$AUTO_DEVOPS_DOMAIN + export KUBE_INGRESS_BASE_DOMAIN=$AUTO_DEVOPS_DOMAIN fi } diff --git a/qa/qa/resource/kubernetes_cluster.rb b/qa/qa/resource/kubernetes_cluster.rb index 19c6dc8890d..986b31da528 100644 --- a/qa/qa/resource/kubernetes_cluster.rb +++ b/qa/qa/resource/kubernetes_cluster.rb @@ -9,11 +9,11 @@ class KubernetesCluster < Base :install_helm_tiller, :install_ingress, :install_prometheus, :install_runner, :domain attribute :ingress_ip do - ingress_ip_value + Page::Project::Operations::Kubernetes::Show.perform(&:ingress_ip) end attribute :domain do - "#{ingress_ip_value}.nip.io" + "#{ingress_ip}.nip.io" end def fabricate! @@ -56,12 +56,6 @@ def fabricate! end end end - - private - - def ingress_ip_value - @ingress_ip_value ||= Page::Project::Operations::Kubernetes::Show.perform(&:ingress_ip) - end end end end diff --git a/spec/controllers/groups/clusters_controller_spec.rb b/spec/controllers/groups/clusters_controller_spec.rb index d5a149a57df..360030102e0 100644 --- a/spec/controllers/groups/clusters_controller_spec.rb +++ b/spec/controllers/groups/clusters_controller_spec.rb @@ -436,7 +436,7 @@ def go(format: :html) cluster: { enabled: false, name: 'my-new-cluster-name', - domain: domain + base_domain: domain } } end diff --git a/spec/features/clusters/cluster_detail_page_spec.rb b/spec/features/clusters/cluster_detail_page_spec.rb index 844008f841a..e3c47fa4721 100644 --- a/spec/features/clusters/cluster_detail_page_spec.rb +++ b/spec/features/clusters/cluster_detail_page_spec.rb @@ -18,7 +18,7 @@ visit cluster_path within '#cluster-integration' do - fill_in('cluster_domain', with: 'test.com') + fill_in('cluster_base_domain', with: 'test.com') click_on 'Save changes' end diff --git a/spec/migrations/migrate_auto_dev_ops_domain_to_cluster_domain_spec.rb b/spec/migrations/migrate_auto_dev_ops_domain_to_cluster_domain_spec.rb index c7fd27588a5..2ffc0e65fee 100644 --- a/spec/migrations/migrate_auto_dev_ops_domain_to_cluster_domain_spec.rb +++ b/spec/migrations/migrate_auto_dev_ops_domain_to_cluster_domain_spec.rb @@ -1,7 +1,7 @@ # frozen_string_literal: true require 'spec_helper' -require Rails.root.join('db', 'migrate', '20190129165720_migrate_auto_dev_ops_domain_to_cluster_domain.rb') +require Rails.root.join('db', 'post_migrate', '20190204115450_migrate_auto_dev_ops_domain_to_cluster_domain.rb') describe MigrateAutoDevOpsDomainToClusterDomain, :migration do include MigrationHelpers::ClusterHelpers -- GitLab From d9af3752fcfa6e97bcec82515b0cbc1ab88285de Mon Sep 17 00:00:00 2001 From: Mayra Cabrera Date: Tue, 5 Feb 2019 13:11:33 -0600 Subject: [PATCH 5/5] Addresses UX and BE comments: - Changes help text on clusters form to make it more explicit. - Removes unnecessary warnings on auto devops form - Simplifies cluster methods logic --- app/helpers/auto_devops_helper.rb | 26 ------- app/models/clusters/cluster.rb | 28 +++++-- app/views/clusters/clusters/_form.html.haml | 17 ++-- .../settings/ci_cd/_autodevops_form.html.haml | 8 +- locale/gitlab.pot | 22 ++---- .../clusters/cluster_detail_page_spec.rb | 2 +- spec/helpers/auto_devops_helper_spec.rb | 35 --------- spec/models/clusters/cluster_spec.rb | 78 +++++++++++++++---- .../ci_cd/_autodevops_form.html.haml_spec.rb | 53 +------------ 9 files changed, 103 insertions(+), 166 deletions(-) diff --git a/app/helpers/auto_devops_helper.rb b/app/helpers/auto_devops_helper.rb index 8628c90dc51..67e7e475920 100644 --- a/app/helpers/auto_devops_helper.rb +++ b/app/helpers/auto_devops_helper.rb @@ -9,30 +9,4 @@ def show_auto_devops_callout?(project) !project.repository.gitlab_ci_yml && !project.ci_service end - - def auto_devops_warning_message(project) - if missing_auto_devops_service?(project) - params = { - kubernetes: link_to('Kubernetes cluster', project_clusters_path(project)) - } - - if missing_auto_devops_domain?(project) - _('Auto Review Apps and Auto Deploy need a domain name and a %{kubernetes} to work correctly.') % params - else - _('Auto Review Apps and Auto Deploy need a %{kubernetes} to work correctly.') % params - end - elsif missing_auto_devops_domain?(project) - _('Auto Review Apps and Auto Deploy need a domain name to work correctly.') - end - end - - private - - def missing_auto_devops_domain?(project) - !(project.auto_devops || project.build_auto_devops)&.has_domain? - end - - def missing_auto_devops_service?(project) - !project.deployment_platform&.active? - end end diff --git a/app/models/clusters/cluster.rb b/app/models/clusters/cluster.rb index bf339c935cf..f2f5b89e3bb 100644 --- a/app/models/clusters/cluster.rb +++ b/app/models/clusters/cluster.rb @@ -18,6 +18,7 @@ class Cluster < ActiveRecord::Base Applications::Knative.application_name => Applications::Knative }.freeze DEFAULT_ENVIRONMENT = '*'.freeze + KUBE_INGRESS_BASE_DOMAIN = 'KUBE_INGRESS_BASE_DOMAIN'.freeze belongs_to :user @@ -196,22 +197,39 @@ def allow_user_defined_namespace? project_type? end - def has_domain? - domain.present? || instance_domain.present? + def kube_ingress_domain + @kube_ingress_domain ||= domain.presence || instance_domain || legacy_auto_devops_domain end def predefined_variables Gitlab::Ci::Variables::Collection.new.tap do |variables| - break variables unless has_domain? + break variables unless kube_ingress_domain - variables.append(key: 'KUBE_INGRESS_BASE_DOMAIN', value: domain.presence || instance_domain) + variables.append(key: KUBE_INGRESS_BASE_DOMAIN, value: kube_ingress_domain) end end private def instance_domain - Gitlab::CurrentSettings.auto_devops_domain + @instance_domain ||= Gitlab::CurrentSettings.auto_devops_domain + end + + # To keep backward compatibility with AUTO_DEVOPS_DOMAIN + # environment variable, we need to ensure KUBE_INGRESS_BASE_DOMAIN + # is set if AUTO_DEVOPS_DOMAIN is set on any of the following options: + # ProjectAutoDevops#Domain, project variables or group variables, + # as the AUTO_DEVOPS_DOMAIN is needed for CI_ENVIRONMENT_URL + # + # This method should be removed on 12.0 + def legacy_auto_devops_domain + if project_type? + project&.auto_devops&.domain.presence || + project.variables.find_by(key: 'AUTO_DEVOPS_DOMAIN')&.value.presence || + project.group&.variables&.find_by(key: 'AUTO_DEVOPS_DOMAIN')&.value.presence + elsif group_type? + group.variables.find_by(key: 'AUTO_DEVOPS_DOMAIN')&.value.presence + end end def restrict_modification diff --git a/app/views/clusters/clusters/_form.html.haml b/app/views/clusters/clusters/_form.html.haml index e0d3b7e1aec..7acd9ce0562 100644 --- a/app/views/clusters/clusters/_form.html.haml +++ b/app/views/clusters/clusters/_form.html.haml @@ -20,7 +20,7 @@ .form-text.text-muted= s_("ClusterIntegration|Choose which of your environments will use this cluster.") - else = text_field_tag :environment_scope, '*', class: 'col-md-6 form-control disabled', placeholder: s_('ClusterIntegration|Environment scope'), disabled: true - - environment_scope_url = help_page_path('user/project/clusters', anchor: 'base-domain') + - environment_scope_url = help_page_path('user/project/clusters/index', anchor: 'base-domain') - environment_scope_start = ''.html_safe % { url: environment_scope_url } .form-text.text-muted %code * @@ -30,17 +30,16 @@ %h5= s_('ClusterIntegration|Base domain') = field.text_field :base_domain, class: 'col-md-6 form-control js-select-on-focus' .form-text.text-muted + - auto_devops_url = help_page_path('topics/autodevops/index') + - auto_devops_start = ''.html_safe % { url: auto_devops_url } + = s_('ClusterIntegration|Specifying a domain will allow you to use Auto Review Apps and Auto Deploy stages for %{auto_devops_start}Auto DevOps%{auto_devops_end}. The domain should have a wildcard DNS configured matching the domain.').html_safe % { auto_devops_start: auto_devops_start, auto_devops_end: ''.html_safe } - if @cluster.application_ingress_external_ip.present? - - auto_devops_url = help_page_path('topics/autodevops/') - - auto_devops_start = ''.html_safe % { url: auto_devops_url } - = s_('ClusterIntegration|Specifying a domain will allow you to use Auto Review Apps and Auto Deploy stages for %{auto_devops_start}Auto DevOps%{auto_devops_end}. The domain should have a wildcard DNS configured to the Ingress IP Address below.').html_safe % { auto_devops_start: auto_devops_start, auto_devops_end: ''.html_safe } = s_('ClusterIntegration|Alternatively') %code #{@cluster.application_ingress_external_ip}.nip.io - - custom_domain_url = help_page_path('user/project/clusters/', anchor: 'pointing-your-dns-at-the-cluster-ip') - - custom_domain_start = ''.html_safe % { url: custom_domain_url } - = s_('ClusterIntegration| can be used instead of a custom domain. %{custom_domain_start}More information%{custom_domain_end}').html_safe % { custom_domain_start: custom_domain_start, custom_domain_end: ''.html_safe } - - else - = s_('ClusterIntegration|Before setting a domain, you must first install Ingress on your cluster below.') + = s_('ClusterIntegration| can be used instead of a custom domain.') + - custom_domain_url = help_page_path('user/project/clusters/index', anchor: 'pointing-your-dns-at-the-cluster-ip') + - custom_domain_start = ''.html_safe % { url: custom_domain_url } + = s_('ClusterIntegration| %{custom_domain_start}More information%{custom_domain_end}.').html_safe % { custom_domain_start: custom_domain_start, custom_domain_end: ''.html_safe } - if can?(current_user, :update_cluster, @cluster) .form-group diff --git a/app/views/projects/settings/ci_cd/_autodevops_form.html.haml b/app/views/projects/settings/ci_cd/_autodevops_form.html.haml index d905d015c22..8c4d1c32ebe 100644 --- a/app/views/projects/settings/ci_cd/_autodevops_form.html.haml +++ b/app/views/projects/settings/ci_cd/_autodevops_form.html.haml @@ -4,10 +4,6 @@ = form_errors(@project) %fieldset.builds-feature.js-auto-devops-settings .form-group - - message = auto_devops_warning_message(@project) - - if message - %p.auto-devops-warning-message.settings-message.text-center - = message.html_safe = f.fields_for :auto_devops_attributes, @auto_devops do |form| .card.auto-devops-card .card-body @@ -22,13 +18,11 @@ = link_to _('More information'), help_page_path('topics/autodevops/index.md'), target: '_blank' .card-footer.js-extra-settings{ class: @project.auto_devops_enabled? || 'hidden' } %p.settings-message.text-center - - kubernetes_cluster_link = help_page_path('user/project/clusters/') + - kubernetes_cluster_link = help_page_path('user/project/clusters/index') - kubernetes_cluster_start = ''.html_safe % { url: kubernetes_cluster_link } = s_('CICD|You must add a %{kubernetes_cluster_start}Kubernetes cluster integration%{kubernetes_cluster_end} to this project with a domain in order for your deployment strategy to work correctly.').html_safe % { kubernetes_cluster_start: kubernetes_cluster_start, kubernetes_cluster_end: ''.html_safe } %label.prepend-top-10 %strong= s_('CICD|Deployment strategy') - %p.settings-message.text-center - = s_('CICD|Deployment strategy needs a domain name to work correctly.') .form-check = form.radio_button :deploy_strategy, 'continuous', class: 'form-check-input' = form.label :deploy_strategy_continuous, class: 'form-check-label' do diff --git a/locale/gitlab.pot b/locale/gitlab.pot index 8600e6fa394..d4b7f478b3f 100644 --- a/locale/gitlab.pot +++ b/locale/gitlab.pot @@ -846,15 +846,6 @@ msgstr "" msgid "Auto DevOps, runners and job artifacts" msgstr "" -msgid "Auto Review Apps and Auto Deploy need a %{kubernetes} to work correctly." -msgstr "" - -msgid "Auto Review Apps and Auto Deploy need a domain name and a %{kubernetes} to work correctly." -msgstr "" - -msgid "Auto Review Apps and Auto Deploy need a domain name to work correctly." -msgstr "" - msgid "Auto-cancel redundant, pending pipelines" msgstr "" @@ -1221,9 +1212,6 @@ msgstr "" msgid "CICD|Deployment strategy" msgstr "" -msgid "CICD|Deployment strategy needs a domain name to work correctly." -msgstr "" - msgid "CICD|Jobs" msgstr "" @@ -1506,7 +1494,10 @@ msgstr "" msgid "Closed (moved)" msgstr "" -msgid "ClusterIntegration| can be used instead of a custom domain. %{custom_domain_start}More information%{custom_domain_end}" +msgid "ClusterIntegration| %{custom_domain_start}More information%{custom_domain_end}." +msgstr "" + +msgid "ClusterIntegration| can be used instead of a custom domain." msgstr "" msgid "ClusterIntegration| is the default environment scope for this cluster. This means that all jobs, regardless of their environment, will use this cluster. %{environment_scope_start}More information%{environment_scope_end}" @@ -1566,9 +1557,6 @@ msgstr "" msgid "ClusterIntegration|Base domain" msgstr "" -msgid "ClusterIntegration|Before setting a domain, you must first install Ingress on your cluster below." -msgstr "" - msgid "ClusterIntegration|CA Certificate" msgstr "" @@ -1893,7 +1881,7 @@ msgstr "" msgid "ClusterIntegration|Something went wrong while installing %{title}" msgstr "" -msgid "ClusterIntegration|Specifying a domain will allow you to use Auto Review Apps and Auto Deploy stages for %{auto_devops_start}Auto DevOps%{auto_devops_end}. The domain should have a wildcard DNS configured to the Ingress IP Address below." +msgid "ClusterIntegration|Specifying a domain will allow you to use Auto Review Apps and Auto Deploy stages for %{auto_devops_start}Auto DevOps%{auto_devops_end}. The domain should have a wildcard DNS configured matching the domain." msgstr "" msgid "ClusterIntegration|The IP address is in the process of being assigned. Please check your Kubernetes cluster or Quotas on Google Kubernetes Engine if it takes a long time." diff --git a/spec/features/clusters/cluster_detail_page_spec.rb b/spec/features/clusters/cluster_detail_page_spec.rb index e3c47fa4721..0a9c4bcaf12 100644 --- a/spec/features/clusters/cluster_detail_page_spec.rb +++ b/spec/features/clusters/cluster_detail_page_spec.rb @@ -45,7 +45,7 @@ visit cluster_path within '#cluster-integration' do - expect(page).to have_content('Before setting a domain, you must first install Ingress on your cluster below.') + expect(page).not_to have_content('can be used instead of a custom domain.') end end end diff --git a/spec/helpers/auto_devops_helper_spec.rb b/spec/helpers/auto_devops_helper_spec.rb index 75c30dbfe48..223e562238d 100644 --- a/spec/helpers/auto_devops_helper_spec.rb +++ b/spec/helpers/auto_devops_helper_spec.rb @@ -90,39 +90,4 @@ it { is_expected.to eq(false) } end end - - describe '.auto_devops_warning_message' do - subject { helper.auto_devops_warning_message(project) } - - context 'when the service is missing' do - before do - allow(helper).to receive(:missing_auto_devops_service?).and_return(true) - end - - context 'when the domain is missing' do - before do - allow(helper).to receive(:missing_auto_devops_domain?).and_return(true) - end - - it { is_expected.to match(/Auto Review Apps and Auto Deploy need a domain name and a .* to work correctly./) } - end - - context 'when the domain is not missing' do - before do - allow(helper).to receive(:missing_auto_devops_domain?).and_return(false) - end - - it { is_expected.to match(/Auto Review Apps and Auto Deploy need a .* to work correctly./) } - end - end - - context 'when the domain is missing' do - before do - allow(helper).to receive(:missing_auto_devops_service?).and_return(false) - allow(helper).to receive(:missing_auto_devops_domain?).and_return(true) - end - - it { is_expected.to eq('Auto Review Apps and Auto Deploy need a domain name to work correctly.') } - end - end end diff --git a/spec/models/clusters/cluster_spec.rb b/spec/models/clusters/cluster_spec.rb index abef586d258..92ce2b0999a 100644 --- a/spec/models/clusters/cluster_spec.rb +++ b/spec/models/clusters/cluster_spec.rb @@ -516,29 +516,75 @@ end end - describe '#has_domain?' do - subject { cluster.has_domain? } - - context 'with domain set at instance level' do - let(:cluster) { create(:cluster, :provided_by_gcp) } - - before do - stub_application_setting(auto_devops_domain: 'global_domain.com') - end + describe '#kube_ingress_domain' do + let(:cluster) { create(:cluster, :provided_by_gcp) } - it { is_expected.to be_truthy } - end + subject { cluster.kube_ingress_domain } context 'with domain set in cluster' do let(:cluster) { create(:cluster, :provided_by_gcp, :with_domain) } - it { is_expected.to be_truthy } + it { is_expected.to eq(cluster.domain) } end - context 'when domain is not set at instance level nor in cluster' do - let(:cluster) { create(:cluster, :provided_by_gcp) } + context 'with no domain on cluster' do + context 'with a project cluster' do + let(:cluster) { create(:cluster, :project, :provided_by_gcp) } + let(:project) { cluster.project } + + context 'with domain set at instance level' do + before do + stub_application_setting(auto_devops_domain: 'global_domain.com') + + it { is_expected.to eq('global_domain.com') } + end + end + + context 'with domain set on ProjectAutoDevops' do + before do + auto_devops = project.build_auto_devops(domain: 'legacy-ado-domain.com') + auto_devops.save + end + + it { is_expected.to eq('legacy-ado-domain.com') } + end - it { is_expected.to be_falsy } + context 'with domain set as environment variable on project' do + before do + variable = project.variables.build(key: 'AUTO_DEVOPS_DOMAIN', value: 'project-ado-domain.com') + variable.save + end + + it { is_expected.to eq('project-ado-domain.com') } + end + + context 'with domain set as environment variable on the group project' do + let(:group) { create(:group) } + + before do + project.update(parent_id: group.id) + variable = group.variables.build(key: 'AUTO_DEVOPS_DOMAIN', value: 'group-ado-domain.com') + variable.save + end + + it { is_expected.to eq('group-ado-domain.com') } + end + end + + context 'with a group cluster' do + let(:cluster) { create(:cluster, :group, :provided_by_gcp) } + + context 'with domain set as environment variable for the group' do + let(:group) { cluster.group } + + before do + variable = group.variables.build(key: 'AUTO_DEVOPS_DOMAIN', value: 'group-ado-domain.com') + variable.save + end + + it { is_expected.to eq('group-ado-domain.com') } + end + end end end @@ -566,7 +612,7 @@ end context 'with no domain' do - let(:cluster) { create(:cluster) } + let(:cluster) { create(:cluster, :provided_by_gcp, :project) } it 'should return an empty array' do expect(subject.to_hash).to be_empty diff --git a/spec/views/projects/settings/ci_cd/_autodevops_form.html.haml_spec.rb b/spec/views/projects/settings/ci_cd/_autodevops_form.html.haml_spec.rb index cb1b9e6f5fb..2a2539c80b5 100644 --- a/spec/views/projects/settings/ci_cd/_autodevops_form.html.haml_spec.rb +++ b/spec/views/projects/settings/ci_cd/_autodevops_form.html.haml_spec.rb @@ -7,56 +7,9 @@ assign :project, project end - context 'when kubernetes is not active' do - context 'when auto devops domain is not defined' do - it 'shows warning message' do - render + it 'shows a warning message about Kubernetes cluster' do + render - expect(rendered).to have_css('.auto-devops-warning-message') - expect(rendered).to have_text('Auto Review Apps and Auto Deploy need a domain name and a') - expect(rendered).to have_link('Kubernetes cluster') - end - end - - context 'when auto devops domain is defined' do - before do - project.build_auto_devops(domain: 'example.com') - end - - it 'shows warning message' do - render - - expect(rendered).to have_css('.auto-devops-warning-message') - expect(rendered).to have_text('Auto Review Apps and Auto Deploy need a') - expect(rendered).to have_link('Kubernetes cluster') - end - end - end - - context 'when kubernetes is active' do - before do - create(:kubernetes_service, project: project) - end - - context 'when auto devops domain is not defined' do - it 'shows warning message' do - render - - expect(rendered).to have_css('.auto-devops-warning-message') - expect(rendered).to have_text('Auto Review Apps and Auto Deploy need a domain name to work correctly.') - end - end - - context 'when auto devops domain is defined' do - before do - project.build_auto_devops(domain: 'example.com') - end - - it 'does not show warning message' do - render - - expect(rendered).not_to have_css('.auto-devops-warning-message') - end - end + expect(rendered).to have_text('You must add a Kubernetes cluster integration to this project with a domain in order for your deployment strategy to work correctly.') end end -- GitLab