diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2019-10-22 18:06:06 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2019-10-22 18:06:06 +0300 |
commit | 6653aab95dfdfd260e8814e7499cc2345f451f99 (patch) | |
tree | 695acdeb5be70a87a26e39a592dd302f29d1c1fc /app | |
parent | b1bcdba89bc241e2cede910f26cf3f5fff8d7901 (diff) |
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'app')
20 files changed, 241 insertions, 24 deletions
diff --git a/app/assets/images/cluster_app_logos/elastic_stack.png b/app/assets/images/cluster_app_logos/elastic_stack.png Binary files differnew file mode 100644 index 00000000000..69fbc6aacd0 --- /dev/null +++ b/app/assets/images/cluster_app_logos/elastic_stack.png diff --git a/app/assets/javascripts/clusters/clusters_bundle.js b/app/assets/javascripts/clusters/clusters_bundle.js index 7ea8901ecbb..17251ccdffb 100644 --- a/app/assets/javascripts/clusters/clusters_bundle.js +++ b/app/assets/javascripts/clusters/clusters_bundle.js @@ -37,6 +37,7 @@ export default class Clusters { installJupyterPath, installKnativePath, updateKnativePath, + installElasticStackPath, installPrometheusPath, managePrometheusPath, clusterEnvironmentsPath, @@ -86,6 +87,7 @@ export default class Clusters { installJupyterEndpoint: installJupyterPath, installKnativeEndpoint: installKnativePath, updateKnativeEndpoint: updateKnativePath, + installElasticStackEndpoint: installElasticStackPath, clusterEnvironmentsEndpoint: clusterEnvironmentsPath, }); diff --git a/app/assets/javascripts/clusters/components/applications.vue b/app/assets/javascripts/clusters/components/applications.vue index b95f97077f6..44d77277cc5 100644 --- a/app/assets/javascripts/clusters/components/applications.vue +++ b/app/assets/javascripts/clusters/components/applications.vue @@ -12,6 +12,7 @@ import certManagerLogo from 'images/cluster_app_logos/cert_manager.png'; import knativeLogo from 'images/cluster_app_logos/knative.png'; import meltanoLogo from 'images/cluster_app_logos/meltano.png'; import prometheusLogo from 'images/cluster_app_logos/prometheus.png'; +import elasticStackLogo from 'images/cluster_app_logos/elastic_stack.png'; import { s__, sprintf } from '../../locale'; import applicationRow from './application_row.vue'; import clipboardButton from '../../vue_shared/components/clipboard_button.vue'; @@ -91,6 +92,7 @@ export default { knativeLogo, meltanoLogo, prometheusLogo, + elasticStackLogo, }), computed: { isProjectCluster() { @@ -114,6 +116,9 @@ export default { certManagerInstalled() { return this.applications.cert_manager.status === APPLICATION_STATUS.INSTALLED; }, + enableClusterApplicationElasticStack() { + return gon.features && gon.features.enableClusterApplicationElasticStack; + }, ingressDescription() { return sprintf( _.escape( @@ -168,6 +173,12 @@ export default { jupyterHostname() { return this.applications.jupyter.hostname; }, + elasticStackInstalled() { + return this.applications.elastic_stack.status === APPLICATION_STATUS.INSTALLED; + }, + elasticStackKibanaHostname() { + return this.applications.elastic_stack.kibana_hostname; + }, knative() { return this.applications.knative; }, @@ -542,6 +553,75 @@ export default { /> </div> </application-row> + <application-row + v-if="enableClusterApplicationElasticStack" + id="elastic_stack" + :logo-url="elasticStackLogo" + :title="applications.elastic_stack.title" + :status="applications.elastic_stack.status" + :status-reason="applications.elastic_stack.statusReason" + :request-status="applications.elastic_stack.requestStatus" + :request-reason="applications.elastic_stack.requestReason" + :version="applications.elastic_stack.version" + :chart-repo="applications.elastic_stack.chartRepo" + :update-available="applications.elastic_stack.updateAvailable" + :installed="applications.elastic_stack.installed" + :install-failed="applications.elastic_stack.installFailed" + :update-successful="applications.elastic_stack.updateSuccessful" + :update-failed="applications.elastic_stack.updateFailed" + :uninstallable="applications.elastic_stack.uninstallable" + :uninstall-successful="applications.elastic_stack.uninstallSuccessful" + :uninstall-failed="applications.elastic_stack.uninstallFailed" + :disabled="!helmInstalled" + :install-application-request-params="{ + kibana_hostname: applications.elastic_stack.kibana_hostname, + }" + title-link="https://github.com/helm/charts/tree/master/stable/elastic-stack" + > + <div slot="description"> + <p> + {{ + s__( + `ClusterIntegration|The elastic stack collects logs from all pods in your cluster`, + ) + }} + </p> + + <template v-if="ingressExternalEndpoint"> + <div class="form-group"> + <label for="elastic-stack-kibana-hostname">{{ + s__('ClusterIntegration|Kibana Hostname') + }}</label> + + <div class="input-group"> + <input + v-model="applications.elastic_stack.kibana_hostname" + :readonly="elasticStackInstalled" + type="text" + class="form-control js-hostname" + /> + <span class="input-group-btn"> + <clipboard-button + :text="elasticStackKibanaHostname" + :title="s__('ClusterIntegration|Copy Kibana Hostname')" + class="js-clipboard-btn" + /> + </span> + </div> + + <p v-if="ingressInstalled" class="form-text text-muted"> + {{ + s__(`ClusterIntegration|Replace this with your own hostname if you want. + If you do so, point hostname to Ingress IP Address from above.`) + }} + <a :href="ingressDnsHelpPath" target="_blank" rel="noopener noreferrer"> + {{ __('More information') }} + </a> + </p> + </div> + </template> + </div> + </application-row> </div> </section> </template> diff --git a/app/assets/javascripts/clusters/components/uninstall_application_confirmation_modal.vue b/app/assets/javascripts/clusters/components/uninstall_application_confirmation_modal.vue index f1925c243f2..125bcaacc1c 100644 --- a/app/assets/javascripts/clusters/components/uninstall_application_confirmation_modal.vue +++ b/app/assets/javascripts/clusters/components/uninstall_application_confirmation_modal.vue @@ -2,7 +2,16 @@ import { GlModal } from '@gitlab/ui'; import { sprintf, s__ } from '~/locale'; import trackUninstallButtonClickMixin from 'ee_else_ce/clusters/mixins/track_uninstall_button_click'; -import { HELM, INGRESS, CERT_MANAGER, PROMETHEUS, RUNNER, KNATIVE, JUPYTER } from '../constants'; +import { + HELM, + INGRESS, + CERT_MANAGER, + PROMETHEUS, + RUNNER, + KNATIVE, + JUPYTER, + ELASTIC_STACK, +} from '../constants'; const CUSTOM_APP_WARNING_TEXT = { [HELM]: sprintf( @@ -28,6 +37,7 @@ const CUSTOM_APP_WARNING_TEXT = { [JUPYTER]: s__( 'ClusterIntegration|All data not committed to GitLab will be deleted and cannot be restored.', ), + [ELASTIC_STACK]: s__('ClusterIntegration|All data will be deleted and cannot be restored.'), }; export default { diff --git a/app/assets/javascripts/clusters/constants.js b/app/assets/javascripts/clusters/constants.js index c6e4b7951cf..d7152e32376 100644 --- a/app/assets/javascripts/clusters/constants.js +++ b/app/assets/javascripts/clusters/constants.js @@ -51,7 +51,17 @@ export const KNATIVE = 'knative'; export const RUNNER = 'runner'; export const CERT_MANAGER = 'cert_manager'; export const PROMETHEUS = 'prometheus'; +export const ELASTIC_STACK = 'elastic_stack'; -export const APPLICATIONS = [HELM, INGRESS, JUPYTER, KNATIVE, RUNNER, CERT_MANAGER, PROMETHEUS]; +export const APPLICATIONS = [ + HELM, + INGRESS, + JUPYTER, + KNATIVE, + RUNNER, + CERT_MANAGER, + PROMETHEUS, + ELASTIC_STACK, +]; export const INGRESS_DOMAIN_SUFFIX = '.nip.io'; diff --git a/app/assets/javascripts/clusters/services/clusters_service.js b/app/assets/javascripts/clusters/services/clusters_service.js index fa12802b3de..dab4da04bf3 100644 --- a/app/assets/javascripts/clusters/services/clusters_service.js +++ b/app/assets/javascripts/clusters/services/clusters_service.js @@ -11,6 +11,7 @@ export default class ClusterService { prometheus: this.options.installPrometheusEndpoint, jupyter: this.options.installJupyterEndpoint, knative: this.options.installKnativeEndpoint, + elastic_stack: this.options.installElasticStackEndpoint, }; this.appUpdateEndpointMap = { knative: this.options.updateKnativeEndpoint, diff --git a/app/assets/javascripts/clusters/stores/clusters_store.js b/app/assets/javascripts/clusters/stores/clusters_store.js index 6464461ea0c..6304e81c296 100644 --- a/app/assets/javascripts/clusters/stores/clusters_store.js +++ b/app/assets/javascripts/clusters/stores/clusters_store.js @@ -5,6 +5,7 @@ import { JUPYTER, KNATIVE, CERT_MANAGER, + ELASTIC_STACK, RUNNER, APPLICATION_INSTALLED_STATUSES, APPLICATION_STATUS, @@ -85,6 +86,11 @@ export default class ClusterStore { updateSuccessful: false, updateFailed: false, }, + elastic_stack: { + ...applicationInitialState, + title: s__('ClusterIntegration|Elastic Stack'), + kibana_hostname: null, + }, }, environments: [], fetchingEnvironments: false, @@ -198,12 +204,11 @@ export default class ClusterStore { this.state.applications.cert_manager.email = this.state.applications.cert_manager.email || serverAppEntry.email; } else if (appId === JUPYTER) { - this.state.applications.jupyter.hostname = - this.state.applications.jupyter.hostname || - serverAppEntry.hostname || - (this.state.applications.ingress.externalIp - ? `jupyter.${this.state.applications.ingress.externalIp}.nip.io` - : ''); + this.state.applications.jupyter.hostname = this.updateHostnameIfUnset( + this.state.applications.jupyter.hostname, + serverAppEntry.hostname, + 'jupyter', + ); } else if (appId === KNATIVE) { if (!this.state.applications.knative.isEditingHostName) { this.state.applications.knative.hostname = @@ -216,10 +221,26 @@ export default class ClusterStore { } else if (appId === RUNNER) { this.state.applications.runner.version = version; this.state.applications.runner.updateAvailable = updateAvailable; + } else if (appId === ELASTIC_STACK) { + this.state.applications.elastic_stack.kibana_hostname = this.updateHostnameIfUnset( + this.state.applications.elastic_stack.kibana_hostname, + serverAppEntry.kibana_hostname, + 'kibana', + ); } }); } + updateHostnameIfUnset(current, updated, fallback) { + return ( + current || + updated || + (this.state.applications.ingress.externalIp + ? `${fallback}.${this.state.applications.ingress.externalIp}.nip.io` + : '') + ); + } + toggleFetchEnvironments(isFetching) { this.state.fetchingEnvironments = isFetching; } diff --git a/app/assets/javascripts/pages/projects/project.js b/app/assets/javascripts/pages/projects/project.js index 435e8705803..01acfca158f 100644 --- a/app/assets/javascripts/pages/projects/project.js +++ b/app/assets/javascripts/pages/projects/project.js @@ -40,11 +40,6 @@ export default class Project { $label.text(activeText); }); - $('#modal-geo-info').data({ - cloneUrlSecondary: $this.attr('href'), - cloneUrlPrimary: $this.data('primaryUrl') || '', - }); - if (mobileCloneField) { mobileCloneField.dataset.clipboardText = url; } else { diff --git a/app/controllers/clusters/applications_controller.rb b/app/controllers/clusters/applications_controller.rb index 16c2365f85d..5364116a5f8 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) + params.permit(:application, :hostname, :kibana_hostname, :email) end def cluster_application_destroy_params diff --git a/app/controllers/clusters/clusters_controller.rb b/app/controllers/clusters/clusters_controller.rb index 993aba661f3..bb47ccb72b3 100644 --- a/app/controllers/clusters/clusters_controller.rb +++ b/app/controllers/clusters/clusters_controller.rb @@ -15,6 +15,9 @@ class Clusters::ClustersController < Clusters::BaseController before_action only: [:new, :create_gcp] do push_frontend_feature_flag(:create_eks_clusters) end + before_action only: [:show] do + push_frontend_feature_flag(:enable_cluster_application_elastic_stack) + end helper_method :token_in_session diff --git a/app/models/clusters/applications/elastic_stack.rb b/app/models/clusters/applications/elastic_stack.rb new file mode 100644 index 00000000000..addf092fc5e --- /dev/null +++ b/app/models/clusters/applications/elastic_stack.rb @@ -0,0 +1,79 @@ +# frozen_string_literal: true + +module Clusters + module Applications + class ElasticStack < ApplicationRecord + VERSION = '1.8.0' + + self.table_name = 'clusters_applications_elastic_stacks' + + include ::Clusters::Concerns::ApplicationCore + include ::Clusters::Concerns::ApplicationStatus + include ::Clusters::Concerns::ApplicationVersion + include ::Clusters::Concerns::ApplicationData + + default_value_for :version, VERSION + + def set_initial_status + return unless not_installable? + return unless cluster&.application_ingress_available? + + ingress = cluster.application_ingress + self.status = status_states[:installable] if ingress.external_ip_or_hostname? + end + + def chart + 'stable/elastic-stack' + end + + def values + content_values.to_yaml + end + + def install_command + Gitlab::Kubernetes::Helm::InstallCommand.new( + name: 'elastic-stack', + version: VERSION, + rbac: cluster.platform_kubernetes_rbac?, + chart: chart, + files: files + ) + end + + def uninstall_command + Gitlab::Kubernetes::Helm::DeleteCommand.new( + name: 'elastic-stack', + rbac: cluster.platform_kubernetes_rbac?, + files: files, + postdelete: post_delete_script + ) + end + + private + + def specification + { + "kibana" => { + "ingress" => { + "hosts" => [kibana_hostname], + "tls" => [{ + "hosts" => [kibana_hostname], + "secretName" => "kibana-cert" + }] + } + } + } + end + + def content_values + YAML.load_file(chart_values_file).deep_merge!(specification) + end + + def post_delete_script + [ + Gitlab::Kubernetes::KubectlCmd.delete("pvc", "--selector", "release=elastic-stack") + ].compact + end + end + end +end diff --git a/app/models/clusters/applications/ingress.rb b/app/models/clusters/applications/ingress.rb index 885e4ff7197..48712c8cc09 100644 --- a/app/models/clusters/applications/ingress.rb +++ b/app/models/clusters/applications/ingress.rb @@ -40,7 +40,7 @@ module Clusters end def allowed_to_uninstall? - external_ip_or_hostname? && application_jupyter_nil_or_installable? + external_ip_or_hostname? && application_jupyter_nil_or_installable? && application_elastic_stack_nil_or_installable? end def install_command @@ -91,6 +91,10 @@ module Clusters def application_jupyter_nil_or_installable? cluster.application_jupyter.nil? || cluster.application_jupyter&.installable? end + + def application_elastic_stack_nil_or_installable? + cluster.application_elastic_stack.nil? || cluster.application_elastic_stack&.installable? + end end end end diff --git a/app/models/clusters/applications/runner.rb b/app/models/clusters/applications/runner.rb index 954046c143b..fa15ec6703b 100644 --- a/app/models/clusters/applications/runner.rb +++ b/app/models/clusters/applications/runner.rb @@ -3,7 +3,7 @@ module Clusters module Applications class Runner < ApplicationRecord - VERSION = '0.9.0' + VERSION = '0.10.0' self.table_name = 'clusters_applications_runners' diff --git a/app/models/clusters/cluster.rb b/app/models/clusters/cluster.rb index d6f5d7c3f93..c600717f5df 100644 --- a/app/models/clusters/cluster.rb +++ b/app/models/clusters/cluster.rb @@ -18,7 +18,8 @@ module Clusters Applications::Prometheus.application_name => Applications::Prometheus, Applications::Runner.application_name => Applications::Runner, Applications::Jupyter.application_name => Applications::Jupyter, - Applications::Knative.application_name => Applications::Knative + Applications::Knative.application_name => Applications::Knative, + Applications::ElasticStack.application_name => Applications::ElasticStack }.merge(PROJECT_ONLY_APPLICATIONS).freeze DEFAULT_ENVIRONMENT = '*' KUBE_INGRESS_BASE_DOMAIN = 'KUBE_INGRESS_BASE_DOMAIN' @@ -51,6 +52,7 @@ module Clusters has_one_cluster_application :runner has_one_cluster_application :jupyter has_one_cluster_application :knative + has_one_cluster_application :elastic_stack has_many :kubernetes_namespaces diff --git a/app/models/issue.rb b/app/models/issue.rb index b9b481ac29b..91bef81227f 100644 --- a/app/models/issue.rb +++ b/app/models/issue.rb @@ -206,7 +206,16 @@ class Issue < ApplicationRecord if self.confidential? "#{iid}-confidential-issue" else - "#{iid}-#{title.parameterize}" + branch_name = "#{iid}-#{title.parameterize}" + + if branch_name.length > 100 + truncated_string = branch_name[0, 100] + # Delete everything dangling after the last hyphen so as not to risk + # existence of unintended words in the branch name due to mid-word split. + branch_name = truncated_string[0, truncated_string.rindex("-")] + end + + branch_name end end diff --git a/app/serializers/cluster_application_entity.rb b/app/serializers/cluster_application_entity.rb index 2a916b13f52..a5b983d4074 100644 --- a/app/serializers/cluster_application_entity.rb +++ b/app/serializers/cluster_application_entity.rb @@ -8,6 +8,7 @@ class ClusterApplicationEntity < Grape::Entity expose :external_ip, if: -> (e, _) { e.respond_to?(:external_ip) } expose :external_hostname, if: -> (e, _) { e.respond_to?(:external_hostname) } expose :hostname, if: -> (e, _) { e.respond_to?(:hostname) } + expose :kibana_hostname, if: -> (e, _) { e.respond_to?(:kibana_hostname) } expose :email, if: -> (e, _) { e.respond_to?(:email) } expose :update_available?, as: :update_available, if: -> (e, _) { e.respond_to?(:update_available?) } expose :can_uninstall?, as: :can_uninstall diff --git a/app/services/clusters/applications/base_service.rb b/app/services/clusters/applications/base_service.rb index 67fb3ac8355..b39fc7d20a9 100644 --- a/app/services/clusters/applications/base_service.rb +++ b/app/services/clusters/applications/base_service.rb @@ -19,6 +19,10 @@ module Clusters application.hostname = params[:hostname] end + if application.has_attribute?(:kibana_hostname) + application.kibana_hostname = params[:kibana_hostname] + end + if application.has_attribute?(:email) application.email = params[:email] end @@ -60,7 +64,7 @@ module Clusters end def invalid_application? - unknown_application? || (!cluster.project_type? && project_only_application?) + unknown_application? || (!cluster.project_type? && project_only_application?) || (application_name == Applications::ElasticStack.application_name && !Feature.enabled?(:enable_cluster_application_elastic_stack)) end def unknown_application? diff --git a/app/views/clusters/clusters/show.html.haml b/app/views/clusters/clusters/show.html.haml index 31d5f592d75..c5288c8d02d 100644 --- a/app/views/clusters/clusters/show.html.haml +++ b/app/views/clusters/clusters/show.html.haml @@ -17,6 +17,7 @@ install_jupyter_path: clusterable.install_applications_cluster_path(@cluster, :jupyter), install_knative_path: clusterable.install_applications_cluster_path(@cluster, :knative), update_knative_path: clusterable.update_applications_cluster_path(@cluster, :knative), + install_elastic_stack_path: clusterable.install_applications_cluster_path(@cluster, :elastic_stack), cluster_environments_path: cluster_environments_path, toggle_status: @cluster.enabled? ? 'true': 'false', has_rbac: has_rbac_enabled?(@cluster) ? 'true': 'false', diff --git a/app/views/projects/buttons/_clone.html.haml b/app/views/projects/buttons/_clone.html.haml index abef33ca01c..ed22573b23e 100644 --- a/app/views/projects/buttons/_clone.html.haml +++ b/app/views/projects/buttons/_clone.html.haml @@ -25,5 +25,3 @@ = clipboard_button(target: '#http_project_clone', title: _("Copy URL"), class: "input-group-text btn-default btn-clipboard") = render_if_exists 'projects/buttons/geo' = render_if_exists 'projects/buttons/kerberos_clone_field' - -= render_if_exists 'shared/geo_info_modal', project: project diff --git a/app/views/shared/_clone_panel.html.haml b/app/views/shared/_clone_panel.html.haml index cb834878276..3e805189055 100644 --- a/app/views/shared/_clone_panel.html.haml +++ b/app/views/shared/_clone_panel.html.haml @@ -22,6 +22,3 @@ .input-group-append = clipboard_button(target: '#project_clone', title: _("Copy URL"), class: "input-group-text btn-default btn-clipboard") - = render_if_exists 'shared/geo_modal_button' - -= render_if_exists 'shared/geo_modal', project: project |