# frozen_string_literal: true 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_work_type = :external_dependency self.reactive_cache_worker_finder = ->(_id, *args) { from_cache(*args) } MAX_CLUSTERS = 10 def initialize(project) @project = project end def execute knative_services.flatten.compact end 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 end end states.any? { |state| state == ::Clusters::KnativeServicesFinder::KNATIVE_STATES['installed'] } end def service(environment_scope, name) knative_service(environment_scope, name)&.first end def invocation_metrics(environment_scope, name) environment = finders_for_scope(environment_scope).first&.environment if environment.present? && environment.prometheus_adapter&.can_query? func = ::Serverless::Function.new(project, name, environment.deployment_namespace) environment.prometheus_adapter.query(:knative_invocation, func) end end def has_prometheus?(environment_scope) finders_for_scope(environment_scope).any? do |finder| finder.cluster.application_prometheus_available? 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 .services .select { |svc| svc["metadata"]["name"] == name } attributes = add_metadata(finder, services).first next unless attributes Gitlab::Serverless::Service.new(attributes) end end def knative_services services_finders.map do |finder| attributes = add_metadata(finder, finder.services) attributes&.map do |attributes| Gitlab::Serverless::Service.new(attributes) end end end def add_metadata(finder, services) return if services.nil? add_pod_count = services.one? services.each do |s| s["environment_scope"] = finder.cluster.environment_scope s["environment"] = finder.environment s["cluster"] = finder.cluster if add_pod_count s["podcount"] = finder .service_pod_details(s["metadata"]["name"]) .length end end end def services_finders strong_memoize(:services_finders) do available_environments.map(&:knative_services_finder).compact end end def available_environments @project.environments.available.preload_cluster end def finders_for_scope(environment_scope) services_finders.select do |finder| environment_scope == finder.cluster.environment_scope end end def id nil end end end end