Allow plugin to take an etc_type keyword argument for using the TYPE_ETC ubid type, and remove the separate definitions in every model that uses the TYPE_ETC ubid type. This was the cleanest way to DRY things up. You cannot extend the models with a module to do this before including ResourceMethods, because then ResourceMethods::ClassMethods will override it, and you cannot extend the models with a module to do this after including ResourceMethods, because the inclusion will not work correctly due to the eager definition of @ubid_format. Best reviewed without whitespace differences.
248 lines
6.8 KiB
Ruby
248 lines
6.8 KiB
Ruby
# frozen_string_literal: true
|
|
|
|
require_relative "lib/thread_printer"
|
|
Signal.trap("QUIT") do
|
|
ThreadPrinter.run
|
|
Kernel.exit!(Signal.list["QUIT"] + 128)
|
|
end
|
|
|
|
require "bundler"
|
|
rack_env = ENV["RACK_ENV"] || "development"
|
|
Bundler.setup(:default, rack_env.to_sym)
|
|
|
|
require_relative "config"
|
|
require "mail"
|
|
require "warning"
|
|
require "rack/unreloader"
|
|
|
|
REPL = false unless defined? REPL
|
|
Warning.ignore(/To use (retry|multipart) middleware with Faraday v2\.0\+, install `faraday-(retry|multipart)` gem/)
|
|
|
|
force_autoload = Config.production? || ENV["FORCE_AUTOLOAD"] == "1"
|
|
Unreloader = Rack::Unreloader.new(reload: Config.development?, autoload: true) { Clover }
|
|
|
|
autoload :DB, "#{__dir__}/db.rb"
|
|
Unreloader.autoload("#{__dir__}/ubid.rb") { "UBID" }
|
|
|
|
AUTOLOAD_CONSTANTS = ["UBID"]
|
|
|
|
# Set up autoloads using Unreloader using a style much like Zeitwerk:
|
|
# directories are modules, file names are classes.
|
|
autoload_normal = ->(subdirectory, include_first: false, flat: false) do
|
|
absolute = File.join(__dir__, subdirectory)
|
|
rgx = if flat
|
|
# No matter how deep the file system traversal, this Regexp
|
|
# only matches the filename in its capturing group,
|
|
# i.e. it's like File.basename.
|
|
Regexp.new('\A.*?([^/]*)\.rb\z')
|
|
else
|
|
# Capture the relative path of a traversed file, by using
|
|
# Regexp.escape on the prefix that should *not* be
|
|
# interpreted as modules/namespaces. Since this is works on
|
|
# absolute paths, the ignored content will often be like
|
|
# "/home/myuser/..."
|
|
Regexp.new('\A' + Regexp.escape((File.file?(absolute) ? File.dirname(absolute) : absolute) + "/") + '(.*)\.rb\z')
|
|
end
|
|
|
|
# Copied from sequel/model/inflections.rb's camelize, to convert
|
|
# file paths into module and class names.
|
|
camelize = ->(s) do
|
|
s.gsub(/\/(.?)/) { |x| "::#{x[-1..].upcase}" }.gsub(/(^|_)(.)/) { |x| x[-1..].upcase }
|
|
end
|
|
|
|
Unreloader.autoload(absolute) do |f|
|
|
full_name = camelize.call((include_first ? subdirectory + File::SEPARATOR : "") + rgx.match(f)[1])
|
|
AUTOLOAD_CONSTANTS << full_name unless AUTOLOAD_CONSTANTS.frozen?
|
|
full_name
|
|
end
|
|
end
|
|
|
|
# Define empty modules instead of trying to have autoload_normal create them via metaprogramming
|
|
module Hosting; end
|
|
|
|
module Minio; end
|
|
|
|
module Kubernetes; end
|
|
|
|
module Prog; end
|
|
|
|
module Prog::Ai; end
|
|
|
|
module Prog::Aws; end
|
|
|
|
module Prog::DnsZone; end
|
|
|
|
module Prog::Github; end
|
|
|
|
module Prog::Kubernetes; end
|
|
|
|
module Prog::Minio; end
|
|
|
|
module Prog::Postgres; end
|
|
|
|
module Prog::Storage; end
|
|
|
|
module Prog::VictoriaMetrics; end
|
|
|
|
module Prog::Vm; end
|
|
|
|
module Prog::Vnet; end
|
|
|
|
module Scheduling; end
|
|
|
|
module Serializers; end
|
|
|
|
module VictoriaMetrics; end
|
|
|
|
autoload_normal.call("model", flat: true)
|
|
%w[lib clover.rb].each { autoload_normal.call(it) }
|
|
%w[scheduling prog serializers].each { autoload_normal.call(it, include_first: true) }
|
|
|
|
if ENV["LOAD_FILES_SEPARATELY_CHECK"] == "1"
|
|
files = %w[model lib scheduling prog serializers].flat_map { Dir["#{it}/**/*.rb"] }
|
|
files << "clover.rb"
|
|
|
|
Sequel::DATABASES.each(&:disconnect)
|
|
files.each do |file|
|
|
pid = fork do
|
|
require_relative file
|
|
exit(0)
|
|
rescue LoadError, StandardError => e
|
|
puts "ERROR: problems loading #{file}: #{e.class}: #{e.message}"
|
|
end
|
|
Process.wait(pid)
|
|
end
|
|
exit(0)
|
|
end
|
|
|
|
AUTOLOAD_CONSTANTS.freeze
|
|
|
|
Unreloader.record_dependency("lib/authorization.rb", "model")
|
|
Unreloader.record_dependency("lib/health_monitor_methods.rb", "model")
|
|
Unreloader.record_dependency("lib/resource_methods.rb", "model")
|
|
Unreloader.record_dependency("lib/semaphore_methods.rb", "model")
|
|
|
|
if force_autoload
|
|
AUTOLOAD_CONSTANT_VALUES = AUTOLOAD_CONSTANTS.map { Object.const_get(it) }.freeze
|
|
|
|
# All classes are already available, so speed up UBID.class_for_ubid using
|
|
# hash of prefixes to class objects
|
|
class UBID
|
|
TYPE2CLASS = TYPE2CLASSNAME.transform_values { Object.const_get(it) }.freeze
|
|
private_constant :TYPE2CLASS
|
|
|
|
singleton_class.remove_method(:class_for_ubid)
|
|
def self.class_for_ubid(str)
|
|
TYPE2CLASS[str[..1]]
|
|
end
|
|
end
|
|
end
|
|
|
|
case Config.mail_driver
|
|
when :smtp
|
|
::Mail.defaults do
|
|
delivery_method :smtp, {
|
|
address: Config.smtp_hostname,
|
|
port: Config.smtp_port,
|
|
user_name: Config.smtp_user,
|
|
password: Config.smtp_password,
|
|
authentication: :plain,
|
|
enable_starttls: Config.smtp_tls
|
|
}
|
|
end
|
|
when :logger
|
|
::Mail.defaults do
|
|
delivery_method :logger
|
|
end
|
|
when :test
|
|
::Mail.defaults do
|
|
delivery_method :test
|
|
end
|
|
end
|
|
|
|
def clover_freeze
|
|
return unless Config.production? || ENV["CLOVER_FREEZE"] == "1"
|
|
require "refrigerator"
|
|
|
|
# Take care of library dependencies that modify core classes.
|
|
|
|
# For at least Puma, per
|
|
# https://github.com/jeremyevans/roda-sequel-stack/blob/931e810a802b2ab14628111cfce596998316b556/config.ru#L41C6-L42C1
|
|
require "yaml"
|
|
|
|
# Also for at least puma, but not itemized by the roda-sequel-stack
|
|
# project for some reason.
|
|
require "nio4r"
|
|
|
|
# this Ruby standard library method patches core classes.
|
|
"".unicode_normalize(:nfc)
|
|
|
|
# Aws SDK started to autoload modules when used, so we need to load them
|
|
# before freezing. https://github.com/aws/aws-sdk-ruby/pull/3105
|
|
[:Client, :Presigner, :Errors].each { Aws::S3.const_get(it) }
|
|
|
|
# A standard library method that edits/creates a module variable as
|
|
# a side effect. We encountered it when using rubygems for its tar
|
|
# file writing.
|
|
Gem.source_date_epoch
|
|
|
|
# Freeze all constants that are autoloaded
|
|
DB.freeze
|
|
Sequel::Model.freeze_descendants
|
|
AUTOLOAD_CONSTANT_VALUES.each(&:freeze)
|
|
[
|
|
Authorization,
|
|
Authorization::Unauthorized,
|
|
HealthMonitorMethods,
|
|
Hosting,
|
|
Minio,
|
|
Minio::Client::Blob,
|
|
Minio::Crypto::AesGcmCipherProvider,
|
|
PostgresResource::Flavor,
|
|
PostgresResource::HaType,
|
|
Prog,
|
|
Prog::Ai,
|
|
Prog::Base::Exit,
|
|
Prog::Base::FlowControl,
|
|
Prog::Base::Hop,
|
|
Prog::Base::Nap,
|
|
Prog::DnsZone,
|
|
Prog::Github,
|
|
Prog::Kubernetes,
|
|
Prog::Minio,
|
|
Prog::Postgres,
|
|
Prog::Storage,
|
|
Prog::VictoriaMetrics,
|
|
Prog::Vm,
|
|
Prog::Vnet,
|
|
Prog::Vnet::RekeyNicTunnel::Xfrm,
|
|
ResourceMethods,
|
|
ResourceMethods::ClassMethods,
|
|
ResourceMethods::InstanceMethods,
|
|
ResourceMethods::UbidTypeEtcMethods,
|
|
Scheduling,
|
|
Scheduling::Allocator,
|
|
Scheduling::Allocator::Allocation,
|
|
Scheduling::Allocator::GpuAllocation,
|
|
Scheduling::Allocator::StorageAllocation,
|
|
Scheduling::Allocator::StorageAllocation::StorageDeviceAllocation,
|
|
Scheduling::Allocator::VmHostAllocation,
|
|
Scheduling::Allocator::VmHostCpuAllocation,
|
|
Scheduling::Allocator::VmHostSliceAllocation,
|
|
SemaphoreMethods,
|
|
SemaphoreMethods::ClassMethods,
|
|
Sequel::Database,
|
|
Sequel::Dataset,
|
|
SequelExtensions,
|
|
Sequel::Model,
|
|
Serializers,
|
|
Serializers::Base,
|
|
Sshable::SshError,
|
|
Validation,
|
|
Validation::ValidationFailed
|
|
].each(&:freeze)
|
|
|
|
RubyVM::YJIT.enable
|
|
Refrigerator.freeze_core
|
|
end
|