Commit d572f776 authored by GitLab Bot's avatar GitLab Bot

Automatic merge of gitlab-org/gitlab master

parents d26644db f6563235
...@@ -237,6 +237,7 @@ class Admin::ApplicationSettingsController < Admin::ApplicationController ...@@ -237,6 +237,7 @@ class Admin::ApplicationSettingsController < Admin::ApplicationController
[ [
*::ApplicationSettingsHelper.visible_attributes, *::ApplicationSettingsHelper.visible_attributes,
*::ApplicationSettingsHelper.external_authorization_service_attributes, *::ApplicationSettingsHelper.external_authorization_service_attributes,
*ApplicationSetting.repository_storages_weighted_attributes,
*ApplicationSetting.kroki_formats_attributes.keys.map { |key| "kroki_formats_#{key}".to_sym }, *ApplicationSetting.kroki_formats_attributes.keys.map { |key| "kroki_formats_#{key}".to_sym },
:lets_encrypt_notification_email, :lets_encrypt_notification_email,
:lets_encrypt_terms_of_service_accepted, :lets_encrypt_terms_of_service_accepted,
...@@ -247,8 +248,8 @@ class Admin::ApplicationSettingsController < Admin::ApplicationController ...@@ -247,8 +248,8 @@ class Admin::ApplicationSettingsController < Admin::ApplicationController
:default_branch_name, :default_branch_name,
disabled_oauth_sign_in_sources: [], disabled_oauth_sign_in_sources: [],
import_sources: [], import_sources: [],
restricted_visibility_levels: [], repository_storages: [],
repository_storages_weighted: {} restricted_visibility_levels: []
] ]
end end
......
...@@ -37,8 +37,13 @@ module ApplicationSettingsHelper ...@@ -37,8 +37,13 @@ module ApplicationSettingsHelper
end end
def storage_weights def storage_weights
Gitlab.config.repositories.storages.keys.each_with_object(OpenStruct.new) do |storage, weights| ApplicationSetting.repository_storages_weighted_attributes.map do |attribute|
weights[storage.to_sym] = @application_setting.repository_storages_weighted[storage] || 0 storage = attribute.to_s.delete_prefix('repository_storages_weighted_')
{
name: attribute,
label: storage,
value: @application_setting.repository_storages_weighted[storage] || 0
}
end end
end end
......
...@@ -25,6 +25,10 @@ class ApplicationSetting < ApplicationRecord ...@@ -25,6 +25,10 @@ class ApplicationSetting < ApplicationRecord
alias_attribute :instance_group_id, :instance_administrators_group_id alias_attribute :instance_group_id, :instance_administrators_group_id
alias_attribute :instance_administrators_group, :instance_group alias_attribute :instance_administrators_group, :instance_group
def self.repository_storages_weighted_attributes
@repository_storages_weighted_atributes ||= Gitlab.config.repositories.storages.keys.map { |k| "repository_storages_weighted_#{k}".to_sym }.freeze
end
def self.kroki_formats_attributes def self.kroki_formats_attributes
{ {
blockdiag: { blockdiag: {
...@@ -40,6 +44,7 @@ class ApplicationSetting < ApplicationRecord ...@@ -40,6 +44,7 @@ class ApplicationSetting < ApplicationRecord
end end
store_accessor :kroki_formats, *ApplicationSetting.kroki_formats_attributes.keys, prefix: true store_accessor :kroki_formats, *ApplicationSetting.kroki_formats_attributes.keys, prefix: true
store_accessor :repository_storages_weighted, *Gitlab.config.repositories.storages.keys, prefix: true
# Include here so it can override methods from # Include here so it can override methods from
# `add_authentication_token_field` # `add_authentication_token_field`
...@@ -498,7 +503,6 @@ class ApplicationSetting < ApplicationRecord ...@@ -498,7 +503,6 @@ class ApplicationSetting < ApplicationRecord
inclusion: { in: [true, false], message: _('must be a boolean value') } inclusion: { in: [true, false], message: _('must be a boolean value') }
before_validation :ensure_uuid! before_validation :ensure_uuid!
before_validation :coerce_repository_storages_weighted, if: :repository_storages_weighted_changed?
before_save :ensure_runners_registration_token before_save :ensure_runners_registration_token
before_save :ensure_health_check_access_token before_save :ensure_health_check_access_token
...@@ -579,6 +583,12 @@ class ApplicationSetting < ApplicationRecord ...@@ -579,6 +583,12 @@ class ApplicationSetting < ApplicationRecord
recaptcha_enabled || login_recaptcha_protection_enabled recaptcha_enabled || login_recaptcha_protection_enabled
end end
repository_storages_weighted_attributes.each do |attribute|
define_method :"#{attribute}=" do |value|
super(value.to_i)
end
end
kroki_formats_attributes.keys.each do |key| kroki_formats_attributes.keys.each do |key|
define_method :"kroki_formats_#{key}=" do |value| define_method :"kroki_formats_#{key}=" do |value|
super(::Gitlab::Utils.to_boolean(value)) super(::Gitlab::Utils.to_boolean(value))
......
...@@ -298,6 +298,10 @@ module ApplicationSettingImplementation ...@@ -298,6 +298,10 @@ module ApplicationSettingImplementation
Array(read_attribute(:repository_storages)) Array(read_attribute(:repository_storages))
end end
def repository_storages_weighted
read_attribute(:repository_storages_weighted)
end
def commit_email_hostname def commit_email_hostname
super.presence || self.class.default_commit_email_hostname super.presence || self.class.default_commit_email_hostname
end end
...@@ -329,10 +333,9 @@ module ApplicationSettingImplementation ...@@ -329,10 +333,9 @@ module ApplicationSettingImplementation
def normalized_repository_storage_weights def normalized_repository_storage_weights
strong_memoize(:normalized_repository_storage_weights) do strong_memoize(:normalized_repository_storage_weights) do
repository_storages_weights = repository_storages_weighted.slice(*Gitlab.config.repositories.storages.keys) weights_total = repository_storages_weighted.values.reduce(:+)
weights_total = repository_storages_weights.values.reduce(:+)
repository_storages_weights.transform_values do |w| repository_storages_weighted.transform_values do |w|
next w if weights_total == 0 next w if weights_total == 0
w.to_f / weights_total w.to_f / weights_total
...@@ -470,20 +473,16 @@ module ApplicationSettingImplementation ...@@ -470,20 +473,16 @@ module ApplicationSettingImplementation
invalid.empty? invalid.empty?
end end
def coerce_repository_storages_weighted
repository_storages_weighted.transform_values!(&:to_i)
end
def check_repository_storages_weighted def check_repository_storages_weighted
invalid = repository_storages_weighted.keys - Gitlab.config.repositories.storages.keys invalid = repository_storages_weighted.keys - Gitlab.config.repositories.storages.keys
errors.add(:repository_storages_weighted, _("can't include: %{invalid_storages}") % { invalid_storages: invalid.join(", ") }) unless errors.add(:repository_storages_weighted, "can't include: %{invalid_storages}" % { invalid_storages: invalid.join(", ") }) unless
invalid.empty? invalid.empty?
repository_storages_weighted.each do |key, val| repository_storages_weighted.each do |key, val|
next unless val.present? next unless val.present?
errors.add(:repository_storages_weighted, _("value for '%{storage}' must be an integer") % { storage: key }) unless val.is_a?(Integer) errors.add(:"repository_storages_weighted_#{key}", "value must be an integer") unless val.is_a?(Integer)
errors.add(:repository_storages_weighted, _("value for '%{storage}' must be between 0 and 100") % { storage: key }) unless val.between?(0, 100) errors.add(:"repository_storages_weighted_#{key}", "value must be between 0 and 100") unless val.between?(0, 100)
end end
end end
......
...@@ -18,9 +18,8 @@ ...@@ -18,9 +18,8 @@
= _('Enter weights for storages for new repositories.') = _('Enter weights for storages for new repositories.')
= link_to sprite_icon('question-o'), help_page_path('administration/repository_storage_paths') = link_to sprite_icon('question-o'), help_page_path('administration/repository_storage_paths')
.form-check .form-check
= f.fields_for :repository_storages_weighted, storage_weights do |storage_form| - storage_weights.each do |attribute|
- Gitlab.config.repositories.storages.keys.each do |storage| = f.text_field attribute[:name], class: 'form-text-input', value: attribute[:value]
= storage_form.text_field storage, class: 'form-text-input' = f.label attribute[:label], attribute[:label], class: 'label-bold form-check-label'
= storage_form.label storage, storage, class: 'label-bold form-check-label' %br
%br
= f.submit _('Save changes'), class: "gl-button btn btn-success qa-save-changes-button" = f.submit _('Save changes'), class: "gl-button btn btn-success qa-save-changes-button"
---
title: Allow saving repository weights after a storage has been removed
merge_request: 53803
author:
type: fixed
...@@ -140,13 +140,11 @@ To create and add a new Kubernetes cluster to your project, group, or instance: ...@@ -140,13 +140,11 @@ To create and add a new Kubernetes cluster to your project, group, or instance:
1. Click **Review policy**. 1. Click **Review policy**.
1. Enter a suitable name for this policy, and click **Create Policy**. You can now close this window. 1. Enter a suitable name for this policy, and click **Create Policy**. You can now close this window.
1. In the [IAM Management Console](https://console.aws.amazon.com/iam/home), create an EKS management IAM role. 1. In the [IAM Management Console](https://console.aws.amazon.com/iam/home), create an **EKS IAM role** following the [Amazon EKS cluster IAM role instructions](https://docs.aws.amazon.com/eks/latest/userguide/service_IAM_role.html). This role should exist so that Kubernetes clusters managed by Amazon EKS can make calls to other AWS services on your behalf to manage the resources that you use with the service.
To do so, follow the [Amazon EKS cluster IAM role](https://docs.aws.amazon.com/eks/latest/userguide/service_IAM_role.html) instructions
to create a IAM role suitable for managing the AWS EKS cluster's resources on your behalf.
In addition to the policies that guide suggests, you must also include the `AmazonEKSClusterPolicy` In addition to the policies that guide suggests, you must also include the `AmazonEKSClusterPolicy`
policy for this role in order for GitLab to manage the EKS cluster correctly. policy for this role in order for GitLab to manage the EKS cluster correctly.
1. In the [IAM Management Console](https://console.aws.amazon.com/iam/home), create an IAM role: 1. In the [IAM Management Console](https://console.aws.amazon.com/iam/home), create another IAM role which will be used by GitLab to authenticate with AWS. Follow these steps to create it:
1. From the left panel, select **Roles**. 1. On the AWS IAM console, select **Roles** from the left panel.
1. Click **Create role**. 1. Click **Create role**.
1. Under `Select type of trusted entity`, select **Another AWS account**. 1. Under `Select type of trusted entity`, select **Another AWS account**.
1. Enter the Account ID from GitLab into the `Account ID` field. 1. Enter the Account ID from GitLab into the `Account ID` field.
......
...@@ -34923,9 +34923,6 @@ msgstr "" ...@@ -34923,9 +34923,6 @@ msgstr ""
msgid "can't be enabled because signed commits are required for this project" msgid "can't be enabled because signed commits are required for this project"
msgstr "" msgstr ""
msgid "can't include: %{invalid_storages}"
msgstr ""
msgid "cannot be a date in the past" msgid "cannot be a date in the past"
msgstr "" msgstr ""
...@@ -36332,12 +36329,6 @@ msgstr "" ...@@ -36332,12 +36329,6 @@ msgstr ""
msgid "v%{version} published %{timeAgo}" msgid "v%{version} published %{timeAgo}"
msgstr "" msgstr ""
msgid "value for '%{storage}' must be an integer"
msgstr ""
msgid "value for '%{storage}' must be between 0 and 100"
msgstr ""
msgid "verify ownership" msgid "verify ownership"
msgstr "" msgstr ""
......
...@@ -144,10 +144,10 @@ RSpec.describe Admin::ApplicationSettingsController do ...@@ -144,10 +144,10 @@ RSpec.describe Admin::ApplicationSettingsController do
end end
it 'updates repository_storages_weighted setting' do it 'updates repository_storages_weighted setting' do
put :update, params: { application_setting: { repository_storages_weighted: { default: 75 } } } put :update, params: { application_setting: { repository_storages_weighted_default: 75 } }
expect(response).to redirect_to(general_admin_application_settings_path) expect(response).to redirect_to(general_admin_application_settings_path)
expect(ApplicationSetting.current.repository_storages_weighted).to eq('default' => 75) expect(ApplicationSetting.current.repository_storages_weighted_default).to eq(75)
end end
it 'updates kroki_formats setting' do it 'updates kroki_formats setting' do
......
...@@ -384,20 +384,7 @@ RSpec.describe 'Admin updates settings' do ...@@ -384,20 +384,7 @@ RSpec.describe 'Admin updates settings' do
click_button 'Save changes' click_button 'Save changes'
end end
expect(current_settings.repository_storages_weighted).to eq('default' => 50) expect(current_settings.repository_storages_weighted_default).to be 50
end
it 'still saves when settings are outdated' do
current_settings.update_attribute :repository_storages_weighted, { 'default' => 100, 'outdated' => 100 }
visit repository_admin_application_settings_path
page.within('.as-repository-storage') do
fill_in 'application_setting_repository_storages_weighted_default', with: 50
click_button 'Save changes'
end
expect(current_settings.repository_storages_weighted).to eq('default' => 50)
end end
end end
......
...@@ -130,15 +130,20 @@ RSpec.describe ApplicationSettingsHelper do ...@@ -130,15 +130,20 @@ RSpec.describe ApplicationSettingsHelper do
before do before do
helper.instance_variable_set(:@application_setting, application_setting) helper.instance_variable_set(:@application_setting, application_setting)
stub_storage_settings({ 'default': {}, 'storage_1': {}, 'storage_2': {} }) stub_storage_settings({ 'default': {}, 'storage_1': {}, 'storage_2': {} })
allow(ApplicationSetting).to receive(:repository_storages_weighted_attributes).and_return(
[:repository_storages_weighted_default,
:repository_storages_weighted_storage_1,
:repository_storages_weighted_storage_2])
stub_application_setting(repository_storages_weighted: { 'default' => 100, 'storage_1' => 50, 'storage_2' => nil }) stub_application_setting(repository_storages_weighted: { 'default' => 100, 'storage_1' => 50, 'storage_2' => nil })
end end
it 'returns storages correctly' do it 'returns storages correctly' do
expect(helper.storage_weights).to eq(OpenStruct.new( expect(helper.storage_weights).to eq([
default: 100, { name: :repository_storages_weighted_default, label: 'default', value: 100 },
storage_1: 50, { name: :repository_storages_weighted_storage_1, label: 'storage_1', value: 50 },
storage_2: 0 { name: :repository_storages_weighted_storage_2, label: 'storage_2', value: 0 }
)) ])
end end
end end
......
...@@ -105,14 +105,14 @@ RSpec.describe ApplicationSetting do ...@@ -105,14 +105,14 @@ RSpec.describe ApplicationSetting do
it { is_expected.not_to allow_value(false).for(:hashed_storage_enabled) } it { is_expected.not_to allow_value(false).for(:hashed_storage_enabled) }
it { is_expected.to allow_value('default' => 0).for(:repository_storages_weighted) } it { is_expected.not_to allow_value(101).for(:repository_storages_weighted_default) }
it { is_expected.to allow_value('default' => 50).for(:repository_storages_weighted) } it { is_expected.to allow_value('90').for(:repository_storages_weighted_default) }
it { is_expected.to allow_value('default' => 100).for(:repository_storages_weighted) } it { is_expected.not_to allow_value(-1).for(:repository_storages_weighted_default) }
it { is_expected.to allow_value('default' => '90').for(:repository_storages_weighted) } it { is_expected.to allow_value(100).for(:repository_storages_weighted_default) }
it { is_expected.to allow_value('default' => nil).for(:repository_storages_weighted) } it { is_expected.to allow_value(0).for(:repository_storages_weighted_default) }
it { is_expected.not_to allow_value('default' => -1).for(:repository_storages_weighted).with_message("value for 'default' must be between 0 and 100") } it { is_expected.to allow_value(50).for(:repository_storages_weighted_default) }
it { is_expected.not_to allow_value('default' => 101).for(:repository_storages_weighted).with_message("value for 'default' must be between 0 and 100") } it { is_expected.to allow_value(nil).for(:repository_storages_weighted_default) }
it { is_expected.not_to allow_value('default' => 100, shouldntexist: 50).for(:repository_storages_weighted).with_message("can't include: shouldntexist") } it { is_expected.not_to allow_value({ default: 100, shouldntexist: 50 }).for(:repository_storages_weighted) }
it { is_expected.to allow_value(400).for(:notes_create_limit) } it { is_expected.to allow_value(400).for(:notes_create_limit) }
it { is_expected.not_to allow_value('two').for(:notes_create_limit) } it { is_expected.not_to allow_value('two').for(:notes_create_limit) }
...@@ -984,6 +984,12 @@ RSpec.describe ApplicationSetting do ...@@ -984,6 +984,12 @@ RSpec.describe ApplicationSetting do
it_behaves_like 'application settings examples' it_behaves_like 'application settings examples'
describe 'repository_storages_weighted_attributes' do
it 'returns the keys for repository_storages_weighted' do
expect(subject.class.repository_storages_weighted_attributes).to eq([:repository_storages_weighted_default])
end
end
describe 'kroki_format_supported?' do describe 'kroki_format_supported?' do
it 'returns true when Excalidraw is enabled' do it 'returns true when Excalidraw is enabled' do
subject.kroki_formats_excalidraw = true subject.kroki_formats_excalidraw = true
...@@ -1027,4 +1033,11 @@ RSpec.describe ApplicationSetting do ...@@ -1027,4 +1033,11 @@ RSpec.describe ApplicationSetting do
expect(subject.kroki_formats_excalidraw).to eq(true) expect(subject.kroki_formats_excalidraw).to eq(true)
end end
end end
it 'does not allow to set weight for non existing storage' do
setting.repository_storages_weighted = { invalid_storage: 100 }
expect(setting).not_to be_valid
expect(setting.errors.messages[:repository_storages_weighted]).to match_array(["can't include: invalid_storage"])
end
end end
...@@ -289,7 +289,6 @@ RSpec.shared_examples 'application settings examples' do ...@@ -289,7 +289,6 @@ RSpec.shared_examples 'application settings examples' do
describe '#pick_repository_storage' do describe '#pick_repository_storage' do
before do before do
allow(Gitlab.config.repositories.storages).to receive(:keys).and_return(%w(default backup))
allow(setting).to receive(:repository_storages_weighted).and_return({ 'default' => 20, 'backup' => 80 }) allow(setting).to receive(:repository_storages_weighted).and_return({ 'default' => 20, 'backup' => 80 })
end end
...@@ -305,19 +304,15 @@ RSpec.shared_examples 'application settings examples' do ...@@ -305,19 +304,15 @@ RSpec.shared_examples 'application settings examples' do
describe '#normalized_repository_storage_weights' do describe '#normalized_repository_storage_weights' do
using RSpec::Parameterized::TableSyntax using RSpec::Parameterized::TableSyntax
where(:config_storages, :storages, :normalized) do where(:storages, :normalized) do
%w(default backup) | { 'default' => 0, 'backup' => 100 } | { 'default' => 0.0, 'backup' => 1.0 } { 'default' => 0, 'backup' => 100 } | { 'default' => 0.0, 'backup' => 1.0 }
%w(default backup) | { 'default' => 100, 'backup' => 100 } | { 'default' => 0.5, 'backup' => 0.5 } { 'default' => 100, 'backup' => 100 } | { 'default' => 0.5, 'backup' => 0.5 }
%w(default backup) | { 'default' => 20, 'backup' => 80 } | { 'default' => 0.2, 'backup' => 0.8 } { 'default' => 20, 'backup' => 80 } | { 'default' => 0.2, 'backup' => 0.8 }
%w(default backup) | { 'default' => 0, 'backup' => 0 } | { 'default' => 0.0, 'backup' => 0.0 } { 'default' => 0, 'backup' => 0 } | { 'default' => 0.0, 'backup' => 0.0 }
%w(default) | { 'default' => 0, 'backup' => 100 } | { 'default' => 0.0 }
%w(default) | { 'default' => 100, 'backup' => 100 } | { 'default' => 1.0 }
%w(default) | { 'default' => 20, 'backup' => 80 } | { 'default' => 1.0 }
end end
with_them do with_them do
before do before do
allow(Gitlab.config.repositories.storages).to receive(:keys).and_return(config_storages)
allow(setting).to receive(:repository_storages_weighted).and_return(storages) allow(setting).to receive(:repository_storages_weighted).and_return(storages)
end end
......
...@@ -3,49 +3,34 @@ ...@@ -3,49 +3,34 @@
require 'spec_helper' require 'spec_helper'
RSpec.describe 'admin/application_settings/_repository_storage.html.haml' do RSpec.describe 'admin/application_settings/_repository_storage.html.haml' do
let(:app_settings) { build(:application_setting, repository_storages_weighted: repository_storages_weighted) } let(:app_settings) { create(:application_setting) }
let(:repository_storages_weighted_attributes) { [:repository_storages_weighted_default, :repository_storages_weighted_mepmep, :repository_storages_weighted_foobar]}
let(:repository_storages_weighted) do
{
"default" => 100,
"mepmep" => 50
}
end
before do before do
stub_storage_settings({ 'default': {}, 'mepmep': {}, 'foobar': {} }) allow(app_settings).to receive(:repository_storages_weighted).and_return(repository_storages_weighted)
allow(app_settings).to receive(:repository_storages_weighted_mepmep).and_return(100)
allow(app_settings).to receive(:repository_storages_weighted_foobar).and_return(50)
assign(:application_setting, app_settings) assign(:application_setting, app_settings)
allow(ApplicationSetting).to receive(:repository_storages_weighted_attributes).and_return(repository_storages_weighted_attributes)
end end
context 'additional storage config' do context 'when multiple storages are available' do
let(:repository_storages_weighted) do
{
'default' => 100,
'mepmep' => 50
}
end
it 'lists them all' do it 'lists them all' do
render render
Gitlab.config.repositories.storages.keys.each do |storage_name| # lists storages that are saved with weights
repository_storages_weighted.each do |storage_name, storage_weight|
expect(rendered).to have_content(storage_name) expect(rendered).to have_content(storage_name)
end end
# lists storage not saved with weight
expect(rendered).to have_content('foobar') expect(rendered).to have_content('foobar')
end end
end end
context 'fewer storage configs' do
let(:repository_storages_weighted) do
{
'default' => 100,
'mepmep' => 50,
'something_old' => 100
}
end
it 'lists only configured storages' do
render
Gitlab.config.repositories.storages.keys.each do |storage_name|
expect(rendered).to have_content(storage_name)
end
expect(rendered).not_to have_content('something_old')
end
end
end end
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