applications.vue 11.7 KB
Newer Older
1
<script>
2 3 4 5 6
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, INGRESS } from '../constants';
7

8 9 10 11 12 13 14 15 16 17
export default {
  components: {
    applicationRow,
    clipboardButton,
  },
  props: {
    applications: {
      type: Object,
      required: false,
      default: () => ({}),
18
    },
19 20 21 22
    helpPath: {
      type: String,
      required: false,
      default: '',
23
    },
24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44
    ingressHelpPath: {
      type: String,
      required: false,
      default: '',
    },
    ingressDnsHelpPath: {
      type: String,
      required: false,
      default: '',
    },
    managePrometheusPath: {
      type: String,
      required: false,
      default: '',
    },
  },
  computed: {
    generalApplicationDescription() {
      return sprintf(
        _.escape(
          s__(
45 46
            `ClusterIntegration|Install applications on your Kubernetes cluster.
            Read more about %{helpLink}`,
47 48 49 50
          ),
        ),
        {
          helpLink: `<a href="${this.helpPath}">
51 52
              ${_.escape(s__('ClusterIntegration|installing applications'))}
            </a>`,
53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69
        },
        false,
      );
    },
    ingressId() {
      return INGRESS;
    },
    ingressInstalled() {
      return this.applications.ingress.status === APPLICATION_INSTALLED;
    },
    ingressExternalIp() {
      return this.applications.ingress.externalIp;
    },
    ingressDescription() {
      const extraCostParagraph = sprintf(
        _.escape(
          s__(
70 71
            `ClusterIntegration|%{boldNotice} This will add some extra resources
            like a load balancer, which may incur additional costs depending on
72 73 74 75 76 77 78
            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">
79
              ${_.escape(s__('ClusterIntegration|check the pricing here'))}</a>`,
80 81 82
        },
        false,
      );
83

84 85 86
      const externalIpParagraph = sprintf(
        _.escape(
          s__(
87 88
            `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}`,
89 90 91 92
          ),
        ),
        {
          ingressHelpLink: `<a href="${this.ingressHelpPath}">
93 94
              ${_.escape(s__('ClusterIntegration|More information'))}
            </a>`,
95 96 97
        },
        false,
      );
98

99
      return `
100
          <p>
101 102
            ${extraCostParagraph}
          </p>
103 104 105
          <p class="settings-message append-bottom-0">
            ${externalIpParagraph}
          </p>
106
        `;
107 108 109 110 111
    },
    prometheusDescription() {
      return sprintf(
        _.escape(
          s__(
112 113
            `ClusterIntegration|Prometheus is an open-source monitoring system
            with %{gitlabIntegrationLink} to monitor deployed applications.`,
114 115 116 117
          ),
        ),
        {
          gitlabIntegrationLink: `<a href="https://docs.gitlab.com/ce/user/project/integrations/prometheus.html"
118
              target="_blank" rel="noopener noreferrer">
119
              ${_.escape(s__('ClusterIntegration|GitLab Integration'))}</a>`,
120 121 122
        },
        false,
      );
123
    },
124 125 126 127 128 129
    jupyterInstalled() {
      return this.applications.jupyter.status === APPLICATION_INSTALLED;
    },
    jupyterHostname() {
      return this.applications.jupyter.hostname;
    },
130 131
  },
};
132 133 134
</script>

<template>
135 136 137 138
  <section
    id="cluster-applications"
    class="settings no-animate expanded"
  >
139 140 141 142 143 144 145 146 147 148 149 150
    <div class="settings-header">
      <h4>
        {{ s__('ClusterIntegration|Applications') }}
      </h4>
      <p
        class="append-bottom-0"
        v-html="generalApplicationDescription"
      >
      </p>
    </div>

    <div class="settings-content">
151
      <div class="append-bottom-20">
152 153 154 155 156 157 158 159
        <application-row
          id="helm"
          :title="applications.helm.title"
          title-link="https://docs.helm.sh/"
          :status="applications.helm.status"
          :status-reason="applications.helm.statusReason"
          :request-status="applications.helm.requestStatus"
          :request-reason="applications.helm.requestReason"
160 161
        >
          <div slot="description">
Filipa Lacerda's avatar
Filipa Lacerda committed
162 163 164 165
            {{ s__(`ClusterIntegration|Helm streamlines installing
              and managing Kubernetes applications.
              Tiller runs inside of your Kubernetes Cluster,
              and manages releases of your charts.`) }}
166 167
          </div>
        </application-row>
168
        <application-row
Filipa Lacerda's avatar
Filipa Lacerda committed
169
          :id="ingressId"
170 171 172 173 174 175
          :title="applications.ingress.title"
          title-link="https://kubernetes.io/docs/concepts/services-networking/ingress/"
          :status="applications.ingress.status"
          :status-reason="applications.ingress.statusReason"
          :request-status="applications.ingress.requestStatus"
          :request-reason="applications.ingress.requestReason"
176 177 178
        >
          <div slot="description">
            <p>
179
              {{ s__(`ClusterIntegration|Ingress gives you a way to route
180
                requests to services based on the request host or path,
181
                centralizing a number of services into a single entrypoint.`) }}
182 183 184 185
            </p>

            <template v-if="ingressInstalled">
              <div class="form-group">
Filipa Lacerda's avatar
Filipa Lacerda committed
186
                <label for="ingress-ip-address">
187
                  {{ s__('ClusterIntegration|Ingress IP Address') }}
188 189
                </label>
                <div
190
                  v-if="ingressExternalIp"
191 192 193 194
                  class="input-group"
                >
                  <input
                    type="text"
Filipa Lacerda's avatar
Filipa Lacerda committed
195
                    id="ingress-ip-address"
Filipa Lacerda's avatar
Filipa Lacerda committed
196
                    class="form-control js-ip-address"
197
                    :value="ingressExternalIp"
198 199 200 201
                    readonly
                  />
                  <span class="input-group-btn">
                    <clipboard-button
202
                      :text="ingressExternalIp"
203
                      :title="s__('ClusterIntegration|Copy Ingress IP Address to clipboard')"
204
                      class="js-clipboard-btn"
205 206 207 208 209 210
                    />
                  </span>
                </div>
                <input
                  v-else
                  type="text"
Filipa Lacerda's avatar
Filipa Lacerda committed
211
                  class="form-control js-ip-address"
212
                  readonly
213
                  value="?"
214 215 216 217
                />
              </div>

              <p
218
                v-if="!ingressExternalIp"
219 220
                class="settings-message js-no-ip-message"
              >
221 222
                {{ s__(`ClusterIntegration|The IP address is in
                the process of being assigned. Please check your Kubernetes
223
                cluster or Quotas on Google Kubernetes Engine if it takes a long time.`) }}
224

225
                <a
226
                  :href="ingressHelpPath"
227 228 229
                  target="_blank"
                  rel="noopener noreferrer"
                >
Filipa Lacerda's avatar
Filipa Lacerda committed
230
                  {{ __('More information') }}
231 232 233 234 235 236 237 238
                </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
239
                  :href="ingressDnsHelpPath"
240 241 242
                  target="_blank"
                  rel="noopener noreferrer"
                >
Filipa Lacerda's avatar
Filipa Lacerda committed
243
                  {{ __('More information') }}
244 245 246 247
                </a>
              </p>

            </template>
Filipa Lacerda's avatar
Filipa Lacerda committed
248
            <div
249 250 251
              v-else
              v-html="ingressDescription"
            >
Filipa Lacerda's avatar
Filipa Lacerda committed
252
            </div>
253 254
          </div>
        </application-row>
255 256 257 258
        <application-row
          id="prometheus"
          :title="applications.prometheus.title"
          title-link="https://prometheus.io/docs/introduction/overview/"
259
          :manage-link="managePrometheusPath"
260 261 262 263
          :status="applications.prometheus.status"
          :status-reason="applications.prometheus.statusReason"
          :request-status="applications.prometheus.requestStatus"
          :request-reason="applications.prometheus.requestReason"
264 265 266 267 268 269 270
        >
          <div
            slot="description"
            v-html="prometheusDescription"
          >
          </div>
        </application-row>
271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286
        <application-row
          id="runner"
          :title="applications.runner.title"
          title-link="https://docs.gitlab.com/runner/"
          :status="applications.runner.status"
          :status-reason="applications.runner.statusReason"
          :request-status="applications.runner.requestStatus"
          :request-reason="applications.runner.requestReason"
        >
          <div slot="description">
            {{ s__(`ClusterIntegration|GitLab Runner connects to this
              project's repository and executes CI/CD jobs,
              pushing results back and deploying,
              applications to production.`) }}
          </div>
        </application-row>
287 288 289 290 291 292 293 294
        <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"
295
          :install-application-request-params="{ hostname: applications.jupyter.hostname }"
296 297 298 299 300 301 302 303 304
        >
          <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>
305

306
            <template v-if="ingressExternalIp">
307 308 309 310
              <div class="form-group">
                <label for="jupyter-hostname">
                  {{ s__('ClusterIntegration|Jupyter Hostname') }}
                </label>
311

312 313 314 315
                <div class="input-group">
                  <input
                    type="text"
                    class="form-control js-hostname"
316 317
                    v-model="applications.jupyter.hostname"
                    :readonly="jupyterInstalled"
318
                  />
319 320 321
                  <span
                    class="input-group-btn"
                  >
322 323 324 325 326 327 328 329
                    <clipboard-button
                      :text="jupyterHostname"
                      :title="s__('ClusterIntegration|Copy Jupyter Hostname to clipboard')"
                      class="js-clipboard-btn"
                    />
                  </span>
                </div>
              </div>
330
              <p v-if="ingressInstalled">
331 332 333 334 335 336 337 338 339 340 341 342 343
                {{ 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>
344 345 346 347
        <!--
          NOTE: Don't forget to update `clusters.scss`
          min-height for this block and uncomment `application_spec` tests
        -->
348
        <!-- Add Jupyter row, all other plumbing is complete -->
349 350 351 352
      </div>
    </div>
  </section>
</template>