diff options
author | Filipa Lacerda <filipa@gitlab.com> | 2018-02-19 14:03:41 +0000 |
---|---|---|
committer | Filipa Lacerda <filipa@gitlab.com> | 2018-02-19 14:05:09 +0000 |
commit | f0b27f9b406579a03e55fa16cbc7095009dc8c2b (patch) | |
tree | f4ca8bd423a68241f4ca2a80249947df5d3c6063 | |
parent | 9fc393c23dfa206802fdce162be1e06dca65ab54 (diff) | |
download | gitlab-ce-f0b27f9b406579a03e55fa16cbc7095009dc8c2b.tar.gz |
Adds support to render the IP address in the application ingress row
Updates components to use a slot to allow to reuse the clipboard button
Adds tests
5 files changed, 189 insertions, 27 deletions
diff --git a/app/assets/javascripts/clusters/components/application_row.vue b/app/assets/javascripts/clusters/components/application_row.vue index 50e35bbbba5..428a762a9c8 100644 --- a/app/assets/javascripts/clusters/components/application_row.vue +++ b/app/assets/javascripts/clusters/components/application_row.vue @@ -36,10 +36,6 @@ type: String, required: false, }, - description: { - type: String, - required: true, - }, status: { type: String, required: false, @@ -148,11 +144,14 @@ class="table-section section-wrap" role="gridcell" > - <div v-html="description"></div> + <slot name="description"></slot> </div> <div class="table-section table-button-footer section-align-top" - :class="{ 'section-20': showManageButton, 'section-15': !showManageButton }" + :class="{ + 'section-20': showManageButton, + 'section-15': !showManageButton, + }" role="gridcell" > <div diff --git a/app/assets/javascripts/clusters/components/applications.vue b/app/assets/javascripts/clusters/components/applications.vue index 978881a4831..69178cb0162 100644 --- a/app/assets/javascripts/clusters/components/applications.vue +++ b/app/assets/javascripts/clusters/components/applications.vue @@ -2,10 +2,15 @@ import _ from 'underscore'; import { s__, sprintf } from '../../locale'; import applicationRow from './application_row.vue'; + import clipboardButton from '../../vue_shared/components/clipboard_button.vue'; + import { + APPLICATION_INSTALLED, + } from '../constants'; export default { components: { applicationRow, + clipboardButton, }, props: { applications: { @@ -43,19 +48,10 @@ false, ); }, - helmTillerDescription() { - return _.escape(s__( - `ClusterIntegration|Helm streamlines installing and managing Kubernetes applications. - Tiller runs inside of your Kubernetes Cluster, and manages - releases of your charts.`, - )); + ingressInstalled() { + return this.applications.ingress.status === APPLICATION_INSTALLED; }, ingressDescription() { - const descriptionParagraph = _.escape(s__( - `ClusterIntegration|Ingress gives you a way to route requests to services based on the - request host or path, centralizing a number of services into a single entrypoint.`, - )); - const extraCostParagraph = sprintf( _.escape(s__( `ClusterIntegration|%{boldNotice} This will add some extra resources @@ -84,9 +80,6 @@ return ` <p> - ${descriptionParagraph} - </p> - <p> ${extraCostParagraph} </p> <p class="settings-message append-bottom-0"> @@ -136,33 +129,123 @@ id="helm" :title="applications.helm.title" title-link="https://docs.helm.sh/" - :description="helmTillerDescription" :status="applications.helm.status" :status-reason="applications.helm.statusReason" :request-status="applications.helm.requestStatus" :request-reason="applications.helm.requestReason" - /> + > + <div slot="description"> + {{ s__( + `ClusterIntegration|Helm streamlines installing and managing Kubernetes applications. + Tiller runs inside of your Kubernetes Cluster, and manages releases of your charts.`, + ) }} + </div> + </application-row> <application-row id="ingress" :title="applications.ingress.title" title-link="https://kubernetes.io/docs/concepts/services-networking/ingress/" - :description="ingressDescription" :status="applications.ingress.status" :status-reason="applications.ingress.statusReason" :request-status="applications.ingress.requestStatus" :request-reason="applications.ingress.requestReason" - /> + > + <div slot="description"> + <p> + {{ s__( + `ClusterIntegration|Ingress gives you a way to route + requests to services based on the request host or path, + centralizing a number of services into a single entrypoint.`, + ) }} + </p> + + <template v-if="ingressInstalled"> + <div class="form-group"> + <label for="ipAddress"> + {{ s__("ClusterIntegration| Ingress IP Address") }} + </label> + <div + v-if="applications.ingress.external_ip" + class="input-group" + > + <input + type="text" + id="ipAddress" + class="form-control js-select-on-focus" + :placeholder="applications.ingress.external_ip" + readonly + /> + <span class="input-group-btn"> + <clipboard-button + :text="applications.ingress.external_ip" + :title="s__('ClusterIntegration|Copy Ingress IP Address')" + css-class="btn btn-default js-clipboard-btn" + /> + </span> + </div> + <input + v-else + type="text" + id="ipAddress" + class="form-control" + readonly + placeholder="?" + /> + </div> + + <p + v-if="!applications.ingress.external_ip" + class="settings-message js-no-ip-message" + > + {{ s__(`ClusterIntegration|The IP address is in process + to be assigned, please check your Kubernetes + cluster or Quotas on GKE if it takes a long time.`) }} + <a + href="TODO" + target="_blank" + rel="noopener noreferrer" + > + {{ __("More information") }} + </a> + </p> + + <p> + {{ s__(`ClusterIntegration|Point a wildcard DNS to this + generated IP address in order to access + your application after it has been deployed.`) }} + <a + href="TODO" + target="_blank" + rel="noopener noreferrer" + > + {{ __("More information") }} + </a> + </p> + + </template> + <template + v-else + v-html="ingressDescription" + > + </template> + </div> + </application-row> <application-row id="prometheus" :title="applications.prometheus.title" title-link="https://prometheus.io/docs/introduction/overview/" :manage-link="managePrometheusPath" - :description="prometheusDescription" :status="applications.prometheus.status" :status-reason="applications.prometheus.statusReason" :request-status="applications.prometheus.requestStatus" :request-reason="applications.prometheus.requestReason" - /> + > + <div + slot="description" + v-html="prometheusDescription" + > + </div> + </application-row> <!-- NOTE: Don't forget to update `clusters.scss` min-height for this block and uncomment `application_spec` tests diff --git a/app/assets/javascripts/vue_shared/components/clipboard_button.vue b/app/assets/javascripts/vue_shared/components/clipboard_button.vue index 31d9b9d9c48..ca4ad8eea92 100644 --- a/app/assets/javascripts/vue_shared/components/clipboard_button.vue +++ b/app/assets/javascripts/vue_shared/components/clipboard_button.vue @@ -28,6 +28,11 @@ required: false, default: false, }, + cssClass: { + type: String, + required: false, + default: 'btn btn-default btn-transparent btn-clipboard', + }, }, }; </script> @@ -35,7 +40,7 @@ <template> <button type="button" - class="btn btn-transparent btn-clipboard" + :class="cssClass" :title="title" :data-clipboard-text="text" v-tooltip diff --git a/changelogs/unreleased/42643-persist-external-ip-of-ingress-controller-gke.yml b/changelogs/unreleased/42643-persist-external-ip-of-ingress-controller-gke.yml new file mode 100644 index 00000000000..8303a5860d6 --- /dev/null +++ b/changelogs/unreleased/42643-persist-external-ip-of-ingress-controller-gke.yml @@ -0,0 +1,5 @@ +--- +title: Display ingress IP address in the Kubernetes page +merge_request: +author: +type: fixed diff --git a/spec/javascripts/clusters/components/applications_spec.js b/spec/javascripts/clusters/components/applications_spec.js index 1a8affad4e3..d055679aea8 100644 --- a/spec/javascripts/clusters/components/applications_spec.js +++ b/spec/javascripts/clusters/components/applications_spec.js @@ -44,4 +44,74 @@ describe('Applications', () => { }); /* */ }); + + describe('Ingress application', () => { + describe('when installed', () => { + describe('with ip address', () => { + it('renders ip address with a clipboard button', () => { + vm = mountComponent(Applications, { + applications: { + ingress: { + title: 'Ingress', + status: 'installed', + external_ip: '0.0.0.0', + }, + helm: { title: 'Helm Tiller' }, + runner: { title: 'GitLab Runner' }, + prometheus: { title: 'Prometheus' }, + }, + }); + + expect( + vm.$el.querySelector('#ipAddress').getAttribute('placeholder'), + ).toEqual('0.0.0.0'); + expect( + vm.$el.querySelector('.js-clipboard-btn').getAttribute('data-clipboard-text'), + ).toEqual('0.0.0.0'); + }); + }); + + describe('without ip address', () => { + it('renders an input text with a question mark and an alert text', () => { + vm = mountComponent(Applications, { + applications: { + ingress: { + title: 'Ingress', + status: 'installed', + }, + helm: { title: 'Helm Tiller' }, + runner: { title: 'GitLab Runner' }, + prometheus: { title: 'Prometheus' }, + }, + }); + + expect( + vm.$el.querySelector('#ipAddress').getAttribute('placeholder'), + ).toEqual('?'); + + expect( + vm.$el.querySelector('.js-no-ip-message').textContent.replace(/\n(\s)+/g, ' ').trim(), + ).toEqual( + 'The IP address is in process to be assigned, please check your Kubernetes cluster or Quotas on GKE if it takes a long time. More information', + ); + }); + }); + }); + + describe('before installing', () => { + it('does not render the IP address', () => { + vm = mountComponent(Applications, { + applications: { + helm: { title: 'Helm Tiller' }, + ingress: { title: 'Ingress' }, + runner: { title: 'GitLab Runner' }, + prometheus: { title: 'Prometheus' }, + }, + }); + + expect(vm.$el.textContent).not.toContain('Ingress IP Address'); + expect(vm.$el.querySelector('#ipAddress')).toBe(null); + }); + }); + }); }); |