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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 448f6e4c937fdc568cf15f2bd0c488f89c2d65fc83396f5cec02f7b8cdb791a7
4
- data.tar.gz: 0d48b483b1dfc7991398ce6b499426b21657466c62588235ed155ab3acf7fecd
3
+ metadata.gz: 890642297383c9a1dab1d88aa7700c2799474eb4dc9ab980b8a7933cb66600bb
4
+ data.tar.gz: 211049d5fff3cd653a350e1acd68fb61da25f6553c7efbf86b02158025dc79e8
5
5
  SHA512:
6
- metadata.gz: 05a39822bd08957051d973ab2ca2fe1f39a976962bcb73e4381831b2c18660c9880f0034ba491749618601429494bb53ba1877bc07501d495f2f3304c3b1c139
7
- data.tar.gz: 8a3ca786d459492a724a9cfe65e9616d009ad5ffd7982e8517a2e44ddbed3d8a6892f89aef879fc8a8f6369d18c3d44c69a8d606135eedeb7cc2e2f9b141d27c
6
+ metadata.gz: bdc85050dfcc1bfafb3c75978e23643dc6ce11101bbda12fcccfbe49da5d748a53755ea74c77786997f7b7db92fdf4f6e8835829f869846f9f6862f7290d35d8
7
+ data.tar.gz: 2cca48030792406231b510547a1408e185c0da35cca308e99ac0a24f528717ca3518252bad2ff03d9cf3b7d51931780a766c757c1770aeef3c4023454e2683d5
@@ -16,15 +16,11 @@ jobs:
16
16
  runs-on: ubuntu-latest
17
17
  strategy:
18
18
  matrix:
19
- ruby_version: ['2.5.x', '2.6.x', '2.7.x']
19
+ ruby_version: ['3.1', '3.2', '3.3']
20
20
  steps:
21
21
  - uses: actions/checkout@v2
22
- - name: Set up Ruby ${{ matrix.ruby_version }}
23
- uses: actions/setup-ruby@v1
22
+ - uses: ruby/setup-ruby@v1
24
23
  with:
25
24
  ruby-version: ${{ matrix.ruby_version }}
26
- - name: Run spec
27
- run: |
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-deifinition oneoff-application:2
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. Defualt: EC2
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 as many as `every` block. Each event has as many targets as there are commands in the block.
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 # scheduled task (identifier_68237a3b152a6c44359e1cf5cd8e7cf0def303d7)
93
- rake "hoge:run" # target for `identifier_68237a3b152a6c44359e1cf5cd8e7cf0def303d7`
94
- command "awesome" # target for `identifier_68237a3b152a6c44359e1cf5cd8e7cf0def303d7`
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
- ## Compatible with Whenever
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
 
@@ -29,4 +29,5 @@ Gem::Specification.new do |spec|
29
29
  spec.add_dependency "aws-sdk-iam", "~> 1.0"
30
30
  spec.add_dependency "chronic", "~> 0.10"
31
31
  spec.add_dependency "retryable", "~> 3.0"
32
+ spec.add_dependency "rexml", ">= 0"
32
33
  end
data/exe/elastic_whenever CHANGED
@@ -2,4 +2,4 @@
2
2
 
3
3
  require "elastic_whenever"
4
4
 
5
- exit ElasticWhenever::CLI.run(ARGV)
5
+ exit ElasticWhenever::CLI.new(ARGV).run
@@ -3,123 +3,149 @@ module ElasticWhenever
3
3
  SUCCESS_EXIT_CODE = 0
4
4
  ERROR_EXIT_CODE = 1
5
5
 
6
- class << self
7
- def run(args)
8
- option = Option.new(args)
9
- case option.mode
10
- when Option::DRYRUN_MODE
11
- option.validate!
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
- SUCCESS_EXIT_CODE
35
- rescue Aws::Errors::MissingRegionError
36
- Logger.instance.fail("missing region error occurred; please use `--region` option or export `AWS_REGION` environment variable.")
37
- ERROR_EXIT_CODE
38
- rescue Aws::Errors::MissingCredentialsError
39
- 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.")
40
- ERROR_EXIT_CODE
41
- rescue OptionParser::MissingArgument,
42
- Option::InvalidOptionException,
43
- Task::Target::InvalidContainerException => exn
44
-
45
- Logger.instance.fail(exn.message)
46
- ERROR_EXIT_CODE
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
- private
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
- def update_tasks(option, dry_run:)
52
- schedule = Schedule.new(option.schedule_file, option.verbose, option.variables)
50
+ Logger.instance.fail(exn.message)
51
+ ERROR_EXIT_CODE
52
+ end
53
53
 
54
- cluster = Task::Cluster.new(option, option.cluster)
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
- clear_tasks(option) unless dry_run
62
- schedule.tasks.each do |task|
63
- rule = Task::Rule.convert(option, task)
64
- targets = task.commands.map do |command|
65
- Task::Target.new(
66
- option,
67
- cluster: cluster,
68
- definition: definition,
69
- container: option.container,
70
- commands: command,
71
- rule: rule,
72
- role: role,
73
- )
74
- end
75
-
76
- if dry_run
77
- print_task(rule, targets)
78
- else
79
- begin
80
- rule.create
81
- rescue Aws::CloudWatchEvents::Errors::ValidationException => exn
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
- def clear_tasks(option)
91
- Task::Rule.fetch(option).each(&:delete)
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
- def list_tasks(option)
95
- Task::Rule.fetch(option).each do |rule|
96
- targets = Task::Target.fetch(option, rule)
97
- print_task(rule, targets)
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
- def print_version
102
- puts "Elastic Whenever v#{ElasticWhenever::VERSION}"
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
- def print_task(rule, targets)
106
- targets.each do |target|
107
- puts "#{rule.expression} #{target.cluster.name} #{target.definition.name} #{target.container} #{target.commands.join(" ")}"
108
- puts
109
- end
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
- def with_concurrent_modification_handling
113
- Retryable.retryable(
114
- tries: 5,
115
- on: Aws::CloudWatchEvents::Errors::ConcurrentModificationException,
116
- sleep: lambda { |_n| rand(1..10) },
117
- ) do |retries, exn|
118
- if retries > 0
119
- Logger.instance.warn("concurrent modification detected; Retrying...")
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', 'Clear and create scheduled tasks by schedule file') do |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-deifinition oneoff-application:2') do |definition|
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. Defualt: EC2') do |launch_type|
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 profile
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
@@ -4,7 +4,7 @@ module ElasticWhenever
4
4
  class InvalidInputException < StandardError; end
5
5
 
6
6
  def initialize(option, name)
7
- @client = Aws::ECS::Client.new(option.aws_config)
7
+ @client = option.ecs_client
8
8
  @cluster = client.describe_clusters(
9
9
  clusters: [name]
10
10
  ).clusters.first
@@ -2,7 +2,8 @@ module ElasticWhenever
2
2
  class Task
3
3
  class Definition
4
4
  def initialize(option, family)
5
- @client = Aws::ECS::Client.new(option.aws_config)
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 = Aws::IAM::Client.new(option.aws_config)
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 = Aws::CloudWatchEvents::Client.new(option.aws_config)
13
- client.list_rules(name_prefix: option.identifier).rules.map do |rule|
14
- self.new(
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, task)
32
+ def self.convert(option, expression, command)
25
33
  self.new(
26
34
  option,
27
- name: rule_name(option.identifier, task.expression, task.commands),
28
- expression: task.expression,
29
- description: rule_description(option.identifier, task.expression, task.commands)
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 = Aws::CloudWatchEvents::Client.new(option.aws_config)
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(identifier, expression, commands)
64
- "#{identifier}_#{Digest::SHA1.hexdigest([expression, commands.map { |command| command.join("-") }.join("-")].join("-"))}"
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, commands)
68
- "#{identifier} - #{expression} - #{commands.map { |command| command.join(" ") }.join(" - ")}"
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 = Aws::CloudWatchEvents::Client.new(option.aws_config)
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 = Aws::CloudWatchEvents::Client.new(option.aws_config)
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
@@ -1,3 +1,3 @@
1
1
  module ElasticWhenever
2
- VERSION = "0.6.1"
2
+ VERSION = "1.0.0"
3
3
  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.6.1
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: 2020-11-08 00:00:00.000000000 Z
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.1.2
189
+ rubygems_version: 3.4.10
176
190
  signing_key:
177
191
  specification_version: 4
178
192
  summary: Manage ECS Scheduled Tasks like Whenever