rollo 0.1.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 +7 -0
- data/.envrc +5 -0
- data/.gitignore +31 -0
- data/.rspec +3 -0
- data/.ruby-version +1 -0
- data/.travis.yml +5 -0
- data/CODE_OF_CONDUCT.md +75 -0
- data/Gemfile +6 -0
- data/Gemfile.lock +750 -0
- data/LICENSE.txt +21 -0
- data/README.md +58 -0
- data/Rakefile +24 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/exe/rollo +5 -0
- data/go +61 -0
- data/lib/rollo/commands/host_cluster.rb +184 -0
- data/lib/rollo/commands/main.rb +93 -0
- data/lib/rollo/commands/service_cluster.rb +124 -0
- data/lib/rollo/commands.rb +1 -0
- data/lib/rollo/model/host.rb +25 -0
- data/lib/rollo/model/host_cluster.rb +128 -0
- data/lib/rollo/model/scaling_activity.rb +32 -0
- data/lib/rollo/model/service.rb +104 -0
- data/lib/rollo/model/service_cluster.rb +53 -0
- data/lib/rollo/model.rb +2 -0
- data/lib/rollo/version.rb +3 -0
- data/lib/rollo.rb +5 -0
- data/rollo.gemspec +37 -0
- metadata +227 -0
data/LICENSE.txt
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2018 Toby Clemson
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
13
|
+
all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
|
+
THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,58 @@
|
|
1
|
+
# Rollo
|
2
|
+
|
3
|
+
Welcome to your new gem! In this directory, you'll find the files you need to
|
4
|
+
be able to package up your Ruby library into a gem. Put your Ruby code in the
|
5
|
+
file `lib/rollo`. To experiment with that code, run `bin/console` for an
|
6
|
+
interactive prompt.
|
7
|
+
|
8
|
+
TODO: Delete this and the text above, and describe your gem
|
9
|
+
|
10
|
+
## Installation
|
11
|
+
|
12
|
+
Add this line to your application's Gemfile:
|
13
|
+
|
14
|
+
```ruby
|
15
|
+
gem 'rollo'
|
16
|
+
```
|
17
|
+
|
18
|
+
And then execute:
|
19
|
+
|
20
|
+
$ bundle
|
21
|
+
|
22
|
+
Or install it yourself as:
|
23
|
+
|
24
|
+
$ gem install rollo
|
25
|
+
|
26
|
+
## Usage
|
27
|
+
|
28
|
+
TODO: Write usage instructions here
|
29
|
+
|
30
|
+
## Development
|
31
|
+
|
32
|
+
After checking out the repo, run `bin/setup` to install dependencies. Then, run
|
33
|
+
`rake spec` to run the tests. You can also run `bin/console` for an interactive
|
34
|
+
prompt that will allow you to experiment.
|
35
|
+
|
36
|
+
To install this gem onto your local machine, run `bundle exec rake install`. To
|
37
|
+
release a new version, update the version number in `version.rb`, and then run
|
38
|
+
`bundle exec rake release`, which will create a git tag for the version, push
|
39
|
+
git commits and tags, and push the `.gem` file to
|
40
|
+
[rubygems.org](https://rubygems.org).
|
41
|
+
|
42
|
+
## Contributing
|
43
|
+
|
44
|
+
Bug reports and pull requests are welcome on GitHub at
|
45
|
+
https://github.com/infrablocks/rollo. This project is intended to be a safe,
|
46
|
+
welcoming space for collaboration, and contributors are expected to adhere to
|
47
|
+
the [Contributor Covenant](http://contributor-covenant.org) code of conduct.
|
48
|
+
|
49
|
+
## License
|
50
|
+
|
51
|
+
The gem is available as open source under the terms of the
|
52
|
+
[MIT License](https://opensource.org/licenses/MIT).
|
53
|
+
|
54
|
+
## Code of Conduct
|
55
|
+
|
56
|
+
Everyone interacting in the Rollo project’s codebases, issue trackers, chat
|
57
|
+
rooms and mailing lists is expected to follow the [code of conduct](
|
58
|
+
https://github.com/[USERNAME]/rollo/blob/master/CODE_OF_CONDUCT.md).
|
data/Rakefile
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
require "rspec/core/rake_task"
|
2
|
+
|
3
|
+
RSpec::Core::RakeTask.new(:spec)
|
4
|
+
|
5
|
+
task :default => :spec
|
6
|
+
|
7
|
+
namespace :version do
|
8
|
+
desc "Bump version for specified type (pre, major, minor patch)"
|
9
|
+
task :bump, [:type] do |_, args|
|
10
|
+
bump_version_for(args.type)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
desc "Release gem"
|
15
|
+
task :release do
|
16
|
+
sh "gem release --tag --push"
|
17
|
+
end
|
18
|
+
|
19
|
+
def bump_version_for(version_type)
|
20
|
+
sh "gem bump --version #{version_type} " +
|
21
|
+
"&& bundle install " +
|
22
|
+
"&& export LAST_MESSAGE=\"$(git log -1 --pretty=%B)\" " +
|
23
|
+
"&& git commit -a --amend -m \"${LAST_MESSAGE} [ci skip]\""
|
24
|
+
end
|
data/bin/console
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require "bundler/setup"
|
4
|
+
require "rollo"
|
5
|
+
|
6
|
+
# You can add fixtures and/or initialization code here to make experimenting
|
7
|
+
# with your gem easier. You can also use a different console, if you like.
|
8
|
+
|
9
|
+
# (If you use this, don't forget to add pry to your Gemfile!)
|
10
|
+
# require "pry"
|
11
|
+
# Pry.start
|
12
|
+
|
13
|
+
require "irb"
|
14
|
+
IRB.start(__FILE__)
|
data/bin/setup
ADDED
data/exe/rollo
ADDED
data/go
ADDED
@@ -0,0 +1,61 @@
|
|
1
|
+
#!/usr/bin/env bash
|
2
|
+
|
3
|
+
[ -n "$GO_DEBUG" ] && set -x
|
4
|
+
set -e
|
5
|
+
|
6
|
+
project_dir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
7
|
+
|
8
|
+
verbose="no"
|
9
|
+
skip_checks="no"
|
10
|
+
offline="no"
|
11
|
+
|
12
|
+
missing_dependency="no"
|
13
|
+
|
14
|
+
[ -n "$GO_DEBUG" ] && verbose="yes"
|
15
|
+
[ -n "$GO_SKIP_CHECKS" ] && skip_checks="yes"
|
16
|
+
[ -n "$GO_OFFLINE" ] && offline="yes"
|
17
|
+
|
18
|
+
|
19
|
+
if [[ "$skip_checks" = "no" ]]; then
|
20
|
+
echo "Checking for system dependencies."
|
21
|
+
ruby_version="$(cat "$project_dir"/.ruby-version)"
|
22
|
+
if ! type ruby >/dev/null 2>&1 || ! ruby -v | grep -q "$ruby_version"; then
|
23
|
+
echo "This codebase requires Ruby $ruby_version."
|
24
|
+
missing_dependency="yes"
|
25
|
+
fi
|
26
|
+
|
27
|
+
if ! type bundler >/dev/null 2>&1; then
|
28
|
+
echo "This codebase requires Bundler."
|
29
|
+
missing_dependency="yes"
|
30
|
+
fi
|
31
|
+
|
32
|
+
if [[ "$missing_dependency" = "yes" ]]; then
|
33
|
+
echo "Please install missing dependencies to continue."
|
34
|
+
exit 1
|
35
|
+
fi
|
36
|
+
|
37
|
+
echo "All system dependencies present. Continuing."
|
38
|
+
fi
|
39
|
+
|
40
|
+
if [[ "$offline" = "no" ]]; then
|
41
|
+
echo "Installing bundler."
|
42
|
+
if [[ "$verbose" = "yes" ]]; then
|
43
|
+
gem install --no-document bundler
|
44
|
+
else
|
45
|
+
gem install --no-document bundler > /dev/null
|
46
|
+
fi
|
47
|
+
|
48
|
+
echo "Installing ruby dependencies."
|
49
|
+
if [[ "$verbose" = "yes" ]]; then
|
50
|
+
bundle install
|
51
|
+
else
|
52
|
+
bundle install > /dev/null
|
53
|
+
fi
|
54
|
+
fi
|
55
|
+
|
56
|
+
echo "Starting rake."
|
57
|
+
if [[ "$verbose" = "yes" ]]; then
|
58
|
+
time bundle exec rake --verbose "$@"
|
59
|
+
else
|
60
|
+
time bundle exec rake "$@"
|
61
|
+
fi
|
@@ -0,0 +1,184 @@
|
|
1
|
+
require 'thor'
|
2
|
+
require_relative '../model'
|
3
|
+
|
4
|
+
module Rollo
|
5
|
+
module Commands
|
6
|
+
class HostCluster < Thor
|
7
|
+
def self.exit_on_failure?
|
8
|
+
true
|
9
|
+
end
|
10
|
+
|
11
|
+
desc(
|
12
|
+
'expand REGION ASG_NAME ECS_CLUSTER_NAME',
|
13
|
+
'')
|
14
|
+
method_option(
|
15
|
+
:batch_size,
|
16
|
+
aliases: '-b',
|
17
|
+
type: :numeric,
|
18
|
+
default: 3,
|
19
|
+
desc: 'The number of hosts to add at a time.')
|
20
|
+
def expand(
|
21
|
+
region, asg_name, _,
|
22
|
+
host_cluster = nil)
|
23
|
+
batch_size = options[:batch_size]
|
24
|
+
|
25
|
+
host_cluster = host_cluster ||
|
26
|
+
Rollo::HostCluster.new(asg_name, region)
|
27
|
+
|
28
|
+
say("Increasing host cluster desired capacity by #{batch_size}...")
|
29
|
+
with_padding do
|
30
|
+
host_cluster.increase_capacity_by(batch_size) do |on|
|
31
|
+
on.prepare do |current, target|
|
32
|
+
say(
|
33
|
+
"Changing desired capacity from #{current} to " +
|
34
|
+
"#{target}...")
|
35
|
+
end
|
36
|
+
on.waiting_for_start do |attempt|
|
37
|
+
say(
|
38
|
+
'Waiting for capacity change to start ' +
|
39
|
+
"(attempt #{attempt})...")
|
40
|
+
end
|
41
|
+
on.waiting_for_end do |attempt|
|
42
|
+
say(
|
43
|
+
'Waiting for capacity change to complete ' +
|
44
|
+
"(attempt #{attempt})...")
|
45
|
+
end
|
46
|
+
on.waiting_for_health do |attempt|
|
47
|
+
say("Waiting for a healthy state (attempt #{attempt})")
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
say "Host cluster desired capacity increased, continuing..."
|
52
|
+
end
|
53
|
+
|
54
|
+
desc(
|
55
|
+
'contract REGION ASG_NAME ECS_CLUSTER_NAME',
|
56
|
+
'')
|
57
|
+
method_option(
|
58
|
+
:batch_size,
|
59
|
+
aliases: '-b',
|
60
|
+
type: :numeric,
|
61
|
+
default: 3,
|
62
|
+
desc: 'The number of hosts to remove at a time.')
|
63
|
+
def contract(
|
64
|
+
region, asg_name, ecs_cluster_name,
|
65
|
+
host_cluster = nil, service_cluster = nil)
|
66
|
+
batch_size = options[:batch_size]
|
67
|
+
|
68
|
+
host_cluster = host_cluster ||
|
69
|
+
Rollo::HostCluster.new(asg_name, region)
|
70
|
+
service_cluster = service_cluster ||
|
71
|
+
Rollo::ServiceCluster.new(ecs_cluster_name, region)
|
72
|
+
|
73
|
+
say("Decreasing host cluster desired capacity by #{batch_size}...")
|
74
|
+
with_padding do
|
75
|
+
host_cluster.decrease_capacity_by(batch_size) do |on|
|
76
|
+
on.prepare do |current, target|
|
77
|
+
say(
|
78
|
+
"Changing desired capacity from #{current} to " +
|
79
|
+
"#{target}...")
|
80
|
+
end
|
81
|
+
on.waiting_for_start do |attempt|
|
82
|
+
say(
|
83
|
+
"Waiting for capacity change to start " +
|
84
|
+
"(attempt #{attempt})...")
|
85
|
+
end
|
86
|
+
on.waiting_for_end do |attempt|
|
87
|
+
say(
|
88
|
+
"Waiting for capacity change to complete " +
|
89
|
+
"(attempt #{attempt})...")
|
90
|
+
end
|
91
|
+
on.waiting_for_health do |attempt|
|
92
|
+
say(
|
93
|
+
"Waiting for host cluster to reach healthy state " +
|
94
|
+
"(attempt #{attempt})...")
|
95
|
+
end
|
96
|
+
end
|
97
|
+
service_cluster.with_replica_services do |on|
|
98
|
+
on.each_service do |service|
|
99
|
+
service.wait_for_service_health do |on|
|
100
|
+
on.waiting_for_health do |attempt|
|
101
|
+
say(
|
102
|
+
"Waiting for service #{service.name} to reach a " +
|
103
|
+
"steady state (attempt #{attempt})...")
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
109
|
+
say "Host cluster desired capacity decreased, continuing..."
|
110
|
+
end
|
111
|
+
|
112
|
+
desc(
|
113
|
+
'terminate REGION ASG_NAME ECS_CLUSTER_NAME INSTANCE_IDS*',
|
114
|
+
'')
|
115
|
+
method_option(
|
116
|
+
:batch_size,
|
117
|
+
aliases: '-b',
|
118
|
+
type: :numeric,
|
119
|
+
default: 3,
|
120
|
+
desc: 'The number of hosts to add at a time.')
|
121
|
+
method_option(
|
122
|
+
:startup_time,
|
123
|
+
aliases: '-t',
|
124
|
+
type: :numeric,
|
125
|
+
default: 2,
|
126
|
+
desc: 'The number of minutes to wait for services to start up.')
|
127
|
+
def terminate(
|
128
|
+
region, asg_name, ecs_cluster_name, instance_ids,
|
129
|
+
host_cluster = nil, service_cluster = nil)
|
130
|
+
batch_size = options[:batch_size]
|
131
|
+
|
132
|
+
service_start_wait_minutes = options[:startup_time]
|
133
|
+
service_start_wait_seconds = 60 * service_start_wait_minutes
|
134
|
+
|
135
|
+
host_cluster = host_cluster ||
|
136
|
+
Rollo::HostCluster.new(asg_name, region)
|
137
|
+
service_cluster = service_cluster ||
|
138
|
+
Rollo::ServiceCluster.new(ecs_cluster_name, region)
|
139
|
+
|
140
|
+
hosts = host_cluster.hosts.select {|h| instance_ids.include?(h.id) }
|
141
|
+
host_batches = hosts.each_slice(batch_size).to_a
|
142
|
+
|
143
|
+
say(
|
144
|
+
'Terminating old hosts in host cluster in batches of ' +
|
145
|
+
"#{batch_size}...")
|
146
|
+
with_padding do
|
147
|
+
host_batches.each_with_index do |host_batch, index|
|
148
|
+
say(
|
149
|
+
"Batch #{index + 1} contains hosts: " +
|
150
|
+
"\n\t\t[#{host_batch.map(&:id).join(",\n\t\t ")}]\n" +
|
151
|
+
'Terminating...')
|
152
|
+
host_batch.each(&:terminate)
|
153
|
+
host_cluster.wait_for_capacity_health do |on|
|
154
|
+
on.waiting_for_health do |attempt|
|
155
|
+
say(
|
156
|
+
'Waiting for host cluster to reach healthy state ' +
|
157
|
+
"(attempt #{attempt})")
|
158
|
+
end
|
159
|
+
end
|
160
|
+
service_cluster.with_replica_services do |on|
|
161
|
+
on.each_service do |service|
|
162
|
+
service.wait_for_service_health do |on|
|
163
|
+
on.waiting_for_health do |attempt|
|
164
|
+
say(
|
165
|
+
"Waiting for service #{service.name} to reach a " +
|
166
|
+
"steady state (attempt #{attempt})...")
|
167
|
+
end
|
168
|
+
end
|
169
|
+
end
|
170
|
+
end
|
171
|
+
say(
|
172
|
+
"Waiting #{service_start_wait_minutes} minute(s) for " +
|
173
|
+
'services to finish starting...')
|
174
|
+
sleep(service_start_wait_seconds)
|
175
|
+
say(
|
176
|
+
"Waited #{service_start_wait_minutes} minute(s). " +
|
177
|
+
'Continuing...')
|
178
|
+
end
|
179
|
+
end
|
180
|
+
|
181
|
+
end
|
182
|
+
end
|
183
|
+
end
|
184
|
+
end
|
@@ -0,0 +1,93 @@
|
|
1
|
+
require 'thor'
|
2
|
+
require_relative '../model'
|
3
|
+
require_relative './host_cluster'
|
4
|
+
require_relative './service_cluster'
|
5
|
+
|
6
|
+
module Rollo
|
7
|
+
module Commands
|
8
|
+
class Main < Thor
|
9
|
+
def self.exit_on_failure?
|
10
|
+
true
|
11
|
+
end
|
12
|
+
|
13
|
+
desc('host-cluster', 'manages the host cluster')
|
14
|
+
subcommand "host-cluster", HostCluster
|
15
|
+
|
16
|
+
desc('service-cluster', 'manages the service cluster')
|
17
|
+
subcommand "service-cluster", ServiceCluster
|
18
|
+
|
19
|
+
desc('version', 'prints the version number of rollo')
|
20
|
+
def version
|
21
|
+
say Rollo::VERSION
|
22
|
+
end
|
23
|
+
|
24
|
+
desc('roll REGION ASG_NAME ECS_CLUSTER_NAME',
|
25
|
+
'rolls all instances in an ECS cluster')
|
26
|
+
method_option(
|
27
|
+
:batch_size,
|
28
|
+
aliases: '-b',
|
29
|
+
type: :numeric,
|
30
|
+
default: 3,
|
31
|
+
desc:
|
32
|
+
'The number of hosts / service instances to add / remove at ' +
|
33
|
+
'a time.')
|
34
|
+
def roll(region, asg_name, ecs_cluster_name)
|
35
|
+
host_cluster = Rollo::HostCluster.new(asg_name, region)
|
36
|
+
service_cluster = Rollo::ServiceCluster.new(ecs_cluster_name, region)
|
37
|
+
|
38
|
+
initial_hosts = host_cluster.hosts
|
39
|
+
|
40
|
+
say(
|
41
|
+
"Rolling instances in host cluster #{host_cluster.name} for " +
|
42
|
+
"service cluster #{service_cluster.name}...")
|
43
|
+
with_padding do
|
44
|
+
unless host_cluster.has_desired_capacity?
|
45
|
+
say('ERROR: Host cluster is not in stable state.')
|
46
|
+
say('This may be due to scaling above or below the desired')
|
47
|
+
say('capacity or because hosts are not in service or are ')
|
48
|
+
say('unhealthy. Cowardly refusing to roll instances.')
|
49
|
+
exit 1
|
50
|
+
end
|
51
|
+
|
52
|
+
invoke(
|
53
|
+
"host-cluster:expand",
|
54
|
+
[
|
55
|
+
region, asg_name, ecs_cluster_name,
|
56
|
+
host_cluster
|
57
|
+
])
|
58
|
+
|
59
|
+
invoke(
|
60
|
+
"service-cluster:expand",
|
61
|
+
[
|
62
|
+
region, asg_name, ecs_cluster_name,
|
63
|
+
service_cluster
|
64
|
+
])
|
65
|
+
|
66
|
+
invoke(
|
67
|
+
"host-cluster:terminate",
|
68
|
+
[
|
69
|
+
region, asg_name, ecs_cluster_name, initial_hosts.map(&:id),
|
70
|
+
host_cluster, service_cluster
|
71
|
+
])
|
72
|
+
|
73
|
+
invoke(
|
74
|
+
"host-cluster:contract",
|
75
|
+
[
|
76
|
+
region, asg_name, ecs_cluster_name,
|
77
|
+
host_cluster, service_cluster
|
78
|
+
])
|
79
|
+
|
80
|
+
invoke(
|
81
|
+
"service-cluster:contract",
|
82
|
+
[
|
83
|
+
region, asg_name, ecs_cluster_name,
|
84
|
+
service_cluster
|
85
|
+
])
|
86
|
+
end
|
87
|
+
|
88
|
+
say("Instances in host cluster #{host_cluster.name} rolled " +
|
89
|
+
"successfully.")
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
@@ -0,0 +1,124 @@
|
|
1
|
+
require 'thor'
|
2
|
+
require_relative '../model'
|
3
|
+
|
4
|
+
module Rollo
|
5
|
+
module Commands
|
6
|
+
class ServiceCluster < Thor
|
7
|
+
def self.exit_on_failure?
|
8
|
+
true
|
9
|
+
end
|
10
|
+
|
11
|
+
desc(
|
12
|
+
'expand REGION ASG_NAME ECS_CLUSTER_NAME',
|
13
|
+
'')
|
14
|
+
method_option(
|
15
|
+
:batch_size,
|
16
|
+
aliases: '-b',
|
17
|
+
type: :numeric,
|
18
|
+
default: 3,
|
19
|
+
desc: 'The number of service instances to add at a time.')
|
20
|
+
method_option(
|
21
|
+
:startup_time,
|
22
|
+
aliases: '-t',
|
23
|
+
type: :numeric,
|
24
|
+
default: 2,
|
25
|
+
desc: 'The number of minutes to wait for services to start up.')
|
26
|
+
|
27
|
+
def expand(
|
28
|
+
region, _, ecs_cluster_name,
|
29
|
+
service_cluster = nil)
|
30
|
+
batch_size = options[:batch_size]
|
31
|
+
service_start_wait_minutes = options[:startup_time]
|
32
|
+
service_start_wait_seconds = 60 * service_start_wait_minutes
|
33
|
+
|
34
|
+
service_cluster = service_cluster ||
|
35
|
+
Rollo::ServiceCluster.new(ecs_cluster_name, region)
|
36
|
+
|
37
|
+
say("Increasing service instance counts by #{batch_size}...")
|
38
|
+
with_padding do
|
39
|
+
service_cluster.with_replica_services do |on|
|
40
|
+
on.start do |services|
|
41
|
+
say(
|
42
|
+
'Service cluster contains services:' +
|
43
|
+
"\n\t\t[#{services.map(&:name).join(",\n\t\t ")}]")
|
44
|
+
end
|
45
|
+
on.each_service do |service|
|
46
|
+
say(
|
47
|
+
"Increasing instance count by #{batch_size} " +
|
48
|
+
"for #{service.name}")
|
49
|
+
with_padding do
|
50
|
+
service.increase_instance_count_by(batch_size) do |on|
|
51
|
+
on.prepare do |current, target|
|
52
|
+
say(
|
53
|
+
"Changing instance count from #{current} " +
|
54
|
+
"to #{target}...")
|
55
|
+
end
|
56
|
+
on.waiting_for_health do |attempt|
|
57
|
+
say(
|
58
|
+
"Waiting for service to reach a steady state " +
|
59
|
+
"(attempt #{attempt})...")
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
say(
|
67
|
+
"Waiting #{service_start_wait_minutes} minute(s) for " +
|
68
|
+
'services to finish starting...')
|
69
|
+
with_padding do
|
70
|
+
sleep(service_start_wait_seconds)
|
71
|
+
say(
|
72
|
+
"Waited #{service_start_wait_minutes} minute(s). " +
|
73
|
+
'Continuing...')
|
74
|
+
end
|
75
|
+
say('Service instance counts increased, continuing...')
|
76
|
+
end
|
77
|
+
|
78
|
+
desc(
|
79
|
+
'contract REGION ASG_NAME ECS_CLUSTER_NAME',
|
80
|
+
'')
|
81
|
+
method_option(
|
82
|
+
:batch_size,
|
83
|
+
aliases: '-b',
|
84
|
+
type: :numeric,
|
85
|
+
default: 3,
|
86
|
+
desc: 'The number of service instances to remove at a time.')
|
87
|
+
|
88
|
+
def contract(
|
89
|
+
region, _, ecs_cluster_name,
|
90
|
+
service_cluster = nil)
|
91
|
+
batch_size = options[:batch_size]
|
92
|
+
|
93
|
+
service_cluster = service_cluster ||
|
94
|
+
Rollo::ServiceCluster.new(ecs_cluster_name, region)
|
95
|
+
|
96
|
+
say("Decreasing service instance counts by #{batch_size}...")
|
97
|
+
with_padding do
|
98
|
+
service_cluster.with_replica_services do |on|
|
99
|
+
on.each_service do |service|
|
100
|
+
say(
|
101
|
+
"Decreasing instance count by #{batch_size} " +
|
102
|
+
"for #{service.name}")
|
103
|
+
with_padding do
|
104
|
+
service.decrease_instance_count_by(batch_size) do |on|
|
105
|
+
on.prepare do |current, target|
|
106
|
+
say(
|
107
|
+
"Changing instance count from #{current} " +
|
108
|
+
"to #{target}...")
|
109
|
+
end
|
110
|
+
on.waiting_for_health do |attempt|
|
111
|
+
say(
|
112
|
+
'Waiting for service to reach a steady state ' +
|
113
|
+
"(attempt #{attempt})...")
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
120
|
+
say("Service instance counts decreased, continuing...")
|
121
|
+
end
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
require_relative 'commands/main'
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module Rollo
|
2
|
+
module Model
|
3
|
+
class Host
|
4
|
+
def initialize(instance)
|
5
|
+
@instance = instance
|
6
|
+
end
|
7
|
+
|
8
|
+
def id
|
9
|
+
@instance.id
|
10
|
+
end
|
11
|
+
|
12
|
+
def terminate
|
13
|
+
@instance.terminate(should_decrement_desired_capacity: false)
|
14
|
+
end
|
15
|
+
|
16
|
+
def is_in_service?
|
17
|
+
@instance.lifecycle_state == 'InService'
|
18
|
+
end
|
19
|
+
|
20
|
+
def is_healthy?
|
21
|
+
@instance.health_status == 'Healthy'
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|