Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
7f4a1ba886
commit
c1f270b8ba
Binary file not shown.
|
After Width: | Height: | Size: 1.8 KiB |
|
|
@ -8,7 +8,7 @@ import Flash from '../flash';
|
|||
import Poll from '../lib/utils/poll';
|
||||
import initSettingsPanels from '../settings_panels';
|
||||
import eventHub from './event_hub';
|
||||
import { APPLICATION_STATUS, INGRESS, INGRESS_DOMAIN_SUFFIX } from './constants';
|
||||
import { APPLICATION_STATUS, INGRESS, INGRESS_DOMAIN_SUFFIX, CROSSPLANE } from './constants';
|
||||
import ClustersService from './services/clusters_service';
|
||||
import ClustersStore from './stores/clusters_store';
|
||||
import Applications from './components/applications.vue';
|
||||
|
|
@ -39,6 +39,7 @@ export default class Clusters {
|
|||
installKnativePath,
|
||||
updateKnativePath,
|
||||
installElasticStackPath,
|
||||
installCrossplanePath,
|
||||
installPrometheusPath,
|
||||
managePrometheusPath,
|
||||
clusterEnvironmentsPath,
|
||||
|
|
@ -83,6 +84,7 @@ export default class Clusters {
|
|||
installHelmEndpoint: installHelmPath,
|
||||
installIngressEndpoint: installIngressPath,
|
||||
installCertManagerEndpoint: installCertManagerPath,
|
||||
installCrossplaneEndpoint: installCrossplanePath,
|
||||
installRunnerEndpoint: installRunnerPath,
|
||||
installPrometheusEndpoint: installPrometheusPath,
|
||||
installJupyterEndpoint: installJupyterPath,
|
||||
|
|
@ -227,6 +229,7 @@ export default class Clusters {
|
|||
eventHub.$on('saveKnativeDomain', data => this.saveKnativeDomain(data));
|
||||
eventHub.$on('setKnativeHostname', data => this.setKnativeHostname(data));
|
||||
eventHub.$on('uninstallApplication', data => this.uninstallApplication(data));
|
||||
eventHub.$on('setCrossplaneProviderStack', data => this.setCrossplaneProviderStack(data));
|
||||
// Add event listener to all the banner close buttons
|
||||
this.addBannerCloseHandler(this.unreachableContainer, 'unreachable');
|
||||
this.addBannerCloseHandler(this.authenticationFailureContainer, 'authentication_failure');
|
||||
|
|
@ -238,6 +241,7 @@ export default class Clusters {
|
|||
eventHub.$off('updateApplication', this.updateApplication);
|
||||
eventHub.$off('saveKnativeDomain');
|
||||
eventHub.$off('setKnativeHostname');
|
||||
eventHub.$off('setCrossplaneProviderStack');
|
||||
eventHub.$off('uninstallApplication');
|
||||
}
|
||||
|
||||
|
|
@ -404,18 +408,33 @@ export default class Clusters {
|
|||
}
|
||||
|
||||
installApplication({ id: appId, params }) {
|
||||
this.store.updateAppProperty(appId, 'requestReason', null);
|
||||
this.store.updateAppProperty(appId, 'statusReason', null);
|
||||
return Clusters.validateInstallation(appId, params)
|
||||
.then(() => {
|
||||
this.store.updateAppProperty(appId, 'requestReason', null);
|
||||
this.store.updateAppProperty(appId, 'statusReason', null);
|
||||
this.store.installApplication(appId);
|
||||
|
||||
this.store.installApplication(appId);
|
||||
// eslint-disable-next-line promise/no-nesting
|
||||
this.service.installApplication(appId, params).catch(() => {
|
||||
this.store.notifyInstallFailure(appId);
|
||||
this.store.updateAppProperty(
|
||||
appId,
|
||||
'requestReason',
|
||||
s__('ClusterIntegration|Request to begin installing failed'),
|
||||
);
|
||||
});
|
||||
})
|
||||
.catch(error => this.store.updateAppProperty(appId, 'validationError', error));
|
||||
}
|
||||
|
||||
return this.service.installApplication(appId, params).catch(() => {
|
||||
this.store.notifyInstallFailure(appId);
|
||||
this.store.updateAppProperty(
|
||||
appId,
|
||||
'requestReason',
|
||||
s__('ClusterIntegration|Request to begin installing failed'),
|
||||
);
|
||||
static validateInstallation(appId, params) {
|
||||
return new Promise((resolve, reject) => {
|
||||
if (appId === CROSSPLANE && !params.stack) {
|
||||
reject(s__('ClusterIntegration|Select a stack to install Crossplane.'));
|
||||
return;
|
||||
}
|
||||
|
||||
resolve();
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -463,6 +482,12 @@ export default class Clusters {
|
|||
this.store.updateAppProperty(appId, 'hostname', data.hostname);
|
||||
}
|
||||
|
||||
setCrossplaneProviderStack(data) {
|
||||
const appId = data.id;
|
||||
this.store.updateAppProperty(appId, 'stack', data.stack.code);
|
||||
this.store.updateAppProperty(appId, 'validationError', null);
|
||||
}
|
||||
|
||||
destroy() {
|
||||
this.destroyed = true;
|
||||
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ 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';
|
||||
import certManagerLogo from 'images/cluster_app_logos/cert_manager.png';
|
||||
import crossplaneLogo from 'images/cluster_app_logos/crossplane.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';
|
||||
|
|
@ -20,6 +21,7 @@ import KnativeDomainEditor from './knative_domain_editor.vue';
|
|||
import { CLUSTER_TYPE, PROVIDER_TYPE, APPLICATION_STATUS, INGRESS } from '../constants';
|
||||
import LoadingButton from '~/vue_shared/components/loading_button.vue';
|
||||
import eventHub from '~/clusters/event_hub';
|
||||
import CrossplaneProviderStack from './crossplane_provider_stack.vue';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
|
|
@ -28,6 +30,7 @@ export default {
|
|||
LoadingButton,
|
||||
GlLoadingIcon,
|
||||
KnativeDomainEditor,
|
||||
CrossplaneProviderStack,
|
||||
},
|
||||
props: {
|
||||
type: {
|
||||
|
|
@ -89,6 +92,7 @@ export default {
|
|||
jupyterhubLogo,
|
||||
kubernetesLogo,
|
||||
certManagerLogo,
|
||||
crossplaneLogo,
|
||||
knativeLogo,
|
||||
meltanoLogo,
|
||||
prometheusLogo,
|
||||
|
|
@ -116,6 +120,12 @@ export default {
|
|||
certManagerInstalled() {
|
||||
return this.applications.cert_manager.status === APPLICATION_STATUS.INSTALLED;
|
||||
},
|
||||
crossplaneInstalled() {
|
||||
return this.applications.crossplane.status === APPLICATION_STATUS.INSTALLED;
|
||||
},
|
||||
enableClusterApplicationCrossplane() {
|
||||
return gon.features && gon.features.enableClusterApplicationCrossplane;
|
||||
},
|
||||
enableClusterApplicationElasticStack() {
|
||||
return gon.features && gon.features.enableClusterApplicationElasticStack;
|
||||
},
|
||||
|
|
@ -151,6 +161,24 @@ export default {
|
|||
false,
|
||||
);
|
||||
},
|
||||
crossplaneDescription() {
|
||||
return sprintf(
|
||||
_.escape(
|
||||
s__(
|
||||
`ClusterIntegration|Crossplane enables declarative provisioning of managed services from your cloud of choice using %{kubectl} or %{gitlabIntegrationLink}.
|
||||
Crossplane runs inside your Kubernetes cluster and supports secure connectivity and secrets management between app containers and the cloud services they depend on.`,
|
||||
),
|
||||
),
|
||||
{
|
||||
gitlabIntegrationLink: `<a href="https://docs.gitlab.com/ce/user/project/integrations/crossplane.html"
|
||||
target="_blank" rel="noopener noreferrer">
|
||||
${_.escape(s__('ClusterIntegration|Gitlab Integration'))}</a>`,
|
||||
kubectl: `<code>kubectl</code>`,
|
||||
},
|
||||
false,
|
||||
);
|
||||
},
|
||||
|
||||
prometheusDescription() {
|
||||
return sprintf(
|
||||
_.escape(
|
||||
|
|
@ -182,6 +210,9 @@ export default {
|
|||
knative() {
|
||||
return this.applications.knative;
|
||||
},
|
||||
crossplane() {
|
||||
return this.applications.crossplane;
|
||||
},
|
||||
cloudRun() {
|
||||
return this.providerType === PROVIDER_TYPE.GCP && this.preInstalledKnative;
|
||||
},
|
||||
|
|
@ -218,6 +249,12 @@ export default {
|
|||
hostname,
|
||||
});
|
||||
},
|
||||
setCrossplaneProviderStack(stack) {
|
||||
eventHub.$emit('setCrossplaneProviderStack', {
|
||||
id: 'crossplane',
|
||||
stack,
|
||||
});
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
|
@ -228,7 +265,7 @@ export default {
|
|||
<p class="append-bottom-0">
|
||||
{{
|
||||
s__(`ClusterIntegration|Choose which applications to install on your Kubernetes cluster.
|
||||
Helm Tiller is required to install any of the following applications.`)
|
||||
Helm Tiller is required to install any of the following applications.`)
|
||||
}}
|
||||
<a :href="helpPath">{{ __('More information') }}</a>
|
||||
</p>
|
||||
|
|
@ -253,9 +290,9 @@ export default {
|
|||
<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.`)
|
||||
and managing Kubernetes applications.
|
||||
Tiller runs inside of your Kubernetes Cluster,
|
||||
and manages releases of your charts.`)
|
||||
}}
|
||||
</div>
|
||||
</application-row>
|
||||
|
|
@ -263,7 +300,7 @@ export default {
|
|||
<div class="svg-container" v-html="helmInstallIllustration"></div>
|
||||
{{
|
||||
s__(`ClusterIntegration|You must first install Helm Tiller before
|
||||
installing the applications below`)
|
||||
installing the applications below`)
|
||||
}}
|
||||
</div>
|
||||
<application-row
|
||||
|
|
@ -286,8 +323,8 @@ export default {
|
|||
<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.`)
|
||||
requests to services based on the request host or path,
|
||||
centralizing a number of services into a single entrypoint.`)
|
||||
}}
|
||||
</p>
|
||||
|
||||
|
|
@ -319,8 +356,8 @@ export default {
|
|||
<p class="form-text text-muted">
|
||||
{{
|
||||
s__(`ClusterIntegration|Point a wildcard DNS to this
|
||||
generated endpoint in order to access
|
||||
your application after it has been deployed.`)
|
||||
generated endpoint in order to access
|
||||
your application after it has been deployed.`)
|
||||
}}
|
||||
<a :href="ingressDnsHelpPath" target="_blank" rel="noopener noreferrer">
|
||||
{{ __('More information') }}
|
||||
|
|
@ -331,8 +368,8 @@ export default {
|
|||
<p v-if="!ingressExternalEndpoint" class="settings-message js-no-endpoint-message">
|
||||
{{
|
||||
s__(`ClusterIntegration|The endpoint is in
|
||||
the process of being assigned. Please check your Kubernetes
|
||||
cluster or Quotas on Google Kubernetes Engine if it takes a long time.`)
|
||||
the process of being assigned. Please check your Kubernetes
|
||||
cluster or Quotas on Google Kubernetes Engine if it takes a long time.`)
|
||||
}}
|
||||
<a :href="ingressDnsHelpPath" target="_blank" rel="noopener noreferrer">
|
||||
{{ __('More information') }}
|
||||
|
|
@ -379,7 +416,7 @@ export default {
|
|||
<p class="form-text text-muted">
|
||||
{{
|
||||
s__(`ClusterIntegration|Issuers represent a certificate authority.
|
||||
You must provide an email address for your Issuer. `)
|
||||
You must provide an email address for your Issuer. `)
|
||||
}}
|
||||
<a
|
||||
href="http://docs.cert-manager.io/en/latest/reference/issuers.html?highlight=email"
|
||||
|
|
@ -435,12 +472,40 @@ export default {
|
|||
<div slot="description">
|
||||
{{
|
||||
s__(`ClusterIntegration|GitLab Runner connects to the
|
||||
repository and executes CI/CD jobs,
|
||||
pushing results back and deploying
|
||||
applications to production.`)
|
||||
repository and executes CI/CD jobs,
|
||||
pushing results back and deploying
|
||||
applications to production.`)
|
||||
}}
|
||||
</div>
|
||||
</application-row>
|
||||
<application-row
|
||||
v-if="enableClusterApplicationCrossplane"
|
||||
id="crossplane"
|
||||
:logo-url="crossplaneLogo"
|
||||
:title="applications.crossplane.title"
|
||||
:status="applications.crossplane.status"
|
||||
:status-reason="applications.crossplane.statusReason"
|
||||
:request-status="applications.crossplane.requestStatus"
|
||||
:request-reason="applications.crossplane.requestReason"
|
||||
:installed="applications.crossplane.installed"
|
||||
:install-failed="applications.crossplane.installFailed"
|
||||
:uninstallable="applications.crossplane.uninstallable"
|
||||
:uninstall-successful="applications.crossplane.uninstallSuccessful"
|
||||
:uninstall-failed="applications.crossplane.uninstallFailed"
|
||||
:install-application-request-params="{ stack: applications.crossplane.stack }"
|
||||
:disabled="!helmInstalled"
|
||||
title-link="https://crossplane.io"
|
||||
>
|
||||
<template>
|
||||
<div slot="description">
|
||||
<p v-html="crossplaneDescription"></p>
|
||||
<div class="form-group">
|
||||
<CrossplaneProviderStack :crossplane="crossplane" @set="setCrossplaneProviderStack" />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</application-row>
|
||||
|
||||
<application-row
|
||||
id="jupyter"
|
||||
:logo-url="jupyterhubLogo"
|
||||
|
|
@ -462,10 +527,10 @@ export default {
|
|||
<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.`)
|
||||
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>
|
||||
|
||||
|
|
@ -492,7 +557,7 @@ export default {
|
|||
<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.`)
|
||||
If you do so, point hostname to Ingress IP Address from above.`)
|
||||
}}
|
||||
<a :href="ingressDnsHelpPath" target="_blank" rel="noopener noreferrer">
|
||||
{{ __('More information') }}
|
||||
|
|
@ -538,9 +603,9 @@ export default {
|
|||
<p>
|
||||
{{
|
||||
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.`)
|
||||
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.`)
|
||||
}}
|
||||
</p>
|
||||
|
||||
|
|
@ -612,7 +677,7 @@ export default {
|
|||
<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.`)
|
||||
If you do so, point hostname to Ingress IP Address from above.`)
|
||||
}}
|
||||
<a :href="ingressDnsHelpPath" target="_blank" rel="noopener noreferrer">
|
||||
{{ __('More information') }}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,93 @@
|
|||
<script>
|
||||
import { GlDropdown, GlDropdownItem } from '@gitlab/ui';
|
||||
import Icon from '~/vue_shared/components/icon.vue';
|
||||
import { s__ } from '../../locale';
|
||||
|
||||
export default {
|
||||
name: 'CrossplaneProviderStack',
|
||||
components: {
|
||||
GlDropdown,
|
||||
GlDropdownItem,
|
||||
Icon,
|
||||
},
|
||||
props: {
|
||||
stacks: {
|
||||
type: Array,
|
||||
required: false,
|
||||
default: () => [
|
||||
{
|
||||
name: s__('Google Cloud Platform'),
|
||||
code: 'gcp',
|
||||
},
|
||||
{
|
||||
name: s__('Amazon Web Services'),
|
||||
code: 'aws',
|
||||
},
|
||||
{
|
||||
name: s__('Microsoft Azure'),
|
||||
code: 'azure',
|
||||
},
|
||||
{
|
||||
name: s__('Rook'),
|
||||
code: 'rook',
|
||||
},
|
||||
],
|
||||
},
|
||||
crossplane: {
|
||||
type: Object,
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
dropdownText() {
|
||||
const result = this.stacks.reduce((map, obj) => {
|
||||
// eslint-disable-next-line no-param-reassign
|
||||
map[obj.code] = obj.name;
|
||||
return map;
|
||||
}, {});
|
||||
const { stack } = this.crossplane;
|
||||
if (stack !== '') {
|
||||
return result[stack];
|
||||
}
|
||||
return s__('Select Stack');
|
||||
},
|
||||
validationError() {
|
||||
return this.crossplane.validationError;
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
selectStack(stack) {
|
||||
this.$emit('set', stack);
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div>
|
||||
<label>
|
||||
{{ s__('ClusterIntegration|Enabled stack') }}
|
||||
</label>
|
||||
<gl-dropdown
|
||||
:disabled="crossplane.installed"
|
||||
:text="dropdownText"
|
||||
toggle-class="dropdown-menu-toggle gl-field-error-outline"
|
||||
class="w-100"
|
||||
:class="{ 'gl-show-field-errors': validationError }"
|
||||
>
|
||||
<gl-dropdown-item v-for="stack in stacks" :key="stack.code" @click="selectStack(stack)">
|
||||
<span class="ml-1">{{ stack.name }}</span>
|
||||
</gl-dropdown-item>
|
||||
</gl-dropdown>
|
||||
<span v-if="validationError" class="gl-field-error">{{ validationError }}</span>
|
||||
<p class="form-text text-muted">
|
||||
{{ s__(`You must select a stack for configuring your cloud provider. Learn more about`) }}
|
||||
<a
|
||||
href="https://crossplane.io/docs/master/stacks-guide.html"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>{{ __('Crossplane') }}</a
|
||||
>
|
||||
</p>
|
||||
</div>
|
||||
</template>
|
||||
|
|
@ -50,6 +50,7 @@ export const JUPYTER = 'jupyter';
|
|||
export const KNATIVE = 'knative';
|
||||
export const RUNNER = 'runner';
|
||||
export const CERT_MANAGER = 'cert_manager';
|
||||
export const CROSSPLANE = 'crossplane';
|
||||
export const PROMETHEUS = 'prometheus';
|
||||
export const ELASTIC_STACK = 'elastic_stack';
|
||||
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ export default class ClusterService {
|
|||
helm: this.options.installHelmEndpoint,
|
||||
ingress: this.options.installIngressEndpoint,
|
||||
cert_manager: this.options.installCertManagerEndpoint,
|
||||
crossplane: this.options.installCrossplaneEndpoint,
|
||||
runner: this.options.installRunnerEndpoint,
|
||||
prometheus: this.options.installPrometheusEndpoint,
|
||||
jupyter: this.options.installJupyterEndpoint,
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ import {
|
|||
KNATIVE,
|
||||
CERT_MANAGER,
|
||||
ELASTIC_STACK,
|
||||
CROSSPLANE,
|
||||
RUNNER,
|
||||
APPLICATION_INSTALLED_STATUSES,
|
||||
APPLICATION_STATUS,
|
||||
|
|
@ -26,6 +27,7 @@ const applicationInitialState = {
|
|||
uninstallable: false,
|
||||
uninstallFailed: false,
|
||||
uninstallSuccessful: false,
|
||||
validationError: null,
|
||||
};
|
||||
|
||||
export default class ClusterStore {
|
||||
|
|
@ -58,6 +60,11 @@ export default class ClusterStore {
|
|||
title: s__('ClusterIntegration|Cert-Manager'),
|
||||
email: null,
|
||||
},
|
||||
crossplane: {
|
||||
...applicationInitialState,
|
||||
title: s__('ClusterIntegration|Crossplane'),
|
||||
stack: null,
|
||||
},
|
||||
runner: {
|
||||
...applicationInitialState,
|
||||
title: s__('ClusterIntegration|GitLab Runner'),
|
||||
|
|
@ -203,6 +210,9 @@ export default class ClusterStore {
|
|||
} else if (appId === CERT_MANAGER) {
|
||||
this.state.applications.cert_manager.email =
|
||||
this.state.applications.cert_manager.email || serverAppEntry.email;
|
||||
} else if (appId === CROSSPLANE) {
|
||||
this.state.applications.crossplane.stack =
|
||||
this.state.applications.crossplane.stack || serverAppEntry.stack;
|
||||
} else if (appId === JUPYTER) {
|
||||
this.state.applications.jupyter.hostname = this.updateHostnameIfUnset(
|
||||
this.state.applications.jupyter.hostname,
|
||||
|
|
|
|||
|
|
@ -47,7 +47,7 @@ class Clusters::ApplicationsController < Clusters::BaseController
|
|||
end
|
||||
|
||||
def cluster_application_params
|
||||
params.permit(:application, :hostname, :kibana_hostname, :email)
|
||||
params.permit(:application, :hostname, :kibana_hostname, :email, :stack)
|
||||
end
|
||||
|
||||
def cluster_application_destroy_params
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@ class Clusters::ClustersController < Clusters::BaseController
|
|||
end
|
||||
before_action only: [:show] do
|
||||
push_frontend_feature_flag(:enable_cluster_application_elastic_stack)
|
||||
push_frontend_feature_flag(:enable_cluster_application_crossplane)
|
||||
end
|
||||
|
||||
helper_method :token_in_session
|
||||
|
|
|
|||
|
|
@ -0,0 +1,60 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module Clusters
|
||||
module Applications
|
||||
class Crossplane < ApplicationRecord
|
||||
VERSION = '0.4.1'
|
||||
|
||||
self.table_name = 'clusters_applications_crossplane'
|
||||
|
||||
include ::Clusters::Concerns::ApplicationCore
|
||||
include ::Clusters::Concerns::ApplicationStatus
|
||||
include ::Clusters::Concerns::ApplicationVersion
|
||||
include ::Clusters::Concerns::ApplicationData
|
||||
|
||||
default_value_for :version, VERSION
|
||||
|
||||
default_value_for :stack do |crossplane|
|
||||
''
|
||||
end
|
||||
|
||||
validates :stack, presence: true
|
||||
|
||||
def chart
|
||||
'crossplane/crossplane'
|
||||
end
|
||||
|
||||
def repository
|
||||
'https://charts.crossplane.io/alpha'
|
||||
end
|
||||
|
||||
def install_command
|
||||
Gitlab::Kubernetes::Helm::InstallCommand.new(
|
||||
name: 'crossplane',
|
||||
repository: repository,
|
||||
version: VERSION,
|
||||
rbac: cluster.platform_kubernetes_rbac?,
|
||||
chart: chart,
|
||||
files: files
|
||||
)
|
||||
end
|
||||
|
||||
def values
|
||||
crossplane_values.to_yaml
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def crossplane_values
|
||||
{
|
||||
"clusterStacks" => {
|
||||
self.stack => {
|
||||
"deploy" => true,
|
||||
"version" => "alpha"
|
||||
}
|
||||
}
|
||||
}
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -14,6 +14,7 @@ module Clusters
|
|||
Applications::Helm.application_name => Applications::Helm,
|
||||
Applications::Ingress.application_name => Applications::Ingress,
|
||||
Applications::CertManager.application_name => Applications::CertManager,
|
||||
Applications::Crossplane.application_name => Applications::Crossplane,
|
||||
Applications::Prometheus.application_name => Applications::Prometheus,
|
||||
Applications::Runner.application_name => Applications::Runner,
|
||||
Applications::Jupyter.application_name => Applications::Jupyter,
|
||||
|
|
@ -47,6 +48,7 @@ module Clusters
|
|||
has_one_cluster_application :helm
|
||||
has_one_cluster_application :ingress
|
||||
has_one_cluster_application :cert_manager
|
||||
has_one_cluster_application :crossplane
|
||||
has_one_cluster_application :prometheus
|
||||
has_one_cluster_application :runner
|
||||
has_one_cluster_application :jupyter
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ class ClusterApplicationEntity < Grape::Entity
|
|||
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 :stack, if: -> (e, _) { e.respond_to?(:stack) }
|
||||
expose :update_available?, as: :update_available, if: -> (e, _) { e.respond_to?(:update_available?) }
|
||||
expose :can_uninstall?, as: :can_uninstall
|
||||
end
|
||||
|
|
|
|||
|
|
@ -27,6 +27,10 @@ module Clusters
|
|||
application.email = params[:email]
|
||||
end
|
||||
|
||||
if application.has_attribute?(:stack)
|
||||
application.stack = params[:stack]
|
||||
end
|
||||
|
||||
if application.respond_to?(:oauth_application)
|
||||
application.oauth_application = create_oauth_application(application, request)
|
||||
end
|
||||
|
|
@ -64,7 +68,7 @@ module Clusters
|
|||
end
|
||||
|
||||
def invalid_application?
|
||||
unknown_application? || (application_name == Applications::ElasticStack.application_name && !Feature.enabled?(:enable_cluster_application_elastic_stack))
|
||||
unknown_application? || (application_name == Applications::ElasticStack.application_name && !Feature.enabled?(:enable_cluster_application_elastic_stack)) || (application_name == Applications::Crossplane.application_name && !Feature.enabled?(:enable_cluster_application_crossplane))
|
||||
end
|
||||
|
||||
def unknown_application?
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@
|
|||
install_helm_path: clusterable.install_applications_cluster_path(@cluster, :helm),
|
||||
install_ingress_path: clusterable.install_applications_cluster_path(@cluster, :ingress),
|
||||
install_cert_manager_path: clusterable.install_applications_cluster_path(@cluster, :cert_manager),
|
||||
install_crossplane_path: clusterable.install_applications_cluster_path(@cluster, :crossplane),
|
||||
install_prometheus_path: clusterable.install_applications_cluster_path(@cluster, :prometheus),
|
||||
install_runner_path: clusterable.install_applications_cluster_path(@cluster, :runner),
|
||||
install_jupyter_path: clusterable.install_applications_cluster_path(@cluster, :jupyter),
|
||||
|
|
|
|||
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
title: Support for Crossplane as a managed app
|
||||
merge_request: 18797
|
||||
author: Mahendra Bagul
|
||||
type: added
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class CreateClustersApplicationsCrossplane < ActiveRecord::Migration[5.2]
|
||||
include Gitlab::Database::MigrationHelpers
|
||||
|
||||
DOWNTIME = false
|
||||
|
||||
def change
|
||||
create_table :clusters_applications_crossplane do |t|
|
||||
t.timestamps_with_timezone null: false
|
||||
t.references :cluster, null: false, index: false, foreign_key: { on_delete: :cascade }
|
||||
t.integer :status, null: false
|
||||
t.string :version, null: false, limit: 255
|
||||
t.string :stack, null: false, limit: 255
|
||||
t.text :status_reason
|
||||
t.index :cluster_id, unique: true
|
||||
end
|
||||
end
|
||||
end
|
||||
12
db/schema.rb
12
db/schema.rb
|
|
@ -1078,6 +1078,17 @@ ActiveRecord::Schema.define(version: 2019_11_14_173624) do
|
|||
t.index ["cluster_id"], name: "index_clusters_applications_cert_managers_on_cluster_id", unique: true
|
||||
end
|
||||
|
||||
create_table "clusters_applications_crossplane", id: :serial, force: :cascade do |t|
|
||||
t.datetime_with_timezone "created_at", null: false
|
||||
t.datetime_with_timezone "updated_at", null: false
|
||||
t.bigint "cluster_id", null: false
|
||||
t.integer "status", null: false
|
||||
t.string "version", limit: 255, null: false
|
||||
t.string "stack", limit: 255, null: false
|
||||
t.text "status_reason"
|
||||
t.index ["cluster_id"], name: "index_clusters_applications_crossplane_on_cluster_id", unique: true
|
||||
end
|
||||
|
||||
create_table "clusters_applications_elastic_stacks", force: :cascade do |t|
|
||||
t.datetime_with_timezone "created_at", null: false
|
||||
t.datetime_with_timezone "updated_at", null: false
|
||||
|
|
@ -4222,6 +4233,7 @@ ActiveRecord::Schema.define(version: 2019_11_14_173624) do
|
|||
add_foreign_key "clusters", "projects", column: "management_project_id", name: "fk_f05c5e5a42", on_delete: :nullify
|
||||
add_foreign_key "clusters", "users", on_delete: :nullify
|
||||
add_foreign_key "clusters_applications_cert_managers", "clusters", on_delete: :cascade
|
||||
add_foreign_key "clusters_applications_crossplane", "clusters", on_delete: :cascade
|
||||
add_foreign_key "clusters_applications_elastic_stacks", "clusters", on_delete: :cascade
|
||||
add_foreign_key "clusters_applications_helm", "clusters", on_delete: :cascade
|
||||
add_foreign_key "clusters_applications_ingress", "clusters", on_delete: :cascade
|
||||
|
|
|
|||
|
|
@ -305,7 +305,7 @@ The following documentation relates to the DevOps **Configure** stage:
|
|||
| Configure Topics | Description |
|
||||
|:-----------------------------------------------------------------------------------------------------------------------------------|:--------------------------------------------------------------------------|
|
||||
| [Auto DevOps](topics/autodevops/index.md) | Automatically employ a complete DevOps lifecycle. |
|
||||
| [Create Kubernetes clusters on GKE](user/project/clusters/add_remove_clusters.md#add-new-gke-cluster) | Use Google Kubernetes Engine and GitLab. |
|
||||
| [Create Kubernetes clusters](user/project/clusters/add_remove_clusters.md#add-new-cluster) | Use Kubernetes and GitLab. |
|
||||
| [Executable Runbooks](user/project/clusters/runbooks/index.md) | Documented procedures that explain how to carry out particular processes. |
|
||||
| [GitLab ChatOps](ci/chatops/README.md) | Interact with CI/CD jobs through chat services. |
|
||||
| [Installing Applications](user/project/clusters/index.md#installing-applications) | Deploy Helm, Ingress, and Prometheus on Kubernetes. |
|
||||
|
|
|
|||
|
|
@ -100,7 +100,7 @@ To make full use of Auto DevOps, you will need:
|
|||
To enable deployments, you will need:
|
||||
|
||||
1. A [Kubernetes 1.12+ cluster](../../user/project/clusters/index.md) for the project. The easiest
|
||||
way is to add a [new GKE cluster using the GitLab UI](../../user/project/clusters/add_remove_clusters.md#add-new-gke-cluster).
|
||||
way is to add a [new cluster using the GitLab UI](../../user/project/clusters/add_remove_clusters.md#add-new-cluster).
|
||||
1. NGINX Ingress. You can deploy it to your Kubernetes cluster by installing
|
||||
the [GitLab-managed app for Ingress](../../user/clusters/applications.md#ingress),
|
||||
once you have configured GitLab's Kubernetes integration in the previous step.
|
||||
|
|
|
|||
|
|
@ -5,9 +5,6 @@ GitLab can integrate with the following Kubernetes providers:
|
|||
- Google Kubernetes Engine (GKE).
|
||||
- Amazon Elastic Kubernetes Service (EKS).
|
||||
|
||||
GitLab is more deeply integrated with GKE, but deeper integration with EKS
|
||||
[is planned](https://gitlab.com/gitlab-org/gitlab/issues/22392).
|
||||
|
||||
TIP: **Tip:**
|
||||
Every new Google Cloud Platform (GCP) account receives [$300 in credit upon sign up](https://console.cloud.google.com/freetrial),
|
||||
and in partnership with Google, GitLab is able to offer an additional $200 for new GCP accounts to get started with GitLab's
|
||||
|
|
@ -62,17 +59,17 @@ Note the following about access controls:
|
|||
|
||||
GitLab creates the following resources for RBAC clusters.
|
||||
|
||||
| Name | Type | Details | Created when |
|
||||
|:----------------------|:---------------------|:-----------------------------------------------------------------------------------------------------------|:---------------------------|
|
||||
| `gitlab` | `ServiceAccount` | `default` namespace | Creating a new GKE Cluster |
|
||||
| `gitlab-admin` | `ClusterRoleBinding` | [`cluster-admin`](https://kubernetes.io/docs/reference/access-authn-authz/rbac/#user-facing-roles) roleRef | Creating a new GKE Cluster |
|
||||
| `gitlab-token` | `Secret` | Token for `gitlab` ServiceAccount | Creating a new GKE Cluster |
|
||||
| `tiller` | `ServiceAccount` | `gitlab-managed-apps` namespace | Installing Helm Tiller |
|
||||
| `tiller-admin` | `ClusterRoleBinding` | `cluster-admin` roleRef | Installing Helm Tiller |
|
||||
| Environment namespace | `Namespace` | Contains all environment-specific resources | Deploying to a cluster |
|
||||
| Environment namespace | `ServiceAccount` | Uses namespace of environment | Deploying to a cluster |
|
||||
| Environment namespace | `Secret` | Token for environment ServiceAccount | Deploying to a cluster |
|
||||
| Environment namespace | `RoleBinding` | [`edit`](https://kubernetes.io/docs/reference/access-authn-authz/rbac/#user-facing-roles) roleRef | Deploying to a cluster |
|
||||
| Name | Type | Details | Created when |
|
||||
|:----------------------|:---------------------|:-----------------------------------------------------------------------------------------------------------|:-----------------------|
|
||||
| `gitlab` | `ServiceAccount` | `default` namespace | Creating a new cluster |
|
||||
| `gitlab-admin` | `ClusterRoleBinding` | [`cluster-admin`](https://kubernetes.io/docs/reference/access-authn-authz/rbac/#user-facing-roles) roleRef | Creating a new cluster |
|
||||
| `gitlab-token` | `Secret` | Token for `gitlab` ServiceAccount | Creating a new cluster |
|
||||
| `tiller` | `ServiceAccount` | `gitlab-managed-apps` namespace | Installing Helm Tiller |
|
||||
| `tiller-admin` | `ClusterRoleBinding` | `cluster-admin` roleRef | Installing Helm Tiller |
|
||||
| Environment namespace | `Namespace` | Contains all environment-specific resources | Deploying to a cluster |
|
||||
| Environment namespace | `ServiceAccount` | Uses namespace of environment | Deploying to a cluster |
|
||||
| Environment namespace | `Secret` | Token for environment ServiceAccount | Deploying to a cluster |
|
||||
| Environment namespace | `RoleBinding` | [`edit`](https://kubernetes.io/docs/reference/access-authn-authz/rbac/#user-facing-roles) roleRef | Deploying to a cluster |
|
||||
|
||||
### ABAC cluster resources
|
||||
|
||||
|
|
@ -80,13 +77,13 @@ GitLab creates the following resources for ABAC clusters.
|
|||
|
||||
| Name | Type | Details | Created when |
|
||||
|:----------------------|:---------------------|:-------------------------------------|:---------------------------|
|
||||
| `gitlab` | `ServiceAccount` | `default` namespace | Creating a new GKE Cluster |
|
||||
| `gitlab-token` | `Secret` | Token for `gitlab` ServiceAccount | Creating a new GKE Cluster |
|
||||
| `tiller` | `ServiceAccount` | `gitlab-managed-apps` namespace | Installing Helm Tiller |
|
||||
| `tiller-admin` | `ClusterRoleBinding` | `cluster-admin` roleRef | Installing Helm Tiller |
|
||||
| Environment namespace | `Namespace` | Contains all environment-specific resources | Deploying to a cluster |
|
||||
| Environment namespace | `ServiceAccount` | Uses namespace of environment | Deploying to a cluster |
|
||||
| Environment namespace | `Secret` | Token for environment ServiceAccount | Deploying to a cluster |
|
||||
| `gitlab` | `ServiceAccount` | `default` namespace | Creating a new cluster |
|
||||
| `gitlab-token` | `Secret` | Token for `gitlab` ServiceAccount | Creating a new cluster |
|
||||
| `tiller` | `ServiceAccount` | `gitlab-managed-apps` namespace | Installing Helm Tiller |
|
||||
| `tiller-admin` | `ClusterRoleBinding` | `cluster-admin` roleRef | Installing Helm Tiller |
|
||||
| Environment namespace | `Namespace` | Contains all environment-specific resources | Deploying to a cluster |
|
||||
| Environment namespace | `ServiceAccount` | Uses namespace of environment | Deploying to a cluster |
|
||||
| Environment namespace | `Secret` | Token for environment ServiceAccount | Deploying to a cluster |
|
||||
|
||||
### Security of GitLab Runners
|
||||
|
||||
|
|
@ -112,7 +109,9 @@ If you don't want to use GitLab Runner in privileged mode, either:
|
|||
1. Installing a Runner
|
||||
[using `docker+machine`](https://docs.gitlab.com/runner/executors/docker_machine.html).
|
||||
|
||||
## Add new GKE cluster
|
||||
## Add new cluster
|
||||
|
||||
### GKE cluster
|
||||
|
||||
GitLab supports:
|
||||
|
||||
|
|
@ -126,7 +125,7 @@ The [Google authentication integration](../../../integration/google.md) must
|
|||
be enabled in GitLab at the instance level. If that's not the case, ask your
|
||||
GitLab administrator to enable it. On GitLab.com, this is enabled.
|
||||
|
||||
### Requirements
|
||||
#### GKE Requirements
|
||||
|
||||
Before creating your first cluster on Google Kubernetes Engine with GitLab's
|
||||
integration, make sure the following requirements are met:
|
||||
|
|
@ -151,7 +150,7 @@ order to setup an [initial service account](#access-controls). Starting from [Gi
|
|||
11.10](https://gitlab.com/gitlab-org/gitlab-foss/issues/58208), the cluster creation process will
|
||||
explicitly request that basic authentication and client certificate is enabled.
|
||||
|
||||
### Creating the cluster
|
||||
#### Creating the cluster on GKE
|
||||
|
||||
If all of the above requirements are met, you can proceed to create and add a
|
||||
new Kubernetes cluster to your project:
|
||||
|
|
@ -185,7 +184,7 @@ new Kubernetes cluster to your project:
|
|||
After a couple of minutes, your cluster will be ready to go. You can now proceed
|
||||
to install some [pre-defined applications](index.md#installing-applications).
|
||||
|
||||
### Cloud Run on GKE
|
||||
#### Cloud Run on GKE
|
||||
|
||||
> [Introduced](https://gitlab.com/gitlab-org/gitlab/merge_requests/16566) in GitLab 12.4.
|
||||
|
||||
|
|
@ -194,6 +193,159 @@ separately after the cluster has been created. This means that Cloud Run
|
|||
(Knative), Istio, and HTTP Load Balancing will be enabled on the cluster at
|
||||
create time and cannot be [installed or uninstalled](../../clusters/applications.md) separately.
|
||||
|
||||
### EKS Cluster
|
||||
|
||||
GitLab supports:
|
||||
|
||||
- Creating a new EKS cluster using the GitLab UI
|
||||
([Introduced](https://gitlab.com/gitlab-org/gitlab/issues/22392) in GitLab 12.5).
|
||||
- Providing credentials to add an [existing Kubernetes cluster](#add-existing-cluster).
|
||||
|
||||
#### EKS Requirements
|
||||
|
||||
Before creating your first cluster on Amazon EKS with GitLab's integration,
|
||||
make sure the following requirements are met:
|
||||
|
||||
- An [Amazon Web Services](https://aws.amazon.com/) account is set up and you are able to log in.
|
||||
- You have permissions to manage IAM resources.
|
||||
|
||||
##### Additional requirements for self-managed instances
|
||||
|
||||
If you are using a self-managed GitLab instance, GitLab must first
|
||||
be configured with a set of Amazon credentials. These credentials
|
||||
will be used to assume an Amazon IAM role provided by the user
|
||||
creating the cluster. Create an IAM user and ensure it has permissions
|
||||
to assume the role(s) that your users will use to create EKS clusters.
|
||||
|
||||
For example, the following policy document allows assuming a role whose name starts with
|
||||
`gitlab-eks-` in account `123456789012`:
|
||||
|
||||
```json
|
||||
{
|
||||
"Version": "2012-10-17",
|
||||
"Statement": {
|
||||
"Effect": "Allow",
|
||||
"Action": "sts:AssumeRole",
|
||||
"Resource": "arn:aws:iam::123456789012:role/gitlab-eks-*"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Generate an access key for the IAM user, and configure GitLab with the credentials:
|
||||
|
||||
1. Navigate to **Admin Area > Settings > Integrations** and expand the **Amazon EKS** section.
|
||||
1. Check **Enable Amazon EKS integration**.
|
||||
1. Enter the account ID and access key credentials into the respective
|
||||
`Account ID`, `Access key ID` and `Secret access key` fields.
|
||||
1. Click **Save changes**.
|
||||
|
||||
#### Creating the cluster on EKS
|
||||
|
||||
If all of the above requirements are met, you can proceed to create and add a
|
||||
new Kubernetes cluster to your project:
|
||||
|
||||
1. Navigate to your project's **Operations > Kubernetes** page.
|
||||
|
||||
NOTE: **Note:**
|
||||
You need Maintainer [permissions](../../permissions.md) and above to access the Kubernetes page.
|
||||
|
||||
1. Click **Add Kubernetes cluster**.
|
||||
1. Click **Amazon EKS**. You will be provided with an `Account ID` and `External ID` to use in the next step.
|
||||
1. In the [IAM Management Console](https://console.aws.amazon.com/iam/home), create an IAM role:
|
||||
1. From the left panel, select **Roles**.
|
||||
1. Click **Create role**.
|
||||
1. Under `Select type of trusted entity`, select **Another AWS account**.
|
||||
1. Enter the Account ID from GitLab into the `Account ID` field.
|
||||
1. Check **Require external ID**.
|
||||
1. Enter the External ID from GitLab into the `External ID` field.
|
||||
1. Click **Next: Permissions**.
|
||||
1. Click **Create Policy**, which will open a new window.
|
||||
1. Select the **JSON** tab, and paste in the following snippet in place of the existing content:
|
||||
|
||||
```json
|
||||
{
|
||||
"Version": "2012-10-17",
|
||||
"Statement": [
|
||||
{
|
||||
"Effect": "Allow",
|
||||
"Action": [
|
||||
"autoscaling:CreateAutoScalingGroup",
|
||||
"autoscaling:DescribeAutoScalingGroups",
|
||||
"autoscaling:DescribeScalingActivities",
|
||||
"autoscaling:UpdateAutoScalingGroup",
|
||||
"autoscaling:CreateLaunchConfiguration",
|
||||
"autoscaling:DescribeLaunchConfigurations",
|
||||
"cloudformation:CreateStack",
|
||||
"cloudformation:DescribeStacks",
|
||||
"ec2:AuthorizeSecurityGroupEgress",
|
||||
"ec2:AuthorizeSecurityGroupIngress",
|
||||
"ec2:RevokeSecurityGroupEgress",
|
||||
"ec2:RevokeSecurityGroupIngress",
|
||||
"ec2:CreateSecurityGroup",
|
||||
"ec2:createTags",
|
||||
"ec2:DescribeImages",
|
||||
"ec2:DescribeKeyPairs",
|
||||
"ec2:DescribeRegions",
|
||||
"ec2:DescribeSecurityGroups",
|
||||
"ec2:DescribeSubnets",
|
||||
"ec2:DescribeVpcs",
|
||||
"eks:CreateCluster",
|
||||
"eks:DescribeCluster",
|
||||
"iam:AddRoleToInstanceProfile",
|
||||
"iam:AttachRolePolicy",
|
||||
"iam:CreateRole",
|
||||
"iam:CreateInstanceProfile",
|
||||
"iam:GetRole",
|
||||
"iam:ListRoles",
|
||||
"iam:PassRole",
|
||||
"ssm:GetParameters"
|
||||
],
|
||||
"Resource": "*"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
NOTE: **Note:**
|
||||
These permissions give GitLab the ability to create resources, but not delete them.
|
||||
This means that if an error is encountered during the creation process, changes will
|
||||
not be rolled back and you must remove resources manually. You can do this by deleting
|
||||
the relevant [CloudFormation stack](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/cfn-console-delete-stack.html)
|
||||
|
||||
1. Click **Review policy**.
|
||||
1. Enter a suitable name for this policy, and click **Create Policy**. You can now close this window.
|
||||
1. Switch back to the "Create role" window, and select the policy you just created.
|
||||
1. Click **Next: Tags**, and optionally enter any tags you wish to associate with this role.
|
||||
1. Click **Next: Review**.
|
||||
1. Enter a role name and optional description into the fields provided.
|
||||
1. Click **Create role**, the new role name will appear at the top. Click on its name and copy the `Role ARN` from the newly created role.
|
||||
1. In GitLab, enter the copied role ARN into the `Role ARN` field.
|
||||
1. Click **Authenticate with AWS**.
|
||||
1. Choose your cluster's settings:
|
||||
- **Kubernetes cluster name** - The name you wish to give the cluster.
|
||||
- **Environment scope** - The [associated environment](index.md#setting-the-environment-scope-premium) to this cluster.
|
||||
- **Kubernetes version** - The Kubernetes version to use. Currently the only version supported is 1.14.
|
||||
- **Role name** - Select the [IAM role](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles.html)
|
||||
to allow Amazon EKS and the Kubernetes control plane to manage AWS resources on your behalf.
|
||||
- **Region** - The [region](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/using-regions-availability-zones.html)
|
||||
in which the cluster will be created.
|
||||
- **Key pair name** - Select the [key pair](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-key-pairs.html)
|
||||
that you can use to connect to your worker nodes if required.
|
||||
- **VPC** - Select a [VPC](https://docs.aws.amazon.com/vpc/latest/userguide/what-is-amazon-vpc.html)
|
||||
to use for your EKS Cluster resources.
|
||||
- **Subnets** - Choose the [subnets](https://docs.aws.amazon.com/vpc/latest/userguide/VPC_Subnets.html)
|
||||
in your VPC where your worker nodes will run.
|
||||
- **Security group** - Choose the [security group](https://docs.aws.amazon.com/vpc/latest/userguide/VPC_SecurityGroups.html)
|
||||
to apply to the EKS-managed Elastic Network Interfaces that are created in your worker node subnets.
|
||||
- **Instance type** - The [instance type](https://aws.amazon.com/ec2/instance-types/) of your worker nodes.
|
||||
- **Node count** - The number of worker nodes.
|
||||
- **GitLab-managed cluster** - Leave this checked if you want GitLab to manage namespaces and service accounts for this cluster.
|
||||
See the [Managed clusters section](index.md#gitlab-managed-clusters) for more information.
|
||||
1. Finally, click the **Create Kubernetes cluster** button.
|
||||
|
||||
After about 10 minutes, your cluster will be ready to go. You can now proceed
|
||||
to install some [pre-defined applications](index.md#installing-applications).
|
||||
|
||||
## Add existing cluster
|
||||
|
||||
If you have either of the following types of clusters already, you can add them to a project:
|
||||
|
|
|
|||
|
|
@ -35,7 +35,7 @@ for an overview of how this is accomplished in GitLab!**
|
|||
To create an executable runbook, you will need:
|
||||
|
||||
1. **Kubernetes** - A Kubernetes cluster is required to deploy the rest of the applications.
|
||||
The simplest way to get started is to add a cluster using [GitLab's GKE integration](../add_remove_clusters.md#add-new-gke-cluster).
|
||||
The simplest way to get started is to add a cluster using one of [GitLab's integrations](../add_remove_clusters.md#add-new-cluster).
|
||||
1. **Helm Tiller** - Helm is a package manager for Kubernetes and is required to install
|
||||
all the other applications. It is installed in its own pod inside the cluster which
|
||||
can run the Helm CLI in a safe environment.
|
||||
|
|
@ -60,7 +60,7 @@ the components outlined above and the preloaded demo runbook.
|
|||
|
||||
### 1. Add a Kubernetes cluster
|
||||
|
||||
Follow the steps outlined in [Add new GKE cluster](../add_remove_clusters.md#add-new-gke-cluster)
|
||||
Follow the steps outlined in [Add new cluster](../add_remove_clusters.md#add-new-cluster)
|
||||
to add a Kubernetes cluster to your project.
|
||||
|
||||
### 2. Install Helm Tiller, Ingress, and JupyterHub
|
||||
|
|
|
|||
|
|
@ -41,7 +41,7 @@ To run Knative on GitLab, you will need:
|
|||
- If you are planning on deploying a serverless application, clone the sample [Knative Ruby App](https://gitlab.com/knative-examples/knative-ruby-app) to get started.
|
||||
|
||||
1. **Kubernetes Cluster:** An RBAC-enabled Kubernetes cluster is required to deploy Knative.
|
||||
The simplest way to get started is to add a cluster using [GitLab's GKE integration](../add_remove_clusters.md#add-new-gke-cluster).
|
||||
The simplest way to get started is to add a cluster using [GitLab's GKE integration](../add_remove_clusters.md#gke-cluster).
|
||||
The set of minimum recommended cluster specifications to run Knative is 3 nodes, 6 vCPUs, and 22.50 GB memory.
|
||||
1. **Helm Tiller:** Helm is a package manager for Kubernetes and is required to install
|
||||
Knative.
|
||||
|
|
@ -64,6 +64,8 @@ To run Knative on GitLab, you will need:
|
|||
using our [runtimes](https://gitlab.com/gitlab-org/serverless/runtimes).
|
||||
1. **Prometheus** (optional): Installing Prometheus allows you to monitor the scale and traffic of your serverless function/application.
|
||||
See [Installing Applications](../index.md#installing-applications) for more information.
|
||||
1. **Logging** (optional): Configuring logging allows you to view and search request logs for your serverless function/application.
|
||||
See [Configuring logging](#configuring-logging) for more information.
|
||||
|
||||
## Installing Knative via GitLab's Kubernetes integration
|
||||
|
||||
|
|
@ -166,13 +168,61 @@ You must do the following:
|
|||
or [serverless applications](#deploying-serverless-applications) onto your
|
||||
cluster.
|
||||
|
||||
## Deploying functions
|
||||
## Configuring logging
|
||||
|
||||
> Introduced in GitLab 11.6.
|
||||
> [Introduced](https://gitlab.com/gitlab-org/gitlab/issues/33330) in GitLab 12.5.
|
||||
|
||||
Using functions is useful for dealing with independent events without needing
|
||||
to maintain a complex unified infrastructure. This allows you to focus on a
|
||||
single task that can be executed/scaled automatically and independently.
|
||||
### Prerequisites
|
||||
|
||||
- A GitLab-managed cluster.
|
||||
- `kubectl` installed and working.
|
||||
|
||||
Running `kubectl` commands on your cluster requires setting up access to the
|
||||
cluster first. For clusters created on:
|
||||
|
||||
- GKE, see [GKE Cluster Access](https://cloud.google.com/kubernetes-engine/docs/how-to/cluster-access-for-kubectl)
|
||||
- Other platforms, see [Install and Set Up kubectl](https://kubernetes.io/docs/tasks/tools/install-kubectl/).
|
||||
|
||||
### Enable request log template
|
||||
|
||||
Run the following command to enable request logs:
|
||||
|
||||
```shell
|
||||
kubectl edit cm -n knative-serving config-observability
|
||||
```
|
||||
|
||||
Copy the `logging.request-log-template` from the `data._example` field to the data field one level up in the hierarchy.
|
||||
|
||||
### Enable request logs
|
||||
|
||||
Run the following commands to install Elasticsearch, Kibana, and Filebeat into a `kube-logging` namespace and configure all nodes to forward logs using Filebeat:
|
||||
|
||||
```shell
|
||||
kubectl apply -f https://gitlab.com/gitlab-org/serverless/configurations/knative/raw/v0.7.0/kube-logging-filebeat.yaml
|
||||
kubectl label nodes --all beta.kubernetes.io/filebeat-ready="true"
|
||||
```
|
||||
|
||||
### Viewing request logs
|
||||
|
||||
To view request logs:
|
||||
|
||||
1. Run `kubectl proxy`.
|
||||
1. Navigate to Kibana UI.
|
||||
|
||||
Or:
|
||||
|
||||
1. Open the Kibana UI.
|
||||
1. Click on **Discover**, then select `filebeat-*` from the dropdown on the left.
|
||||
1. Enter `kubernetes.container.name:"queue-proxy" AND message:/httpRequest/` into the search box.
|
||||
|
||||
## Supported runtimes
|
||||
|
||||
Serverless functions for GitLab can be written in 6 supported languages:
|
||||
|
||||
- NodeJS and Ruby, with GitLab-managed and OpenFaas runtimes.
|
||||
- C#, Go, PHP, and Python with OpenFaaS runtimes only.
|
||||
|
||||
### GitLab managed runtimes
|
||||
|
||||
Currently the following [runtimes](https://gitlab.com/gitlab-org/serverless/runtimes) are offered:
|
||||
|
||||
|
|
@ -182,6 +232,31 @@ Currently the following [runtimes](https://gitlab.com/gitlab-org/serverless/runt
|
|||
|
||||
`Dockerfile` presence is assumed when a runtime is not specified.
|
||||
|
||||
### OpenFaaS runtimes
|
||||
|
||||
> [Introduced](https://gitlab.com/gitlab-org/gitlab/issues/29253) in GitLab 12.5.
|
||||
|
||||
[OpenFaaS classic runtimes](https://github.com/openfaas/templates#templates-in-store) can be used with GitLab serverless.
|
||||
Runtimes are specified using the pattern: `openfaas/classic/<template_name>`. The following
|
||||
example shows how to define a function in `serverless.yml` using an OpenFaaS runtime:
|
||||
|
||||
```yaml
|
||||
hello:
|
||||
source: ./hello
|
||||
runtime: openfaas/classic/ruby
|
||||
description: "Ruby function using OpenFaaS classic runtime"
|
||||
```
|
||||
|
||||
`handler` is not needed for OpenFaaS functions. The location of the handler is defined
|
||||
by the conventions of the runtime.
|
||||
|
||||
See the [`ruby-openfaas-function`](https://gitlab.com/knative-examples/ruby-openfaas-function)
|
||||
project for an example of a function using an OpenFaaS runtime.
|
||||
|
||||
## Deploying functions
|
||||
|
||||
> Introduced in GitLab 11.6.
|
||||
|
||||
You can find and import all the files referenced in this doc in the
|
||||
**[functions example project](https://gitlab.com/knative-examples/functions)**.
|
||||
|
||||
|
|
@ -322,7 +397,7 @@ Running functions locally requires:
|
|||
- Go 1.12 or newer installed.
|
||||
- Docker Engine installed and running.
|
||||
- `gitlabktl` installed using the Go package manager:
|
||||
|
||||
|
||||
```shell
|
||||
GO111MODULE=on go get gitlab.com/gitlab-org/gitlabktl
|
||||
```
|
||||
|
|
@ -352,6 +427,10 @@ To run a function locally:
|
|||
|
||||
> Introduced in GitLab 11.5.
|
||||
|
||||
Serverless applications are the building block of serverless functions. They are useful in scenarios where an existing
|
||||
runtime does not meet the needs of an application, such as one written in a language that has no runtime available. Note
|
||||
though that serverless applications should be stateless!
|
||||
|
||||
NOTE: **Note:**
|
||||
You can reference and import the sample [Knative Ruby App](https://gitlab.com/knative-examples/knative-ruby-app) to get started.
|
||||
|
||||
|
|
|
|||
|
|
@ -73,6 +73,7 @@ module Gitlab
|
|||
clusters_applications_helm: count(::Clusters::Applications::Helm.available),
|
||||
clusters_applications_ingress: count(::Clusters::Applications::Ingress.available),
|
||||
clusters_applications_cert_managers: count(::Clusters::Applications::CertManager.available),
|
||||
clusters_applications_crossplane: count(::Clusters::Applications::Crossplane.available),
|
||||
clusters_applications_prometheus: count(::Clusters::Applications::Prometheus.available),
|
||||
clusters_applications_runner: count(::Clusters::Applications::Runner.available),
|
||||
clusters_applications_knative: count(::Clusters::Applications::Knative.available),
|
||||
|
|
|
|||
|
|
@ -1495,6 +1495,9 @@ msgstr ""
|
|||
msgid "Amazon EKS integration allows you to provision EKS clusters from GitLab."
|
||||
msgstr ""
|
||||
|
||||
msgid "Amazon Web Services"
|
||||
msgstr ""
|
||||
|
||||
msgid "Amazon authentication is not %{link_start}correctly configured%{link_end}. Ask your GitLab administrator if you want to use this service."
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -3646,6 +3649,12 @@ msgstr ""
|
|||
msgid "ClusterIntegration|Creating Kubernetes cluster"
|
||||
msgstr ""
|
||||
|
||||
msgid "ClusterIntegration|Crossplane"
|
||||
msgstr ""
|
||||
|
||||
msgid "ClusterIntegration|Crossplane enables declarative provisioning of managed services from your cloud of choice using %{kubectl} or %{gitlabIntegrationLink}. Crossplane runs inside your Kubernetes cluster and supports secure connectivity and secrets management between app containers and the cloud services they depend on."
|
||||
msgstr ""
|
||||
|
||||
msgid "ClusterIntegration|Did you know?"
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -3661,6 +3670,9 @@ msgstr ""
|
|||
msgid "ClusterIntegration|Enable this setting if using role-based access control (RBAC)."
|
||||
msgstr ""
|
||||
|
||||
msgid "ClusterIntegration|Enabled stack"
|
||||
msgstr ""
|
||||
|
||||
msgid "ClusterIntegration|Enter the details for your Amazon EKS Kubernetes cluster"
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -3709,6 +3721,9 @@ msgstr ""
|
|||
msgid "ClusterIntegration|GitLab-managed cluster"
|
||||
msgstr ""
|
||||
|
||||
msgid "ClusterIntegration|Gitlab Integration"
|
||||
msgstr ""
|
||||
|
||||
msgid "ClusterIntegration|Google Cloud Platform project"
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -4030,6 +4045,9 @@ msgstr ""
|
|||
msgid "ClusterIntegration|Select a region to choose a VPC"
|
||||
msgstr ""
|
||||
|
||||
msgid "ClusterIntegration|Select a stack to install Crossplane."
|
||||
msgstr ""
|
||||
|
||||
msgid "ClusterIntegration|Select machine type"
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -4982,6 +5000,9 @@ msgstr ""
|
|||
msgid "Cron syntax"
|
||||
msgstr ""
|
||||
|
||||
msgid "Crossplane"
|
||||
msgstr ""
|
||||
|
||||
msgid "Current Branch"
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -8442,6 +8463,9 @@ msgstr ""
|
|||
msgid "Golden Tanuki"
|
||||
msgstr ""
|
||||
|
||||
msgid "Google Cloud Platform"
|
||||
msgstr ""
|
||||
|
||||
msgid "Google Code import"
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -10885,6 +10909,9 @@ msgstr ""
|
|||
msgid "Metrics|e.g. req/sec"
|
||||
msgstr ""
|
||||
|
||||
msgid "Microsoft Azure"
|
||||
msgstr ""
|
||||
|
||||
msgid "Migrated %{success_count}/%{total_count} files."
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -14669,6 +14696,9 @@ msgstr ""
|
|||
msgid "Rollback"
|
||||
msgstr ""
|
||||
|
||||
msgid "Rook"
|
||||
msgstr ""
|
||||
|
||||
msgid "Run CI/CD pipelines for external repositories"
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -15243,6 +15273,9 @@ msgstr ""
|
|||
msgid "Select Page"
|
||||
msgstr ""
|
||||
|
||||
msgid "Select Stack"
|
||||
msgstr ""
|
||||
|
||||
msgid "Select a file from the left sidebar to begin editing. Afterwards, you'll be able to commit your changes."
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -19854,6 +19887,9 @@ msgstr ""
|
|||
msgid "You must provide your current password in order to change it."
|
||||
msgstr ""
|
||||
|
||||
msgid "You must select a stack for configuring your cloud provider. Learn more about"
|
||||
msgstr ""
|
||||
|
||||
msgid "You need a different license to enable FileLocks feature"
|
||||
msgstr ""
|
||||
|
||||
|
|
|
|||
|
|
@ -83,6 +83,11 @@ FactoryBot.define do
|
|||
cluster factory: %i(cluster with_installed_helm provided_by_gcp)
|
||||
end
|
||||
|
||||
factory :clusters_applications_crossplane, class: Clusters::Applications::Crossplane do
|
||||
stack { 'gcp' }
|
||||
cluster factory: %i(cluster with_installed_helm provided_by_gcp)
|
||||
end
|
||||
|
||||
factory :clusters_applications_prometheus, class: Clusters::Applications::Prometheus do
|
||||
cluster factory: %i(cluster with_installed_helm provided_by_gcp)
|
||||
end
|
||||
|
|
|
|||
|
|
@ -37,6 +37,7 @@
|
|||
"hostname": { "type": ["string", "null"] },
|
||||
"kibana_hostname": { "type": ["string", "null"] },
|
||||
"email": { "type": ["string", "null"] },
|
||||
"stack": { "type": ["string", "null"] },
|
||||
"update_available": { "type": ["boolean", "null"] },
|
||||
"can_uninstall": { "type": "boolean" }
|
||||
},
|
||||
|
|
|
|||
|
|
@ -286,16 +286,21 @@ describe('Clusters', () => {
|
|||
});
|
||||
|
||||
describe('installApplication', () => {
|
||||
it.each(APPLICATIONS)('tries to install %s', applicationId => {
|
||||
jest.spyOn(cluster.service, 'installApplication').mockResolvedValueOnce();
|
||||
it.each(APPLICATIONS)('tries to install %s', (applicationId, done) => {
|
||||
jest.spyOn(cluster.service, 'installApplication').mockResolvedValue();
|
||||
|
||||
cluster.store.state.applications[applicationId].status = INSTALLABLE;
|
||||
|
||||
cluster.installApplication({ id: applicationId });
|
||||
|
||||
expect(cluster.store.state.applications[applicationId].status).toEqual(INSTALLING);
|
||||
expect(cluster.store.state.applications[applicationId].requestReason).toEqual(null);
|
||||
expect(cluster.service.installApplication).toHaveBeenCalledWith(applicationId, undefined);
|
||||
// eslint-disable-next-line promise/valid-params
|
||||
cluster
|
||||
.installApplication({ id: applicationId })
|
||||
.then(() => {
|
||||
expect(cluster.store.state.applications[applicationId].status).toEqual(INSTALLING);
|
||||
expect(cluster.store.state.applications[applicationId].requestReason).toEqual(null);
|
||||
expect(cluster.service.installApplication).toHaveBeenCalledWith(applicationId, undefined);
|
||||
done();
|
||||
})
|
||||
.catch();
|
||||
});
|
||||
|
||||
it('sets error request status when the request fails', () => {
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ import { APPLICATIONS_MOCK_STATE } from '../services/mock_data';
|
|||
import eventHub from '~/clusters/event_hub';
|
||||
import { shallowMount } from '@vue/test-utils';
|
||||
import KnativeDomainEditor from '~/clusters/components/knative_domain_editor.vue';
|
||||
import CrossplaneProviderStack from '~/clusters/components/crossplane_provider_stack.vue';
|
||||
|
||||
describe('Applications', () => {
|
||||
let vm;
|
||||
|
|
@ -16,6 +17,7 @@ describe('Applications', () => {
|
|||
|
||||
gon.features = gon.features || {};
|
||||
gon.features.enableClusterApplicationElasticStack = true;
|
||||
gon.features.enableClusterApplicationCrossplane = true;
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
|
|
@ -42,6 +44,10 @@ describe('Applications', () => {
|
|||
expect(vm.$el.querySelector('.js-cluster-application-row-cert_manager')).not.toBeNull();
|
||||
});
|
||||
|
||||
it('renders a row for Crossplane', () => {
|
||||
expect(vm.$el.querySelector('.js-cluster-application-row-crossplane')).not.toBeNull();
|
||||
});
|
||||
|
||||
it('renders a row for Prometheus', () => {
|
||||
expect(vm.$el.querySelector('.js-cluster-application-row-prometheus')).not.toBeNull();
|
||||
});
|
||||
|
|
@ -83,6 +89,10 @@ describe('Applications', () => {
|
|||
expect(vm.$el.querySelector('.js-cluster-application-row-cert_manager')).not.toBeNull();
|
||||
});
|
||||
|
||||
it('renders a row for Crossplane', () => {
|
||||
expect(vm.$el.querySelector('.js-cluster-application-row-crossplane')).not.toBeNull();
|
||||
});
|
||||
|
||||
it('renders a row for Prometheus', () => {
|
||||
expect(vm.$el.querySelector('.js-cluster-application-row-prometheus')).not.toBeNull();
|
||||
});
|
||||
|
|
@ -124,6 +134,10 @@ describe('Applications', () => {
|
|||
expect(vm.$el.querySelector('.js-cluster-application-row-cert_manager')).not.toBeNull();
|
||||
});
|
||||
|
||||
it('renders a row for Crossplane', () => {
|
||||
expect(vm.$el.querySelector('.js-cluster-application-row-crossplane')).not.toBeNull();
|
||||
});
|
||||
|
||||
it('renders a row for Prometheus', () => {
|
||||
expect(vm.$el.querySelector('.js-cluster-application-row-prometheus')).not.toBeNull();
|
||||
});
|
||||
|
|
@ -179,6 +193,7 @@ describe('Applications', () => {
|
|||
},
|
||||
helm: { title: 'Helm Tiller' },
|
||||
cert_manager: { title: 'Cert-Manager' },
|
||||
crossplane: { title: 'Crossplane', stack: '' },
|
||||
runner: { title: 'GitLab Runner' },
|
||||
prometheus: { title: 'Prometheus' },
|
||||
jupyter: { title: 'JupyterHub', hostname: '' },
|
||||
|
|
@ -390,6 +405,32 @@ describe('Applications', () => {
|
|||
});
|
||||
});
|
||||
|
||||
describe('Crossplane application', () => {
|
||||
const propsData = {
|
||||
applications: {
|
||||
...APPLICATIONS_MOCK_STATE,
|
||||
crossplane: {
|
||||
title: 'Crossplane',
|
||||
stack: {
|
||||
code: '',
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
let wrapper;
|
||||
beforeEach(() => {
|
||||
wrapper = shallowMount(Applications, { propsData });
|
||||
});
|
||||
afterEach(() => {
|
||||
wrapper.destroy();
|
||||
});
|
||||
it('renders the correct Component', () => {
|
||||
const crossplane = wrapper.find(CrossplaneProviderStack);
|
||||
expect(crossplane.exists()).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Elastic Stack application', () => {
|
||||
describe('with ingress installed with ip & elastic stack installable', () => {
|
||||
it('renders hostname active input', () => {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,78 @@
|
|||
import { shallowMount } from '@vue/test-utils';
|
||||
import { GlDropdownItem } from '@gitlab/ui';
|
||||
import CrossplaneProviderStack from '~/clusters/components/crossplane_provider_stack.vue';
|
||||
|
||||
describe('CrossplaneProviderStack component', () => {
|
||||
let wrapper;
|
||||
|
||||
const defaultProps = {
|
||||
stacks: [
|
||||
{
|
||||
name: 'Google Cloud Platform',
|
||||
code: 'gcp',
|
||||
},
|
||||
{
|
||||
name: 'Amazon Web Services',
|
||||
code: 'aws',
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
function createComponent(props = {}) {
|
||||
const propsData = {
|
||||
...defaultProps,
|
||||
...props,
|
||||
};
|
||||
|
||||
wrapper = shallowMount(CrossplaneProviderStack, {
|
||||
propsData,
|
||||
});
|
||||
}
|
||||
|
||||
beforeEach(() => {
|
||||
const crossplane = {
|
||||
title: 'crossplane',
|
||||
stack: '',
|
||||
};
|
||||
createComponent({ crossplane });
|
||||
});
|
||||
|
||||
const findDropdownElements = () => wrapper.findAll(GlDropdownItem);
|
||||
const findFirstDropdownElement = () => findDropdownElements().at(0);
|
||||
|
||||
afterEach(() => {
|
||||
wrapper.destroy();
|
||||
});
|
||||
|
||||
it('renders all of the available stacks in the dropdown', () => {
|
||||
const dropdownElements = findDropdownElements();
|
||||
|
||||
expect(dropdownElements.length).toBe(defaultProps.stacks.length);
|
||||
|
||||
defaultProps.stacks.forEach((stack, index) =>
|
||||
expect(dropdownElements.at(index).text()).toEqual(stack.name),
|
||||
);
|
||||
});
|
||||
|
||||
it('displays the correct label for the first dropdown item if a stack is selected', () => {
|
||||
const crossplane = {
|
||||
title: 'crossplane',
|
||||
stack: 'gcp',
|
||||
};
|
||||
createComponent({ crossplane });
|
||||
expect(wrapper.vm.dropdownText).toBe('Google Cloud Platform');
|
||||
});
|
||||
|
||||
it('emits the "set" event with the selected stack value', () => {
|
||||
const crossplane = {
|
||||
title: 'crossplane',
|
||||
stack: 'gcp',
|
||||
};
|
||||
createComponent({ crossplane });
|
||||
findFirstDropdownElement().vm.$emit('click');
|
||||
expect(wrapper.emitted().set[0][0].code).toEqual('gcp');
|
||||
});
|
||||
it('it renders the correct dropdown text when no stack is selected', () => {
|
||||
expect(wrapper.vm.dropdownText).toBe('Select Stack');
|
||||
});
|
||||
});
|
||||
|
|
@ -52,9 +52,15 @@ const CLUSTERS_MOCK_DATA = {
|
|||
email: 'test@example.com',
|
||||
can_uninstall: false,
|
||||
},
|
||||
{
|
||||
name: 'crossplane',
|
||||
status: APPLICATION_STATUS.ERROR,
|
||||
status_reason: 'Cannot connect',
|
||||
can_uninstall: false,
|
||||
},
|
||||
{
|
||||
name: 'elastic_stack',
|
||||
status: APPLICATION_STATUS.INSTALLING,
|
||||
status: APPLICATION_STATUS.ERROR,
|
||||
status_reason: 'Cannot connect',
|
||||
can_uninstall: false,
|
||||
},
|
||||
|
|
@ -104,6 +110,12 @@ const CLUSTERS_MOCK_DATA = {
|
|||
status_reason: 'Cannot connect',
|
||||
email: 'test@example.com',
|
||||
},
|
||||
{
|
||||
name: 'crossplane',
|
||||
status: APPLICATION_STATUS.ERROR,
|
||||
status_reason: 'Cannot connect',
|
||||
stack: 'gcp',
|
||||
},
|
||||
{
|
||||
name: 'elastic_stack',
|
||||
status: APPLICATION_STATUS.ERROR,
|
||||
|
|
@ -116,6 +128,7 @@ const CLUSTERS_MOCK_DATA = {
|
|||
POST: {
|
||||
'/gitlab-org/gitlab-shell/clusters/1/applications/helm': {},
|
||||
'/gitlab-org/gitlab-shell/clusters/1/applications/ingress': {},
|
||||
'/gitlab-org/gitlab-shell/clusters/1/applications/crossplane': {},
|
||||
'/gitlab-org/gitlab-shell/clusters/1/applications/cert_manager': {},
|
||||
'/gitlab-org/gitlab-shell/clusters/1/applications/runner': {},
|
||||
'/gitlab-org/gitlab-shell/clusters/1/applications/prometheus': {},
|
||||
|
|
@ -138,6 +151,7 @@ const DEFAULT_APPLICATION_STATE = {
|
|||
const APPLICATIONS_MOCK_STATE = {
|
||||
helm: { title: 'Helm Tiller', status: 'installable' },
|
||||
ingress: { title: 'Ingress', status: 'installable' },
|
||||
crossplane: { title: 'Crossplane', status: 'installable', stack: '' },
|
||||
cert_manager: { title: 'Cert-Manager', status: 'installable' },
|
||||
runner: { title: 'GitLab Runner' },
|
||||
prometheus: { title: 'Prometheus' },
|
||||
|
|
|
|||
|
|
@ -71,6 +71,7 @@ describe('Clusters Store', () => {
|
|||
uninstallable: false,
|
||||
uninstallSuccessful: false,
|
||||
uninstallFailed: false,
|
||||
validationError: null,
|
||||
},
|
||||
ingress: {
|
||||
title: 'Ingress',
|
||||
|
|
@ -84,6 +85,7 @@ describe('Clusters Store', () => {
|
|||
uninstallable: false,
|
||||
uninstallSuccessful: false,
|
||||
uninstallFailed: false,
|
||||
validationError: null,
|
||||
},
|
||||
runner: {
|
||||
title: 'GitLab Runner',
|
||||
|
|
@ -100,6 +102,7 @@ describe('Clusters Store', () => {
|
|||
uninstallable: false,
|
||||
uninstallSuccessful: false,
|
||||
uninstallFailed: false,
|
||||
validationError: null,
|
||||
},
|
||||
prometheus: {
|
||||
title: 'Prometheus',
|
||||
|
|
@ -111,6 +114,7 @@ describe('Clusters Store', () => {
|
|||
uninstallable: false,
|
||||
uninstallSuccessful: false,
|
||||
uninstallFailed: false,
|
||||
validationError: null,
|
||||
},
|
||||
jupyter: {
|
||||
title: 'JupyterHub',
|
||||
|
|
@ -123,6 +127,7 @@ describe('Clusters Store', () => {
|
|||
uninstallable: false,
|
||||
uninstallSuccessful: false,
|
||||
uninstallFailed: false,
|
||||
validationError: null,
|
||||
},
|
||||
knative: {
|
||||
title: 'Knative',
|
||||
|
|
@ -140,6 +145,7 @@ describe('Clusters Store', () => {
|
|||
uninstallFailed: false,
|
||||
updateSuccessful: false,
|
||||
updateFailed: false,
|
||||
validationError: null,
|
||||
},
|
||||
cert_manager: {
|
||||
title: 'Cert-Manager',
|
||||
|
|
@ -152,11 +158,12 @@ describe('Clusters Store', () => {
|
|||
uninstallable: false,
|
||||
uninstallSuccessful: false,
|
||||
uninstallFailed: false,
|
||||
validationError: null,
|
||||
},
|
||||
elastic_stack: {
|
||||
title: 'Elastic Stack',
|
||||
status: mockResponseData.applications[7].status,
|
||||
installFailed: false,
|
||||
status: APPLICATION_STATUS.INSTALLABLE,
|
||||
installFailed: true,
|
||||
statusReason: mockResponseData.applications[7].status_reason,
|
||||
requestReason: null,
|
||||
kibana_hostname: '',
|
||||
|
|
@ -164,6 +171,19 @@ describe('Clusters Store', () => {
|
|||
uninstallable: false,
|
||||
uninstallSuccessful: false,
|
||||
uninstallFailed: false,
|
||||
validationError: null,
|
||||
},
|
||||
crossplane: {
|
||||
title: 'Crossplane',
|
||||
status: APPLICATION_STATUS.INSTALLABLE,
|
||||
installFailed: true,
|
||||
statusReason: mockResponseData.applications[8].status_reason,
|
||||
requestReason: null,
|
||||
installed: false,
|
||||
uninstallable: false,
|
||||
uninstallSuccessful: false,
|
||||
uninstallFailed: false,
|
||||
validationError: null,
|
||||
},
|
||||
},
|
||||
environments: [],
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'spec_helper'
|
||||
|
||||
describe Gitlab::Gfm::ReferenceRewriter do
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'spec_helper'
|
||||
|
||||
describe Gitlab::Gfm::UploadsRewriter do
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'spec_helper'
|
||||
|
||||
describe Gitlab::GithubImport::BulkImporting do
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'spec_helper'
|
||||
|
||||
describe Gitlab::GithubImport::Caching, :clean_gitlab_redis_cache do
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'spec_helper'
|
||||
|
||||
describe Gitlab::GithubImport::Client do
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'spec_helper'
|
||||
|
||||
describe Gitlab::GithubImport::Importer::DiffNoteImporter do
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'spec_helper'
|
||||
|
||||
describe Gitlab::GithubImport::Importer::DiffNotesImporter do
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'spec_helper'
|
||||
|
||||
describe Gitlab::GithubImport::Importer::IssueAndLabelLinksImporter do
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'spec_helper'
|
||||
|
||||
describe Gitlab::GithubImport::Importer::IssueImporter, :clean_gitlab_redis_cache do
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'spec_helper'
|
||||
|
||||
describe Gitlab::GithubImport::Importer::IssuesImporter do
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'spec_helper'
|
||||
|
||||
describe Gitlab::GithubImport::Importer::LabelLinksImporter do
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'spec_helper'
|
||||
|
||||
describe Gitlab::GithubImport::Importer::LabelsImporter, :clean_gitlab_redis_cache do
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'spec_helper'
|
||||
|
||||
describe Gitlab::GithubImport::Importer::LfsObjectImporter do
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'spec_helper'
|
||||
|
||||
describe Gitlab::GithubImport::Importer::LfsObjectsImporter do
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'spec_helper'
|
||||
|
||||
describe Gitlab::GithubImport::Importer::MilestonesImporter, :clean_gitlab_redis_cache do
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'spec_helper'
|
||||
|
||||
describe Gitlab::GithubImport::Importer::NoteImporter do
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'spec_helper'
|
||||
|
||||
describe Gitlab::GithubImport::Importer::NotesImporter do
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'spec_helper'
|
||||
|
||||
describe Gitlab::GithubImport::Importer::PullRequestImporter, :clean_gitlab_redis_cache do
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'spec_helper'
|
||||
|
||||
describe Gitlab::GithubImport::Importer::PullRequestsImporter do
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'spec_helper'
|
||||
|
||||
describe Gitlab::GithubImport::Importer::ReleasesImporter do
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'spec_helper'
|
||||
|
||||
describe Gitlab::GithubImport::Importer::RepositoryImporter do
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'spec_helper'
|
||||
|
||||
describe Gitlab::GithubImport::IssuableFinder, :clean_gitlab_redis_cache do
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'spec_helper'
|
||||
|
||||
describe Gitlab::GithubImport::LabelFinder, :clean_gitlab_redis_cache do
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'spec_helper'
|
||||
|
||||
describe Gitlab::GithubImport::MarkdownText do
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'spec_helper'
|
||||
|
||||
describe Gitlab::GithubImport::MilestoneFinder, :clean_gitlab_redis_cache do
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'spec_helper'
|
||||
|
||||
describe Gitlab::GithubImport::PageCounter, :clean_gitlab_redis_cache do
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'spec_helper'
|
||||
|
||||
describe Gitlab::GithubImport::ParallelImporter do
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'spec_helper'
|
||||
|
||||
describe Gitlab::GithubImport::ParallelScheduling do
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'spec_helper'
|
||||
|
||||
describe Gitlab::GithubImport::Representation::DiffNote do
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'spec_helper'
|
||||
|
||||
describe Gitlab::GithubImport::Representation::ExposeAttribute do
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'spec_helper'
|
||||
|
||||
describe Gitlab::GithubImport::Representation::Issue do
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'spec_helper'
|
||||
|
||||
describe Gitlab::GithubImport::Representation::Note do
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'spec_helper'
|
||||
|
||||
describe Gitlab::GithubImport::Representation::PullRequest do
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'spec_helper'
|
||||
|
||||
describe Gitlab::GithubImport::Representation::ToHash do
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'spec_helper'
|
||||
|
||||
describe Gitlab::GithubImport::Representation::User do
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'spec_helper'
|
||||
|
||||
describe Gitlab::GithubImport::Representation do
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'spec_helper'
|
||||
|
||||
describe Gitlab::GithubImport::SequentialImporter do
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'spec_helper'
|
||||
|
||||
describe Gitlab::GithubImport::UserFinder, :clean_gitlab_redis_cache do
|
||||
|
|
|
|||
|
|
@ -44,6 +44,7 @@ describe Gitlab::UsageData do
|
|||
create(:clusters_applications_ingress, :installed, cluster: gcp_cluster)
|
||||
create(:clusters_applications_cert_manager, :installed, cluster: gcp_cluster)
|
||||
create(:clusters_applications_prometheus, :installed, cluster: gcp_cluster)
|
||||
create(:clusters_applications_crossplane, :installed, cluster: gcp_cluster)
|
||||
create(:clusters_applications_runner, :installed, cluster: gcp_cluster)
|
||||
create(:clusters_applications_knative, :installed, cluster: gcp_cluster)
|
||||
create(:clusters_applications_elastic_stack, :installed, cluster: gcp_cluster)
|
||||
|
|
@ -140,6 +141,7 @@ describe Gitlab::UsageData do
|
|||
clusters_applications_ingress
|
||||
clusters_applications_cert_managers
|
||||
clusters_applications_prometheus
|
||||
clusters_applications_crossplane
|
||||
clusters_applications_runner
|
||||
clusters_applications_knative
|
||||
clusters_applications_elastic_stack
|
||||
|
|
@ -222,6 +224,7 @@ describe Gitlab::UsageData do
|
|||
expect(count_data[:clusters_applications_helm]).to eq(1)
|
||||
expect(count_data[:clusters_applications_ingress]).to eq(1)
|
||||
expect(count_data[:clusters_applications_cert_managers]).to eq(1)
|
||||
expect(count_data[:clusters_applications_crossplane]).to eq(1)
|
||||
expect(count_data[:clusters_applications_prometheus]).to eq(1)
|
||||
expect(count_data[:clusters_applications_runner]).to eq(1)
|
||||
expect(count_data[:clusters_applications_knative]).to eq(1)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,57 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'spec_helper'
|
||||
|
||||
describe Clusters::Applications::Crossplane do
|
||||
let(:crossplane) { create(:clusters_applications_crossplane) }
|
||||
|
||||
include_examples 'cluster application core specs', :clusters_applications_crossplane
|
||||
include_examples 'cluster application status specs', :clusters_applications_crossplane
|
||||
include_examples 'cluster application version specs', :clusters_applications_crossplane
|
||||
include_examples 'cluster application initial status specs'
|
||||
|
||||
describe 'validations' do
|
||||
it { is_expected.to validate_presence_of(:stack) }
|
||||
end
|
||||
|
||||
describe '#can_uninstall?' do
|
||||
subject { crossplane.can_uninstall? }
|
||||
|
||||
it { is_expected.to be_truthy }
|
||||
end
|
||||
|
||||
describe '#install_command' do
|
||||
let(:stack) { 'gcp' }
|
||||
|
||||
subject { crossplane.install_command }
|
||||
|
||||
it { is_expected.to be_an_instance_of(Gitlab::Kubernetes::Helm::InstallCommand) }
|
||||
|
||||
it 'is initialized with crossplane arguments' do
|
||||
expect(subject.name).to eq('crossplane')
|
||||
expect(subject.chart).to eq('crossplane/crossplane')
|
||||
expect(subject.repository).to eq('https://charts.crossplane.io/alpha')
|
||||
expect(subject.version).to eq('0.4.1')
|
||||
expect(subject).to be_rbac
|
||||
end
|
||||
|
||||
context 'application failed to install previously' do
|
||||
let(:crossplane) { create(:clusters_applications_crossplane, :errored, version: '0.0.1') }
|
||||
|
||||
it 'is initialized with the locked version' do
|
||||
expect(subject.version).to eq('0.4.1')
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '#files' do
|
||||
let(:application) { crossplane }
|
||||
let(:values) { subject[:'values.yaml'] }
|
||||
|
||||
subject { application.files }
|
||||
|
||||
it 'includes crossplane specific keys in the values.yaml file' do
|
||||
expect(values).to include('clusterStacks')
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -515,6 +515,7 @@ describe Clusters::Cluster, :use_clean_rails_memory_store_caching do
|
|||
let!(:helm) { create(:clusters_applications_helm, cluster: cluster) }
|
||||
let!(:ingress) { create(:clusters_applications_ingress, cluster: cluster) }
|
||||
let!(:cert_manager) { create(:clusters_applications_cert_manager, cluster: cluster) }
|
||||
let!(:crossplane) { create(:clusters_applications_crossplane, cluster: cluster) }
|
||||
let!(:prometheus) { create(:clusters_applications_prometheus, cluster: cluster) }
|
||||
let!(:runner) { create(:clusters_applications_runner, cluster: cluster) }
|
||||
let!(:jupyter) { create(:clusters_applications_jupyter, cluster: cluster) }
|
||||
|
|
@ -522,7 +523,7 @@ describe Clusters::Cluster, :use_clean_rails_memory_store_caching do
|
|||
let!(:elastic_stack) { create(:clusters_applications_elastic_stack, cluster: cluster) }
|
||||
|
||||
it 'returns a list of created applications' do
|
||||
is_expected.to contain_exactly(helm, ingress, cert_manager, prometheus, runner, jupyter, knative, elastic_stack)
|
||||
is_expected.to contain_exactly(helm, ingress, cert_manager, crossplane, prometheus, runner, jupyter, knative, elastic_stack)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
Loading…
Reference in New Issue