168 lines
4.4 KiB
Crystal
168 lines
4.4 KiB
Crystal
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
|
||
|