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
diff options
context:
space:
mode:
authorDmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>2018-05-16 12:01:13 +0300
committerDmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>2018-05-25 17:16:41 +0300
commit4220e914db356f4a55c771a7ad7f559e2507dd56 (patch)
tree104c2b12cc9369985dd6e0f938a94077e680ddb3 /app/assets/javascripts
parent8a1ac8f4ce0d8e96234ef32cd032adaf7cc57b1a (diff)
Add support for Jupyter in GitLab via Kubernetes
Signed-off-by: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>
Diffstat (limited to 'app/assets/javascripts')
-rw-r--r--app/assets/javascripts/clusters/clusters_bundle.js2
-rw-r--r--app/assets/javascripts/clusters/components/applications.vue99
-rw-r--r--app/assets/javascripts/clusters/constants.js1
-rw-r--r--app/assets/javascripts/clusters/services/clusters_service.js10
-rw-r--r--app/assets/javascripts/clusters/stores/clusters_store.js12
5 files changed, 121 insertions, 3 deletions
diff --git a/app/assets/javascripts/clusters/clusters_bundle.js b/app/assets/javascripts/clusters/clusters_bundle.js
index 01aec4f36af..6bf9dca1112 100644
--- a/app/assets/javascripts/clusters/clusters_bundle.js
+++ b/app/assets/javascripts/clusters/clusters_bundle.js
@@ -31,6 +31,7 @@ export default class Clusters {
installHelmPath,
installIngressPath,
installRunnerPath,
+ installJupyterPath,
installPrometheusPath,
managePrometheusPath,
clusterStatus,
@@ -51,6 +52,7 @@ export default class Clusters {
installIngressEndpoint: installIngressPath,
installRunnerEndpoint: installRunnerPath,
installPrometheusEndpoint: installPrometheusPath,
+ installJupyterEndpoint: installJupyterPath,
});
this.installApplication = this.installApplication.bind(this);
diff --git a/app/assets/javascripts/clusters/components/applications.vue b/app/assets/javascripts/clusters/components/applications.vue
index 9c12b89240c..e03db7b8974 100644
--- a/app/assets/javascripts/clusters/components/applications.vue
+++ b/app/assets/javascripts/clusters/components/applications.vue
@@ -37,6 +37,11 @@ export default {
default: '',
},
},
+ data() {
+ return {
+ jupyterSuggestHostnameValue: '',
+ };
+ },
computed: {
generalApplicationDescription() {
return sprintf(
@@ -121,6 +126,20 @@ export default {
false,
);
},
+ jupyterInstalled() {
+ return this.applications.jupyter.status === APPLICATION_INSTALLED;
+ },
+ jupyterHostname() {
+ return this.applications.jupyter.hostname;
+ },
+ jupyterSuggestHostname() {
+ return `jupyter.${this.applications.ingress.externalIp}.xip.io`;
+ },
+ },
+ watch: {
+ jupyterSuggestHostname() {
+ this.jupyterSuggestHostnameValue = this.jupyterSuggestHostname;
+ },
},
};
</script>
@@ -278,11 +297,89 @@ export default {
applications to production.`) }}
</div>
</application-row>
+ <application-row
+ id="jupyter"
+ :title="applications.jupyter.title"
+ title-link="https://jupyterhub.readthedocs.io/en/stable/"
+ :status="applications.jupyter.status"
+ :status-reason="applications.jupyter.statusReason"
+ :request-status="applications.jupyter.requestStatus"
+ :request-reason="applications.jupyter.requestReason"
+ >
+ <div slot="description">
+ <p>
+ {{ s__(`ClusterIntegration|JupyterHub, a multi-user Hub, spawns,
+ manages, and proxies multiple instances of the single-user
+ Jupyter notebook server. JupyterHub can be used to serve
+ notebooks to a class of students, a corporate data science group,
+ or a scientific research group.`) }}
+ </p>
+ <template v-if="jupyterInstalled">
+ <div class="form-group">
+ <label for="jupyter-hostname">
+ {{ s__('ClusterIntegration|Jupyter Hostname') }}
+ </label>
+ <div
+ v-if="jupyterHostname"
+ class="input-group"
+ >
+ <input
+ type="text"
+ id="jupyter-hostname"
+ class="form-control js-hostname"
+ :value="jupyterHostname"
+ readonly
+ />
+ <span class="input-group-btn">
+ <clipboard-button
+ :text="jupyterHostname"
+ :title="s__('ClusterIntegration|Copy Jupyter Hostname to clipboard')"
+ class="js-clipboard-btn"
+ />
+ </span>
+ </div>
+ </div>
+ </template>
+ <template v-else-if="ingressInstalled">
+ <div class="form-group">
+ <label for="jupyter-hostname">
+ {{ s__('ClusterIntegration|Jupyter Hostname') }}
+ </label>
+ <div class="input-group">
+ <input
+ type="text"
+ id="jupyter-hostname"
+ class="form-control js-hostname"
+ v-model="jupyterSuggestHostnameValue"
+ />
+ <span class="input-group-btn">
+ <clipboard-button
+ :text="jupyterHostname"
+ :title="s__('ClusterIntegration|Copy Jupyter Hostname to clipboard')"
+ class="js-clipboard-btn"
+ />
+ </span>
+ </div>
+ </div>
+ <p>
+ {{ 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>
+ </template>
+ </div>
+ </application-row>
<!--
NOTE: Don't forget to update `clusters.scss`
min-height for this block and uncomment `application_spec` tests
-->
- <!-- Add GitLab Runner row, all other plumbing is complete -->
+ <!-- Add Jupyter row, all other plumbing is complete -->
</div>
</div>
</section>
diff --git a/app/assets/javascripts/clusters/constants.js b/app/assets/javascripts/clusters/constants.js
index b7179f52bb3..371f71fde44 100644
--- a/app/assets/javascripts/clusters/constants.js
+++ b/app/assets/javascripts/clusters/constants.js
@@ -11,3 +11,4 @@ export const REQUEST_LOADING = 'request-loading';
export const REQUEST_SUCCESS = 'request-success';
export const REQUEST_FAILURE = 'request-failure';
export const INGRESS = 'ingress';
+export const JUPYTER = 'jupyter';
diff --git a/app/assets/javascripts/clusters/services/clusters_service.js b/app/assets/javascripts/clusters/services/clusters_service.js
index 13468578f4f..e49db9c2f4f 100644
--- a/app/assets/javascripts/clusters/services/clusters_service.js
+++ b/app/assets/javascripts/clusters/services/clusters_service.js
@@ -1,4 +1,5 @@
import axios from '../../lib/utils/axios_utils';
+import { JUPYTER } from '../constants';
export default class ClusterService {
constructor(options = {}) {
@@ -8,6 +9,7 @@ export default class ClusterService {
ingress: this.options.installIngressEndpoint,
runner: this.options.installRunnerEndpoint,
prometheus: this.options.installPrometheusEndpoint,
+ jupyter: this.options.installJupyterEndpoint,
};
}
@@ -16,7 +18,13 @@ export default class ClusterService {
}
installApplication(appId) {
- return axios.post(this.appInstallEndpointMap[appId]);
+ const data = {};
+
+ if (appId === JUPYTER) {
+ data.hostname = document.getElementById('jupyter-hostname').value;
+ }
+
+ return axios.post(this.appInstallEndpointMap[appId], data);
}
static updateCluster(endpoint, data) {
diff --git a/app/assets/javascripts/clusters/stores/clusters_store.js b/app/assets/javascripts/clusters/stores/clusters_store.js
index 348bbec3b25..f609b425190 100644
--- a/app/assets/javascripts/clusters/stores/clusters_store.js
+++ b/app/assets/javascripts/clusters/stores/clusters_store.js
@@ -1,5 +1,5 @@
import { s__ } from '../../locale';
-import { INGRESS } from '../constants';
+import { INGRESS, JUPYTER } from '../constants';
export default class ClusterStore {
constructor() {
@@ -38,6 +38,14 @@ export default class ClusterStore {
requestStatus: null,
requestReason: null,
},
+ jupyter: {
+ title: s__('ClusterIntegration|JupyterHub'),
+ status: null,
+ statusReason: null,
+ requestStatus: null,
+ requestReason: null,
+ hostname: null,
+ },
},
};
}
@@ -83,6 +91,8 @@ export default class ClusterStore {
if (appId === INGRESS) {
this.state.applications.ingress.externalIp = serverAppEntry.external_ip;
+ } else if (appId === JUPYTER) {
+ this.state.applications.jupyter.hostname = serverAppEntry.hostname;
}
});
}