hako 2.11.0 → 2.15.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.rubocop.yml +8 -3
- data/.rubocop_todo.yml +0 -2
- data/.travis.yml +3 -5
- data/CHANGELOG.md +29 -0
- data/examples/hello-grpc.jsonnet +60 -0
- data/hako.gemspec +3 -3
- data/lib/hako/cli.rb +7 -1
- data/lib/hako/commander.rb +5 -4
- data/lib/hako/container.rb +9 -0
- data/lib/hako/env_providers/file.rb +1 -1
- data/lib/hako/env_providers/yaml.rb +1 -1
- data/lib/hako/schedulers/ecs.rb +154 -55
- data/lib/hako/schedulers/ecs_autoscaling.rb +1 -3
- data/lib/hako/schedulers/ecs_definition_comparator.rb +11 -0
- data/lib/hako/schedulers/ecs_elb_v2.rb +9 -0
- data/lib/hako/schedulers/ecs_service_comparator.rb +10 -1
- data/lib/hako/scripts/nginx_front.rb +1 -1
- data/lib/hako/version.rb +1 -1
- metadata +12 -11
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1c1298dda5d9e120f1856ed3a559c520451b1023384d1a56bd921f66c70f6da5
|
4
|
+
data.tar.gz: 833a89a305a9e075df8016e90a7d4ad45f18c29ad208197e3ebdacba5a60848b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: bfba96a068f38a760e7760188574e7b5afe2dd5400ce745905f3611f71fe18f87d2cbe446878c2d00ee55e56b423ac0185baa96c91737b10847f3f77442d5035
|
7
|
+
data.tar.gz: cfa5202766106d88e125cba58011fcccff3954a843c2fdc56a301e62d476239b1ae955b627de3dfbcf185e08bfb721418669c6f86548f68d55765f164e969e56
|
data/.rubocop.yml
CHANGED
@@ -2,14 +2,17 @@ inherit_from: .rubocop_todo.yml
|
|
2
2
|
|
3
3
|
AllCops:
|
4
4
|
DisplayCopNames: true
|
5
|
-
TargetRubyVersion: 2.
|
5
|
+
TargetRubyVersion: 2.5
|
6
|
+
NewCops: disable
|
6
7
|
|
7
|
-
Layout/
|
8
|
+
Layout/FirstArgumentIndentation:
|
9
|
+
Enabled: false
|
10
|
+
Layout/LineLength:
|
8
11
|
Enabled: false
|
9
12
|
|
10
13
|
Naming/PredicateName:
|
11
14
|
Enabled: false
|
12
|
-
Naming/
|
15
|
+
Naming/MethodParameterName:
|
13
16
|
Enabled: false
|
14
17
|
Naming/MemoizedInstanceVariableName:
|
15
18
|
Enabled: false
|
@@ -35,6 +38,8 @@ Style/RaiseArgs:
|
|
35
38
|
EnforcedStyle: compact
|
36
39
|
Style/SignalException:
|
37
40
|
Enabled: false
|
41
|
+
Style/SoleNestedConditional:
|
42
|
+
Enabled: false
|
38
43
|
Style/StderrPuts:
|
39
44
|
Enabled: false
|
40
45
|
Style/TrailingCommaInArguments:
|
data/.rubocop_todo.yml
CHANGED
data/.travis.yml
CHANGED
@@ -1,12 +1,10 @@
|
|
1
1
|
language: ruby
|
2
2
|
sudo: false
|
3
3
|
rvm:
|
4
|
-
- 2.
|
5
|
-
- 2.
|
4
|
+
- 2.5.8
|
5
|
+
- 2.6.6
|
6
|
+
- 2.7.2
|
6
7
|
- ruby-head
|
7
|
-
before_install:
|
8
|
-
- gem update --system # https://github.com/rubygems/rubygems/pull/1819
|
9
|
-
- gem install bundler
|
10
8
|
matrix:
|
11
9
|
allow_failures:
|
12
10
|
- rvm: ruby-head
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,32 @@
|
|
1
|
+
# 2.15.0 (2020-11-02)
|
2
|
+
## New features
|
3
|
+
- Support protocol_version and matcher option of ALB target groups
|
4
|
+
|
5
|
+
# 2.14.0 (2020-05-20)
|
6
|
+
## New features
|
7
|
+
- Support tags for task definition and propagate them to ECS tasks
|
8
|
+
- Now all created ECS services and launched ECS tasks have `propagate_tags=TASK_DEFINITION` parameter.
|
9
|
+
- Support repository_credentials
|
10
|
+
|
11
|
+
# 2.13.0 (2020-01-10)
|
12
|
+
## New features
|
13
|
+
- Support capacity provider strategy
|
14
|
+
|
15
|
+
## Bug fixes
|
16
|
+
- Do not try to update assign_public_ip when it is not changed
|
17
|
+
|
18
|
+
# 2.12.0 (2019-09-09)
|
19
|
+
## New features
|
20
|
+
- Support more overrides options for `hako oneshot`
|
21
|
+
- `--app-cpu`, `--app-memory` and `--app-memory-reservation` are added
|
22
|
+
|
23
|
+
## Bug fixes
|
24
|
+
- Show `--health-*` options in dry-run
|
25
|
+
|
26
|
+
# 2.11.1 (2019-05-17)
|
27
|
+
## Bug fixes
|
28
|
+
- Fix comparison of `system_controls` parameter
|
29
|
+
|
1
30
|
# 2.11.0 (2019-05-17)
|
2
31
|
## New features
|
3
32
|
- Support `system_controls` parameter in container definition
|
@@ -0,0 +1,60 @@
|
|
1
|
+
{
|
2
|
+
scheduler: {
|
3
|
+
type: 'ecs',
|
4
|
+
region: 'ap-northeast-1',
|
5
|
+
cluster: 'eagletmt',
|
6
|
+
desired_count: 2,
|
7
|
+
role: 'ecsServiceRole',
|
8
|
+
elb_v2: {
|
9
|
+
// Specify protocol_version for gRPC servers
|
10
|
+
protocol_version: 'GRPC',
|
11
|
+
// VPC id where the target group is located
|
12
|
+
vpc_id: 'vpc-WWWWWWWW',
|
13
|
+
// If you want internal ELB, then use 'scheme'. (ex. internal service that like microservice inside VPC)
|
14
|
+
scheme: 'internal',
|
15
|
+
// Health check path of the target group
|
16
|
+
health_check_path: '/AWS.ELB/healthcheck',
|
17
|
+
listeners: [
|
18
|
+
{
|
19
|
+
port: 50051,
|
20
|
+
protocol: 'HTTPS',
|
21
|
+
certificate_arn: 'arn:aws:acm:ap-northeast-1:012345678901:certificate/01234567-89ab-cdef-0123-456789abcdef',
|
22
|
+
},
|
23
|
+
],
|
24
|
+
subnets: ['subnet-XXXXXXXX', 'subnet-YYYYYYYY'],
|
25
|
+
security_groups: ['sg-ZZZZZZZZ'],
|
26
|
+
load_balancer_attributes: {
|
27
|
+
'access_logs.s3.enabled': 'true',
|
28
|
+
'access_logs.s3.bucket': 'hako-access-logs',
|
29
|
+
'access_logs.s3.prefix': 'hako-hello-grpc',
|
30
|
+
},
|
31
|
+
target_group_attributes: {
|
32
|
+
// http://docs.aws.amazon.com/en_us/elasticloadbalancing/latest/application/load-balancer-target-groups.html#target-group-attributes
|
33
|
+
'deregistration_delay.timeout_seconds': '20',
|
34
|
+
},
|
35
|
+
// Route ELB traffic to app container directly
|
36
|
+
container_name: 'app',
|
37
|
+
container: 50051,
|
38
|
+
},
|
39
|
+
},
|
40
|
+
app: {
|
41
|
+
image: 'awesome-grpc-server',
|
42
|
+
memory: 128,
|
43
|
+
cpu: 256,
|
44
|
+
env: {
|
45
|
+
PORT: '50051',
|
46
|
+
},
|
47
|
+
secrets: [{
|
48
|
+
name: 'MESSAGE',
|
49
|
+
value_from: 'arn:aws:ssm:ap-northeast-1:012345678901:parameter/hako/hello-grpc/secret-message',
|
50
|
+
}],
|
51
|
+
port_mappings: [
|
52
|
+
{
|
53
|
+
container_port: 50051,
|
54
|
+
host_port: 0,
|
55
|
+
protocol: 'tcp',
|
56
|
+
},
|
57
|
+
],
|
58
|
+
},
|
59
|
+
scripts: [],
|
60
|
+
}
|
data/hako.gemspec
CHANGED
@@ -19,16 +19,16 @@ Gem::Specification.new do |spec|
|
|
19
19
|
spec.bindir = 'exe'
|
20
20
|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
21
21
|
spec.require_paths = ['lib']
|
22
|
-
spec.required_ruby_version = '>= 2.
|
22
|
+
spec.required_ruby_version = '>= 2.5.0'
|
23
23
|
|
24
24
|
spec.add_dependency 'aws-sdk-applicationautoscaling'
|
25
25
|
spec.add_dependency 'aws-sdk-autoscaling'
|
26
26
|
spec.add_dependency 'aws-sdk-cloudwatch'
|
27
27
|
spec.add_dependency 'aws-sdk-cloudwatchlogs'
|
28
28
|
spec.add_dependency 'aws-sdk-ec2'
|
29
|
-
spec.add_dependency 'aws-sdk-ecs', '>= 1.
|
29
|
+
spec.add_dependency 'aws-sdk-ecs', '>= 1.54.0'
|
30
30
|
spec.add_dependency 'aws-sdk-elasticloadbalancing'
|
31
|
-
spec.add_dependency 'aws-sdk-elasticloadbalancingv2'
|
31
|
+
spec.add_dependency 'aws-sdk-elasticloadbalancingv2', '>= 1.54.0'
|
32
32
|
spec.add_dependency 'aws-sdk-s3'
|
33
33
|
spec.add_dependency 'aws-sdk-servicediscovery'
|
34
34
|
spec.add_dependency 'aws-sdk-sns'
|
data/lib/hako/cli.rb
CHANGED
@@ -147,6 +147,8 @@ module Hako
|
|
147
147
|
end
|
148
148
|
|
149
149
|
class Oneshot
|
150
|
+
Overrides = Struct.new(:app_cpu, :app_memory, :app_memory_reservation)
|
151
|
+
|
150
152
|
def run(argv)
|
151
153
|
parse!(argv)
|
152
154
|
require 'hako/application'
|
@@ -162,7 +164,7 @@ module Hako
|
|
162
164
|
else
|
163
165
|
{}
|
164
166
|
end
|
165
|
-
Commander.new(Application.new(@definition_path, options)).oneshot(@argv, tag: @tag, containers: @containers, env: @env, dry_run: @dry_run, no_wait: @no_wait)
|
167
|
+
Commander.new(Application.new(@definition_path, options)).oneshot(@argv, tag: @tag, containers: @containers, env: @env, dry_run: @dry_run, no_wait: @no_wait, overrides: @overrides)
|
166
168
|
end
|
167
169
|
|
168
170
|
def parse!(argv)
|
@@ -171,6 +173,7 @@ module Hako
|
|
171
173
|
@env = {}
|
172
174
|
@verbose = false
|
173
175
|
@no_wait = false
|
176
|
+
@overrides = Overrides.new
|
174
177
|
parser.parse!(argv)
|
175
178
|
@definition_path = argv.shift
|
176
179
|
@argv = argv
|
@@ -194,6 +197,9 @@ module Hako
|
|
194
197
|
k, v = arg.split('=', 2)
|
195
198
|
@env[k] = v
|
196
199
|
end
|
200
|
+
opts.on('--app-cpu=VAL', Integer, 'Override the default cpu for the app container') { |v| @overrides.app_cpu = v }
|
201
|
+
opts.on('--app-memory=VAL', Integer, 'Override the default memory for the app container') { |v| @overrides.app_memory = v }
|
202
|
+
opts.on('--app-memory-reservation=VAL', Integer, 'Override the default memory reservation for the app container') { |v| @overrides.app_memory_reservation = v }
|
197
203
|
end
|
198
204
|
end
|
199
205
|
end
|
data/lib/hako/commander.rb
CHANGED
@@ -18,7 +18,7 @@ module Hako
|
|
18
18
|
# @param [String, nil] tag
|
19
19
|
# @param [Boolean] dry_run
|
20
20
|
# @return [nil]
|
21
|
-
def deploy(force: false,
|
21
|
+
def deploy(tag:, timeout:, force: false, dry_run: false)
|
22
22
|
containers = load_containers(tag, dry_run: dry_run)
|
23
23
|
scripts = @app.definition.fetch('scripts', []).map { |config| load_script(config, dry_run: dry_run) }
|
24
24
|
volumes = @app.definition.fetch('volumes', {})
|
@@ -46,8 +46,9 @@ module Hako
|
|
46
46
|
# @param [Hash<String, String>] env
|
47
47
|
# @param [Boolean] dry_run
|
48
48
|
# @param [Boolean] no_wait
|
49
|
+
# @param [Hako::CLI::Oneshot::Overrides, nil] overrides
|
49
50
|
# @return [nil]
|
50
|
-
def oneshot(commands, tag:, containers:, env: {}, dry_run: false, no_wait: false)
|
51
|
+
def oneshot(commands, tag:, containers:, env: {}, dry_run: false, no_wait: false, overrides: nil)
|
51
52
|
containers = load_containers(tag, dry_run: dry_run, with: containers)
|
52
53
|
scripts = @app.definition.fetch('scripts', []).map { |config| load_script(config, dry_run: dry_run) }
|
53
54
|
volumes = @app.definition.fetch('volumes', {})
|
@@ -55,7 +56,7 @@ module Hako
|
|
55
56
|
|
56
57
|
scripts.each { |script| script.oneshot_starting(containers) }
|
57
58
|
exit_code = with_oneshot_signal_handlers(scheduler) do
|
58
|
-
scheduler.oneshot(containers, commands, env, no_wait: no_wait)
|
59
|
+
scheduler.oneshot(containers, commands, env, no_wait: no_wait, overrides: overrides)
|
59
60
|
end
|
60
61
|
scripts.each { |script| script.oneshot_finished(containers) }
|
61
62
|
exit exit_code
|
@@ -125,7 +126,7 @@ module Hako
|
|
125
126
|
# @param [Boolean] dry_run
|
126
127
|
# @param [Integer] timeout
|
127
128
|
# @return [Scheduler]
|
128
|
-
def load_scheduler(scheduler_definition, scripts, volumes: {}, force: false,
|
129
|
+
def load_scheduler(scheduler_definition, scripts, dry_run:, volumes: {}, force: false, timeout: nil)
|
129
130
|
Loader.new(Hako::Schedulers, 'hako/schedulers').load(scheduler_definition.fetch('type')).new(@app.id, scheduler_definition, volumes: volumes, scripts: scripts, force: force, dry_run: dry_run, timeout: timeout)
|
130
131
|
end
|
131
132
|
|
data/lib/hako/container.rb
CHANGED
@@ -213,6 +213,15 @@ module Hako
|
|
213
213
|
end
|
214
214
|
end
|
215
215
|
|
216
|
+
# @return [Hash, nil]
|
217
|
+
def repository_credentials
|
218
|
+
if @definition.key?('repository_credentials')
|
219
|
+
{
|
220
|
+
credentials_parameter: @definition['repository_credentials'].fetch('credentials_parameter'),
|
221
|
+
}
|
222
|
+
end
|
223
|
+
end
|
224
|
+
|
216
225
|
private
|
217
226
|
|
218
227
|
PROVIDERS_KEY = '$providers'
|
@@ -7,7 +7,7 @@ module Hako
|
|
7
7
|
class File < EnvProvider
|
8
8
|
# @param [Pathname] root_path
|
9
9
|
# @param [Hash<String, Object>] options
|
10
|
-
def initialize(root_path, options)
|
10
|
+
def initialize(root_path, options) # rubocop:disable Lint/MissingSuper
|
11
11
|
unless options['path']
|
12
12
|
validation_error!('path must be set')
|
13
13
|
end
|
@@ -8,7 +8,7 @@ module Hako
|
|
8
8
|
class Yaml < EnvProvider
|
9
9
|
# @param [Pathname] root_path
|
10
10
|
# @param [Hash<String, Object>] options
|
11
|
-
def initialize(root_path, options)
|
11
|
+
def initialize(root_path, options) # rubocop:disable Lint/MissingSuper
|
12
12
|
unless options['path']
|
13
13
|
validation_error!('path must be set')
|
14
14
|
end
|
data/lib/hako/schedulers/ecs.rb
CHANGED
@@ -74,6 +74,15 @@ module Hako
|
|
74
74
|
@memory = options.fetch('memory', nil)
|
75
75
|
@requires_compatibilities = options.fetch('requires_compatibilities', nil)
|
76
76
|
@launch_type = options.fetch('launch_type', nil)
|
77
|
+
if options.key?('capacity_provider_strategy')
|
78
|
+
@capacity_provider_strategy = options.fetch('capacity_provider_strategy').map do |strategy|
|
79
|
+
{
|
80
|
+
capacity_provider: strategy.fetch('capacity_provider'),
|
81
|
+
weight: strategy.fetch('weight', nil),
|
82
|
+
base: strategy.fetch('base', nil),
|
83
|
+
}
|
84
|
+
end
|
85
|
+
end
|
77
86
|
@platform_version = options.fetch('platform_version', nil)
|
78
87
|
if options.key?('network_configuration')
|
79
88
|
network_configuration = options.fetch('network_configuration')
|
@@ -91,6 +100,7 @@ module Hako
|
|
91
100
|
if options['service_discovery']
|
92
101
|
@service_discovery = EcsServiceDiscovery.new(options.fetch('service_discovery'), @region, dry_run: @dry_run)
|
93
102
|
end
|
103
|
+
@tags = options.fetch('tags', {}).map { |k, v| { key: k, value: v.to_s } }
|
94
104
|
|
95
105
|
@started_at = nil
|
96
106
|
@container_instance_arn = nil
|
@@ -198,8 +208,9 @@ module Hako
|
|
198
208
|
# @param [Array<String>] commands
|
199
209
|
# @param [Hash<String, String>] env
|
200
210
|
# @param [Boolean] no_wait
|
211
|
+
# @param [Hako::CLI::Oneshot::Overrides, nil] overrides
|
201
212
|
# @return [Integer] Returns exit code
|
202
|
-
def oneshot(containers, commands, env, no_wait: false)
|
213
|
+
def oneshot(containers, commands, env, no_wait: false, overrides: nil)
|
203
214
|
definitions = create_definitions(containers)
|
204
215
|
|
205
216
|
if @dry_run
|
@@ -210,7 +221,7 @@ module Hako
|
|
210
221
|
if d[:name] == 'app'
|
211
222
|
d[:command] = commands
|
212
223
|
end
|
213
|
-
print_definition_in_cli_format(d, additional_env: env)
|
224
|
+
print_definition_in_cli_format(d, additional_env: env, overrides: overrides)
|
214
225
|
check_secrets(d)
|
215
226
|
end
|
216
227
|
0
|
@@ -221,7 +232,7 @@ module Hako
|
|
221
232
|
else
|
222
233
|
Hako.logger.info "Task definition isn't changed: #{task_definition.task_definition_arn}"
|
223
234
|
end
|
224
|
-
@task = run_task(task_definition, commands, env)
|
235
|
+
@task = run_task(task_definition, commands, env, overrides)
|
225
236
|
Hako.logger.info "Started task: #{@task.task_arn}"
|
226
237
|
@scripts.each { |script| script.oneshot_started(self) }
|
227
238
|
if no_wait
|
@@ -454,8 +465,9 @@ module Hako
|
|
454
465
|
|
455
466
|
# @param [Array<Hash>] desired_definitions
|
456
467
|
# @param [Aws::ECS::Types::TaskDefinition] actual_definition
|
457
|
-
# @
|
458
|
-
|
468
|
+
# @param [Array<Aws::ECS::Types::Tag>] actual_tags
|
469
|
+
# @return [Array<Boolean>]
|
470
|
+
def task_definition_changed?(desired_definitions, actual_definition, actual_tags)
|
459
471
|
if @force
|
460
472
|
return true
|
461
473
|
end
|
@@ -504,6 +516,12 @@ module Hako
|
|
504
516
|
return true
|
505
517
|
end
|
506
518
|
|
519
|
+
actual_tags_set = Set.new(actual_tags.map { |t| { key: t.key, value: t.value } })
|
520
|
+
tags_set = Set.new(@tags)
|
521
|
+
if actual_tags_set != tags_set
|
522
|
+
return true
|
523
|
+
end
|
524
|
+
|
507
525
|
false
|
508
526
|
end
|
509
527
|
|
@@ -525,7 +543,10 @@ module Hako
|
|
525
543
|
# @return [Array<Boolean, Aws::ECS::Types::TaskDefinition>]
|
526
544
|
def register_task_definition(definitions)
|
527
545
|
current_task_definition = describe_task_definition(@app_id)
|
528
|
-
if
|
546
|
+
if current_task_definition
|
547
|
+
current_tags = ecs_client.list_tags_for_resource(resource_arn: current_task_definition.task_definition_arn).tags
|
548
|
+
end
|
549
|
+
if task_definition_changed?(definitions, current_task_definition, current_tags)
|
529
550
|
new_task_definition = ecs_client.register_task_definition(
|
530
551
|
family: @app_id,
|
531
552
|
task_role_arn: @task_role_arn,
|
@@ -536,6 +557,7 @@ module Hako
|
|
536
557
|
requires_compatibilities: @requires_compatibilities,
|
537
558
|
cpu: @cpu,
|
538
559
|
memory: @memory,
|
560
|
+
tags: @tags.empty? ? nil : @tags,
|
539
561
|
).task_definition
|
540
562
|
[true, new_task_definition]
|
541
563
|
else
|
@@ -555,34 +577,36 @@ module Hako
|
|
555
577
|
# @return [Array<Boolean, Aws::ECS::Types::TaskDefinition]
|
556
578
|
def register_task_definition_for_oneshot(definitions)
|
557
579
|
10.times do |i|
|
558
|
-
|
559
|
-
|
560
|
-
|
561
|
-
|
562
|
-
|
563
|
-
|
564
|
-
|
565
|
-
|
566
|
-
|
567
|
-
|
568
|
-
|
569
|
-
|
570
|
-
|
571
|
-
|
572
|
-
|
573
|
-
|
574
|
-
|
575
|
-
|
576
|
-
|
577
|
-
|
578
|
-
|
579
|
-
|
580
|
-
|
581
|
-
|
582
|
-
|
583
|
-
|
584
|
-
|
585
|
-
|
580
|
+
family = "#{@app_id}-oneshot"
|
581
|
+
current_task_definition = describe_task_definition(family)
|
582
|
+
if current_task_definition
|
583
|
+
current_tags = ecs_client.list_tags_for_resource(resource_arn: current_task_definition.task_definition_arn).tags
|
584
|
+
end
|
585
|
+
if task_definition_changed?(definitions, current_task_definition, current_tags)
|
586
|
+
new_task_definition = ecs_client.register_task_definition(
|
587
|
+
family: family,
|
588
|
+
task_role_arn: @task_role_arn,
|
589
|
+
execution_role_arn: @execution_role_arn,
|
590
|
+
network_mode: @network_mode,
|
591
|
+
container_definitions: definitions,
|
592
|
+
volumes: volumes_definition,
|
593
|
+
requires_compatibilities: @requires_compatibilities,
|
594
|
+
cpu: @cpu,
|
595
|
+
memory: @memory,
|
596
|
+
tags: @tags.empty? ? nil : @tags,
|
597
|
+
).task_definition
|
598
|
+
return [true, new_task_definition]
|
599
|
+
else
|
600
|
+
return [false, current_task_definition]
|
601
|
+
end
|
602
|
+
rescue Aws::ECS::Errors::ClientException => e
|
603
|
+
if e.message.include?('Too many concurrent attempts to create a new revision of the specified family')
|
604
|
+
Hako.logger.error(e.message)
|
605
|
+
interval = 2**i + rand(0.0..10.0)
|
606
|
+
Hako.logger.error("Retrying register_task_definition_for_oneshot after #{interval} seconds")
|
607
|
+
sleep(interval)
|
608
|
+
else
|
609
|
+
raise e
|
586
610
|
end
|
587
611
|
end
|
588
612
|
raise Error.new('Unable to register task definition for oneshot due to too many client errors')
|
@@ -652,33 +676,28 @@ module Hako
|
|
652
676
|
readonly_root_filesystem: container.readonly_root_filesystem,
|
653
677
|
docker_security_options: container.docker_security_options,
|
654
678
|
system_controls: container.system_controls,
|
679
|
+
repository_credentials: container.repository_credentials,
|
655
680
|
}
|
656
681
|
end
|
657
682
|
|
658
683
|
# @param [Aws::ECS::Types::TaskDefinition] task_definition
|
659
684
|
# @param [Array<String>] commands
|
660
685
|
# @param [Hash<String, String>] env
|
686
|
+
# @param [Hako::CLI::Oneshot::Overrides] overrides
|
661
687
|
# @return [Aws::ECS::Types::Task]
|
662
|
-
def run_task(task_definition, commands, env)
|
663
|
-
environment = env.map { |k, v| { name: k, value: v } }
|
688
|
+
def run_task(task_definition, commands, env, overrides)
|
664
689
|
result = ecs_client.run_task(
|
665
690
|
cluster: @cluster,
|
666
691
|
task_definition: task_definition.task_definition_arn,
|
667
|
-
overrides:
|
668
|
-
container_overrides: [
|
669
|
-
{
|
670
|
-
name: 'app',
|
671
|
-
command: commands,
|
672
|
-
environment: environment,
|
673
|
-
},
|
674
|
-
],
|
675
|
-
},
|
692
|
+
overrides: overrides_option(commands, env, overrides),
|
676
693
|
count: 1,
|
677
694
|
placement_constraints: @placement_constraints,
|
678
695
|
started_by: 'hako oneshot',
|
679
696
|
launch_type: @launch_type,
|
697
|
+
capacity_provider_strategy: @capacity_provider_strategy,
|
680
698
|
platform_version: @platform_version,
|
681
699
|
network_configuration: @network_configuration,
|
700
|
+
propagate_tags: 'TASK_DEFINITION',
|
682
701
|
)
|
683
702
|
result.failures.each do |failure|
|
684
703
|
Hako.logger.error("#{failure.arn} #{failure.reason}")
|
@@ -702,6 +721,25 @@ module Hako
|
|
702
721
|
end
|
703
722
|
end
|
704
723
|
|
724
|
+
# @param [Array<String>] commands
|
725
|
+
# @param [Hash<String, String>] env
|
726
|
+
# @param [Hako::CLI::Oneshot::Overrides, nil] overrides
|
727
|
+
# @doc https://docs.aws.amazon.com/AmazonECS/latest/APIReference/API_ContainerOverride.html
|
728
|
+
def overrides_option(commands, env, overrides)
|
729
|
+
{
|
730
|
+
container_overrides: [
|
731
|
+
{
|
732
|
+
name: 'app',
|
733
|
+
cpu: overrides&.app_cpu,
|
734
|
+
memory: overrides&.app_memory,
|
735
|
+
memory_reservation: overrides&.app_memory_reservation,
|
736
|
+
command: commands,
|
737
|
+
environment: env.map { |k, v| { name: k, value: v } },
|
738
|
+
},
|
739
|
+
],
|
740
|
+
}
|
741
|
+
end
|
742
|
+
|
705
743
|
# @return [Fixnum]
|
706
744
|
def wait_for_oneshot_finish
|
707
745
|
containers = wait_for_task(@task)
|
@@ -852,6 +890,7 @@ module Hako
|
|
852
890
|
desired_count: @desired_count,
|
853
891
|
task_definition: task_definition_arn,
|
854
892
|
deployment_configuration: @deployment_configuration,
|
893
|
+
capacity_provider_strategy: @capacity_provider_strategy,
|
855
894
|
platform_version: @platform_version,
|
856
895
|
network_configuration: @network_configuration,
|
857
896
|
health_check_grace_period_seconds: @health_check_grace_period_seconds,
|
@@ -860,6 +899,20 @@ module Hako
|
|
860
899
|
# Keep current desired_count if autoscaling is enabled
|
861
900
|
params[:desired_count] = current_service.desired_count
|
862
901
|
end
|
902
|
+
# Copy the current capacity provider strategy in order to avoid a
|
903
|
+
# perpetual diff when the service is created with no strategy to use the
|
904
|
+
# cluster's default capacity provider strategy, which results in the
|
905
|
+
# strategy being set to the default strategy at that moment.
|
906
|
+
# It is not allowed to update the service to use the cluster's default
|
907
|
+
# capacity provider strategy when it is using a non-default capacity
|
908
|
+
# provider strategy.
|
909
|
+
params[:capacity_provider_strategy] ||= current_service.capacity_provider_strategy&.map(&:to_h)
|
910
|
+
if different_capacity_provider_strategy?(params[:capacity_provider_strategy], current_service.capacity_provider_strategy)
|
911
|
+
# Switching from launch type to capacity provider strategy or making
|
912
|
+
# a change to a capacity provider strategy requires to force a new
|
913
|
+
# deployment.
|
914
|
+
params[:force_new_deployment] = true
|
915
|
+
end
|
863
916
|
warn_placement_policy_change(current_service)
|
864
917
|
warn_service_registries_change(current_service)
|
865
918
|
if service_changed?(current_service, params)
|
@@ -883,9 +936,11 @@ module Hako
|
|
883
936
|
placement_strategy: @placement_strategy,
|
884
937
|
scheduling_strategy: @scheduling_strategy,
|
885
938
|
launch_type: @launch_type,
|
939
|
+
capacity_provider_strategy: @capacity_provider_strategy,
|
886
940
|
platform_version: @platform_version,
|
887
941
|
network_configuration: @network_configuration,
|
888
942
|
health_check_grace_period_seconds: @health_check_grace_period_seconds,
|
943
|
+
propagate_tags: 'TASK_DEFINITION',
|
889
944
|
}
|
890
945
|
if @scheduling_strategy != 'DAEMON'
|
891
946
|
params[:desired_count] = 0
|
@@ -1154,17 +1209,33 @@ module Hako
|
|
1154
1209
|
|
1155
1210
|
# @param [Hash] definition
|
1156
1211
|
# @param [Hash<String, String>] additional_env
|
1212
|
+
# @param [Hako::CLI::Oneshot::Overrides, nil] overrides
|
1157
1213
|
# @return [nil]
|
1158
|
-
def print_definition_in_cli_format(definition, additional_env: {})
|
1214
|
+
def print_definition_in_cli_format(definition, additional_env: {}, overrides: nil)
|
1159
1215
|
cmd = %w[docker run]
|
1160
1216
|
cmd << '--name' << definition.fetch(:name)
|
1161
|
-
|
1162
|
-
if definition
|
1163
|
-
|
1164
|
-
|
1165
|
-
|
1166
|
-
|
1217
|
+
|
1218
|
+
if overrides && definition.fetch(:name) == 'app'
|
1219
|
+
cpu = overrides.app_cpu || definition.fetch(:cpu)
|
1220
|
+
cmd << '--cpu-shares' << cpu
|
1221
|
+
memory = overrides.app_memory || definition[:memory]
|
1222
|
+
if memory
|
1223
|
+
cmd << '--memory' << "#{memory}M"
|
1224
|
+
end
|
1225
|
+
memory_reservation = overrides.app_memory_reservation || definition[:memory_reservation]
|
1226
|
+
if memory_reservation
|
1227
|
+
cmd << '--memory-reservation' << "#{memory_reservation}M"
|
1228
|
+
end
|
1229
|
+
else
|
1230
|
+
cmd << '--cpu-shares' << definition.fetch(:cpu)
|
1231
|
+
if definition[:memory]
|
1232
|
+
cmd << '--memory' << "#{definition[:memory]}M"
|
1233
|
+
end
|
1234
|
+
if definition[:memory_reservation]
|
1235
|
+
cmd << '--memory-reservation' << "#{definition[:memory_reservation]}M"
|
1236
|
+
end
|
1167
1237
|
end
|
1238
|
+
|
1168
1239
|
definition.fetch(:links).each do |link|
|
1169
1240
|
cmd << '--link' << link
|
1170
1241
|
end
|
@@ -1227,9 +1298,6 @@ module Hako
|
|
1227
1298
|
cmd << '--tmpfs' << "#{tmpfs[:container_path]}:#{options.join(',')}"
|
1228
1299
|
end
|
1229
1300
|
end
|
1230
|
-
definition.fetch(:volumes_from).each do |volumes_from|
|
1231
|
-
p volumes_from
|
1232
|
-
end
|
1233
1301
|
if definition[:user]
|
1234
1302
|
cmd << '--user' << definition[:user]
|
1235
1303
|
end
|
@@ -1247,6 +1315,28 @@ module Hako
|
|
1247
1315
|
cmd << '--sysctl' << "#{system_control.fetch(:namespace)}=#{system_control.fetch(:value)}"
|
1248
1316
|
end
|
1249
1317
|
end
|
1318
|
+
if definition[:health_check]
|
1319
|
+
if definition[:health_check][:command]
|
1320
|
+
health_check_command_type = definition[:health_check][:command][0]
|
1321
|
+
case health_check_command_type
|
1322
|
+
when 'NONE'
|
1323
|
+
cmd << '--no-healthcheck'
|
1324
|
+
when 'CMD', 'CMD-SHELL'
|
1325
|
+
health_check_command = definition[:health_check][:command][1..-1].join(' ')
|
1326
|
+
cmd << '--health-cmd' << health_check_command.inspect
|
1327
|
+
else
|
1328
|
+
raise "Health check command type #{health_check_command_type} is not supported. CMD, CMD-SHELL and NONE are supported."
|
1329
|
+
end
|
1330
|
+
end
|
1331
|
+
if definition[:health_check][:retries]
|
1332
|
+
cmd << '--health-retries' << definition[:health_check][:retries]
|
1333
|
+
end
|
1334
|
+
%i[interval timeout start_period].each do |property|
|
1335
|
+
if definition[:health_check][property]
|
1336
|
+
cmd << "--health-#{property}" << "#{definition[:health_check][property]}s"
|
1337
|
+
end
|
1338
|
+
end
|
1339
|
+
end
|
1250
1340
|
|
1251
1341
|
cmd << "\\\n "
|
1252
1342
|
definition.fetch(:environment).each do |env|
|
@@ -1301,6 +1391,15 @@ module Hako
|
|
1301
1391
|
nil
|
1302
1392
|
end
|
1303
1393
|
|
1394
|
+
# @param [Hash, nil] expected_strategy
|
1395
|
+
# @param [Aws::ECS::Types::CapacityProviderStrategyItem, nil] actual_strategy
|
1396
|
+
# @return [Boolean]
|
1397
|
+
def different_capacity_provider_strategy?(expected_strategy, actual_strategy)
|
1398
|
+
expected = (expected_strategy || []).map { |s| [s[:capacity_provider], s[:weight] || 0, s[:base] || 0] }.sort
|
1399
|
+
actual = (actual_strategy || []).map { |s| [s.capacity_provider, s.weight, s.base] }.sort
|
1400
|
+
expected != actual
|
1401
|
+
end
|
1402
|
+
|
1304
1403
|
# @param [Aws::ECS::Types::Service] service
|
1305
1404
|
# @return [nil]
|
1306
1405
|
def warn_placement_policy_change(service)
|
@@ -162,9 +162,7 @@ module Hako
|
|
162
162
|
end
|
163
163
|
|
164
164
|
class Policy
|
165
|
-
attr_reader :policy_type
|
166
|
-
attr_reader :alarms, :cooldown, :adjustment_type, :scaling_adjustment, :metric_interval_lower_bound, :metric_interval_upper_bound, :metric_aggregation_type
|
167
|
-
attr_reader :target_value, :predefined_metric_type, :scale_out_cooldown, :scale_in_cooldown, :disable_scale_in
|
165
|
+
attr_reader :policy_type, :alarms, :cooldown, :adjustment_type, :scaling_adjustment, :metric_interval_lower_bound, :metric_interval_upper_bound, :metric_aggregation_type, :target_value, :predefined_metric_type, :scale_out_cooldown, :scale_in_cooldown, :disable_scale_in
|
168
166
|
|
169
167
|
# @param [Hash] options
|
170
168
|
def initialize(options)
|
@@ -46,6 +46,7 @@ module Hako
|
|
46
46
|
struct.member(:readonly_root_filesystem, Schema::Nullable.new(Schema::Boolean.new))
|
47
47
|
struct.member(:docker_security_options, Schema::Nullable.new(Schema::UnorderedArray.new(Schema::String.new)))
|
48
48
|
struct.member(:system_controls, Schema::Nullable.new(system_controls_schema))
|
49
|
+
struct.member(:repository_credentials, Schema::Nullable.new(repository_credentials_schema))
|
49
50
|
end
|
50
51
|
end
|
51
52
|
|
@@ -173,11 +174,21 @@ module Hako
|
|
173
174
|
end
|
174
175
|
|
175
176
|
def system_controls_schema
|
177
|
+
Schema::UnorderedArray.new(system_control_schema)
|
178
|
+
end
|
179
|
+
|
180
|
+
def system_control_schema
|
176
181
|
Schema::Structure.new.tap do |struct|
|
177
182
|
struct.member(:namespace, Schema::String.new)
|
178
183
|
struct.member(:value, Schema::String.new)
|
179
184
|
end
|
180
185
|
end
|
186
|
+
|
187
|
+
def repository_credentials_schema
|
188
|
+
Schema::Structure.new.tap do |struct|
|
189
|
+
struct.member(:credentials_parameter, Schema::String.new)
|
190
|
+
end
|
191
|
+
end
|
181
192
|
end
|
182
193
|
end
|
183
194
|
end
|
@@ -89,13 +89,22 @@ module Hako
|
|
89
89
|
target_type: @elb_v2_config.fetch('target_type', nil),
|
90
90
|
).target_groups[0]
|
91
91
|
else
|
92
|
+
matcher =
|
93
|
+
if @elb_v2_config.key?('matcher')
|
94
|
+
{
|
95
|
+
http_code: @elb_v2_config.fetch('matcher')['http_code'],
|
96
|
+
grpc_code: @elb_v2_config.fetch('matcher')['grpc_code'],
|
97
|
+
}
|
98
|
+
end
|
92
99
|
elb_client.create_target_group(
|
93
100
|
name: target_group_name,
|
94
101
|
port: 80,
|
95
102
|
protocol: 'HTTP',
|
103
|
+
protocol_version: @elb_v2_config.fetch('protocol_version', 'HTTP1'),
|
96
104
|
vpc_id: @elb_v2_config.fetch('vpc_id'),
|
97
105
|
health_check_path: @elb_v2_config.fetch('health_check_path', nil),
|
98
106
|
target_type: @elb_v2_config.fetch('target_type', nil),
|
107
|
+
matcher: matcher,
|
99
108
|
).target_groups[0]
|
100
109
|
end
|
101
110
|
|
@@ -23,6 +23,7 @@ module Hako
|
|
23
23
|
struct.member(:desired_count, Schema::Integer.new)
|
24
24
|
struct.member(:task_definition, Schema::String.new)
|
25
25
|
struct.member(:deployment_configuration, Schema::WithDefault.new(deployment_configuration_schema, default_configuration))
|
26
|
+
struct.member(:capacity_provider_strategy, Schema::Nullable.new(Schema::UnorderedArray.new(capacity_provider_strategy_schema)))
|
26
27
|
struct.member(:platform_version, Schema::WithDefault.new(Schema::String.new, 'LATEST'))
|
27
28
|
struct.member(:network_configuration, Schema::Nullable.new(network_configuration_schema))
|
28
29
|
struct.member(:health_check_grace_period_seconds, Schema::Nullable.new(Schema::Integer.new))
|
@@ -36,6 +37,14 @@ module Hako
|
|
36
37
|
end
|
37
38
|
end
|
38
39
|
|
40
|
+
def capacity_provider_strategy_schema
|
41
|
+
Schema::Structure.new.tap do |struct|
|
42
|
+
struct.member(:capacity_provider, Schema::String.new)
|
43
|
+
struct.member(:weight, Schema::WithDefault.new(Schema::Integer.new, 0))
|
44
|
+
struct.member(:base, Schema::WithDefault.new(Schema::Integer.new, 0))
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
39
48
|
def network_configuration_schema
|
40
49
|
Schema::Structure.new.tap do |struct|
|
41
50
|
struct.member(:awsvpc_configuration, awsvpc_configuration_schema)
|
@@ -46,7 +55,7 @@ module Hako
|
|
46
55
|
Schema::Structure.new.tap do |struct|
|
47
56
|
struct.member(:subnets, Schema::UnorderedArray.new(Schema::String.new))
|
48
57
|
struct.member(:security_groups, Schema::UnorderedArray.new(Schema::String.new))
|
49
|
-
struct.member(:assign_public_ip, Schema::String.new)
|
58
|
+
struct.member(:assign_public_ip, Schema::WithDefault.new(Schema::String.new, 'DISABLED'))
|
50
59
|
end
|
51
60
|
end
|
52
61
|
|
@@ -10,7 +10,7 @@ module Hako
|
|
10
10
|
class NginxFront < Script
|
11
11
|
S3Config = Struct.new(:region, :bucket, :prefix) do
|
12
12
|
# @param [Hash] options
|
13
|
-
def initialize(options)
|
13
|
+
def initialize(options) # rubocop:disable Lint/MissingSuper
|
14
14
|
self.region = options.fetch('region')
|
15
15
|
self.bucket = options.fetch('bucket')
|
16
16
|
self.prefix = options.fetch('prefix', nil)
|
data/lib/hako/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: hako
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.
|
4
|
+
version: 2.15.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Kohei Suzuki
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2020-11-02 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: aws-sdk-applicationautoscaling
|
@@ -86,14 +86,14 @@ dependencies:
|
|
86
86
|
requirements:
|
87
87
|
- - ">="
|
88
88
|
- !ruby/object:Gem::Version
|
89
|
-
version: 1.
|
89
|
+
version: 1.54.0
|
90
90
|
type: :runtime
|
91
91
|
prerelease: false
|
92
92
|
version_requirements: !ruby/object:Gem::Requirement
|
93
93
|
requirements:
|
94
94
|
- - ">="
|
95
95
|
- !ruby/object:Gem::Version
|
96
|
-
version: 1.
|
96
|
+
version: 1.54.0
|
97
97
|
- !ruby/object:Gem::Dependency
|
98
98
|
name: aws-sdk-elasticloadbalancing
|
99
99
|
requirement: !ruby/object:Gem::Requirement
|
@@ -114,14 +114,14 @@ dependencies:
|
|
114
114
|
requirements:
|
115
115
|
- - ">="
|
116
116
|
- !ruby/object:Gem::Version
|
117
|
-
version:
|
117
|
+
version: 1.54.0
|
118
118
|
type: :runtime
|
119
119
|
prerelease: false
|
120
120
|
version_requirements: !ruby/object:Gem::Requirement
|
121
121
|
requirements:
|
122
122
|
- - ">="
|
123
123
|
- !ruby/object:Gem::Version
|
124
|
-
version:
|
124
|
+
version: 1.54.0
|
125
125
|
- !ruby/object:Gem::Dependency
|
126
126
|
name: aws-sdk-s3
|
127
127
|
requirement: !ruby/object:Gem::Requirement
|
@@ -321,6 +321,7 @@ files:
|
|
321
321
|
- examples/hello-cap-add-app.jsonnet
|
322
322
|
- examples/hello-fargate-batch.jsonnet
|
323
323
|
- examples/hello-fargate.jsonnet
|
324
|
+
- examples/hello-grpc.jsonnet
|
324
325
|
- examples/hello-internal-nlb.jsonnet
|
325
326
|
- examples/hello-lb-v2.jsonnet
|
326
327
|
- examples/hello-lb.jsonnet
|
@@ -382,7 +383,7 @@ homepage: https://github.com/eagletmt/hako
|
|
382
383
|
licenses:
|
383
384
|
- MIT
|
384
385
|
metadata: {}
|
385
|
-
post_install_message:
|
386
|
+
post_install_message:
|
386
387
|
rdoc_options: []
|
387
388
|
require_paths:
|
388
389
|
- lib
|
@@ -390,15 +391,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
390
391
|
requirements:
|
391
392
|
- - ">="
|
392
393
|
- !ruby/object:Gem::Version
|
393
|
-
version: 2.
|
394
|
+
version: 2.5.0
|
394
395
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
395
396
|
requirements:
|
396
397
|
- - ">="
|
397
398
|
- !ruby/object:Gem::Version
|
398
399
|
version: '0'
|
399
400
|
requirements: []
|
400
|
-
rubygems_version: 3.
|
401
|
-
signing_key:
|
401
|
+
rubygems_version: 3.1.4
|
402
|
+
signing_key:
|
402
403
|
specification_version: 4
|
403
404
|
summary: Deploy Docker container
|
404
405
|
test_files: []
|