Commit 6eed9c5e authored by Magdalena Frankiewicz's avatar Magdalena Frankiewicz Committed by Kamil Trzciński

Check Knative installation on cluster

When no deployment has been done yet, there is no environment, so the
check for Knative needs to happen via Kubeclient
parent 3ee4aa9c
......@@ -4,9 +4,15 @@ module Projects
module Serverless
class FunctionsFinder
include Gitlab::Utils::StrongMemoize
include ReactiveCaching
attr_reader :project
self.reactive_cache_key = ->(finder) { finder.cache_key }
self.reactive_cache_worker_finder = ->(_id, *args) { from_cache(*args) }
MAX_CLUSTERS = 10
def initialize(project)
@project = project
end
......@@ -15,8 +21,9 @@ module Projects
knative_services.flatten.compact
end
# Possible return values: Clusters::KnativeServicesFinder::KNATIVE_STATE
def knative_installed
return knative_installed_from_cluster?(*cache_key) if available_environments.empty?
states = services_finders.map do |finder|
finder.knative_detected.tap do |state|
return state if state == ::Clusters::KnativeServicesFinder::KNATIVE_STATES['checking'] # rubocop:disable Cop/AvoidReturnFromBlocks
......@@ -45,8 +52,41 @@ module Projects
end
end
def self.from_cache(project_id)
project = Project.find(project_id)
new(project)
end
def cache_key(*args)
[project.id]
end
def calculate_reactive_cache(*)
# rubocop: disable CodeReuse/ActiveRecord
project.all_clusters.enabled.take(MAX_CLUSTERS).any? do |cluster|
cluster.kubeclient.knative_client.discover
rescue Kubeclient::ResourceNotFoundError
next
end
end
private
def knative_installed_from_cluster?(*cache_key)
cached_data = with_reactive_cache_memoized(*cache_key) { |data| data }
return ::Clusters::KnativeServicesFinder::KNATIVE_STATES['checking'] if cached_data.nil?
cached_data ? true : false
end
def with_reactive_cache_memoized(*cache_key)
strong_memoize(:reactive_cache) do
with_reactive_cache(*cache_key) { |data| data }
end
end
def knative_service(environment_scope, name)
finders_for_scope(environment_scope).map do |finder|
services = finder
......@@ -95,6 +135,10 @@ module Projects
environment_scope == finder.cluster.environment_scope
end
end
def id
nil
end
end
end
end
......@@ -16,7 +16,12 @@ describe 'Functions', :js do
shared_examples "it's missing knative installation" do
before do
functions_finder = Projects::Serverless::FunctionsFinder.new(project)
visit project_serverless_functions_path(project)
allow(Projects::Serverless::FunctionsFinder)
.to receive(:new)
.and_return(functions_finder)
synchronous_reactive_cache(functions_finder)
end
it 'sees an empty state require Knative installation' do
......
......@@ -26,10 +26,70 @@ describe Projects::Serverless::FunctionsFinder do
project.add_maintainer(user)
end
describe '#installed' do
it 'when reactive_caching is still fetching data' do
describe '#knative_installed' do
context 'when environment does not exist yet' do
shared_examples 'before first deployment' do
let(:service) { cluster.platform_kubernetes }
let(:deployment) { nil }
it 'returns true if Knative is installed on cluster' do
stub_kubeclient_discover_knative_found(service.api_url)
function_finder = described_class.new(project)
synchronous_reactive_cache(function_finder)
expect(function_finder.knative_installed).to be true
end
it 'returns false if Knative is not installed on cluster' do
stub_kubeclient_discover_knative_not_found(service.api_url)
function_finder = described_class.new(project)
synchronous_reactive_cache(function_finder)
expect(function_finder.knative_installed).to be false
end
end
context 'when project level cluster is present and enabled' do
it_behaves_like 'before first deployment' do
let(:cluster) { create(:cluster, :project, :provided_by_gcp, enabled: true) }
let(:project) { cluster.project }
end
end
context 'when group level cluster is present and enabled' do
it_behaves_like 'before first deployment' do
let(:cluster) { create(:cluster, :group, :provided_by_gcp, enabled: true) }
let(:project) { create(:project, group: cluster.groups.first) }
end
end
context 'when instance level cluster is present and enabled' do
it_behaves_like 'before first deployment' do
let(:project) { create(:project) }
let(:cluster) { create(:cluster, :instance, :provided_by_gcp, enabled: true) }
end
end
context 'when project level cluster is present, but disabled' do
let(:cluster) { create(:cluster, :project, :provided_by_gcp, enabled: false) }
let(:project) { cluster.project }
let(:service) { cluster.platform_kubernetes }
let(:deployment) { nil }
it 'returns false even if Knative is installed on cluster' do
stub_kubeclient_discover_knative_found(service.api_url)
function_finder = described_class.new(project)
synchronous_reactive_cache(function_finder)
expect(function_finder.knative_installed).to be false
end
end
end
context 'when reactive_caching is still fetching data' do
it 'returns "checking"' do
expect(described_class.new(project).knative_installed).to eq 'checking'
end
end
context 'when reactive_caching has finished' do
before do
......
......@@ -60,6 +60,12 @@ module KubernetesHelpers
.to_return(status: [404, "Resource Not Found"])
end
def stub_kubeclient_discover_knative_found(api_url)
WebMock
.stub_request(:get, api_url + '/apis/serving.knative.dev/v1alpha1')
.to_return(kube_response(kube_knative_discovery_body))
end
def stub_kubeclient_service_pods(response = nil, options = {})
stub_kubeclient_discover(service.api_url)
......@@ -288,6 +294,13 @@ module KubernetesHelpers
}
end
def kube_knative_discovery_body
{
"kind" => "APIResourceList",
"resources" => []
}
end
def kube_extensions_v1beta1_discovery_body
{
"kind" => "APIResourceList",
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment