elastic_whenever 0.6.1 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/workflows/build.yml +4 -8
- data/CHANGELOG.md +33 -0
- data/README.md +8 -7
- data/elastic_whenever.gemspec +1 -0
- data/exe/elastic_whenever +1 -1
- data/lib/elastic_whenever/cli.rb +124 -98
- data/lib/elastic_whenever/option.rb +40 -7
- data/lib/elastic_whenever/task/cluster.rb +1 -1
- data/lib/elastic_whenever/task/definition.rb +16 -2
- data/lib/elastic_whenever/task/role.rb +1 -1
- data/lib/elastic_whenever/task/rule.rb +23 -13
- data/lib/elastic_whenever/task/target.rb +4 -4
- data/lib/elastic_whenever/version.rb +1 -1
- metadata +17 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 890642297383c9a1dab1d88aa7700c2799474eb4dc9ab980b8a7933cb66600bb
|
4
|
+
data.tar.gz: 211049d5fff3cd653a350e1acd68fb61da25f6553c7efbf86b02158025dc79e8
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: bdc85050dfcc1bfafb3c75978e23643dc6ce11101bbda12fcccfbe49da5d748a53755ea74c77786997f7b7db92fdf4f6e8835829f869846f9f6862f7290d35d8
|
7
|
+
data.tar.gz: 2cca48030792406231b510547a1408e185c0da35cca308e99ac0a24f528717ca3518252bad2ff03d9cf3b7d51931780a766c757c1770aeef3c4023454e2683d5
|
data/.github/workflows/build.yml
CHANGED
@@ -16,15 +16,11 @@ jobs:
|
|
16
16
|
runs-on: ubuntu-latest
|
17
17
|
strategy:
|
18
18
|
matrix:
|
19
|
-
ruby_version: ['
|
19
|
+
ruby_version: ['3.1', '3.2', '3.3']
|
20
20
|
steps:
|
21
21
|
- uses: actions/checkout@v2
|
22
|
-
-
|
23
|
-
uses: actions/setup-ruby@v1
|
22
|
+
- uses: ruby/setup-ruby@v1
|
24
23
|
with:
|
25
24
|
ruby-version: ${{ matrix.ruby_version }}
|
26
|
-
|
27
|
-
|
28
|
-
gem install bundler
|
29
|
-
bundle install --jobs 4 --retry 3
|
30
|
-
bundle exec rake
|
25
|
+
bundler-cache: true
|
26
|
+
- run: bundle exec rake
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,36 @@
|
|
1
|
+
## v1.0.0 (2024-01-07)
|
2
|
+
|
3
|
+
Although this is a major version release, there are no notable incompatibilities. This means that the current behavior is stable enough that no major future changes are planned at this time.
|
4
|
+
|
5
|
+
### Enhancements
|
6
|
+
|
7
|
+
- [#69](https://github.com/wata727/elastic_whenever/pull/69): Improve profile support ([@mfittko](https://github.com/mfittko))
|
8
|
+
- Previously, a profile passed with the `--profile` flag was always used only for shared credentials, and could not be used to switch profiles for credentials issued by IAM Identity Center, etc.
|
9
|
+
- With this change, the passed profile will be used correctly to other credentials as well.
|
10
|
+
|
11
|
+
### Chores
|
12
|
+
|
13
|
+
- [#60](https://github.com/wata727/elastic_whenever/pull/60) [#64](https://github.com/wata727/elastic_whenever/pull/64) [#68](https://github.com/wata727/elastic_whenever/pull/68): CI against Ruby 3.1, 3.2, 3.3
|
14
|
+
- [#62](https://github.com/wata727/elastic_whenever/pull/62): fix small typo ([@kijimaD](https://github.com/kijimaD))
|
15
|
+
- [#65](https://github.com/wata727/elastic_whenever/pull/65): fix/typos-documentation ([@jotolo](https://github.com/jotolo))
|
16
|
+
|
17
|
+
## v0.7.0 (2021-09-25)
|
18
|
+
|
19
|
+
This release contains a major change to the behavior when updating tasks. In most cases, this change has no effect, but be aware of the change in behavior when omitting a revision of the task definition. In particular, if you are building a deployment workflow where the update timing of task definitions and the update timing of scheduled tasks are different, the revisions that are executed may be different.
|
20
|
+
|
21
|
+
### Breaking Changes
|
22
|
+
|
23
|
+
- [#57](https://github.com/wata727/elastic_whenever/pull/57): Selective Updates ([@HistoireDeBabar](https://github.com/HistoireDeBabar))
|
24
|
+
- Previously, Elastic Whenever recreates all scheduled tasks after deleting all tasks when updating tasks. However, in this case, there is a risk that frequently invoked tasks will not be executed, so this change now creates/deletes only those tasks that have changed.
|
25
|
+
- Due to this change, the naming convention for scheduled tasks has changed. When updating from v0.6, all rules will be deleted and recreated due to different naming conventions, and the behavior will be the same as before. After that, the task will not change if the names are the same.
|
26
|
+
- The breaking change is that the behavior when omitting a revision of a task definition has changed. Previously, when you created a task, you resolved the latest revision at that time, so even if the task definition was updated, the revision that was executed was always the same. In v0.7 and later, revisions are not resolved when you created a task, so the latest revision is always adopted.
|
27
|
+
|
28
|
+
### Chores
|
29
|
+
|
30
|
+
- [#55](https://github.com/wata727/elastic_whenever/pull/55): CI against Ruby 3.0
|
31
|
+
- [#56](https://github.com/wata727/elastic_whenever/pull/56): Add the rexml dependency explictly
|
32
|
+
- [#58](https://github.com/wata727/elastic_whenever/pull/58): Fix typo
|
33
|
+
|
1
34
|
## v0.6.1 (2020-11-08)
|
2
35
|
|
3
36
|
### BugFixes
|
data/README.md
CHANGED
@@ -34,9 +34,9 @@ Usage: elastic_whenever [options]
|
|
34
34
|
-s, --set variables Example: --set 'environment=staging'
|
35
35
|
--cluster cluster ECS cluster to run tasks
|
36
36
|
--task-definition task_definition
|
37
|
-
Task definition name, If omit a revision, use the latest revision of the family automatically. Example: --task-
|
37
|
+
Task definition name, If omit a revision, use the latest revision of the family automatically. Example: --task-definition oneoff-application:2
|
38
38
|
--container container Container name defined in the task definition
|
39
|
-
--launch-type launch_type Launch type. EC2 or FARGATE.
|
39
|
+
--launch-type launch_type Launch type. EC2 or FARGATE. Default: EC2
|
40
40
|
--assign-public-ip Assign a public IP. Default: DISABLED (FARGATE only)
|
41
41
|
--security-groups groups Example: --security-groups 'sg-2c503655,sg-72f0cb0a' (FARGATE only)
|
42
42
|
--subnets subnets Example: --subnets 'subnet-4973d63f,subnet-45827d1d' (FARGATE only)
|
@@ -86,12 +86,13 @@ end
|
|
86
86
|
Especially, `@environment` defaults to `"production"`.
|
87
87
|
|
88
88
|
## How it works
|
89
|
-
Elastic Whenever creates CloudWatch Events
|
89
|
+
Elastic Whenever creates CloudWatch Events for every command. Each rule has a one to one mapping to a target.
|
90
|
+
for example, the following input will generate two Rules each with one Target.
|
90
91
|
|
91
92
|
```ruby
|
92
|
-
every '0 0 * * *' do
|
93
|
-
rake "hoge:run"
|
94
|
-
command "awesome"
|
93
|
+
every '0 0 * * *' do
|
94
|
+
rake "hoge:run"
|
95
|
+
command "awesome"
|
95
96
|
end
|
96
97
|
```
|
97
98
|
|
@@ -99,7 +100,7 @@ The scheduled task's name is a digest value calculated from an identifier, comma
|
|
99
100
|
|
100
101
|
NOTE: You should not use the same identifier across different clusters because CloudWatch Events rule names are unique across all clusters.
|
101
102
|
|
102
|
-
##
|
103
|
+
## Compatibility with Whenever
|
103
104
|
### `job_type`
|
104
105
|
Whenever supports custom job type with `job_type` method, but Elastic Whenever doesn't support it.
|
105
106
|
|
data/elastic_whenever.gemspec
CHANGED
data/exe/elastic_whenever
CHANGED
data/lib/elastic_whenever/cli.rb
CHANGED
@@ -3,123 +3,149 @@ module ElasticWhenever
|
|
3
3
|
SUCCESS_EXIT_CODE = 0
|
4
4
|
ERROR_EXIT_CODE = 1
|
5
5
|
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
update_tasks(option, dry_run: true)
|
13
|
-
Logger.instance.message("Above is your schedule file converted to scheduled tasks; your scheduled tasks was not updated.")
|
14
|
-
Logger.instance.message("Run `elastic_whenever --help' for more options.")
|
15
|
-
when Option::UPDATE_MODE
|
16
|
-
option.validate!
|
17
|
-
with_concurrent_modification_handling do
|
18
|
-
update_tasks(option, dry_run: false)
|
19
|
-
end
|
20
|
-
Logger.instance.log("write", "scheduled tasks updated")
|
21
|
-
when Option::CLEAR_MODE
|
22
|
-
with_concurrent_modification_handling do
|
23
|
-
clear_tasks(option)
|
24
|
-
end
|
25
|
-
Logger.instance.log("write", "scheduled tasks cleared")
|
26
|
-
when Option::LIST_MODE
|
27
|
-
list_tasks(option)
|
28
|
-
Logger.instance.message("Above is your scheduled tasks.")
|
29
|
-
Logger.instance.message("Run `elastic_whenever --help` for more options.")
|
30
|
-
when Option::PRINT_VERSION_MODE
|
31
|
-
print_version
|
32
|
-
end
|
6
|
+
attr_reader :args, :option
|
7
|
+
|
8
|
+
def initialize(args)
|
9
|
+
@args = args
|
10
|
+
@option = Option.new(args)
|
11
|
+
end
|
33
12
|
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
Logger.instance.
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
13
|
+
def run
|
14
|
+
case option.mode
|
15
|
+
when Option::DRYRUN_MODE
|
16
|
+
option.validate!
|
17
|
+
update_tasks(dry_run: true)
|
18
|
+
Logger.instance.message("Above is your schedule file converted to scheduled tasks; your scheduled tasks was not updated.")
|
19
|
+
Logger.instance.message("Run `elastic_whenever --help' for more options.")
|
20
|
+
when Option::UPDATE_MODE
|
21
|
+
option.validate!
|
22
|
+
with_concurrent_modification_handling do
|
23
|
+
update_tasks(dry_run: false)
|
24
|
+
end
|
25
|
+
Logger.instance.log("write", "scheduled tasks updated")
|
26
|
+
when Option::CLEAR_MODE
|
27
|
+
with_concurrent_modification_handling do
|
28
|
+
clear_tasks
|
29
|
+
end
|
30
|
+
Logger.instance.log("write", "scheduled tasks cleared")
|
31
|
+
when Option::LIST_MODE
|
32
|
+
list_tasks
|
33
|
+
Logger.instance.message("Above is your scheduled tasks.")
|
34
|
+
Logger.instance.message("Run `elastic_whenever --help` for more options.")
|
35
|
+
when Option::PRINT_VERSION_MODE
|
36
|
+
print_version
|
47
37
|
end
|
48
38
|
|
49
|
-
|
39
|
+
SUCCESS_EXIT_CODE
|
40
|
+
rescue Aws::Errors::MissingRegionError
|
41
|
+
Logger.instance.fail("missing region error occurred; please use `--region` option or export `AWS_REGION` environment variable.")
|
42
|
+
ERROR_EXIT_CODE
|
43
|
+
rescue Aws::Errors::MissingCredentialsError => e
|
44
|
+
Logger.instance.fail("missing credential error occurred; please specify it with arguments, use shared credentials, or export `AWS_ACCESS_KEY_ID` and `AWS_SECRET_ACCESS_KEY` environment variable")
|
45
|
+
ERROR_EXIT_CODE
|
46
|
+
rescue OptionParser::MissingArgument,
|
47
|
+
Option::InvalidOptionException,
|
48
|
+
Task::Target::InvalidContainerException => exn
|
50
49
|
|
51
|
-
|
52
|
-
|
50
|
+
Logger.instance.fail(exn.message)
|
51
|
+
ERROR_EXIT_CODE
|
52
|
+
end
|
53
53
|
|
54
|
-
|
55
|
-
definition = Task::Definition.new(option, option.task_definition)
|
56
|
-
role = Task::Role.new(option)
|
57
|
-
if !role.exists? && !dry_run
|
58
|
-
role.create
|
59
|
-
end
|
54
|
+
private
|
60
55
|
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
Logger.instance.warn("#{exn.message} Ignore this task: name=#{rule.name} expression=#{rule.expression}")
|
83
|
-
next
|
84
|
-
end
|
85
|
-
targets.each(&:create)
|
86
|
-
end
|
56
|
+
def update_tasks(dry_run:)
|
57
|
+
schedule = Schedule.new(option.schedule_file, option.verbose, option.variables)
|
58
|
+
|
59
|
+
cluster = Task::Cluster.new(option, option.cluster)
|
60
|
+
definition = Task::Definition.new(option, option.task_definition)
|
61
|
+
role = Task::Role.new(option)
|
62
|
+
if !role.exists? && !dry_run
|
63
|
+
role.create
|
64
|
+
end
|
65
|
+
|
66
|
+
targets = schedule.tasks.map do |task|
|
67
|
+
task.commands.map do |command|
|
68
|
+
Task::Target.new(
|
69
|
+
option,
|
70
|
+
cluster: cluster,
|
71
|
+
definition: definition,
|
72
|
+
container: option.container,
|
73
|
+
commands: command,
|
74
|
+
rule: Task::Rule.convert(option, task.expression, command),
|
75
|
+
role: role,
|
76
|
+
)
|
87
77
|
end
|
78
|
+
end.flatten
|
79
|
+
|
80
|
+
if dry_run
|
81
|
+
print_task(targets)
|
82
|
+
else
|
83
|
+
create_missing_rules_from_targets(targets)
|
84
|
+
delete_unused_rules_from_targets(targets)
|
88
85
|
end
|
86
|
+
end
|
87
|
+
|
88
|
+
def remote_rules
|
89
|
+
Task::Rule.fetch(option)
|
90
|
+
end
|
89
91
|
|
90
|
-
|
91
|
-
|
92
|
+
# Creates a rule but only persists the rule remotely if it does not exist
|
93
|
+
def create_missing_rules_from_targets(targets)
|
94
|
+
cached_remote_rules = remote_rules
|
95
|
+
targets.each do |target|
|
96
|
+
exists = cached_remote_rules.any? do |remote_rule|
|
97
|
+
target.rule.name == remote_rule.name
|
98
|
+
end
|
99
|
+
|
100
|
+
unless exists
|
101
|
+
target.rule.create
|
102
|
+
target.create
|
103
|
+
end
|
92
104
|
end
|
105
|
+
end
|
93
106
|
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
107
|
+
def delete_unused_rules_from_targets(targets)
|
108
|
+
remote_rules.each do |remote_rule|
|
109
|
+
rule_exists_in_schedule = targets.any? do |target|
|
110
|
+
target.rule.name == remote_rule.name
|
98
111
|
end
|
112
|
+
|
113
|
+
remote_rule.delete unless rule_exists_in_schedule
|
99
114
|
end
|
115
|
+
end
|
100
116
|
|
101
|
-
|
102
|
-
|
117
|
+
def clear_tasks
|
118
|
+
Task::Rule.fetch(option).each(&:delete)
|
119
|
+
end
|
120
|
+
|
121
|
+
def list_tasks
|
122
|
+
Task::Rule.fetch(option).each do |rule|
|
123
|
+
targets = Task::Target.fetch(option, rule)
|
124
|
+
print_task(targets)
|
103
125
|
end
|
126
|
+
end
|
104
127
|
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
128
|
+
def print_version
|
129
|
+
puts "Elastic Whenever v#{ElasticWhenever::VERSION}"
|
130
|
+
end
|
131
|
+
|
132
|
+
def print_task(targets)
|
133
|
+
targets.each do |target|
|
134
|
+
puts "#{target.rule.expression} #{target.cluster.name} #{target.definition.name} #{target.container} #{target.commands.join(" ")}"
|
135
|
+
puts
|
110
136
|
end
|
137
|
+
end
|
111
138
|
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
end
|
121
|
-
yield
|
139
|
+
def with_concurrent_modification_handling
|
140
|
+
Retryable.retryable(
|
141
|
+
tries: 5,
|
142
|
+
on: Aws::CloudWatchEvents::Errors::ConcurrentModificationException,
|
143
|
+
sleep: lambda { |_n| rand(1..10) },
|
144
|
+
) do |retries, exn|
|
145
|
+
if retries > 0
|
146
|
+
Logger.instance.warn("concurrent modification detected; Retrying...")
|
122
147
|
end
|
148
|
+
yield
|
123
149
|
end
|
124
150
|
end
|
125
151
|
end
|
@@ -23,6 +23,10 @@ module ElasticWhenever
|
|
23
23
|
attr_reader :schedule_file
|
24
24
|
attr_reader :iam_role
|
25
25
|
attr_reader :rule_state
|
26
|
+
attr_reader :aws_config
|
27
|
+
attr_reader :ecs_client
|
28
|
+
attr_reader :iam_client
|
29
|
+
attr_reader :cloudwatch_events_client
|
26
30
|
|
27
31
|
class InvalidOptionException < StandardError; end
|
28
32
|
|
@@ -48,7 +52,7 @@ module ElasticWhenever
|
|
48
52
|
@region = nil
|
49
53
|
|
50
54
|
OptionParser.new do |opts|
|
51
|
-
opts.on('-i', '--update identifier', '
|
55
|
+
opts.on('-i', '--update identifier', 'Creates and deletes tasks as needed by schedule file') do |identifier|
|
52
56
|
@identifier = identifier
|
53
57
|
@mode = UPDATE_MODE
|
54
58
|
end
|
@@ -74,13 +78,13 @@ module ElasticWhenever
|
|
74
78
|
opts.on('--cluster cluster', 'ECS cluster to run tasks') do |cluster|
|
75
79
|
@cluster = cluster
|
76
80
|
end
|
77
|
-
opts.on('--task-definition task_definition', 'Task definition name, If omit a revision, use the latest revision of the family automatically. Example: --task-
|
81
|
+
opts.on('--task-definition task_definition', 'Task definition name, If omit a revision, use the latest revision of the family automatically. Example: --task-definition oneoff-application:2') do |definition|
|
78
82
|
@task_definition = definition
|
79
83
|
end
|
80
84
|
opts.on('--container container', 'Container name defined in the task definition') do |container|
|
81
85
|
@container = container
|
82
86
|
end
|
83
|
-
opts.on('--launch-type launch_type', 'Launch type. EC2 or FARGATE.
|
87
|
+
opts.on('--launch-type launch_type', 'Launch type. EC2 or FARGATE. Default: EC2') do |launch_type|
|
84
88
|
@launch_type = launch_type
|
85
89
|
end
|
86
90
|
opts.on('--assign-public-ip', 'Assign a public IP. Default: DISABLED (FARGATE only)') do
|
@@ -124,15 +128,25 @@ module ElasticWhenever
|
|
124
128
|
end
|
125
129
|
end.parse(args)
|
126
130
|
|
127
|
-
@credentials = if
|
128
|
-
Aws::SharedCredentials.new(profile_name: profile)
|
129
|
-
elsif access_key && secret_key
|
131
|
+
@credentials = if access_key && secret_key
|
130
132
|
Aws::Credentials.new(access_key, secret_key)
|
131
133
|
end
|
132
134
|
end
|
133
135
|
|
134
136
|
def aws_config
|
135
|
-
{ credentials: credentials, region: region }.delete_if { |_k, v| v.nil? }
|
137
|
+
@aws_config ||= { credentials: credentials, region: region, profile: profile }.delete_if { |_k, v| v.nil? }
|
138
|
+
end
|
139
|
+
|
140
|
+
def ecs_client
|
141
|
+
@ecs_client ||= Aws::ECS::Client.new(aws_config)
|
142
|
+
end
|
143
|
+
|
144
|
+
def iam_client
|
145
|
+
@iam_client ||= Aws::IAM::Client.new(aws_config)
|
146
|
+
end
|
147
|
+
|
148
|
+
def cloudwatch_events_client
|
149
|
+
@cloudwatch_events_client ||= Aws::CloudWatchEvents::Client.new(aws_config)
|
136
150
|
end
|
137
151
|
|
138
152
|
def validate!
|
@@ -143,6 +157,25 @@ module ElasticWhenever
|
|
143
157
|
raise InvalidOptionException.new("Invalid rule state. Possible values are #{POSSIBLE_RULE_STATES.join(", ")}") unless POSSIBLE_RULE_STATES.include?(rule_state)
|
144
158
|
end
|
145
159
|
|
160
|
+
def key
|
161
|
+
Digest::SHA1.hexdigest(
|
162
|
+
[
|
163
|
+
identifier,
|
164
|
+
variables,
|
165
|
+
cluster,
|
166
|
+
task_definition,
|
167
|
+
container,
|
168
|
+
assign_public_ip,
|
169
|
+
launch_type,
|
170
|
+
platform_version,
|
171
|
+
security_groups,
|
172
|
+
subnets,
|
173
|
+
iam_role,
|
174
|
+
rule_state,
|
175
|
+
].join
|
176
|
+
)
|
177
|
+
end
|
178
|
+
|
146
179
|
private
|
147
180
|
|
148
181
|
attr_reader :profile
|
@@ -2,7 +2,8 @@ module ElasticWhenever
|
|
2
2
|
class Task
|
3
3
|
class Definition
|
4
4
|
def initialize(option, family)
|
5
|
-
@client =
|
5
|
+
@client = option.ecs_client
|
6
|
+
@family = family
|
6
7
|
@definition = client.describe_task_definition(
|
7
8
|
task_definition: family
|
8
9
|
).task_definition
|
@@ -13,7 +14,12 @@ module ElasticWhenever
|
|
13
14
|
end
|
14
15
|
|
15
16
|
def arn
|
16
|
-
definition&.task_definition_arn
|
17
|
+
arn = definition&.task_definition_arn
|
18
|
+
if family_with_revision?
|
19
|
+
arn
|
20
|
+
else
|
21
|
+
remove_revision(arn)
|
22
|
+
end
|
17
23
|
end
|
18
24
|
|
19
25
|
def containers
|
@@ -24,6 +30,14 @@ module ElasticWhenever
|
|
24
30
|
|
25
31
|
attr_reader :client
|
26
32
|
attr_reader :definition
|
33
|
+
|
34
|
+
def family_with_revision?
|
35
|
+
@family.include?(":")
|
36
|
+
end
|
37
|
+
|
38
|
+
def remove_revision(arn)
|
39
|
+
arn.split(":")[0...-1].join(":")
|
40
|
+
end
|
27
41
|
end
|
28
42
|
end
|
29
43
|
end
|
@@ -2,7 +2,7 @@ module ElasticWhenever
|
|
2
2
|
class Task
|
3
3
|
class Role
|
4
4
|
def initialize(option)
|
5
|
-
client =
|
5
|
+
client = option.iam_client
|
6
6
|
@resource = Aws::IAM::Resource.new(client: client)
|
7
7
|
@role_name = option.iam_role
|
8
8
|
@role = resource.role(@role_name)
|
@@ -8,10 +8,13 @@ module ElasticWhenever
|
|
8
8
|
|
9
9
|
class UnsupportedOptionException < StandardError; end
|
10
10
|
|
11
|
-
def self.fetch(option)
|
12
|
-
client =
|
13
|
-
|
14
|
-
|
11
|
+
def self.fetch(option, rules: [], next_token: nil)
|
12
|
+
client = option.cloudwatch_events_client
|
13
|
+
prefix = option.identifier
|
14
|
+
|
15
|
+
response = client.list_rules(name_prefix: prefix, next_token: next_token)
|
16
|
+
response.rules.each do |rule|
|
17
|
+
rules << self.new(
|
15
18
|
option,
|
16
19
|
name: rule.name,
|
17
20
|
expression: rule.schedule_expression,
|
@@ -19,14 +22,19 @@ module ElasticWhenever
|
|
19
22
|
client: client
|
20
23
|
)
|
21
24
|
end
|
25
|
+
if response.next_token.nil?
|
26
|
+
rules
|
27
|
+
else
|
28
|
+
fetch(option, rules: rules, next_token: response.next_token)
|
29
|
+
end
|
22
30
|
end
|
23
31
|
|
24
|
-
def self.convert(option,
|
32
|
+
def self.convert(option, expression, command)
|
25
33
|
self.new(
|
26
34
|
option,
|
27
|
-
name: rule_name(option
|
28
|
-
expression:
|
29
|
-
description: rule_description(option.identifier,
|
35
|
+
name: rule_name(option, expression, command),
|
36
|
+
expression: expression,
|
37
|
+
description: rule_description(option.identifier, expression, command)
|
30
38
|
)
|
31
39
|
end
|
32
40
|
|
@@ -38,12 +46,13 @@ module ElasticWhenever
|
|
38
46
|
if client != nil
|
39
47
|
@client = client
|
40
48
|
else
|
41
|
-
@client =
|
49
|
+
@client = option.cloudwatch_events_client
|
42
50
|
end
|
43
51
|
end
|
44
52
|
|
45
53
|
def create
|
46
54
|
# See https://docs.aws.amazon.com/eventbridge/latest/APIReference/API_PutRule.html#API_PutRule_RequestSyntax
|
55
|
+
Logger.instance.message("Creating Rule: #{name} #{expression}")
|
47
56
|
client.put_rule(
|
48
57
|
name: name,
|
49
58
|
schedule_expression: expression,
|
@@ -55,17 +64,18 @@ module ElasticWhenever
|
|
55
64
|
def delete
|
56
65
|
targets = client.list_targets_by_rule(rule: name).targets
|
57
66
|
client.remove_targets(rule: name, ids: targets.map(&:id)) unless targets.empty?
|
67
|
+
Logger.instance.message("Removing Rule: #{name}")
|
58
68
|
client.delete_rule(name: name)
|
59
69
|
end
|
60
70
|
|
61
71
|
private
|
62
72
|
|
63
|
-
def self.rule_name(
|
64
|
-
"#{identifier}_#{Digest::SHA1.hexdigest([expression,
|
73
|
+
def self.rule_name(option, expression, command)
|
74
|
+
"#{option.identifier}_#{Digest::SHA1.hexdigest([option.key, expression, command.join("-")].join("-"))}"
|
65
75
|
end
|
66
76
|
|
67
|
-
def self.rule_description(identifier, expression,
|
68
|
-
"#{identifier} - #{expression} - #{
|
77
|
+
def self.rule_description(identifier, expression, command)
|
78
|
+
"#{identifier} - #{expression} - #{command.join(" ")}"
|
69
79
|
end
|
70
80
|
|
71
81
|
def truncate(string, max)
|
@@ -10,11 +10,12 @@ module ElasticWhenever
|
|
10
10
|
attr_reader :platform_version
|
11
11
|
attr_reader :security_groups
|
12
12
|
attr_reader :subnets
|
13
|
+
attr_reader :rule
|
13
14
|
|
14
15
|
class InvalidContainerException < StandardError; end
|
15
16
|
|
16
17
|
def self.fetch(option, rule)
|
17
|
-
client =
|
18
|
+
client = option.cloudwatch_events_client
|
18
19
|
targets = client.list_targets_by_rule(rule: rule.name).targets
|
19
20
|
targets.map do |target|
|
20
21
|
input = JSON.parse(target.input, symbolize_names: true)
|
@@ -26,7 +27,7 @@ module ElasticWhenever
|
|
26
27
|
container: input[:containerOverrides].first[:name],
|
27
28
|
commands: input[:containerOverrides].first[:command],
|
28
29
|
rule: rule,
|
29
|
-
role: Role.new(option)
|
30
|
+
role: Role.new(option),
|
30
31
|
)
|
31
32
|
end
|
32
33
|
end
|
@@ -47,7 +48,7 @@ module ElasticWhenever
|
|
47
48
|
@platform_version = option.platform_version
|
48
49
|
@security_groups = option.security_groups
|
49
50
|
@subnets = option.subnets
|
50
|
-
@client =
|
51
|
+
@client = option.cloudwatch_events_client
|
51
52
|
end
|
52
53
|
|
53
54
|
def create
|
@@ -102,7 +103,6 @@ module ElasticWhenever
|
|
102
103
|
end
|
103
104
|
end
|
104
105
|
|
105
|
-
attr_reader :rule
|
106
106
|
attr_reader :role
|
107
107
|
attr_reader :client
|
108
108
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: elastic_whenever
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 1.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Kazuma Watanabe
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2024-01-07 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -122,6 +122,20 @@ dependencies:
|
|
122
122
|
- - "~>"
|
123
123
|
- !ruby/object:Gem::Version
|
124
124
|
version: '3.0'
|
125
|
+
- !ruby/object:Gem::Dependency
|
126
|
+
name: rexml
|
127
|
+
requirement: !ruby/object:Gem::Requirement
|
128
|
+
requirements:
|
129
|
+
- - ">="
|
130
|
+
- !ruby/object:Gem::Version
|
131
|
+
version: '0'
|
132
|
+
type: :runtime
|
133
|
+
prerelease: false
|
134
|
+
version_requirements: !ruby/object:Gem::Requirement
|
135
|
+
requirements:
|
136
|
+
- - ">="
|
137
|
+
- !ruby/object:Gem::Version
|
138
|
+
version: '0'
|
125
139
|
description: Manage ECS Scheduled Tasks like Whenever
|
126
140
|
email:
|
127
141
|
- watassbass@gmail.com
|
@@ -172,7 +186,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
172
186
|
- !ruby/object:Gem::Version
|
173
187
|
version: '0'
|
174
188
|
requirements: []
|
175
|
-
rubygems_version: 3.
|
189
|
+
rubygems_version: 3.4.10
|
176
190
|
signing_key:
|
177
191
|
specification_version: 4
|
178
192
|
summary: Manage ECS Scheduled Tasks like Whenever
|