diff --git a/app/models/clusters/applications/prometheus.rb b/app/models/clusters/applications/prometheus.rb index b9c136abab4..3160a000705 100644 --- a/app/models/clusters/applications/prometheus.rb +++ b/app/models/clusters/applications/prometheus.rb @@ -44,6 +44,10 @@ module Clusters end end + def managed_prometheus? + !externally_installed? && !uninstalled? + end + def updated_since?(timestamp) last_update_started_at && last_update_started_at > timestamp && @@ -70,6 +74,7 @@ module Clusters ) end + # Deprecated, to be removed in %14.0 as part of https://gitlab.com/groups/gitlab-org/-/epics/4280 def patch_command(values) helm_command_module::PatchCommand.new( name: name, diff --git a/app/models/concerns/prometheus_adapter.rb b/app/models/concerns/prometheus_adapter.rb index 55c2bf96a94..b26d376bb9b 100644 --- a/app/models/concerns/prometheus_adapter.rb +++ b/app/models/concerns/prometheus_adapter.rb @@ -26,6 +26,11 @@ module PrometheusAdapter } end + # Overridden in app/models/clusters/applications/prometheus.rb + def managed_prometheus? + false + end + # This is a light-weight check if a prometheus client is properly configured. def configured? raise NotImplemented diff --git a/app/services/clusters/applications/prometheus_update_service.rb b/app/services/clusters/applications/prometheus_update_service.rb index 437f6ab1202..b8b50f06d72 100644 --- a/app/services/clusters/applications/prometheus_update_service.rb +++ b/app/services/clusters/applications/prometheus_update_service.rb @@ -2,6 +2,7 @@ module Clusters module Applications + # Deprecated, to be removed in %14.0 as part of https://gitlab.com/groups/gitlab-org/-/epics/4280 class PrometheusUpdateService < BaseHelmService attr_accessor :project @@ -11,6 +12,8 @@ module Clusters end def execute + raise NotImplementedError, 'Externally installed prometheus should not be modified!' unless app.managed_prometheus? + app.make_updating! helm_api.update(patch_command(values)) diff --git a/app/services/clusters/applications/schedule_update_service.rb b/app/services/clusters/applications/schedule_update_service.rb index 41718df9a98..4f130f76b87 100644 --- a/app/services/clusters/applications/schedule_update_service.rb +++ b/app/services/clusters/applications/schedule_update_service.rb @@ -14,6 +14,7 @@ module Clusters def execute return unless application + return unless application.managed_prometheus? if recently_scheduled? worker_class.perform_in(BACKOFF_DELAY, application.name, application.id, project.id, Time.current) diff --git a/app/workers/cluster_update_app_worker.rb b/app/workers/cluster_update_app_worker.rb index 29feb813043..dc57a1a90d9 100644 --- a/app/workers/cluster_update_app_worker.rb +++ b/app/workers/cluster_update_app_worker.rb @@ -1,5 +1,6 @@ # frozen_string_literal: true +# Deprecated, to be removed in %14.0 as part of https://gitlab.com/groups/gitlab-org/-/epics/4280 class ClusterUpdateAppWorker # rubocop:disable Scalability/IdempotentWorker UpdateAlreadyInProgressError = Class.new(StandardError) @@ -35,6 +36,7 @@ class ClusterUpdateAppWorker # rubocop:disable Scalability/IdempotentWorker # rubocop: enable CodeReuse/ActiveRecord def update_prometheus(app, scheduled_time, project) + return unless app.managed_prometheus? return if app.updated_since?(scheduled_time) return if app.update_in_progress? diff --git a/changelogs/unreleased/disable_alerts_for_prometheus_cluster_integrations.yml b/changelogs/unreleased/disable_alerts_for_prometheus_cluster_integrations.yml new file mode 100644 index 00000000000..897f577cf59 --- /dev/null +++ b/changelogs/unreleased/disable_alerts_for_prometheus_cluster_integrations.yml @@ -0,0 +1,5 @@ +--- +title: Disable automatic setup of alerts for Prometheus cluster integration +merge_request: 58853 +author: +type: changed diff --git a/doc/administration/auth/ldap/index.md b/doc/administration/auth/ldap/index.md index 0e55efba8ae..364c7cebea3 100644 --- a/doc/administration/auth/ldap/index.md +++ b/doc/administration/auth/ldap/index.md @@ -5,7 +5,7 @@ group: Access info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments --- -# General LDAP Setup +# General LDAP setup **(FREE SELF)** GitLab integrates with LDAP to support user authentication. @@ -29,7 +29,7 @@ stands for **Lightweight Directory Access Protocol**, which is a standard application protocol for accessing and maintaining distributed directory information services over an Internet Protocol (IP) network. -## Security **(FREE SELF)** +## Security GitLab assumes that LDAP users: @@ -44,7 +44,7 @@ We recommend against using LDAP integration if your LDAP users are allowed to change their 'mail', 'email' or 'userPrincipalName' attribute on the LDAP server or share email addresses. -### User deletion **(FREE SELF)** +### User deletion If a user is deleted from the LDAP server, they are also blocked in GitLab. Users are immediately blocked from logging in. However, there is an @@ -56,13 +56,13 @@ immediately block all access. GitLab Enterprise Edition Premium supports a [configurable sync time](#adjusting-ldap-user-sync-schedule). **(PREMIUM)** -## Git password authentication **(FREE SELF)** +## Git password authentication LDAP-enabled users can always authenticate with Git using their GitLab username or email and LDAP password, even if password authentication for Git is disabled in the application settings. -## Enabling LDAP sign-in for existing GitLab users **(FREE SELF)** +## Enabling LDAP sign-in for existing GitLab users When a user signs in to GitLab with LDAP for the first time, and their LDAP email address is the primary email address of an existing GitLab user, then @@ -73,7 +73,7 @@ In other words, if an existing GitLab user wants to enable LDAP sign-in for themselves, they should check that their GitLab email address matches their LDAP email address, and then sign into GitLab via their LDAP credentials. -## Google Secure LDAP **(FREE SELF)** +## Google Secure LDAP > Introduced in GitLab 11.9. @@ -81,7 +81,7 @@ LDAP email address, and then sign into GitLab via their LDAP credentials. LDAP service that can be configured with GitLab for authentication and group sync. See [Google Secure LDAP](google_secure_ldap.md) for detailed configuration instructions. -## Configuration **(FREE SELF)** +## Configuration To enable LDAP integration you need to add your LDAP server settings in `/etc/gitlab/gitlab.rb` or `/home/git/gitlab/config/gitlab.yml` for Omnibus @@ -100,7 +100,7 @@ would be on port 389. `plain` also operates on port 389. Removed values: `tls` w LDAP users must have a set email address, regardless of whether or not it's used to sign in. -### Example Configurations **(FREE SELF)** +### Example Configurations **Omnibus Configuration** @@ -163,7 +163,7 @@ production: ... ``` -### Basic Configuration Settings **(FREE SELF)** +### Basic Configuration Settings | Setting | Description | Required | Examples | | ------- | ----------- | -------- | -------- | @@ -190,7 +190,7 @@ Some examples of the `user_filter` field syntax: - `'(employeeType=developer)'` - `'(&(objectclass=user)(|(samaccountname=momo)(samaccountname=toto)))'` -### SSL Configuration Settings **(FREE SELF)** +### SSL Configuration Settings | Setting | Description | Required | Examples | | ------- | ----------- | -------- | -------- | @@ -200,7 +200,7 @@ Some examples of the `user_filter` field syntax: | `cert` | Client certificate | no | `'-----BEGIN CERTIFICATE----- -----END CERTIFICATE -----'` | | `key` | Client private key | no | `'-----BEGIN PRIVATE KEY----- -----END PRIVATE KEY -----'` | -### Attribute Configuration Settings **(FREE SELF)** +### Attribute Configuration Settings LDAP attributes that GitLab uses to create an account for the LDAP user. The specified attribute can either be the attribute name as a string (for example, `'mail'`), or an array of attribute names to try in order (for example, `['mail', 'email']`). Note that the user's LDAP sign-in is the attribute specified as `uid` above. @@ -221,7 +221,7 @@ LDAP attributes that GitLab uses to create an account for the LDAP user. The spe | `external_groups` | An array of CNs of groups containing users that should be considered external. Note: Not `cn=interns` or the full DN. | no | `['interns', 'contractors']` | | `sync_ssh_keys` | The LDAP attribute containing a user's public SSH key. | no | `'sshPublicKey'` or false if not set | -### Set up LDAP user filter **(FREE SELF)** +### Set up LDAP user filter If you want to limit all GitLab access to a subset of the LDAP users on your LDAP server, the first step should be to narrow the configured `base`. However, @@ -266,7 +266,7 @@ Support for nested members in the user filter should not be confused with Please note that GitLab does not support the custom filter syntax used by OmniAuth LDAP. -#### Escaping special characters **(FREE SELF)** +#### Escaping special characters The `user_filter` DN can contain special characters. For example: @@ -297,7 +297,7 @@ The `user_filter` DN can contain special characters. For example: OU=Gitlab \28Inc\29,DC=gitlab,DC=com ``` -### Enabling LDAP username lowercase **(FREE SELF)** +### Enabling LDAP username lowercase Some LDAP servers, depending on their configurations, can return uppercase usernames. This can lead to several confusing issues such as creating links or namespaces with uppercase names. @@ -335,7 +335,7 @@ the configuration option `lowercase_usernames`. By default, this configuration o 1. [Restart GitLab](../../restart_gitlab.md#installations-from-source) for the changes to take effect. -### Disable LDAP web sign in **(FREE SELF)** +### Disable LDAP web sign in It can be useful to prevent using LDAP credentials through the web UI when an alternative such as SAML is preferred. This allows LDAP to be used for group @@ -367,7 +367,7 @@ This does not disable [using LDAP credentials for Git access](#git-password-auth 1. [Restart GitLab](../../restart_gitlab.md#installations-from-source) for the changes to take effect. -### Using encrypted credentials **(FREE SELF)** +### Using encrypted credentials Instead of having the LDAP integration credentials stored in plaintext in the configuration files, you can optionally use an encrypted file for the LDAP credentials. To use this feature, you first need to enable @@ -454,7 +454,7 @@ If initially your LDAP configuration looked like: 1. [Restart GitLab](../../restart_gitlab.md#installations-from-source) for the changes to take effect. -## Encryption **(FREE SELF)** +## Encryption ### TLS Server Authentication diff --git a/doc/development/usage_ping/dictionary.md b/doc/development/usage_ping/dictionary.md index 7c5d1c79d64..5df9d859ee6 100644 --- a/doc/development/usage_ping/dictionary.md +++ b/doc/development/usage_ping/dictionary.md @@ -6360,13 +6360,13 @@ Tiers: `free` The version of the PostgreSQL database. -[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/license/20210216175609_version.yml) +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/settings/20210216175609_version.yml) Group: `group::distribution` Status: `data_available` -Tiers: `free` +Tiers: `free`, `premium`, `ultimate` ### `dependency_proxy_enabled` @@ -6384,7 +6384,7 @@ Tiers: `free` Edition of GitLab such as EE or CE -[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/license/20210216175604_edition.yml) +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/settings/20210216175604_edition.yml) Group: `group::distribution` diff --git a/doc/integration/jira/dvcs.md b/doc/integration/jira/dvcs.md index 5d315ebd802..3099c02ff36 100644 --- a/doc/integration/jira/dvcs.md +++ b/doc/integration/jira/dvcs.md @@ -4,7 +4,7 @@ group: Ecosystem info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments --- -# Jira DVCS connector +# Jira DVCS connector **(FREE)** Use the Jira DVCS (distributed version control system) connector if you self-host either your Jira instance or your GitLab instance, and you want to sync information diff --git a/doc/operations/error_tracking.md b/doc/operations/error_tracking.md index 18e5eaeef43..78aa664b339 100644 --- a/doc/operations/error_tracking.md +++ b/doc/operations/error_tracking.md @@ -65,9 +65,8 @@ By default, a **Create issue** button is displayed: ![Error Details without Issue Link](img/error_details_v12_7.png) -If you create a GitLab issue from the error, the **Create issue** button changes to a **View issue** button and a link to the GitLab issue displays within the error detail section: - -![Error Details with Issue Link](img/error_details_with_issue_v12_8.png) +If you create a GitLab issue from the error, the **Create issue** button changes to a **View issue** +button and a link to the GitLab issue displays within the error detail section. ## Taking Action on errors diff --git a/doc/operations/img/error_details_v12_7.png b/doc/operations/img/error_details_v12_7.png index 1c7ace35e2a..a961e128351 100644 Binary files a/doc/operations/img/error_details_v12_7.png and b/doc/operations/img/error_details_v12_7.png differ diff --git a/doc/operations/img/error_details_with_issue_v12_8.png b/doc/operations/img/error_details_with_issue_v12_8.png deleted file mode 100644 index 0536861b070..00000000000 Binary files a/doc/operations/img/error_details_with_issue_v12_8.png and /dev/null differ diff --git a/doc/operations/img/error_tracking_list_v12_6.png b/doc/operations/img/error_tracking_list_v12_6.png index b99c83c14d3..934d43bed3e 100644 Binary files a/doc/operations/img/error_tracking_list_v12_6.png and b/doc/operations/img/error_tracking_list_v12_6.png differ diff --git a/doc/operations/metrics/alerts.md b/doc/operations/metrics/alerts.md index 7763224d21e..ff62152363b 100644 --- a/doc/operations/metrics/alerts.md +++ b/doc/operations/metrics/alerts.md @@ -49,6 +49,10 @@ as soon as the alert fires: ![Linked Runbook in charts](img/linked_runbooks_on_charts.png) +## Prometheus cluster integrations + +Alerts are not currently supported for [Prometheus cluster integrations](../../user/clusters/integrations.md). + ## External Prometheus instances > - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/9258) in GitLab Ultimate 11.8. diff --git a/doc/user/clusters/integrations.md b/doc/user/clusters/integrations.md index 74c48d1a010..68ec39be73f 100644 --- a/doc/user/clusters/integrations.md +++ b/doc/user/clusters/integrations.md @@ -20,6 +20,9 @@ You can integrate your Kubernetes cluster with [Prometheus](https://prometheus.io/) for monitoring key metrics of your apps directly from the GitLab UI. +[Alerts](../../operations/metrics/alerts.md) are not currently +supported. + Once enabled, you will see metrics from services available in the [metrics library](../project/integrations/prometheus_library/index.md). diff --git a/spec/models/clusters/applications/prometheus_spec.rb b/spec/models/clusters/applications/prometheus_spec.rb index 5a0ccabd467..f74a89eaec5 100644 --- a/spec/models/clusters/applications/prometheus_spec.rb +++ b/spec/models/clusters/applications/prometheus_spec.rb @@ -65,6 +65,26 @@ RSpec.describe Clusters::Applications::Prometheus do end end + describe '#managed_prometheus?' do + subject { prometheus.managed_prometheus? } + + let(:prometheus) { build(:clusters_applications_prometheus) } + + it { is_expected.to be_truthy } + + context 'externally installed' do + let(:prometheus) { build(:clusters_applications_prometheus, :externally_installed) } + + it { is_expected.to be_falsey } + end + + context 'uninstalled' do + let(:prometheus) { build(:clusters_applications_prometheus, :uninstalled) } + + it { is_expected.to be_falsey } + end + end + describe '#can_uninstall?' do let(:prometheus) { create(:clusters_applications_prometheus) } diff --git a/spec/services/clusters/applications/prometheus_update_service_spec.rb b/spec/services/clusters/applications/prometheus_update_service_spec.rb index 076ff0210c9..615bfc44045 100644 --- a/spec/services/clusters/applications/prometheus_update_service_spec.rb +++ b/spec/services/clusters/applications/prometheus_update_service_spec.rb @@ -9,83 +9,102 @@ RSpec.describe Clusters::Applications::PrometheusUpdateService do let(:cluster) { create(:cluster, :provided_by_user, :with_installed_helm, projects: [project]) } let(:application) { create(:clusters_applications_prometheus, :installed, cluster: cluster) } let(:empty_alerts_values_update_yaml) { "---\nalertmanager:\n enabled: false\nserverFiles:\n alerts: {}\n" } - let!(:patch_command) { application.patch_command(empty_alerts_values_update_yaml) } let(:helm_client) { instance_double(::Gitlab::Kubernetes::Helm::API) } subject(:service) { described_class.new(application, project) } - before do - allow(service).to receive(:patch_command).with(empty_alerts_values_update_yaml).and_return(patch_command) - allow(service).to receive(:helm_api).and_return(helm_client) - end + context 'when prometheus is a Clusters::Integrations::Prometheus' do + let(:application) { create(:clusters_integrations_prometheus, cluster: cluster) } - context 'when there are no errors' do - before do - expect(helm_client).to receive(:update).with(patch_command) - - allow(::ClusterWaitForAppUpdateWorker) - .to receive(:perform_in) - .and_return(nil) - end - - it 'make the application updating' do - expect(application.cluster).not_to be_nil - - service.execute - - expect(application).to be_updating - end - - it 'updates current config' do - prometheus_config_service = spy(:prometheus_config_service) - - expect(Clusters::Applications::PrometheusConfigService) - .to receive(:new) - .with(project, cluster, application) - .and_return(prometheus_config_service) - - expect(prometheus_config_service) - .to receive(:execute) - .and_return(YAML.safe_load(empty_alerts_values_update_yaml)) - - service.execute - end - - it 'schedules async update status check' do - expect(::ClusterWaitForAppUpdateWorker).to receive(:perform_in).once - - service.execute + it 'raises NotImplementedError' do + expect { service.execute }.to raise_error(NotImplementedError) end end - context 'when k8s cluster communication fails' do - before do - error = ::Kubeclient::HttpError.new(500, 'system failure', nil) - allow(helm_client).to receive(:update).and_raise(error) - end + context 'when prometheus is externally installed' do + let(:application) { create(:clusters_applications_prometheus, :externally_installed, cluster: cluster) } - it 'make the application update errored' do - service.execute - - expect(application).to be_update_errored - expect(application.status_reason).to match(/kubernetes error:/i) + it 'raises NotImplementedError' do + expect { service.execute }.to raise_error(NotImplementedError) end end - context 'when application cannot be persisted' do - let(:application) { build(:clusters_applications_prometheus, :installed) } + context 'when prometheus is a Clusters::Applications::Prometheus' do + let!(:patch_command) { application.patch_command(empty_alerts_values_update_yaml) } before do - allow(application).to receive(:make_updating!).once - .and_raise(ActiveRecord::RecordInvalid.new(application)) + allow(service).to receive(:patch_command).with(empty_alerts_values_update_yaml).and_return(patch_command) + allow(service).to receive(:helm_api).and_return(helm_client) end - it 'make the application update errored' do - expect(helm_client).not_to receive(:update) + context 'when there are no errors' do + before do + expect(helm_client).to receive(:update).with(patch_command) - service.execute + allow(::ClusterWaitForAppUpdateWorker) + .to receive(:perform_in) + .and_return(nil) + end - expect(application).to be_update_errored + it 'make the application updating' do + expect(application.cluster).not_to be_nil + + service.execute + + expect(application).to be_updating + end + + it 'updates current config' do + prometheus_config_service = spy(:prometheus_config_service) + + expect(Clusters::Applications::PrometheusConfigService) + .to receive(:new) + .with(project, cluster, application) + .and_return(prometheus_config_service) + + expect(prometheus_config_service) + .to receive(:execute) + .and_return(YAML.safe_load(empty_alerts_values_update_yaml)) + + service.execute + end + + it 'schedules async update status check' do + expect(::ClusterWaitForAppUpdateWorker).to receive(:perform_in).once + + service.execute + end + end + + context 'when k8s cluster communication fails' do + before do + error = ::Kubeclient::HttpError.new(500, 'system failure', nil) + allow(helm_client).to receive(:update).and_raise(error) + end + + it 'make the application update errored' do + service.execute + + expect(application).to be_update_errored + expect(application.status_reason).to match(/kubernetes error:/i) + end + end + + context 'when application cannot be persisted' do + let(:application) { build(:clusters_applications_prometheus, :installed) } + + before do + allow(application).to receive(:make_updating!).once + .and_raise(ActiveRecord::RecordInvalid.new(application)) + end + + it 'make the application update errored' do + expect(helm_client).not_to receive(:update) + + service.execute + + expect(application).to be_update_errored + end end end end diff --git a/spec/services/clusters/applications/schedule_update_service_spec.rb b/spec/services/clusters/applications/schedule_update_service_spec.rb index 01a75a334e6..2cbcb861938 100644 --- a/spec/services/clusters/applications/schedule_update_service_spec.rb +++ b/spec/services/clusters/applications/schedule_update_service_spec.rb @@ -10,6 +10,32 @@ RSpec.describe Clusters::Applications::ScheduleUpdateService do freeze_time { example.run } end + context 'when the application is a Clusters::Integrations::Prometheus' do + let(:application) { create(:clusters_integrations_prometheus) } + + it 'does nothing' do + service = described_class.new(application, project) + + expect(::ClusterUpdateAppWorker).not_to receive(:perform_in) + expect(::ClusterUpdateAppWorker).not_to receive(:perform_async) + + service.execute + end + end + + context 'when the application is externally installed' do + let(:application) { create(:clusters_applications_prometheus, :externally_installed) } + + it 'does nothing' do + service = described_class.new(application, project) + + expect(::ClusterUpdateAppWorker).not_to receive(:perform_in) + expect(::ClusterUpdateAppWorker).not_to receive(:perform_async) + + service.execute + end + end + context 'when application is able to be updated' do context 'when the application was recently scheduled' do it 'schedules worker with a backoff delay' do diff --git a/spec/workers/cluster_update_app_worker_spec.rb b/spec/workers/cluster_update_app_worker_spec.rb index 0db255cf68d..8f61ee17162 100644 --- a/spec/workers/cluster_update_app_worker_spec.rb +++ b/spec/workers/cluster_update_app_worker_spec.rb @@ -46,6 +46,16 @@ RSpec.describe ClusterUpdateAppWorker do subject.perform(application.name, application.id, project.id, Time.current) end + context 'application is externally installed' do + it 'does not execute PrometheusUpdateService' do + application = create(:clusters_applications_prometheus, :externally_installed) + + expect(prometheus_update_service).not_to receive(:execute) + + subject.perform(application.name, application.id, project.id, Time.current) + end + end + context 'with exclusive lease' do let_it_be(:user) { create(:user) }