diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2020-05-04 03:09:50 +0000 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2020-05-04 03:09:50 +0000 |
commit | 21be9646a94e2c145897e25d9c521523d55e1614 (patch) | |
tree | 2873c5461d2222f9e51ba9cea9d2ed87d3f87e20 | |
parent | 933d8b6d85b56a2f0f9d8ffe54f0212422537b03 (diff) | |
download | gitlab-ce-21be9646a94e2c145897e25d9c521523d55e1614.tar.gz |
Add latest changes from gitlab-org/gitlab@master
-rw-r--r-- | app/models/clusters/applications/ingress.rb | 5 | ||||
-rw-r--r-- | app/models/clusters/cluster.rb | 1 | ||||
-rw-r--r-- | app/services/clusters/applications/ingress_modsecurity_usage_service.rb | 69 | ||||
-rw-r--r-- | changelogs/unreleased/32358-add-initial-stats-for-modsecurity-installations.yml | 5 | ||||
-rw-r--r-- | db/migrate/20200402115013_add_index_on_modsecurity_to_ingress.rb | 18 | ||||
-rw-r--r-- | db/migrate/20200402115623_add_index_on_successful_deployment_and_environment_id_to_deployments.rb | 18 | ||||
-rw-r--r-- | db/migrate/20200420141733_add_index_on_enabled_clusters.rb | 18 | ||||
-rw-r--r-- | db/structure.sql | 9 | ||||
-rw-r--r-- | doc/api/pipelines.md | 2 | ||||
-rw-r--r-- | doc/user/admin_area/settings/usage_statistics.md | 2 | ||||
-rw-r--r-- | lib/gitlab/database/batch_count.rb | 8 | ||||
-rw-r--r-- | lib/gitlab/usage_data.rb | 26 | ||||
-rw-r--r-- | spec/factories/clusters/applications/helm.rb | 18 | ||||
-rw-r--r-- | spec/lib/gitlab/database/batch_count_spec.rb | 8 | ||||
-rw-r--r-- | spec/lib/gitlab/usage_data_spec.rb | 138 | ||||
-rw-r--r-- | spec/services/clusters/applications/ingress_modsecurity_usage_service_spec.rb | 196 |
16 files changed, 261 insertions, 280 deletions
diff --git a/app/models/clusters/applications/ingress.rb b/app/models/clusters/applications/ingress.rb index d8f90e15c42..dd354198910 100644 --- a/app/models/clusters/applications/ingress.rb +++ b/app/models/clusters/applications/ingress.rb @@ -17,6 +17,7 @@ module Clusters include ::Clusters::Concerns::ApplicationVersion include ::Clusters::Concerns::ApplicationData include AfterCommitQueue + include UsageStatistics default_value_for :ingress_type, :nginx default_value_for :modsecurity_enabled, true @@ -29,6 +30,10 @@ module Clusters enum modsecurity_mode: { logging: 0, blocking: 1 } + scope :modsecurity_not_installed, -> { where(modsecurity_enabled: nil) } + scope :modsecurity_enabled, -> { where(modsecurity_enabled: true) } + scope :modsecurity_disabled, -> { where(modsecurity_enabled: false) } + FETCH_IP_ADDRESS_DELAY = 30.seconds state_machine :status do diff --git a/app/models/clusters/cluster.rb b/app/models/clusters/cluster.rb index 78dd876020b..b21f9137d59 100644 --- a/app/models/clusters/cluster.rb +++ b/app/models/clusters/cluster.rb @@ -35,6 +35,7 @@ module Clusters has_many :projects, through: :cluster_projects, class_name: '::Project' has_one :cluster_project, -> { order(id: :desc) }, class_name: 'Clusters::Project' has_many :deployment_clusters + has_many :deployments, inverse_of: :cluster has_many :cluster_groups, class_name: 'Clusters::Group' has_many :groups, through: :cluster_groups, class_name: '::Group' diff --git a/app/services/clusters/applications/ingress_modsecurity_usage_service.rb b/app/services/clusters/applications/ingress_modsecurity_usage_service.rb deleted file mode 100644 index 4aac8bb3cbd..00000000000 --- a/app/services/clusters/applications/ingress_modsecurity_usage_service.rb +++ /dev/null @@ -1,69 +0,0 @@ -# frozen_string_literal: true - -# rubocop: disable CodeReuse/ActiveRecord -module Clusters - module Applications - ## - # This service measures usage of the Modsecurity Web Application Firewall across the entire - # instance's deployed environments. - # - # The default configuration is`AUTO_DEVOPS_MODSECURITY_SEC_RULE_ENGINE=DetectionOnly` so we - # measure non-default values via definition of either ci_variables or ci_pipeline_variables. - # Since both these values are encrypted, we must decrypt and count them in memory. - # - # NOTE: this service is an approximation as it does not yet take into account `environment_scope` or `ci_group_variables`. - ## - class IngressModsecurityUsageService - ADO_MODSEC_KEY = "AUTO_DEVOPS_MODSECURITY_SEC_RULE_ENGINE" - - def initialize(blocking_count: 0, disabled_count: 0) - @blocking_count = blocking_count - @disabled_count = disabled_count - end - - def execute - conditions = -> { merge(::Environment.available).merge(::Deployment.success).where(key: ADO_MODSEC_KEY) } - - ci_pipeline_var_enabled = - ::Ci::PipelineVariable - .joins(pipeline: { environments: :last_visible_deployment }) - .merge(conditions) - .order('deployments.environment_id, deployments.id DESC') - - ci_var_enabled = - ::Ci::Variable - .joins(project: { environments: :last_visible_deployment }) - .merge(conditions) - .merge( - # Give priority to pipeline variables by excluding from dataset - ::Ci::Variable.joins(project: :environments).where.not( - environments: { id: ci_pipeline_var_enabled.select('DISTINCT ON (deployments.environment_id) deployments.environment_id') } - ) - ).select('DISTINCT ON (deployments.environment_id) ci_variables.*') - - sum_modsec_config_counts( - ci_pipeline_var_enabled.select('DISTINCT ON (deployments.environment_id) ci_pipeline_variables.*') - ) - sum_modsec_config_counts(ci_var_enabled) - - { - ingress_modsecurity_blocking: @blocking_count, - ingress_modsecurity_disabled: @disabled_count - } - end - - private - - # These are encrypted so we must decrypt and count in memory - def sum_modsec_config_counts(dataset) - dataset.each do |var| - case var.value - when "On" then @blocking_count += 1 - when "Off" then @disabled_count += 1 - # `else` could be default or any unsupported user input - end - end - end - end - end -end diff --git a/changelogs/unreleased/32358-add-initial-stats-for-modsecurity-installations.yml b/changelogs/unreleased/32358-add-initial-stats-for-modsecurity-installations.yml new file mode 100644 index 00000000000..cbb0098c718 --- /dev/null +++ b/changelogs/unreleased/32358-add-initial-stats-for-modsecurity-installations.yml @@ -0,0 +1,5 @@ +--- +title: Add indexes on ingress, enabled clusters and successful deployments +merge_request: 28331 +author: +type: performance diff --git a/db/migrate/20200402115013_add_index_on_modsecurity_to_ingress.rb b/db/migrate/20200402115013_add_index_on_modsecurity_to_ingress.rb new file mode 100644 index 00000000000..8bd2d957092 --- /dev/null +++ b/db/migrate/20200402115013_add_index_on_modsecurity_to_ingress.rb @@ -0,0 +1,18 @@ +# frozen_string_literal: true + +class AddIndexOnModsecurityToIngress < ActiveRecord::Migration[6.0] + include Gitlab::Database::MigrationHelpers + + DOWNTIME = false + INDEX_NAME = 'index_clusters_applications_ingress_on_modsecurity' + + disable_ddl_transaction! + + def up + add_concurrent_index :clusters_applications_ingress, [:modsecurity_enabled, :modsecurity_mode, :cluster_id], name: INDEX_NAME + end + + def down + remove_concurrent_index :clusters_applications_ingress, [:modsecurity_enabled, :modsecurity_mode, :cluster_id], name: INDEX_NAME + end +end diff --git a/db/migrate/20200402115623_add_index_on_successful_deployment_and_environment_id_to_deployments.rb b/db/migrate/20200402115623_add_index_on_successful_deployment_and_environment_id_to_deployments.rb new file mode 100644 index 00000000000..c86f7ad63f0 --- /dev/null +++ b/db/migrate/20200402115623_add_index_on_successful_deployment_and_environment_id_to_deployments.rb @@ -0,0 +1,18 @@ +# frozen_string_literal: true + +class AddIndexOnSuccessfulDeploymentAndEnvironmentIdToDeployments < ActiveRecord::Migration[6.0] + include Gitlab::Database::MigrationHelpers + + DOWNTIME = false + INDEX_NAME = 'index_successful_deployments_on_cluster_id_and_environment_id' + + disable_ddl_transaction! + + def up + add_concurrent_index :deployments, [:cluster_id, :environment_id], where: 'status = 2', name: INDEX_NAME + end + + def down + remove_concurrent_index :deployments, [:cluster_id, :environment_id], where: 'status = 2', name: INDEX_NAME + end +end diff --git a/db/migrate/20200420141733_add_index_on_enabled_clusters.rb b/db/migrate/20200420141733_add_index_on_enabled_clusters.rb new file mode 100644 index 00000000000..43f4b072c82 --- /dev/null +++ b/db/migrate/20200420141733_add_index_on_enabled_clusters.rb @@ -0,0 +1,18 @@ +# frozen_string_literal: true + +class AddIndexOnEnabledClusters < ActiveRecord::Migration[6.0] + include Gitlab::Database::MigrationHelpers + + DOWNTIME = false + INDEX_NAME = 'index_enabled_clusters_on_id' + + disable_ddl_transaction! + + def up + add_concurrent_index :clusters, [:id], where: 'enabled = true', name: INDEX_NAME + end + + def down + remove_concurrent_index :clusters, [:id], where: 'enabled = true', name: INDEX_NAME + end +end diff --git a/db/structure.sql b/db/structure.sql index c0a222b61df..11ceb670805 100644 --- a/db/structure.sql +++ b/db/structure.sql @@ -9289,6 +9289,8 @@ CREATE UNIQUE INDEX index_clusters_applications_helm_on_cluster_id ON public.clu CREATE UNIQUE INDEX index_clusters_applications_ingress_on_cluster_id ON public.clusters_applications_ingress USING btree (cluster_id); +CREATE INDEX index_clusters_applications_ingress_on_modsecurity ON public.clusters_applications_ingress USING btree (modsecurity_enabled, modsecurity_mode, cluster_id); + CREATE UNIQUE INDEX index_clusters_applications_jupyter_on_cluster_id ON public.clusters_applications_jupyter USING btree (cluster_id); CREATE INDEX index_clusters_applications_jupyter_on_oauth_application_id ON public.clusters_applications_jupyter USING btree (oauth_application_id); @@ -9421,6 +9423,8 @@ CREATE UNIQUE INDEX index_emails_on_email ON public.emails USING btree (email); CREATE INDEX index_emails_on_user_id ON public.emails USING btree (user_id); +CREATE INDEX index_enabled_clusters_on_id ON public.clusters USING btree (id) WHERE (enabled = true); + CREATE INDEX index_environments_on_auto_stop_at ON public.environments USING btree (auto_stop_at) WHERE (auto_stop_at IS NOT NULL); CREATE INDEX index_environments_on_name_varchar_pattern_ops ON public.environments USING btree (name varchar_pattern_ops); @@ -10525,6 +10529,8 @@ CREATE INDEX index_subscriptions_on_project_id ON public.subscriptions USING btr CREATE UNIQUE INDEX index_subscriptions_on_subscribable_and_user_id_and_project_id ON public.subscriptions USING btree (subscribable_id, subscribable_type, user_id, project_id); +CREATE INDEX index_successful_deployments_on_cluster_id_and_environment_id ON public.deployments USING btree (cluster_id, environment_id) WHERE (status = 2); + CREATE UNIQUE INDEX index_suggestions_on_note_id_and_relative_order ON public.suggestions USING btree (note_id, relative_order); CREATE UNIQUE INDEX index_system_note_metadata_on_description_version_id ON public.system_note_metadata USING btree (description_version_id) WHERE (description_version_id IS NOT NULL); @@ -13542,6 +13548,8 @@ COPY "schema_migrations" (version) FROM STDIN; 20200401095430 20200401211005 20200402001106 +20200402115013 +20200402115623 20200402123926 20200402124802 20200402135250 @@ -13607,6 +13615,7 @@ COPY "schema_migrations" (version) FROM STDIN; 20200420104303 20200420104323 20200420115948 +20200420141733 20200420162730 20200420172113 20200420172752 diff --git a/doc/api/pipelines.md b/doc/api/pipelines.md index 5b67df14ace..a4245ec02aa 100644 --- a/doc/api/pipelines.md +++ b/doc/api/pipelines.md @@ -225,7 +225,7 @@ Response: } ``` -## Cancel a pipelines jobs +## Cancel a pipeline's jobs > [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/5837) in GitLab 8.11 diff --git a/doc/user/admin_area/settings/usage_statistics.md b/doc/user/admin_area/settings/usage_statistics.md index 1f01a364514..f9a45fadf6d 100644 --- a/doc/user/admin_area/settings/usage_statistics.md +++ b/doc/user/admin_area/settings/usage_statistics.md @@ -304,8 +304,10 @@ but commented out to help encourage others to add to it in the future. --> |licenses_list_views|counts|| |user_preferences_group_overview_details|counts|| |user_preferences_group_overview_security_dashboard|counts|| +|ingress_modsecurity_logging|counts|| |ingress_modsecurity_blocking|counts|| |ingress_modsecurity_disabled|counts|| +|ingress_modsecurity_not_installed|counts|| |dependency_list_usages_total|counts|| |epics|counts|| |feature_flags|counts|| diff --git a/lib/gitlab/database/batch_count.rb b/lib/gitlab/database/batch_count.rb index 2359dceae48..ab069ce1da1 100644 --- a/lib/gitlab/database/batch_count.rb +++ b/lib/gitlab/database/batch_count.rb @@ -91,11 +91,17 @@ module Gitlab def batch_fetch(start, finish, mode) # rubocop:disable GitlabSecurity/PublicSend - @relation.select(@column).public_send(mode).where(@column => start..(finish - 1)).count + @relation.select(@column).public_send(mode).where(between_condition(start, finish)).count end private + def between_condition(start, finish) + return @column.between(start..(finish - 1)) if @column.is_a?(Arel::Attributes::Attribute) + + { @column => start..(finish - 1) } + end + def actual_start(start) start || @relation.minimum(@column) || 0 end diff --git a/lib/gitlab/usage_data.rb b/lib/gitlab/usage_data.rb index 68e70ecf8e1..f05825d2be1 100644 --- a/lib/gitlab/usage_data.rb +++ b/lib/gitlab/usage_data.rb @@ -273,7 +273,24 @@ module Gitlab end def ingress_modsecurity_usage - ::Clusters::Applications::IngressModsecurityUsageService.new.execute + ## + # This method measures usage of the Modsecurity Web Application Firewall across the entire + # instance's deployed environments. + # + # NOTE: this service is an approximation as it does not yet take into account if environment + # is enabled and only measures applications installed using GitLab Managed Apps (disregards + # CI-based managed apps). + # + # More details: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/28331#note_318621786 + ## + + column = ::Deployment.arel_table[:environment_id] + { + ingress_modsecurity_logging: distinct_count(successful_deployments_with_cluster(::Clusters::Applications::Ingress.modsecurity_enabled.logging), column), + ingress_modsecurity_blocking: distinct_count(successful_deployments_with_cluster(::Clusters::Applications::Ingress.modsecurity_enabled.blocking), column), + ingress_modsecurity_disabled: distinct_count(successful_deployments_with_cluster(::Clusters::Applications::Ingress.modsecurity_disabled), column), + ingress_modsecurity_not_installed: distinct_count(successful_deployments_with_cluster(::Clusters::Applications::Ingress.modsecurity_not_installed), column) + } end # rubocop: disable CodeReuse/ActiveRecord @@ -318,6 +335,13 @@ module Gitlab rescue ActiveRecord::StatementInvalid { projects_jira_server_active: -1, projects_jira_cloud_active: -1, projects_jira_active: -1 } end + + def successful_deployments_with_cluster(scope) + scope + .joins(cluster: :deployments) + .merge(Clusters::Cluster.enabled) + .merge(Deployment.success) + end # rubocop: enable CodeReuse/ActiveRecord def jira_import_usage diff --git a/spec/factories/clusters/applications/helm.rb b/spec/factories/clusters/applications/helm.rb index 0152b16c8ea..7e52c54d4f1 100644 --- a/spec/factories/clusters/applications/helm.rb +++ b/spec/factories/clusters/applications/helm.rb @@ -77,6 +77,24 @@ FactoryBot.define do trait :no_helm_installed do cluster factory: %i(cluster provided_by_gcp) end + + trait :modsecurity_blocking do + modsecurity_enabled { true } + modsecurity_mode { :blocking } + end + + trait :modsecurity_logging do + modsecurity_enabled { true } + modsecurity_mode { :logging } + end + + trait :modsecurity_disabled do + modsecurity_enabled { false } + end + + trait :modsecurity_not_installed do + modsecurity_enabled { nil } + end end factory :clusters_applications_cert_manager, class: 'Clusters::Applications::CertManager' do diff --git a/spec/lib/gitlab/database/batch_count_spec.rb b/spec/lib/gitlab/database/batch_count_spec.rb index 7be84b8f980..e7cb53f2dbd 100644 --- a/spec/lib/gitlab/database/batch_count_spec.rb +++ b/spec/lib/gitlab/database/batch_count_spec.rb @@ -35,6 +35,10 @@ describe Gitlab::Database::BatchCount do expect(described_class.batch_count(model, "#{model.table_name}.id")).to eq(5) end + it 'counts with Arel column' do + expect(described_class.batch_count(model, model.arel_table[:id])).to eq(5) + end + it 'counts table with batch_size 50K' do expect(described_class.batch_count(model, batch_size: 50_000)).to eq(5) end @@ -98,6 +102,10 @@ describe Gitlab::Database::BatchCount do expect(described_class.batch_distinct_count(model, "#{model.table_name}.#{column}")).to eq(2) end + it 'counts with Arel column' do + expect(described_class.batch_distinct_count(model, model.arel_table[column])).to eq(2) + end + it 'counts with :column field with batch_size of 50K' do expect(described_class.batch_distinct_count(model, column, batch_size: 50_000)).to eq(2) end diff --git a/spec/lib/gitlab/usage_data_spec.rb b/spec/lib/gitlab/usage_data_spec.rb index 858ee360d8a..ddbc4240f10 100644 --- a/spec/lib/gitlab/usage_data_spec.rb +++ b/spec/lib/gitlab/usage_data_spec.rb @@ -319,18 +319,132 @@ describe Gitlab::UsageData, :aggregate_failures do describe '#ingress_modsecurity_usage' do subject { described_class.ingress_modsecurity_usage } - it 'gathers variable data' do - allow_any_instance_of( - ::Clusters::Applications::IngressModsecurityUsageService - ).to receive(:execute).and_return( - { - ingress_modsecurity_blocking: 1, - ingress_modsecurity_disabled: 2 - } - ) - - expect(subject[:ingress_modsecurity_blocking]).to eq(1) - expect(subject[:ingress_modsecurity_disabled]).to eq(2) + let(:environment) { create(:environment) } + let(:project) { environment.project } + let(:environment_scope) { '*' } + let(:deployment) { create(:deployment, :success, environment: environment, project: project, cluster: cluster) } + let(:cluster) { create(:cluster, environment_scope: environment_scope, projects: [project]) } + let(:ingress_mode) { :modsecurity_blocking } + let!(:ingress) { create(:clusters_applications_ingress, ingress_mode, cluster: cluster) } + + context 'when cluster is disabled' do + let(:cluster) { create(:cluster, :disabled, projects: [project]) } + + it 'gathers ingress data' do + expect(subject[:ingress_modsecurity_logging]).to eq(0) + expect(subject[:ingress_modsecurity_blocking]).to eq(0) + expect(subject[:ingress_modsecurity_disabled]).to eq(0) + expect(subject[:ingress_modsecurity_not_installed]).to eq(0) + end + end + + context 'when deployment is unsuccessful' do + let!(:deployment) { create(:deployment, :failed, environment: environment, project: project, cluster: cluster) } + + it 'gathers ingress data' do + expect(subject[:ingress_modsecurity_logging]).to eq(0) + expect(subject[:ingress_modsecurity_blocking]).to eq(0) + expect(subject[:ingress_modsecurity_disabled]).to eq(0) + expect(subject[:ingress_modsecurity_not_installed]).to eq(0) + end + end + + context 'when deployment is successful' do + let!(:deployment) { create(:deployment, :success, environment: environment, project: project, cluster: cluster) } + + context 'when modsecurity is in blocking mode' do + it 'gathers ingress data' do + expect(subject[:ingress_modsecurity_logging]).to eq(0) + expect(subject[:ingress_modsecurity_blocking]).to eq(1) + expect(subject[:ingress_modsecurity_disabled]).to eq(0) + expect(subject[:ingress_modsecurity_not_installed]).to eq(0) + end + end + + context 'when modsecurity is in logging mode' do + let(:ingress_mode) { :modsecurity_logging } + + it 'gathers ingress data' do + expect(subject[:ingress_modsecurity_logging]).to eq(1) + expect(subject[:ingress_modsecurity_blocking]).to eq(0) + expect(subject[:ingress_modsecurity_disabled]).to eq(0) + expect(subject[:ingress_modsecurity_not_installed]).to eq(0) + end + end + + context 'when modsecurity is disabled' do + let(:ingress_mode) { :modsecurity_disabled } + + it 'gathers ingress data' do + expect(subject[:ingress_modsecurity_logging]).to eq(0) + expect(subject[:ingress_modsecurity_blocking]).to eq(0) + expect(subject[:ingress_modsecurity_disabled]).to eq(1) + expect(subject[:ingress_modsecurity_not_installed]).to eq(0) + end + end + + context 'when modsecurity is not installed' do + let(:ingress_mode) { :modsecurity_not_installed } + + it 'gathers ingress data' do + expect(subject[:ingress_modsecurity_logging]).to eq(0) + expect(subject[:ingress_modsecurity_blocking]).to eq(0) + expect(subject[:ingress_modsecurity_disabled]).to eq(0) + expect(subject[:ingress_modsecurity_not_installed]).to eq(1) + end + end + + context 'with multiple projects' do + let(:environment_2) { create(:environment) } + let(:project_2) { environment_2.project } + let(:cluster_2) { create(:cluster, environment_scope: environment_scope, projects: [project_2]) } + let!(:ingress_2) { create(:clusters_applications_ingress, :modsecurity_logging, cluster: cluster_2) } + let!(:deployment_2) { create(:deployment, :success, environment: environment_2, project: project_2, cluster: cluster_2) } + + it 'gathers non-duplicated ingress data' do + expect(subject[:ingress_modsecurity_logging]).to eq(1) + expect(subject[:ingress_modsecurity_blocking]).to eq(1) + expect(subject[:ingress_modsecurity_disabled]).to eq(0) + expect(subject[:ingress_modsecurity_not_installed]).to eq(0) + end + end + + context 'with multiple deployments' do + let!(:deployment_2) { create(:deployment, :success, environment: environment, project: project, cluster: cluster) } + + it 'gathers non-duplicated ingress data' do + expect(subject[:ingress_modsecurity_logging]).to eq(0) + expect(subject[:ingress_modsecurity_blocking]).to eq(1) + expect(subject[:ingress_modsecurity_disabled]).to eq(0) + expect(subject[:ingress_modsecurity_not_installed]).to eq(0) + end + end + + context 'with multiple projects' do + let(:environment_2) { create(:environment) } + let(:project_2) { environment_2.project } + let!(:deployment_2) { create(:deployment, :success, environment: environment_2, project: project_2, cluster: cluster) } + let(:cluster) { create(:cluster, environment_scope: environment_scope, projects: [project, project_2]) } + + it 'gathers ingress data' do + expect(subject[:ingress_modsecurity_logging]).to eq(0) + expect(subject[:ingress_modsecurity_blocking]).to eq(2) + expect(subject[:ingress_modsecurity_disabled]).to eq(0) + expect(subject[:ingress_modsecurity_not_installed]).to eq(0) + end + end + + context 'with multiple environments' do + let!(:environment_2) { create(:environment, project: project) } + let!(:deployment_2) { create(:deployment, :success, environment: environment_2, project: project, cluster: cluster) } + + it 'gathers ingress data' do + expect(subject[:ingress_modsecurity_logging]).to eq(0) + expect(subject[:ingress_modsecurity_blocking]).to eq(2) + expect(subject[:ingress_modsecurity_disabled]).to eq(0) + expect(subject[:ingress_modsecurity_not_installed]).to eq(0) + end + end end end diff --git a/spec/services/clusters/applications/ingress_modsecurity_usage_service_spec.rb b/spec/services/clusters/applications/ingress_modsecurity_usage_service_spec.rb deleted file mode 100644 index d456284f76a..00000000000 --- a/spec/services/clusters/applications/ingress_modsecurity_usage_service_spec.rb +++ /dev/null @@ -1,196 +0,0 @@ -# frozen_string_literal: true - -require 'spec_helper' - -describe Clusters::Applications::IngressModsecurityUsageService do - describe '#execute' do - ADO_MODSEC_KEY = Clusters::Applications::IngressModsecurityUsageService::ADO_MODSEC_KEY - - let(:project_with_ci_var) { create(:environment).project } - let(:project_with_pipeline_var) { create(:environment).project } - - subject { described_class.new.execute } - - context 'with multiple projects' do - let(:pipeline1) { create(:ci_pipeline, :with_job, project: project_with_pipeline_var) } - let(:pipeline2) { create(:ci_pipeline, :with_job, project: project_with_ci_var) } - - let!(:deployment_with_pipeline_var) do - create( - :deployment, - :success, - environment: project_with_pipeline_var.environments.first, - project: project_with_pipeline_var, - deployable: pipeline1.builds.last - ) - end - let!(:deployment_with_project_var) do - create( - :deployment, - :success, - environment: project_with_ci_var.environments.first, - project: project_with_ci_var, - deployable: pipeline2.builds.last - ) - end - - context 'mixed data' do - let!(:ci_variable) { create(:ci_variable, project: project_with_ci_var, key: ADO_MODSEC_KEY, value: "On") } - let!(:pipeline_variable) { create(:ci_pipeline_variable, pipeline: pipeline1, key: ADO_MODSEC_KEY, value: "Off") } - - it 'gathers variable data' do - expect(subject[:ingress_modsecurity_blocking]).to eq(1) - expect(subject[:ingress_modsecurity_disabled]).to eq(1) - end - end - - context 'blocking' do - let(:modsec_values) { { key: ADO_MODSEC_KEY, value: "On" } } - - let!(:ci_variable) { create(:ci_variable, project: project_with_ci_var, **modsec_values) } - let!(:pipeline_variable) { create(:ci_pipeline_variable, pipeline: pipeline1, **modsec_values) } - - it 'gathers variable data' do - expect(subject[:ingress_modsecurity_blocking]).to eq(2) - expect(subject[:ingress_modsecurity_disabled]).to eq(0) - end - end - - context 'disabled' do - let(:modsec_values) { { key: ADO_MODSEC_KEY, value: "Off" } } - - let!(:ci_variable) { create(:ci_variable, project: project_with_ci_var, **modsec_values) } - let!(:pipeline_variable) { create(:ci_pipeline_variable, pipeline: pipeline1, **modsec_values) } - - it 'gathers variable data' do - expect(subject[:ingress_modsecurity_blocking]).to eq(0) - expect(subject[:ingress_modsecurity_disabled]).to eq(2) - end - end - end - - context 'when set as both ci and pipeline variables' do - let(:modsec_values) { { key: ADO_MODSEC_KEY, value: "Off" } } - - let(:pipeline) { create(:ci_pipeline, :with_job, project: project_with_ci_var) } - let!(:deployment) do - create( - :deployment, - :success, - environment: project_with_ci_var.environments.first, - project: project_with_ci_var, - deployable: pipeline.builds.last - ) - end - - let!(:ci_variable) { create(:ci_variable, project: project_with_ci_var, **modsec_values) } - let!(:pipeline_variable) { create(:ci_pipeline_variable, pipeline: pipeline, **modsec_values) } - - it 'wont double-count projects' do - expect(subject[:ingress_modsecurity_blocking]).to eq(0) - expect(subject[:ingress_modsecurity_disabled]).to eq(1) - end - - it 'gives precedence to pipeline variable' do - pipeline_variable.update(value: "On") - - expect(subject[:ingress_modsecurity_blocking]).to eq(1) - expect(subject[:ingress_modsecurity_disabled]).to eq(0) - end - end - - context 'when a project has multiple environments' do - let(:modsec_values) { { key: ADO_MODSEC_KEY, value: "On" } } - - let!(:env1) { project_with_pipeline_var.environments.first } - let!(:env2) { create(:environment, project: project_with_pipeline_var) } - - let!(:pipeline_with_2_deployments) do - create(:ci_pipeline, :with_job, project: project_with_ci_var).tap do |pip| - pip.builds << build(:ci_build, pipeline: pip, project: project_with_pipeline_var) - end - end - - let!(:deployment1) do - create( - :deployment, - :success, - environment: env1, - project: project_with_pipeline_var, - deployable: pipeline_with_2_deployments.builds.last - ) - end - let!(:deployment2) do - create( - :deployment, - :success, - environment: env2, - project: project_with_pipeline_var, - deployable: pipeline_with_2_deployments.builds.last - ) - end - - context 'when set as ci variable' do - let!(:ci_variable) { create(:ci_variable, project: project_with_pipeline_var, **modsec_values) } - - it 'gathers variable data' do - expect(subject[:ingress_modsecurity_blocking]).to eq(2) - expect(subject[:ingress_modsecurity_disabled]).to eq(0) - end - end - - context 'when set as pipeline variable' do - let!(:pipeline_variable) { create(:ci_pipeline_variable, pipeline: pipeline_with_2_deployments, **modsec_values) } - - it 'gathers variable data' do - expect(subject[:ingress_modsecurity_blocking]).to eq(2) - expect(subject[:ingress_modsecurity_disabled]).to eq(0) - end - end - end - - context 'when an environment has multiple deployments' do - let!(:env) { project_with_pipeline_var.environments.first } - - let!(:pipeline_first) do - create(:ci_pipeline, :with_job, project: project_with_pipeline_var).tap do |pip| - pip.builds << build(:ci_build, pipeline: pip, project: project_with_pipeline_var) - end - end - let!(:pipeline_last) do - create(:ci_pipeline, :with_job, project: project_with_pipeline_var).tap do |pip| - pip.builds << build(:ci_build, pipeline: pip, project: project_with_pipeline_var) - end - end - - let!(:deployment_first) do - create( - :deployment, - :success, - environment: env, - project: project_with_pipeline_var, - deployable: pipeline_first.builds.last - ) - end - let!(:deployment_last) do - create( - :deployment, - :success, - environment: env, - project: project_with_pipeline_var, - deployable: pipeline_last.builds.last - ) - end - - context 'when set as pipeline variable' do - let!(:first_pipeline_variable) { create(:ci_pipeline_variable, pipeline: pipeline_first, key: ADO_MODSEC_KEY, value: "On") } - let!(:last_pipeline_variable) { create(:ci_pipeline_variable, pipeline: pipeline_last, key: ADO_MODSEC_KEY, value: "Off") } - - it 'gives precedence to latest deployment' do - expect(subject[:ingress_modsecurity_blocking]).to eq(0) - expect(subject[:ingress_modsecurity_disabled]).to eq(1) - end - end - end - end -end |