Commit 9690e747 authored by Alper Akgun's avatar Alper Akgun Committed by Bob Van Landuyt

Remove feature flag for usage ping batch counter

- Was default on (true) on all environments
- Was well tested past 3 months not to cause any problems
parent 9149d54a
...@@ -283,443 +283,435 @@ RSpec.describe Gitlab::UsageData do ...@@ -283,443 +283,435 @@ RSpec.describe Gitlab::UsageData do
end end
end end
[true, false].each do |usage_ping_batch_counter_on| describe '.uncached_data' do
describe "when the feature flag usage_ping_batch_counter is set to #{usage_ping_batch_counter_on}" do describe '.usage_activity_by_stage' do
before do it 'includes usage_activity_by_stage data' do
stub_feature_flags(usage_ping_batch_counter: usage_ping_batch_counter_on) expect(described_class.uncached_data).to include(:usage_activity_by_stage)
expect(described_class.uncached_data).to include(:usage_activity_by_stage_monthly)
end end
describe '.uncached_data' do context 'for configure' do
describe '.usage_activity_by_stage' do it 'includes accurate usage_activity_by_stage data' do
it 'includes usage_activity_by_stage data' do for_defined_days_back do
expect(described_class.uncached_data).to include(:usage_activity_by_stage) user = create(:user)
expect(described_class.uncached_data).to include(:usage_activity_by_stage_monthly) cluster = create(:cluster, user: user)
project = create(:project, creator: user)
create(:clusters_applications_cert_manager, :installed, cluster: cluster)
create(:clusters_applications_helm, :installed, cluster: cluster)
create(:clusters_applications_ingress, :installed, cluster: cluster)
create(:clusters_applications_knative, :installed, cluster: cluster)
create(:cluster, :disabled, user: user)
create(:cluster_provider_gcp, :created)
create(:cluster_provider_aws, :created)
create(:cluster_platform_kubernetes)
create(:cluster, :group, :disabled, user: user)
create(:cluster, :group, user: user)
create(:cluster, :instance, :disabled, :production_environment)
create(:cluster, :instance, :production_environment)
create(:cluster, :management_project)
create(:slack_service, project: project)
create(:slack_slash_commands_service, project: project)
create(:prometheus_service, project: project)
end end
context 'for configure' do expect(described_class.uncached_data[:usage_activity_by_stage][:configure]).to eq(
it 'includes accurate usage_activity_by_stage data' do clusters_applications_cert_managers: 2,
for_defined_days_back do clusters_applications_helm: 2,
user = create(:user) clusters_applications_ingress: 2,
cluster = create(:cluster, user: user) clusters_applications_knative: 2,
project = create(:project, creator: user) clusters_management_project: 2,
create(:clusters_applications_cert_manager, :installed, cluster: cluster) clusters_disabled: 4,
create(:clusters_applications_helm, :installed, cluster: cluster) clusters_enabled: 12,
create(:clusters_applications_ingress, :installed, cluster: cluster) clusters_platforms_gke: 2,
create(:clusters_applications_knative, :installed, cluster: cluster) clusters_platforms_eks: 2,
create(:cluster, :disabled, user: user) clusters_platforms_user: 2,
create(:cluster_provider_gcp, :created) instance_clusters_disabled: 2,
create(:cluster_provider_aws, :created) instance_clusters_enabled: 2,
create(:cluster_platform_kubernetes) group_clusters_disabled: 2,
create(:cluster, :group, :disabled, user: user) group_clusters_enabled: 2,
create(:cluster, :group, user: user) project_clusters_disabled: 2,
create(:cluster, :instance, :disabled, :production_environment) project_clusters_enabled: 10,
create(:cluster, :instance, :production_environment) projects_slack_notifications_active: 2,
create(:cluster, :management_project) projects_slack_slash_active: 2,
create(:slack_service, project: project) projects_with_prometheus_alerts: 2
create(:slack_slash_commands_service, project: project) )
create(:prometheus_service, project: project) expect(described_class.uncached_data[:usage_activity_by_stage_monthly][:configure]).to eq(
end clusters_applications_cert_managers: 1,
clusters_applications_helm: 1,
expect(described_class.uncached_data[:usage_activity_by_stage][:configure]).to eq( clusters_applications_ingress: 1,
clusters_applications_cert_managers: 2, clusters_applications_knative: 1,
clusters_applications_helm: 2, clusters_management_project: 1,
clusters_applications_ingress: 2, clusters_disabled: 2,
clusters_applications_knative: 2, clusters_enabled: 6,
clusters_management_project: 2, clusters_platforms_gke: 1,
clusters_disabled: 4, clusters_platforms_eks: 1,
clusters_enabled: 12, clusters_platforms_user: 1,
clusters_platforms_gke: 2, instance_clusters_disabled: 1,
clusters_platforms_eks: 2, instance_clusters_enabled: 1,
clusters_platforms_user: 2, group_clusters_disabled: 1,
instance_clusters_disabled: 2, group_clusters_enabled: 1,
instance_clusters_enabled: 2, project_clusters_disabled: 1,
group_clusters_disabled: 2, project_clusters_enabled: 5,
group_clusters_enabled: 2, projects_slack_notifications_active: 1,
project_clusters_disabled: 2, projects_slack_slash_active: 1,
project_clusters_enabled: 10, projects_with_prometheus_alerts: 1
projects_slack_notifications_active: 2, )
projects_slack_slash_active: 2, end
projects_with_prometheus_alerts: 2 end
)
expect(described_class.uncached_data[:usage_activity_by_stage_monthly][:configure]).to eq( context 'for create' do
clusters_applications_cert_managers: 1, it 'includes accurate usage_activity_by_stage data' do
clusters_applications_helm: 1, for_defined_days_back do
clusters_applications_ingress: 1, user = create(:user)
clusters_applications_knative: 1, project = create(:project, :repository_private, :github_imported,
clusters_management_project: 1, :test_repo, :remote_mirror, creator: user)
clusters_disabled: 2, merge_request = create(:merge_request, source_project: project)
clusters_enabled: 6, create(:deploy_key, user: user)
clusters_platforms_gke: 1, create(:key, user: user)
clusters_platforms_eks: 1, create(:project, creator: user)
clusters_platforms_user: 1, create(:protected_branch, project: project)
instance_clusters_disabled: 1, create(:remote_mirror, project: project)
instance_clusters_enabled: 1, create(:snippet, author: user)
group_clusters_disabled: 1, create(:suggestion, note: create(:note, project: project))
group_clusters_enabled: 1, create(:code_owner_rule, merge_request: merge_request, approvals_required: 3)
project_clusters_disabled: 1, create(:code_owner_rule, merge_request: merge_request, approvals_required: 7)
project_clusters_enabled: 5, create_list(:code_owner_rule, 3, approvals_required: 2)
projects_slack_notifications_active: 1, create_list(:code_owner_rule, 2)
projects_slack_slash_active: 1,
projects_with_prometheus_alerts: 1
)
end
end end
context 'for create' do expect(described_class.uncached_data[:usage_activity_by_stage][:create]).to eq(
it 'includes accurate usage_activity_by_stage data' do deploy_keys: 2,
for_defined_days_back do keys: 2,
user = create(:user) merge_requests: 12,
project = create(:project, :repository_private, :github_imported, projects_enforcing_code_owner_approval: 0,
:test_repo, :remote_mirror, creator: user) merge_requests_with_optional_codeowners: 4,
merge_request = create(:merge_request, source_project: project) merge_requests_with_required_codeowners: 8,
create(:deploy_key, user: user) projects_imported_from_github: 2,
create(:key, user: user) projects_with_repositories_enabled: 12,
create(:project, creator: user) protected_branches: 2,
create(:protected_branch, project: project) remote_mirrors: 2,
create(:remote_mirror, project: project) snippets: 2,
create(:snippet, author: user) suggestions: 2
create(:suggestion, note: create(:note, project: project)) )
create(:code_owner_rule, merge_request: merge_request, approvals_required: 3) expect(described_class.uncached_data[:usage_activity_by_stage_monthly][:create]).to eq(
create(:code_owner_rule, merge_request: merge_request, approvals_required: 7) deploy_keys: 1,
create_list(:code_owner_rule, 3, approvals_required: 2) keys: 1,
create_list(:code_owner_rule, 2) merge_requests: 6,
end projects_enforcing_code_owner_approval: 0,
merge_requests_with_optional_codeowners: 2,
expect(described_class.uncached_data[:usage_activity_by_stage][:create]).to eq( merge_requests_with_required_codeowners: 4,
deploy_keys: 2, projects_imported_from_github: 1,
keys: 2, projects_with_repositories_enabled: 6,
merge_requests: 12, protected_branches: 1,
projects_enforcing_code_owner_approval: 0, remote_mirrors: 1,
merge_requests_with_optional_codeowners: 4, snippets: 1,
merge_requests_with_required_codeowners: 8, suggestions: 1
projects_imported_from_github: 2, )
projects_with_repositories_enabled: 12, end
protected_branches: 2, end
remote_mirrors: 2,
snippets: 2, context 'for manage' do
suggestions: 2 it 'includes accurate usage_activity_by_stage data' do
) stub_config(
expect(described_class.uncached_data[:usage_activity_by_stage_monthly][:create]).to eq( ldap:
deploy_keys: 1, { enabled: true, servers: ldap_server_config },
keys: 1, omniauth:
merge_requests: 6, { providers: omniauth_providers }
projects_enforcing_code_owner_approval: 0, )
merge_requests_with_optional_codeowners: 2,
merge_requests_with_required_codeowners: 4, for_defined_days_back do
projects_imported_from_github: 1, user = create(:user)
projects_with_repositories_enabled: 6, create(:event, author: user)
protected_branches: 1, create(:group_member, user: user)
remote_mirrors: 1, create(:key, type: 'LDAPKey', user: user)
snippets: 1, create(:group_member, ldap: true, user: user)
suggestions: 1 create(:cycle_analytics_group_stage)
) create(:compliance_framework_project_setting)
end
end end
context 'for manage' do expect(described_class.uncached_data[:usage_activity_by_stage][:manage]).to eq(
it 'includes accurate usage_activity_by_stage data' do events: 2,
stub_config( groups: 2,
ldap: ldap_keys: 2,
{ enabled: true, servers: ldap_server_config }, ldap_users: 2,
omniauth: users_created: 8,
{ providers: omniauth_providers } value_stream_management_customized_group_stages: 2,
) projects_with_compliance_framework: 2,
ldap_servers: 2,
for_defined_days_back do ldap_group_sync_enabled: true,
user = create(:user) ldap_admin_sync_enabled: true,
create(:event, author: user) omniauth_providers: ['google_oauth2'],
create(:group_member, user: user) group_saml_enabled: true
create(:key, type: 'LDAPKey', user: user) )
create(:group_member, ldap: true, user: user) expect(described_class.uncached_data[:usage_activity_by_stage_monthly][:manage]).to eq(
create(:cycle_analytics_group_stage) events: 1,
create(:compliance_framework_project_setting) groups: 1,
end ldap_keys: 1,
ldap_users: 1,
expect(described_class.uncached_data[:usage_activity_by_stage][:manage]).to eq( users_created: 5,
events: 2, value_stream_management_customized_group_stages: 2,
groups: 2, projects_with_compliance_framework: 2,
ldap_keys: 2, ldap_servers: 2,
ldap_users: 2, ldap_group_sync_enabled: true,
users_created: 8, ldap_admin_sync_enabled: true,
value_stream_management_customized_group_stages: 2, omniauth_providers: ['google_oauth2'],
projects_with_compliance_framework: 2, group_saml_enabled: true
ldap_servers: 2, )
ldap_group_sync_enabled: true, end
ldap_admin_sync_enabled: true,
omniauth_providers: ['google_oauth2'], def omniauth_providers
group_saml_enabled: true [
) OpenStruct.new(name: 'google_oauth2'),
expect(described_class.uncached_data[:usage_activity_by_stage_monthly][:manage]).to eq( OpenStruct.new(name: 'ldapmain'),
events: 1, OpenStruct.new(name: 'group_saml')
groups: 1, ]
ldap_keys: 1, end
ldap_users: 1,
users_created: 5, def ldap_server_config
value_stream_management_customized_group_stages: 2, {
projects_with_compliance_framework: 2, 'main' =>
ldap_servers: 2, {
ldap_group_sync_enabled: true, 'provider_name' => 'ldapmain',
ldap_admin_sync_enabled: true, 'group_base' => 'ou=groups',
omniauth_providers: ['google_oauth2'], 'admin_group' => 'my_group'
group_saml_enabled: true },
) 'secondary' =>
end
def omniauth_providers
[
OpenStruct.new(name: 'google_oauth2'),
OpenStruct.new(name: 'ldapmain'),
OpenStruct.new(name: 'group_saml')
]
end
def ldap_server_config
{ {
'main' => 'provider_name' => 'ldapsecondary',
{ 'group_base' => nil,
'provider_name' => 'ldapmain', 'admin_group' => nil
'group_base' => 'ou=groups',
'admin_group' => 'my_group'
},
'secondary' =>
{
'provider_name' => 'ldapsecondary',
'group_base' => nil,
'admin_group' => nil
}
} }
end }
end
end
context 'for monitor' do
it 'includes accurate usage_activity_by_stage data' do
for_defined_days_back do
user = create(:user, dashboard: 'operations')
cluster = create(:cluster, user: user)
project = create(:project, creator: user)
create(:clusters_applications_prometheus, :installed, cluster: cluster)
create(:users_ops_dashboard_project, user: user)
create(:prometheus_service, project: project)
create(:project_error_tracking_setting, project: project)
create(:project_tracing_setting, project: project)
end end
context 'for monitor' do expect(described_class.uncached_data[:usage_activity_by_stage][:monitor]).to eq(
it 'includes accurate usage_activity_by_stage data' do clusters: 2,
for_defined_days_back do clusters_applications_prometheus: 2,
user = create(:user, dashboard: 'operations') operations_dashboard_default_dashboard: 2,
cluster = create(:cluster, user: user) operations_dashboard_users_with_projects_added: 2,
project = create(:project, creator: user) projects_prometheus_active: 2,
projects_with_error_tracking_enabled: 2,
create(:clusters_applications_prometheus, :installed, cluster: cluster) projects_with_tracing_enabled: 2
create(:users_ops_dashboard_project, user: user) )
create(:prometheus_service, project: project) expect(described_class.uncached_data[:usage_activity_by_stage_monthly][:monitor]).to eq(
create(:project_error_tracking_setting, project: project) clusters: 1,
create(:project_tracing_setting, project: project) clusters_applications_prometheus: 1,
end operations_dashboard_default_dashboard: 1,
operations_dashboard_users_with_projects_added: 1,
expect(described_class.uncached_data[:usage_activity_by_stage][:monitor]).to eq( projects_prometheus_active: 1,
clusters: 2, projects_with_error_tracking_enabled: 1,
clusters_applications_prometheus: 2, projects_with_tracing_enabled: 1
operations_dashboard_default_dashboard: 2, )
operations_dashboard_users_with_projects_added: 2, end
projects_prometheus_active: 2, end
projects_with_error_tracking_enabled: 2,
projects_with_tracing_enabled: 2 context 'for package' do
) it 'includes accurate usage_activity_by_stage data' do
expect(described_class.uncached_data[:usage_activity_by_stage_monthly][:monitor]).to eq( for_defined_days_back do
clusters: 1, create(:project, packages: [create(:package)] )
clusters_applications_prometheus: 1,
operations_dashboard_default_dashboard: 1,
operations_dashboard_users_with_projects_added: 1,
projects_prometheus_active: 1,
projects_with_error_tracking_enabled: 1,
projects_with_tracing_enabled: 1
)
end
end end
context 'for package' do expect(described_class.uncached_data[:usage_activity_by_stage][:package]).to eq(
it 'includes accurate usage_activity_by_stage data' do projects_with_packages: 2
for_defined_days_back do )
create(:project, packages: [create(:package)] ) expect(described_class.uncached_data[:usage_activity_by_stage_monthly][:package]).to eq(
end projects_with_packages: 1
)
expect(described_class.uncached_data[:usage_activity_by_stage][:package]).to eq( end
projects_with_packages: 2 end
)
expect(described_class.uncached_data[:usage_activity_by_stage_monthly][:package]).to eq( context 'for plan' do
projects_with_packages: 1 it 'includes accurate usage_activity_by_stage data' do
) stub_licensed_features(board_assignee_lists: true, board_milestone_lists: true)
end
for_defined_days_back do
user = create(:user)
project = create(:project, creator: user)
issue = create(:issue, project: project, author: User.support_bot)
create(:issue, project: project, author: user)
board = create(:board, project: project)
create(:user_list, board: board, user: user)
create(:milestone_list, board: board, milestone: create(:milestone, project: project), user: user)
create(:list, board: board, label: create(:label, project: project), user: user)
create(:note, project: project, noteable: issue, author: user)
create(:epic, author: user)
create(:todo, project: project, target: issue, author: user)
create(:jira_service, :jira_cloud_service, active: true, project: create(:project, :jira_dvcs_cloud, creator: user))
create(:jira_service, active: true, project: create(:project, :jira_dvcs_server, creator: user))
end end
context 'for plan' do expect(described_class.uncached_data[:usage_activity_by_stage][:plan]).to eq(
it 'includes accurate usage_activity_by_stage data' do assignee_lists: 2,
stub_licensed_features(board_assignee_lists: true, board_milestone_lists: true) epics: 2,
issues: 3,
for_defined_days_back do label_lists: 2,
user = create(:user) milestone_lists: 2,
project = create(:project, creator: user) notes: 2,
issue = create(:issue, project: project, author: User.support_bot) projects: 2,
create(:issue, project: project, author: user) projects_jira_active: 2,
board = create(:board, project: project) projects_jira_dvcs_cloud_active: 2,
create(:user_list, board: board, user: user) projects_jira_dvcs_server_active: 2,
create(:milestone_list, board: board, milestone: create(:milestone, project: project), user: user) service_desk_enabled_projects: 2,
create(:list, board: board, label: create(:label, project: project), user: user) service_desk_issues: 2,
create(:note, project: project, noteable: issue, author: user) todos: 2
create(:epic, author: user) )
create(:todo, project: project, target: issue, author: user) expect(described_class.uncached_data[:usage_activity_by_stage_monthly][:plan]).to eq(
create(:jira_service, :jira_cloud_service, active: true, project: create(:project, :jira_dvcs_cloud, creator: user)) assignee_lists: 1,
create(:jira_service, active: true, project: create(:project, :jira_dvcs_server, creator: user)) epics: 1,
end issues: 2,
label_lists: 1,
expect(described_class.uncached_data[:usage_activity_by_stage][:plan]).to eq( milestone_lists: 1,
assignee_lists: 2, notes: 1,
epics: 2, projects: 1,
issues: 3, projects_jira_active: 1,
label_lists: 2, projects_jira_dvcs_cloud_active: 1,
milestone_lists: 2, projects_jira_dvcs_server_active: 1,
notes: 2, service_desk_enabled_projects: 1,
projects: 2, service_desk_issues: 1,
projects_jira_active: 2, todos: 1
projects_jira_dvcs_cloud_active: 2, )
projects_jira_dvcs_server_active: 2, end
service_desk_enabled_projects: 2, end
service_desk_issues: 2,
todos: 2 context 'for release' do
) it 'includes accurate usage_activity_by_stage data' do
expect(described_class.uncached_data[:usage_activity_by_stage_monthly][:plan]).to eq( for_defined_days_back do
assignee_lists: 1, user = create(:user)
epics: 1, create(:deployment, :failed, user: user)
issues: 2, create(:project, :mirror, mirror_trigger_builds: true)
label_lists: 1, create(:release, author: user)
milestone_lists: 1, create(:deployment, :success, user: user)
notes: 1,
projects: 1,
projects_jira_active: 1,
projects_jira_dvcs_cloud_active: 1,
projects_jira_dvcs_server_active: 1,
service_desk_enabled_projects: 1,
service_desk_issues: 1,
todos: 1
)
end
end end
context 'for release' do expect(described_class.uncached_data[:usage_activity_by_stage][:release]).to eq(
it 'includes accurate usage_activity_by_stage data' do deployments: 2,
for_defined_days_back do failed_deployments: 2,
user = create(:user) projects_mirrored_with_pipelines_enabled: 2,
create(:deployment, :failed, user: user) releases: 2,
create(:project, :mirror, mirror_trigger_builds: true) successful_deployments: 2
create(:release, author: user) )
create(:deployment, :success, user: user) expect(described_class.uncached_data[:usage_activity_by_stage_monthly][:release]).to eq(
end deployments: 1,
failed_deployments: 1,
expect(described_class.uncached_data[:usage_activity_by_stage][:release]).to eq( projects_mirrored_with_pipelines_enabled: 1,
deployments: 2, releases: 1,
failed_deployments: 2, successful_deployments: 1
projects_mirrored_with_pipelines_enabled: 2, )
releases: 2, end
successful_deployments: 2 end
)
expect(described_class.uncached_data[:usage_activity_by_stage_monthly][:release]).to eq( context 'for secure' do
deployments: 1, let_it_be(:user) { create(:user, group_view: :security_dashboard) }
failed_deployments: 1,
projects_mirrored_with_pipelines_enabled: 1, before do
releases: 1, for_defined_days_back do
successful_deployments: 1 create(:ci_build, name: 'container_scanning', user: user)
) create(:ci_build, name: 'dast', user: user)
end create(:ci_build, name: 'dependency_scanning', user: user)
create(:ci_build, name: 'license_management', user: user)
create(:ci_build, name: 'sast', user: user)
create(:ci_build, name: 'secret_detection', user: user)
end end
end
context 'for secure' do it 'includes accurate usage_activity_by_stage data' do
let_it_be(:user) { create(:user, group_view: :security_dashboard) } expect(described_class.uncached_data[:usage_activity_by_stage_monthly][:secure]).to eq(
user_preferences_group_overview_security_dashboard: 1,
before do user_container_scanning_jobs: 1,
for_defined_days_back do user_dast_jobs: 1,
create(:ci_build, name: 'container_scanning', user: user) user_dependency_scanning_jobs: 1,
create(:ci_build, name: 'dast', user: user) user_license_management_jobs: 1,
create(:ci_build, name: 'dependency_scanning', user: user) user_sast_jobs: 1,
create(:ci_build, name: 'license_management', user: user) user_secret_detection_jobs: 1
create(:ci_build, name: 'sast', user: user) )
create(:ci_build, name: 'secret_detection', user: user) end
end
end it 'combines license_scanning into license_management' do
for_defined_days_back do
it 'includes accurate usage_activity_by_stage data' do create(:ci_build, name: 'license_scanning', user: user)
expect(described_class.uncached_data[:usage_activity_by_stage_monthly][:secure]).to eq(
user_preferences_group_overview_security_dashboard: 1,
user_container_scanning_jobs: 1,
user_dast_jobs: 1,
user_dependency_scanning_jobs: 1,
user_license_management_jobs: 1,
user_sast_jobs: 1,
user_secret_detection_jobs: 1
)
end
it 'combines license_scanning into license_management' do
for_defined_days_back do
create(:ci_build, name: 'license_scanning', user: user)
end
expect(described_class.uncached_data[:usage_activity_by_stage_monthly][:secure]).to eq(
user_preferences_group_overview_security_dashboard: 1,
user_container_scanning_jobs: 1,
user_dast_jobs: 1,
user_dependency_scanning_jobs: 1,
user_license_management_jobs: 2,
user_sast_jobs: 1,
user_secret_detection_jobs: 1
)
end
it 'has to resort to 0 for counting license scan' do
allow(Gitlab::Database::BatchCount).to receive(:batch_distinct_count).and_raise(ActiveRecord::StatementInvalid)
allow(::Ci::Build).to receive(:distinct_count_by).and_raise(ActiveRecord::StatementInvalid)
expect(described_class.uncached_data[:usage_activity_by_stage_monthly][:secure]).to eq(
user_preferences_group_overview_security_dashboard: 1,
user_container_scanning_jobs: -1,
user_dast_jobs: -1,
user_dependency_scanning_jobs: -1,
user_license_management_jobs: -1,
user_sast_jobs: -1,
user_secret_detection_jobs: -1
)
end
end end
context 'for verify' do expect(described_class.uncached_data[:usage_activity_by_stage_monthly][:secure]).to eq(
it 'includes accurate usage_activity_by_stage data' do user_preferences_group_overview_security_dashboard: 1,
for_defined_days_back do user_container_scanning_jobs: 1,
user = create(:user) user_dast_jobs: 1,
create(:ci_build, user: user) user_dependency_scanning_jobs: 1,
create(:ci_empty_pipeline, source: :external, user: user) user_license_management_jobs: 2,
create(:ci_empty_pipeline, user: user) user_sast_jobs: 1,
create(:ci_pipeline, :auto_devops_source, user: user) user_secret_detection_jobs: 1
create(:ci_pipeline, :repository_source, user: user) )
create(:ci_pipeline_schedule, owner: user) end
create(:ci_trigger, owner: user)
create(:clusters_applications_runner, :installed) it 'has to resort to 0 for counting license scan' do
create(:github_service) allow(Gitlab::Database::BatchCount).to receive(:batch_distinct_count).and_raise(ActiveRecord::StatementInvalid)
end allow(::Ci::Build).to receive(:distinct_count_by).and_raise(ActiveRecord::StatementInvalid)
expect(described_class.uncached_data[:usage_activity_by_stage][:verify]).to eq( expect(described_class.uncached_data[:usage_activity_by_stage_monthly][:secure]).to eq(
ci_builds: 2, user_preferences_group_overview_security_dashboard: 1,
ci_external_pipelines: 2, user_container_scanning_jobs: -1,
ci_internal_pipelines: 2, user_dast_jobs: -1,
ci_pipeline_config_auto_devops: 2, user_dependency_scanning_jobs: -1,
ci_pipeline_config_repository: 2, user_license_management_jobs: -1,
ci_pipeline_schedules: 2, user_sast_jobs: -1,
ci_pipelines: 2, user_secret_detection_jobs: -1
ci_triggers: 2, )
clusters_applications_runner: 2, end
projects_reporting_ci_cd_back_to_github: 2 end
)
expect(described_class.uncached_data[:usage_activity_by_stage_monthly][:verify]).to eq( context 'for verify' do
ci_builds: 1, it 'includes accurate usage_activity_by_stage data' do
ci_external_pipelines: 1, for_defined_days_back do
ci_internal_pipelines: 1, user = create(:user)
ci_pipeline_config_auto_devops: 1, create(:ci_build, user: user)
ci_pipeline_config_repository: 1, create(:ci_empty_pipeline, source: :external, user: user)
ci_pipeline_schedules: 1, create(:ci_empty_pipeline, user: user)
ci_pipelines: 1, create(:ci_pipeline, :auto_devops_source, user: user)
ci_triggers: 1, create(:ci_pipeline, :repository_source, user: user)
clusters_applications_runner: 1, create(:ci_pipeline_schedule, owner: user)
projects_reporting_ci_cd_back_to_github: 1 create(:ci_trigger, owner: user)
) create(:clusters_applications_runner, :installed)
end create(:github_service)
end end
expect(described_class.uncached_data[:usage_activity_by_stage][:verify]).to eq(
ci_builds: 2,
ci_external_pipelines: 2,
ci_internal_pipelines: 2,
ci_pipeline_config_auto_devops: 2,
ci_pipeline_config_repository: 2,
ci_pipeline_schedules: 2,
ci_pipelines: 2,
ci_triggers: 2,
clusters_applications_runner: 2,
projects_reporting_ci_cd_back_to_github: 2
)
expect(described_class.uncached_data[:usage_activity_by_stage_monthly][:verify]).to eq(
ci_builds: 1,
ci_external_pipelines: 1,
ci_internal_pipelines: 1,
ci_pipeline_config_auto_devops: 1,
ci_pipeline_config_repository: 1,
ci_pipeline_schedules: 1,
ci_pipelines: 1,
ci_triggers: 1,
clusters_applications_runner: 1,
projects_reporting_ci_cd_back_to_github: 1
)
end end
end end
end end
......
...@@ -40,7 +40,7 @@ module Gitlab ...@@ -40,7 +40,7 @@ module Gitlab
FALLBACK = -1 FALLBACK = -1
def count(relation, column = nil, batch: true, start: nil, finish: nil) def count(relation, column = nil, batch: true, start: nil, finish: nil)
if batch && Feature.enabled?(:usage_ping_batch_counter, default_enabled: true) if batch
Gitlab::Database::BatchCount.batch_count(relation, column, start: start, finish: finish) Gitlab::Database::BatchCount.batch_count(relation, column, start: start, finish: finish)
else else
relation.count relation.count
...@@ -50,7 +50,7 @@ module Gitlab ...@@ -50,7 +50,7 @@ module Gitlab
end end
def distinct_count(relation, column = nil, batch: true, batch_size: nil, start: nil, finish: nil) def distinct_count(relation, column = nil, batch: true, batch_size: nil, start: nil, finish: nil)
if batch && Feature.enabled?(:usage_ping_batch_counter, default_enabled: true) if batch
Gitlab::Database::BatchCount.batch_distinct_count(relation, column, batch_size: batch_size, start: start, finish: finish) Gitlab::Database::BatchCount.batch_distinct_count(relation, column, batch_size: batch_size, start: start, finish: finish)
else else
relation.distinct_count_by(column) relation.distinct_count_by(column)
......
...@@ -10,656 +10,638 @@ describe Gitlab::UsageData, :aggregate_failures do ...@@ -10,656 +10,638 @@ describe Gitlab::UsageData, :aggregate_failures do
stub_object_store_settings stub_object_store_settings
end end
shared_examples "usage data execution" do describe '#data' do
describe '#data' do let!(:ud) { build(:usage_data) }
let!(:ud) { build(:usage_data) }
before do before do
allow(described_class).to receive(:grafana_embed_usage_data).and_return(2) allow(described_class).to receive(:grafana_embed_usage_data).and_return(2)
end end
subject { described_class.data } subject { described_class.data }
it 'gathers usage data' do it 'gathers usage data' do
expect(subject.keys).to include(*UsageDataHelpers::USAGE_DATA_KEYS) expect(subject.keys).to include(*UsageDataHelpers::USAGE_DATA_KEYS)
end end
it 'gathers usage counts' do it 'gathers usage counts' do
count_data = subject[:counts] count_data = subject[:counts]
expect(count_data[:boards]).to eq(1) expect(count_data[:boards]).to eq(1)
expect(count_data[:projects]).to eq(4) expect(count_data[:projects]).to eq(4)
expect(count_data.values_at(*UsageDataHelpers::SMAU_KEYS)).to all(be_an(Integer)) expect(count_data.values_at(*UsageDataHelpers::SMAU_KEYS)).to all(be_an(Integer))
expect(count_data.keys).to include(*UsageDataHelpers::COUNTS_KEYS) expect(count_data.keys).to include(*UsageDataHelpers::COUNTS_KEYS)
expect(UsageDataHelpers::COUNTS_KEYS - count_data.keys).to be_empty expect(UsageDataHelpers::COUNTS_KEYS - count_data.keys).to be_empty
end end
it 'gathers projects data correctly' do it 'gathers projects data correctly' do
count_data = subject[:counts] count_data = subject[:counts]
expect(count_data[:projects]).to eq(4) expect(count_data[:projects]).to eq(4)
expect(count_data[:projects_asana_active]).to eq(0) expect(count_data[:projects_asana_active]).to eq(0)
expect(count_data[:projects_prometheus_active]).to eq(1) expect(count_data[:projects_prometheus_active]).to eq(1)
expect(count_data[:projects_jira_active]).to eq(4) expect(count_data[:projects_jira_active]).to eq(4)
expect(count_data[:projects_jira_server_active]).to eq(2) expect(count_data[:projects_jira_server_active]).to eq(2)
expect(count_data[:projects_jira_cloud_active]).to eq(2) expect(count_data[:projects_jira_cloud_active]).to eq(2)
expect(count_data[:jira_imports_projects_count]).to eq(2) expect(count_data[:jira_imports_projects_count]).to eq(2)
expect(count_data[:jira_imports_total_imported_count]).to eq(3) expect(count_data[:jira_imports_total_imported_count]).to eq(3)
expect(count_data[:jira_imports_total_imported_issues_count]).to eq(13) expect(count_data[:jira_imports_total_imported_issues_count]).to eq(13)
expect(count_data[:projects_slack_notifications_active]).to eq(2) expect(count_data[:projects_slack_notifications_active]).to eq(2)
expect(count_data[:projects_slack_slash_active]).to eq(1) expect(count_data[:projects_slack_slash_active]).to eq(1)
expect(count_data[:projects_slack_active]).to eq(2) expect(count_data[:projects_slack_active]).to eq(2)
expect(count_data[:projects_slack_slash_commands_active]).to eq(1) expect(count_data[:projects_slack_slash_commands_active]).to eq(1)
expect(count_data[:projects_custom_issue_tracker_active]).to eq(1) expect(count_data[:projects_custom_issue_tracker_active]).to eq(1)
expect(count_data[:projects_mattermost_active]).to eq(0) expect(count_data[:projects_mattermost_active]).to eq(0)
expect(count_data[:projects_with_repositories_enabled]).to eq(3) expect(count_data[:projects_with_repositories_enabled]).to eq(3)
expect(count_data[:projects_with_error_tracking_enabled]).to eq(1) expect(count_data[:projects_with_error_tracking_enabled]).to eq(1)
expect(count_data[:projects_with_alerts_service_enabled]).to eq(1) expect(count_data[:projects_with_alerts_service_enabled]).to eq(1)
expect(count_data[:projects_with_prometheus_alerts]).to eq(2) expect(count_data[:projects_with_prometheus_alerts]).to eq(2)
expect(count_data[:projects_with_terraform_reports]).to eq(2) expect(count_data[:projects_with_terraform_reports]).to eq(2)
expect(count_data[:projects_with_terraform_states]).to eq(2) expect(count_data[:projects_with_terraform_states]).to eq(2)
expect(count_data[:terraform_reports]).to eq(3) expect(count_data[:terraform_reports]).to eq(3)
expect(count_data[:terraform_states]).to eq(3) expect(count_data[:terraform_states]).to eq(3)
expect(count_data[:issues_created_from_gitlab_error_tracking_ui]).to eq(1) expect(count_data[:issues_created_from_gitlab_error_tracking_ui]).to eq(1)
expect(count_data[:issues_with_associated_zoom_link]).to eq(2) expect(count_data[:issues_with_associated_zoom_link]).to eq(2)
expect(count_data[:issues_using_zoom_quick_actions]).to eq(3) expect(count_data[:issues_using_zoom_quick_actions]).to eq(3)
expect(count_data[:issues_with_embedded_grafana_charts_approx]).to eq(2) expect(count_data[:issues_with_embedded_grafana_charts_approx]).to eq(2)
expect(count_data[:incident_issues]).to eq(4) expect(count_data[:incident_issues]).to eq(4)
expect(count_data[:issues_created_gitlab_alerts]).to eq(1) expect(count_data[:issues_created_gitlab_alerts]).to eq(1)
expect(count_data[:alert_bot_incident_issues]).to eq(4) expect(count_data[:alert_bot_incident_issues]).to eq(4)
expect(count_data[:incident_labeled_issues]).to eq(3) expect(count_data[:incident_labeled_issues]).to eq(3)
expect(count_data[:clusters_enabled]).to eq(6) expect(count_data[:clusters_enabled]).to eq(6)
expect(count_data[:project_clusters_enabled]).to eq(4) expect(count_data[:project_clusters_enabled]).to eq(4)
expect(count_data[:group_clusters_enabled]).to eq(1) expect(count_data[:group_clusters_enabled]).to eq(1)
expect(count_data[:instance_clusters_enabled]).to eq(1) expect(count_data[:instance_clusters_enabled]).to eq(1)
expect(count_data[:clusters_disabled]).to eq(3) expect(count_data[:clusters_disabled]).to eq(3)
expect(count_data[:project_clusters_disabled]).to eq(1) expect(count_data[:project_clusters_disabled]).to eq(1)
expect(count_data[:group_clusters_disabled]).to eq(1) expect(count_data[:group_clusters_disabled]).to eq(1)
expect(count_data[:instance_clusters_disabled]).to eq(1) expect(count_data[:instance_clusters_disabled]).to eq(1)
expect(count_data[:clusters_platforms_eks]).to eq(1) expect(count_data[:clusters_platforms_eks]).to eq(1)
expect(count_data[:clusters_platforms_gke]).to eq(1) expect(count_data[:clusters_platforms_gke]).to eq(1)
expect(count_data[:clusters_platforms_user]).to eq(1) expect(count_data[:clusters_platforms_user]).to eq(1)
expect(count_data[:clusters_applications_helm]).to eq(1) expect(count_data[:clusters_applications_helm]).to eq(1)
expect(count_data[:clusters_applications_ingress]).to eq(1) expect(count_data[:clusters_applications_ingress]).to eq(1)
expect(count_data[:clusters_applications_cert_managers]).to eq(1) expect(count_data[:clusters_applications_cert_managers]).to eq(1)
expect(count_data[:clusters_applications_crossplane]).to eq(1) expect(count_data[:clusters_applications_crossplane]).to eq(1)
expect(count_data[:clusters_applications_prometheus]).to eq(1) expect(count_data[:clusters_applications_prometheus]).to eq(1)
expect(count_data[:clusters_applications_runner]).to eq(1) expect(count_data[:clusters_applications_runner]).to eq(1)
expect(count_data[:clusters_applications_knative]).to eq(1) expect(count_data[:clusters_applications_knative]).to eq(1)
expect(count_data[:clusters_applications_elastic_stack]).to eq(1) expect(count_data[:clusters_applications_elastic_stack]).to eq(1)
expect(count_data[:grafana_integrated_projects]).to eq(2) expect(count_data[:grafana_integrated_projects]).to eq(2)
expect(count_data[:clusters_applications_jupyter]).to eq(1) expect(count_data[:clusters_applications_jupyter]).to eq(1)
expect(count_data[:clusters_management_project]).to eq(1) expect(count_data[:clusters_management_project]).to eq(1)
end end
it 'gathers object store usage correctly' do it 'gathers object store usage correctly' do
expect(subject[:object_store]).to eq( expect(subject[:object_store]).to eq(
{ artifacts: { enabled: true, object_store: { enabled: true, direct_upload: true, background_upload: false, provider: "AWS" } }, { artifacts: { enabled: true, object_store: { enabled: true, direct_upload: true, background_upload: false, provider: "AWS" } },
external_diffs: { enabled: false }, external_diffs: { enabled: false },
lfs: { enabled: true, object_store: { enabled: false, direct_upload: true, background_upload: false, provider: "AWS" } }, lfs: { enabled: true, object_store: { enabled: false, direct_upload: true, background_upload: false, provider: "AWS" } },
uploads: { enabled: nil, object_store: { enabled: false, direct_upload: true, background_upload: false, provider: "AWS" } }, uploads: { enabled: nil, object_store: { enabled: false, direct_upload: true, background_upload: false, provider: "AWS" } },
packages: { enabled: true, object_store: { enabled: false, direct_upload: false, background_upload: true, provider: "AWS" } } } packages: { enabled: true, object_store: { enabled: false, direct_upload: false, background_upload: true, provider: "AWS" } } }
) )
end end
context 'with existing container expiration policies' do context 'with existing container expiration policies' do
let_it_be(:disabled) { create(:container_expiration_policy, enabled: false) } let_it_be(:disabled) { create(:container_expiration_policy, enabled: false) }
let_it_be(:enabled) { create(:container_expiration_policy, enabled: true) } let_it_be(:enabled) { create(:container_expiration_policy, enabled: true) }
%i[keep_n cadence older_than].each do |attribute| %i[keep_n cadence older_than].each do |attribute|
ContainerExpirationPolicy.send("#{attribute}_options").keys.each do |value| ContainerExpirationPolicy.send("#{attribute}_options").keys.each do |value|
let_it_be("container_expiration_policy_with_#{attribute}_set_to_#{value}") { create(:container_expiration_policy, attribute => value) } let_it_be("container_expiration_policy_with_#{attribute}_set_to_#{value}") { create(:container_expiration_policy, attribute => value) }
end
end end
end
let_it_be('container_expiration_policy_with_keep_n_set_to_null') { create(:container_expiration_policy, keep_n: nil) } let_it_be('container_expiration_policy_with_keep_n_set_to_null') { create(:container_expiration_policy, keep_n: nil) }
let_it_be('container_expiration_policy_with_older_than_set_to_null') { create(:container_expiration_policy, older_than: nil) } let_it_be('container_expiration_policy_with_older_than_set_to_null') { create(:container_expiration_policy, older_than: nil) }
let(:inactive_policies) { ::ContainerExpirationPolicy.where(enabled: false) }
let(:active_policies) { ::ContainerExpirationPolicy.active }
subject { described_class.data[:counts] }
it 'gathers usage data' do
expect(subject[:projects_with_expiration_policy_enabled]).to eq 22
expect(subject[:projects_with_expiration_policy_disabled]).to eq 1
expect(subject[:projects_with_expiration_policy_enabled_with_keep_n_unset]).to eq 1 let(:inactive_policies) { ::ContainerExpirationPolicy.where(enabled: false) }
expect(subject[:projects_with_expiration_policy_enabled_with_keep_n_set_to_1]).to eq 1 let(:active_policies) { ::ContainerExpirationPolicy.active }
expect(subject[:projects_with_expiration_policy_enabled_with_keep_n_set_to_5]).to eq 1
expect(subject[:projects_with_expiration_policy_enabled_with_keep_n_set_to_10]).to eq 16
expect(subject[:projects_with_expiration_policy_enabled_with_keep_n_set_to_25]).to eq 1
expect(subject[:projects_with_expiration_policy_enabled_with_keep_n_set_to_50]).to eq 1
expect(subject[:projects_with_expiration_policy_enabled_with_older_than_unset]).to eq 1 subject { described_class.data[:counts] }
expect(subject[:projects_with_expiration_policy_enabled_with_older_than_set_to_7d]).to eq 1
expect(subject[:projects_with_expiration_policy_enabled_with_older_than_set_to_14d]).to eq 1
expect(subject[:projects_with_expiration_policy_enabled_with_older_than_set_to_30d]).to eq 1
expect(subject[:projects_with_expiration_policy_enabled_with_older_than_set_to_90d]).to eq 18
expect(subject[:projects_with_expiration_policy_enabled_with_cadence_set_to_1d]).to eq 18 it 'gathers usage data' do
expect(subject[:projects_with_expiration_policy_enabled_with_cadence_set_to_7d]).to eq 1 expect(subject[:projects_with_expiration_policy_enabled]).to eq 22
expect(subject[:projects_with_expiration_policy_enabled_with_cadence_set_to_14d]).to eq 1 expect(subject[:projects_with_expiration_policy_disabled]).to eq 1
expect(subject[:projects_with_expiration_policy_enabled_with_cadence_set_to_1month]).to eq 1
expect(subject[:projects_with_expiration_policy_enabled_with_cadence_set_to_3month]).to eq 1 expect(subject[:projects_with_expiration_policy_enabled_with_keep_n_unset]).to eq 1
end expect(subject[:projects_with_expiration_policy_enabled_with_keep_n_set_to_1]).to eq 1
expect(subject[:projects_with_expiration_policy_enabled_with_keep_n_set_to_5]).to eq 1
expect(subject[:projects_with_expiration_policy_enabled_with_keep_n_set_to_10]).to eq 16
expect(subject[:projects_with_expiration_policy_enabled_with_keep_n_set_to_25]).to eq 1
expect(subject[:projects_with_expiration_policy_enabled_with_keep_n_set_to_50]).to eq 1
expect(subject[:projects_with_expiration_policy_enabled_with_older_than_unset]).to eq 1
expect(subject[:projects_with_expiration_policy_enabled_with_older_than_set_to_7d]).to eq 1
expect(subject[:projects_with_expiration_policy_enabled_with_older_than_set_to_14d]).to eq 1
expect(subject[:projects_with_expiration_policy_enabled_with_older_than_set_to_30d]).to eq 1
expect(subject[:projects_with_expiration_policy_enabled_with_older_than_set_to_90d]).to eq 18
expect(subject[:projects_with_expiration_policy_enabled_with_cadence_set_to_1d]).to eq 18
expect(subject[:projects_with_expiration_policy_enabled_with_cadence_set_to_7d]).to eq 1
expect(subject[:projects_with_expiration_policy_enabled_with_cadence_set_to_14d]).to eq 1
expect(subject[:projects_with_expiration_policy_enabled_with_cadence_set_to_1month]).to eq 1
expect(subject[:projects_with_expiration_policy_enabled_with_cadence_set_to_3month]).to eq 1
end end
end
it 'works when queries time out' do it 'works when queries time out' do
allow_any_instance_of(ActiveRecord::Relation) allow_any_instance_of(ActiveRecord::Relation)
.to receive(:count).and_raise(ActiveRecord::StatementInvalid.new('')) .to receive(:count).and_raise(ActiveRecord::StatementInvalid.new(''))
expect { subject }.not_to raise_error expect { subject }.not_to raise_error
end end
it 'jira usage works when queries time out' do it 'jira usage works when queries time out' do
allow_any_instance_of(ActiveRecord::Relation) allow_any_instance_of(ActiveRecord::Relation)
.to receive(:find_in_batches).and_raise(ActiveRecord::StatementInvalid.new('')) .to receive(:find_in_batches).and_raise(ActiveRecord::StatementInvalid.new(''))
expect { described_class.jira_usage }.not_to raise_error expect { described_class.jira_usage }.not_to raise_error
end
end end
end
describe '#usage_data_counters' do describe '#usage_data_counters' do
subject { described_class.usage_data_counters } subject { described_class.usage_data_counters }
it { is_expected.to all(respond_to :totals) } it { is_expected.to all(respond_to :totals) }
it { is_expected.to all(respond_to :fallback_totals) } it { is_expected.to all(respond_to :fallback_totals) }
describe 'the results of calling #totals on all objects in the array' do describe 'the results of calling #totals on all objects in the array' do
subject { described_class.usage_data_counters.map(&:totals) } subject { described_class.usage_data_counters.map(&:totals) }
it { is_expected.to all(be_a Hash) } it { is_expected.to all(be_a Hash) }
it { is_expected.to all(have_attributes(keys: all(be_a Symbol), values: all(be_a Integer))) } it { is_expected.to all(have_attributes(keys: all(be_a Symbol), values: all(be_a Integer))) }
end end
describe 'the results of calling #fallback_totals on all objects in the array' do describe 'the results of calling #fallback_totals on all objects in the array' do
subject { described_class.usage_data_counters.map(&:fallback_totals) } subject { described_class.usage_data_counters.map(&:fallback_totals) }
it { is_expected.to all(be_a Hash) } it { is_expected.to all(be_a Hash) }
it { is_expected.to all(have_attributes(keys: all(be_a Symbol), values: all(eq(-1)))) } it { is_expected.to all(have_attributes(keys: all(be_a Symbol), values: all(eq(-1)))) }
end end
it 'does not have any conflicts' do it 'does not have any conflicts' do
all_keys = subject.flat_map { |counter| counter.totals.keys } all_keys = subject.flat_map { |counter| counter.totals.keys }
expect(all_keys.size).to eq all_keys.to_set.size expect(all_keys.size).to eq all_keys.to_set.size
end
end end
end
describe '#license_usage_data' do describe '#license_usage_data' do
subject { described_class.license_usage_data } subject { described_class.license_usage_data }
it 'gathers license data' do it 'gathers license data' do
expect(subject[:uuid]).to eq(Gitlab::CurrentSettings.uuid) expect(subject[:uuid]).to eq(Gitlab::CurrentSettings.uuid)
expect(subject[:version]).to eq(Gitlab::VERSION) expect(subject[:version]).to eq(Gitlab::VERSION)
expect(subject[:installation_type]).to eq('gitlab-development-kit') expect(subject[:installation_type]).to eq('gitlab-development-kit')
expect(subject[:active_user_count]).to eq(User.active.size) expect(subject[:active_user_count]).to eq(User.active.size)
expect(subject[:recorded_at]).to be_a(Time) expect(subject[:recorded_at]).to be_a(Time)
end
end end
end
describe '.recording_ce_finished_at' do describe '.recording_ce_finished_at' do
subject { described_class.recording_ce_finish_data } subject { described_class.recording_ce_finish_data }
it 'gathers time ce recording finishes at' do it 'gathers time ce recording finishes at' do
expect(subject[:recording_ce_finished_at]).to be_a(Time) expect(subject[:recording_ce_finished_at]).to be_a(Time)
end
end end
end
context 'when not relying on database records' do context 'when not relying on database records' do
describe '#features_usage_data_ce' do describe '#features_usage_data_ce' do
subject { described_class.features_usage_data_ce } subject { described_class.features_usage_data_ce }
it 'gathers feature usage data' do it 'gathers feature usage data' do
expect(subject[:mattermost_enabled]).to eq(Gitlab.config.mattermost.enabled) expect(subject[:mattermost_enabled]).to eq(Gitlab.config.mattermost.enabled)
expect(subject[:signup_enabled]).to eq(Gitlab::CurrentSettings.allow_signup?) expect(subject[:signup_enabled]).to eq(Gitlab::CurrentSettings.allow_signup?)
expect(subject[:ldap_enabled]).to eq(Gitlab.config.ldap.enabled) expect(subject[:ldap_enabled]).to eq(Gitlab.config.ldap.enabled)
expect(subject[:gravatar_enabled]).to eq(Gitlab::CurrentSettings.gravatar_enabled?) expect(subject[:gravatar_enabled]).to eq(Gitlab::CurrentSettings.gravatar_enabled?)
expect(subject[:omniauth_enabled]).to eq(Gitlab::Auth.omniauth_enabled?) expect(subject[:omniauth_enabled]).to eq(Gitlab::Auth.omniauth_enabled?)
expect(subject[:reply_by_email_enabled]).to eq(Gitlab::IncomingEmail.enabled?) expect(subject[:reply_by_email_enabled]).to eq(Gitlab::IncomingEmail.enabled?)
expect(subject[:container_registry_enabled]).to eq(Gitlab.config.registry.enabled) expect(subject[:container_registry_enabled]).to eq(Gitlab.config.registry.enabled)
expect(subject[:dependency_proxy_enabled]).to eq(Gitlab.config.dependency_proxy.enabled) expect(subject[:dependency_proxy_enabled]).to eq(Gitlab.config.dependency_proxy.enabled)
expect(subject[:gitlab_shared_runners_enabled]).to eq(Gitlab.config.gitlab_ci.shared_runners_enabled) expect(subject[:gitlab_shared_runners_enabled]).to eq(Gitlab.config.gitlab_ci.shared_runners_enabled)
expect(subject[:web_ide_clientside_preview_enabled]).to eq(Gitlab::CurrentSettings.web_ide_clientside_preview_enabled?) expect(subject[:web_ide_clientside_preview_enabled]).to eq(Gitlab::CurrentSettings.web_ide_clientside_preview_enabled?)
expect(subject[:grafana_link_enabled]).to eq(Gitlab::CurrentSettings.grafana_enabled?) expect(subject[:grafana_link_enabled]).to eq(Gitlab::CurrentSettings.grafana_enabled?)
end end
context 'with embedded grafana' do
it 'returns true when embedded grafana is enabled' do
stub_application_setting(grafana_enabled: true)
expect(subject[:grafana_link_enabled]).to eq(true)
end
it 'returns false when embedded grafana is disabled' do context 'with embedded grafana' do
stub_application_setting(grafana_enabled: false) it 'returns true when embedded grafana is enabled' do
stub_application_setting(grafana_enabled: true)
expect(subject[:grafana_link_enabled]).to eq(false) expect(subject[:grafana_link_enabled]).to eq(true)
end
end end
end
describe '#components_usage_data' do
subject { described_class.components_usage_data }
it 'gathers basic components usage data' do it 'returns false when embedded grafana is disabled' do
stub_runtime(:puma) stub_application_setting(grafana_enabled: false)
expect(subject[:app_server][:type]).to eq('puma') expect(subject[:grafana_link_enabled]).to eq(false)
expect(subject[:gitlab_pages][:enabled]).to eq(Gitlab.config.pages.enabled)
expect(subject[:gitlab_pages][:version]).to eq(Gitlab::Pages::VERSION)
expect(subject[:git][:version]).to eq(Gitlab::Git.version)
expect(subject[:database][:adapter]).to eq(Gitlab::Database.adapter_name)
expect(subject[:database][:version]).to eq(Gitlab::Database.version)
expect(subject[:gitaly][:version]).to be_present
expect(subject[:gitaly][:servers]).to be >= 1
expect(subject[:gitaly][:clusters]).to be >= 0
expect(subject[:gitaly][:filesystems]).to be_an(Array)
expect(subject[:gitaly][:filesystems].first).to be_a(String)
end end
end
end
def stub_runtime(runtime) describe '#components_usage_data' do
allow(Gitlab::Runtime).to receive(:identify).and_return(runtime) subject { described_class.components_usage_data }
end
it 'gathers basic components usage data' do
stub_runtime(:puma)
expect(subject[:app_server][:type]).to eq('puma')
expect(subject[:gitlab_pages][:enabled]).to eq(Gitlab.config.pages.enabled)
expect(subject[:gitlab_pages][:version]).to eq(Gitlab::Pages::VERSION)
expect(subject[:git][:version]).to eq(Gitlab::Git.version)
expect(subject[:database][:adapter]).to eq(Gitlab::Database.adapter_name)
expect(subject[:database][:version]).to eq(Gitlab::Database.version)
expect(subject[:gitaly][:version]).to be_present
expect(subject[:gitaly][:servers]).to be >= 1
expect(subject[:gitaly][:clusters]).to be >= 0
expect(subject[:gitaly][:filesystems]).to be_an(Array)
expect(subject[:gitaly][:filesystems].first).to be_a(String)
end end
describe '#topology_usage_data' do def stub_runtime(runtime)
subject { described_class.topology_usage_data } allow(Gitlab::Runtime).to receive(:identify).and_return(runtime)
end
end
describe '#topology_usage_data' do
subject { described_class.topology_usage_data }
before do
# this pins down time shifts when benchmarking durations
allow(Process).to receive(:clock_gettime).and_return(0)
end
context 'when embedded Prometheus server is enabled' do
before do before do
# this pins down time shifts when benchmarking durations expect(Gitlab::Prometheus::Internal).to receive(:prometheus_enabled?).and_return(true)
allow(Process).to receive(:clock_gettime).and_return(0) expect(Gitlab::Prometheus::Internal).to receive(:uri).and_return('http://prom:9090')
end end
context 'when embedded Prometheus server is enabled' do it 'contains a topology element' do
before do allow_prometheus_queries
expect(Gitlab::Prometheus::Internal).to receive(:prometheus_enabled?).and_return(true)
expect(Gitlab::Prometheus::Internal).to receive(:uri).and_return('http://prom:9090')
end
it 'contains a topology element' do expect(subject).to have_key(:topology)
allow_prometheus_queries end
expect(subject).to have_key(:topology)
end
context 'tracking node metrics' do context 'tracking node metrics' do
it 'contains node level metrics for each instance' do it 'contains node level metrics for each instance' do
expect_prometheus_api_to receive(:aggregate) expect_prometheus_api_to receive(:aggregate)
.with(func: 'avg', metric: 'node_memory_MemTotal_bytes', by: 'instance') .with(func: 'avg', metric: 'node_memory_MemTotal_bytes', by: 'instance')
.and_return({ .and_return({
'instance1' => 512, 'instance1' => 512,
'instance2' => 1024 'instance2' => 1024
})
expect(subject[:topology]).to eq({
duration_s: 0,
nodes: [
{
node_memory_total_bytes: 512
},
{
node_memory_total_bytes: 1024
}
]
}) })
end
end
context 'and no results are found' do
it 'does not report anything' do
expect_prometheus_api_to receive(:aggregate).and_return({})
expect(subject[:topology]).to eq({ expect(subject[:topology]).to eq({
duration_s: 0, duration_s: 0,
nodes: [] nodes: [
}) {
end node_memory_total_bytes: 512
},
{
node_memory_total_bytes: 1024
}
]
})
end end
end
context 'and a connection error is raised' do context 'and no results are found' do
it 'does not report anything' do it 'does not report anything' do
expect_prometheus_api_to receive(:aggregate).and_raise('Connection failed') expect_prometheus_api_to receive(:aggregate).and_return({})
expect(subject[:topology]).to eq({ duration_s: 0 }) expect(subject[:topology]).to eq({
end duration_s: 0,
nodes: []
})
end end
end end
context 'when embedded Prometheus server is disabled' do context 'and a connection error is raised' do
it 'does not report anything' do it 'does not report anything' do
expect_prometheus_api_to receive(:aggregate).and_raise('Connection failed')
expect(subject[:topology]).to eq({ duration_s: 0 }) expect(subject[:topology]).to eq({ duration_s: 0 })
end end
end end
end
def expect_prometheus_api_to(receive_matcher) context 'when embedded Prometheus server is disabled' do
expect_next_instance_of(Gitlab::PrometheusClient) do |client| it 'does not report anything' do
expect(client).to receive_matcher expect(subject[:topology]).to eq({ duration_s: 0 })
end
end end
end
def allow_prometheus_queries def expect_prometheus_api_to(receive_matcher)
allow_next_instance_of(Gitlab::PrometheusClient) do |client| expect_next_instance_of(Gitlab::PrometheusClient) do |client|
allow(client).to receive(:aggregate).and_return({}) expect(client).to receive_matcher
end
end end
end end
describe '#app_server_type' do def allow_prometheus_queries
subject { described_class.app_server_type } allow_next_instance_of(Gitlab::PrometheusClient) do |client|
allow(client).to receive(:aggregate).and_return({})
end
end
end
it 'successfully identifies runtime and returns the identifier' do describe '#app_server_type' do
expect(Gitlab::Runtime).to receive(:identify).and_return(:runtime_identifier) subject { described_class.app_server_type }
is_expected.to eq('runtime_identifier') it 'successfully identifies runtime and returns the identifier' do
end expect(Gitlab::Runtime).to receive(:identify).and_return(:runtime_identifier)
context 'when runtime is not identified' do is_expected.to eq('runtime_identifier')
let(:exception) { Gitlab::Runtime::IdentificationError.new('exception message from runtime identify') } end
it 'logs the exception and returns unknown app server type' do context 'when runtime is not identified' do
expect(Gitlab::Runtime).to receive(:identify).and_raise(exception) let(:exception) { Gitlab::Runtime::IdentificationError.new('exception message from runtime identify') }
expect(Gitlab::AppLogger).to receive(:error).with(exception.message) it 'logs the exception and returns unknown app server type' do
expect(Gitlab::ErrorTracking).to receive(:track_exception).with(exception) expect(Gitlab::Runtime).to receive(:identify).and_raise(exception)
expect(subject).to eq('unknown_app_server_type')
end expect(Gitlab::AppLogger).to receive(:error).with(exception.message)
expect(Gitlab::ErrorTracking).to receive(:track_exception).with(exception)
expect(subject).to eq('unknown_app_server_type')
end end
end end
end
describe '#object_store_config' do describe '#object_store_config' do
let(:component) { 'lfs' } let(:component) { 'lfs' }
subject { described_class.object_store_config(component) } subject { described_class.object_store_config(component) }
context 'when object_store is not configured' do context 'when object_store is not configured' do
it 'returns component enable status only' do it 'returns component enable status only' do
allow(Settings).to receive(:[]).with(component).and_return({ 'enabled' => false }) allow(Settings).to receive(:[]).with(component).and_return({ 'enabled' => false })
expect(subject).to eq({ enabled: false }) expect(subject).to eq({ enabled: false })
end
end end
end
context 'when object_store is configured' do context 'when object_store is configured' do
it 'returns filtered object store config' do it 'returns filtered object store config' do
allow(Settings).to receive(:[]).with(component) allow(Settings).to receive(:[]).with(component)
.and_return( .and_return(
{ 'enabled' => true,
'object_store' =>
{ 'enabled' => true, { 'enabled' => true,
'object_store' => 'remote_directory' => component,
{ 'enabled' => true, 'direct_upload' => true,
'remote_directory' => component, 'connection' =>
'direct_upload' => true, { 'provider' => 'AWS', 'aws_access_key_id' => 'minio', 'aws_secret_access_key' => 'gdk-minio', 'region' => 'gdk', 'endpoint' => 'http://127.0.0.1:9000', 'path_style' => true },
'connection' => 'background_upload' => false,
{ 'provider' => 'AWS', 'aws_access_key_id' => 'minio', 'aws_secret_access_key' => 'gdk-minio', 'region' => 'gdk', 'endpoint' => 'http://127.0.0.1:9000', 'path_style' => true }, 'proxy_download' => false } })
'background_upload' => false,
'proxy_download' => false } }) expect(subject).to eq(
{ enabled: true, object_store: { enabled: true, direct_upload: true, background_upload: false, provider: "AWS" } })
expect(subject).to eq(
{ enabled: true, object_store: { enabled: true, direct_upload: true, background_upload: false, provider: "AWS" } })
end
end end
end
context 'when retrieve component setting meets exception' do context 'when retrieve component setting meets exception' do
it 'returns -1 for component enable status' do it 'returns -1 for component enable status' do
allow(Settings).to receive(:[]).with(component).and_raise(StandardError) allow(Settings).to receive(:[]).with(component).and_raise(StandardError)
expect(subject).to eq({ enabled: -1 }) expect(subject).to eq({ enabled: -1 })
end
end end
end end
end
describe '#object_store_usage_data' do describe '#object_store_usage_data' do
subject { described_class.object_store_usage_data } subject { described_class.object_store_usage_data }
it 'fetches object store config of five components' do
%w(artifacts external_diffs lfs uploads packages).each do |component|
expect(described_class).to receive(:object_store_config).with(component).and_return("#{component}_object_store_config")
end
expect(subject).to eq( it 'fetches object store config of five components' do
object_store: { %w(artifacts external_diffs lfs uploads packages).each do |component|
artifacts: 'artifacts_object_store_config', expect(described_class).to receive(:object_store_config).with(component).and_return("#{component}_object_store_config")
external_diffs: 'external_diffs_object_store_config',
lfs: 'lfs_object_store_config',
uploads: 'uploads_object_store_config',
packages: 'packages_object_store_config'
})
end end
expect(subject).to eq(
object_store: {
artifacts: 'artifacts_object_store_config',
external_diffs: 'external_diffs_object_store_config',
lfs: 'lfs_object_store_config',
uploads: 'uploads_object_store_config',
packages: 'packages_object_store_config'
})
end end
end
describe '#cycle_analytics_usage_data' do describe '#cycle_analytics_usage_data' do
subject { described_class.cycle_analytics_usage_data } subject { described_class.cycle_analytics_usage_data }
it 'works when queries time out in new' do it 'works when queries time out in new' do
allow(Gitlab::CycleAnalytics::UsageData) allow(Gitlab::CycleAnalytics::UsageData)
.to receive(:new).and_raise(ActiveRecord::StatementInvalid.new('')) .to receive(:new).and_raise(ActiveRecord::StatementInvalid.new(''))
expect { subject }.not_to raise_error expect { subject }.not_to raise_error
end end
it 'works when queries time out in to_json' do
allow_any_instance_of(Gitlab::CycleAnalytics::UsageData)
.to receive(:to_json).and_raise(ActiveRecord::StatementInvalid.new(''))
it 'works when queries time out in to_json' do expect { subject }.not_to raise_error
allow_any_instance_of(Gitlab::CycleAnalytics::UsageData) end
.to receive(:to_json).and_raise(ActiveRecord::StatementInvalid.new('')) end
expect { subject }.not_to raise_error describe '#ingress_modsecurity_usage' do
subject { described_class.ingress_modsecurity_usage }
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
end end
describe '#ingress_modsecurity_usage' do context 'when deployment is unsuccessful' do
subject { described_class.ingress_modsecurity_usage } let!(:deployment) { create(:deployment, :failed, environment: environment, project: project, cluster: cluster) }
let(:environment) { create(:environment) } it 'gathers ingress data' do
let(:project) { environment.project } expect(subject[:ingress_modsecurity_logging]).to eq(0)
let(:environment_scope) { '*' } expect(subject[:ingress_modsecurity_blocking]).to eq(0)
let(:deployment) { create(:deployment, :success, environment: environment, project: project, cluster: cluster) } expect(subject[:ingress_modsecurity_disabled]).to eq(0)
let(:cluster) { create(:cluster, environment_scope: environment_scope, projects: [project]) } expect(subject[:ingress_modsecurity_not_installed]).to eq(0)
let(:ingress_mode) { :modsecurity_blocking } end
let!(:ingress) { create(:clusters_applications_ingress, ingress_mode, cluster: cluster) } end
context 'when cluster is disabled' do context 'when deployment is successful' do
let(:cluster) { create(:cluster, :disabled, projects: [project]) } let!(:deployment) { create(:deployment, :success, environment: environment, project: project, cluster: cluster) }
context 'when modsecurity is in blocking mode' do
it 'gathers ingress data' do it 'gathers ingress data' do
expect(subject[:ingress_modsecurity_logging]).to eq(0) expect(subject[:ingress_modsecurity_logging]).to eq(0)
expect(subject[:ingress_modsecurity_blocking]).to eq(0) expect(subject[:ingress_modsecurity_blocking]).to eq(1)
expect(subject[:ingress_modsecurity_disabled]).to eq(0) expect(subject[:ingress_modsecurity_disabled]).to eq(0)
expect(subject[:ingress_modsecurity_not_installed]).to eq(0) expect(subject[:ingress_modsecurity_not_installed]).to eq(0)
end end
end end
context 'when deployment is unsuccessful' do context 'when modsecurity is in logging mode' do
let!(:deployment) { create(:deployment, :failed, environment: environment, project: project, cluster: cluster) } let(:ingress_mode) { :modsecurity_logging }
it 'gathers ingress data' do it 'gathers ingress data' do
expect(subject[:ingress_modsecurity_logging]).to eq(0) expect(subject[:ingress_modsecurity_logging]).to eq(1)
expect(subject[:ingress_modsecurity_blocking]).to eq(0) expect(subject[:ingress_modsecurity_blocking]).to eq(0)
expect(subject[:ingress_modsecurity_disabled]).to eq(0) expect(subject[:ingress_modsecurity_disabled]).to eq(0)
expect(subject[:ingress_modsecurity_not_installed]).to eq(0) expect(subject[:ingress_modsecurity_not_installed]).to eq(0)
end end
end end
context 'when deployment is successful' do context 'when modsecurity is disabled' do
let!(:deployment) { create(:deployment, :success, environment: environment, project: project, cluster: cluster) } let(:ingress_mode) { :modsecurity_disabled }
context 'when modsecurity is in blocking mode' do it 'gathers ingress data' do
it 'gathers ingress data' do expect(subject[:ingress_modsecurity_logging]).to eq(0)
expect(subject[:ingress_modsecurity_logging]).to eq(0) expect(subject[:ingress_modsecurity_blocking]).to eq(0)
expect(subject[:ingress_modsecurity_blocking]).to eq(1) expect(subject[:ingress_modsecurity_disabled]).to eq(1)
expect(subject[:ingress_modsecurity_disabled]).to eq(0) expect(subject[:ingress_modsecurity_not_installed]).to eq(0)
expect(subject[:ingress_modsecurity_not_installed]).to eq(0)
end
end end
end
context 'when modsecurity is in logging mode' do context 'when modsecurity is not installed' do
let(:ingress_mode) { :modsecurity_logging } let(:ingress_mode) { :modsecurity_not_installed }
it 'gathers ingress data' do it 'gathers ingress data' do
expect(subject[:ingress_modsecurity_logging]).to eq(1) expect(subject[:ingress_modsecurity_logging]).to eq(0)
expect(subject[:ingress_modsecurity_blocking]).to eq(0) expect(subject[:ingress_modsecurity_blocking]).to eq(0)
expect(subject[:ingress_modsecurity_disabled]).to eq(0) expect(subject[:ingress_modsecurity_disabled]).to eq(0)
expect(subject[:ingress_modsecurity_not_installed]).to eq(0) expect(subject[:ingress_modsecurity_not_installed]).to eq(1)
end
end end
end
context 'when modsecurity is disabled' do context 'with multiple projects' do
let(:ingress_mode) { :modsecurity_disabled } 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 ingress data' do it 'gathers non-duplicated ingress data' do
expect(subject[:ingress_modsecurity_logging]).to eq(0) expect(subject[:ingress_modsecurity_logging]).to eq(1)
expect(subject[:ingress_modsecurity_blocking]).to eq(0) expect(subject[:ingress_modsecurity_blocking]).to eq(1)
expect(subject[:ingress_modsecurity_disabled]).to eq(1) expect(subject[:ingress_modsecurity_disabled]).to eq(0)
expect(subject[:ingress_modsecurity_not_installed]).to eq(0) expect(subject[:ingress_modsecurity_not_installed]).to eq(0)
end
end end
end
context 'when modsecurity is not installed' do context 'with multiple deployments' do
let(:ingress_mode) { :modsecurity_not_installed } let!(:deployment_2) { create(:deployment, :success, 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(1)
end
end
context 'with multiple projects' do it 'gathers non-duplicated ingress data' do
let(:environment_2) { create(:environment) } expect(subject[:ingress_modsecurity_logging]).to eq(0)
let(:project_2) { environment_2.project } expect(subject[:ingress_modsecurity_blocking]).to eq(1)
let(:cluster_2) { create(:cluster, environment_scope: environment_scope, projects: [project_2]) } expect(subject[:ingress_modsecurity_disabled]).to eq(0)
let!(:ingress_2) { create(:clusters_applications_ingress, :modsecurity_logging, cluster: cluster_2) } expect(subject[:ingress_modsecurity_not_installed]).to eq(0)
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 end
end
context 'with multiple deployments' do context 'with multiple projects' do
let!(:deployment_2) { create(:deployment, :success, environment: environment, project: project, cluster: cluster) } 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 non-duplicated ingress data' do it 'gathers ingress data' do
expect(subject[:ingress_modsecurity_logging]).to eq(0) expect(subject[:ingress_modsecurity_logging]).to eq(0)
expect(subject[:ingress_modsecurity_blocking]).to eq(1) expect(subject[:ingress_modsecurity_blocking]).to eq(2)
expect(subject[:ingress_modsecurity_disabled]).to eq(0) expect(subject[:ingress_modsecurity_disabled]).to eq(0)
expect(subject[:ingress_modsecurity_not_installed]).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 end
end
context 'with multiple environments' do context 'with multiple environments' do
let!(:environment_2) { create(:environment, project: project) } let!(:environment_2) { create(:environment, project: project) }
let!(:deployment_2) { create(:deployment, :success, environment: environment_2, project: project, cluster: cluster) } let!(:deployment_2) { create(:deployment, :success, environment: environment_2, project: project, cluster: cluster) }
it 'gathers ingress data' do it 'gathers ingress data' do
expect(subject[:ingress_modsecurity_logging]).to eq(0) expect(subject[:ingress_modsecurity_logging]).to eq(0)
expect(subject[:ingress_modsecurity_blocking]).to eq(2) expect(subject[:ingress_modsecurity_blocking]).to eq(2)
expect(subject[:ingress_modsecurity_disabled]).to eq(0) expect(subject[:ingress_modsecurity_disabled]).to eq(0)
expect(subject[:ingress_modsecurity_not_installed]).to eq(0) expect(subject[:ingress_modsecurity_not_installed]).to eq(0)
end
end end
end end
end end
end
describe '#grafana_embed_usage_data' do describe '#grafana_embed_usage_data' do
subject { described_class.grafana_embed_usage_data } subject { described_class.grafana_embed_usage_data }
let(:project) { create(:project) } let(:project) { create(:project) }
let(:description_with_embed) { "Some comment\n\nhttps://grafana.example.com/d/xvAk4q0Wk/go-processes?orgId=1&from=1573238522762&to=1573240322762&var-job=prometheus&var-interval=10m&panelId=1&fullscreen" } let(:description_with_embed) { "Some comment\n\nhttps://grafana.example.com/d/xvAk4q0Wk/go-processes?orgId=1&from=1573238522762&to=1573240322762&var-job=prometheus&var-interval=10m&panelId=1&fullscreen" }
let(:description_with_unintegrated_embed) { "Some comment\n\nhttps://grafana.exp.com/d/xvAk4q0Wk/go-processes?orgId=1&from=1573238522762&to=1573240322762&var-job=prometheus&var-interval=10m&panelId=1&fullscreen" } let(:description_with_unintegrated_embed) { "Some comment\n\nhttps://grafana.exp.com/d/xvAk4q0Wk/go-processes?orgId=1&from=1573238522762&to=1573240322762&var-job=prometheus&var-interval=10m&panelId=1&fullscreen" }
let(:description_with_non_grafana_inline_metric) { "Some comment\n\n#{Gitlab::Routing.url_helpers.metrics_namespace_project_environment_url(*['foo', 'bar', 12])}" } let(:description_with_non_grafana_inline_metric) { "Some comment\n\n#{Gitlab::Routing.url_helpers.metrics_namespace_project_environment_url(*['foo', 'bar', 12])}" }
shared_examples "zero count" do shared_examples "zero count" do
it "does not count the issue" do it "does not count the issue" do
expect(subject).to eq(0) expect(subject).to eq(0)
end
end end
end
context 'with project grafana integration enabled' do context 'with project grafana integration enabled' do
before do before do
create(:grafana_integration, project: project, enabled: true) create(:grafana_integration, project: project, enabled: true)
end
context 'with valid and invalid embeds' do
before do
# Valid
create(:issue, project: project, description: description_with_embed)
create(:issue, project: project, description: description_with_embed)
# In-Valid
create(:issue, project: project, description: description_with_unintegrated_embed)
create(:issue, project: project, description: description_with_non_grafana_inline_metric)
create(:issue, project: project, description: nil)
create(:issue, project: project, description: '')
create(:issue, project: project)
end
it 'counts only the issues with embeds' do
expect(subject).to eq(2)
end
end
end end
context 'with project grafana integration disabled' do context 'with valid and invalid embeds' do
before do before do
create(:grafana_integration, project: project, enabled: false) # Valid
create(:issue, project: project, description: description_with_embed)
create(:issue, project: project, description: description_with_embed)
# In-Valid
create(:issue, project: project, description: description_with_unintegrated_embed)
create(:issue, project: project, description: description_with_non_grafana_inline_metric)
create(:issue, project: project, description: nil)
create(:issue, project: project, description: '')
create(:issue, project: project)
end end
context 'with one issue having a grafana link in the description and one without' do it 'counts only the issues with embeds' do
before do expect(subject).to eq(2)
create(:issue, project: project, description: description_with_embed)
create(:issue, project: project)
end
it_behaves_like('zero count')
end end
end end
end
context 'with an un-integrated project' do context 'with project grafana integration disabled' do
context 'with one issue having a grafana link in the description and one without' do before do
before do create(:grafana_integration, project: project, enabled: false)
create(:issue, project: project, description: description_with_embed) end
create(:issue, project: project)
end
it_behaves_like('zero count') context 'with one issue having a grafana link in the description and one without' do
before do
create(:issue, project: project, description: description_with_embed)
create(:issue, project: project)
end end
it_behaves_like('zero count')
end end
end end
end
end
context 'when usage usage_ping_batch_counter is true' do context 'with an un-integrated project' do
before do context 'with one issue having a grafana link in the description and one without' do
stub_feature_flags(usage_ping_batch_counter: true) before do
end create(:issue, project: project, description: description_with_embed)
create(:issue, project: project)
it_behaves_like 'usage data execution' end
end
context 'when usage usage_ping_batch_counter is false' do it_behaves_like('zero count')
before do end
stub_feature_flags(usage_ping_batch_counter: false) end
end end
it_behaves_like 'usage data execution'
end end
describe '#merge_requests_usage_data' do describe '#merge_requests_usage_data' do
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment