require "yaml" require "specparser" class ServiceDefinition struct Consumes getter token : String getter optional : Bool def initialize(@token) @optional = false if @token.match /\?$/ @token = @token.gsub /\?$/, "" @optional = true end end end struct Provides getter token : String def initialize(@token) end end struct FileDefinition getter name : String getter file_path : String getter creation_command : String? getter deletion_command : String? getter export_command : String? @configuration = false def initialize(@file_path, @name = @file_path, @creation_command = nil, @deletion_command = nil, @export_command = nil, @configuration = false) end def initialize(section : SpecParser::Section) @file_path = section.options[0] @name = section.content["name"]?.try(&.as_s) || @file_path @configuration = section.content["configuration"]? .try(&.as_s) .==("true") @creation_command = section.content["creation-command"]? .try &.as_s @deletion_command = section.content["deletion-command"]? .try &.as_s @export_command = section.content["export-command"]? .try &.as_s #@unless_directory = section.content["unless-directory"]? # .try &.as_s #@unless_file = section.content["unless-file"]?.try &.as_s end def is_configuration? @configuration end end struct PortDefinition getter name : String getter default_value : Int32? def initialize(string : String) match = string.match(/([^?=]*)(=([^?]*))?/).not_nil! @name = match[1] @default_value = match[3]?.try &.to_i end end class_getter all = [] of ServiceDefinition getter name : String getter command : String getter stop_command : String? getter reload_command : String? getter readiness_check_command : String? getter directory : String? getter user : String? getter group : String? getter start_as_root : Bool? getter provides : String? getter consumes : Array(Consumes) getter environment_variables : Array(String) getter files : Array(FileDefinition) getter provides : Array(Provides) getter port_definitions : Array(PortDefinition) getter non_runnable : Bool getter requires_domain = false def initialize(@name, specs : SpecParser) sections = specs.sections specs = specs.assignments @command = specs["command"].as_s @non_runnable = (@command == "none") @stop_command = specs["stop-command"]?.try &.as_s @reload_command = specs["reload-command"]?.try &.as_s @readiness_check_command = specs["readiness-check-command"]?.try &.as_s @directory = specs["directory"]?.try &.as_s @user = specs["user"]?.try &.as_s @group = specs["group"]?.try &.as_s @start_as_root = specs["start-as-root"]?.try(&.as_s).try(&.==("true")) || false @provides = specs["provides"]?.try &.as_a_or_s.map { |x| Provides.new x } || Array(Provides).new @consumes = specs["consumes"]?.try &.as_a_or_s.map { |x| Consumes.new x } || Array(Consumes).new @environment_variables = specs["environment-variables"]?.try &.as_a_or_s || Array(String).new @port_definitions = specs["ports"]?.try &.as_a_or_s.map { |x| PortDefinition.new x } || Array(PortDefinition).new # FIXME: as_b? requires_domain = specs["requires-domain"]?.try &.as_s case requires_domain when nil when "true", "yes" @requires_domain = true when "false", "no" @requires_domain = false else STDERR.puts "warning: definition '#{@name}' has a 'requires-domain' entry with an invalid value" end @files = Array(FileDefinition).new sections.each do |section| case section.name when "file", "directory" @files << FileDefinition.new section when "configuration" options = section.options[0].split /[ \t]/ template = options[0]? name = section.content["name"]?.try &.as_s if template.nil? STDERR.puts "warning: (#{@name}) %configuration wasn’t provided a target." next end target = options[1]? unless target target = template template = File.basename target end files << FileDefinition.new target, (name || target), creation_command: "gen-config \"#{template}\" \"#{target}\"", deletion_command: "rm \"#{target}\"", configuration: true when "database" options = section.options[0].split /[ \t]/ type = options[0]? || section.content["type"]?.try &.as_s # FIXME: %database is not currently implemented. end end end def to_s name end end