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:
James Fargher 2019-06-21 08:54:43 +01:00
parent 507dfc66b4
commit 398c0e48f7
5 changed files with 2 additions and 372 deletions

View file

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

View file

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

View file

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

View file

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

View file

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