Merge branch '49952-port-upgrade-command-to-ce' into 'master'
Port UpgradeCommand to CE See merge request gitlab-org/gitlab-ce!21949
This commit is contained in:
commit
607f263c48
|
@ -15,6 +15,9 @@ module Clusters
|
|||
state :scheduled, value: 1
|
||||
state :installing, value: 2
|
||||
state :installed, value: 3
|
||||
state :updating, value: 4
|
||||
state :updated, value: 5
|
||||
state :update_errored, value: 6
|
||||
|
||||
event :make_scheduled do
|
||||
transition [:installable, :errored] => :scheduled
|
||||
|
@ -32,6 +35,18 @@ module Clusters
|
|||
transition any => :errored
|
||||
end
|
||||
|
||||
event :make_updating do
|
||||
transition [:installed, :updated, :update_errored] => :updating
|
||||
end
|
||||
|
||||
event :make_updated do
|
||||
transition [:updating] => :updated
|
||||
end
|
||||
|
||||
event :make_update_errored do
|
||||
transition any => :update_errored
|
||||
end
|
||||
|
||||
before_transition any => [:scheduled] do |app_status, _|
|
||||
app_status.status_reason = nil
|
||||
end
|
||||
|
@ -40,6 +55,15 @@ module Clusters
|
|||
status_reason = transition.args.first
|
||||
app_status.status_reason = status_reason if status_reason
|
||||
end
|
||||
|
||||
before_transition any => [:updating] do |app_status, _|
|
||||
app_status.status_reason = nil
|
||||
end
|
||||
|
||||
before_transition any => [:update_errored] do |app_status, transition|
|
||||
status_reason = transition.args.first
|
||||
app_status.status_reason = status_reason if status_reason
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -17,6 +17,12 @@ module Gitlab
|
|||
kubeclient.create_pod(command.pod_resource)
|
||||
end
|
||||
|
||||
def update(command)
|
||||
namespace.ensure_exists!
|
||||
update_config_map(command)
|
||||
kubeclient.create_pod(command.pod_resource)
|
||||
end
|
||||
|
||||
##
|
||||
# Returns Pod phase
|
||||
#
|
||||
|
@ -36,6 +42,12 @@ module Gitlab
|
|||
kubeclient.delete_pod(pod_name, namespace.name)
|
||||
end
|
||||
|
||||
def get_config_map(config_map_name)
|
||||
namespace.ensure_exists!
|
||||
|
||||
kubeclient.get_config_map(config_map_name, namespace.name)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
attr_reader :kubeclient, :namespace
|
||||
|
@ -46,6 +58,12 @@ module Gitlab
|
|||
end
|
||||
end
|
||||
|
||||
def update_config_map(command)
|
||||
command.config_map_resource.tap do |config_map_resource|
|
||||
kubeclient.update_config_map(config_map_resource)
|
||||
end
|
||||
end
|
||||
|
||||
def create_service_account(command)
|
||||
command.service_account_resource.tap do |service_account_resource|
|
||||
break unless service_account_resource
|
||||
|
|
|
@ -0,0 +1,71 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module Gitlab
|
||||
module Kubernetes
|
||||
module Helm
|
||||
class UpgradeCommand
|
||||
include BaseCommand
|
||||
|
||||
attr_reader :name, :chart, :version, :repository, :files
|
||||
|
||||
def initialize(name, chart:, files:, rbac:, version: nil, repository: nil)
|
||||
@name = name
|
||||
@chart = chart
|
||||
@rbac = rbac
|
||||
@version = version
|
||||
@files = files
|
||||
@repository = repository
|
||||
end
|
||||
|
||||
def generate_script
|
||||
super + [
|
||||
init_command,
|
||||
repository_command,
|
||||
script_command
|
||||
].compact.join("\n")
|
||||
end
|
||||
|
||||
def rbac?
|
||||
@rbac
|
||||
end
|
||||
|
||||
def pod_name
|
||||
"upgrade-#{name}"
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def init_command
|
||||
'helm init --client-only >/dev/null'
|
||||
end
|
||||
|
||||
def repository_command
|
||||
"helm repo add #{name} #{repository}" if repository
|
||||
end
|
||||
|
||||
def script_command
|
||||
upgrade_flags = "#{optional_version_flag}#{optional_tls_flags}" \
|
||||
" --reset-values" \
|
||||
" --install" \
|
||||
" --namespace #{::Gitlab::Kubernetes::Helm::NAMESPACE}" \
|
||||
" -f /data/helm/#{name}/config/values.yaml"
|
||||
|
||||
"helm upgrade #{name} #{chart}#{upgrade_flags} >/dev/null\n"
|
||||
end
|
||||
|
||||
def optional_version_flag
|
||||
" --version #{version}" if version
|
||||
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
|
||||
end
|
|
@ -22,11 +22,24 @@ FactoryBot.define do
|
|||
status 3
|
||||
end
|
||||
|
||||
trait :updating do
|
||||
status 4
|
||||
end
|
||||
|
||||
trait :updated do
|
||||
status 5
|
||||
end
|
||||
|
||||
trait :errored do
|
||||
status(-1)
|
||||
status_reason 'something went wrong'
|
||||
end
|
||||
|
||||
trait :update_errored do
|
||||
status(6)
|
||||
status_reason 'something went wrong'
|
||||
end
|
||||
|
||||
trait :timeouted do
|
||||
installing
|
||||
updated_at ClusterWaitForAppInstallationWorker::TIMEOUT.ago
|
||||
|
|
|
@ -150,6 +150,43 @@ describe Gitlab::Kubernetes::Helm::Api do
|
|||
end
|
||||
end
|
||||
|
||||
describe '#update' do
|
||||
let(:rbac) { false }
|
||||
|
||||
let(:command) do
|
||||
Gitlab::Kubernetes::Helm::UpgradeCommand.new(
|
||||
application_name,
|
||||
chart: 'chart-name',
|
||||
files: files,
|
||||
rbac: rbac
|
||||
)
|
||||
end
|
||||
|
||||
before do
|
||||
allow(namespace).to receive(:ensure_exists!).once
|
||||
|
||||
allow(client).to receive(:update_config_map).and_return(nil)
|
||||
allow(client).to receive(:create_pod).and_return(nil)
|
||||
end
|
||||
|
||||
it 'ensures the namespace exists before creating the pod' do
|
||||
expect(namespace).to receive(:ensure_exists!).once.ordered
|
||||
expect(client).to receive(:create_pod).once.ordered
|
||||
|
||||
subject.update(command)
|
||||
end
|
||||
|
||||
it 'updates the config map on kubeclient when one exists' do
|
||||
resource = Gitlab::Kubernetes::ConfigMap.new(
|
||||
application_name, files
|
||||
).generate
|
||||
|
||||
expect(client).to receive(:update_config_map).with(resource).once
|
||||
|
||||
subject.update(command)
|
||||
end
|
||||
end
|
||||
|
||||
describe '#status' do
|
||||
let(:phase) { Gitlab::Kubernetes::Pod::RUNNING }
|
||||
let(:pod) { Kubeclient::Resource.new(status: { phase: phase }) } # partial representation
|
||||
|
@ -179,4 +216,25 @@ describe Gitlab::Kubernetes::Helm::Api do
|
|||
subject.delete_pod!(command.pod_name)
|
||||
end
|
||||
end
|
||||
|
||||
describe '#get_config_map' do
|
||||
before do
|
||||
allow(namespace).to receive(:ensure_exists!).once
|
||||
allow(client).to receive(:get_config_map).and_return(nil)
|
||||
end
|
||||
|
||||
it 'ensures the namespace exists before retrieving the config map' do
|
||||
expect(namespace).to receive(:ensure_exists!).once
|
||||
|
||||
subject.get_config_map('example-config-map-name')
|
||||
end
|
||||
|
||||
it 'gets the config map on kubeclient' do
|
||||
expect(client).to receive(:get_config_map)
|
||||
.with('example-config-map-name', namespace.name)
|
||||
.once
|
||||
|
||||
subject.get_config_map('example-config-map-name')
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -0,0 +1,136 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'rails_helper'
|
||||
|
||||
describe Gitlab::Kubernetes::Helm::UpgradeCommand do
|
||||
let(:application) { build(:clusters_applications_prometheus) }
|
||||
let(:files) { { 'ca.pem': 'some file content' } }
|
||||
let(:namespace) { ::Gitlab::Kubernetes::Helm::NAMESPACE }
|
||||
let(:rbac) { false }
|
||||
let(:upgrade_command) do
|
||||
described_class.new(
|
||||
application.name,
|
||||
chart: application.chart,
|
||||
files: files,
|
||||
rbac: rbac
|
||||
)
|
||||
end
|
||||
|
||||
subject { upgrade_command }
|
||||
|
||||
it_behaves_like 'helm commands' do
|
||||
let(:commands) do
|
||||
<<~EOS
|
||||
helm init --client-only >/dev/null
|
||||
helm upgrade #{application.name} #{application.chart} --tls --tls-ca-cert /data/helm/#{application.name}/config/ca.pem --tls-cert /data/helm/#{application.name}/config/cert.pem --tls-key /data/helm/#{application.name}/config/key.pem --reset-values --install --namespace #{namespace} -f /data/helm/#{application.name}/config/values.yaml >/dev/null
|
||||
EOS
|
||||
end
|
||||
end
|
||||
|
||||
context 'rbac is true' do
|
||||
let(:rbac) { true }
|
||||
|
||||
it_behaves_like 'helm commands' do
|
||||
let(:commands) do
|
||||
<<~EOS
|
||||
helm init --client-only >/dev/null
|
||||
helm upgrade #{application.name} #{application.chart} --tls --tls-ca-cert /data/helm/#{application.name}/config/ca.pem --tls-cert /data/helm/#{application.name}/config/cert.pem --tls-key /data/helm/#{application.name}/config/key.pem --reset-values --install --namespace #{namespace} -f /data/helm/#{application.name}/config/values.yaml >/dev/null
|
||||
EOS
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'with an application with a repository' do
|
||||
let(:ci_runner) { create(:ci_runner) }
|
||||
let(:application) { build(:clusters_applications_runner, runner: ci_runner) }
|
||||
let(:upgrade_command) do
|
||||
described_class.new(
|
||||
application.name,
|
||||
chart: application.chart,
|
||||
files: files,
|
||||
rbac: rbac,
|
||||
repository: application.repository
|
||||
)
|
||||
end
|
||||
|
||||
it_behaves_like 'helm commands' do
|
||||
let(:commands) do
|
||||
<<~EOS
|
||||
helm init --client-only >/dev/null
|
||||
helm repo add #{application.name} #{application.repository}
|
||||
helm upgrade #{application.name} #{application.chart} --tls --tls-ca-cert /data/helm/#{application.name}/config/ca.pem --tls-cert /data/helm/#{application.name}/config/cert.pem --tls-key /data/helm/#{application.name}/config/key.pem --reset-values --install --namespace #{namespace} -f /data/helm/#{application.name}/config/values.yaml >/dev/null
|
||||
EOS
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'when there is no ca.pem file' do
|
||||
let(:files) { { 'file.txt': 'some content' } }
|
||||
|
||||
it_behaves_like 'helm commands' do
|
||||
let(:commands) do
|
||||
<<~EOS
|
||||
helm init --client-only >/dev/null
|
||||
helm upgrade #{application.name} #{application.chart} --reset-values --install --namespace #{namespace} -f /data/helm/#{application.name}/config/values.yaml >/dev/null
|
||||
EOS
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '#pod_resource' do
|
||||
subject { upgrade_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 '#config_map_resource' do
|
||||
let(:metadata) do
|
||||
{
|
||||
name: "values-content-configuration-#{application.name}",
|
||||
namespace: namespace,
|
||||
labels: { name: "values-content-configuration-#{application.name}" }
|
||||
}
|
||||
end
|
||||
let(:resource) { ::Kubeclient::Resource.new(metadata: metadata, data: files) }
|
||||
|
||||
it 'returns a KubeClient resource with config map content for the application' do
|
||||
expect(subject.config_map_resource).to eq(resource)
|
||||
end
|
||||
end
|
||||
|
||||
describe '#rbac?' do
|
||||
subject { upgrade_command.rbac? }
|
||||
|
||||
context 'rbac is enabled' do
|
||||
let(:rbac) { true }
|
||||
|
||||
it { is_expected.to be_truthy }
|
||||
end
|
||||
|
||||
context 'rbac is not enabled' do
|
||||
let(:rbac) { false }
|
||||
|
||||
it { is_expected.to be_falsey }
|
||||
end
|
||||
end
|
||||
|
||||
describe '#pod_name' do
|
||||
it 'returns the pod name' do
|
||||
expect(subject.pod_name).to eq("upgrade-#{application.name}")
|
||||
end
|
||||
end
|
||||
end
|
Loading…
Reference in New Issue