Implement Helm ResetCommand for removing Tiller
Also creates specs Only allow Helm to be uninstalled if it's the only app - Remove Tiller leftovers after reser command - Fixes specs and offenses Adds changelog file Fix reset_command specs
This commit is contained in:
parent
2d697018ca
commit
5027979b9b
11 changed files with 215 additions and 21 deletions
|
@ -2,9 +2,12 @@
|
|||
import { GlModal } from '@gitlab/ui';
|
||||
import { sprintf, s__ } from '~/locale';
|
||||
import trackUninstallButtonClickMixin from 'ee_else_ce/clusters/mixins/track_uninstall_button_click';
|
||||
import { INGRESS, CERT_MANAGER, PROMETHEUS, RUNNER, KNATIVE, JUPYTER } from '../constants';
|
||||
import { HELM, INGRESS, CERT_MANAGER, PROMETHEUS, RUNNER, KNATIVE, JUPYTER } from '../constants';
|
||||
|
||||
const CUSTOM_APP_WARNING_TEXT = {
|
||||
[HELM]: s__(
|
||||
'ClusterIntegration|The associated Tiller pod will be deleted and cannot be restored.',
|
||||
),
|
||||
[INGRESS]: s__(
|
||||
'ClusterIntegration|The associated load balancer and IP will be deleted and cannot be restored.',
|
||||
),
|
||||
|
|
|
@ -14,6 +14,7 @@ module Clusters
|
|||
|
||||
include ::Clusters::Concerns::ApplicationCore
|
||||
include ::Clusters::Concerns::ApplicationStatus
|
||||
include ::Gitlab::Utils::StrongMemoize
|
||||
|
||||
default_value_for :version, Gitlab::Kubernetes::Helm::HELM_VERSION
|
||||
|
||||
|
@ -29,11 +30,22 @@ module Clusters
|
|||
self.status = 'installable' if cluster&.platform_kubernetes_active?
|
||||
end
|
||||
|
||||
# We will implement this in future MRs.
|
||||
# Basically we need to check all other applications are not installed
|
||||
# first.
|
||||
# It can only be uninstalled if there are no other applications installed
|
||||
# or with intermitent installation statuses in the database.
|
||||
def allowed_to_uninstall?
|
||||
false
|
||||
strong_memoize(:allowed_to_uninstall) do
|
||||
applications = nil
|
||||
|
||||
Clusters::Cluster::APPLICATIONS.each do |application_name, klass|
|
||||
next if application_name == 'helm'
|
||||
|
||||
extra_apps = Clusters::Applications::Helm.where('EXISTS (?)', klass.select(1).where(cluster_id: cluster_id))
|
||||
|
||||
applications = applications.present? ? applications.or(extra_apps) : extra_apps
|
||||
end
|
||||
|
||||
!applications.exists?
|
||||
end
|
||||
end
|
||||
|
||||
def install_command
|
||||
|
@ -44,6 +56,14 @@ module Clusters
|
|||
)
|
||||
end
|
||||
|
||||
def uninstall_command
|
||||
Gitlab::Kubernetes::Helm::ResetCommand.new(
|
||||
name: name,
|
||||
files: files,
|
||||
rbac: cluster.platform_kubernetes_rbac?
|
||||
)
|
||||
end
|
||||
|
||||
def has_ssl?
|
||||
ca_key.present? && ca_cert.present?
|
||||
end
|
||||
|
|
5
changelogs/unreleased/60516-uninstall-tiller.yml
Normal file
5
changelogs/unreleased/60516-uninstall-tiller.yml
Normal file
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
title: Allow Helm to be uninstalled from the UI
|
||||
merge_request: 27359
|
||||
author:
|
||||
type: added
|
|
@ -253,6 +253,7 @@ The applications below can be uninstalled.
|
|||
| Application | GitLab version | Notes |
|
||||
| ----------- | -------------- | ----- |
|
||||
| GitLab Runner | 12.2+ | Any running pipelines will be canceled. |
|
||||
| Helm | 12.2+ | The associated Tiller pod will be deleted and cannot be restored. |
|
||||
| Ingress | 12.1+ | The associated load balancer and IP will be deleted and cannot be restored. Furthermore, it can only be uninstalled if JupyterHub is not installed. |
|
||||
| JupyterHub | 12.1+ | All data not committed to GitLab will be deleted and cannot be restored. |
|
||||
| Knative | 12.1+ | The associated IP will be deleted and cannot be restored. |
|
||||
|
|
|
@ -43,17 +43,6 @@ module Gitlab
|
|||
|
||||
command.shelljoin
|
||||
end
|
||||
|
||||
def optional_tls_flags
|
||||
return [] unless files.key?(:'ca.pem')
|
||||
|
||||
[
|
||||
'--tls',
|
||||
'--tls-ca-cert', "#{files_dir}/ca.pem",
|
||||
'--tls-cert', "#{files_dir}/cert.pem",
|
||||
'--tls-key', "#{files_dir}/key.pem"
|
||||
]
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
54
lib/gitlab/kubernetes/helm/reset_command.rb
Normal file
54
lib/gitlab/kubernetes/helm/reset_command.rb
Normal file
|
@ -0,0 +1,54 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module Gitlab
|
||||
module Kubernetes
|
||||
module Helm
|
||||
class ResetCommand
|
||||
include BaseCommand
|
||||
include ClientCommand
|
||||
|
||||
attr_reader :name, :files
|
||||
|
||||
def initialize(name:, rbac:, files:)
|
||||
@name = name
|
||||
@files = files
|
||||
@rbac = rbac
|
||||
end
|
||||
|
||||
def generate_script
|
||||
super + [
|
||||
reset_helm_command,
|
||||
delete_tiller_replicaset
|
||||
].join("\n")
|
||||
end
|
||||
|
||||
def rbac?
|
||||
@rbac
|
||||
end
|
||||
|
||||
def pod_name
|
||||
"uninstall-#{name}"
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
# This method can be delete once we upgrade Helm to > 12.13.0
|
||||
# https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/27096#note_159695900
|
||||
#
|
||||
# Tracking this method to be removed here:
|
||||
# https://gitlab.com/gitlab-org/gitlab-ce/issues/52791#note_199374155
|
||||
def delete_tiller_replicaset
|
||||
command = %w[kubectl delete replicaset -n gitlab-managed-apps -l name=tiller]
|
||||
|
||||
command.shelljoin
|
||||
end
|
||||
|
||||
def reset_helm_command
|
||||
command = %w[helm reset] + optional_tls_flags
|
||||
|
||||
command.shelljoin
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -2818,6 +2818,9 @@ msgstr ""
|
|||
msgid "ClusterIntegration|The associated IP and all deployed services will be deleted and cannot be restored. Uninstalling Knative will also remove Istio from your cluster. This will not effect any other applications."
|
||||
msgstr ""
|
||||
|
||||
msgid "ClusterIntegration|The associated Tiller pod will be deleted and cannot be restored."
|
||||
msgstr ""
|
||||
|
||||
msgid "ClusterIntegration|The associated certifcate will be deleted and cannot be restored."
|
||||
msgstr ""
|
||||
|
||||
|
|
|
@ -63,7 +63,8 @@ describe 'Clusters Applications', :js do
|
|||
|
||||
Clusters::Cluster.last.application_helm.make_installed!
|
||||
|
||||
expect(page).to have_css('.js-cluster-application-install-button[disabled]', exact_text: 'Installed')
|
||||
expect(page).not_to have_css('.js-cluster-application-install-button')
|
||||
expect(page).to have_css('.js-cluster-application-uninstall-button:not([disabled])', exact_text: 'Uninstall')
|
||||
end
|
||||
|
||||
expect(page).to have_content('Helm Tiller was successfully installed on your Kubernetes cluster')
|
||||
|
|
65
spec/lib/gitlab/kubernetes/helm/reset_command_spec.rb
Normal file
65
spec/lib/gitlab/kubernetes/helm/reset_command_spec.rb
Normal file
|
@ -0,0 +1,65 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'spec_helper'
|
||||
|
||||
describe Gitlab::Kubernetes::Helm::ResetCommand do
|
||||
let(:rbac) { true }
|
||||
let(:name) { 'helm' }
|
||||
let(:files) { {} }
|
||||
let(:reset_command) { described_class.new(name: name, rbac: rbac, files: files) }
|
||||
|
||||
subject { reset_command }
|
||||
|
||||
it_behaves_like 'helm commands' do
|
||||
let(:commands) do
|
||||
<<~EOS
|
||||
helm reset
|
||||
kubectl delete replicaset -n gitlab-managed-apps -l name\\=tiller
|
||||
EOS
|
||||
end
|
||||
end
|
||||
|
||||
context 'when there is a ca.pem file' do
|
||||
let(:files) { { 'ca.pem': 'some file content' } }
|
||||
|
||||
it_behaves_like 'helm commands' do
|
||||
let(:commands) do
|
||||
<<~EOS1.squish + "\n" + <<~EOS2
|
||||
helm reset
|
||||
--tls
|
||||
--tls-ca-cert /data/helm/helm/config/ca.pem
|
||||
--tls-cert /data/helm/helm/config/cert.pem
|
||||
--tls-key /data/helm/helm/config/key.pem
|
||||
EOS1
|
||||
kubectl delete replicaset -n gitlab-managed-apps -l name\\=tiller
|
||||
EOS2
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '#pod_resource' do
|
||||
subject { reset_command.pod_resource }
|
||||
|
||||
context 'rbac is enabled' do
|
||||
let(:rbac) { true }
|
||||
|
||||
it 'generates a pod that uses the tiller serviceAccountName' do
|
||||
expect(subject.spec.serviceAccountName).to eq('tiller')
|
||||
end
|
||||
end
|
||||
|
||||
context 'rbac is not enabled' do
|
||||
let(:rbac) { false }
|
||||
|
||||
it 'generates a pod that uses the default serviceAccountName' do
|
||||
expect(subject.spec.serviceAcccountName).to be_nil
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '#pod_name' do
|
||||
subject { reset_command.pod_name }
|
||||
|
||||
it { is_expected.to eq('uninstall-helm') }
|
||||
end
|
||||
end
|
|
@ -19,11 +19,27 @@ describe Clusters::Applications::Helm do
|
|||
end
|
||||
|
||||
describe '#can_uninstall?' do
|
||||
let(:helm) { create(:clusters_applications_helm) }
|
||||
context "with other existing applications" do
|
||||
Clusters::Cluster::APPLICATIONS.keys.each do |application_name|
|
||||
next if application_name == 'helm'
|
||||
|
||||
subject { helm.can_uninstall? }
|
||||
it do
|
||||
cluster_application = create("clusters_applications_#{application_name}".to_sym)
|
||||
|
||||
it { is_expected.to be_falsey }
|
||||
helm = cluster_application.cluster.application_helm
|
||||
|
||||
expect(helm.allowed_to_uninstall?).to be_falsy
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context "without other existing applications" do
|
||||
subject { helm.can_uninstall? }
|
||||
|
||||
let(:helm) { create(:clusters_applications_helm) }
|
||||
|
||||
it { is_expected.to be_truthy }
|
||||
end
|
||||
end
|
||||
|
||||
describe '#issue_client_cert' do
|
||||
|
@ -73,4 +89,41 @@ describe Clusters::Applications::Helm do
|
|||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '#uninstall_command' do
|
||||
let(:helm) { create(:clusters_applications_helm) }
|
||||
|
||||
subject { helm.uninstall_command }
|
||||
|
||||
it { is_expected.to be_an_instance_of(Gitlab::Kubernetes::Helm::ResetCommand) }
|
||||
|
||||
it 'has name' do
|
||||
expect(subject.name).to eq('helm')
|
||||
end
|
||||
|
||||
it 'has cert files' do
|
||||
expect(subject.files[:'ca.pem']).to be_present
|
||||
expect(subject.files[:'ca.pem']).to eq(helm.ca_cert)
|
||||
|
||||
expect(subject.files[:'cert.pem']).to be_present
|
||||
expect(subject.files[:'key.pem']).to be_present
|
||||
|
||||
cert = OpenSSL::X509::Certificate.new(subject.files[:'cert.pem'])
|
||||
expect(cert.not_after).to be > 999.years.from_now
|
||||
end
|
||||
|
||||
describe 'rbac' do
|
||||
context 'rbac cluster' do
|
||||
it { expect(subject).to be_rbac }
|
||||
end
|
||||
|
||||
context 'non rbac cluster' do
|
||||
before do
|
||||
helm.cluster.platform_kubernetes.abac!
|
||||
end
|
||||
|
||||
it { expect(subject).not_to be_rbac }
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -22,7 +22,7 @@ describe ClusterApplicationEntity do
|
|||
end
|
||||
|
||||
it 'has can_uninstall' do
|
||||
expect(subject[:can_uninstall]).to be_falsey
|
||||
expect(subject[:can_uninstall]).to be_truthy
|
||||
end
|
||||
|
||||
context 'non-helm application' do
|
||||
|
|
Loading…
Reference in a new issue