wheneverd 0.3.0 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.ruby-version +1 -0
- data/CHANGELOG.md +16 -0
- data/Gemfile.lock +38 -33
- data/README.md +64 -7
- data/lib/wheneverd/cli/activate.rb +5 -5
- data/lib/wheneverd/cli/deactivate.rb +6 -6
- data/lib/wheneverd/cli/reload.rb +8 -8
- data/lib/wheneverd/cli/status.rb +13 -6
- data/lib/wheneverd/cli.rb +10 -8
- data/lib/wheneverd/dsl/context.rb +46 -0
- data/lib/wheneverd/dsl/period_parser.rb +8 -107
- data/lib/wheneverd/dsl/period_strategy/array_strategy.rb +29 -0
- data/lib/wheneverd/dsl/period_strategy/base.rb +65 -0
- data/lib/wheneverd/dsl/period_strategy/duration_strategy.rb +33 -0
- data/lib/wheneverd/dsl/period_strategy/string_strategy.rb +51 -0
- data/lib/wheneverd/dsl/period_strategy/symbol_strategy.rb +31 -0
- data/lib/wheneverd/dsl/period_strategy.rb +43 -0
- data/lib/wheneverd/duration.rb +1 -7
- data/lib/wheneverd/errors.rb +3 -0
- data/lib/wheneverd/interval.rb +22 -7
- data/lib/wheneverd/schedule.rb +15 -1
- data/lib/wheneverd/service.rb +105 -0
- data/lib/wheneverd/systemd/cron_parser/dow_parser.rb +208 -0
- data/lib/wheneverd/systemd/cron_parser/field_parser.rb +163 -0
- data/lib/wheneverd/systemd/cron_parser.rb +56 -303
- data/lib/wheneverd/systemd/renderer.rb +31 -66
- data/lib/wheneverd/systemd/unit_content_builder.rb +99 -0
- data/lib/wheneverd/systemd/unit_deleter.rb +2 -28
- data/lib/wheneverd/systemd/unit_lister.rb +2 -28
- data/lib/wheneverd/systemd/unit_namer.rb +6 -15
- data/lib/wheneverd/systemd/unit_path_utils.rb +54 -0
- data/lib/wheneverd/systemd/unit_writer.rb +2 -28
- data/lib/wheneverd/trigger/base.rb +22 -0
- data/lib/wheneverd/trigger/boot.rb +8 -6
- data/lib/wheneverd/trigger/calendar.rb +7 -0
- data/lib/wheneverd/trigger/interval.rb +8 -6
- data/lib/wheneverd/validation.rb +89 -0
- data/lib/wheneverd/version.rb +1 -1
- data/lib/wheneverd.rb +5 -1
- data/test/cli_activate_test.rb +27 -0
- data/test/cli_reload_test.rb +23 -0
- data/test/cli_status_test.rb +14 -4
- data/test/domain_model_test.rb +105 -0
- data/test/dsl_context_shell_test.rb +31 -0
- data/test/systemd_cron_parser_test.rb +41 -25
- data/test/systemd_renderer_errors_test.rb +1 -1
- data/test/systemd_renderer_test.rb +73 -0
- metadata +16 -2
data/test/domain_model_test.rb
CHANGED
|
@@ -105,4 +105,109 @@ class DomainModelTest < Minitest::Test
|
|
|
105
105
|
def test_entry_requires_a_trigger
|
|
106
106
|
assert_raises(ArgumentError) { Wheneverd::Entry.new(trigger: nil) }
|
|
107
107
|
end
|
|
108
|
+
|
|
109
|
+
def test_trigger_base_module_raises_not_implemented
|
|
110
|
+
# Create a class that includes Base but doesn't implement the methods
|
|
111
|
+
test_trigger_class = Class.new do
|
|
112
|
+
include Wheneverd::Trigger::Base
|
|
113
|
+
end
|
|
114
|
+
trigger = test_trigger_class.new
|
|
115
|
+
|
|
116
|
+
error = assert_raises(NotImplementedError) { trigger.systemd_timer_lines }
|
|
117
|
+
assert_includes error.message, "must implement #systemd_timer_lines"
|
|
118
|
+
|
|
119
|
+
error = assert_raises(NotImplementedError) { trigger.signature }
|
|
120
|
+
assert_includes error.message, "must implement #signature"
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
def test_trigger_signatures
|
|
124
|
+
interval = Wheneverd::Trigger::Interval.new(seconds: 60)
|
|
125
|
+
assert_equal "interval:60", interval.signature
|
|
126
|
+
|
|
127
|
+
boot = Wheneverd::Trigger::Boot.new(seconds: 5)
|
|
128
|
+
assert_equal "boot:5", boot.signature
|
|
129
|
+
|
|
130
|
+
calendar = Wheneverd::Trigger::Calendar.new(on_calendar: %w[daily hourly])
|
|
131
|
+
assert_equal "calendar:daily|hourly", calendar.signature
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
def test_period_strategy_base_raises_not_implemented
|
|
135
|
+
# Create a class that inherits from Base but doesn't implement the methods
|
|
136
|
+
test_strategy_class = Class.new(Wheneverd::DSL::PeriodStrategy::Base)
|
|
137
|
+
strategy = test_strategy_class.new(path: "test")
|
|
138
|
+
|
|
139
|
+
error = assert_raises(NotImplementedError) { strategy.handles?(:anything) }
|
|
140
|
+
assert_includes error.message, "must implement #handles?"
|
|
141
|
+
|
|
142
|
+
error = assert_raises(NotImplementedError) { strategy.parse(:anything, at_times: []) }
|
|
143
|
+
assert_includes error.message, "must implement #parse"
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
def test_validation_type
|
|
147
|
+
# Valid type
|
|
148
|
+
assert_equal 42, Wheneverd::Validation.type(42, Integer, name: "value")
|
|
149
|
+
|
|
150
|
+
# Invalid type
|
|
151
|
+
error = assert_raises(ArgumentError) do
|
|
152
|
+
Wheneverd::Validation.type("string", Integer, name: "value")
|
|
153
|
+
end
|
|
154
|
+
assert_includes error.message, "value must be a Integer"
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
def test_validation_positive_integer
|
|
158
|
+
# Valid positive integer
|
|
159
|
+
assert_equal 5, Wheneverd::Validation.positive_integer(5, name: "count")
|
|
160
|
+
|
|
161
|
+
# Non-positive
|
|
162
|
+
error = assert_raises(ArgumentError) do
|
|
163
|
+
Wheneverd::Validation.positive_integer(0, name: "count")
|
|
164
|
+
end
|
|
165
|
+
assert_includes error.message, "must be positive"
|
|
166
|
+
|
|
167
|
+
# Non-integer
|
|
168
|
+
error = assert_raises(ArgumentError) do
|
|
169
|
+
Wheneverd::Validation.positive_integer("5", name: "count")
|
|
170
|
+
end
|
|
171
|
+
assert_includes error.message, "must be a Integer"
|
|
172
|
+
end
|
|
173
|
+
|
|
174
|
+
def test_validation_non_empty_string
|
|
175
|
+
# Valid non-empty string
|
|
176
|
+
assert_equal "hello", Wheneverd::Validation.non_empty_string(" hello ", name: "text")
|
|
177
|
+
|
|
178
|
+
# Empty string
|
|
179
|
+
error = assert_raises(ArgumentError) do
|
|
180
|
+
Wheneverd::Validation.non_empty_string(" ", name: "text")
|
|
181
|
+
end
|
|
182
|
+
assert_includes error.message, "must not be empty"
|
|
183
|
+
end
|
|
184
|
+
|
|
185
|
+
def test_validation_non_empty_array
|
|
186
|
+
# Valid non-empty array
|
|
187
|
+
arr = [1, 2, 3]
|
|
188
|
+
assert_equal arr, Wheneverd::Validation.non_empty_array(arr, name: "items")
|
|
189
|
+
|
|
190
|
+
# Empty array
|
|
191
|
+
error = assert_raises(ArgumentError) do
|
|
192
|
+
Wheneverd::Validation.non_empty_array([], name: "items")
|
|
193
|
+
end
|
|
194
|
+
assert_includes error.message, "must not be empty"
|
|
195
|
+
|
|
196
|
+
# Non-array
|
|
197
|
+
error = assert_raises(ArgumentError) do
|
|
198
|
+
Wheneverd::Validation.non_empty_array("not an array", name: "items")
|
|
199
|
+
end
|
|
200
|
+
assert_includes error.message, "must be a Array"
|
|
201
|
+
end
|
|
202
|
+
|
|
203
|
+
def test_validation_in_range
|
|
204
|
+
# Valid in range
|
|
205
|
+
assert_equal 5, Wheneverd::Validation.in_range(5, 1..10, name: "value")
|
|
206
|
+
|
|
207
|
+
# Out of range
|
|
208
|
+
error = assert_raises(ArgumentError) do
|
|
209
|
+
Wheneverd::Validation.in_range(15, 1..10, name: "value")
|
|
210
|
+
end
|
|
211
|
+
assert_includes error.message, "must be in 1..10"
|
|
212
|
+
end
|
|
108
213
|
end
|
|
@@ -15,6 +15,37 @@ class DSLContextShellTest < Minitest::Test
|
|
|
15
15
|
assert_includes error.message, "shell() script must be a String"
|
|
16
16
|
end
|
|
17
17
|
|
|
18
|
+
def test_service_accepts_shell_command
|
|
19
|
+
ctx = Wheneverd::DSL::Context.new(path: "/tmp/config/schedule.rb")
|
|
20
|
+
ctx.service("live-poller", shell: "bundle exec bin/live")
|
|
21
|
+
|
|
22
|
+
service = ctx.schedule.services.fetch(0)
|
|
23
|
+
assert_equal "live-poller", service.name
|
|
24
|
+
assert_equal ["/bin/bash", "-lc", "bundle exec bin/live"], service.command.argv
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def test_service_requires_command_or_shell
|
|
28
|
+
ctx = Wheneverd::DSL::Context.new(path: "/tmp/config/schedule.rb")
|
|
29
|
+
error = assert_raises(Wheneverd::DSL::LoadError) { ctx.service("live-poller") }
|
|
30
|
+
assert_includes error.message, "service() requires command: or shell:"
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def test_service_rejects_command_and_shell_together
|
|
34
|
+
ctx = Wheneverd::DSL::Context.new(path: "/tmp/config/schedule.rb")
|
|
35
|
+
error = assert_raises(Wheneverd::DSL::LoadError) do
|
|
36
|
+
ctx.service("live-poller", command: "bin/live", shell: "bin/live")
|
|
37
|
+
end
|
|
38
|
+
assert_includes error.message, "service() accepts command: or shell:, not both"
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def test_service_wraps_validation_errors_as_load_errors
|
|
42
|
+
ctx = Wheneverd::DSL::Context.new(path: "/tmp/config/schedule.rb")
|
|
43
|
+
error = assert_raises(Wheneverd::DSL::LoadError) do
|
|
44
|
+
ctx.service("live-poller", command: "bin/live", service: { "Bad-Key" => "1" })
|
|
45
|
+
end
|
|
46
|
+
assert_includes error.message, "Invalid service setting name"
|
|
47
|
+
end
|
|
48
|
+
|
|
18
49
|
def test_shell_rejects_empty_script
|
|
19
50
|
ctx = Wheneverd::DSL::Context.new(path: "/tmp/config/schedule.rb")
|
|
20
51
|
error = assert_raises(Wheneverd::DSL::LoadError) { ctx.every("1m") { shell(" ") } }
|
|
@@ -38,28 +38,51 @@ class SystemdCronParserTest < Minitest::Test
|
|
|
38
38
|
end
|
|
39
39
|
end
|
|
40
40
|
|
|
41
|
-
def
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
41
|
+
def test_field_parser_rejects_empty_numeric_field
|
|
42
|
+
assert_raises(Wheneverd::Systemd::UnsupportedCronError) do
|
|
43
|
+
Wheneverd::Systemd::CronParser::FieldParser.parse_mapped(
|
|
44
|
+
"",
|
|
45
|
+
0..59,
|
|
46
|
+
field: "minute",
|
|
47
|
+
input: "x",
|
|
48
|
+
names: {}
|
|
49
|
+
)
|
|
50
|
+
end
|
|
50
51
|
end
|
|
51
52
|
|
|
52
|
-
def
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
53
|
+
def test_field_parser_rejects_invalid_numeric_tokens
|
|
54
|
+
# Empty token (just whitespace)
|
|
55
|
+
assert_raises(Wheneverd::Systemd::UnsupportedCronError) do
|
|
56
|
+
Wheneverd::Systemd::CronParser::FieldParser.parse_mapped(
|
|
57
|
+
" ",
|
|
58
|
+
0..59,
|
|
59
|
+
field: "minute",
|
|
60
|
+
input: "x",
|
|
61
|
+
names: {}
|
|
62
|
+
)
|
|
63
|
+
end
|
|
56
64
|
end
|
|
57
65
|
|
|
58
|
-
def
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
66
|
+
def test_dow_parser_rejects_empty_and_invalid_tokens
|
|
67
|
+
# Empty day-of-week field
|
|
68
|
+
assert_raises(Wheneverd::Systemd::UnsupportedCronError) do
|
|
69
|
+
Wheneverd::Systemd::CronParser::DowParser.parse("", input: "x")
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
# Out of range day-of-week value (8)
|
|
73
|
+
assert_raises(Wheneverd::Systemd::UnsupportedCronError) do
|
|
74
|
+
Wheneverd::Systemd::CronParser::DowParser.parse("8", input: "x")
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
# Invalid step (non-numeric)
|
|
78
|
+
assert_raises(Wheneverd::Systemd::UnsupportedCronError) do
|
|
79
|
+
Wheneverd::Systemd::CronParser::DowParser.parse("*/x", input: "x")
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
# Invalid step (zero)
|
|
83
|
+
assert_raises(Wheneverd::Systemd::UnsupportedCronError) do
|
|
84
|
+
Wheneverd::Systemd::CronParser::DowParser.parse("*/0", input: "x")
|
|
85
|
+
end
|
|
63
86
|
end
|
|
64
87
|
|
|
65
88
|
def test_rejects_unsupported_cron_patterns
|
|
@@ -97,13 +120,6 @@ class SystemdCronParserTest < Minitest::Test
|
|
|
97
120
|
assert_equal expected, Wheneverd::Systemd::CronParser.to_on_calendar_values(cron)
|
|
98
121
|
end
|
|
99
122
|
|
|
100
|
-
def assert_private_unsupported(method, *args, **kwargs)
|
|
101
|
-
parser = Wheneverd::Systemd::CronParser
|
|
102
|
-
assert_raises(Wheneverd::Systemd::UnsupportedCronError) do
|
|
103
|
-
parser.send(method, *args, **kwargs)
|
|
104
|
-
end
|
|
105
|
-
end
|
|
106
|
-
|
|
107
123
|
def assert_unsupported(*crons)
|
|
108
124
|
crons.each do |cron|
|
|
109
125
|
assert_raises(Wheneverd::Systemd::UnsupportedCronError) do
|
|
@@ -44,7 +44,7 @@ class SystemdRendererErrorsTest < Minitest::Test
|
|
|
44
44
|
|
|
45
45
|
def test_timer_lines_for_rejects_unknown_trigger
|
|
46
46
|
assert_raises(ArgumentError) do
|
|
47
|
-
Wheneverd::Systemd::
|
|
47
|
+
Wheneverd::Systemd::UnitContentBuilder.timer_lines_for(Object.new)
|
|
48
48
|
end
|
|
49
49
|
end
|
|
50
50
|
|
|
@@ -37,11 +37,84 @@ module SystemdRendererTestHelpers
|
|
|
37
37
|
)
|
|
38
38
|
end
|
|
39
39
|
|
|
40
|
+
def render_schedule(schedule, identifier: "demo")
|
|
41
|
+
Wheneverd::Systemd::Renderer.render(schedule, identifier: identifier)
|
|
42
|
+
end
|
|
43
|
+
|
|
40
44
|
def marker
|
|
41
45
|
"# Generated by wheneverd (wheneverd) #{Wheneverd::VERSION}; do not edit."
|
|
42
46
|
end
|
|
43
47
|
end
|
|
44
48
|
|
|
49
|
+
class SystemdRendererServiceTest < Minitest::Test
|
|
50
|
+
include SystemdRendererTestHelpers
|
|
51
|
+
|
|
52
|
+
def test_standalone_service_contains_restart_and_extra_service_settings
|
|
53
|
+
service = Wheneverd::Service.new(
|
|
54
|
+
name: "live-poller",
|
|
55
|
+
command: ["/bin/bash", "-lc", "bundle exec bin/live"],
|
|
56
|
+
restart: "always",
|
|
57
|
+
restart_sec: "5s",
|
|
58
|
+
service: { "Nice" => "10", "CPUQuota" => "80%" }
|
|
59
|
+
)
|
|
60
|
+
units = render_schedule(Wheneverd::Schedule.new(services: [service]))
|
|
61
|
+
unit = units.fetch(0)
|
|
62
|
+
|
|
63
|
+
assert_equal :service, unit.kind
|
|
64
|
+
assert_equal :service, unit.activation
|
|
65
|
+
assert_includes unit.contents, marker
|
|
66
|
+
assert_includes unit.contents, "Description=wheneverd service #{unit.path_basename}"
|
|
67
|
+
assert_includes unit.contents, "Type=simple"
|
|
68
|
+
assert_includes unit.contents, 'ExecStart=/bin/bash -lc "bundle exec bin/live"'
|
|
69
|
+
assert_includes unit.contents, "Restart=always"
|
|
70
|
+
assert_includes unit.contents, "RestartSec=5s"
|
|
71
|
+
assert_includes unit.contents, "Nice=10"
|
|
72
|
+
assert_includes unit.contents, "CPUQuota=80%"
|
|
73
|
+
assert_includes unit.contents, "WantedBy=default.target"
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
def test_standalone_service_accepts_array_service_lines
|
|
77
|
+
service = Wheneverd::Service.new(
|
|
78
|
+
name: "live-poller",
|
|
79
|
+
command: "bin/live",
|
|
80
|
+
service: ["Environment=RAILS_ENV=production"]
|
|
81
|
+
)
|
|
82
|
+
unit = render_schedule(Wheneverd::Schedule.new(services: [service])).fetch(0)
|
|
83
|
+
|
|
84
|
+
assert_includes unit.contents, "Environment=RAILS_ENV=production"
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
def test_standalone_service_rejects_invalid_service_lines
|
|
88
|
+
assert_raises(Wheneverd::InvalidCommandError) do
|
|
89
|
+
Wheneverd::Service.new(name: "live-poller", command: "bin/live", service: ["NoEquals"])
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
def test_standalone_service_rejects_invalid_service_settings_collection
|
|
94
|
+
assert_raises(Wheneverd::InvalidCommandError) do
|
|
95
|
+
Wheneverd::Service.new(name: "live-poller", command: "bin/live", service: "Nice=10")
|
|
96
|
+
end
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
def test_standalone_service_rejects_newlines_in_setting_values
|
|
100
|
+
assert_raises(Wheneverd::InvalidCommandError) do
|
|
101
|
+
Wheneverd::Service.new(name: "live-poller", command: "bin/live",
|
|
102
|
+
service: { "Environment" => "A=1\nB=2" })
|
|
103
|
+
end
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
def test_standalone_service_naming_is_stable
|
|
107
|
+
service = Wheneverd::Service.new(name: "worker", command: "bin/worker")
|
|
108
|
+
schedule = Wheneverd::Schedule.new(services: [service])
|
|
109
|
+
|
|
110
|
+
units1 = render_schedule(schedule)
|
|
111
|
+
units2 = render_schedule(schedule)
|
|
112
|
+
|
|
113
|
+
assert_equal units1.map(&:path_basename), units2.map(&:path_basename)
|
|
114
|
+
assert_match(/\Awheneverd-demo-[0-9a-f]{12}\.service\z/, units1.fetch(0).path_basename)
|
|
115
|
+
end
|
|
116
|
+
end
|
|
117
|
+
|
|
45
118
|
class SystemdRendererIntervalTest < Minitest::Test
|
|
46
119
|
include SystemdRendererTestHelpers
|
|
47
120
|
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: wheneverd
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.5.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- bigcurl
|
|
@@ -32,6 +32,7 @@ extra_rdoc_files: []
|
|
|
32
32
|
files:
|
|
33
33
|
- ".gitignore"
|
|
34
34
|
- ".rubocop.yml"
|
|
35
|
+
- ".ruby-version"
|
|
35
36
|
- ".yardopts"
|
|
36
37
|
- AGENTS.md
|
|
37
38
|
- CHANGELOG.md
|
|
@@ -66,27 +67,40 @@ files:
|
|
|
66
67
|
- lib/wheneverd/dsl/errors.rb
|
|
67
68
|
- lib/wheneverd/dsl/loader.rb
|
|
68
69
|
- lib/wheneverd/dsl/period_parser.rb
|
|
70
|
+
- lib/wheneverd/dsl/period_strategy.rb
|
|
71
|
+
- lib/wheneverd/dsl/period_strategy/array_strategy.rb
|
|
72
|
+
- lib/wheneverd/dsl/period_strategy/base.rb
|
|
73
|
+
- lib/wheneverd/dsl/period_strategy/duration_strategy.rb
|
|
74
|
+
- lib/wheneverd/dsl/period_strategy/string_strategy.rb
|
|
75
|
+
- lib/wheneverd/dsl/period_strategy/symbol_strategy.rb
|
|
69
76
|
- lib/wheneverd/duration.rb
|
|
70
77
|
- lib/wheneverd/entry.rb
|
|
71
78
|
- lib/wheneverd/errors.rb
|
|
72
79
|
- lib/wheneverd/interval.rb
|
|
73
80
|
- lib/wheneverd/job/command.rb
|
|
74
81
|
- lib/wheneverd/schedule.rb
|
|
82
|
+
- lib/wheneverd/service.rb
|
|
75
83
|
- lib/wheneverd/systemd/analyze.rb
|
|
76
84
|
- lib/wheneverd/systemd/calendar_spec.rb
|
|
77
85
|
- lib/wheneverd/systemd/cron_parser.rb
|
|
86
|
+
- lib/wheneverd/systemd/cron_parser/dow_parser.rb
|
|
87
|
+
- lib/wheneverd/systemd/cron_parser/field_parser.rb
|
|
78
88
|
- lib/wheneverd/systemd/errors.rb
|
|
79
89
|
- lib/wheneverd/systemd/loginctl.rb
|
|
80
90
|
- lib/wheneverd/systemd/renderer.rb
|
|
81
91
|
- lib/wheneverd/systemd/systemctl.rb
|
|
82
92
|
- lib/wheneverd/systemd/time_parser.rb
|
|
93
|
+
- lib/wheneverd/systemd/unit_content_builder.rb
|
|
83
94
|
- lib/wheneverd/systemd/unit_deleter.rb
|
|
84
95
|
- lib/wheneverd/systemd/unit_lister.rb
|
|
85
96
|
- lib/wheneverd/systemd/unit_namer.rb
|
|
97
|
+
- lib/wheneverd/systemd/unit_path_utils.rb
|
|
86
98
|
- lib/wheneverd/systemd/unit_writer.rb
|
|
99
|
+
- lib/wheneverd/trigger/base.rb
|
|
87
100
|
- lib/wheneverd/trigger/boot.rb
|
|
88
101
|
- lib/wheneverd/trigger/calendar.rb
|
|
89
102
|
- lib/wheneverd/trigger/interval.rb
|
|
103
|
+
- lib/wheneverd/validation.rb
|
|
90
104
|
- lib/wheneverd/version.rb
|
|
91
105
|
- test/cli_activate_test.rb
|
|
92
106
|
- test/cli_current_test.rb
|
|
@@ -142,7 +156,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
142
156
|
- !ruby/object:Gem::Version
|
|
143
157
|
version: '0'
|
|
144
158
|
requirements: []
|
|
145
|
-
rubygems_version: 4.0.
|
|
159
|
+
rubygems_version: 4.0.11
|
|
146
160
|
specification_version: 4
|
|
147
161
|
summary: Wheneverd is to systemd timers what whenever is to cron.
|
|
148
162
|
test_files: []
|