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 ...@@ -4,9 +4,15 @@ module Projects
module Serverless module Serverless
class FunctionsFinder class FunctionsFinder
include Gitlab::Utils::StrongMemoize include Gitlab::Utils::StrongMemoize
include ReactiveCaching
attr_reader :project 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) def initialize(project)
@project = project @project = project
end end
...@@ -15,8 +21,9 @@ module Projects ...@@ -15,8 +21,9 @@ module Projects
knative_services.flatten.compact knative_services.flatten.compact
end end
# Possible return values: Clusters::KnativeServicesFinder::KNATIVE_STATE
def knative_installed def knative_installed
return knative_installed_from_cluster?(*cache_key) if available_environments.empty?
states = services_finders.map do |finder| states = services_finders.map do |finder|
finder.knative_detected.tap do |state| finder.knative_detected.tap do |state|
return state if state == ::Clusters::KnativeServicesFinder::KNATIVE_STATES['checking'] # rubocop:disable Cop/AvoidReturnFromBlocks return state if state == ::Clusters::KnativeServicesFinder::KNATIVE_STATES['checking'] # rubocop:disable Cop/AvoidReturnFromBlocks
...@@ -45,8 +52,41 @@ module Projects ...@@ -45,8 +52,41 @@ module Projects
end end
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 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) def knative_service(environment_scope, name)
finders_for_scope(environment_scope).map do |finder| finders_for_scope(environment_scope).map do |finder|
services = finder services = finder
...@@ -95,6 +135,10 @@ module Projects ...@@ -95,6 +135,10 @@ module Projects
environment_scope == finder.cluster.environment_scope environment_scope == finder.cluster.environment_scope
end end
end end
def id
nil
end
end end
end end
end end
...@@ -16,7 +16,12 @@ describe 'Functions', :js do ...@@ -16,7 +16,12 @@ describe 'Functions', :js do
shared_examples "it's missing knative installation" do shared_examples "it's missing knative installation" do
before do before do
functions_finder = Projects::Serverless::FunctionsFinder.new(project)
visit project_serverless_functions_path(project) visit project_serverless_functions_path(project)
allow(Projects::Serverless::FunctionsFinder)
.to receive(:new)
.and_return(functions_finder)
synchronous_reactive_cache(functions_finder)
end end
it 'sees an empty state require Knative installation' do it 'sees an empty state require Knative installation' do
......
...@@ -26,9 +26,69 @@ describe Projects::Serverless::FunctionsFinder do ...@@ -26,9 +26,69 @@ describe Projects::Serverless::FunctionsFinder do
project.add_maintainer(user) project.add_maintainer(user)
end end
describe '#installed' do describe '#knative_installed' do
it 'when reactive_caching is still fetching data' do context 'when environment does not exist yet' do
expect(described_class.new(project).knative_installed).to eq 'checking' 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 end
context 'when reactive_caching has finished' do context 'when reactive_caching has finished' do
......
...@@ -60,6 +60,12 @@ module KubernetesHelpers ...@@ -60,6 +60,12 @@ module KubernetesHelpers
.to_return(status: [404, "Resource Not Found"]) .to_return(status: [404, "Resource Not Found"])
end 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 = {}) def stub_kubeclient_service_pods(response = nil, options = {})
stub_kubeclient_discover(service.api_url) stub_kubeclient_discover(service.api_url)
...@@ -288,6 +294,13 @@ module KubernetesHelpers ...@@ -288,6 +294,13 @@ module KubernetesHelpers
} }
end end
def kube_knative_discovery_body
{
"kind" => "APIResourceList",
"resources" => []
}
end
def kube_extensions_v1beta1_discovery_body def kube_extensions_v1beta1_discovery_body
{ {
"kind" => "APIResourceList", "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