diff options
Diffstat (limited to 'app')
-rw-r--r-- | app/assets/javascripts/pages/admin/serverless/domains/index.js | 19 | ||||
-rw-r--r-- | app/assets/stylesheets/pages/pages.scss | 11 | ||||
-rw-r--r-- | app/controllers/admin/serverless/domains_controller.rb | 62 | ||||
-rw-r--r-- | app/controllers/projects/environments_controller.rb | 2 | ||||
-rw-r--r-- | app/controllers/projects/merge_requests/diffs_controller.rb | 2 | ||||
-rw-r--r-- | app/controllers/projects/merge_requests_controller.rb | 2 | ||||
-rw-r--r-- | app/models/pages_domain.rb | 3 | ||||
-rw-r--r-- | app/services/environments/auto_stop_service.rb | 2 | ||||
-rw-r--r-- | app/services/metrics/dashboard/system_dashboard_service.rb | 1 | ||||
-rw-r--r-- | app/services/snippets/create_service.rb | 4 | ||||
-rw-r--r-- | app/views/admin/serverless/domains/_form.html.haml | 68 | ||||
-rw-r--r-- | app/views/admin/serverless/domains/index.html.haml | 25 | ||||
-rw-r--r-- | app/views/layouts/nav/sidebar/_admin.html.haml | 5 | ||||
-rw-r--r-- | app/workers/environments/auto_stop_cron_worker.rb | 2 |
14 files changed, 201 insertions, 7 deletions
diff --git a/app/assets/javascripts/pages/admin/serverless/domains/index.js b/app/assets/javascripts/pages/admin/serverless/domains/index.js new file mode 100644 index 00000000000..5be466886a5 --- /dev/null +++ b/app/assets/javascripts/pages/admin/serverless/domains/index.js @@ -0,0 +1,19 @@ +import initSettingsPanels from '~/settings_panels'; + +document.addEventListener('DOMContentLoaded', () => { + // Initialize expandable settings panels + initSettingsPanels(); + + const domainCard = document.querySelector('.js-domain-cert-show'); + const domainForm = document.querySelector('.js-domain-cert-inputs'); + const domainReplaceButton = document.querySelector('.js-domain-cert-replace-btn'); + const domainSubmitButton = document.querySelector('.js-serverless-domain-submit'); + + if (domainReplaceButton && domainCard && domainForm) { + domainReplaceButton.addEventListener('click', () => { + domainCard.classList.add('hidden'); + domainForm.classList.remove('hidden'); + domainSubmitButton.removeAttribute('disabled'); + }); + } +}); diff --git a/app/assets/stylesheets/pages/pages.scss b/app/assets/stylesheets/pages/pages.scss index 374227fe16a..93caa345f8a 100644 --- a/app/assets/stylesheets/pages/pages.scss +++ b/app/assets/stylesheets/pages/pages.scss @@ -56,4 +56,15 @@ border-top-right-radius: $border-radius-default; } + &.floating-status-badge { + position: absolute; + right: $gl-padding-24; + bottom: $gl-padding-4; + margin-bottom: 0; + } +} + +.form-control.has-floating-status-badge { + position: relative; + padding-right: 120px; } diff --git a/app/controllers/admin/serverless/domains_controller.rb b/app/controllers/admin/serverless/domains_controller.rb new file mode 100644 index 00000000000..c37aec13105 --- /dev/null +++ b/app/controllers/admin/serverless/domains_controller.rb @@ -0,0 +1,62 @@ +# frozen_string_literal: true + +class Admin::Serverless::DomainsController < Admin::ApplicationController + before_action :check_feature_flag + before_action :domain, only: [:update, :verify] + + def index + @domain = PagesDomain.instance_serverless.first_or_initialize + end + + def create + if PagesDomain.instance_serverless.count > 0 + return redirect_to admin_serverless_domains_path, notice: _('An instance-level serverless domain already exists.') + end + + @domain = PagesDomain.instance_serverless.create(create_params) + + if @domain.persisted? + redirect_to admin_serverless_domains_path, notice: _('Domain was successfully created.') + else + render 'index' + end + end + + def update + if domain.update(update_params) + redirect_to admin_serverless_domains_path, notice: _('Domain was successfully updated.') + else + render 'index' + end + end + + def verify + result = VerifyPagesDomainService.new(domain).execute + + if result[:status] == :success + flash[:notice] = _('Successfully verified domain ownership') + else + flash[:alert] = _('Failed to verify domain ownership') + end + + redirect_to admin_serverless_domains_path + end + + private + + def domain + @domain = PagesDomain.instance_serverless.find(params[:id]) + end + + def check_feature_flag + render_404 unless Feature.enabled?(:serverless_domain) + end + + def update_params + params.require(:pages_domain).permit(:user_provided_certificate, :user_provided_key) + end + + def create_params + params.require(:pages_domain).permit(:domain, :user_provided_certificate, :user_provided_key) + end +end diff --git a/app/controllers/projects/environments_controller.rb b/app/controllers/projects/environments_controller.rb index 70c4b536854..5c49fa842a4 100644 --- a/app/controllers/projects/environments_controller.rb +++ b/app/controllers/projects/environments_controller.rb @@ -16,7 +16,7 @@ class Projects::EnvironmentsController < Projects::ApplicationController push_frontend_feature_flag(:prometheus_computed_alerts) end before_action do - push_frontend_feature_flag(:auto_stop_environments) + push_frontend_feature_flag(:auto_stop_environments, default_enabled: true) end after_action :expire_etag_cache, only: [:cancel_auto_stop] diff --git a/app/controllers/projects/merge_requests/diffs_controller.rb b/app/controllers/projects/merge_requests/diffs_controller.rb index 872497992e1..953b2ffeb0b 100644 --- a/app/controllers/projects/merge_requests/diffs_controller.rb +++ b/app/controllers/projects/merge_requests/diffs_controller.rb @@ -18,7 +18,7 @@ class Projects::MergeRequests::DiffsController < Projects::MergeRequests::Applic end def diffs_batch - return render_404 unless Feature.enabled?(:diffs_batch_load, @merge_request.project) + return render_404 unless Feature.enabled?(:diffs_batch_load, @merge_request.project, default_enabled: true) diffs = @compare.diffs_in_batch(params[:page], params[:per_page], diff_options: diff_options) positions = @merge_request.note_positions_for_paths(diffs.diff_file_paths, current_user) diff --git a/app/controllers/projects/merge_requests_controller.rb b/app/controllers/projects/merge_requests_controller.rb index 8c0188e1783..c5f017efe8d 100644 --- a/app/controllers/projects/merge_requests_controller.rb +++ b/app/controllers/projects/merge_requests_controller.rb @@ -19,7 +19,7 @@ class Projects::MergeRequestsController < Projects::MergeRequests::ApplicationCo before_action :authenticate_user!, only: [:assign_related_issues] before_action :check_user_can_push_to_source_branch!, only: [:rebase] before_action only: [:show] do - push_frontend_feature_flag(:diffs_batch_load, @project) + push_frontend_feature_flag(:diffs_batch_load, @project, default_enabled: true) push_frontend_feature_flag(:single_mr_diff_view, @project) push_frontend_feature_flag(:suggest_pipeline) if experiment_enabled?(:suggest_pipeline) end diff --git a/app/models/pages_domain.rb b/app/models/pages_domain.rb index 91767c53f81..05cf427184c 100644 --- a/app/models/pages_domain.rb +++ b/app/models/pages_domain.rb @@ -14,6 +14,7 @@ class PagesDomain < ApplicationRecord validates :domain, hostname: { allow_numeric_hostname: true } validates :domain, uniqueness: { case_sensitive: false } + validates :certificate, :key, presence: true, if: :usage_serverless? validates :certificate, presence: { message: 'must be present if HTTPS-only is enabled' }, if: :certificate_should_be_present? validates :certificate, certificate: true, if: ->(domain) { domain.certificate.present? } @@ -64,6 +65,8 @@ class PagesDomain < ApplicationRecord scope :with_logging_info, -> { includes(project: [:namespace, :route]) } + scope :instance_serverless, -> { where(wildcard: true, scope: :instance, usage: :serverless) } + def verified? !!verified_at end diff --git a/app/services/environments/auto_stop_service.rb b/app/services/environments/auto_stop_service.rb index 6eef8138493..ee7f25a4d76 100644 --- a/app/services/environments/auto_stop_service.rb +++ b/app/services/environments/auto_stop_service.rb @@ -30,7 +30,7 @@ module Environments def stop_in_batch environments = Environment.auto_stoppable(BATCH_SIZE) - return false unless environments.exists? && Feature.enabled?(:auto_stop_environments) + return false unless environments.exists? && Feature.enabled?(:auto_stop_environments, default_enabled: true) Ci::StopEnvironmentsService.execute_in_batch(environments) end diff --git a/app/services/metrics/dashboard/system_dashboard_service.rb b/app/services/metrics/dashboard/system_dashboard_service.rb index bef65dbe1c2..aa8421e10d5 100644 --- a/app/services/metrics/dashboard/system_dashboard_service.rb +++ b/app/services/metrics/dashboard/system_dashboard_service.rb @@ -11,6 +11,7 @@ module Metrics SEQUENCE = [ STAGES::CommonMetricsInserter, STAGES::ProjectMetricsInserter, + STAGES::ProjectMetricsDetailsInserter, STAGES::EndpointInserter, STAGES::Sorter ].freeze diff --git a/app/services/snippets/create_service.rb b/app/services/snippets/create_service.rb index 9e87bebbe4e..7ded185a6f9 100644 --- a/app/services/snippets/create_service.rb +++ b/app/services/snippets/create_service.rb @@ -24,8 +24,8 @@ module Snippets spam_check(snippet, current_user) snippet_saved = snippet.with_transaction_returning_status do - if snippet.save && snippet.store_mentions! - create_repository_for(snippet, current_user) + (snippet.save && snippet.store_mentions!).tap do |saved| + create_repository_for(snippet, current_user) if saved end end diff --git a/app/views/admin/serverless/domains/_form.html.haml b/app/views/admin/serverless/domains/_form.html.haml new file mode 100644 index 00000000000..8c1c1d41caa --- /dev/null +++ b/app/views/admin/serverless/domains/_form.html.haml @@ -0,0 +1,68 @@ +- form_name = 'js-serverless-domain-settings' +- form_url = @domain.persisted? ? admin_serverless_domain_path(@domain.id, anchor: form_name) : admin_serverless_domains_path(anchor: form_name) +- show_certificate_card = @domain.persisted? && @domain.errors.blank? += form_for @domain, url: form_url, html: { class: 'fieldset-form' } do |f| + = form_errors(@domain) + + %fieldset + - if @domain.persisted? + - dns_record = "*.#{@domain.domain} CNAME #{Settings.pages.host}." + - verification_record = "#{@domain.verification_domain} TXT #{@domain.keyed_verification_code}" + .form-group.row + .col-sm-6.position-relative + = f.label :domain, _('Domain'), class: 'label-bold' + = f.text_field :domain, class: 'form-control has-floating-status-badge', readonly: true + .status-badge.floating-status-badge + - text, status = @domain.unverified? ? [_('Unverified'), 'badge-danger'] : [_('Verified'), 'badge-success'] + .badge{ class: status } + = text + = link_to sprite_icon("redo"), verify_admin_serverless_domain_path(@domain.id), method: :post, class: "btn has-tooltip", title: _("Retry verification") + + .col-sm-6 + = f.label :serverless_domain_dns, _('DNS'), class: 'label-bold' + .input-group + = text_field_tag :serverless_domain_dns, dns_record , class: "monospace js-select-on-focus form-control", readonly: true + .input-group-append + = clipboard_button(target: '#serverless_domain_dns', class: 'btn-default input-group-text d-none d-sm-block') + + .col-sm-12.form-text.text-muted + = _("To access this domain create a new DNS record") + + .form-group + = f.label :serverless_domain_verification, _('Verification status'), class: 'label-bold' + .input-group + = text_field_tag :serverless_domain_verification, verification_record, class: "monospace js-select-on-focus form-control", readonly: true + .input-group-append + = clipboard_button(target: '#serverless_domain_verification', class: 'btn-default d-none d-sm-block') + %p.form-text.text-muted + - link_to_help = link_to(_('verify ownership'), help_page_path('user/project/pages/custom_domains_ssl_tls_certification/index.md', anchor: '4-verify-the-domains-ownership')) + = _("To %{link_to_help} of your domain, add the above key to a TXT record within to your DNS configuration.").html_safe % { link_to_help: link_to_help } + + - else + .form-group + = f.label :domain, _('Domain'), class: 'label-bold' + = f.text_field :domain, class: 'form-control' + + - if show_certificate_card + .card.js-domain-cert-show + .card-header + = _('Certificate') + .d-flex.justify-content-between.align-items-center.p-3 + %span + = @domain.subject || _('missing') + %button.btn.btn-remove.btn-sm.js-domain-cert-replace-btn{ type: 'button' } + = _('Replace') + + .js-domain-cert-inputs{ class: ('hidden' if show_certificate_card) } + .form-group + = f.label :user_provided_certificate, _('Certificate (PEM)'), class: 'label-bold' + = f.text_area :user_provided_certificate, rows: 5, class: 'form-control', value: '' + %span.form-text.text-muted + = _("Upload a certificate for your domain with all intermediates") + .form-group + = f.label :user_provided_key, _('Key (PEM)'), class: 'label-bold' + = f.text_area :user_provided_key, rows: 5, class: 'form-control', value: '' + %span.form-text.text-muted + = _("Upload a private key for your certificate") + + = f.submit @domain.persisted? ? _('Save changes') : _('Add domain'), class: "btn btn-success js-serverless-domain-submit", disabled: @domain.persisted? diff --git a/app/views/admin/serverless/domains/index.html.haml b/app/views/admin/serverless/domains/index.html.haml new file mode 100644 index 00000000000..bd3c6bc6e04 --- /dev/null +++ b/app/views/admin/serverless/domains/index.html.haml @@ -0,0 +1,25 @@ +- breadcrumb_title _("Operations") +- page_title _("Operations") +- @content_class = "limit-container-width" unless fluid_layout + +-# normally expanded_by_default? is used here, but since this is the only panel +-# in this settings page, let's leave it always open by default +- expanded = true + +%section.settings.as-serverless-domain.no-animate#js-serverless-domain-settings{ class: ('expanded' if expanded) } + .settings-header + %h4 + = _('Serverless domain') + %button.btn.btn-default.js-settings-toggle{ type: 'button' } + = expanded ? _('Collapse') : _('Expand') + %p + = _('Set an instance-wide domain that will be available to all clusters when installing Knative.') + .settings-content + - if Gitlab.config.pages.enabled + = render 'form' + - else + .card + .card-header + = s_('GitLabPages|Domains') + .nothing-here-block + = s_("GitLabPages|Support for domains and certificates is disabled. Ask your system's administrator to enable it.") diff --git a/app/views/layouts/nav/sidebar/_admin.html.haml b/app/views/layouts/nav/sidebar/_admin.html.haml index e8e1da720cd..9f70124ba0d 100644 --- a/app/views/layouts/nav/sidebar/_admin.html.haml +++ b/app/views/layouts/nav/sidebar/_admin.html.haml @@ -254,6 +254,11 @@ = link_to ci_cd_admin_application_settings_path, title: _('CI/CD') do %span = _('CI/CD') + - if Feature.enabled?(:serverless_domain) + = nav_link(path: 'application_settings#operations') do + = link_to admin_serverless_domains_path, title: _('Operations') do + %span + = _('Operations') = nav_link(path: 'application_settings#reporting') do = link_to reporting_admin_application_settings_path, title: _('Reporting') do %span diff --git a/app/workers/environments/auto_stop_cron_worker.rb b/app/workers/environments/auto_stop_cron_worker.rb index 8fcda35b414..fdc9490453c 100644 --- a/app/workers/environments/auto_stop_cron_worker.rb +++ b/app/workers/environments/auto_stop_cron_worker.rb @@ -8,7 +8,7 @@ module Environments feature_category :continuous_delivery def perform - return unless Feature.enabled?(:auto_stop_environments) + return unless Feature.enabled?(:auto_stop_environments, default_enabled: true) AutoStopService.new.execute end |