lambda_whenever 0.1.1 → 0.3.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/lib/lambda_whenever/cli.rb +26 -0
- data/lib/lambda_whenever/event_bridge_scheduler.rb +72 -10
- data/lib/lambda_whenever/option.rb +5 -1
- data/lib/lambda_whenever/task.rb +6 -2
- data/lib/lambda_whenever/version.rb +1 -1
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5f129b23aca4d25d6b995c09a9d1644a6d8f510f2a620996168ca2eff79a292d
|
4
|
+
data.tar.gz: ec91d0520bb573d4f630bfe8b07fc7fbe4a15b41930ea6aaeb146046c4ae24e9
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 900fd11c932e0620aea048f497be0b59655e45422953794fa13fc0ae149ad0662d9832de3283ede985ffec566ec8eacc74c01c2f20991621cdd5f1f7a75933f1
|
7
|
+
data.tar.gz: df722523f0dca951232658b021f4ad81cf9d320fabd0fedcc866a04a407a59c69210df9ac4431ba01d8d9451251dcc44c879ba2f921924961714ed6deb78074d
|
data/lib/lambda_whenever/cli.rb
CHANGED
@@ -26,6 +26,12 @@ module LambdaWhenever
|
|
26
26
|
update_eb_schedules
|
27
27
|
end
|
28
28
|
Logger.instance.log("write", "scheduled tasks updated")
|
29
|
+
when Option::SYNC_MODE
|
30
|
+
option.validate!
|
31
|
+
with_concurrent_modification_handling do
|
32
|
+
sync_eb_schedules
|
33
|
+
end
|
34
|
+
Logger.instance.log("write", "scheduled tasks updated")
|
29
35
|
when Option::CLEAR_MODE
|
30
36
|
with_concurrent_modification_handling do
|
31
37
|
clear_tasks
|
@@ -68,6 +74,26 @@ module LambdaWhenever
|
|
68
74
|
end
|
69
75
|
end
|
70
76
|
|
77
|
+
def sync_eb_schedules
|
78
|
+
schedule = Schedule.new(option.schedule_file, option.verbose, option.variables)
|
79
|
+
scheduler = EventBridgeScheduler.new(option.scheduler_client, schedule.timezone)
|
80
|
+
|
81
|
+
scheduler.create_schedule_group(option.scheduler_group)
|
82
|
+
|
83
|
+
current_schedules = scheduler.list_schedules(option.scheduler_group)
|
84
|
+
lambda_arn = TargetLambda.fetch_arn(option.lambda_name, option.lambda_client)
|
85
|
+
desired_schedules = schedule.tasks.map do |task|
|
86
|
+
target = TargetLambda.new(arn: lambda_arn, task: task)
|
87
|
+
{
|
88
|
+
name: scheduler.schedule_name(task, option),
|
89
|
+
target: target,
|
90
|
+
task: task
|
91
|
+
}
|
92
|
+
end
|
93
|
+
|
94
|
+
scheduler.sync_schedules(desired_schedules, current_schedules, option)
|
95
|
+
end
|
96
|
+
|
71
97
|
def clear_tasks
|
72
98
|
scheduler = EventBridgeScheduler.new(option.scheduler_client)
|
73
99
|
scheduler.clean_up_schedules(option.scheduler_group)
|
@@ -13,17 +13,60 @@ module LambdaWhenever
|
|
13
13
|
def list_schedules(group_name)
|
14
14
|
Logger.instance.message("Schedules in group '#{group_name}':")
|
15
15
|
response = @scheduler_client.list_schedules({ group_name: group_name })
|
16
|
-
response.schedules.
|
16
|
+
response.schedules.map do |schedule|
|
17
17
|
detail = @scheduler_client.get_schedule({ group_name: group_name, name: schedule.name })
|
18
|
-
|
18
|
+
Logger.instance.message "#{schedule.state} #{schedule.name} #{detail.schedule_expression} #{detail.description}"
|
19
|
+
{
|
20
|
+
name: schedule.name,
|
21
|
+
state: schedule.state,
|
22
|
+
expression: detail.schedule_expression,
|
23
|
+
description: detail.description
|
24
|
+
}
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def sync_schedules(desired_schedules, current_schedules, option)
|
29
|
+
desired_names = desired_schedules.map { |s| s[:name] }.to_set
|
30
|
+
current_schedules_hash = current_schedules.to_h do |schedule|
|
31
|
+
[schedule[:name], schedule]
|
32
|
+
end
|
33
|
+
current_names = current_schedules_hash.keys.to_set
|
34
|
+
to_delete = current_names - desired_names
|
35
|
+
|
36
|
+
to_add, to_update = desired_schedules.each_with_object([[], []]) do |desired, (add, update)|
|
37
|
+
current = current_schedules_hash[desired[:name]]
|
38
|
+
if current.nil?
|
39
|
+
add << desired
|
40
|
+
elsif schedules_differ?(current, desired, option)
|
41
|
+
update << desired
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
Logger.instance.message("Deleting #{to_delete.length} schedules...")
|
46
|
+
to_delete.each do |name|
|
47
|
+
Logger.instance.message "delete schedule: #{name}"
|
48
|
+
delete_schedule(name, option.scheduler_group)
|
49
|
+
end
|
50
|
+
|
51
|
+
Logger.instance.message("Creating #{to_add.length} schedules...")
|
52
|
+
to_add.each do |schedule|
|
53
|
+
Logger.instance.message "create schedule: #{schedule[:name]}"
|
54
|
+
create_schedule(schedule[:target], option)
|
55
|
+
end
|
56
|
+
|
57
|
+
Logger.instance.message("Updating #{to_update.length} schedules...")
|
58
|
+
to_update.each do |desired|
|
59
|
+
Logger.instance.message("Updating schedule: #{desired[:name]}")
|
60
|
+
delete_schedule(desired[:name], option.scheduler_group)
|
61
|
+
create_schedule(desired[:target], option)
|
19
62
|
end
|
20
63
|
end
|
21
64
|
|
22
65
|
def create_schedule_group(group_name)
|
23
66
|
@scheduler_client.create_schedule_group({ name: group_name })
|
24
|
-
|
67
|
+
Logger.instance.message "Schedule group '#{group_name}' created."
|
25
68
|
rescue Aws::Scheduler::Errors::ConflictException
|
26
|
-
|
69
|
+
Logger.instance.message "Schedule group '#{group_name}' already exists."
|
27
70
|
end
|
28
71
|
|
29
72
|
# https://docs.aws.amazon.com/sdk-for-ruby/v3/api/Aws/Scheduler/Client.html#create_schedule-instance_method
|
@@ -49,7 +92,8 @@ module LambdaWhenever
|
|
49
92
|
end
|
50
93
|
|
51
94
|
def schedule_name(task, option)
|
52
|
-
Digest::SHA1.hexdigest([option.key, task.expression, *task.commands].join("-"))
|
95
|
+
input = "#{task.name}-#{Digest::SHA1.hexdigest([option.key, task.expression, *task.commands].join("-"))}"
|
96
|
+
sanitize_and_trim(input)
|
53
97
|
end
|
54
98
|
|
55
99
|
def schedule_description(task)
|
@@ -59,13 +103,31 @@ module LambdaWhenever
|
|
59
103
|
def clean_up_schedules(schedule_group)
|
60
104
|
response = @scheduler_client.list_schedules({ group_name: schedule_group })
|
61
105
|
response.schedules.each do |schedule|
|
62
|
-
|
63
|
-
name: schedule.name,
|
64
|
-
group_name: schedule_group
|
65
|
-
})
|
106
|
+
delete_schedule(schedule.name, schedule_group)
|
66
107
|
end
|
108
|
+
end
|
109
|
+
|
110
|
+
private
|
111
|
+
|
112
|
+
def sanitize_and_trim(input)
|
113
|
+
sanitized = input.gsub(/[^a-zA-Z0-9\-._]/, "_")
|
114
|
+
sanitized[0, 64]
|
115
|
+
end
|
116
|
+
|
117
|
+
def schedules_differ?(current, desired, option)
|
118
|
+
task = desired[:target].task
|
119
|
+
current[:expression] != task.expression ||
|
120
|
+
current[:description] != schedule_description(task) ||
|
121
|
+
current[:state] != option.rule_state
|
122
|
+
end
|
123
|
+
|
124
|
+
def delete_schedule(name, group_name)
|
125
|
+
@scheduler_client.delete_schedule({
|
126
|
+
name: name,
|
127
|
+
group_name: group_name
|
128
|
+
})
|
67
129
|
rescue Aws::Scheduler::Errors::ResourceNotFoundException
|
68
|
-
|
130
|
+
Logger.instance.message("Schedule '#{name}' does not exist.")
|
69
131
|
end
|
70
132
|
end
|
71
133
|
end
|
@@ -10,6 +10,7 @@ module LambdaWhenever
|
|
10
10
|
CLEAR_MODE = 3
|
11
11
|
LIST_MODE = 4
|
12
12
|
PRINT_VERSION_MODE = 5
|
13
|
+
SYNC_MODE = 6
|
13
14
|
|
14
15
|
attr_reader :mode, :verbose, :variables, :schedule_file, :iam_role, :rule_state,
|
15
16
|
:lambda_name, :scheduler_group
|
@@ -31,9 +32,12 @@ module LambdaWhenever
|
|
31
32
|
opts.on("--dryrun", "dry-run") do
|
32
33
|
@mode = DRYRUN_MODE
|
33
34
|
end
|
34
|
-
opts.on("--update", "
|
35
|
+
opts.on("--update", "clear and create schedules") do
|
35
36
|
@mode = UPDATE_MODE
|
36
37
|
end
|
38
|
+
opts.on("--sync", "Creates and deletes tasks as needed by schedule file") do
|
39
|
+
@mode = SYNC_MODE
|
40
|
+
end
|
37
41
|
opts.on("-c", "--clear", "Clear scheduled tasks") do
|
38
42
|
@mode = CLEAR_MODE
|
39
43
|
end
|
data/lib/lambda_whenever/task.rb
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
|
3
3
|
module LambdaWhenever
|
4
4
|
class Task
|
5
|
-
attr_reader :commands, :expression
|
5
|
+
attr_reader :commands, :expression, :name
|
6
6
|
|
7
7
|
def initialize(environment, verbose, bundle_command, expression)
|
8
8
|
@environment = environment
|
@@ -10,6 +10,7 @@ module LambdaWhenever
|
|
10
10
|
@bundle_command = bundle_command.split(" ")
|
11
11
|
@expression = expression
|
12
12
|
@commands = []
|
13
|
+
@name = ""
|
13
14
|
end
|
14
15
|
|
15
16
|
def command(task)
|
@@ -17,14 +18,17 @@ module LambdaWhenever
|
|
17
18
|
end
|
18
19
|
|
19
20
|
def rake(task)
|
20
|
-
@
|
21
|
+
@name = task
|
22
|
+
@commands << [*@bundle_command, "rake", task, *@verbose_mode]
|
21
23
|
end
|
22
24
|
|
23
25
|
def runner(src)
|
26
|
+
@name = src
|
24
27
|
@commands << [@bundle_command, "rails", "runner", "-e", @environment, src].flatten
|
25
28
|
end
|
26
29
|
|
27
30
|
def script(script)
|
31
|
+
@name = script
|
28
32
|
@commands << [@bundle_command, "script/#{script}"].flatten
|
29
33
|
end
|
30
34
|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: lambda_whenever
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- toshichanapp
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-
|
11
|
+
date: 2024-12-02 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rake
|
@@ -224,7 +224,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
224
224
|
- !ruby/object:Gem::Version
|
225
225
|
version: '0'
|
226
226
|
requirements: []
|
227
|
-
rubygems_version: 3.5.
|
227
|
+
rubygems_version: 3.5.22
|
228
228
|
signing_key:
|
229
229
|
specification_version: 4
|
230
230
|
summary: whenever for Amazon EventBridge Scheduler.
|