ecs_deploy 1.0.3 → 1.0.5

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: f4d2cb1f5439702efac5ec26e9cd0c47c6225e0106c05b6f73b7860098098488
4
- data.tar.gz: 29007dc6fdeb7b64b82a0113ac78ad00025ec9693bca1b238ccca3c507065c01
3
+ metadata.gz: a9b02fc9a3cfda6288d7e00f339487fd2050b441e973d5fc7a822f9c261ea272
4
+ data.tar.gz: 9c002ab5e543435304d8d56eb88d19fceac56b4d70916f1b740176b6c3070dfc
5
5
  SHA512:
6
- metadata.gz: 42481f7631cebe62057fbd9e2c0fc6ba61ff0ee198e5d537958934df8a001c76ef5ddb6f8965c2f7db57d0098aac3b79cb43a677cdbaa95609107d29826892b8
7
- data.tar.gz: 28a2d8072e7f94a84301e0f0607fc02c469561d1f39da439cf87d3f7b64c12e301bb77a13bb96e0823870b43af36f5f35ee3e4984567ac57ebe5ae759342d61c
6
+ metadata.gz: c88b02664cb84e45ae1b14b4bbd97907d984a46d3ff6eb817f48d0ffb626f7b8c88311f1b6c5a31c8f8b27a2eaeee8ed9a06c61c93551e4b3dd1c3099d382628
7
+ data.tar.gz: 144449c85ed16c1f4dbfe8340cb6a11b1b4aee8ac55de07e2322dda654932c3bbfb12a125b39776aad3294841487b0047098dd9e65e46f2d44aec125c933b9e4
@@ -0,0 +1,23 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ pull_request:
6
+
7
+ jobs:
8
+ test:
9
+
10
+ runs-on: ubuntu-latest
11
+ strategy:
12
+ matrix:
13
+ ruby-version: ['2.5', '2.6', '2.7', '3.0', '3.1', '3.2']
14
+
15
+ steps:
16
+ - uses: actions/checkout@v3
17
+ - name: Set up Ruby
18
+ uses: ruby/setup-ruby@v1
19
+ with:
20
+ ruby-version: ${{ matrix.ruby-version }}
21
+ bundler-cache: true
22
+ - name: Run tests
23
+ run: bundle exec rake
data/CHANGELOG.md CHANGED
@@ -1,5 +1,37 @@
1
1
  # v1.0
2
2
 
3
+ ## Release v1.0.5 - 2023/03/15
4
+
5
+ ### Enhancement
6
+
7
+ - Add variable of capistrano `ecs_client_retry_params` to override parameter of ECS::Client#initialize https://github.com/reproio/ecs_deploy/pull/88
8
+
9
+ ## Release v1.0.4 - 2023/02/10
10
+
11
+ ### Bug fixes
12
+
13
+ - Fix Aws::AutoScaling::Errors::ValidationError https://github.com/reproio/ecs_deploy/pull/85
14
+
15
+ - Fix Timeout::Error that occurs in trigger_capacity_update https://github.com/reproio/ecs_deploy/pull/80
16
+
17
+ - use force a new deployment, when switching from launch type to capacity provider strategy on an existing service https://github.com/reproio/ecs_deploy/pull/75
18
+
19
+ ### Enhancement
20
+
21
+ - Run test with Ruby 3.2 https://github.com/reproio/ecs_deploy/pull/83
22
+
23
+ - Merge `propagate_tags` to service_options when updating service https://github.com/reproio/ecs_deploy/pull/82
24
+
25
+ - Show service event logs while waiting for services https://github.com/reproio/ecs_deploy/pull/81
26
+
27
+ - Stop supporting ruby 2.4 https://github.com/reproio/ecs_deploy/pull/79
28
+
29
+ - Display warning that desired count has reached max value https://github.com/reproio/ecs_deploy/pull/78
30
+
31
+ - Make draining feature opt-outable https://github.com/reproio/ecs_deploy/pull/77
32
+
33
+ - Add capacity_provider_strategy options to Service https://github.com/reproio/ecs_deploy/pull/74
34
+
3
35
  ## Release v1.0.3 - 2021/11/17
4
36
 
5
37
  ### Bug fixes
data/README.md CHANGED
@@ -33,6 +33,7 @@ set :ecs_service_role, "customEcsServiceRole" # default: ecsServiceRole
33
33
  set :ecs_deploy_wait_timeout, 600 # default: 300
34
34
  set :ecs_wait_until_services_stable_max_attempts, 40 # optional
35
35
  set :ecs_wait_until_services_stable_delay, 15 # optional
36
+ set :ecs_client_params, { retry_mode: "standard", max_attempts: 10 } # default: {}
36
37
 
37
38
  set :ecs_tasks, [
38
39
  {
@@ -215,6 +216,7 @@ auto_scaling_groups:
215
216
  # autoscaler will set the capacity to (buffer + desired_tasks * required_capacity).
216
217
  # Adjust this value if it takes much time to prepare ECS instances and launch new tasks.
217
218
  buffer: 1
219
+ disable_draining: false # cf. spot_instance_intrp_warns_queue_urls
218
220
  services:
219
221
  - name: repro-api-production
220
222
  step: 1
@@ -242,6 +244,7 @@ spot_fleet_requests:
242
244
  region: ap-northeast-1
243
245
  cluster: ecs-cluster-for-worker
244
246
  buffer: 1
247
+ disable_draining: false # cf. spot_instance_intrp_warns_queue_urls
245
248
  services:
246
249
  - name: repro-worker-production
247
250
  step: 1
@@ -261,11 +264,15 @@ spot_fleet_requests:
261
264
  state: ALARM
262
265
  prioritized_over_upscale_triggers: true
263
266
 
264
- # If you specify `spot_instance_intrp_warns_queue_urls` as SQS queue for spot instance interruption warnings,
265
- # autoscaler will polls them and set the state of instances to be intrrupted to "DRAINING".
266
- # autoscaler will also waits for the capacity of active instances in the cluster being decreased
267
- # when the capacity of spot fleet request is decreased,
268
- # so you should specify URLs or set the state of the instances to "DRAINING" manually.
267
+ # When you use spot instances, instances that receive interruption warnings should be drained.
268
+ # If you set URLs of SQS queues for spot instance interruption warnings to `spot_instance_intrp_warns_queue_urls`,
269
+ # autoscaler drains instances to interrupt and detaches the instances from the auto scaling groups with
270
+ # should_decrement_desired_capacity false.
271
+ # If you set ECS_ENABLE_SPOT_INSTANCE_DRAINING to true, we recommend that you opt out of the draining feature
272
+ # by setting disable_draining to true in the configurations of auto scaling groups and spot fleet requests.
273
+ # Otherwise, instances don't seem to be drained on rare occasions.
274
+ # Even if you opt out of the feature, you still have the advantage of setting `spot_instance_intrp_warns_queue_urls`
275
+ # because instances to interrupt are replaced with new instances as soon as possible.
269
276
  spot_instance_intrp_warns_queue_urls:
270
277
  - https://sqs.ap-northeast-1.amazonaws.com/<account-id>/spot-instance-intrp-warns
271
278
  ```
data/ecs_deploy.gemspec CHANGED
@@ -30,4 +30,5 @@ Gem::Specification.new do |spec|
30
30
  spec.add_development_dependency "bundler", ">= 1.11", "< 3"
31
31
  spec.add_development_dependency "rake", ">= 10.0"
32
32
  spec.add_development_dependency "rspec", "~> 3.0"
33
+ spec.add_development_dependency "rexml" # For aws-sdk-*
33
34
  end
@@ -7,7 +7,7 @@ require "ecs_deploy/auto_scaler/cluster_resource_manager"
7
7
 
8
8
  module EcsDeploy
9
9
  module AutoScaler
10
- AutoScalingGroupConfig = Struct.new(:name, :region, :cluster, :buffer, :service_configs) do
10
+ AutoScalingGroupConfig = Struct.new(:name, :region, :cluster, :buffer, :service_configs, :disable_draining) do
11
11
  include ConfigBase
12
12
 
13
13
  MAX_DETACHABLE_INSTANCE_COUNT = 20
@@ -82,7 +82,7 @@ module EcsDeploy
82
82
  def decrease_desired_capacity(count)
83
83
  container_instance_arns_in_service = cluster_resource_manager.fetch_container_instance_arns_in_service
84
84
  container_instances_in_cluster = cluster_resource_manager.fetch_container_instances_in_cluster
85
- auto_scaling_group_instances = instances(reload: true)
85
+ auto_scaling_group_instances = describe_detachable_instances
86
86
  deregisterable_instances = container_instances_in_cluster.select do |i|
87
87
  i.pending_tasks_count == 0 &&
88
88
  !running_essential_task?(i, container_instance_arns_in_service) &&
@@ -144,15 +144,8 @@ module EcsDeploy
144
144
 
145
145
  def detach_and_terminate_orphan_instances
146
146
  container_instance_ids = cluster_resource_manager.fetch_container_instances_in_cluster.map(&:ec2_instance_id)
147
- orphans = instances(reload: true).reject do |i|
147
+ orphans = describe_detachable_instances.reject do |i|
148
148
  next true if container_instance_ids.include?(i.instance_id)
149
-
150
- # The lifecycle state of terminated instances becomes "Terminating", "Terminating:Wait", or "Terminating:Proceed",
151
- # and we can't detach instances in such a state.
152
- if i.lifecycle_state.start_with?("Terminating")
153
- AutoScaler.error_logger.warn("#{log_prefix} The lifesycle state of #{i.instance_id} is \"#{i.lifecycle_state}\", so ignore it")
154
- next true
155
- end
156
149
  end.map(&:instance_id)
157
150
 
158
151
  return if orphans.empty?
@@ -184,14 +177,11 @@ module EcsDeploy
184
177
  )
185
178
  end
186
179
 
187
- def instances(reload: false)
188
- if reload || @instances.nil?
189
- resp = client.describe_auto_scaling_groups({
190
- auto_scaling_group_names: [name],
191
- })
192
- @instances = resp.auto_scaling_groups[0].instances
193
- else
194
- @instances
180
+ def describe_detachable_instances
181
+ client.describe_auto_scaling_groups({ auto_scaling_group_names: [name] }).auto_scaling_groups[0].instances.reject do |i|
182
+ # The lifecycle state of terminated instances becomes "Detaching", "Terminating", "Terminating:Wait", or "Terminating:Proceed",
183
+ # and we can't detach instances in such a state.
184
+ i.lifecycle_state.start_with?("Terminating") || i.lifecycle_state == "Detaching"
195
185
  end
196
186
  end
197
187
 
@@ -74,39 +74,42 @@ module EcsDeploy
74
74
  end
75
75
 
76
76
  def trigger_capacity_update(old_desired_capacity, new_desired_capacity, interval: 5, wait_until_capacity_updated: false)
77
+ return if new_desired_capacity == old_desired_capacity
78
+
77
79
  th = Thread.new do
78
80
  @logger&.info "#{log_prefix} Start updating capacity: #{old_desired_capacity} -> #{new_desired_capacity}"
79
81
  Timeout.timeout(180) do
80
- until @capacity == new_desired_capacity || (new_desired_capacity >= old_desired_capacity && @capacity > new_desired_capacity)
82
+ until @capacity == new_desired_capacity ||
83
+ (new_desired_capacity > old_desired_capacity && @capacity > new_desired_capacity) ||
84
+ (new_desired_capacity < old_desired_capacity && @capacity < new_desired_capacity)
81
85
  @mutex.synchronize do
82
- begin
83
- @capacity = calculate_active_instance_capacity
84
- @resource.broadcast
85
- rescue => e
86
- AutoScaler.error_logger.warn("#{log_prefix} `#{__method__}': #{e} (#{e.class})")
87
- end
86
+ @capacity = calculate_active_instance_capacity
87
+ @resource.broadcast
88
+ rescue => e
89
+ AutoScaler.error_logger.warn("#{log_prefix} `#{__method__}': #{e} (#{e.class})")
88
90
  end
89
91
 
90
92
  sleep interval
91
93
  end
92
94
  @logger&.info "#{log_prefix} capacity is updated to #{@capacity}"
93
95
  end
96
+ rescue Timeout::Error => e
97
+ msg = "#{log_prefix} `#{__method__}': #{e} (#{e.class})"
98
+ if @capacity_based_on == "vCPUs"
99
+ # Timeout::Error sometimes occur.
100
+ # For example, the following case never meats the condition of until
101
+ # * old_desired_capaacity is 102
102
+ # * new_desired_capaacity is 101
103
+ # * all instances have 2 vCPUs
104
+ AutoScaler.error_logger.warn(msg)
105
+ else
106
+ AutoScaler.error_logger.error(msg)
107
+ end
94
108
  end
95
109
 
96
110
  if wait_until_capacity_updated
97
111
  @logger&.info "#{log_prefix} Wait for the capacity of active instances to become #{new_desired_capacity} from #{old_desired_capacity}"
98
- begin
99
- th.join
100
- rescue Timeout::Error => e
101
- msg = "#{log_prefix} `#{__method__}': #{e} (#{e.class})"
102
- if @capacity_based_on == "vCPUs"
103
- # Timeout::Error sometimes occur.
104
- # For example, @capacity won't be new_desired_capacity if new_desired_capacity is odd and all instances have 2 vCPUs
105
- AutoScaler.error_logger.warn(msg)
106
- else
107
- AutoScaler.error_logger.error(msg)
108
- end
109
- end
112
+ th.join
110
113
  end
111
114
  end
112
115
 
@@ -78,6 +78,11 @@ module EcsDeploy
78
78
  def set_instance_state_to_draining(config_to_instance_ids, region)
79
79
  cl = ecs_client(region)
80
80
  config_to_instance_ids.each do |config, instance_ids|
81
+ if config.disable_draining == true || config.disable_draining == "true"
82
+ @logger.info "Skip draining instances: region: #{region}, cluster: #{config.cluster}, instance_ids: #{instance_ids.inspect}"
83
+ next
84
+ end
85
+
81
86
  arns = cl.list_container_instances(
82
87
  cluster: config.cluster,
83
88
  filter: "ec2InstanceId in [#{instance_ids.join(",")}]",
@@ -135,6 +135,9 @@ module EcsDeploy
135
135
  now = Process.clock_gettime(Process::CLOCK_MONOTONIC, :second)
136
136
  @reach_max_at ||= now
137
137
  @logger.info "#{log_prefix} Service waits cooldown elapsed #{(now - @reach_max_at).to_i}sec"
138
+ if next_desired_count > max_task_count[current_level] && current_level == max_task_count.size - 1
139
+ @logger.warn "#{log_prefix} Desired count has reached the maximum value and couldn't be increased"
140
+ end
138
141
  elsif current_level == next_level && next_desired_count < max_task_count[current_level]
139
142
  level = current_level
140
143
  @reach_max_at = nil
@@ -8,7 +8,7 @@ require "ecs_deploy/auto_scaler/cluster_resource_manager"
8
8
 
9
9
  module EcsDeploy
10
10
  module AutoScaler
11
- SpotFleetRequestConfig = Struct.new(:id, :region, :cluster, :buffer, :service_configs) do
11
+ SpotFleetRequestConfig = Struct.new(:id, :region, :cluster, :buffer, :service_configs, :disable_draining) do
12
12
  include ConfigBase
13
13
 
14
14
  def initialize(attributes = {}, logger)
@@ -10,6 +10,7 @@ namespace :ecs do
10
10
  c.default_region = Array(fetch(:ecs_region))[0] if fetch(:ecs_region)
11
11
  c.ecs_wait_until_services_stable_max_attempts = fetch(:ecs_wait_until_services_stable_max_attempts) if fetch(:ecs_wait_until_services_stable_max_attempts)
12
12
  c.ecs_wait_until_services_stable_delay = fetch(:ecs_wait_until_services_stable_delay) if fetch(:ecs_wait_until_services_stable_delay)
13
+ c.ecs_client_params = fetch(:ecs_client_params) if fetch(:ecs_client_params)
13
14
  end
14
15
 
15
16
  if ENV["TARGET_CLUSTER"]
@@ -113,6 +114,7 @@ namespace :ecs do
113
114
  service_options[:deployment_configuration] = service[:deployment_configuration] if service[:deployment_configuration]
114
115
  service_options[:placement_constraints] = service[:placement_constraints] if service[:placement_constraints]
115
116
  service_options[:placement_strategy] = service[:placement_strategy] if service[:placement_strategy]
117
+ service_options[:capacity_provider_strategy] = service[:capacity_provider_strategy] if service[:capacity_provider_strategy]
116
118
  service_options[:scheduling_strategy] = service[:scheduling_strategy] if service[:scheduling_strategy]
117
119
  s = EcsDeploy::Service.new(**service_options)
118
120
  s.deploy
@@ -179,6 +181,7 @@ namespace :ecs do
179
181
  service_options[:deployment_configuration] = service[:deployment_configuration] if service[:deployment_configuration]
180
182
  service_options[:placement_constraints] = service[:placement_constraints] if service[:placement_constraints]
181
183
  service_options[:placement_strategy] = service[:placement_strategy] if service[:placement_strategy]
184
+ service_options[:capacity_provider_strategy] = service[:capacity_provider_strategy] if service[:capacity_provider_strategy]
182
185
  s = EcsDeploy::Service.new(**service_options)
183
186
  s.deploy
184
187
  EcsDeploy::TaskDefinition.deregister(current_task_definition_arn, region: r)
@@ -8,7 +8,8 @@ module EcsDeploy
8
8
  :deploy_wait_timeout,
9
9
  :ecs_service_role,
10
10
  :ecs_wait_until_services_stable_max_attempts,
11
- :ecs_wait_until_services_stable_delay
11
+ :ecs_wait_until_services_stable_delay,
12
+ :ecs_client_params
12
13
 
13
14
  def initialize
14
15
  @log_level = :info
@@ -16,6 +17,7 @@ module EcsDeploy
16
17
  # The following values are the default values of Aws::ECS::Waiters::ServicesStable
17
18
  @ecs_wait_until_services_stable_max_attempts = 40
18
19
  @ecs_wait_until_services_stable_delay = 15
20
+ @ecs_client_params = {}
19
21
  end
20
22
  end
21
23
  end
@@ -113,7 +113,7 @@ module EcsDeploy
113
113
  end
114
114
 
115
115
  def ecs_client
116
- @ecs_client ||= Aws::ECS::Client.new(aws_params)
116
+ @ecs_client ||= Aws::ECS::Client.new(aws_params.merge(EcsDeploy.config.ecs_client_params))
117
117
  end
118
118
 
119
119
  def fetch_auto_scaling_group
@@ -27,9 +27,10 @@ module EcsDeploy
27
27
  @platform_version = platform_version
28
28
  @group = group
29
29
  region ||= EcsDeploy.config.default_region
30
+ params ||= EcsDeploy.config.ecs_client_params
30
31
  @container_overrides = container_overrides
31
32
 
32
- @client = region ? Aws::ECS::Client.new(region: region) : Aws::ECS::Client.new
33
+ @client = region ? Aws::ECS::Client.new(params.merge(region: region)) : Aws::ECS::Client.new(params)
33
34
  @region = @client.config.region
34
35
  @cloud_watch_events = Aws::CloudWatchEvents::Client.new(region: @region)
35
36
  end
@@ -7,7 +7,7 @@ module EcsDeploy
7
7
 
8
8
  class TooManyAttemptsError < StandardError; end
9
9
 
10
- attr_reader :cluster, :region, :service_name, :delete
10
+ attr_reader :cluster, :region, :service_name, :delete, :deploy_started_at
11
11
 
12
12
  def initialize(
13
13
  cluster:, service_name:, task_definition_name: nil, revision: nil,
@@ -16,6 +16,7 @@ module EcsDeploy
16
16
  launch_type: nil,
17
17
  placement_constraints: [],
18
18
  placement_strategy: [],
19
+ capacity_provider_strategy: nil,
19
20
  network_configuration: nil,
20
21
  health_check_grace_period_seconds: nil,
21
22
  scheduling_strategy: 'REPLICA',
@@ -35,6 +36,7 @@ module EcsDeploy
35
36
  @launch_type = launch_type
36
37
  @placement_constraints = placement_constraints
37
38
  @placement_strategy = placement_strategy
39
+ @capacity_provider_strategy = capacity_provider_strategy
38
40
  @network_configuration = network_configuration
39
41
  @health_check_grace_period_seconds = health_check_grace_period_seconds
40
42
  @scheduling_strategy = scheduling_strategy
@@ -47,7 +49,8 @@ module EcsDeploy
47
49
  @response = nil
48
50
 
49
51
  region ||= EcsDeploy.config.default_region
50
- @client = region ? Aws::ECS::Client.new(region: region) : Aws::ECS::Client.new
52
+ params ||= EcsDeploy.config.ecs_client_params
53
+ @client = region ? Aws::ECS::Client.new(params.merge(region: region)) : Aws::ECS::Client.new(params)
51
54
  @region = @client.config.region
52
55
 
53
56
  @delete = delete
@@ -59,6 +62,7 @@ module EcsDeploy
59
62
  end
60
63
 
61
64
  def deploy
65
+ @deploy_started_at = Time.now
62
66
  res = @client.describe_services(cluster: @cluster, services: [@service_name])
63
67
  service_options = {
64
68
  cluster: @cluster,
@@ -66,8 +70,25 @@ module EcsDeploy
66
70
  deployment_configuration: @deployment_configuration,
67
71
  network_configuration: @network_configuration,
68
72
  health_check_grace_period_seconds: @health_check_grace_period_seconds,
73
+ capacity_provider_strategy: @capacity_provider_strategy,
69
74
  enable_execute_command: @enable_execute_command,
75
+ enable_ecs_managed_tags: @enable_ecs_managed_tags,
76
+ placement_constraints: @placement_constraints,
77
+ placement_strategy: @placement_strategy,
70
78
  }
79
+
80
+ if @load_balancers && EcsDeploy.config.ecs_service_role
81
+ service_options.merge!({
82
+ role: EcsDeploy.config.ecs_service_role,
83
+ })
84
+ end
85
+
86
+ if @load_balancers
87
+ service_options.merge!({
88
+ load_balancers: @load_balancers,
89
+ })
90
+ end
91
+
71
92
  if res.services.select{ |s| s.status == 'ACTIVE' }.empty?
72
93
  return if @delete
73
94
 
@@ -75,25 +96,10 @@ module EcsDeploy
75
96
  service_name: @service_name,
76
97
  desired_count: @desired_count.to_i,
77
98
  launch_type: @launch_type,
78
- placement_constraints: @placement_constraints,
79
- placement_strategy: @placement_strategy,
80
- enable_ecs_managed_tags: @enable_ecs_managed_tags,
81
99
  tags: @tags,
82
100
  propagate_tags: @propagate_tags,
83
101
  })
84
102
 
85
- if @load_balancers && EcsDeploy.config.ecs_service_role
86
- service_options.merge!({
87
- role: EcsDeploy.config.ecs_service_role,
88
- })
89
- end
90
-
91
- if @load_balancers
92
- service_options.merge!({
93
- load_balancers: @load_balancers,
94
- })
95
- end
96
-
97
103
  if @scheduling_strategy == 'DAEMON'
98
104
  service_options[:scheduling_strategy] = @scheduling_strategy
99
105
  service_options.delete(:desired_count)
@@ -105,12 +111,34 @@ module EcsDeploy
105
111
 
106
112
  service_options.merge!({service: @service_name})
107
113
  service_options.merge!({desired_count: @desired_count}) if @desired_count
114
+ service_options.merge!({propagate_tags: @propagate_tags}) if @propagate_tags
115
+
116
+ current_service = res.services[0]
117
+ service_options.merge!({force_new_deployment: true}) if need_force_new_deployment?(current_service)
118
+
108
119
  update_tags(@service_name, @tags)
109
120
  @response = @client.update_service(service_options)
110
121
  EcsDeploy.logger.info "update service [#{@service_name}] [#{@cluster}] [#{@region}] [#{Paint['OK', :green]}]"
111
122
  end
112
123
  end
113
124
 
125
+ private def need_force_new_deployment?(service)
126
+ return false unless @capacity_provider_strategy
127
+ return true unless service.capacity_provider_strategy
128
+
129
+ return true if @capacity_provider_strategy.size != service.capacity_provider_strategy.size
130
+
131
+ match_array = @capacity_provider_strategy.all? do |strategy|
132
+ service.capacity_provider_strategy.find do |current_strategy|
133
+ strategy[:capacity_provider] == current_strategy.capacity_provider &&
134
+ strategy[:weight] == current_strategy.weight &&
135
+ strategy[:base] == current_strategy.base
136
+ end
137
+ end
138
+
139
+ !match_array
140
+ end
141
+
114
142
  def delete_service
115
143
  if @scheduling_strategy != 'DAEMON'
116
144
  @client.update_service(cluster: @cluster, service: @service_name, desired_count: 0)
@@ -142,9 +170,20 @@ module EcsDeploy
142
170
  end
143
171
  end
144
172
 
173
+ def log_events(ecs_service)
174
+ ecs_service.events.sort_by(&:created_at).each do |e|
175
+ next if e.created_at <= deploy_started_at
176
+ next if @last_event && e.created_at <= @last_event.created_at
177
+
178
+ EcsDeploy.logger.info e.message
179
+ @last_event = e
180
+ end
181
+ end
182
+
145
183
  def self.wait_all_running(services)
146
184
  services.group_by { |s| [s.cluster, s.region] }.flat_map do |(cl, region), ss|
147
- client = Aws::ECS::Client.new(region: region)
185
+ params ||= EcsDeploy.config.ecs_client_params
186
+ client = Aws::ECS::Client.new(params.merge(region: region))
148
187
  ss.reject(&:delete).map(&:service_name).each_slice(MAX_DESCRIBE_SERVICES).map do |chunked_service_names|
149
188
  Thread.new do
150
189
  EcsDeploy.config.ecs_wait_until_services_stable_max_attempts.times do
@@ -155,6 +194,8 @@ module EcsDeploy
155
194
  if s.deployments.size == 1 && s.running_count == s.desired_count
156
195
  chunked_service_names.delete(s.service_name)
157
196
  end
197
+ service = ss.detect {|sc| sc.service_name == s.service_name }
198
+ service.log_events(s)
158
199
  end
159
200
  break if chunked_service_names.empty?
160
201
  sleep EcsDeploy.config.ecs_wait_until_services_stable_delay
@@ -1,15 +1,9 @@
1
1
  module EcsDeploy
2
2
  class TaskDefinition
3
- RETRY_BACKOFF = lambda do |c|
4
- sleep(1)
5
- end
6
-
7
- RETRY_LIMIT = 10
8
-
9
3
  def self.deregister(arn, region: nil)
10
4
  region ||= EcsDeploy.config.default_region
11
- param = {retry_backoff: RETRY_BACKOFF, retry_limit: RETRY_LIMIT}
12
- client = region ? Aws::ECS::Client.new(param.merge(region: region)) : Aws::ECS::Client.new(param)
5
+ params ||= EcsDeploy.config.ecs_client_params
6
+ client = region ? Aws::ECS::Client.new(params.merge(region: region)) : Aws::ECS::Client.new(params)
13
7
  client.deregister_task_definition({
14
8
  task_definition: arn,
15
9
  })
@@ -29,6 +23,7 @@ module EcsDeploy
29
23
  @task_role_arn = task_role_arn
30
24
  @execution_role_arn = execution_role_arn
31
25
  region ||= EcsDeploy.config.default_region
26
+ params ||= EcsDeploy.config.ecs_client_params
32
27
 
33
28
  @container_definitions = container_definitions.map do |cd|
34
29
  if cd[:docker_labels]
@@ -46,8 +41,7 @@ module EcsDeploy
46
41
  @cpu = cpu&.to_s
47
42
  @memory = memory&.to_s
48
43
  @tags = tags
49
- param = {retry_backoff: RETRY_BACKOFF, retry_limit: RETRY_LIMIT}
50
- @client = region ? Aws::ECS::Client.new(param.merge(region: region)) : Aws::ECS::Client.new(param)
44
+ @client = region ? Aws::ECS::Client.new(params.merge(region: region)) : Aws::ECS::Client.new(params)
51
45
  @region = @client.config.region
52
46
  end
53
47
 
@@ -1,3 +1,3 @@
1
1
  module EcsDeploy
2
- VERSION = "1.0.3"
2
+ VERSION = "1.0.5"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ecs_deploy
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.3
4
+ version: 1.0.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - joker1007
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2021-11-17 00:00:00.000000000 Z
11
+ date: 2023-03-15 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: aws-sdk-autoscaling
@@ -170,6 +170,20 @@ dependencies:
170
170
  - - "~>"
171
171
  - !ruby/object:Gem::Version
172
172
  version: '3.0'
173
+ - !ruby/object:Gem::Dependency
174
+ name: rexml
175
+ requirement: !ruby/object:Gem::Requirement
176
+ requirements:
177
+ - - ">="
178
+ - !ruby/object:Gem::Version
179
+ version: '0'
180
+ type: :development
181
+ prerelease: false
182
+ version_requirements: !ruby/object:Gem::Requirement
183
+ requirements:
184
+ - - ">="
185
+ - !ruby/object:Gem::Version
186
+ version: '0'
173
187
  description: AWS ECS deploy helper
174
188
  email:
175
189
  - kakyoin.hierophant@gmail.com
@@ -178,8 +192,8 @@ executables:
178
192
  extensions: []
179
193
  extra_rdoc_files: []
180
194
  files:
195
+ - ".github/workflows/test.yml"
181
196
  - ".gitignore"
182
- - ".travis.yml"
183
197
  - CHANGELOG.md
184
198
  - Gemfile
185
199
  - README.md
@@ -222,7 +236,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
222
236
  - !ruby/object:Gem::Version
223
237
  version: '0'
224
238
  requirements: []
225
- rubygems_version: 3.2.15
239
+ rubygems_version: 3.4.2
226
240
  signing_key:
227
241
  specification_version: 4
228
242
  summary: AWS ECS deploy helper
data/.travis.yml DELETED
@@ -1,5 +0,0 @@
1
- language: ruby
2
- rvm:
3
- - ruby-2.4.9
4
- - ruby-2.5.7
5
- - ruby-2.6.5