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
path: root/app
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2020-04-04 03:09:37 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2020-04-04 03:09:37 +0300
commite3bdfa1a13d7e6c92716324c78b5b20c07eeb7c6 (patch)
treee8776263096b027d32d4be5118cccc87b00de2bc /app
parentc1a50b8195f4e36fda9b233acbde57a449bcf6c3 (diff)
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'app')
-rw-r--r--app/assets/javascripts/clusters/clusters_bundle.js12
-rw-r--r--app/assets/javascripts/clusters/components/applications.vue21
-rw-r--r--app/assets/javascripts/clusters/components/knative_domain_editor.vue105
-rw-r--r--app/assets/javascripts/clusters/stores/clusters_store.js9
-rw-r--r--app/assets/javascripts/lib/utils/url_utility.js8
-rw-r--r--app/assets/javascripts/vue_shared/components/clone_dropdown.vue89
-rw-r--r--app/controllers/admin/integrations_controller.rb6
-rw-r--r--app/controllers/clusters/applications_controller.rb2
-rw-r--r--app/controllers/concerns/integrations_actions.rb31
-rw-r--r--app/controllers/groups/settings/integrations_controller.rb6
-rw-r--r--app/models/project_services/jira_service.rb4
-rw-r--r--app/models/project_services/pipelines_email_service.rb2
-rw-r--r--app/models/service.rb4
13 files changed, 232 insertions, 67 deletions
diff --git a/app/assets/javascripts/clusters/clusters_bundle.js b/app/assets/javascripts/clusters/clusters_bundle.js
index da34c5030f9..1b11ec355bb 100644
--- a/app/assets/javascripts/clusters/clusters_bundle.js
+++ b/app/assets/javascripts/clusters/clusters_bundle.js
@@ -259,7 +259,7 @@ export default class Clusters {
eventHub.$on('installApplication', this.installApplication);
eventHub.$on('updateApplication', data => this.updateApplication(data));
eventHub.$on('saveKnativeDomain', data => this.saveKnativeDomain(data));
- eventHub.$on('setKnativeHostname', data => this.setKnativeHostname(data));
+ eventHub.$on('setKnativeDomain', data => this.setKnativeDomain(data));
eventHub.$on('uninstallApplication', data => this.uninstallApplication(data));
eventHub.$on('setCrossplaneProviderStack', data => this.setCrossplaneProviderStack(data));
eventHub.$on('setIngressModSecurityEnabled', data => this.setIngressModSecurityEnabled(data));
@@ -275,7 +275,7 @@ export default class Clusters {
eventHub.$off('installApplication', this.installApplication);
eventHub.$off('updateApplication', this.updateApplication);
eventHub.$off('saveKnativeDomain');
- eventHub.$off('setKnativeHostname');
+ eventHub.$off('setKnativeDomain');
eventHub.$off('setCrossplaneProviderStack');
eventHub.$off('uninstallApplication');
eventHub.$off('setIngressModSecurityEnabled');
@@ -521,10 +521,10 @@ export default class Clusters {
});
}
- setKnativeHostname(data) {
- const appId = data.id;
- this.store.updateAppProperty(appId, 'isEditingHostName', true);
- this.store.updateAppProperty(appId, 'hostname', data.hostname);
+ setKnativeDomain({ id: appId, domain, domainId }) {
+ this.store.updateAppProperty(appId, 'isEditingDomain', true);
+ this.store.updateAppProperty(appId, 'hostname', domain);
+ this.store.updateAppProperty(appId, 'pagesDomain', domainId ? { id: domainId, domain } : null);
}
setCrossplaneProviderStack(data) {
diff --git a/app/assets/javascripts/clusters/components/applications.vue b/app/assets/javascripts/clusters/components/applications.vue
index 219825b1c01..723030c5b8b 100644
--- a/app/assets/javascripts/clusters/components/applications.vue
+++ b/app/assets/javascripts/clusters/components/applications.vue
@@ -240,16 +240,20 @@ Crossplane runs inside your Kubernetes cluster and supports secure connectivity
this.helmInstallIllustration = helmInstallIllustration;
},
methods: {
- saveKnativeDomain(hostname) {
+ saveKnativeDomain() {
eventHub.$emit('saveKnativeDomain', {
id: 'knative',
- params: { hostname },
+ params: {
+ hostname: this.applications.knative.hostname,
+ pages_domain_id: this.applications.knative.pagesDomain?.id,
+ },
});
},
- setKnativeHostname(hostname) {
- eventHub.$emit('setKnativeHostname', {
+ setKnativeDomain({ domainId, domain }) {
+ eventHub.$emit('setKnativeDomain', {
id: 'knative',
- hostname,
+ domainId,
+ domain,
});
},
setCrossplaneProviderStack(stack) {
@@ -591,7 +595,10 @@ Crossplane runs inside your Kubernetes cluster and supports secure connectivity
:request-reason="applications.knative.requestReason"
:installed="applications.knative.installed"
:install-failed="applications.knative.installFailed"
- :install-application-request-params="{ hostname: applications.knative.hostname }"
+ :install-application-request-params="{
+ hostname: applications.knative.hostname,
+ pages_domain_id: applications.knative.pagesDomain && applications.knative.pagesDomain.id,
+ }"
:installed-via="installedVia"
:uninstallable="applications.knative.uninstallable"
:uninstall-successful="applications.knative.uninstallSuccessful"
@@ -628,7 +635,7 @@ Crossplane runs inside your Kubernetes cluster and supports secure connectivity
:knative="knative"
:ingress-dns-help-path="ingressDnsHelpPath"
@save="saveKnativeDomain"
- @set="setKnativeHostname"
+ @set="setKnativeDomain"
/>
</div>
</application-row>
diff --git a/app/assets/javascripts/clusters/components/knative_domain_editor.vue b/app/assets/javascripts/clusters/components/knative_domain_editor.vue
index 30efbe2e0f7..8136704d13b 100644
--- a/app/assets/javascripts/clusters/components/knative_domain_editor.vue
+++ b/app/assets/javascripts/clusters/components/knative_domain_editor.vue
@@ -1,5 +1,12 @@
<script>
-import { GlLoadingIcon } from '@gitlab/ui';
+import {
+ GlDropdown,
+ GlDropdownDivider,
+ GlDropdownItem,
+ GlLoadingIcon,
+ GlSearchBoxByType,
+ GlSprintf,
+} from '@gitlab/ui';
import LoadingButton from '~/vue_shared/components/loading_button.vue';
import ClipboardButton from '../../vue_shared/components/clipboard_button.vue';
import { __, s__ } from '~/locale';
@@ -13,6 +20,11 @@ export default {
LoadingButton,
ClipboardButton,
GlLoadingIcon,
+ GlDropdown,
+ GlDropdownDivider,
+ GlDropdownItem,
+ GlSearchBoxByType,
+ GlSprintf,
},
props: {
knative: {
@@ -25,6 +37,11 @@ export default {
required: false,
},
},
+ data() {
+ return {
+ searchQuery: '',
+ };
+ },
computed: {
saveButtonDisabled() {
return [UNINSTALLING, UPDATING].includes(this.knative.status);
@@ -49,9 +66,22 @@ export default {
return this.knative.hostname;
},
set(hostname) {
- this.$emit('set', hostname);
+ this.selectCustomDomain(hostname);
},
},
+ domainDropdownText() {
+ return this.knativeHostname || s__('ClusterIntegration|Select existing domain or use new');
+ },
+ availableDomains() {
+ return this.knative.availableDomains || [];
+ },
+ filteredDomains() {
+ const query = this.searchQuery.toLowerCase();
+ return this.availableDomains.filter(({ domain }) => domain.toLowerCase().includes(query));
+ },
+ showDomainsDropdown() {
+ return this.availableDomains.length > 0;
+ },
},
watch: {
knativeUpdateSuccessful(updateSuccessful) {
@@ -60,6 +90,14 @@ export default {
}
},
},
+ methods: {
+ selectDomain({ id, domain }) {
+ this.$emit('set', { domain, domainId: id });
+ },
+ selectCustomDomain(domain) {
+ this.$emit('set', { domain, domainId: null });
+ },
+ },
};
</script>
@@ -72,22 +110,55 @@ export default {
{{ s__('ClusterIntegration|Something went wrong while updating Knative domain name.') }}
</div>
- <template>
- <div
- :class="{ 'col-md-6': knativeInstalled, 'col-12': !knativeInstalled }"
- class="form-group col-sm-12 mb-0"
+ <div
+ :class="{ 'col-md-6': knativeInstalled, 'col-12': !knativeInstalled }"
+ class="form-group col-sm-12 mb-0"
+ >
+ <label for="knative-domainname">
+ <strong>{{ s__('ClusterIntegration|Knative Domain Name:') }}</strong>
+ </label>
+
+ <gl-dropdown
+ v-if="showDomainsDropdown"
+ :text="domainDropdownText"
+ toggle-class="dropdown-menu-toggle"
+ class="w-100 mb-2"
>
- <label for="knative-domainname">
- <strong>{{ s__('ClusterIntegration|Knative Domain Name:') }}</strong>
- </label>
- <input
- id="knative-domainname"
- v-model="knativeHostname"
- type="text"
- class="form-control js-knative-domainname"
+ <gl-search-box-by-type
+ v-model.trim="searchQuery"
+ :placeholder="s__('ClusterIntegration|Search domains')"
+ class="m-2"
/>
- </div>
- </template>
+ <gl-dropdown-item
+ v-for="domain in filteredDomains"
+ :key="domain.id"
+ @click="selectDomain(domain)"
+ >
+ <span class="ml-1">{{ domain.domain }}</span>
+ </gl-dropdown-item>
+ <template v-if="searchQuery">
+ <gl-dropdown-divider />
+ <gl-dropdown-item key="custom-domain" @click="selectCustomDomain(searchQuery)">
+ <span class="ml-1">
+ <gl-sprintf :message="s__('ClusterIntegration|Use %{query}')">
+ <template #query>
+ <code>{{ searchQuery }}</code>
+ </template>
+ </gl-sprintf>
+ </span>
+ </gl-dropdown-item>
+ </template>
+ </gl-dropdown>
+
+ <input
+ v-else
+ id="knative-domainname"
+ v-model="knativeHostname"
+ type="text"
+ class="form-control js-knative-domainname"
+ />
+ </div>
+
<template v-if="knativeInstalled">
<div class="form-group col-sm-12 col-md-6 pl-md-0 mb-0 mt-3 mt-md-0">
<label for="knative-endpoint">
@@ -144,7 +215,7 @@ export default {
:loading="saving"
:disabled="saveButtonDisabled"
:label="saveButtonLabel"
- @click="$emit('save', knativeHostname)"
+ @click="$emit('save')"
/>
</template>
</div>
diff --git a/app/assets/javascripts/clusters/stores/clusters_store.js b/app/assets/javascripts/clusters/stores/clusters_store.js
index 8685e3decc5..b09fd6800b6 100644
--- a/app/assets/javascripts/clusters/stores/clusters_store.js
+++ b/app/assets/javascripts/clusters/stores/clusters_store.js
@@ -93,7 +93,7 @@ export default class ClusterStore {
...applicationInitialState,
title: s__('ClusterIntegration|Knative'),
hostname: null,
- isEditingHostName: false,
+ isEditingDomain: false,
externalIp: null,
externalHostname: null,
updateSuccessful: false,
@@ -234,7 +234,12 @@ export default class ClusterStore {
'jupyter',
);
} else if (appId === KNATIVE) {
- if (!this.state.applications.knative.isEditingHostName) {
+ if (serverAppEntry.available_domains) {
+ this.state.applications.knative.availableDomains = serverAppEntry.available_domains;
+ }
+ if (!this.state.applications.knative.isEditingDomain) {
+ this.state.applications.knative.pagesDomain =
+ serverAppEntry.pages_domain || this.state.applications.knative.pagesDomain;
this.state.applications.knative.hostname =
serverAppEntry.hostname || this.state.applications.knative.hostname;
}
diff --git a/app/assets/javascripts/lib/utils/url_utility.js b/app/assets/javascripts/lib/utils/url_utility.js
index 1ff4f7bab97..a495d2040d3 100644
--- a/app/assets/javascripts/lib/utils/url_utility.js
+++ b/app/assets/javascripts/lib/utils/url_utility.js
@@ -318,3 +318,11 @@ export const setUrlParams = (params, url = window.location.href, clearParams = f
export function urlIsDifferent(url, compare = String(window.location)) {
return url !== compare;
}
+
+export function getHTTPProtocol(url) {
+ if (!url) {
+ return window.location.protocol.slice(0, -1);
+ }
+ const protocol = url.split(':');
+ return protocol.length > 1 ? protocol[0] : undefined;
+}
diff --git a/app/assets/javascripts/vue_shared/components/clone_dropdown.vue b/app/assets/javascripts/vue_shared/components/clone_dropdown.vue
new file mode 100644
index 00000000000..3b9b9f37f52
--- /dev/null
+++ b/app/assets/javascripts/vue_shared/components/clone_dropdown.vue
@@ -0,0 +1,89 @@
+<script>
+import {
+ GlNewDropdown,
+ GlNewDropdownHeader,
+ GlFormInputGroup,
+ GlNewButton,
+ GlIcon,
+ GlTooltipDirective,
+} from '@gitlab/ui';
+import { __, sprintf } from '~/locale';
+import { getHTTPProtocol } from '~/lib/utils/url_utility';
+
+export default {
+ components: {
+ GlNewDropdown,
+ GlNewDropdownHeader,
+ GlFormInputGroup,
+ GlNewButton,
+ GlIcon,
+ },
+ directives: {
+ GlTooltip: GlTooltipDirective,
+ },
+ props: {
+ sshLink: {
+ type: String,
+ required: false,
+ default: '',
+ },
+ httpLink: {
+ type: String,
+ required: false,
+ default: '',
+ },
+ },
+ computed: {
+ httpLabel() {
+ const protocol = this.httpLink ? getHTTPProtocol(this.httpLink)?.toUpperCase() : '';
+ return sprintf(__('Clone with %{protocol}'), { protocol });
+ },
+ },
+ labels: {
+ defaultLabel: __('Clone'),
+ ssh: __('Clone with SSH'),
+ },
+ copyURLTooltip: __('Copy URL'),
+};
+</script>
+<template>
+ <gl-new-dropdown :text="$options.labels.defaultLabel" category="primary" variant="info">
+ <div class="pb-2 mx-1">
+ <template v-if="sshLink">
+ <gl-new-dropdown-header>{{ $options.labels.ssh }}</gl-new-dropdown-header>
+
+ <div class="mx-3">
+ <gl-form-input-group :value="sshLink" readonly select-on-click>
+ <template #append>
+ <gl-new-button
+ v-gl-tooltip.hover
+ :title="$options.copyURLTooltip"
+ :data-clipboard-text="sshLink"
+ >
+ <gl-icon name="copy-to-clipboard" :title="$options.copyURLTooltip" />
+ </gl-new-button>
+ </template>
+ </gl-form-input-group>
+ </div>
+ </template>
+
+ <template v-if="httpLink">
+ <gl-new-dropdown-header>{{ httpLabel }}</gl-new-dropdown-header>
+
+ <div class="mx-3">
+ <gl-form-input-group :value="httpLink" readonly select-on-click>
+ <template #append>
+ <gl-new-button
+ v-gl-tooltip.hover
+ :title="$options.copyURLTooltip"
+ :data-clipboard-text="httpLink"
+ >
+ <gl-icon name="copy-to-clipboard" :title="$options.copyURLTooltip" />
+ </gl-new-button>
+ </template>
+ </gl-form-input-group>
+ </div>
+ </template>
+ </div>
+ </gl-new-dropdown>
+</template>
diff --git a/app/controllers/admin/integrations_controller.rb b/app/controllers/admin/integrations_controller.rb
index 0d79032233f..4f3be43d14d 100644
--- a/app/controllers/admin/integrations_controller.rb
+++ b/app/controllers/admin/integrations_controller.rb
@@ -5,6 +5,12 @@ class Admin::IntegrationsController < Admin::ApplicationController
private
+ def find_or_initialize_integration(name)
+ if name.in?(Service.available_services_names)
+ "#{name}_service".camelize.constantize.find_or_initialize_by(instance: true) # rubocop:disable CodeReuse/ActiveRecord
+ end
+ end
+
def integrations_enabled?
Feature.enabled?(:instance_level_integrations)
end
diff --git a/app/controllers/clusters/applications_controller.rb b/app/controllers/clusters/applications_controller.rb
index ba62cfeea7e..3ebd248c29e 100644
--- a/app/controllers/clusters/applications_controller.rb
+++ b/app/controllers/clusters/applications_controller.rb
@@ -47,7 +47,7 @@ class Clusters::ApplicationsController < Clusters::BaseController
end
def cluster_application_params
- params.permit(:application, :hostname, :email, :stack, :modsecurity_enabled, :modsecurity_mode)
+ params.permit(:application, :hostname, :pages_domain_id, :email, :stack, :modsecurity_enabled, :modsecurity_mode)
end
def cluster_application_destroy_params
diff --git a/app/controllers/concerns/integrations_actions.rb b/app/controllers/concerns/integrations_actions.rb
index ffb5d7a8086..4c998055a5d 100644
--- a/app/controllers/concerns/integrations_actions.rb
+++ b/app/controllers/concerns/integrations_actions.rb
@@ -37,11 +37,7 @@ module IntegrationsActions
end
def test
- if integration.can_test?
- render json: service_test_response, status: :ok
- else
- render json: {}, status: :not_found
- end
+ render json: {}, status: :ok
end
private
@@ -50,17 +46,11 @@ module IntegrationsActions
false
end
- # TODO: Use actual integrations on the group / instance level
- # To be completed in https://gitlab.com/groups/gitlab-org/-/epics/2430
- def project
- Project.first
- end
-
def integration
# Using instance variable `@service` still required as it's used in ServiceParams
# and app/views/shared/_service_settings.html.haml. Should be removed once
# those 2 are refactored to use `@integration`.
- @integration = @service ||= project.find_or_initialize_service(params[:id]) # rubocop:disable Gitlab/ModuleWithInstanceVariables
+ @integration = @service ||= find_or_initialize_integration(params[:id]) # rubocop:disable Gitlab/ModuleWithInstanceVariables
end
def success_message
@@ -74,21 +64,4 @@ module IntegrationsActions
.as_json(only: integration.json_fields)
.merge(errors: integration.errors.as_json)
end
-
- def service_test_response
- unless integration.update(service_params[:service])
- return { error: true, message: _('Validations failed.'), service_response: integration.errors.full_messages.join(','), test_failed: false }
- end
-
- data = integration.test_data(project, current_user)
- outcome = integration.test(data)
-
- unless outcome[:success]
- return { error: true, message: _('Test failed.'), service_response: outcome[:result].to_s, test_failed: true }
- end
-
- {}
- rescue Gitlab::HTTP::BlockedUrlError => e
- { error: true, message: _('Test failed.'), service_response: e.message, test_failed: true }
- end
end
diff --git a/app/controllers/groups/settings/integrations_controller.rb b/app/controllers/groups/settings/integrations_controller.rb
index 43f8a7118d4..0ba030f26bc 100644
--- a/app/controllers/groups/settings/integrations_controller.rb
+++ b/app/controllers/groups/settings/integrations_controller.rb
@@ -9,6 +9,12 @@ module Groups
private
+ # TODO: Make this compatible with group-level integration
+ # https://gitlab.com/groups/gitlab-org/-/epics/2543
+ def find_or_initialize_integration(name)
+ Project.first.find_or_initialize_service(name)
+ end
+
def integrations_enabled?
Feature.enabled?(:group_level_integrations, group)
end
diff --git a/app/models/project_services/jira_service.rb b/app/models/project_services/jira_service.rb
index 2766ba11c97..eaddac9cce3 100644
--- a/app/models/project_services/jira_service.rb
+++ b/app/models/project_services/jira_service.rb
@@ -201,8 +201,7 @@ class JiraService < IssueTrackerService
end
# Jira does not need test data.
- # We are requesting the project that belongs to the project key.
- def test_data(user = nil, project = nil)
+ def test_data(_, _)
nil
end
@@ -221,7 +220,6 @@ class JiraService < IssueTrackerService
def test_settings
return unless client_url.present?
- # Test settings by getting the project
jira_request { client.ServerInfo.all.attrs }
end
diff --git a/app/models/project_services/pipelines_email_service.rb b/app/models/project_services/pipelines_email_service.rb
index c3ed958242b..b5e5afb6ea5 100644
--- a/app/models/project_services/pipelines_email_service.rb
+++ b/app/models/project_services/pipelines_email_service.rb
@@ -53,7 +53,7 @@ class PipelinesEmailService < Service
end
def can_test?
- project.ci_pipelines.any?
+ project&.ci_pipelines&.any?
end
def test_data(project, user)
diff --git a/app/models/service.rb b/app/models/service.rb
index 6bb3a94ce81..017c15468a2 100644
--- a/app/models/service.rb
+++ b/app/models/service.rb
@@ -184,8 +184,10 @@ class Service < ApplicationRecord
{ success: result.present?, result: result }
end
+ # Disable test for instance-level services.
+ # https://gitlab.com/gitlab-org/gitlab/-/issues/213138
def can_test?
- true
+ !instance?
end
# Provide convenient accessor methods