Merge branch 'cert-manager-email' into 'master'

Ability to override Issuer Email for Cert Manager

See merge request gitlab-org/gitlab-ce!23503
This commit is contained in:
Dmitriy Zaporozhets 2018-12-07 20:10:15 +00:00
commit f689b1612e
16 changed files with 202 additions and 32 deletions

View File

@ -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(
@ -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.`,
),
),
{
@ -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">
@ -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>
@ -295,10 +297,41 @@ 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"
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"
@ -381,16 +414,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>

View File

@ -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';

View File

@ -1,5 +1,5 @@
import { s__ } from '../../locale';
import { INGRESS, JUPYTER, KNATIVE } from '../constants';
import { INGRESS, JUPYTER, KNATIVE, CERT_MANAGER } from '../constants';
export default class ClusterStore {
constructor() {
@ -30,6 +30,7 @@ export default class ClusterStore {
statusReason: null,
requestStatus: null,
requestReason: null,
email: null,
},
runner: {
title: s__('ClusterIntegration|GitLab Runner'),
@ -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 ||

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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)

View File

@ -0,0 +1,5 @@
---
title: Ability to override email for cert-manager
merge_request: 23503
author: Amit Rathi
type: added

View File

@ -267,7 +267,7 @@ 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/) |

View File

@ -1473,6 +1473,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 ""
@ -1587,6 +1590,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 ""
@ -1806,9 +1815,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 ""

View File

@ -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

View File

@ -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" ]
}

View File

@ -176,6 +176,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', () => {

View File

@ -42,6 +42,7 @@ const CLUSTERS_MOCK_DATA = {
name: 'cert_manager',
status: APPLICATION_STATUS.ERROR,
status_reason: 'Cannot connect',
email: 'test@example.com',
},
],
},
@ -86,6 +87,7 @@ const CLUSTERS_MOCK_DATA = {
name: 'cert_manager',
status: APPLICATION_STATUS.ERROR,
status_reason: 'Cannot connect',
email: 'test@example.com',
},
],
},

View File

@ -115,6 +115,7 @@ describe('Clusters Store', () => {
statusReason: mockResponseData.applications[6].status_reason,
requestStatus: null,
requestReason: null,
email: mockResponseData.applications[6].email,
},
},
});

View File

@ -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
{