Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
1f992463a9
commit
e39b6277eb
54 changed files with 347 additions and 401 deletions
|
@ -18,31 +18,6 @@ Gitlab/Json:
|
|||
- 'app/controllers/projects/templates_controller.rb'
|
||||
- 'app/controllers/projects_controller.rb'
|
||||
- 'app/controllers/search_controller.rb'
|
||||
- 'app/helpers/access_tokens_helper.rb'
|
||||
- 'app/helpers/application_settings_helper.rb'
|
||||
- 'app/helpers/breadcrumbs_helper.rb'
|
||||
- 'app/helpers/ci/builds_helper.rb'
|
||||
- 'app/helpers/ci/pipelines_helper.rb'
|
||||
- 'app/helpers/compare_helper.rb'
|
||||
- 'app/helpers/emails_helper.rb'
|
||||
- 'app/helpers/environment_helper.rb'
|
||||
- 'app/helpers/groups_helper.rb'
|
||||
- 'app/helpers/ide_helper.rb'
|
||||
- 'app/helpers/integrations_helper.rb'
|
||||
- 'app/helpers/invite_members_helper.rb'
|
||||
- 'app/helpers/issuables_description_templates_helper.rb'
|
||||
- 'app/helpers/issuables_helper.rb'
|
||||
- 'app/helpers/jira_connect_helper.rb'
|
||||
- 'app/helpers/learn_gitlab_helper.rb'
|
||||
- 'app/helpers/namespaces_helper.rb'
|
||||
- 'app/helpers/notes_helper.rb'
|
||||
- 'app/helpers/operations_helper.rb'
|
||||
- 'app/helpers/packages_helper.rb'
|
||||
- 'app/helpers/projects/project_members_helper.rb'
|
||||
- 'app/helpers/projects_helper.rb'
|
||||
- 'app/helpers/search_helper.rb'
|
||||
- 'app/helpers/terms_helper.rb'
|
||||
- 'app/helpers/users_helper.rb'
|
||||
- 'app/mailers/emails/members.rb'
|
||||
- 'app/models/concerns/redis_cacheable.rb'
|
||||
- 'app/models/diff_discussion.rb'
|
||||
|
|
|
@ -194,6 +194,7 @@ export default {
|
|||
ref="dropdown"
|
||||
:text="buttonText"
|
||||
class="gl-w-full"
|
||||
block
|
||||
data-testid="labels-select-dropdown-contents"
|
||||
data-qa-selector="labels_dropdown_content"
|
||||
@hide="handleDropdownHide"
|
||||
|
|
27
app/graphql/mutations/ci/pipeline_schedule/take_ownership.rb
Normal file
27
app/graphql/mutations/ci/pipeline_schedule/take_ownership.rb
Normal file
|
@ -0,0 +1,27 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module Mutations
|
||||
module Ci
|
||||
module PipelineSchedule
|
||||
class TakeOwnership < Base
|
||||
graphql_name 'PipelineScheduleTakeOwnership'
|
||||
|
||||
authorize :take_ownership_pipeline_schedule
|
||||
|
||||
field :pipeline_schedule,
|
||||
Types::Ci::PipelineScheduleType,
|
||||
description: 'Updated pipeline schedule ownership.'
|
||||
|
||||
def resolve(id:)
|
||||
schedule = authorized_find!(id: id)
|
||||
|
||||
service_response = ::Ci::PipelineSchedules::TakeOwnershipService.new(schedule, current_user).execute
|
||||
{
|
||||
pipeline_schedule: schedule,
|
||||
errors: service_response.errors
|
||||
}
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -115,6 +115,7 @@ module Types
|
|||
mount_mutation Mutations::Ci::Pipeline::Destroy
|
||||
mount_mutation Mutations::Ci::Pipeline::Retry
|
||||
mount_mutation Mutations::Ci::PipelineSchedule::Delete
|
||||
mount_mutation Mutations::Ci::PipelineSchedule::TakeOwnership
|
||||
mount_mutation Mutations::Ci::CiCdSettingsUpdate, deprecated: {
|
||||
reason: :renamed,
|
||||
replacement: 'ProjectCiCdSettingsUpdate',
|
||||
|
|
|
@ -9,7 +9,7 @@ module AccessTokensHelper
|
|||
end
|
||||
|
||||
def tokens_app_data
|
||||
{
|
||||
data = {
|
||||
feed_token: {
|
||||
enabled: !Gitlab::CurrentSettings.disable_feed_token,
|
||||
token: current_user.feed_token,
|
||||
|
@ -25,7 +25,9 @@ module AccessTokensHelper
|
|||
token: current_user.enabled_static_object_token,
|
||||
reset_path: reset_static_object_token_profile_path
|
||||
}
|
||||
}.to_json
|
||||
}
|
||||
|
||||
Gitlab::Json.dump(data)
|
||||
end
|
||||
|
||||
def expires_at_field_data
|
||||
|
|
|
@ -137,7 +137,7 @@ module ApplicationSettingsHelper
|
|||
}
|
||||
end
|
||||
|
||||
options.to_json
|
||||
Gitlab::Json.dump(options)
|
||||
end
|
||||
|
||||
def external_authorization_description
|
||||
|
|
|
@ -40,11 +40,11 @@ module BreadcrumbsHelper
|
|||
end
|
||||
|
||||
def schema_breadcrumb_json
|
||||
{
|
||||
Gitlab::Json.dump({
|
||||
'@context': 'https://schema.org',
|
||||
'@type': 'BreadcrumbList',
|
||||
'itemListElement': build_item_list_elements
|
||||
}.to_json
|
||||
})
|
||||
end
|
||||
|
||||
private
|
||||
|
|
|
@ -38,13 +38,13 @@ module Ci
|
|||
end
|
||||
|
||||
def prepare_failed_jobs_summary_data(failed_builds)
|
||||
failed_builds.map do |build|
|
||||
Gitlab::Json.dump(failed_builds.map do |build|
|
||||
{
|
||||
id: build.id,
|
||||
failure: build.present.callout_failure_message,
|
||||
failure_summary: build_summary(build)
|
||||
}
|
||||
end.to_json
|
||||
end)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -87,7 +87,7 @@ module Ci
|
|||
endpoint: list_url,
|
||||
project_id: project.id,
|
||||
default_branch_name: project.default_branch,
|
||||
params: params.to_json,
|
||||
params: Gitlab::Json.dump(params),
|
||||
artifacts_endpoint: downloadable_artifacts_project_pipeline_path(project, artifacts_endpoint_placeholder, format: :json),
|
||||
artifacts_endpoint_placeholder: artifacts_endpoint_placeholder,
|
||||
pipeline_schedule_url: pipeline_schedules_path(project),
|
||||
|
@ -100,7 +100,7 @@ module Ci
|
|||
reset_cache_path: can?(current_user, :admin_pipeline, project) && reset_cache_project_settings_ci_cd_path(project),
|
||||
has_gitlab_ci: has_gitlab_ci?(project).to_s,
|
||||
pipeline_editor_path: can?(current_user, :create_pipeline, project) && project_ci_pipeline_editor_path(project),
|
||||
suggested_ci_templates: suggested_ci_templates.to_json,
|
||||
suggested_ci_templates: Gitlab::Json.dump(suggested_ci_templates),
|
||||
ci_runner_settings_path: project_settings_ci_cd_path(project, ci_runner_templates: true, anchor: 'js-runners-settings')
|
||||
}
|
||||
|
||||
|
|
|
@ -37,17 +37,17 @@ module CompareHelper
|
|||
def project_compare_selector_data(project, merge_request, params)
|
||||
{
|
||||
project_compare_index_path: project_compare_index_path(project),
|
||||
source_project: { id: project.id, name: project.full_path }.to_json,
|
||||
target_project: { id: @target_project.id, name: @target_project.full_path }.to_json,
|
||||
source_project: Gitlab::Json.dump({ id: project.id, name: project.full_path }),
|
||||
target_project: Gitlab::Json.dump({ id: @target_project.id, name: @target_project.full_path }),
|
||||
source_project_refs_path: refs_project_path(project),
|
||||
target_project_refs_path: refs_project_path(@target_project),
|
||||
params_from: params[:from],
|
||||
params_to: params[:to],
|
||||
straight: params[:straight]
|
||||
}.tap do |data|
|
||||
data[:projects_from] = target_projects(project).map do |target_project|
|
||||
data[:projects_from] = Gitlab::Json.dump(target_projects(project).map do |target_project|
|
||||
{ id: target_project.id, name: target_project.full_path }
|
||||
end.to_json
|
||||
end)
|
||||
|
||||
data[:project_merge_request_path] =
|
||||
if merge_request.present?
|
||||
|
|
|
@ -36,7 +36,7 @@ module EmailsHelper
|
|||
}
|
||||
|
||||
content_tag :script, type: 'application/ld+json' do
|
||||
data.to_json.html_safe
|
||||
Gitlab::Json.dump(data).html_safe
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -91,6 +91,6 @@ module EnvironmentHelper
|
|||
end
|
||||
|
||||
def environments_detail_data_json(user, project, environment)
|
||||
environments_detail_data(user, project, environment).to_json
|
||||
Gitlab::Json.dump(environments_detail_data(user, project, environment))
|
||||
end
|
||||
end
|
||||
|
|
|
@ -119,7 +119,7 @@ module GroupsHelper
|
|||
{ id: group.id, text: group.human_name }
|
||||
end
|
||||
|
||||
groups.to_json
|
||||
Gitlab::Json.dump(groups)
|
||||
end
|
||||
|
||||
def render_setting_to_allow_project_access_token_creation?(group)
|
||||
|
|
|
@ -56,7 +56,7 @@ module IdeHelper
|
|||
def convert_to_project_entity_json(project)
|
||||
return unless project
|
||||
|
||||
API::Entities::Project.represent(project, current_user: current_user).to_json
|
||||
Gitlab::Json.dump(API::Entities::Project.represent(project, current_user: current_user))
|
||||
end
|
||||
|
||||
def enable_environments_guidance?
|
||||
|
|
|
@ -114,7 +114,7 @@ module IntegrationsHelper
|
|||
learn_more_path: integrations_help_page_path,
|
||||
about_pricing_url: Gitlab::Saas.about_pricing_url,
|
||||
trigger_events: trigger_events_for_integration(integration),
|
||||
sections: integration.sections.to_json,
|
||||
sections: Gitlab::Json.dump(integration.sections),
|
||||
fields: fields_for_integration(integration),
|
||||
inherit_from_id: integration.inherit_from_id,
|
||||
integration_level: integration_level(integration),
|
||||
|
@ -144,7 +144,7 @@ module IntegrationsHelper
|
|||
|
||||
def integration_list_data(integrations, group: nil, project: nil)
|
||||
{
|
||||
integrations: integrations.map { |i| serialize_integration(i, group: group, project: project) }.to_json
|
||||
integrations: Gitlab::Json.dump(integrations.map { |i| serialize_integration(i, group: group, project: project) })
|
||||
}
|
||||
end
|
||||
|
||||
|
@ -237,11 +237,15 @@ module IntegrationsHelper
|
|||
end
|
||||
|
||||
def trigger_events_for_integration(integration)
|
||||
Integrations::EventSerializer.new(integration: integration).represent(integration.configurable_events).to_json
|
||||
serializer = Integrations::EventSerializer.new(integration: integration).represent(integration.configurable_events)
|
||||
|
||||
Gitlab::Json.dump(serializer)
|
||||
end
|
||||
|
||||
def fields_for_integration(integration)
|
||||
Integrations::FieldSerializer.new(integration: integration).represent(integration.form_fields).to_json
|
||||
serializer = Integrations::FieldSerializer.new(integration: integration).represent(integration.form_fields)
|
||||
|
||||
Gitlab::Json.dump(serializer)
|
||||
end
|
||||
|
||||
def integration_level(integration)
|
||||
|
|
|
@ -29,7 +29,7 @@ module InviteMembersHelper
|
|||
invalid_groups: source.related_group_ids,
|
||||
help_link: help_page_url('user/permissions'),
|
||||
is_project: is_project,
|
||||
access_levels: member_class.permissible_access_level_roles(current_user, source).to_json
|
||||
access_levels: Gitlab::Json.dump(member_class.permissible_access_level_roles(current_user, source))
|
||||
}.merge(group_select_data(source))
|
||||
end
|
||||
|
||||
|
@ -44,8 +44,8 @@ module InviteMembersHelper
|
|||
|
||||
if show_invite_members_for_task?(source)
|
||||
dataset.merge!(
|
||||
tasks_to_be_done_options: tasks_to_be_done_options.to_json,
|
||||
projects: projects_for_source(source).to_json,
|
||||
tasks_to_be_done_options: Gitlab::Json.dump(tasks_to_be_done_options),
|
||||
projects: Gitlab::Json.dump(projects_for_source(source)),
|
||||
new_project_path: source.is_a?(Group) ? new_project_path(namespace_id: source.id) : ''
|
||||
)
|
||||
end
|
||||
|
|
|
@ -53,7 +53,7 @@ module IssuablesDescriptionTemplatesHelper
|
|||
end
|
||||
|
||||
def available_service_desk_templates_for(project)
|
||||
issuable_templates(project, 'issue').flatten.to_json
|
||||
Gitlab::Json.dump(issuable_templates(project, 'issue').flatten)
|
||||
end
|
||||
|
||||
def template_names_path(parent, issuable)
|
||||
|
|
|
@ -73,10 +73,9 @@ module IssuablesHelper
|
|||
MergeRequestSerializer
|
||||
end
|
||||
|
||||
serializer_klass
|
||||
Gitlab::Json.dump(serializer_klass
|
||||
.new(current_user: current_user, project: issuable.project)
|
||||
.represent(issuable, opts)
|
||||
.to_json
|
||||
.represent(issuable, opts))
|
||||
end
|
||||
|
||||
def users_dropdown_label(selected_users)
|
||||
|
@ -441,7 +440,7 @@ module IssuablesHelper
|
|||
labels_manage_path: project_labels_path(project),
|
||||
project_issues_path: issuable_sidebar[:project_issuables_path],
|
||||
project_path: project.full_path,
|
||||
selected_labels: issuable_sidebar[:labels].to_json
|
||||
selected_labels: Gitlab::Json.dump(issuable_sidebar[:labels])
|
||||
}
|
||||
end
|
||||
|
||||
|
|
|
@ -6,12 +6,12 @@ module JiraConnectHelper
|
|||
|
||||
{
|
||||
groups_path: api_v4_groups_path(params: { min_access_level: Gitlab::Access::MAINTAINER, skip_groups: skip_groups }),
|
||||
subscriptions: subscriptions.map { |s| serialize_subscription(s) }.to_json,
|
||||
subscriptions: Gitlab::Json.dump(subscriptions.map { |s| serialize_subscription(s) }),
|
||||
add_subscriptions_path: jira_connect_subscriptions_path,
|
||||
subscriptions_path: jira_connect_subscriptions_path(format: :json),
|
||||
users_path: current_user ? nil : jira_connect_users_path, # users_path is used to determine if user is signed in
|
||||
gitlab_user_path: current_user ? user_path(current_user) : nil,
|
||||
oauth_metadata: Feature.enabled?(:jira_connect_oauth, current_user) ? jira_connect_oauth_data(installation).to_json : nil
|
||||
oauth_metadata: Feature.enabled?(:jira_connect_oauth, current_user) ? Gitlab::Json.dump(jira_connect_oauth_data(installation)) : nil
|
||||
}
|
||||
end
|
||||
|
||||
|
|
|
@ -14,9 +14,9 @@ module LearnGitlabHelper
|
|||
|
||||
def learn_gitlab_data(project)
|
||||
{
|
||||
actions: onboarding_actions_data(project).to_json,
|
||||
sections: onboarding_sections_data.to_json,
|
||||
project: onboarding_project_data(project).to_json
|
||||
actions: Gitlab::Json.dump(onboarding_actions_data(project)),
|
||||
sections: Gitlab::Json.dump(onboarding_sections_data),
|
||||
project: Gitlab::Json.dump(onboarding_project_data(project))
|
||||
}
|
||||
end
|
||||
|
||||
|
|
|
@ -67,7 +67,7 @@ module NamespacesHelper
|
|||
end
|
||||
|
||||
{
|
||||
popover_data: popover_data.to_json,
|
||||
popover_data: Gitlab::Json.dump(popover_data),
|
||||
testid: 'cascading-settings-lock-icon'
|
||||
}
|
||||
end
|
||||
|
|
|
@ -22,12 +22,14 @@ module NotesHelper
|
|||
end
|
||||
|
||||
def noteable_json(noteable)
|
||||
{
|
||||
data = {
|
||||
id: noteable.id,
|
||||
class: noteable.class.name,
|
||||
resources: noteable.class.table_name,
|
||||
project_id: noteable.project.id
|
||||
}.to_json
|
||||
}
|
||||
|
||||
Gitlab::Json.dump(data)
|
||||
end
|
||||
|
||||
def diff_view_data
|
||||
|
|
|
@ -26,7 +26,7 @@ module OperationsHelper
|
|||
'disabled' => disabled.to_s,
|
||||
'project_path' => @project.full_path,
|
||||
'multi_integrations' => 'false',
|
||||
'templates' => templates.to_json,
|
||||
'templates' => Gitlab::Json.dump(templates),
|
||||
'create_issue' => setting.create_issue.to_s,
|
||||
'issue_template_key' => setting.issue_template_key.to_s,
|
||||
'send_email' => setting.send_email.to_s,
|
||||
|
|
|
@ -24,7 +24,7 @@ module PackagesHelper
|
|||
def package_from_presenter(package)
|
||||
presenter = ::Packages::Detail::PackagePresenter.new(package)
|
||||
|
||||
presenter.detail_view.to_json
|
||||
Gitlab::Json.dump(presenter.detail_view)
|
||||
end
|
||||
|
||||
def pypi_registry_url(project_id)
|
||||
|
@ -68,9 +68,9 @@ module PackagesHelper
|
|||
{
|
||||
project_id: @project.id,
|
||||
project_path: @project.full_path,
|
||||
cadence_options: cadence_options.to_json,
|
||||
keep_n_options: keep_n_options.to_json,
|
||||
older_than_options: older_than_options.to_json,
|
||||
cadence_options: Gitlab::Json.dump(cadence_options),
|
||||
keep_n_options: Gitlab::Json.dump(keep_n_options),
|
||||
older_than_options: Gitlab::Json.dump(older_than_options),
|
||||
is_admin: current_user&.admin.to_s,
|
||||
admin_settings_path: ci_cd_admin_application_settings_path(anchor: 'js-registry-settings'),
|
||||
project_settings_path: project_settings_packages_and_registries_path(@project),
|
||||
|
|
|
@ -2,14 +2,14 @@
|
|||
|
||||
module Projects::ProjectMembersHelper
|
||||
def project_members_app_data_json(project, members:, invited:, access_requests:, include_relations:, search:)
|
||||
{
|
||||
Gitlab::Json.dump({
|
||||
user: project_members_list_data(project, members, { param_name: :page, params: { search_groups: nil } }),
|
||||
group: project_group_links_list_data(project, include_relations, search),
|
||||
invite: project_members_list_data(project, invited.nil? ? [] : invited),
|
||||
access_request: project_members_list_data(project, access_requests.nil? ? [] : access_requests),
|
||||
source_id: project.id,
|
||||
can_manage_members: Ability.allowed?(current_user, :admin_project_member, project)
|
||||
}.to_json
|
||||
})
|
||||
end
|
||||
|
||||
def project_member_header_subtext(project)
|
||||
|
|
|
@ -300,13 +300,15 @@ module ProjectsHelper
|
|||
return if setting.blank? || setting.project_slug.blank? ||
|
||||
setting.organization_slug.blank?
|
||||
|
||||
{
|
||||
data = {
|
||||
sentry_project_id: setting.sentry_project_id,
|
||||
name: setting.project_name,
|
||||
organization_name: setting.organization_name,
|
||||
organization_slug: setting.organization_slug,
|
||||
slug: setting.project_slug
|
||||
}.to_json
|
||||
}
|
||||
|
||||
Gitlab::Json.dump(data)
|
||||
end
|
||||
|
||||
def directory?
|
||||
|
|
|
@ -440,9 +440,9 @@ module SearchHelper
|
|||
end
|
||||
|
||||
def search_navigation_json
|
||||
search_navigation.each_with_object({}) do |(key, value), hash|
|
||||
Gitlab::Json.dump(search_navigation.each_with_object({}) do |(key, value), hash|
|
||||
hash[key] = search_filter_link_json(key, value[:label], value[:data], value[:search]) if value[:condition]
|
||||
end.to_json
|
||||
end)
|
||||
end
|
||||
|
||||
def search_filter_input_options(type, placeholder = _('Search or filter results...'))
|
||||
|
|
|
@ -4,7 +4,7 @@ module TermsHelper
|
|||
def terms_data(terms, redirect)
|
||||
redirect_params = { redirect: redirect } if redirect
|
||||
|
||||
{
|
||||
data = {
|
||||
terms: markdown_field(terms, :terms),
|
||||
permissions: {
|
||||
can_accept: can?(current_user, :accept_terms, terms),
|
||||
|
@ -15,6 +15,8 @@ module TermsHelper
|
|||
decline: decline_term_path(terms, redirect_params),
|
||||
root: root_path
|
||||
}
|
||||
}.to_json
|
||||
}
|
||||
|
||||
Gitlab::Json.dump(data)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -3,8 +3,8 @@
|
|||
module UsersHelper
|
||||
def admin_users_data_attributes(users)
|
||||
{
|
||||
users: Admin::UserSerializer.new.represent(users, { current_user: current_user }).to_json,
|
||||
paths: admin_users_paths.to_json
|
||||
users: Gitlab::Json.dump(Admin::UserSerializer.new.represent(users, { current_user: current_user })),
|
||||
paths: Gitlab::Json.dump(admin_users_paths)
|
||||
}
|
||||
end
|
||||
|
||||
|
@ -163,8 +163,8 @@ module UsersHelper
|
|||
|
||||
def admin_user_actions_data_attributes(user)
|
||||
{
|
||||
user: Admin::UserEntity.represent(user, { current_user: current_user }).to_json,
|
||||
paths: admin_users_paths.to_json
|
||||
user: Gitlab::Json.dump(Admin::UserEntity.represent(user, { current_user: current_user })),
|
||||
paths: Gitlab::Json.dump(admin_users_paths)
|
||||
}
|
||||
end
|
||||
|
||||
|
|
|
@ -224,6 +224,13 @@ class ContainerRepository < ApplicationRecord
|
|||
end
|
||||
end
|
||||
|
||||
# Container Repository model and the code that makes API calls
|
||||
# are tied. Sometimes (mainly in Geo) we need to work with Registry
|
||||
# when Container Repository record doesn't even exist.
|
||||
# The ability to create a not-persisted record with a certain "path" parameter
|
||||
# is very useful
|
||||
attr_writer :path
|
||||
|
||||
def self.exists_by_path?(path)
|
||||
where(
|
||||
project: path.repository_project,
|
||||
|
|
34
app/services/ci/pipeline_schedules/take_ownership_service.rb
Normal file
34
app/services/ci/pipeline_schedules/take_ownership_service.rb
Normal file
|
@ -0,0 +1,34 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module Ci
|
||||
module PipelineSchedules
|
||||
class TakeOwnershipService
|
||||
def initialize(schedule, user)
|
||||
@schedule = schedule
|
||||
@user = user
|
||||
end
|
||||
|
||||
def execute
|
||||
return forbidden unless allowed?
|
||||
|
||||
if schedule.update(owner: user)
|
||||
ServiceResponse.success(payload: schedule)
|
||||
else
|
||||
ServiceResponse.error(message: schedule.errors.full_messages)
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
attr_reader :schedule, :user
|
||||
|
||||
def allowed?
|
||||
user.can?(:take_ownership_pipeline_schedule, schedule)
|
||||
end
|
||||
|
||||
def forbidden
|
||||
ServiceResponse.error(message: _('Failed to change the owner'), reason: :access_denied)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -1,18 +0,0 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module Clusters
|
||||
module Applications
|
||||
class CreateService < Clusters::Applications::BaseService
|
||||
private
|
||||
|
||||
def worker_class(application)
|
||||
application.updateable? ? ClusterUpgradeAppWorker : ClusterInstallAppWorker
|
||||
end
|
||||
|
||||
def builder
|
||||
cluster.public_send(application_class.association_name) || # rubocop:disable GitlabSecurity/PublicSend
|
||||
cluster.public_send(:"build_application_#{application_name}") # rubocop:disable GitlabSecurity/PublicSend
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -3,4 +3,4 @@
|
|||
.form-group
|
||||
= label_tag _('User restrictions')
|
||||
= render_if_exists 'admin/application_settings/updating_name_disabled_for_users', form: form
|
||||
= form.gitlab_ui_checkbox_component :can_create_group, _("Allow users to create top-level groups")
|
||||
= form.gitlab_ui_checkbox_component :can_create_group, _("Allow new users to create top-level groups")
|
||||
|
|
|
@ -1,5 +1,8 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
# DEPRECATED
|
||||
#
|
||||
# To be removed by https://gitlab.com/gitlab-org/gitlab/-/issues/366573
|
||||
class ClusterInstallAppWorker # rubocop:disable Scalability/IdempotentWorker
|
||||
include ApplicationWorker
|
||||
|
||||
|
@ -12,9 +15,5 @@ class ClusterInstallAppWorker # rubocop:disable Scalability/IdempotentWorker
|
|||
worker_has_external_dependencies!
|
||||
loggable_arguments 0
|
||||
|
||||
def perform(app_name, app_id)
|
||||
find_application(app_name, app_id) do |app|
|
||||
Clusters::Applications::InstallService.new(app).execute
|
||||
end
|
||||
end
|
||||
def perform(app_name, app_id); end
|
||||
end
|
||||
|
|
|
@ -1,5 +1,8 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
# DEPRECATED
|
||||
#
|
||||
# To be removed by https://gitlab.com/gitlab-org/gitlab/-/issues/366573
|
||||
class ClusterUpgradeAppWorker # rubocop:disable Scalability/IdempotentWorker
|
||||
include ApplicationWorker
|
||||
|
||||
|
@ -12,9 +15,5 @@ class ClusterUpgradeAppWorker # rubocop:disable Scalability/IdempotentWorker
|
|||
worker_has_external_dependencies!
|
||||
loggable_arguments 0
|
||||
|
||||
def perform(app_name, app_id)
|
||||
find_application(app_name, app_id) do |app|
|
||||
Clusters::Applications::UpgradeService.new(app).execute
|
||||
end
|
||||
end
|
||||
def perform(app_name, app_id); end
|
||||
end
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
---
|
||||
name: split_background_migration_on_query_canceled
|
||||
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/101825
|
||||
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/378846
|
||||
milestone: '15.6'
|
||||
type: development
|
||||
group: group::database
|
||||
default_enabled: false
|
|
@ -0,0 +1,17 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class AddIndexIdOnScanFindingApprovalMergeRequestRules < Gitlab::Database::Migration[2.0]
|
||||
INDEX_NAME = 'scan_finding_approval_mr_rule_index_id'
|
||||
SCAN_FINDING_REPORT_TYPE = 4
|
||||
|
||||
disable_ddl_transaction!
|
||||
|
||||
def up
|
||||
add_concurrent_index :approval_merge_request_rules, :id,
|
||||
where: "report_type = #{SCAN_FINDING_REPORT_TYPE}", name: INDEX_NAME
|
||||
end
|
||||
|
||||
def down
|
||||
remove_concurrent_index_by_name :approval_merge_request_rules, INDEX_NAME
|
||||
end
|
||||
end
|
1
db/schema_migrations/20221025220607
Normal file
1
db/schema_migrations/20221025220607
Normal file
|
@ -0,0 +1 @@
|
|||
d6eb5bb918f12c08f23c228916b7e21432e1e2958832c10be4e46dfa2079103d
|
|
@ -31078,6 +31078,8 @@ CREATE UNIQUE INDEX partial_index_sop_configs_on_project_id ON security_orchestr
|
|||
|
||||
CREATE INDEX partial_index_user_id_app_id_created_at_token_not_revoked ON oauth_access_tokens USING btree (resource_owner_id, application_id, created_at) WHERE (revoked_at IS NULL);
|
||||
|
||||
CREATE INDEX scan_finding_approval_mr_rule_index_id ON approval_merge_request_rules USING btree (id) WHERE (report_type = 4);
|
||||
|
||||
CREATE INDEX scan_finding_approval_mr_rule_index_merge_request_id ON approval_merge_request_rules USING btree (merge_request_id) WHERE (report_type = 4);
|
||||
|
||||
CREATE INDEX scan_finding_approval_project_rule_index_created_at_project_id ON approval_project_rules USING btree (created_at, project_id) WHERE (report_type = 4);
|
||||
|
|
|
@ -14,7 +14,7 @@ By default, new users can create top-level groups. To disable new users'
|
|||
ability to create top-level groups (does not affect existing users' setting), GitLab administrators can modify this setting:
|
||||
|
||||
- In GitLab 15.5 and later, using either:
|
||||
- The [GitLab UI](../user/admin_area/settings/account_and_limit_settings.md#prevent-users-from-creating-top-level-groups).
|
||||
- The [GitLab UI](../user/admin_area/settings/account_and_limit_settings.md#prevent-new-users-from-creating-top-level-groups).
|
||||
- The [application setting API](../api/settings.md#change-application-settings).
|
||||
- In GitLab 15.4 and earlier, in a configuration file by following the steps in this section.
|
||||
|
||||
|
|
|
@ -4198,6 +4198,25 @@ Input type: `PipelineScheduleDeleteInput`
|
|||
| <a id="mutationpipelinescheduledeleteclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
|
||||
| <a id="mutationpipelinescheduledeleteerrors"></a>`errors` | [`[String!]!`](#string) | Errors encountered during execution of the mutation. |
|
||||
|
||||
### `Mutation.pipelineScheduleTakeOwnership`
|
||||
|
||||
Input type: `PipelineScheduleTakeOwnershipInput`
|
||||
|
||||
#### Arguments
|
||||
|
||||
| Name | Type | Description |
|
||||
| ---- | ---- | ----------- |
|
||||
| <a id="mutationpipelinescheduletakeownershipclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
|
||||
| <a id="mutationpipelinescheduletakeownershipid"></a>`id` | [`CiPipelineScheduleID!`](#cipipelinescheduleid) | ID of the pipeline schedule to mutate. |
|
||||
|
||||
#### Fields
|
||||
|
||||
| Name | Type | Description |
|
||||
| ---- | ---- | ----------- |
|
||||
| <a id="mutationpipelinescheduletakeownershipclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
|
||||
| <a id="mutationpipelinescheduletakeownershiperrors"></a>`errors` | [`[String!]!`](#string) | Errors encountered during execution of the mutation. |
|
||||
| <a id="mutationpipelinescheduletakeownershippipelineschedule"></a>`pipelineSchedule` | [`PipelineSchedule`](#pipelineschedule) | Updated pipeline schedule ownership. |
|
||||
|
||||
### `Mutation.projectCiCdSettingsUpdate`
|
||||
|
||||
Input type: `ProjectCiCdSettingsUpdateInput`
|
||||
|
|
|
@ -339,6 +339,20 @@ This example is specific to GitLab Code Quality. For more general
|
|||
instructions on how to configure DinD with a registry mirror, see the
|
||||
relevant [documentation](../docker/using_docker_build.md#enable-registry-mirror-for-dockerdind-service).
|
||||
|
||||
#### List of images to be stored in the private container registry
|
||||
|
||||
The following images are needed for the [default `.codeclimate.yml`](https://gitlab.com/gitlab-org/ci-cd/codequality/-/blob/master/codeclimate_defaults/.codeclimate.yml.template):
|
||||
|
||||
- `codeclimate/codeclimate-structure:latest`
|
||||
- `codeclimate/codeclimate-csslint:latest`
|
||||
- `codeclimate/codeclimate-coffeelint:latest`
|
||||
- `codeclimate/codeclimate-duplication:latest`
|
||||
- `codeclimate/codeclimate-eslint:latest`
|
||||
- `codeclimate/codeclimate-fixme:latest`
|
||||
- `codeclimate/codeclimate-rubocop:rubocop-0-92`
|
||||
|
||||
If you are using a custom `.codeclimate.yml` configuration file, you must add the specified plugins in your private container registry.
|
||||
|
||||
#### Configure Code Quality to use the Dependency Proxy
|
||||
|
||||
Prerequisite:
|
||||
|
|
|
@ -276,11 +276,11 @@ When this ability is disabled, GitLab administrators can still use the
|
|||
[Admin Area](../index.md#administering-users) or the
|
||||
[API](../../../api/users.md#user-modification) to update usernames.
|
||||
|
||||
## Prevent users from creating top-level groups
|
||||
## Prevent new users from creating top-level groups
|
||||
|
||||
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/367754) in GitLab 15.5.
|
||||
|
||||
By default, new users can create top-level groups. GitLab administrators can prevent users from creating top-level groups:
|
||||
By default, new users can create top-level groups. GitLab administrators can prevent new users from creating top-level groups:
|
||||
|
||||
- In GitLab 15.5 and later, using either:
|
||||
- The GitLab UI using the steps in this section.
|
||||
|
@ -289,7 +289,7 @@ By default, new users can create top-level groups. GitLab administrators can pre
|
|||
|
||||
1. On the top bar, select **Main menu > Admin**.
|
||||
1. On the left sidebar, select **Settings > General**, then expand **Account and limit**.
|
||||
1. Clear the **Allow users to create top-level groups** checkbox.
|
||||
1. Clear the **Allow new users to create top-level groups** checkbox.
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
|
|
|
@ -170,6 +170,7 @@ module API
|
|||
# Mount endpoints to include in the OpenAPI V2 documentation here
|
||||
namespace do
|
||||
mount ::API::AccessRequests
|
||||
mount ::API::Appearance
|
||||
mount ::API::Deployments
|
||||
mount ::API::Metadata
|
||||
mount ::API::UserCounts
|
||||
|
@ -186,7 +187,6 @@ module API
|
|||
mount ::API::Admin::PlanLimits
|
||||
mount ::API::Admin::Sidekiq
|
||||
mount ::API::AlertManagementAlerts
|
||||
mount ::API::Appearance
|
||||
mount ::API::Applications
|
||||
mount ::API::Avatar
|
||||
mount ::API::AwardEmoji
|
||||
|
|
|
@ -22,6 +22,7 @@ module API
|
|||
|
||||
desc 'Modify appearance' do
|
||||
success Entities::Appearance
|
||||
consumes ['multipart/form-data']
|
||||
end
|
||||
params do
|
||||
optional :title, type: String, desc: 'Instance title on the sign in / sign up page'
|
||||
|
|
|
@ -112,7 +112,7 @@ module Gitlab
|
|||
end
|
||||
|
||||
def can_split?(exception)
|
||||
attempts >= MAX_ATTEMPTS && TIMEOUT_EXCEPTIONS.include?(exception&.class) && batch_size > sub_batch_size && batch_size > 1
|
||||
attempts >= MAX_ATTEMPTS && timeout_exception?(exception&.class) && batch_size > sub_batch_size && batch_size > 1
|
||||
end
|
||||
|
||||
def split_and_retry!
|
||||
|
@ -161,6 +161,15 @@ module Gitlab
|
|||
end
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def timeout_exception?(exception_class)
|
||||
return false unless exception_class
|
||||
|
||||
TIMEOUT_EXCEPTIONS.include?(exception_class) ||
|
||||
(Feature.enabled?(:split_background_migration_on_query_canceled) && exception_class == ActiveRecord::QueryCanceled)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -3976,6 +3976,9 @@ msgstr ""
|
|||
msgid "Allow group owners to manage LDAP-related settings"
|
||||
msgstr ""
|
||||
|
||||
msgid "Allow new users to create top-level groups"
|
||||
msgstr ""
|
||||
|
||||
msgid "Allow non-administrators access to the performance bar"
|
||||
msgstr ""
|
||||
|
||||
|
@ -4012,9 +4015,6 @@ msgstr ""
|
|||
msgid "Allow use of licensed EE features"
|
||||
msgstr ""
|
||||
|
||||
msgid "Allow users to create top-level groups"
|
||||
msgstr ""
|
||||
|
||||
msgid "Allow users to dismiss the broadcast message"
|
||||
msgstr ""
|
||||
|
||||
|
|
|
@ -26,7 +26,7 @@ gem 'octokit', '~> 6.0.0'
|
|||
gem "faraday-retry", "~> 2.0"
|
||||
gem 'webdrivers', '~> 5.2'
|
||||
gem 'zeitwerk', '~> 2.4'
|
||||
gem 'influxdb-client', '~> 2.7'
|
||||
gem 'influxdb-client', '~> 2.8'
|
||||
gem 'terminal-table', '~> 3.0.2', require: false
|
||||
gem 'slack-notifier', '~> 2.4', require: false
|
||||
gem 'fog-google', '~> 1.19', require: false
|
||||
|
|
|
@ -156,7 +156,7 @@ GEM
|
|||
httpclient (2.8.3)
|
||||
i18n (1.12.0)
|
||||
concurrent-ruby (~> 1.0)
|
||||
influxdb-client (2.7.0)
|
||||
influxdb-client (2.8.0)
|
||||
jwt (2.5.0)
|
||||
knapsack (4.0.0)
|
||||
rake
|
||||
|
@ -315,7 +315,7 @@ DEPENDENCIES
|
|||
fog-core (= 2.1.0)
|
||||
fog-google (~> 1.19)
|
||||
gitlab-qa (~> 8, >= 8.9.0)
|
||||
influxdb-client (~> 2.7)
|
||||
influxdb-client (~> 2.8)
|
||||
knapsack (~> 4.0)
|
||||
nokogiri (~> 1.13, >= 1.13.9)
|
||||
octokit (~> 6.0.0)
|
||||
|
|
|
@ -391,7 +391,7 @@ RSpec.describe UsersHelper do
|
|||
expect_next_instance_of(Admin::UserSerializer) do |instance|
|
||||
expect(instance).to receive(:represent).with([user], { current_user: user }).and_return(entity)
|
||||
end
|
||||
expect(entity).to receive(:to_json).and_return("{\"username\":\"admin\"}")
|
||||
expect(entity).to receive(:as_json).and_return({ "username" => "admin" })
|
||||
expect(data[:users]).to eq "{\"username\":\"admin\"}"
|
||||
end
|
||||
|
||||
|
|
|
@ -272,7 +272,21 @@ RSpec.describe Gitlab::Database::BackgroundMigration::BatchedJob, type: :model d
|
|||
context 'when is a timeout exception' do
|
||||
let(:exception) { ActiveRecord::StatementTimeout.new }
|
||||
|
||||
it { expect(subject).to be_truthy }
|
||||
it { expect(subject).to be_truthy }
|
||||
end
|
||||
|
||||
context 'when is a QueryCanceled exception' do
|
||||
let(:exception) { ActiveRecord::QueryCanceled.new }
|
||||
|
||||
it { expect(subject).to be_truthy }
|
||||
|
||||
context 'when split_background_migration_on_query_canceled feature flag is disabled' do
|
||||
before do
|
||||
stub_feature_flags(split_background_migration_on_query_canceled: false)
|
||||
end
|
||||
|
||||
it { expect(subject).to be_falsey }
|
||||
end
|
||||
end
|
||||
|
||||
context 'when is not a timeout exception' do
|
||||
|
|
|
@ -0,0 +1,41 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe 'PipelineScheduleTakeOwnership' do
|
||||
include GraphqlHelpers
|
||||
|
||||
let_it_be(:user) { create(:user) }
|
||||
let_it_be(:owner) { create(:user) }
|
||||
let_it_be(:project) { create(:project) }
|
||||
let_it_be(:pipeline_schedule) { create(:ci_pipeline_schedule, project: project, owner: owner) }
|
||||
|
||||
let(:mutation) do
|
||||
graphql_mutation(
|
||||
:pipeline_schedule_take_ownership,
|
||||
{ id: pipeline_schedule_id },
|
||||
<<-QL
|
||||
errors
|
||||
QL
|
||||
)
|
||||
end
|
||||
|
||||
let(:pipeline_schedule_id) { pipeline_schedule.to_global_id.to_s }
|
||||
|
||||
before_all do
|
||||
project.add_maintainer(user)
|
||||
end
|
||||
|
||||
it 'returns an error if the user is not allowed to take ownership of the schedule' do
|
||||
post_graphql_mutation(mutation, current_user: create(:user))
|
||||
|
||||
expect(graphql_errors).not_to be_empty
|
||||
end
|
||||
|
||||
it 'takes ownership of the schedule' do
|
||||
post_graphql_mutation(mutation, current_user: user)
|
||||
|
||||
expect(response).to have_gitlab_http_status(:success)
|
||||
expect(graphql_errors).to be_nil
|
||||
end
|
||||
end
|
|
@ -0,0 +1,63 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe Ci::PipelineSchedules::TakeOwnershipService do
|
||||
let_it_be(:user) { create(:user) }
|
||||
let_it_be(:owner) { create(:user) }
|
||||
let_it_be(:reporter) { create(:user) }
|
||||
let_it_be(:project) { create(:project, :public, :repository) }
|
||||
let_it_be(:pipeline_schedule) { create(:ci_pipeline_schedule, project: project, owner: owner) }
|
||||
|
||||
before_all do
|
||||
project.add_maintainer(user)
|
||||
project.add_maintainer(owner)
|
||||
project.add_reporter(reporter)
|
||||
end
|
||||
|
||||
describe '#execute' do
|
||||
context 'when user does not have permission' do
|
||||
subject(:service) { described_class.new(pipeline_schedule, reporter) }
|
||||
|
||||
it 'returns ServiceResponse.error' do
|
||||
result = service.execute
|
||||
|
||||
expect(result).to be_a(ServiceResponse)
|
||||
expect(result.error?).to be(true)
|
||||
expect(result.message).to eq(_('Failed to change the owner'))
|
||||
end
|
||||
end
|
||||
|
||||
context 'when user has permission' do
|
||||
subject(:service) { described_class.new(pipeline_schedule, user) }
|
||||
|
||||
it 'returns ServiceResponse.success' do
|
||||
result = service.execute
|
||||
|
||||
expect(result).to be_a(ServiceResponse)
|
||||
expect(result.success?).to be(true)
|
||||
expect(result.payload).to eq(pipeline_schedule)
|
||||
end
|
||||
|
||||
context 'when schedule update fails' do
|
||||
subject(:service) { described_class.new(pipeline_schedule, owner) }
|
||||
|
||||
before do
|
||||
allow(pipeline_schedule).to receive(:update).and_return(false)
|
||||
|
||||
errors = ActiveModel::Errors.new(pipeline_schedule)
|
||||
errors.add(:base, 'An error occurred')
|
||||
allow(pipeline_schedule).to receive(:errors).and_return(errors)
|
||||
end
|
||||
|
||||
it 'returns ServiceResponse.error' do
|
||||
result = service.execute
|
||||
|
||||
expect(result).to be_a(ServiceResponse)
|
||||
expect(result.error?).to be(true)
|
||||
expect(result.message).to eq(['An error occurred'])
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -1,279 +0,0 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe Clusters::Applications::CreateService do
|
||||
include TestRequestHelpers
|
||||
|
||||
let(:cluster) { create(:cluster, :project, :provided_by_gcp) }
|
||||
let(:user) { create(:user) }
|
||||
let(:params) { { application: 'ingress' } }
|
||||
let(:service) { described_class.new(cluster, user, params) }
|
||||
|
||||
describe '#execute' do
|
||||
before do
|
||||
allow(ClusterInstallAppWorker).to receive(:perform_async)
|
||||
allow(ClusterUpgradeAppWorker).to receive(:perform_async)
|
||||
end
|
||||
|
||||
subject { service.execute(test_request) }
|
||||
|
||||
it 'creates an application' do
|
||||
expect do
|
||||
subject
|
||||
|
||||
cluster.reload
|
||||
end.to change(cluster, :application_ingress)
|
||||
end
|
||||
|
||||
context 'application already installed' do
|
||||
let!(:application) { create(:clusters_applications_ingress, :installed, cluster: cluster) }
|
||||
|
||||
it 'does not create a new application' do
|
||||
expect do
|
||||
subject
|
||||
end.not_to change(Clusters::Applications::Ingress, :count)
|
||||
end
|
||||
|
||||
it 'schedules an upgrade for the application' do
|
||||
expect(ClusterUpgradeAppWorker).to receive(:perform_async)
|
||||
|
||||
subject
|
||||
end
|
||||
end
|
||||
|
||||
context 'known applications' do
|
||||
context 'ingress application' do
|
||||
let(:params) do
|
||||
{
|
||||
application: 'ingress'
|
||||
}
|
||||
end
|
||||
|
||||
before do
|
||||
expect_any_instance_of(Clusters::Applications::Ingress)
|
||||
.to receive(:make_scheduled!)
|
||||
.and_call_original
|
||||
end
|
||||
|
||||
it 'creates the application' do
|
||||
expect do
|
||||
subject
|
||||
|
||||
cluster.reload
|
||||
end.to change(cluster, :application_ingress)
|
||||
end
|
||||
end
|
||||
|
||||
context 'cert manager application' do
|
||||
let(:params) do
|
||||
{
|
||||
application: 'cert_manager',
|
||||
email: 'test@example.com'
|
||||
}
|
||||
end
|
||||
|
||||
before do
|
||||
expect_any_instance_of(Clusters::Applications::CertManager)
|
||||
.to receive(:make_scheduled!)
|
||||
.and_call_original
|
||||
end
|
||||
|
||||
it 'creates the application' do
|
||||
expect do
|
||||
subject
|
||||
|
||||
cluster.reload
|
||||
end.to change(cluster, :application_cert_manager)
|
||||
end
|
||||
|
||||
it 'sets the email' do
|
||||
expect(subject.email).to eq('test@example.com')
|
||||
end
|
||||
end
|
||||
|
||||
context 'jupyter application' do
|
||||
let(:params) do
|
||||
{
|
||||
application: 'jupyter',
|
||||
hostname: 'example.com'
|
||||
}
|
||||
end
|
||||
|
||||
before do
|
||||
create(:clusters_applications_ingress, :installed, external_ip: "127.0.0.0", cluster: cluster)
|
||||
expect_any_instance_of(Clusters::Applications::Jupyter)
|
||||
.to receive(:make_scheduled!)
|
||||
.and_call_original
|
||||
end
|
||||
|
||||
it 'creates the application' do
|
||||
expect do
|
||||
subject
|
||||
|
||||
cluster.reload
|
||||
end.to change(cluster, :application_jupyter)
|
||||
end
|
||||
|
||||
it 'sets the hostname' do
|
||||
expect(subject.hostname).to eq('example.com')
|
||||
end
|
||||
|
||||
it 'sets the oauth_application' do
|
||||
expect(subject.oauth_application).to be_present
|
||||
end
|
||||
end
|
||||
|
||||
context 'knative application' do
|
||||
let(:params) do
|
||||
{
|
||||
application: 'knative',
|
||||
hostname: 'example.com',
|
||||
pages_domain_id: domain.id
|
||||
}
|
||||
end
|
||||
|
||||
let(:domain) { create(:pages_domain, :instance_serverless) }
|
||||
let(:associate_domain_service) { double('AssociateDomainService') }
|
||||
|
||||
before do
|
||||
expect_any_instance_of(Clusters::Applications::Knative)
|
||||
.to receive(:make_scheduled!)
|
||||
.and_call_original
|
||||
end
|
||||
|
||||
it 'creates the application' do
|
||||
expect do
|
||||
subject
|
||||
|
||||
cluster.reload
|
||||
end.to change(cluster, :application_knative)
|
||||
end
|
||||
|
||||
it 'sets the hostname' do
|
||||
expect(subject.hostname).to eq('example.com')
|
||||
end
|
||||
|
||||
it 'executes AssociateDomainService' do
|
||||
expect(Serverless::AssociateDomainService).to receive(:new) do |knative, args|
|
||||
expect(knative).to be_a(Clusters::Applications::Knative)
|
||||
expect(args[:pages_domain_id]).to eq(params[:pages_domain_id])
|
||||
expect(args[:creator]).to eq(user)
|
||||
|
||||
associate_domain_service
|
||||
end
|
||||
|
||||
expect(associate_domain_service).to receive(:execute)
|
||||
|
||||
subject
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'invalid application' do
|
||||
let(:params) { { application: 'non-existent' } }
|
||||
|
||||
it 'raises an error' do
|
||||
expect { subject }.to raise_error(Clusters::Applications::CreateService::InvalidApplicationError)
|
||||
end
|
||||
end
|
||||
|
||||
context 'group cluster' do
|
||||
let(:cluster) { create(:cluster, :provided_by_gcp, :group) }
|
||||
|
||||
using RSpec::Parameterized::TableSyntax
|
||||
|
||||
where(:application, :association, :allowed, :pre_create_ingress) do
|
||||
'ingress' | :application_ingress | true | false
|
||||
'runner' | :application_runner | true | false
|
||||
'prometheus' | :application_prometheus | true | false
|
||||
'jupyter' | :application_jupyter | true | true
|
||||
end
|
||||
|
||||
with_them do
|
||||
before do
|
||||
klass = "Clusters::Applications::#{application.titleize}"
|
||||
allow_any_instance_of(klass.constantize).to receive(:make_scheduled!).and_call_original
|
||||
create(:clusters_applications_ingress, :installed, cluster: cluster, external_hostname: 'example.com') if pre_create_ingress
|
||||
end
|
||||
|
||||
let(:params) { { application: application } }
|
||||
|
||||
it 'executes for each application' do
|
||||
if allowed
|
||||
expect do
|
||||
subject
|
||||
|
||||
cluster.reload
|
||||
end.to change(cluster, association)
|
||||
else
|
||||
expect { subject }.to raise_error(Clusters::Applications::CreateService::InvalidApplicationError)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'when application is installable' do
|
||||
shared_examples 'installable applications' do
|
||||
it 'makes the application scheduled' do
|
||||
expect do
|
||||
subject
|
||||
end.to change { Clusters::Applications::Ingress.with_status(:scheduled).count }.by(1)
|
||||
end
|
||||
|
||||
it 'schedules an install via worker' do
|
||||
expect(ClusterInstallAppWorker)
|
||||
.to receive(:perform_async)
|
||||
.with(*worker_arguments)
|
||||
.once
|
||||
|
||||
subject
|
||||
end
|
||||
end
|
||||
|
||||
context 'when application is associated with a cluster' do
|
||||
let(:application) { create(:clusters_applications_ingress, :installable, cluster: cluster) }
|
||||
let(:worker_arguments) { [application.name, application.id] }
|
||||
|
||||
it_behaves_like 'installable applications'
|
||||
end
|
||||
|
||||
context 'when application is not associated with a cluster' do
|
||||
let(:worker_arguments) { [params[:application], kind_of(Numeric)] }
|
||||
|
||||
it_behaves_like 'installable applications'
|
||||
end
|
||||
end
|
||||
|
||||
context 'when installation is already in progress' do
|
||||
let!(:application) { create(:clusters_applications_ingress, :installing, cluster: cluster) }
|
||||
|
||||
it 'raises an exception' do
|
||||
expect { subject }
|
||||
.to raise_exception(StateMachines::InvalidTransition)
|
||||
.and not_change(application.class.with_status(:scheduled), :count)
|
||||
end
|
||||
|
||||
it 'does not schedule a cluster worker' do
|
||||
expect(ClusterInstallAppWorker).not_to receive(:perform_async)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when application is installed' do
|
||||
%i(installed updated).each do |status|
|
||||
let(:application) { create(:clusters_applications_ingress, status, cluster: cluster) }
|
||||
|
||||
it 'schedules an upgrade via worker' do
|
||||
expect(ClusterUpgradeAppWorker)
|
||||
.to receive(:perform_async)
|
||||
.with(application.name, application.id)
|
||||
.once
|
||||
|
||||
subject
|
||||
|
||||
expect(application.reload).to be_scheduled
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
Loading…
Reference in a new issue