applications.vue 17.7 KB
Newer Older
1
<script>
2
import _ from 'underscore';
3
import helmInstallIllustration from '@gitlab/svgs/dist/illustrations/kubernetes-installation.svg';
4 5 6 7 8 9
import elasticsearchLogo from 'images/cluster_app_logos/elasticsearch.png';
import gitlabLogo from 'images/cluster_app_logos/gitlab.png';
import helmLogo from 'images/cluster_app_logos/helm.png';
import jeagerLogo from 'images/cluster_app_logos/jeager.png';
import jupyterhubLogo from 'images/cluster_app_logos/jupyterhub.png';
import kubernetesLogo from 'images/cluster_app_logos/kubernetes.png';
Amit Rathi's avatar
Amit Rathi committed
10
import certManagerLogo from 'images/cluster_app_logos/cert_manager.png';
Chris Baumbauer's avatar
Chris Baumbauer committed
11
import knativeLogo from 'images/cluster_app_logos/knative.png';
12 13
import meltanoLogo from 'images/cluster_app_logos/meltano.png';
import prometheusLogo from 'images/cluster_app_logos/prometheus.png';
14 15 16
import { s__, sprintf } from '../../locale';
import applicationRow from './application_row.vue';
import clipboardButton from '../../vue_shared/components/clipboard_button.vue';
17
import { CLUSTER_TYPE, APPLICATION_STATUS, INGRESS } from '../constants';
18

19 20 21 22 23 24
export default {
  components: {
    applicationRow,
    clipboardButton,
  },
  props: {
25 26 27
    type: {
      type: String,
      required: false,
28
      default: CLUSTER_TYPE.PROJECT,
29
    },
30 31 32 33
    applications: {
      type: Object,
      required: false,
      default: () => ({}),
34
    },
35 36 37 38
    helpPath: {
      type: String,
      required: false,
      default: '',
39
    },
40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55
    ingressHelpPath: {
      type: String,
      required: false,
      default: '',
    },
    ingressDnsHelpPath: {
      type: String,
      required: false,
      default: '',
    },
    managePrometheusPath: {
      type: String,
      required: false,
      default: '',
    },
  },
56 57 58 59 60 61 62
  data: () => ({
    elasticsearchLogo,
    gitlabLogo,
    helmLogo,
    jeagerLogo,
    jupyterhubLogo,
    kubernetesLogo,
Amit Rathi's avatar
Amit Rathi committed
63
    certManagerLogo,
Chris Baumbauer's avatar
Chris Baumbauer committed
64
    knativeLogo,
65 66 67
    meltanoLogo,
    prometheusLogo,
  }),
68
  computed: {
69
    isProjectCluster() {
70
      return this.type === CLUSTER_TYPE.PROJECT;
71
    },
72 73 74 75
    helmInstalled() {
      return (
        this.applications.helm.status === APPLICATION_STATUS.INSTALLED ||
        this.applications.helm.status === APPLICATION_STATUS.UPDATED
76 77 78 79 80 81
      );
    },
    ingressId() {
      return INGRESS;
    },
    ingressInstalled() {
82
      return this.applications.ingress.status === APPLICATION_STATUS.INSTALLED;
83 84 85 86 87 88 89 90
    },
    ingressExternalIp() {
      return this.applications.ingress.externalIp;
    },
    ingressDescription() {
      const extraCostParagraph = sprintf(
        _.escape(
          s__(
91 92
            `ClusterIntegration|%{boldNotice} This will add some extra resources
            like a load balancer, which may incur additional costs depending on
93 94 95 96 97 98 99
            the hosting provider your Kubernetes cluster is installed on. If you are using
            Google Kubernetes Engine, you can %{pricingLink}.`,
          ),
        ),
        {
          boldNotice: `<strong>${_.escape(s__('ClusterIntegration|Note:'))}</strong>`,
          pricingLink: `<a href="https://cloud.google.com/compute/pricing#lb" target="_blank" rel="noopener noreferrer">
100
              ${_.escape(s__('ClusterIntegration|check the pricing here'))}</a>`,
101 102 103
        },
        false,
      );
104

105 106 107
      const externalIpParagraph = sprintf(
        _.escape(
          s__(
108 109
            `ClusterIntegration|After installing Ingress, you will need to point your wildcard DNS
            at the generated external IP address in order to view your app after it is deployed. %{ingressHelpLink}`,
110 111 112 113
          ),
        ),
        {
          ingressHelpLink: `<a href="${this.ingressHelpPath}">
114 115
              ${_.escape(s__('ClusterIntegration|More information'))}
            </a>`,
116 117 118
        },
        false,
      );
119

120
      return `
121
          <p>
122 123
            ${extraCostParagraph}
          </p>
124 125 126
          <p class="settings-message append-bottom-0">
            ${externalIpParagraph}
          </p>
127
        `;
128
    },
129 130 131 132 133 134 135 136 137 138 139 140
    certManagerDescription() {
      return sprintf(
        _.escape(
          s__(
            `ClusterIntegration|cert-manager is a native Kubernetes certificate management controller that helps with issuing certificates.
            Installing cert-manager on your cluster will issue a certificate by %{letsEncrypt} and ensure that certificates
            are valid and up to date.`,
          ),
        ),
        {
          letsEncrypt: `<a href="https://letsencrypt.org/"
              target="_blank" rel="noopener noreferrer">
Amit Rathi's avatar
Amit Rathi committed
141
              ${_.escape(s__("ClusterIntegration|Let's Encrypt"))}</a>`,
142 143 144 145
        },
        false,
      );
    },
146 147 148 149
    prometheusDescription() {
      return sprintf(
        _.escape(
          s__(
150 151
            `ClusterIntegration|Prometheus is an open-source monitoring system
            with %{gitlabIntegrationLink} to monitor deployed applications.`,
152 153 154 155
          ),
        ),
        {
          gitlabIntegrationLink: `<a href="https://docs.gitlab.com/ce/user/project/integrations/prometheus.html"
156
              target="_blank" rel="noopener noreferrer">
157
              ${_.escape(s__('ClusterIntegration|GitLab Integration'))}</a>`,
158 159 160
        },
        false,
      );
161
    },
162
    jupyterInstalled() {
163
      return this.applications.jupyter.status === APPLICATION_STATUS.INSTALLED;
164 165 166 167
    },
    jupyterHostname() {
      return this.applications.jupyter.hostname;
    },
Chris Baumbauer's avatar
Chris Baumbauer committed
168 169 170
    knativeInstalled() {
      return this.applications.knative.status === APPLICATION_STATUS.INSTALLED;
    },
171 172 173
    knativeExternalIp() {
      return this.applications.knative.externalIp;
    },
174
  },
175 176 177
  created() {
    this.helmInstallIllustration = helmInstallIllustration;
  },
178
};
179 180 181
</script>

<template>
182
  <section id="cluster-applications">
Mike Greiling's avatar
Mike Greiling committed
183
    <h4>{{ s__('ClusterIntegration|Applications') }}</h4>
184
    <p class="append-bottom-0">
Mike Greiling's avatar
Mike Greiling committed
185 186 187 188 189
      {{
        s__(`ClusterIntegration|Choose which applications to install on your Kubernetes cluster.
        Helm Tiller is required to install any of the following applications.`)
      }}
      <a :href="helpPath"> {{ __('More information') }} </a>
190
    </p>
191

192 193 194 195 196 197 198 199 200 201 202 203 204
    <div class="cluster-application-list prepend-top-10">
      <application-row
        id="helm"
        :logo-url="helmLogo"
        :title="applications.helm.title"
        :status="applications.helm.status"
        :status-reason="applications.helm.statusReason"
        :request-status="applications.helm.requestStatus"
        :request-reason="applications.helm.requestReason"
        class="rounded-top"
        title-link="https://docs.helm.sh/"
      >
        <div slot="description">
Mike Greiling's avatar
Mike Greiling committed
205 206
          {{
            s__(`ClusterIntegration|Helm streamlines installing
207 208
            and managing Kubernetes applications.
            Tiller runs inside of your Kubernetes Cluster,
Mike Greiling's avatar
Mike Greiling committed
209 210
            and manages releases of your charts.`)
          }}
211 212
        </div>
      </application-row>
Mike Greiling's avatar
Mike Greiling committed
213 214 215 216 217 218
      <div v-show="!helmInstalled" class="cluster-application-warning">
        <div class="svg-container" v-html="helmInstallIllustration"></div>
        {{
          s__(`ClusterIntegration|You must first install Helm Tiller before
          installing the applications below`)
        }}
219 220 221 222 223 224 225 226 227 228 229 230 231 232
      </div>
      <application-row
        :id="ingressId"
        :logo-url="kubernetesLogo"
        :title="applications.ingress.title"
        :status="applications.ingress.status"
        :status-reason="applications.ingress.statusReason"
        :request-status="applications.ingress.requestStatus"
        :request-reason="applications.ingress.requestReason"
        :disabled="!helmInstalled"
        title-link="https://kubernetes.io/docs/concepts/services-networking/ingress/"
      >
        <div slot="description">
          <p>
Mike Greiling's avatar
Mike Greiling committed
233 234
            {{
              s__(`ClusterIntegration|Ingress gives you a way to route
235
              requests to services based on the request host or path,
Mike Greiling's avatar
Mike Greiling committed
236 237
              centralizing a number of services into a single entrypoint.`)
            }}
238
          </p>
239

240 241 242 243 244
          <template v-if="ingressInstalled">
            <div class="form-group">
              <label for="ingress-ip-address">
                {{ s__('ClusterIntegration|Ingress IP Address') }}
              </label>
Mike Greiling's avatar
Mike Greiling committed
245
              <div v-if="ingressExternalIp" class="input-group">
246
                <input
247 248
                  id="ingress-ip-address"
                  :value="ingressExternalIp"
249
                  type="text"
Filipa Lacerda's avatar
Filipa Lacerda committed
250
                  class="form-control js-ip-address"
251 252
                  readonly
                />
253 254 255 256 257 258 259
                <span class="input-group-append">
                  <clipboard-button
                    :text="ingressExternalIp"
                    :title="s__('ClusterIntegration|Copy Ingress IP Address to clipboard')"
                    class="input-group-text js-clipboard-btn"
                  />
                </span>
260
              </div>
Mike Greiling's avatar
Mike Greiling committed
261
              <input v-else type="text" class="form-control js-ip-address" readonly value="?" />
262
            </div>
263

Mike Greiling's avatar
Mike Greiling committed
264 265 266
            <p v-if="!ingressExternalIp" class="settings-message js-no-ip-message">
              {{
                s__(`ClusterIntegration|The IP address is in
267
              the process of being assigned. Please check your Kubernetes
Mike Greiling's avatar
Mike Greiling committed
268 269
              cluster or Quotas on Google Kubernetes Engine if it takes a long time.`)
              }}
270

Mike Greiling's avatar
Mike Greiling committed
271
              <a :href="ingressHelpPath" target="_blank" rel="noopener noreferrer">
272 273 274
                {{ __('More information') }}
              </a>
            </p>
275

276
            <p>
Mike Greiling's avatar
Mike Greiling committed
277 278
              {{
                s__(`ClusterIntegration|Point a wildcard DNS to this
279
              generated IP address in order to access
Mike Greiling's avatar
Mike Greiling committed
280 281 282
              your application after it has been deployed.`)
              }}
              <a :href="ingressDnsHelpPath" target="_blank" rel="noopener noreferrer">
283 284 285 286
                {{ __('More information') }}
              </a>
            </p>
          </template>
Mike Greiling's avatar
Mike Greiling committed
287
          <div v-html="ingressDescription"></div>
288 289
        </div>
      </application-row>
Amit Rathi's avatar
Amit Rathi committed
290 291 292 293 294 295 296 297 298 299 300
      <application-row
        id="cert_manager"
        :logo-url="certManagerLogo"
        :title="applications.cert_manager.title"
        :status="applications.cert_manager.status"
        :status-reason="applications.cert_manager.statusReason"
        :request-status="applications.cert_manager.requestStatus"
        :request-reason="applications.cert_manager.requestReason"
        :disabled="!helmInstalled"
        title-link="https://cert-manager.readthedocs.io/en/latest/#"
      >
301
        <div slot="description" v-html="certManagerDescription"></div>
Amit Rathi's avatar
Amit Rathi committed
302
      </application-row>
303
      <application-row
304
        v-if="isProjectCluster"
305 306 307 308 309 310 311 312 313 314 315
        id="prometheus"
        :logo-url="prometheusLogo"
        :title="applications.prometheus.title"
        :manage-link="managePrometheusPath"
        :status="applications.prometheus.status"
        :status-reason="applications.prometheus.statusReason"
        :request-status="applications.prometheus.requestStatus"
        :request-reason="applications.prometheus.requestReason"
        :disabled="!helmInstalled"
        title-link="https://prometheus.io/docs/introduction/overview/"
      >
Mike Greiling's avatar
Mike Greiling committed
316
        <div slot="description" v-html="prometheusDescription"></div>
317 318
      </application-row>
      <application-row
319
        v-if="isProjectCluster"
320 321 322 323 324 325 326 327 328 329 330
        id="runner"
        :logo-url="gitlabLogo"
        :title="applications.runner.title"
        :status="applications.runner.status"
        :status-reason="applications.runner.statusReason"
        :request-status="applications.runner.requestStatus"
        :request-reason="applications.runner.requestReason"
        :disabled="!helmInstalled"
        title-link="https://docs.gitlab.com/runner/"
      >
        <div slot="description">
Mike Greiling's avatar
Mike Greiling committed
331 332
          {{
            s__(`ClusterIntegration|GitLab Runner connects to this
333 334
            project's repository and executes CI/CD jobs,
            pushing results back and deploying,
Mike Greiling's avatar
Mike Greiling committed
335 336
            applications to production.`)
          }}
337 338 339
        </div>
      </application-row>
      <application-row
340
        v-if="isProjectCluster"
341 342 343 344 345 346 347 348 349 350 351 352 353
        id="jupyter"
        :logo-url="jupyterhubLogo"
        :title="applications.jupyter.title"
        :status="applications.jupyter.status"
        :status-reason="applications.jupyter.statusReason"
        :request-status="applications.jupyter.requestStatus"
        :request-reason="applications.jupyter.requestReason"
        :install-application-request-params="{ hostname: applications.jupyter.hostname }"
        :disabled="!helmInstalled"
        title-link="https://jupyterhub.readthedocs.io/en/stable/"
      >
        <div slot="description">
          <p>
Mike Greiling's avatar
Mike Greiling committed
354 355
            {{
              s__(`ClusterIntegration|JupyterHub, a multi-user Hub, spawns,
356 357 358
              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,
Mike Greiling's avatar
Mike Greiling committed
359 360
              or a scientific research group.`)
            }}
361
          </p>
362

363 364 365 366 367
          <template v-if="ingressExternalIp">
            <div class="form-group">
              <label for="jupyter-hostname">
                {{ s__('ClusterIntegration|Jupyter Hostname') }}
              </label>
368

369 370 371 372 373 374 375
              <div class="input-group">
                <input
                  v-model="applications.jupyter.hostname"
                  :readonly="jupyterInstalled"
                  type="text"
                  class="form-control js-hostname"
                />
Mike Greiling's avatar
Mike Greiling committed
376
                <span class="input-group-btn">
377 378 379 380
                  <clipboard-button
                    :text="jupyterHostname"
                    :title="s__('ClusterIntegration|Copy Jupyter Hostname to clipboard')"
                    class="js-clipboard-btn"
381
                  />
382
                </span>
383
              </div>
384 385
            </div>
            <p v-if="ingressInstalled">
Mike Greiling's avatar
Mike Greiling committed
386 387 388 389 390
              {{
                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">
391 392 393 394 395 396
                {{ __('More information') }}
              </a>
            </p>
          </template>
        </div>
      </application-row>
Chris Baumbauer's avatar
Chris Baumbauer committed
397
      <application-row
398
        v-if="isProjectCluster"
Chris Baumbauer's avatar
Chris Baumbauer committed
399 400 401 402 403 404 405
        id="knative"
        :logo-url="knativeLogo"
        :title="applications.knative.title"
        :status="applications.knative.status"
        :status-reason="applications.knative.statusReason"
        :request-status="applications.knative.requestStatus"
        :request-reason="applications.knative.requestReason"
Mike Greiling's avatar
Mike Greiling committed
406
        :install-application-request-params="{ hostname: applications.knative.hostname }"
Chris Baumbauer's avatar
Chris Baumbauer committed
407 408 409 410 411
        :disabled="!helmInstalled"
        title-link="https://github.com/knative/docs"
      >
        <div slot="description">
          <p>
Mike Greiling's avatar
Mike Greiling committed
412
            {{
413 414 415 416
              s__(`ClusterIntegration|Knative extends Kubernetes to provide
              a set of middleware components that are essential to build modern,
              source-centric, and container-based applications that can run
              anywhere: on premises, in the cloud, or even in a third-party data center.`)
Mike Greiling's avatar
Mike Greiling committed
417
            }}
Chris Baumbauer's avatar
Chris Baumbauer committed
418 419 420 421 422 423 424 425 426
          </p>

          <template v-if="knativeInstalled">
            <div class="form-group">
              <label for="knative-domainname">
                {{ s__('ClusterIntegration|Knative Domain Name:') }}
              </label>
              <input
                id="knative-domainname"
427
                v-model="applications.knative.hostname"
Chris Baumbauer's avatar
Chris Baumbauer committed
428 429 430 431 432 433
                type="text"
                class="form-control js-domainname"
                readonly
              />
            </div>
          </template>
434
          <template v-else-if="helmInstalled">
Chris Baumbauer's avatar
Chris Baumbauer committed
435 436 437 438 439 440
            <div class="form-group">
              <label for="knative-domainname">
                {{ s__('ClusterIntegration|Knative Domain Name:') }}
              </label>
              <input
                id="knative-domainname"
441
                v-model="applications.knative.hostname"
Chris Baumbauer's avatar
Chris Baumbauer committed
442 443 444 445 446
                type="text"
                class="form-control js-domainname"
              />
            </div>
          </template>
447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489
          <template v-if="knativeInstalled">
            <div class="form-group">
              <label for="knative-ip-address">
                {{ s__('ClusterIntegration|Knative IP Address:') }}
              </label>
              <div v-if="knativeExternalIp" class="input-group">
                <input
                  id="knative-ip-address"
                  :value="knativeExternalIp"
                  type="text"
                  class="form-control js-ip-address"
                  readonly
                />
                <span class="input-group-append">
                  <clipboard-button
                    :text="knativeExternalIp"
                    :title="s__('ClusterIntegration|Copy Knative IP Address to clipboard')"
                    class="input-group-text js-clipboard-btn"
                  />
                </span>
              </div>
              <input v-else type="text" class="form-control js-ip-address" readonly value="?" />
            </div>

            <p v-if="!knativeExternalIp" class="settings-message js-no-ip-message">
              {{
                s__(`ClusterIntegration|The IP address is in
              the process of being assigned. Please check your Kubernetes
              cluster or Quotas on Google Kubernetes Engine if it takes a long time.`)
              }}
            </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="ingressDnsHelpPath" target="_blank" rel="noopener noreferrer">
                {{ __('More information') }}
              </a>
            </p>
          </template>
Chris Baumbauer's avatar
Chris Baumbauer committed
490 491
        </div>
      </application-row>
492 493 494
    </div>
  </section>
</template>