lib/healthcheck_endpoint/configuration.rb
# frozen_string_literal: true
module HealthcheckEndpoint
class Configuration
ATTRIBUTES = %i[
services
services_startup
services_liveness
services_readiness
endpoints_namespace
endpoint_startup
endpoint_liveness
endpoint_readiness
endpoint_startup_status_success
endpoint_liveness_status_success
endpoint_readiness_status_success
endpoint_startup_status_failure
endpoint_liveness_status_failure
endpoint_readiness_status_failure
].freeze
ENDPOINTS_NAMESPACE = '/healthcheck'
ENDPOINT_STARTUP = '/startup'
ENDPOINT_LIVENESS = '/liveness'
ENDPOINT_READINESS = '/readiness'
DEFAULT_HTTP_STATUS_SUCCESS = 200
DEFAULT_HTTP_STATUS_FAILURE = 500
AVILABLE_HTTP_STATUSES_SUCCESS = (DEFAULT_HTTP_STATUS_SUCCESS..226).freeze
AVILABLE_HTTP_STATUSES_FAILURE = (DEFAULT_HTTP_STATUS_FAILURE..511).freeze
Settings = ::Struct.new(*HealthcheckEndpoint::Configuration::ATTRIBUTES, keyword_init: true) do
def update(&block)
return self unless block
tap(&block)
end
end
attr_reader(*HealthcheckEndpoint::Configuration::ATTRIBUTES)
def initialize(&block)
configuration_settings = build_configuration_settings(&block)
HealthcheckEndpoint::Configuration::ATTRIBUTES.each do |attribute|
public_send(:"#{attribute}=", configuration_settings.public_send(attribute))
end
end
HealthcheckEndpoint::Configuration::ATTRIBUTES.each do |attribute|
define_method(:"#{attribute}=") do |argument|
validate_attribute(__method__, attribute, argument)
instance_variable_set(:"@#{attribute}", argument)
end
end
private
def build_configuration_settings(&block) # rubocop:disable Metrics/MethodLength
HealthcheckEndpoint::Configuration::Settings.new(
services: {},
services_startup: [],
services_liveness: [],
services_readiness: [],
endpoints_namespace: HealthcheckEndpoint::Configuration::ENDPOINTS_NAMESPACE,
endpoint_startup: HealthcheckEndpoint::Configuration::ENDPOINT_STARTUP,
endpoint_liveness: HealthcheckEndpoint::Configuration::ENDPOINT_LIVENESS,
endpoint_readiness: HealthcheckEndpoint::Configuration::ENDPOINT_READINESS,
endpoint_startup_status_success: HealthcheckEndpoint::Configuration::DEFAULT_HTTP_STATUS_SUCCESS,
endpoint_liveness_status_success: HealthcheckEndpoint::Configuration::DEFAULT_HTTP_STATUS_SUCCESS,
endpoint_readiness_status_success: HealthcheckEndpoint::Configuration::DEFAULT_HTTP_STATUS_SUCCESS,
endpoint_startup_status_failure: HealthcheckEndpoint::Configuration::DEFAULT_HTTP_STATUS_FAILURE,
endpoint_liveness_status_failure: HealthcheckEndpoint::Configuration::DEFAULT_HTTP_STATUS_FAILURE,
endpoint_readiness_status_failure: HealthcheckEndpoint::Configuration::DEFAULT_HTTP_STATUS_FAILURE
).update(&block)
end
def validate_attribute(method, attribute, value) # rubocop:disable Metrics/AbcSize
raise_unless(HealthcheckEndpoint::Error::Configuration::ArgumentType, method, *validator_argument_type(attribute, value))
case attribute
when HealthcheckEndpoint::Configuration::ATTRIBUTES[0]
raise_unless(HealthcheckEndpoint::Error::Configuration::NotCallableService, method, *validator_services_callable(value))
when *HealthcheckEndpoint::Configuration::ATTRIBUTES[1..3]
raise_unless(HealthcheckEndpoint::Error::Configuration::UnknownService, method, *validator_services_conformity(value))
when *HealthcheckEndpoint::Configuration::ATTRIBUTES[4..7]
raise_unless(HealthcheckEndpoint::Error::Configuration::EnpointPattern, method, *validator_endpoint(value))
when *HealthcheckEndpoint::Configuration::ATTRIBUTES[8..10]
raise_unless(HealthcheckEndpoint::Error::Configuration::HttpStatusSuccess, method, *validator_http_status_success(value))
when *HealthcheckEndpoint::Configuration::ATTRIBUTES[11..13]
raise_unless(HealthcheckEndpoint::Error::Configuration::HttpStatusFailure, method, *validator_http_status_failure(value))
end
end
def validator_argument_type(method_name, argument)
[
argument,
argument.is_a?(
case method_name
when :services then ::Hash
when *HealthcheckEndpoint::Configuration::ATTRIBUTES[1..3] then ::Array
when *HealthcheckEndpoint::Configuration::ATTRIBUTES[4..7] then ::String
when *HealthcheckEndpoint::Configuration::ATTRIBUTES[8..13] then ::Integer
end
)
]
end
def validator_endpoint(argument)
[argument, argument[%r{\A/.*\z}]]
end
def validator_http_status_success(argument)
[argument, HealthcheckEndpoint::Configuration::AVILABLE_HTTP_STATUSES_SUCCESS.include?(argument)]
end
def validator_http_status_failure(argument)
[argument, HealthcheckEndpoint::Configuration::AVILABLE_HTTP_STATUSES_FAILURE.include?(argument)]
end
def validator_services_callable(services_to_check, target_service = nil)
result = services_to_check.all? do |service_name, service_context|
target_service = service_name
service_context.respond_to?(:call)
end
[target_service, result]
end
def validator_services_conformity(services_to_check, target_service = nil)
result = services_to_check.all? do |service_name|
target_service = service_name
services.key?(service_name)
end
[target_service, result]
end
def raise_unless(exception_class, argument_name, argument_context, condition)
raise exception_class.new(argument_context, argument_name) unless condition
end
end
end