Module: Do::Validator
- Defined in:
- lib/do/validator.rb
Overview
Stateless validation over a parsed Config. Returns human-readable error strings and never touches the system.
Class Method Summary collapse
- .schedule_errors(task) ⇒ Object
- .valid?(config) ⇒ Boolean
-
.validate(config) ⇒ Array<String>
Validation errors (empty when valid).
- .validate!(config) ⇒ Object
- .validate_commands(config) ⇒ Object
- .validate_directories(config) ⇒ Object
- .validate_duplicates(config) ⇒ Object
- .validate_environment(config) ⇒ Object
- .validate_schedules(config) ⇒ Object
- .validate_task_fields(config) ⇒ Object
- .validate_unit_names(config) ⇒ Object
Class Method Details
.schedule_errors(task) ⇒ Object
105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 |
# File 'lib/do/validator.rb', line 105 def schedule_errors(task) sched = task.schedule return [] if sched.nil? || sched.empty? unless Task::SCHEDULES.include?(sched) return ["invalid schedule for task '#{task.name}'. " \ 'Expected: once, hourly, daily, weekly, or monthly.'] end # Driving the calendar generator lets us reuse the exact same parsing # rules that will later be used to emit the systemd unit. begin Scheduler.on_calendar(task) [] rescue Do::Error => e ["invalid schedule for task '#{task.name}': #{e.}"] end end |
.valid?(config) ⇒ Boolean
26 27 28 |
# File 'lib/do/validator.rb', line 26 def valid?(config) validate(config).empty? end |
.validate(config) ⇒ Array<String>
Returns validation errors (empty when valid).
14 15 16 17 18 19 20 21 22 23 24 |
# File 'lib/do/validator.rb', line 14 def validate(config) errors = [] errors.concat(validate_commands(config)) errors.concat(validate_task_fields(config)) errors.concat(validate_duplicates(config)) errors.concat(validate_schedules(config)) errors.concat(validate_unit_names(config)) errors.concat(validate_directories(config)) errors.concat(validate_environment(config)) errors end |
.validate!(config) ⇒ Object
31 32 33 34 35 36 |
# File 'lib/do/validator.rb', line 31 def validate!(config) errors = validate(config) raise ValidationError, errors unless errors.empty? true end |
.validate_commands(config) ⇒ Object
38 39 40 41 42 43 44 45 46 |
# File 'lib/do/validator.rb', line 38 def validate_commands(config) config.tasks.flat_map do |task| if task.command.nil? || task.command.to_s.strip.empty? ["task '#{task.name}' is missing required field 'command'"] else [] end end end |
.validate_directories(config) ⇒ Object
80 81 82 83 84 85 86 87 88 89 90 91 |
# File 'lib/do/validator.rb', line 80 def validate_directories(config) config.tasks.flat_map do |task| wd = task.working_directory next [] if wd.nil? || wd.empty? if File.directory?(File.(wd)) [] else ["working directory '#{wd}' for task '#{task.name}' does not exist"] end end end |
.validate_duplicates(config) ⇒ Object
55 56 57 58 59 60 |
# File 'lib/do/validator.rb', line 55 def validate_duplicates(config) lowered = config.tasks.map { |t| t.name.downcase } lowered .select { |n| lowered.count(n) > 1 }.uniq .map { |n| "duplicate task name '#{n}'" } end |
.validate_environment(config) ⇒ Object
93 94 95 96 97 98 99 100 101 102 103 |
# File 'lib/do/validator.rb', line 93 def validate_environment(config) config.tasks.flat_map do |task| (task.environment || {}).flat_map do |key, value| if key.is_a?(String) && value.is_a?(String) [] else ["environment for task '#{task.name}' must map strings to strings"] end end end end |
.validate_schedules(config) ⇒ Object
62 63 64 |
# File 'lib/do/validator.rb', line 62 def validate_schedules(config) config.tasks.flat_map { |task| schedule_errors(task) } end |
.validate_task_fields(config) ⇒ Object
48 49 50 51 52 53 |
# File 'lib/do/validator.rb', line 48 def validate_task_fields(config) config.tasks.flat_map do |task| unknown = task.raw.keys - Config::KNOWN_TASK_FIELDS unknown.map { |field| "unsupported field '#{field}' for task '#{task.name}'" } end end |
.validate_unit_names(config) ⇒ Object
66 67 68 69 70 71 72 73 74 75 76 77 78 |
# File 'lib/do/validator.rb', line 66 def validate_unit_names(config) config.tasks.flat_map do |task| name = task.name.to_s if name.empty? ['task has an empty name'] elsif name.start_with?('.') || name =~ %r{[\s/]|\.} ["task name '#{name}' is not a valid systemd unit name " \ "(must not contain spaces, '/', dots, or start with a dot)"] else [] end end end |