Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--app/assets/javascripts/monitoring/components/charts/heatmap.vue73
-rw-r--r--app/assets/javascripts/monitoring/components/panel_type.vue7
-rw-r--r--app/assets/javascripts/monitoring/components/shared/prometheus_header.vue15
-rw-r--r--app/controllers/ldap/omniauth_callbacks_controller.rb4
-rw-r--r--app/controllers/sessions_controller.rb8
-rw-r--r--app/helpers/auth_helper.rb14
-rw-r--r--app/views/admin/sessions/_signin_box.html.haml2
-rw-r--r--app/views/devise/sessions/new.html.haml6
-rw-r--r--app/views/devise/shared/_signin_box.html.haml2
-rw-r--r--app/views/devise/shared/_tabs_ldap.html.haml2
-rw-r--r--app/workers/stuck_ci_jobs_worker.rb14
-rw-r--r--changelogs/unreleased/19054-upgrade-helm.yml5
-rw-r--r--changelogs/unreleased/fix-stuck-ci-jobs-worker.yml5
-rw-r--r--changelogs/unreleased/jej-prevent-ldap-sign-in.yml5
-rw-r--r--changelogs/unreleased/jivanvl-add-support-heatmap-charts.yml5
-rw-r--r--config/gitlab.yml.example1
-rw-r--r--config/initializers/1_settings.rb1
-rw-r--r--config/routes/user.rb2
-rw-r--r--doc/administration/auth/ldap.md34
-rw-r--r--doc/development/geo.md11
-rw-r--r--lib/gitlab/auth/ldap/config.rb8
-rw-r--r--lib/gitlab/ci/templates/Jobs/DAST-Default-Branch-Deploy.gitlab-ci.yml2
-rw-r--r--lib/gitlab/ci/templates/Jobs/Deploy.gitlab-ci.yml2
-rw-r--r--lib/gitlab/kubernetes/helm.rb4
-rw-r--r--spec/controllers/ldap/omniauth_callbacks_controller_spec.rb8
-rw-r--r--spec/controllers/sessions_controller_spec.rb25
-rw-r--r--spec/helpers/auth_helper_spec.rb17
-rw-r--r--spec/javascripts/monitoring/charts/heatmap_spec.js69
-rw-r--r--spec/javascripts/monitoring/mock_data.js79
-rw-r--r--spec/javascripts/monitoring/shared/prometheus_header_spec.js26
-rw-r--r--spec/lib/gitlab/auth/ldap/config_spec.rb19
-rw-r--r--spec/lib/gitlab/kubernetes/helm/pod_spec.rb2
-rw-r--r--spec/routing/routing_spec.rb27
-rw-r--r--spec/support/controllers/ldap_omniauth_callbacks_controller_shared_context.rb8
-rw-r--r--spec/views/devise/sessions/new.html.haml_spec.rb71
-rw-r--r--spec/workers/stuck_ci_jobs_worker_spec.rb21
36 files changed, 581 insertions, 23 deletions
diff --git a/app/assets/javascripts/monitoring/components/charts/heatmap.vue b/app/assets/javascripts/monitoring/components/charts/heatmap.vue
new file mode 100644
index 00000000000..b8158247e49
--- /dev/null
+++ b/app/assets/javascripts/monitoring/components/charts/heatmap.vue
@@ -0,0 +1,73 @@
+<script>
+import { GlHeatmap } from '@gitlab/ui/dist/charts';
+import dateformat from 'dateformat';
+import PrometheusHeader from '../shared/prometheus_header.vue';
+import ResizableChartContainer from '~/vue_shared/components/resizable_chart/resizable_chart_container.vue';
+import { graphDataValidatorForValues } from '../../utils';
+
+export default {
+ components: {
+ GlHeatmap,
+ ResizableChartContainer,
+ PrometheusHeader,
+ },
+ props: {
+ graphData: {
+ type: Object,
+ required: true,
+ validator: graphDataValidatorForValues.bind(null, false),
+ },
+ containerWidth: {
+ type: Number,
+ required: true,
+ },
+ },
+ computed: {
+ chartData() {
+ return this.queries.result.reduce(
+ (acc, result, i) => [...acc, ...result.values.map((value, j) => [i, j, value[1]])],
+ [],
+ );
+ },
+ xAxisName() {
+ return this.graphData.x_label || '';
+ },
+ yAxisName() {
+ return this.graphData.y_label || '';
+ },
+ xAxisLabels() {
+ return this.queries.result.map(res => Object.values(res.metric)[0]);
+ },
+ yAxisLabels() {
+ return this.result.values.map(val => {
+ const [yLabel] = val;
+
+ return dateformat(new Date(yLabel), 'HH:MM:ss');
+ });
+ },
+ result() {
+ return this.queries.result[0];
+ },
+ queries() {
+ return this.graphData.queries[0];
+ },
+ },
+};
+</script>
+<template>
+ <div class="prometheus-graph col-12 col-lg-6">
+ <prometheus-header :graph-title="graphData.title" />
+ <resizable-chart-container>
+ <gl-heatmap
+ ref="heatmapChart"
+ v-bind="$attrs"
+ :data-series="chartData"
+ :x-axis-name="xAxisName"
+ :y-axis-name="yAxisName"
+ :x-axis-labels="xAxisLabels"
+ :y-axis-labels="yAxisLabels"
+ :width="containerWidth"
+ />
+ </resizable-chart-container>
+ </div>
+</template>
diff --git a/app/assets/javascripts/monitoring/components/panel_type.vue b/app/assets/javascripts/monitoring/components/panel_type.vue
index e3f99dbda9a..cafb4b0b479 100644
--- a/app/assets/javascripts/monitoring/components/panel_type.vue
+++ b/app/assets/javascripts/monitoring/components/panel_type.vue
@@ -13,6 +13,7 @@ import Icon from '~/vue_shared/components/icon.vue';
import MonitorTimeSeriesChart from './charts/time_series.vue';
import MonitorAnomalyChart from './charts/anomaly.vue';
import MonitorSingleStatChart from './charts/single_stat.vue';
+import MonitorHeatmapChart from './charts/heatmap.vue';
import MonitorEmptyChart from './charts/empty_chart.vue';
import TrackEventDirective from '~/vue_shared/directives/track_event';
import { downloadCSVOptions, generateLinkToChartOptions } from '../utils';
@@ -20,6 +21,7 @@ import { downloadCSVOptions, generateLinkToChartOptions } from '../utils';
export default {
components: {
MonitorSingleStatChart,
+ MonitorHeatmapChart,
MonitorEmptyChart,
Icon,
GlDropdown,
@@ -99,6 +101,11 @@ export default {
v-if="isPanelType('single-stat') && graphDataHasMetrics"
:graph-data="graphData"
/>
+ <monitor-heatmap-chart
+ v-else-if="isPanelType('heatmap') && graphDataHasMetrics"
+ :graph-data="graphData"
+ :container-width="dashboardWidth"
+ />
<component
:is="monitorChartComponent"
v-else-if="graphDataHasMetrics"
diff --git a/app/assets/javascripts/monitoring/components/shared/prometheus_header.vue b/app/assets/javascripts/monitoring/components/shared/prometheus_header.vue
new file mode 100644
index 00000000000..153c8f389db
--- /dev/null
+++ b/app/assets/javascripts/monitoring/components/shared/prometheus_header.vue
@@ -0,0 +1,15 @@
+<script>
+export default {
+ props: {
+ graphTitle: {
+ type: String,
+ required: true,
+ },
+ },
+};
+</script>
+<template>
+ <div class="prometheus-graph-header">
+ <h5 class="prometheus-graph-title js-graph-title">{{ graphTitle }}</h5>
+ </div>
+</template>
diff --git a/app/controllers/ldap/omniauth_callbacks_controller.rb b/app/controllers/ldap/omniauth_callbacks_controller.rb
index 4d8875937eb..71a88bf3395 100644
--- a/app/controllers/ldap/omniauth_callbacks_controller.rb
+++ b/app/controllers/ldap/omniauth_callbacks_controller.rb
@@ -4,7 +4,7 @@ class Ldap::OmniauthCallbacksController < OmniauthCallbacksController
extend ::Gitlab::Utils::Override
def self.define_providers!
- return unless Gitlab::Auth::LDAP::Config.enabled?
+ return unless Gitlab::Auth::LDAP::Config.sign_in_enabled?
Gitlab::Auth::LDAP::Config.available_servers.each do |server|
alias_method server['provider_name'], :ldap
@@ -14,6 +14,8 @@ class Ldap::OmniauthCallbacksController < OmniauthCallbacksController
# We only find ourselves here
# if the authentication to LDAP was successful.
def ldap
+ return unless Gitlab::Auth::LDAP::Config.sign_in_enabled?
+
sign_in_user_flow(Gitlab::Auth::LDAP::User)
end
diff --git a/app/controllers/sessions_controller.rb b/app/controllers/sessions_controller.rb
index 00e3be0edfa..0007d5826ba 100644
--- a/app/controllers/sessions_controller.rb
+++ b/app/controllers/sessions_controller.rb
@@ -270,7 +270,13 @@ class SessionsController < Devise::SessionsController
end
def ldap_servers
- @ldap_servers ||= Gitlab::Auth::LDAP::Config.available_servers
+ @ldap_servers ||= begin
+ if Gitlab::Auth::LDAP::Config.sign_in_enabled?
+ Gitlab::Auth::LDAP::Config.available_servers
+ else
+ []
+ end
+ end
end
def unverified_anonymous_user?
diff --git a/app/helpers/auth_helper.rb b/app/helpers/auth_helper.rb
index 9e6fcf6a267..a9c4cfe7dcc 100644
--- a/app/helpers/auth_helper.rb
+++ b/app/helpers/auth_helper.rb
@@ -8,6 +8,10 @@ module AuthHelper
Gitlab::Auth::LDAP::Config.enabled?
end
+ def ldap_sign_in_enabled?
+ Gitlab::Auth::LDAP::Config.sign_in_enabled?
+ end
+
def omniauth_enabled?
Gitlab::Auth.omniauth_enabled?
end
@@ -56,6 +60,16 @@ module AuthHelper
auth_providers.select { |provider| form_based_provider?(provider) }
end
+ def any_form_based_providers_enabled?
+ form_based_providers.any? { |provider| form_enabled_for_sign_in?(provider) }
+ end
+
+ def form_enabled_for_sign_in?(provider)
+ return true unless provider.to_s.match?(LDAP_PROVIDER)
+
+ ldap_sign_in_enabled?
+ end
+
def crowd_enabled?
auth_providers.include? :crowd
end
diff --git a/app/views/admin/sessions/_signin_box.html.haml b/app/views/admin/sessions/_signin_box.html.haml
index 69baa76060e..1d19915d3c5 100644
--- a/app/views/admin/sessions/_signin_box.html.haml
+++ b/app/views/admin/sessions/_signin_box.html.haml
@@ -1,4 +1,4 @@
-- if form_based_providers.any?
+- if any_form_based_providers_enabled?
- if password_authentication_enabled_for_web?
.login-box.tab-pane{ id: 'login-pane', role: 'tabpanel' }
diff --git a/app/views/devise/sessions/new.html.haml b/app/views/devise/sessions/new.html.haml
index 8f6c3ecbe58..fd6d8f3f769 100644
--- a/app/views/devise/sessions/new.html.haml
+++ b/app/views/devise/sessions/new.html.haml
@@ -1,13 +1,13 @@
- page_title "Sign in"
#signin-container
- - if form_based_providers.any?
+ - if any_form_based_providers_enabled?
= render 'devise/shared/tabs_ldap'
- else
- unless experiment_enabled?(:signup_flow)
= render 'devise/shared/tabs_normal'
.tab-content
- - if password_authentication_enabled_for_web? || ldap_enabled? || crowd_enabled?
+ - if password_authentication_enabled_for_web? || ldap_sign_in_enabled? || crowd_enabled?
= render 'devise/shared/signin_box'
-# Signup only makes sense if you can also sign-in
@@ -15,7 +15,7 @@
= render 'devise/shared/signup_box'
-# Show a message if none of the mechanisms above are enabled
- - if !password_authentication_enabled_for_web? && !ldap_enabled? && !(omniauth_enabled? && devise_mapping.omniauthable?)
+ - if !password_authentication_enabled_for_web? && !ldap_sign_in_enabled? && !(omniauth_enabled? && devise_mapping.omniauthable?)
%div
No authentication methods configured.
diff --git a/app/views/devise/shared/_signin_box.html.haml b/app/views/devise/shared/_signin_box.html.haml
index 746d43edbad..6ddb7e1ac48 100644
--- a/app/views/devise/shared/_signin_box.html.haml
+++ b/app/views/devise/shared/_signin_box.html.haml
@@ -1,4 +1,4 @@
-- if form_based_providers.any?
+- if any_form_based_providers_enabled?
- if crowd_enabled?
.login-box.tab-pane{ id: "crowd", role: 'tabpanel', class: active_when(form_based_auth_provider_has_active_class?(:crowd)) }
.login-body
diff --git a/app/views/devise/shared/_tabs_ldap.html.haml b/app/views/devise/shared/_tabs_ldap.html.haml
index db54c166a53..b8f0cd2a91a 100644
--- a/app/views/devise/shared/_tabs_ldap.html.haml
+++ b/app/views/devise/shared/_tabs_ldap.html.haml
@@ -1,4 +1,4 @@
-%ul.nav-links.new-session-tabs.nav-tabs.nav{ class: ('custom-provider-tabs' if form_based_providers.any?) }
+%ul.nav-links.new-session-tabs.nav-tabs.nav{ class: ('custom-provider-tabs' if any_form_based_providers_enabled?) }
- if crowd_enabled?
%li.nav-item
= link_to "Crowd", "#crowd", class: "nav-link #{active_when(form_based_auth_provider_has_active_class?(:crowd))}", 'data-toggle' => 'tab'
diff --git a/app/workers/stuck_ci_jobs_worker.rb b/app/workers/stuck_ci_jobs_worker.rb
index 5a248ab1137..b116965d105 100644
--- a/app/workers/stuck_ci_jobs_worker.rb
+++ b/app/workers/stuck_ci_jobs_worker.rb
@@ -73,5 +73,19 @@ class StuckCiJobsWorker
Gitlab::OptimisticLocking.retry_lock(build, 3) do |b|
b.drop(reason)
end
+ rescue => ex
+ build.doom!
+
+ track_exception_for_build(ex, build)
+ end
+
+ def track_exception_for_build(ex, build)
+ Gitlab::Sentry.track_acceptable_exception(ex, extra: {
+ build_id: build.id,
+ build_name: build.name,
+ build_stage: build.stage,
+ pipeline_id: build.pipeline_id,
+ project_id: build.project_id
+ })
end
end
diff --git a/changelogs/unreleased/19054-upgrade-helm.yml b/changelogs/unreleased/19054-upgrade-helm.yml
new file mode 100644
index 00000000000..cb4f887a6ed
--- /dev/null
+++ b/changelogs/unreleased/19054-upgrade-helm.yml
@@ -0,0 +1,5 @@
+---
+title: 'Updated Auto-DevOps to kubectl v1.13.12 and helm v2.15.1'
+merge_request: 19054
+author: Leo Antunes
+type: changed
diff --git a/changelogs/unreleased/fix-stuck-ci-jobs-worker.yml b/changelogs/unreleased/fix-stuck-ci-jobs-worker.yml
new file mode 100644
index 00000000000..e5e160f5743
--- /dev/null
+++ b/changelogs/unreleased/fix-stuck-ci-jobs-worker.yml
@@ -0,0 +1,5 @@
+---
+title: Properly handle exceptions in StuckCiJobsWorker
+merge_request: 19465
+author:
+type: fixed
diff --git a/changelogs/unreleased/jej-prevent-ldap-sign-in.yml b/changelogs/unreleased/jej-prevent-ldap-sign-in.yml
new file mode 100644
index 00000000000..cc4625d8b5a
--- /dev/null
+++ b/changelogs/unreleased/jej-prevent-ldap-sign-in.yml
@@ -0,0 +1,5 @@
+---
+title: Add prevent_ldap_sign_in option so LDAP can be used exclusively for sync
+merge_request: 18749
+author:
+type: added
diff --git a/changelogs/unreleased/jivanvl-add-support-heatmap-charts.yml b/changelogs/unreleased/jivanvl-add-support-heatmap-charts.yml
new file mode 100644
index 00000000000..e9a13868559
--- /dev/null
+++ b/changelogs/unreleased/jivanvl-add-support-heatmap-charts.yml
@@ -0,0 +1,5 @@
+---
+title: Add heatmap chart support
+merge_request: 32424
+author:
+type: added
diff --git a/config/gitlab.yml.example b/config/gitlab.yml.example
index 02d66067418..94fd71aaa33 100644
--- a/config/gitlab.yml.example
+++ b/config/gitlab.yml.example
@@ -494,6 +494,7 @@ production: &base
# bundle exec rake gitlab:ldap:check RAILS_ENV=production
ldap:
enabled: false
+ prevent_ldap_sign_in: false
# This setting controls the number of seconds between LDAP permission checks
# for each user. After this time has expired for a given user, their next
diff --git a/config/initializers/1_settings.rb b/config/initializers/1_settings.rb
index 7ee4a4e3610..5e94a0716fa 100644
--- a/config/initializers/1_settings.rb
+++ b/config/initializers/1_settings.rb
@@ -5,6 +5,7 @@ require_relative '../smime_signature_settings'
# Default settings
Settings['ldap'] ||= Settingslogic.new({})
Settings.ldap['enabled'] = false if Settings.ldap['enabled'].nil?
+Settings.ldap['prevent_ldap_sign_in'] = false if Settings.ldap['prevent_ldap_sign_in'].blank?
Gitlab.ee do
Settings.ldap['sync_time'] = 3600 if Settings.ldap['sync_time'].nil?
diff --git a/config/routes/user.rb b/config/routes/user.rb
index d4616c8080d..6e277f18e36 100644
--- a/config/routes/user.rb
+++ b/config/routes/user.rb
@@ -13,7 +13,7 @@ def override_omniauth(provider, controller, path_prefix = '/users/auth')
end
# Use custom controller for LDAP omniauth callback
-if Gitlab::Auth::LDAP::Config.enabled?
+if Gitlab::Auth::LDAP::Config.sign_in_enabled?
devise_scope :user do
Gitlab::Auth::LDAP::Config.available_servers.each do |server|
override_omniauth(server['provider_name'], 'ldap/omniauth_callbacks')
diff --git a/doc/administration/auth/ldap.md b/doc/administration/auth/ldap.md
index e02ce1c0a21..d449a5a72af 100644
--- a/doc/administration/auth/ldap.md
+++ b/doc/administration/auth/ldap.md
@@ -118,6 +118,7 @@ LDAP users must have an email address set, regardless of whether it is used to l
```ruby
gitlab_rails['ldap_enabled'] = true
+gitlab_rails['prevent_ldap_sign_in'] = false
gitlab_rails['ldap_servers'] = YAML.load <<-EOS # remember to close this block with 'EOS' below
##
## 'main' is the GitLab 'provider ID' of this LDAP server
@@ -357,6 +358,7 @@ production:
# snip...
ldap:
enabled: false
+ prevent_ldap_sign_in: false
servers:
##
## 'main' is the GitLab 'provider ID' of this LDAP server
@@ -493,6 +495,38 @@ 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
+
+It can be 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
+sync, while also allowing your SAML identity provider to handle additional
+checks like custom 2FA.
+
+When LDAP web sign in is disabled, users will not see a **LDAP** tab on the sign in page.
+This does not disable [using LDAP credentials for Git access](#git-password-authentication).
+
+**Omnibus configuration**
+
+1. Edit `/etc/gitlab/gitlab.rb`:
+
+ ```ruby
+ gitlab_rails['prevent_ldap_sign_in'] = true
+ ```
+
+1. [Reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure) for the changes to take effect.
+
+**Source configuration**
+
+1. Edit `config/gitlab.yaml`:
+
+ ```yaml
+ production:
+ ldap:
+ prevent_ldap_sign_in: true
+ ```
+
+1. [Restart GitLab](../restart_gitlab.md#installations-from-source) for the changes to take effect.
+
## Encryption
### TLS Server Authentication
diff --git a/doc/development/geo.md b/doc/development/geo.md
index 446d85fceed..2fb4cc710ff 100644
--- a/doc/development/geo.md
+++ b/doc/development/geo.md
@@ -101,15 +101,16 @@ it's successful, we replace the main repo with the newly cloned one.
### Uploads replication
File uploads are also being replicated to the **secondary** node. To
-track the state of syncing, the `Geo::FileRegistry` model is used.
+track the state of syncing, the `Geo::UploadRegistry` model is used.
-#### File Registry
+#### Upload Registry
Similar to the [Project Registry](#project-registry), there is a
-`Geo::FileRegistry` model that tracks the synced uploads.
+`Geo::UploadRegistry` model that tracks the synced uploads.
-CI Job Artifacts are synced in a similar way as uploads or LFS
-objects, but they are tracked by `Geo::JobArtifactRegistry` model.
+CI Job Artifacts and LFS objects are synced in a similar way as uploads,
+but they are tracked by `Geo::JobArtifactRegistry`, and `Geo::LfsObjectRegistry`
+models respectively.
#### File Download Dispatch worker
diff --git a/lib/gitlab/auth/ldap/config.rb b/lib/gitlab/auth/ldap/config.rb
index eb1d0925c55..4bc0ceedae7 100644
--- a/lib/gitlab/auth/ldap/config.rb
+++ b/lib/gitlab/auth/ldap/config.rb
@@ -21,6 +21,14 @@ module Gitlab
Gitlab.config.ldap.enabled
end
+ def self.sign_in_enabled?
+ enabled? && !prevent_ldap_sign_in?
+ end
+
+ def self.prevent_ldap_sign_in?
+ Gitlab.config.ldap.prevent_ldap_sign_in
+ end
+
def self.servers
Gitlab.config.ldap['servers']&.values || []
end
diff --git a/lib/gitlab/ci/templates/Jobs/DAST-Default-Branch-Deploy.gitlab-ci.yml b/lib/gitlab/ci/templates/Jobs/DAST-Default-Branch-Deploy.gitlab-ci.yml
index ae2ff9992f9..eff20b84e3f 100644
--- a/lib/gitlab/ci/templates/Jobs/DAST-Default-Branch-Deploy.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Jobs/DAST-Default-Branch-Deploy.gitlab-ci.yml
@@ -1,5 +1,5 @@
.auto-deploy:
- image: "registry.gitlab.com/gitlab-org/cluster-integration/auto-deploy-image:v0.1.0"
+ image: "registry.gitlab.com/gitlab-org/cluster-integration/auto-deploy-image:v0.4.0"
dast_environment_deploy:
extends: .auto-deploy
diff --git a/lib/gitlab/ci/templates/Jobs/Deploy.gitlab-ci.yml b/lib/gitlab/ci/templates/Jobs/Deploy.gitlab-ci.yml
index 6de7aace8db..a95714d5684 100644
--- a/lib/gitlab/ci/templates/Jobs/Deploy.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Jobs/Deploy.gitlab-ci.yml
@@ -1,5 +1,5 @@
.auto-deploy:
- image: "registry.gitlab.com/gitlab-org/cluster-integration/auto-deploy-image:v0.3.0"
+ image: "registry.gitlab.com/gitlab-org/cluster-integration/auto-deploy-image:v0.4.0"
review:
extends: .auto-deploy
diff --git a/lib/gitlab/kubernetes/helm.rb b/lib/gitlab/kubernetes/helm.rb
index 16ed0cb0f8e..5762c77bb95 100644
--- a/lib/gitlab/kubernetes/helm.rb
+++ b/lib/gitlab/kubernetes/helm.rb
@@ -3,8 +3,8 @@
module Gitlab
module Kubernetes
module Helm
- HELM_VERSION = '2.14.3'
- KUBECTL_VERSION = '1.11.10'
+ HELM_VERSION = '2.15.1'
+ KUBECTL_VERSION = '1.13.12'
NAMESPACE = 'gitlab-managed-apps'
SERVICE_ACCOUNT = 'tiller'
CLUSTER_ROLE_BINDING = 'tiller-admin'
diff --git a/spec/controllers/ldap/omniauth_callbacks_controller_spec.rb b/spec/controllers/ldap/omniauth_callbacks_controller_spec.rb
index 6d588c8f915..ceab9754617 100644
--- a/spec/controllers/ldap/omniauth_callbacks_controller_spec.rb
+++ b/spec/controllers/ldap/omniauth_callbacks_controller_spec.rb
@@ -11,6 +11,14 @@ describe Ldap::OmniauthCallbacksController do
expect(request.env['warden']).to be_authenticated
end
+ context 'with sign in prevented' do
+ let(:ldap_settings) { ldap_setting_defaults.merge(prevent_ldap_sign_in: true) }
+
+ it 'does not allow sign in' do
+ expect { post provider }.to raise_error(ActionController::UrlGenerationError)
+ end
+ end
+
it 'respects remember me checkbox' do
expect do
post provider, params: { remember_me: '1' }
diff --git a/spec/controllers/sessions_controller_spec.rb b/spec/controllers/sessions_controller_spec.rb
index 53847e30a5c..1e47df150b4 100644
--- a/spec/controllers/sessions_controller_spec.rb
+++ b/spec/controllers/sessions_controller_spec.rb
@@ -4,6 +4,7 @@ require 'spec_helper'
describe SessionsController do
include DeviseHelpers
+ include LdapHelpers
describe '#new' do
before do
@@ -35,6 +36,30 @@ describe SessionsController do
end
end
+ context 'with LDAP enabled' do
+ before do
+ stub_ldap_setting(enabled: true)
+ end
+
+ it 'assigns ldap_servers' do
+ get(:new)
+
+ expect(assigns[:ldap_servers].first.to_h).to include('label' => 'ldap', 'provider_name' => 'ldapmain')
+ end
+
+ context 'with sign_in disabled' do
+ before do
+ stub_ldap_setting(prevent_ldap_sign_in: true)
+ end
+
+ it 'assigns no ldap_servers' do
+ get(:new)
+
+ expect(assigns[:ldap_servers]).to eq []
+ end
+ end
+ end
+
describe 'tracking data' do
context 'when the user is part of the experimental group' do
before do
diff --git a/spec/helpers/auth_helper_spec.rb b/spec/helpers/auth_helper_spec.rb
index aae515def0c..cb7c670198d 100644
--- a/spec/helpers/auth_helper_spec.rb
+++ b/spec/helpers/auth_helper_spec.rb
@@ -54,6 +54,23 @@ describe AuthHelper do
end
end
+ describe 'any_form_based_providers_enabled?' do
+ before do
+ allow(Gitlab::Auth::LDAP::Config).to receive(:enabled?).and_return(true)
+ end
+
+ it 'detects form-based providers' do
+ allow(helper).to receive(:auth_providers) { [:twitter, :ldapmain] }
+ expect(helper.any_form_based_providers_enabled?).to be(true)
+ end
+
+ it 'ignores ldap providers when ldap web sign in is disabled' do
+ allow(helper).to receive(:auth_providers) { [:twitter, :ldapmain] }
+ allow(helper).to receive(:ldap_sign_in_enabled?).and_return(false)
+ expect(helper.any_form_based_providers_enabled?).to be(false)
+ end
+ end
+
describe 'enabled_button_based_providers' do
before do
allow(helper).to receive(:auth_providers) { [:twitter, :github] }
diff --git a/spec/javascripts/monitoring/charts/heatmap_spec.js b/spec/javascripts/monitoring/charts/heatmap_spec.js
new file mode 100644
index 00000000000..9a98fc6fb05
--- /dev/null
+++ b/spec/javascripts/monitoring/charts/heatmap_spec.js
@@ -0,0 +1,69 @@
+import { shallowMount } from '@vue/test-utils';
+import { GlHeatmap } from '@gitlab/ui/dist/charts';
+import Heatmap from '~/monitoring/components/charts/heatmap.vue';
+import { graphDataPrometheusQueryRangeMultiTrack } from '../mock_data';
+
+describe('Heatmap component', () => {
+ let heatmapChart;
+ let store;
+
+ beforeEach(() => {
+ heatmapChart = shallowMount(Heatmap, {
+ propsData: {
+ graphData: graphDataPrometheusQueryRangeMultiTrack,
+ containerWidth: 100,
+ },
+ store,
+ });
+ });
+
+ afterEach(() => {
+ heatmapChart.destroy();
+ });
+
+ describe('wrapped components', () => {
+ describe('GitLab UI heatmap chart', () => {
+ let glHeatmapChart;
+
+ beforeEach(() => {
+ glHeatmapChart = heatmapChart.find(GlHeatmap);
+ });
+
+ it('is a Vue instance', () => {
+ expect(glHeatmapChart.isVueInstance()).toBe(true);
+ });
+
+ it('should display a label on the x axis', () => {
+ expect(heatmapChart.vm.xAxisName).toBe(graphDataPrometheusQueryRangeMultiTrack.x_label);
+ });
+
+ it('should display a label on the y axis', () => {
+ expect(heatmapChart.vm.yAxisName).toBe(graphDataPrometheusQueryRangeMultiTrack.y_label);
+ });
+
+ // According to the echarts docs https://echarts.apache.org/en/option.html#series-heatmap.data
+ // each row of the heatmap chart is represented by an array inside another parent array
+ // e.g. [[0, 0, 10]], the format represents the column, the row and finally the value
+ // corresponding to the cell
+
+ it('should return chartData with a length of x by y, with a length of 3 per array', () => {
+ const row = heatmapChart.vm.chartData[0];
+
+ expect(row.length).toBe(3);
+ expect(heatmapChart.vm.chartData.length).toBe(30);
+ });
+
+ it('returns a series of labels for the x axis', () => {
+ const { xAxisLabels } = heatmapChart.vm;
+
+ expect(xAxisLabels.length).toBe(5);
+ });
+
+ it('returns a series of labels for the y axis', () => {
+ const { yAxisLabels } = heatmapChart.vm;
+
+ expect(yAxisLabels.length).toBe(6);
+ });
+ });
+ });
+});
diff --git a/spec/javascripts/monitoring/mock_data.js b/spec/javascripts/monitoring/mock_data.js
index 6f9a2a34ef5..4d63f91f658 100644
--- a/spec/javascripts/monitoring/mock_data.js
+++ b/spec/javascripts/monitoring/mock_data.js
@@ -1013,3 +1013,82 @@ export const graphDataPrometheusQueryRange = {
},
],
};
+
+export const graphDataPrometheusQueryRangeMultiTrack = {
+ title: 'Super Chart A3',
+ type: 'heatmap',
+ weight: 3,
+ x_label: 'Status Code',
+ y_label: 'Time',
+ metrics: [],
+ queries: [
+ {
+ metricId: '1',
+ id: 'response_metrics_nginx_ingress_throughput_status_code',
+ query_range:
+ 'sum(rate(nginx_upstream_responses_total{upstream=~"%{kube_namespace}-%{ci_environment_slug}-.*"}[60m])) by (status_code)',
+ unit: 'req / sec',
+ label: 'Status Code',
+ metric_id: 1,
+ prometheus_endpoint_path:
+ '/root/rails_nodb/environments/3/prometheus/api/v1/query_range?query=sum%28rate%28nginx_upstream_responses_total%7Bupstream%3D~%22%25%7Bkube_namespace%7D-%25%7Bci_environment_slug%7D-.%2A%22%7D%5B2m%5D%29%29+by+%28status_code%29',
+ result: [
+ {
+ metric: { status_code: '1xx' },
+ values: [
+ ['2019-08-30T15:00:00.000Z', 0],
+ ['2019-08-30T16:00:00.000Z', 2],
+ ['2019-08-30T17:00:00.000Z', 0],
+ ['2019-08-30T18:00:00.000Z', 0],
+ ['2019-08-30T19:00:00.000Z', 0],
+ ['2019-08-30T20:00:00.000Z', 3],
+ ],
+ },
+ {
+ metric: { status_code: '2xx' },
+ values: [
+ ['2019-08-30T15:00:00.000Z', 1],
+ ['2019-08-30T16:00:00.000Z', 3],
+ ['2019-08-30T17:00:00.000Z', 6],
+ ['2019-08-30T18:00:00.000Z', 10],
+ ['2019-08-30T19:00:00.000Z', 8],
+ ['2019-08-30T20:00:00.000Z', 6],
+ ],
+ },
+ {
+ metric: { status_code: '3xx' },
+ values: [
+ ['2019-08-30T15:00:00.000Z', 1],
+ ['2019-08-30T16:00:00.000Z', 2],
+ ['2019-08-30T17:00:00.000Z', 3],
+ ['2019-08-30T18:00:00.000Z', 3],
+ ['2019-08-30T19:00:00.000Z', 2],
+ ['2019-08-30T20:00:00.000Z', 1],
+ ],
+ },
+ {
+ metric: { status_code: '4xx' },
+ values: [
+ ['2019-08-30T15:00:00.000Z', 2],
+ ['2019-08-30T16:00:00.000Z', 0],
+ ['2019-08-30T17:00:00.000Z', 0],
+ ['2019-08-30T18:00:00.000Z', 2],
+ ['2019-08-30T19:00:00.000Z', 0],
+ ['2019-08-30T20:00:00.000Z', 2],
+ ],
+ },
+ {
+ metric: { status_code: '5xx' },
+ values: [
+ ['2019-08-30T15:00:00.000Z', 0],
+ ['2019-08-30T16:00:00.000Z', 1],
+ ['2019-08-30T17:00:00.000Z', 0],
+ ['2019-08-30T18:00:00.000Z', 0],
+ ['2019-08-30T19:00:00.000Z', 0],
+ ['2019-08-30T20:00:00.000Z', 2],
+ ],
+ },
+ ],
+ },
+ ],
+};
diff --git a/spec/javascripts/monitoring/shared/prometheus_header_spec.js b/spec/javascripts/monitoring/shared/prometheus_header_spec.js
new file mode 100644
index 00000000000..9f916a4dfbb
--- /dev/null
+++ b/spec/javascripts/monitoring/shared/prometheus_header_spec.js
@@ -0,0 +1,26 @@
+import { shallowMount } from '@vue/test-utils';
+import PrometheusHeader from '~/monitoring/components/shared/prometheus_header.vue';
+
+describe('Prometheus Header component', () => {
+ let prometheusHeader;
+
+ beforeEach(() => {
+ prometheusHeader = shallowMount(PrometheusHeader, {
+ propsData: {
+ graphTitle: 'graph header',
+ },
+ });
+ });
+
+ afterEach(() => {
+ prometheusHeader.destroy();
+ });
+
+ describe('Prometheus header component', () => {
+ it('should show a title', () => {
+ const title = prometheusHeader.vm.$el.querySelector('.js-graph-title').textContent;
+
+ expect(title).toBe('graph header');
+ });
+ });
+});
diff --git a/spec/lib/gitlab/auth/ldap/config_spec.rb b/spec/lib/gitlab/auth/ldap/config_spec.rb
index 577dfe51949..e4a90d4018d 100644
--- a/spec/lib/gitlab/auth/ldap/config_spec.rb
+++ b/spec/lib/gitlab/auth/ldap/config_spec.rb
@@ -535,4 +535,23 @@ AtlErSqafbECNDSwS5BX8yDpu5yRBJ4xegO/rNlmb8ICRYkuJapD1xXicFOsmfUK
end
end
end
+
+ describe 'sign_in_enabled?' do
+ using RSpec::Parameterized::TableSyntax
+
+ where(:enabled, :prevent_ldap_sign_in, :result) do
+ true | false | true
+ 'true' | false | true
+ true | true | false
+ false | nil | false
+ end
+
+ with_them do
+ it do
+ stub_ldap_setting(enabled: enabled, prevent_ldap_sign_in: prevent_ldap_sign_in)
+
+ expect(described_class.sign_in_enabled?).to eq(result)
+ end
+ end
+ end
end
diff --git a/spec/lib/gitlab/kubernetes/helm/pod_spec.rb b/spec/lib/gitlab/kubernetes/helm/pod_spec.rb
index 64cadcc011c..0bba9d6e858 100644
--- a/spec/lib/gitlab/kubernetes/helm/pod_spec.rb
+++ b/spec/lib/gitlab/kubernetes/helm/pod_spec.rb
@@ -30,7 +30,7 @@ describe Gitlab::Kubernetes::Helm::Pod do
it 'generates the appropriate specifications for the container' do
container = subject.generate.spec.containers.first
expect(container.name).to eq('helm')
- expect(container.image).to eq('registry.gitlab.com/gitlab-org/cluster-integration/helm-install-image/releases/2.14.3-kube-1.11.10')
+ expect(container.image).to eq('registry.gitlab.com/gitlab-org/cluster-integration/helm-install-image/releases/2.15.1-kube-1.13.12')
expect(container.env.count).to eq(3)
expect(container.env.map(&:name)).to match_array([:HELM_VERSION, :TILLER_NAMESPACE, :COMMAND_SCRIPT])
expect(container.command).to match_array(["/bin/sh"])
diff --git a/spec/routing/routing_spec.rb b/spec/routing/routing_spec.rb
index e8333232b90..6f67cdb1222 100644
--- a/spec/routing/routing_spec.rb
+++ b/spec/routing/routing_spec.rb
@@ -277,6 +277,33 @@ describe "Authentication", "routing" do
it "PUT /users/password" do
expect(put("/users/password")).to route_to('passwords#update')
end
+
+ context 'with LDAP configured' do
+ include LdapHelpers
+
+ let(:ldap_settings) { { enabled: true } }
+
+ before do
+ stub_ldap_setting(ldap_settings)
+ Rails.application.reload_routes!
+ end
+
+ after(:all) do
+ Rails.application.reload_routes!
+ end
+
+ it 'POST /users/auth/ldapmain/callback' do
+ expect(post("/users/auth/ldapmain/callback")).to route_to('ldap/omniauth_callbacks#ldapmain')
+ end
+
+ context 'with LDAP sign-in disabled' do
+ let(:ldap_settings) { { enabled: true, prevent_ldap_sign_in: true } }
+
+ it 'prevents POST /users/auth/ldapmain/callback' do
+ expect(post("/users/auth/ldapmain/callback")).not_to be_routable
+ end
+ end
+ end
end
describe HealthCheckController, 'routing' do
diff --git a/spec/support/controllers/ldap_omniauth_callbacks_controller_shared_context.rb b/spec/support/controllers/ldap_omniauth_callbacks_controller_shared_context.rb
index d636c1cf6cd..8a8a2f714bc 100644
--- a/spec/support/controllers/ldap_omniauth_callbacks_controller_shared_context.rb
+++ b/spec/support/controllers/ldap_omniauth_callbacks_controller_shared_context.rb
@@ -10,6 +10,8 @@ shared_context 'Ldap::OmniauthCallbacksController' do
let(:provider) { 'ldapmain' }
let(:valid_login?) { true }
let(:user) { create(:omniauth_user, extern_uid: uid, provider: provider) }
+ let(:ldap_setting_defaults) { { enabled: true, servers: ldap_server_config } }
+ let(:ldap_settings) { ldap_setting_defaults }
let(:ldap_server_config) do
{ main: ldap_config_defaults(:main) }
end
@@ -23,7 +25,7 @@ shared_context 'Ldap::OmniauthCallbacksController' do
end
before do
- stub_ldap_setting(enabled: true, servers: ldap_server_config)
+ stub_ldap_setting(ldap_settings)
described_class.define_providers!
Rails.application.reload_routes!
@@ -36,4 +38,8 @@ shared_context 'Ldap::OmniauthCallbacksController' do
after do
Rails.application.env_config['omniauth.auth'] = @original_env_config_omniauth_auth
end
+
+ after(:all) do
+ Rails.application.reload_routes!
+ end
end
diff --git a/spec/views/devise/sessions/new.html.haml_spec.rb b/spec/views/devise/sessions/new.html.haml_spec.rb
new file mode 100644
index 00000000000..66afc2af7ce
--- /dev/null
+++ b/spec/views/devise/sessions/new.html.haml_spec.rb
@@ -0,0 +1,71 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe 'devise/sessions/new' do
+ describe 'ldap' do
+ include LdapHelpers
+
+ let(:server) { { provider_name: 'ldapmain', label: 'LDAP' }.with_indifferent_access }
+
+ before do
+ enable_ldap
+ stub_devise
+ disable_captcha
+ disable_sign_up
+ disable_other_signin_methods
+
+ allow(view).to receive(:experiment_enabled?).and_return(false)
+ end
+
+ it 'is shown when enabled' do
+ render
+
+ expect(rendered).to have_selector('.new-session-tabs')
+ expect(rendered).to have_selector('[data-qa-selector="ldap_tab"]')
+ expect(rendered).to have_field('LDAP Username')
+ end
+
+ it 'is not shown when LDAP sign in is disabled' do
+ disable_ldap_sign_in
+
+ render
+
+ expect(rendered).to have_content('No authentication methods configured')
+ expect(rendered).not_to have_selector('[data-qa-selector="ldap_tab"]')
+ expect(rendered).not_to have_field('LDAP Username')
+ end
+ end
+
+ def disable_other_signin_methods
+ allow(view).to receive(:password_authentication_enabled_for_web?).and_return(false)
+ allow(view).to receive(:omniauth_enabled?).and_return(false)
+ end
+
+ def disable_sign_up
+ allow(view).to receive(:allow_signup?).and_return(false)
+ end
+
+ def stub_devise
+ allow(view).to receive(:devise_mapping).and_return(Devise.mappings[:user])
+ allow(view).to receive(:resource).and_return(spy)
+ allow(view).to receive(:resource_name).and_return(:user)
+ end
+
+ def enable_ldap
+ stub_ldap_setting(enabled: true)
+ assign(:ldap_servers, [server])
+ allow(view).to receive(:form_based_providers).and_return([:ldapmain])
+ allow(view).to receive(:omniauth_callback_path).with(:user, 'ldapmain').and_return('/ldapmain')
+ end
+
+ def disable_ldap_sign_in
+ allow(view).to receive(:ldap_sign_in_enabled?).and_return(false)
+ assign(:ldap_servers, [])
+ end
+
+ def disable_captcha
+ allow(view).to receive(:captcha_enabled?).and_return(false)
+ allow(view).to receive(:captcha_on_login_required?).and_return(false)
+ end
+end
diff --git a/spec/workers/stuck_ci_jobs_worker_spec.rb b/spec/workers/stuck_ci_jobs_worker_spec.rb
index c3d577e2dae..59707409b5a 100644
--- a/spec/workers/stuck_ci_jobs_worker_spec.rb
+++ b/spec/workers/stuck_ci_jobs_worker_spec.rb
@@ -18,15 +18,30 @@ describe StuckCiJobsWorker do
end
shared_examples 'job is dropped' do
- before do
+ it "changes status" do
worker.perform
job.reload
- end
- it "changes status" do
expect(job).to be_failed
expect(job).to be_stuck_or_timeout_failure
end
+
+ context 'when job have data integrity problem' do
+ it "does drop the job and logs the reason" do
+ job.update_columns(yaml_variables: '[{"key" => "value"}]')
+
+ expect(Gitlab::Sentry).to receive(:track_acceptable_exception)
+ .with(anything, a_hash_including(extra: a_hash_including(build_id: job.id)))
+ .once
+ .and_call_original
+
+ worker.perform
+ job.reload
+
+ expect(job).to be_failed
+ expect(job).to be_data_integrity_failure
+ end
+ end
end
shared_examples 'job is unchanged' do