Commit 097e9d2a authored by Kamil Trzciński's avatar Kamil Trzciński

Merge branch '38288-bug-incorrect-serverless-empty-state' into 'master'

Check for Knative installation on enabled clusters

Closes #38288

See merge request gitlab-org/gitlab!22107
parents 602c74bf 6eed9c5e
......@@ -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,9 +26,69 @@ describe Projects::Serverless::FunctionsFinder do
project.add_maintainer(user)
end
describe '#installed' do
it 'when reactive_caching is still fetching data' do
expect(described_class.new(project).knative_installed).to eq 'checking'
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
......
......@@ -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