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 +4 -4
- data/.github/workflows/test.yml +23 -0
- data/CHANGELOG.md +32 -0
- data/README.md +12 -5
- data/ecs_deploy.gemspec +1 -0
- data/lib/ecs_deploy/auto_scaler/auto_scaling_group_config.rb +8 -18
- data/lib/ecs_deploy/auto_scaler/cluster_resource_manager.rb +22 -19
- data/lib/ecs_deploy/auto_scaler/instance_drainer.rb +5 -0
- data/lib/ecs_deploy/auto_scaler/service_config.rb +3 -0
- data/lib/ecs_deploy/auto_scaler/spot_fleet_request_config.rb +1 -1
- data/lib/ecs_deploy/capistrano.rb +3 -0
- data/lib/ecs_deploy/configuration.rb +3 -1
- data/lib/ecs_deploy/instance_fluctuation_manager.rb +1 -1
- data/lib/ecs_deploy/scheduled_task.rb +2 -1
- data/lib/ecs_deploy/service.rb +59 -18
- data/lib/ecs_deploy/task_definition.rb +4 -10
- data/lib/ecs_deploy/version.rb +1 -1
- metadata +18 -4
- data/.travis.yml +0 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a9b02fc9a3cfda6288d7e00f339487fd2050b441e973d5fc7a822f9c261ea272
|
4
|
+
data.tar.gz: 9c002ab5e543435304d8d56eb88d19fceac56b4d70916f1b740176b6c3070dfc
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
|
-
#
|
265
|
-
#
|
266
|
-
# autoscaler
|
267
|
-
#
|
268
|
-
#
|
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
@@ -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 =
|
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 =
|
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
|
188
|
-
|
189
|
-
|
190
|
-
|
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 ||
|
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
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
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
|
-
|
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
|
@@ -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
|
data/lib/ecs_deploy/service.rb
CHANGED
@@ -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
|
-
|
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
|
-
|
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
|
-
|
12
|
-
client = region ? Aws::ECS::Client.new(
|
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
|
-
|
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
|
|
data/lib/ecs_deploy/version.rb
CHANGED
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.
|
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:
|
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
|
239
|
+
rubygems_version: 3.4.2
|
226
240
|
signing_key:
|
227
241
|
specification_version: 4
|
228
242
|
summary: AWS ECS deploy helper
|