Skip to content
Snippets Groups Projects
Commit 1cdcf402 authored by Amit Rathi's avatar Amit Rathi
Browse files

Allows user to override default issuer email for cert manager

parent a445aa0a
No related branches found
No related tags found
No related merge requests found
Showing
with 202 additions and 32 deletions
Loading
Loading
@@ -84,6 +84,9 @@ export default {
ingressExternalIp() {
return this.applications.ingress.externalIp;
},
certManagerInstalled() {
return this.applications.cert_manager.status === APPLICATION_STATUS.INSTALLED;
},
ingressDescription() {
const extraCostParagraph = sprintf(
_.escape(
Loading
Loading
@@ -130,9 +133,9 @@ export default {
return sprintf(
_.escape(
s__(
`ClusterIntegration|cert-manager is a native Kubernetes certificate management controller that helps with issuing certificates.
Installing cert-manager on your cluster will issue a certificate by %{letsEncrypt} and ensure that certificates
are valid and up to date.`,
`ClusterIntegration|Cert-Manager is a native Kubernetes certificate management controller that helps with issuing certificates.
Installing Cert-Manager on your cluster will issue a certificate by %{letsEncrypt} and ensure that certificates
are valid and up-to-date.`,
),
),
{
Loading
Loading
@@ -259,6 +262,16 @@ export default {
</span>
</div>
<input v-else type="text" class="form-control js-ip-address" readonly value="?" />
<p class="form-text text-muted">
{{
s__(`ClusterIntegration|Point a wildcard DNS to this
generated IP address in order to access
your application after it has been deployed.`)
}}
<a :href="ingressDnsHelpPath" target="_blank" rel="noopener noreferrer">
{{ __('More information') }}
</a>
</p>
</div>
 
<p v-if="!ingressExternalIp" class="settings-message js-no-ip-message">
Loading
Loading
@@ -272,17 +285,6 @@ export default {
{{ __('More information') }}
</a>
</p>
<p>
{{
s__(`ClusterIntegration|Point a wildcard DNS to this
generated IP address in order to access
your application after it has been deployed.`)
}}
<a :href="ingressDnsHelpPath" target="_blank" rel="noopener noreferrer">
{{ __('More information') }}
</a>
</p>
</template>
<div v-html="ingressDescription"></div>
</div>
Loading
Loading
@@ -295,11 +297,42 @@ export default {
:status-reason="applications.cert_manager.statusReason"
:request-status="applications.cert_manager.requestStatus"
:request-reason="applications.cert_manager.requestReason"
:install-application-request-params="{ email: applications.cert_manager.email }"
:disabled="!helmInstalled"
class="hide-bottom-border rounded-bottom"
title-link="https://cert-manager.readthedocs.io/en/latest/#"
>
<div slot="description" v-html="certManagerDescription"></div>
<template>
<div slot="description">
<p v-html="certManagerDescription"></p>
<div class="form-group">
<label for="cert-manager-issuer-email">
{{ s__('ClusterIntegration|Issuer Email') }}
</label>
<div class="input-group">
<input
v-model="applications.cert_manager.email"
:readonly="certManagerInstalled"
type="text"
class="form-control js-email"
/>
</div>
<p class="form-text text-muted">
{{
s__(`ClusterIntegration|Issuers represent a certificate authority.
You must provide an email address for your Issuer. `)
}}
<a
href="http://docs.cert-manager.io/en/latest/reference/issuers.html?highlight=email"
target="_blank"
rel="noopener noreferrer"
>
{{ __('More information') }}
</a>
</p>
</div>
</div>
</template>
</application-row>
<application-row
v-if="isProjectCluster"
Loading
Loading
@@ -382,16 +415,17 @@ export default {
/>
</span>
</div>
<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.`)
}}
<a :href="ingressDnsHelpPath" target="_blank" rel="noopener noreferrer">
{{ __('More information') }}
</a>
</p>
</div>
<p v-if="ingressInstalled">
{{
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>
Loading
Loading
Loading
Loading
@@ -24,3 +24,4 @@ export const REQUEST_FAILURE = 'request-failure';
export const INGRESS = 'ingress';
export const JUPYTER = 'jupyter';
export const KNATIVE = 'knative';
export const CERT_MANAGER = 'cert_manager';
import { s__ } from '../../locale';
import { INGRESS, JUPYTER, KNATIVE } from '../constants';
import { INGRESS, JUPYTER, KNATIVE, CERT_MANAGER } from '../constants';
 
export default class ClusterStore {
constructor() {
Loading
Loading
@@ -30,6 +30,7 @@ export default class ClusterStore {
statusReason: null,
requestStatus: null,
requestReason: null,
email: null,
},
runner: {
title: s__('ClusterIntegration|GitLab Runner'),
Loading
Loading
@@ -103,6 +104,9 @@ export default class ClusterStore {
 
if (appId === INGRESS) {
this.state.applications.ingress.externalIp = serverAppEntry.external_ip;
} else if (appId === CERT_MANAGER) {
this.state.applications.cert_manager.email =
this.state.applications.cert_manager.email || serverAppEntry.email;
} else if (appId === JUPYTER) {
this.state.applications.jupyter.hostname =
serverAppEntry.hostname ||
Loading
Loading
Loading
Loading
@@ -23,6 +23,6 @@ class Clusters::ApplicationsController < Clusters::BaseController
end
 
def create_cluster_application_params
params.permit(:application, :hostname)
params.permit(:application, :hostname, :email)
end
end
Loading
Loading
@@ -14,6 +14,10 @@ module Clusters
 
default_value_for :version, VERSION
 
default_value_for :email do |cert_manager|
cert_manager.cluster&.user&.email
end
validates :email, presence: true
 
def chart
Loading
Loading
Loading
Loading
@@ -6,4 +6,5 @@ class ClusterApplicationEntity < Grape::Entity
expose :status_reason
expose :external_ip, if: -> (e, _) { e.respond_to?(:external_ip) }
expose :hostname, if: -> (e, _) { e.respond_to?(:hostname) }
expose :email, if: -> (e, _) { e.respond_to?(:email) }
end
Loading
Loading
@@ -20,7 +20,7 @@ module Clusters
end
 
if application.has_attribute?(:email)
application.email = current_user.email
application.email = params[:email]
end
 
if application.respond_to?(:oauth_application)
Loading
Loading
---
title: Ability to override email for cert-manager
merge_request: 23503
author: Amit Rathi
type: added
Loading
Loading
@@ -260,7 +260,7 @@ twice, which can lead to confusion during deployments.
| ----------- | :------------: | ----------- | --------------- |
| [Helm Tiller](https://docs.helm.sh/) | 10.2+ | 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. | n/a |
| [Ingress](https://kubernetes.io/docs/concepts/services-networking/ingress/) | 10.2+ | Ingress can provide load balancing, SSL termination, and name-based virtual hosting. It acts as a web proxy for your applications and is useful if you want to use [Auto DevOps] or deploy your own web apps. | [stable/nginx-ingress](https://github.com/helm/charts/tree/master/stable/nginx-ingress) |
| [Cert Manager](http://docs.cert-manager.io/en/latest/) | 11.6+ | Cert Manager is a native Kubernetes certificate management controller that helps with issuing certificates. Installing Cert Manager on your cluster will issue a certificate by [Let's Encrypt](https://letsencrypt.org/) and ensure that certificates are valid and up to date. The email address used by Let's Encrypt registration will be taken from the GitLab user that installed Cert Manager on the cluster. | [stable/cert-manager](https://github.com/helm/charts/tree/master/stable/cert-manager) |
| [Cert Manager](http://docs.cert-manager.io/en/latest/) | 11.6+ | Cert Manager is a native Kubernetes certificate management controller that helps with issuing certificates. Installing Cert Manager on your cluster will issue a certificate by [Let's Encrypt](https://letsencrypt.org/) and ensure that certificates are valid and up to date. | [stable/cert-manager](https://github.com/helm/charts/tree/master/stable/cert-manager) |
| [Prometheus](https://prometheus.io/docs/introduction/overview/) | 10.4+ | Prometheus is an open-source monitoring and alerting system useful to supervise your deployed applications. | [stable/prometheus](https://github.com/helm/charts/tree/master/stable/prometheus) |
| [GitLab Runner](https://docs.gitlab.com/runner/) | 10.6+ | GitLab Runner is the open source project that is used to run your jobs and send the results back to GitLab. It is used in conjunction with [GitLab CI/CD](https://about.gitlab.com/features/gitlab-ci-cd/), the open-source continuous integration service included with GitLab that coordinates the jobs. When installing the GitLab Runner via the applications, it will run in **privileged mode** by default. Make sure you read the [security implications](#security-implications) before doing so. | [runner/gitlab-runner](https://gitlab.com/charts/gitlab-runner) |
| [JupyterHub](http://jupyter.org/) | 11.0+ | [JupyterHub](https://jupyterhub.readthedocs.io/en/stable/) is a multi-user service for managing notebooks across a team. [Jupyter Notebooks](https://jupyter-notebook.readthedocs.io/en/latest/) provide a web-based interactive programming environment used for data analysis, visualization, and machine learning. We use [this](https://gitlab.com/gitlab-org/jupyterhub-user-image/blob/master/Dockerfile) custom Jupyter image that installs additional useful packages on top of the base Jupyter. You will also see ready-to-use DevOps Runbooks built with Nurtch's [Rubix library](https://github.com/amit1rrr/rubix). More information on creating executable runbooks can be found at [Nurtch Documentation](http://docs.nurtch.com/en/latest). **Note**: Authentication will be enabled for any user of the GitLab server via OAuth2. HTTPS will be supported in a future release. | [jupyter/jupyterhub](https://jupyterhub.github.io/helm-chart/) |
Loading
Loading
Loading
Loading
@@ -1445,6 +1445,9 @@ msgstr ""
msgid "ClusterIntegration|Cert-Manager"
msgstr ""
 
msgid "ClusterIntegration|Cert-Manager is a native Kubernetes certificate management controller that helps with issuing certificates. Installing Cert-Manager on your cluster will issue a certificate by %{letsEncrypt} and ensure that certificates are valid and up-to-date."
msgstr ""
msgid "ClusterIntegration|Certificate Authority bundle (PEM format)"
msgstr ""
 
Loading
Loading
@@ -1559,6 +1562,12 @@ msgstr ""
msgid "ClusterIntegration|Integration status"
msgstr ""
 
msgid "ClusterIntegration|Issuer Email"
msgstr ""
msgid "ClusterIntegration|Issuers represent a certificate authority. You must provide an email address for your Issuer. "
msgstr ""
msgid "ClusterIntegration|Jupyter Hostname"
msgstr ""
 
Loading
Loading
@@ -1778,9 +1787,6 @@ msgstr ""
msgid "ClusterIntegration|access to Google Kubernetes Engine"
msgstr ""
 
msgid "ClusterIntegration|cert-manager is a native Kubernetes certificate management controller that helps with issuing certificates. Installing cert-manager on your cluster will issue a certificate by %{letsEncrypt} and ensure that certificates are valid and up to date."
msgstr ""
msgid "ClusterIntegration|check the pricing here"
msgstr ""
 
Loading
Loading
Loading
Loading
@@ -70,6 +70,44 @@ describe 'Clusters Applications', :js do
end
end
 
context 'when user installs Cert Manager' do
before do
allow(ClusterInstallAppWorker).to receive(:perform_async)
allow(ClusterWaitForIngressIpAddressWorker).to receive(:perform_in)
allow(ClusterWaitForIngressIpAddressWorker).to receive(:perform_async)
create(:clusters_applications_helm, :installed, cluster: cluster)
page.within('.js-cluster-application-row-cert_manager') do
click_button 'Install'
end
end
it 'shows status transition' do
def email_form_value
page.find('.js-email').value
end
page.within('.js-cluster-application-row-cert_manager') do
expect(email_form_value).to eq(cluster.user.email)
expect(page).to have_css('.js-cluster-application-install-button', exact_text: 'Install')
page.find('.js-email').set("new_email@example.org")
Clusters::Cluster.last.application_cert_manager.make_installing!
expect(email_form_value).to eq('new_email@example.org')
expect(page).to have_css('.js-cluster-application-install-button', exact_text: 'Installing')
Clusters::Cluster.last.application_cert_manager.make_installed!
expect(email_form_value).to eq('new_email@example.org')
expect(page).to have_css('.js-cluster-application-install-button', exact_text: 'Installed')
end
expect(page).to have_content('Cert-Manager was successfully installed on your Kubernetes cluster')
end
end
context 'when user installs Ingress' do
context 'when user installs application: Ingress' do
before do
Loading
Loading
Loading
Loading
@@ -32,7 +32,8 @@
},
"status_reason": { "type": ["string", "null"] },
"external_ip": { "type": ["string", "null"] },
"hostname": { "type": ["string", "null"] }
"hostname": { "type": ["string", "null"] },
"email": { "type": ["string", "null"] }
},
"required" : [ "name", "status" ]
}
Loading
Loading
Loading
Loading
@@ -129,6 +129,54 @@ describe('Applications', () => {
});
});
 
describe('Cert-Manager application', () => {
describe('when not installed', () => {
it('renders email & allows editing', () => {
vm = mountComponent(Applications, {
applications: {
helm: { title: 'Helm Tiller', status: 'installed' },
ingress: { title: 'Ingress', status: 'installed', externalIp: '1.1.1.1' },
cert_manager: {
title: 'Cert-Manager',
email: 'before@example.com',
status: 'installable',
},
runner: { title: 'GitLab Runner' },
prometheus: { title: 'Prometheus' },
jupyter: { title: 'JupyterHub', hostname: '', status: 'installable' },
knative: { title: 'Knative', hostname: '', status: 'installable' },
},
});
expect(vm.$el.querySelector('.js-email').value).toEqual('before@example.com');
expect(vm.$el.querySelector('.js-email').getAttribute('readonly')).toBe(null);
});
});
describe('when installed', () => {
it('renders email in readonly', () => {
vm = mountComponent(Applications, {
applications: {
helm: { title: 'Helm Tiller', status: 'installed' },
ingress: { title: 'Ingress', status: 'installed', externalIp: '1.1.1.1' },
cert_manager: {
title: 'Cert-Manager',
email: 'after@example.com',
status: 'installed',
},
runner: { title: 'GitLab Runner' },
prometheus: { title: 'Prometheus' },
jupyter: { title: 'JupyterHub', hostname: '', status: 'installable' },
knative: { title: 'Knative', hostname: '', status: 'installable' },
},
});
expect(vm.$el.querySelector('.js-email').value).toEqual('after@example.com');
expect(vm.$el.querySelector('.js-email').getAttribute('readonly')).toEqual('readonly');
});
});
});
describe('Jupyter application', () => {
describe('with ingress installed with ip & jupyter installable', () => {
it('renders hostname active input', () => {
Loading
Loading
Loading
Loading
@@ -42,6 +42,7 @@ const CLUSTERS_MOCK_DATA = {
name: 'cert_manager',
status: APPLICATION_STATUS.ERROR,
status_reason: 'Cannot connect',
email: 'test@example.com',
},
],
},
Loading
Loading
@@ -86,6 +87,7 @@ const CLUSTERS_MOCK_DATA = {
name: 'cert_manager',
status: APPLICATION_STATUS.ERROR,
status_reason: 'Cannot connect',
email: 'test@example.com',
},
],
},
Loading
Loading
Loading
Loading
@@ -115,6 +115,7 @@ describe('Clusters Store', () => {
statusReason: mockResponseData.applications[6].status_reason,
requestStatus: null,
requestReason: null,
email: mockResponseData.applications[6].email,
},
},
});
Loading
Loading
Loading
Loading
@@ -31,6 +31,31 @@ describe Clusters::Applications::CreateService do
subject
end
 
context 'cert manager application' do
let(:params) do
{
application: 'cert_manager',
email: 'test@example.com'
}
end
before do
allow_any_instance_of(Clusters::Applications::ScheduleInstallationService).to receive(:execute)
end
it 'creates the application' do
expect do
subject
cluster.reload
end.to change(cluster, :application_cert_manager)
end
it 'sets the email' do
expect(subject.email).to eq('test@example.com')
end
end
context 'jupyter application' do
let(:params) do
{
Loading
Loading
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment