require "weird-crystal-base" class Service end class Service::Context < Weird::Base property pid_directory = PID_DIRECTORY property log_directory = LOG_DIRECTORY property services_directory = RC_DIRECTORY property service_definitions_directory = SERVICES_DIRECTORY property environments_directory = ENVIRONMENTS_DIRECTORY # FIXME: Namespaces. 😬 getter services = [] of Service getter service_definitions = [] of ServiceDefinition getter environments = [] of Environment def initialize @environments = [Environment.new self] end def root_environment @environments[0] end def load_services path = services_directory return unless Dir.exists? path Dir.each_child path do |child| unless child.match /\.spec$/ next end begin specs = SpecParser.parse(File.read "#{path}/#{child}").not_nil! rescue next end @services << Service.new self, specs end end def load_environments path = environments_directory return unless Dir.exists? path Dir.each_child path do |child| unless child.match /\.spec$/ next end file_path = "#{path}/#{child}" begin name = File.basename(child, ".spec") specs = SpecParser.parse File.read(file_path) environment = Environment.new self, name, specs rescue e STDERR << "error loading #{file_path}: " << e << "\n" # FIXME: Print stacktrace? Debug mode? next end @environments << environment end end def load_service_definitions path = service_definitions_directory Dir.each_child path do |child| if child.match /\.spec$/ name = File.basename(child, ".spec") specs = SpecParser.parse File.read "#{path}/#{child}" @service_definitions << ServiceDefinition.new name, specs else next end end end def load load_service_definitions load_environments load_services end def get_service_by_id(id) matches = id.match /[^\/]*/ unless matches # Should not happen, above regex would always match. raise Exception.new "FIXME" end environment_name, service_name = Service.parse_id id @services.find do |service| service.name == service_name && service.environment.name == environment_name end end def get_environment_by_name(name) _def = @environments.find &.name.==(name) if _def.nil? raise ::Service::Exception.new "Environment '#{name}' does not exist." end _def end def get_used_ports(other_reservations = Array(Int32).new) services.map(&.ports.to_a) .flatten .map { |k, v| v } .+(other_reservations) end def get_free_port(other_reservations = Array(Int32).new) port = 49152 used_ports = get_used_ports other_reservations while used_ports.any? &.==(port) port = port + 1 end port end def get_service_definition_by_name(name) _def = @service_definitions.find &.name.==(name) if _def.nil? raise Exception.new "Service '#{name}' does not exist." end _def end def is_port_used(port, other_reservations = Array(Int32).new) used_ports = get_used_ports other_reservations used_ports.any? &.==(port) end end