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:
|
||||
Exclude:
|
||||
- 'app/models/ci/pipeline.rb'
|
||||
- 'app/models/clusters/platforms/kubernetes.rb'
|
||||
- 'app/models/concerns/mentionable.rb'
|
||||
- 'app/models/project_services/hipchat_service.rb'
|
||||
- 'app/models/project_services/irker_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/wiki_page.rb'
|
||||
- 'lib/gitlab/github_import/importer/releases_importer.rb'
|
||||
|
@ -514,7 +512,6 @@ Security/YAMLLoad:
|
|||
- 'spec/config/mail_room_spec.rb'
|
||||
- 'spec/initializers/secret_token_spec.rb'
|
||||
- 'spec/lib/gitlab/prometheus/additional_metrics_parser_spec.rb'
|
||||
- 'spec/models/project_services/kubernetes_service_spec.rb'
|
||||
|
||||
# Offense count: 34
|
||||
# Configuration parameters: EnforcedStyle.
|
||||
|
|
|
@ -1,18 +1,8 @@
|
|||
# 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
|
||||
include Gitlab::Kubernetes
|
||||
include ReactiveCaching
|
||||
|
||||
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
|
||||
# is an invalid or inappropriate name
|
||||
prop_accessor :namespace
|
||||
|
@ -47,8 +37,6 @@ class KubernetesService < Service
|
|||
message: Gitlab::Regex.kubernetes_namespace_regex_message
|
||||
}
|
||||
|
||||
after_save :clear_reactive_cache!
|
||||
|
||||
def self.supported_events
|
||||
%w()
|
||||
end
|
||||
|
@ -94,72 +82,6 @@ class KubernetesService < Service
|
|||
]
|
||||
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?
|
||||
true
|
||||
end
|
||||
|
@ -186,14 +108,6 @@ class KubernetesService < Service
|
|||
|
||||
private
|
||||
|
||||
def kubeconfig
|
||||
to_kubeconfig(
|
||||
url: api_url,
|
||||
namespace: kubernetes_namespace_for(project),
|
||||
token: token,
|
||||
ca_pem: ca_pem)
|
||||
end
|
||||
|
||||
def namespace_placeholder
|
||||
default_namespace || TEMPLATE_PLACEHOLDER
|
||||
end
|
||||
|
@ -205,49 +119,6 @@ class KubernetesService < Service
|
|||
slug.gsub(/[^-a-z0-9]/, '-').gsub(/^-+/, '')
|
||||
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
|
||||
self.namespace = self.namespace&.downcase
|
||||
end
|
||||
|
|
|
@ -27,12 +27,9 @@ module Prometheus
|
|||
end
|
||||
|
||||
def cluster_prometheus_adapter
|
||||
return unless deployment_platform.respond_to?(:cluster)
|
||||
application = deployment_platform&.cluster&.application_prometheus
|
||||
|
||||
cluster = deployment_platform.cluster
|
||||
return unless cluster.application_prometheus&.available?
|
||||
|
||||
cluster.application_prometheus
|
||||
application if application&.available?
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -462,12 +462,6 @@ describe Deployment do
|
|||
it { is_expected.to be_nil }
|
||||
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
|
||||
let!(:cluster) { create(:cluster, projects: [project]) }
|
||||
let!(:platform) { create(:cluster_platform_kubernetes, cluster: cluster) }
|
||||
|
|
|
@ -142,235 +142,6 @@ describe KubernetesService, :use_clean_rails_memory_store_caching do
|
|||
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
|
||||
let(:kubernetes_service) { create(:kubernetes_service) }
|
||||
|
||||
|
|
Loading…
Reference in a new issue