Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
db115d5ac7
commit
eb0665d71e
19 changed files with 185 additions and 83 deletions
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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?
|
||||
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
title: Disable automatic setup of alerts for Prometheus cluster integration
|
||||
merge_request: 58853
|
||||
author:
|
||||
type: changed
|
|
@ -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----- <REDACTED> -----END CERTIFICATE -----'` |
|
||||
| `key` | Client private key | no | `'-----BEGIN PRIVATE KEY----- <REDACTED> -----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
|
||||
|
||||
|
|
|
@ -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`
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 91 KiB After Width: | Height: | Size: 174 KiB |
Binary file not shown.
Before Width: | Height: | Size: 32 KiB |
Binary file not shown.
Before Width: | Height: | Size: 40 KiB After Width: | Height: | Size: 76 KiB |
|
@ -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.
|
||||
|
|
|
@ -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).
|
||||
|
||||
|
|
|
@ -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) }
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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) }
|
||||
|
||||
|
|
Loading…
Reference in a new issue