Remove now unused KubernetesService methods
Now that KubernetesService can no longer be a DeploymentPlatform we can remove all kubernetes client code and KubernetesService edge cases.
This commit is contained in:
parent
507dfc66b4
commit
398c0e48f7
5 changed files with 2 additions and 372 deletions
|
@ -466,12 +466,10 @@ Rails/LinkToBlank:
|
||||||
Rails/Presence:
|
Rails/Presence:
|
||||||
Exclude:
|
Exclude:
|
||||||
- 'app/models/ci/pipeline.rb'
|
- 'app/models/ci/pipeline.rb'
|
||||||
- 'app/models/clusters/platforms/kubernetes.rb'
|
|
||||||
- 'app/models/concerns/mentionable.rb'
|
- 'app/models/concerns/mentionable.rb'
|
||||||
- 'app/models/project_services/hipchat_service.rb'
|
- 'app/models/project_services/hipchat_service.rb'
|
||||||
- 'app/models/project_services/irker_service.rb'
|
- 'app/models/project_services/irker_service.rb'
|
||||||
- 'app/models/project_services/jira_service.rb'
|
- 'app/models/project_services/jira_service.rb'
|
||||||
- 'app/models/project_services/kubernetes_service.rb'
|
|
||||||
- 'app/models/project_services/packagist_service.rb'
|
- 'app/models/project_services/packagist_service.rb'
|
||||||
- 'app/models/wiki_page.rb'
|
- 'app/models/wiki_page.rb'
|
||||||
- 'lib/gitlab/github_import/importer/releases_importer.rb'
|
- 'lib/gitlab/github_import/importer/releases_importer.rb'
|
||||||
|
@ -514,7 +512,6 @@ Security/YAMLLoad:
|
||||||
- 'spec/config/mail_room_spec.rb'
|
- 'spec/config/mail_room_spec.rb'
|
||||||
- 'spec/initializers/secret_token_spec.rb'
|
- 'spec/initializers/secret_token_spec.rb'
|
||||||
- 'spec/lib/gitlab/prometheus/additional_metrics_parser_spec.rb'
|
- 'spec/lib/gitlab/prometheus/additional_metrics_parser_spec.rb'
|
||||||
- 'spec/models/project_services/kubernetes_service_spec.rb'
|
|
||||||
|
|
||||||
# Offense count: 34
|
# Offense count: 34
|
||||||
# Configuration parameters: EnforcedStyle.
|
# Configuration parameters: EnforcedStyle.
|
||||||
|
|
|
@ -1,18 +1,8 @@
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
##
|
|
||||||
# NOTE:
|
|
||||||
# We'll move this class to Clusters::Platforms::Kubernetes, which contains exactly the same logic.
|
|
||||||
# After we've migrated data, we'll remove KubernetesService. This would happen in a few months.
|
|
||||||
# If you're modyfiyng this class, please note that you should update the same change in Clusters::Platforms::Kubernetes.
|
|
||||||
class KubernetesService < Service
|
class KubernetesService < Service
|
||||||
include Gitlab::Kubernetes
|
|
||||||
include ReactiveCaching
|
|
||||||
|
|
||||||
default_value_for :category, 'deployment'
|
default_value_for :category, 'deployment'
|
||||||
|
|
||||||
self.reactive_cache_key = ->(service) { [service.class.model_name.singular, service.project_id] }
|
|
||||||
|
|
||||||
# Namespace defaults to the project path, but can be overridden in case that
|
# Namespace defaults to the project path, but can be overridden in case that
|
||||||
# is an invalid or inappropriate name
|
# is an invalid or inappropriate name
|
||||||
prop_accessor :namespace
|
prop_accessor :namespace
|
||||||
|
@ -47,8 +37,6 @@ class KubernetesService < Service
|
||||||
message: Gitlab::Regex.kubernetes_namespace_regex_message
|
message: Gitlab::Regex.kubernetes_namespace_regex_message
|
||||||
}
|
}
|
||||||
|
|
||||||
after_save :clear_reactive_cache!
|
|
||||||
|
|
||||||
def self.supported_events
|
def self.supported_events
|
||||||
%w()
|
%w()
|
||||||
end
|
end
|
||||||
|
@ -94,72 +82,6 @@ class KubernetesService < Service
|
||||||
]
|
]
|
||||||
end
|
end
|
||||||
|
|
||||||
def kubernetes_namespace_for(project)
|
|
||||||
if namespace.present?
|
|
||||||
namespace
|
|
||||||
else
|
|
||||||
default_namespace
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
# Check we can connect to the Kubernetes API
|
|
||||||
def test(*args)
|
|
||||||
kubeclient = build_kube_client!
|
|
||||||
|
|
||||||
kubeclient.core_client.discover
|
|
||||||
{ success: kubeclient.core_client.discovered, result: "Checked API discovery endpoint" }
|
|
||||||
rescue => err
|
|
||||||
{ success: false, result: err }
|
|
||||||
end
|
|
||||||
|
|
||||||
# Project param was added on
|
|
||||||
# https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/22011,
|
|
||||||
# as a way to keep this service compatible with
|
|
||||||
# Clusters::Platforms::Kubernetes, it won't be used on this method
|
|
||||||
# as it's only needed for Clusters::Cluster.
|
|
||||||
def predefined_variables(project:)
|
|
||||||
Gitlab::Ci::Variables::Collection.new.tap do |variables|
|
|
||||||
variables
|
|
||||||
.append(key: 'KUBE_URL', value: api_url)
|
|
||||||
.append(key: 'KUBE_TOKEN', value: token, public: false, masked: true)
|
|
||||||
.append(key: 'KUBE_NAMESPACE', value: kubernetes_namespace_for(project))
|
|
||||||
.append(key: 'KUBECONFIG', value: kubeconfig, public: false, file: true)
|
|
||||||
|
|
||||||
if ca_pem.present?
|
|
||||||
variables
|
|
||||||
.append(key: 'KUBE_CA_PEM', value: ca_pem)
|
|
||||||
.append(key: 'KUBE_CA_PEM_FILE', value: ca_pem, file: true)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
# Constructs a list of terminals from the reactive cache
|
|
||||||
#
|
|
||||||
# Returns nil if the cache is empty, in which case you should try again a
|
|
||||||
# short time later
|
|
||||||
def terminals(environment)
|
|
||||||
with_reactive_cache do |data|
|
|
||||||
project = environment.project
|
|
||||||
|
|
||||||
pods = filter_by_project_environment(data[:pods], project.full_path_slug, environment.slug)
|
|
||||||
terminals = pods.flat_map { |pod| terminals_for_pod(api_url, kubernetes_namespace_for(project), pod) }.compact
|
|
||||||
terminals.each { |terminal| add_terminal_auth(terminal, terminal_auth) }
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
# Caches resources in the namespace so other calls don't need to block on
|
|
||||||
# network access
|
|
||||||
def calculate_reactive_cache
|
|
||||||
return unless active? && project && !project.pending_delete?
|
|
||||||
|
|
||||||
# We may want to cache extra things in the future
|
|
||||||
{ pods: read_pods }
|
|
||||||
end
|
|
||||||
|
|
||||||
def kubeclient
|
|
||||||
@kubeclient ||= build_kube_client!
|
|
||||||
end
|
|
||||||
|
|
||||||
def deprecated?
|
def deprecated?
|
||||||
true
|
true
|
||||||
end
|
end
|
||||||
|
@ -186,14 +108,6 @@ class KubernetesService < Service
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def kubeconfig
|
|
||||||
to_kubeconfig(
|
|
||||||
url: api_url,
|
|
||||||
namespace: kubernetes_namespace_for(project),
|
|
||||||
token: token,
|
|
||||||
ca_pem: ca_pem)
|
|
||||||
end
|
|
||||||
|
|
||||||
def namespace_placeholder
|
def namespace_placeholder
|
||||||
default_namespace || TEMPLATE_PLACEHOLDER
|
default_namespace || TEMPLATE_PLACEHOLDER
|
||||||
end
|
end
|
||||||
|
@ -205,49 +119,6 @@ class KubernetesService < Service
|
||||||
slug.gsub(/[^-a-z0-9]/, '-').gsub(/^-+/, '')
|
slug.gsub(/[^-a-z0-9]/, '-').gsub(/^-+/, '')
|
||||||
end
|
end
|
||||||
|
|
||||||
def build_kube_client!
|
|
||||||
raise "Incomplete settings" unless api_url && kubernetes_namespace_for(project) && token
|
|
||||||
|
|
||||||
Gitlab::Kubernetes::KubeClient.new(
|
|
||||||
api_url,
|
|
||||||
auth_options: kubeclient_auth_options,
|
|
||||||
ssl_options: kubeclient_ssl_options,
|
|
||||||
http_proxy_uri: ENV['http_proxy']
|
|
||||||
)
|
|
||||||
end
|
|
||||||
|
|
||||||
# Returns a hash of all pods in the namespace
|
|
||||||
def read_pods
|
|
||||||
kubeclient = build_kube_client!
|
|
||||||
|
|
||||||
kubeclient.get_pods(namespace: kubernetes_namespace_for(project)).as_json
|
|
||||||
rescue Kubeclient::ResourceNotFoundError
|
|
||||||
[]
|
|
||||||
end
|
|
||||||
|
|
||||||
def kubeclient_ssl_options
|
|
||||||
opts = { verify_ssl: OpenSSL::SSL::VERIFY_PEER }
|
|
||||||
|
|
||||||
if ca_pem.present?
|
|
||||||
opts[:cert_store] = OpenSSL::X509::Store.new
|
|
||||||
opts[:cert_store].add_cert(OpenSSL::X509::Certificate.new(ca_pem))
|
|
||||||
end
|
|
||||||
|
|
||||||
opts
|
|
||||||
end
|
|
||||||
|
|
||||||
def kubeclient_auth_options
|
|
||||||
{ bearer_token: token }
|
|
||||||
end
|
|
||||||
|
|
||||||
def terminal_auth
|
|
||||||
{
|
|
||||||
token: token,
|
|
||||||
ca_pem: ca_pem,
|
|
||||||
max_session_time: Gitlab::CurrentSettings.terminal_max_session_time
|
|
||||||
}
|
|
||||||
end
|
|
||||||
|
|
||||||
def enforce_namespace_to_lower_case
|
def enforce_namespace_to_lower_case
|
||||||
self.namespace = self.namespace&.downcase
|
self.namespace = self.namespace&.downcase
|
||||||
end
|
end
|
||||||
|
|
|
@ -27,12 +27,9 @@ module Prometheus
|
||||||
end
|
end
|
||||||
|
|
||||||
def cluster_prometheus_adapter
|
def cluster_prometheus_adapter
|
||||||
return unless deployment_platform.respond_to?(:cluster)
|
application = deployment_platform&.cluster&.application_prometheus
|
||||||
|
|
||||||
cluster = deployment_platform.cluster
|
application if application&.available?
|
||||||
return unless cluster.application_prometheus&.available?
|
|
||||||
|
|
||||||
cluster.application_prometheus
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -462,12 +462,6 @@ describe Deployment do
|
||||||
it { is_expected.to be_nil }
|
it { is_expected.to be_nil }
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'project uses the kubernetes service for deployments' do
|
|
||||||
let!(:service) { create(:kubernetes_service, project: project) }
|
|
||||||
|
|
||||||
it { is_expected.to be_nil }
|
|
||||||
end
|
|
||||||
|
|
||||||
context 'project has a deployment platform' do
|
context 'project has a deployment platform' do
|
||||||
let!(:cluster) { create(:cluster, projects: [project]) }
|
let!(:cluster) { create(:cluster, projects: [project]) }
|
||||||
let!(:platform) { create(:cluster_platform_kubernetes, cluster: cluster) }
|
let!(:platform) { create(:cluster_platform_kubernetes, cluster: cluster) }
|
||||||
|
|
|
@ -142,235 +142,6 @@ describe KubernetesService, :use_clean_rails_memory_store_caching do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe '#kubernetes_namespace_for' do
|
|
||||||
subject { service.kubernetes_namespace_for(project) }
|
|
||||||
|
|
||||||
shared_examples 'a correctly formatted namespace' do
|
|
||||||
it 'returns a valid Kubernetes namespace name' do
|
|
||||||
expect(subject).to match(Gitlab::Regex.kubernetes_namespace_regex)
|
|
||||||
expect(subject).to eq(expected_namespace)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
it_behaves_like 'a correctly formatted namespace' do
|
|
||||||
let(:expected_namespace) { service.send(:default_namespace) }
|
|
||||||
end
|
|
||||||
|
|
||||||
context 'when the project path contains forbidden characters' do
|
|
||||||
before do
|
|
||||||
project.path = '-a_Strange.Path--forSure'
|
|
||||||
end
|
|
||||||
|
|
||||||
it_behaves_like 'a correctly formatted namespace' do
|
|
||||||
let(:expected_namespace) { "a-strange-path--forsure-#{project.id}" }
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
context 'when namespace is specified' do
|
|
||||||
before do
|
|
||||||
service.namespace = 'my-namespace'
|
|
||||||
end
|
|
||||||
|
|
||||||
it_behaves_like 'a correctly formatted namespace' do
|
|
||||||
let(:expected_namespace) { 'my-namespace' }
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
context 'when service is not assigned to project' do
|
|
||||||
before do
|
|
||||||
service.project = nil
|
|
||||||
end
|
|
||||||
|
|
||||||
it 'does not return namespace' do
|
|
||||||
is_expected.to be_nil
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
describe '#test' do
|
|
||||||
let(:discovery_url) { 'https://kubernetes.example.com/api/v1' }
|
|
||||||
|
|
||||||
before do
|
|
||||||
stub_kubeclient_discover(service.api_url)
|
|
||||||
end
|
|
||||||
|
|
||||||
context 'with path prefix in api_url' do
|
|
||||||
let(:discovery_url) { 'https://kubernetes.example.com/prefix/api/v1' }
|
|
||||||
|
|
||||||
it 'tests with the prefix' do
|
|
||||||
service.api_url = 'https://kubernetes.example.com/prefix'
|
|
||||||
stub_kubeclient_discover(service.api_url)
|
|
||||||
|
|
||||||
expect(service.test[:success]).to be_truthy
|
|
||||||
expect(WebMock).to have_requested(:get, discovery_url).once
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
context 'with custom CA certificate' do
|
|
||||||
it 'is added to the certificate store' do
|
|
||||||
service.ca_pem = "CA PEM DATA"
|
|
||||||
|
|
||||||
cert = double("certificate")
|
|
||||||
expect(OpenSSL::X509::Certificate).to receive(:new).with(service.ca_pem).and_return(cert)
|
|
||||||
expect_any_instance_of(OpenSSL::X509::Store).to receive(:add_cert).with(cert)
|
|
||||||
|
|
||||||
expect(service.test[:success]).to be_truthy
|
|
||||||
expect(WebMock).to have_requested(:get, discovery_url).once
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
context 'success' do
|
|
||||||
it 'reads the discovery endpoint' do
|
|
||||||
expect(service.test[:success]).to be_truthy
|
|
||||||
expect(WebMock).to have_requested(:get, discovery_url).once
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
context 'failure' do
|
|
||||||
it 'fails to read the discovery endpoint' do
|
|
||||||
WebMock.stub_request(:get, service.api_url + '/api/v1').to_return(status: 404)
|
|
||||||
|
|
||||||
expect(service.test[:success]).to be_falsy
|
|
||||||
expect(WebMock).to have_requested(:get, discovery_url).once
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
describe '#predefined_variable' do
|
|
||||||
let(:kubeconfig) do
|
|
||||||
config_file = expand_fixture_path('config/kubeconfig.yml')
|
|
||||||
config = YAML.load(File.read(config_file))
|
|
||||||
config.dig('users', 0, 'user')['token'] = 'token'
|
|
||||||
config.dig('contexts', 0, 'context')['namespace'] = namespace
|
|
||||||
config.dig('clusters', 0, 'cluster')['certificate-authority-data'] =
|
|
||||||
Base64.strict_encode64('CA PEM DATA')
|
|
||||||
|
|
||||||
YAML.dump(config)
|
|
||||||
end
|
|
||||||
|
|
||||||
before do
|
|
||||||
subject.api_url = 'https://kube.domain.com'
|
|
||||||
subject.token = 'token'
|
|
||||||
subject.ca_pem = 'CA PEM DATA'
|
|
||||||
subject.project = project
|
|
||||||
end
|
|
||||||
|
|
||||||
shared_examples 'setting variables' do
|
|
||||||
it 'sets the variables' do
|
|
||||||
expect(subject.predefined_variables(project: project)).to include(
|
|
||||||
{ key: 'KUBE_URL', value: 'https://kube.domain.com', public: true },
|
|
||||||
{ key: 'KUBE_TOKEN', value: 'token', public: false, masked: true },
|
|
||||||
{ key: 'KUBE_NAMESPACE', value: namespace, public: true },
|
|
||||||
{ key: 'KUBECONFIG', value: kubeconfig, public: false, file: true },
|
|
||||||
{ key: 'KUBE_CA_PEM', value: 'CA PEM DATA', public: true },
|
|
||||||
{ key: 'KUBE_CA_PEM_FILE', value: 'CA PEM DATA', public: true, file: true }
|
|
||||||
)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
context 'namespace is provided' do
|
|
||||||
let(:namespace) { 'my-project' }
|
|
||||||
|
|
||||||
before do
|
|
||||||
subject.namespace = namespace
|
|
||||||
end
|
|
||||||
|
|
||||||
it_behaves_like 'setting variables'
|
|
||||||
end
|
|
||||||
|
|
||||||
context 'no namespace provided' do
|
|
||||||
let(:namespace) { subject.kubernetes_namespace_for(project) }
|
|
||||||
|
|
||||||
it_behaves_like 'setting variables'
|
|
||||||
|
|
||||||
it 'sets the KUBE_NAMESPACE' do
|
|
||||||
kube_namespace = subject.predefined_variables(project: project).find { |h| h[:key] == 'KUBE_NAMESPACE' }
|
|
||||||
|
|
||||||
expect(kube_namespace).not_to be_nil
|
|
||||||
expect(kube_namespace[:value]).to match(/\A#{Gitlab::PathRegex::PATH_REGEX_STR}-\d+\z/)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
describe '#terminals' do
|
|
||||||
let(:environment) { build(:environment, project: project, name: "env", slug: "env-000000") }
|
|
||||||
|
|
||||||
subject { service.terminals(environment) }
|
|
||||||
|
|
||||||
context 'with invalid pods' do
|
|
||||||
it 'returns no terminals' do
|
|
||||||
stub_reactive_cache(service, pods: [{ "bad" => "pod" }])
|
|
||||||
|
|
||||||
is_expected.to be_empty
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
context 'with valid pods' do
|
|
||||||
let(:pod) { kube_pod(environment_slug: environment.slug, namespace: service.kubernetes_namespace_for(project), project_slug: project.full_path_slug) }
|
|
||||||
let(:pod_with_no_terminal) { kube_pod(environment_slug: environment.slug, project_slug: project.full_path_slug, status: "Pending") }
|
|
||||||
let(:terminals) { kube_terminals(service, pod) }
|
|
||||||
|
|
||||||
before do
|
|
||||||
stub_reactive_cache(
|
|
||||||
service,
|
|
||||||
pods: [pod, pod, pod_with_no_terminal, kube_pod(environment_slug: "should-be-filtered-out")]
|
|
||||||
)
|
|
||||||
end
|
|
||||||
|
|
||||||
it 'returns terminals' do
|
|
||||||
is_expected.to eq(terminals + terminals)
|
|
||||||
end
|
|
||||||
|
|
||||||
it 'uses max session time from settings' do
|
|
||||||
stub_application_setting(terminal_max_session_time: 600)
|
|
||||||
|
|
||||||
times = subject.map { |terminal| terminal[:max_session_time] }
|
|
||||||
expect(times).to eq [600, 600, 600, 600]
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
describe '#calculate_reactive_cache' do
|
|
||||||
subject { service.calculate_reactive_cache }
|
|
||||||
|
|
||||||
let(:namespace) { service.kubernetes_namespace_for(project) }
|
|
||||||
|
|
||||||
context 'when service is inactive' do
|
|
||||||
before do
|
|
||||||
service.active = false
|
|
||||||
end
|
|
||||||
|
|
||||||
it { is_expected.to be_nil }
|
|
||||||
end
|
|
||||||
|
|
||||||
context 'when kubernetes responds with valid pods' do
|
|
||||||
before do
|
|
||||||
stub_kubeclient_pods(namespace)
|
|
||||||
stub_kubeclient_deployments(namespace) # Used by EE
|
|
||||||
end
|
|
||||||
|
|
||||||
it { is_expected.to include(pods: [kube_pod]) }
|
|
||||||
end
|
|
||||||
|
|
||||||
context 'when kubernetes responds with 500s' do
|
|
||||||
before do
|
|
||||||
stub_kubeclient_pods(namespace, status: 500)
|
|
||||||
stub_kubeclient_deployments(namespace, status: 500) # Used by EE
|
|
||||||
end
|
|
||||||
|
|
||||||
it { expect { subject }.to raise_error(Kubeclient::HttpError) }
|
|
||||||
end
|
|
||||||
|
|
||||||
context 'when kubernetes responds with 404s' do
|
|
||||||
before do
|
|
||||||
stub_kubeclient_pods(namespace, status: 404)
|
|
||||||
stub_kubeclient_deployments(namespace, status: 404) # Used by EE
|
|
||||||
end
|
|
||||||
|
|
||||||
it { is_expected.to include(pods: []) }
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
describe "#deprecated?" do
|
describe "#deprecated?" do
|
||||||
let(:kubernetes_service) { create(:kubernetes_service) }
|
let(:kubernetes_service) { create(:kubernetes_service) }
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue