ufo 3.5.7 → 4.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +24 -0
- data/Gemfile.lock +16 -10
- data/README.md +12 -13
- data/docs/_config.yml +1 -1
- data/docs/_docs/auto-completion.md +4 -4
- data/docs/_docs/automated-cleanup.md +1 -1
- data/docs/_docs/conventions.md +7 -7
- data/docs/_docs/customize-cloudformation.md +36 -0
- data/docs/_docs/faq.md +9 -7
- data/docs/_docs/fargate.md +102 -0
- data/docs/_docs/helpers.md +3 -3
- data/docs/_docs/load-balancer.md +72 -0
- data/docs/_docs/migrations.md +2 -2
- data/docs/_docs/next-steps.md +2 -2
- data/docs/_docs/params.md +12 -41
- data/docs/_docs/route53-support.md +28 -0
- data/docs/_docs/run-in-pieces.md +2 -2
- data/docs/_docs/security-groups.md +54 -0
- data/docs/_docs/settings-cfn.md +11 -0
- data/docs/_docs/settings-network.md +34 -0
- data/docs/_docs/settings.md +18 -15
- data/docs/_docs/single-task.md +3 -3
- data/docs/_docs/ssl-support.md +42 -0
- data/docs/_docs/structure.md +5 -1
- data/docs/_docs/stuck-cloudformation.md +30 -0
- data/docs/_docs/tutorial-ufo-docker-build.md +19 -31
- data/docs/_docs/tutorial-ufo-init.md +16 -12
- data/docs/_docs/tutorial-ufo-ship.md +50 -54
- data/docs/_docs/tutorial-ufo-ships.md +9 -7
- data/docs/_docs/tutorial-ufo-tasks-build.md +26 -17
- data/docs/_docs/ufo-current.md +50 -0
- data/docs/_docs/ufo-env-extra.md +21 -0
- data/docs/_docs/ufo-env.md +6 -13
- data/docs/_docs/ufo-tasks-register.md +3 -3
- data/docs/_docs/upgrade4.md +49 -0
- data/docs/_docs/variables.md +5 -5
- data/docs/_docs/why-cloudformation.md +22 -0
- data/docs/_includes/about.html +1 -1
- data/docs/_includes/cfn-customize.md +39 -0
- data/docs/_includes/commands.html +6 -6
- data/docs/_includes/css/ufo.css +1 -0
- data/docs/_includes/example.html +13 -13
- data/docs/_includes/reference.md +1 -1
- data/docs/_includes/subnav.html +22 -5
- data/docs/_includes/ufo-ship-options.md +7 -6
- data/docs/_reference/ufo-apps.md +36 -0
- data/docs/_reference/ufo-cancel.md +24 -0
- data/docs/_reference/ufo-completion.md +1 -1
- data/docs/_reference/ufo-completion_script.md +1 -1
- data/docs/_reference/ufo-current.md +93 -0
- data/docs/_reference/ufo-deploy.md +18 -17
- data/docs/_reference/ufo-destroy.md +6 -4
- data/docs/_reference/ufo-docker-base.md +7 -7
- data/docs/_reference/ufo-docker-build.md +9 -9
- data/docs/_reference/ufo-docker-clean.md +8 -8
- data/docs/_reference/ufo-docker-name.md +4 -4
- data/docs/_reference/ufo-docker.md +4 -2
- data/docs/_reference/ufo-init.md +31 -20
- data/docs/_reference/ufo-network-help.md +15 -0
- data/docs/_reference/ufo-network-init.md +38 -0
- data/docs/_reference/ufo-network.md +26 -0
- data/docs/_reference/ufo-ps.md +53 -0
- data/docs/_reference/ufo-releases.md +40 -0
- data/docs/_reference/ufo-resources.md +44 -0
- data/docs/_reference/ufo-rollback.md +59 -0
- data/docs/_reference/ufo-scale.md +23 -3
- data/docs/_reference/ufo-ship.md +54 -27
- data/docs/_reference/ufo-ships.md +17 -26
- data/docs/_reference/ufo-stop.md +31 -0
- data/docs/_reference/ufo-task.md +15 -16
- data/docs/_reference/ufo-tasks-build.md +10 -10
- data/docs/_reference/ufo-tasks-register.md +3 -3
- data/docs/_reference/ufo-tasks.md +1 -1
- data/docs/_reference/ufo-upgrade-help.md +15 -0
- data/docs/_reference/ufo-upgrade-v2to3.md +15 -0
- data/docs/_reference/ufo-upgrade-v3_3to3_4.md +15 -0
- data/docs/_reference/ufo-upgrade-v3to4.md +27 -0
- data/docs/_reference/ufo-upgrade.md +28 -0
- data/docs/_reference/ufo-version.md +1 -1
- data/docs/articles.md +2 -2
- data/docs/docs.md +1 -1
- data/docs/img/docs/cloudformation-resources.png +0 -0
- data/docs/img/tutorials/ecs-console-task-definitions.png +0 -0
- data/docs/img/tutorials/ecs-console-ufo-ship.png +0 -0
- data/docs/img/tutorials/ecs-console-ufo-ships.png +0 -0
- data/docs/quick-start.md +21 -9
- data/docs/reference.md +10 -2
- data/exe/ufo +1 -1
- data/lib/cfn/stack.yml +259 -0
- data/lib/template/.ufo/params.yml.tt +21 -60
- data/lib/template/.ufo/settings.yml.tt +6 -1
- data/lib/template/.ufo/settings/cfn/default.yml.tt +55 -0
- data/lib/template/.ufo/settings/network/default.yml.tt +18 -0
- data/lib/template/.ufo/task_definitions.rb.tt +7 -6
- data/lib/template/.ufo/templates/fargate.json.erb +1 -1
- data/lib/template/.ufo/templates/main.json.erb +1 -0
- data/lib/template/.ufo/variables/base.rb.tt +5 -2
- data/lib/template/Dockerfile +10 -15
- data/lib/template/bin/deploy.tt +2 -2
- data/lib/ufo.rb +29 -20
- data/lib/ufo/apps.rb +49 -0
- data/lib/ufo/apps/cfn_map.rb +70 -0
- data/lib/ufo/apps/service.rb +56 -0
- data/lib/ufo/aws_service.rb +15 -6
- data/lib/ufo/base.rb +32 -0
- data/lib/ufo/cancel.rb +23 -0
- data/lib/ufo/cli.rb +91 -27
- data/lib/ufo/core.rb +35 -3
- data/lib/ufo/current.rb +104 -0
- data/lib/ufo/destroy.rb +10 -41
- data/lib/ufo/docker/builder.rb +5 -4
- data/lib/ufo/docker/cleaner.rb +1 -1
- data/lib/ufo/docker/pusher.rb +2 -2
- data/lib/ufo/ecr/cleaner.rb +1 -1
- data/lib/ufo/help/apps.md +12 -0
- data/lib/ufo/help/balancer.md +3 -0
- data/lib/ufo/help/current.md +65 -0
- data/lib/ufo/help/deploy.md +4 -4
- data/lib/ufo/help/destroy.md +3 -3
- data/lib/ufo/help/docker.md +3 -1
- data/lib/ufo/help/docker/base.md +7 -7
- data/lib/ufo/help/docker/build.md +9 -9
- data/lib/ufo/help/docker/clean.md +8 -8
- data/lib/ufo/help/docker/name.md +4 -4
- data/lib/ufo/help/help.md +5 -0
- data/lib/ufo/help/init.md +24 -16
- data/lib/ufo/help/network/init.md +13 -0
- data/lib/ufo/help/ps.md +27 -0
- data/lib/ufo/help/releases.md +16 -0
- data/lib/ufo/help/resources.md +20 -0
- data/lib/ufo/help/rollback.md +35 -0
- data/lib/ufo/help/scale.md +22 -2
- data/lib/ufo/help/ship.md +40 -14
- data/lib/ufo/help/ships.md +4 -13
- data/lib/ufo/help/stop.md +7 -0
- data/lib/ufo/help/task.md +9 -9
- data/lib/ufo/help/tasks/build.md +10 -10
- data/lib/ufo/help/tasks/register.md +3 -3
- data/lib/ufo/help/upgrade/v3to4.md +3 -0
- data/lib/ufo/info.rb +62 -0
- data/lib/ufo/init.rb +36 -23
- data/lib/ufo/log_group.rb +2 -1
- data/lib/ufo/network.rb +24 -0
- data/lib/ufo/network/fetch.rb +41 -0
- data/lib/ufo/network/helper.rb +23 -0
- data/lib/ufo/network/init.rb +26 -0
- data/lib/ufo/param.rb +5 -5
- data/lib/ufo/ps.rb +102 -0
- data/lib/ufo/ps/task.rb +78 -0
- data/lib/ufo/releases.rb +14 -0
- data/lib/ufo/rollback.rb +53 -0
- data/lib/ufo/scale.rb +6 -12
- data/lib/ufo/sequence.rb +7 -0
- data/lib/ufo/setting.rb +7 -6
- data/lib/ufo/setting/profile.rb +24 -0
- data/lib/ufo/ship.rb +35 -326
- data/lib/ufo/stack.rb +203 -0
- data/lib/ufo/stack/context.rb +242 -0
- data/lib/ufo/stack/helper.rb +28 -0
- data/lib/ufo/stack/status.rb +195 -0
- data/lib/ufo/stop.rb +47 -0
- data/lib/ufo/task.rb +96 -15
- data/lib/ufo/tasks/register.rb +1 -1
- data/lib/ufo/template_scope.rb +81 -7
- data/lib/ufo/upgrade.rb +32 -0
- data/lib/ufo/{upgrade3.rb → upgrade/upgrade3.rb} +1 -1
- data/lib/ufo/{upgrade33_to_34.rb → upgrade/upgrade33to34.rb} +2 -2
- data/lib/ufo/upgrade/upgrade4.rb +161 -0
- data/lib/ufo/util.rb +19 -6
- data/lib/ufo/version.rb +1 -1
- data/spec/fixtures/apps/describe_services.json +96 -0
- data/spec/fixtures/cfn/stack-events-complete.json +1080 -0
- data/spec/fixtures/cfn/stack-events-in-progress.json +1080 -0
- data/spec/fixtures/cfn/stack-events-update-rollback-complete.json +1086 -0
- data/spec/fixtures/deployments.json +50 -0
- data/spec/fixtures/ps/describe_tasks.json +58 -0
- data/spec/fixtures/settings.yml +2 -0
- data/spec/lib/apps_spec.rb +20 -0
- data/spec/lib/cli_spec.rb +4 -4
- data/spec/lib/ps_spec.rb +14 -0
- data/spec/lib/setting_spec.rb +2 -1
- data/spec/lib/ship_spec.rb +6 -30
- data/spec/lib/stack/status_spec.rb +76 -0
- data/spec/lib/stop_spec.rb +13 -0
- data/spec/lib/task_spec.rb +5 -2
- data/spec/spec_helper.rb +1 -1
- data/ufo.gemspec +2 -0
- metadata +120 -6
- data/docs/_reference/ufo-upgrade3.md +0 -23
- data/docs/_reference/ufo-upgrade3_3_to_3_4.md +0 -23
data/lib/ufo/init.rb
CHANGED
@@ -1,23 +1,23 @@
|
|
1
1
|
module Ufo
|
2
2
|
class Init < Sequence
|
3
|
-
|
4
|
-
# https://github.com/erikhuda/thor/blob/master/lib/thor/actions.rb#L49
|
3
|
+
include Network::Helper
|
5
4
|
|
6
5
|
# Ugly, this is how I can get the options from to match with this Thor::Group
|
7
6
|
def self.cli_options
|
8
7
|
[
|
9
8
|
[:force, type: :boolean, desc: "Bypass overwrite are you sure prompt for existing files."],
|
10
|
-
[:image, required: true, desc: "Docker image name without the tag. Example: tongueroo/
|
11
|
-
[:app,
|
9
|
+
[:image, required: true, desc: "Docker image name without the tag. Example: tongueroo/demo-ufo. Configures ufo/settings.yml"],
|
10
|
+
[:app, desc: "App name. Preferably one word. Used in the generated ufo/task_definitions.rb. If not specified then the app name is inferred as the folder name."],
|
12
11
|
[:launch_type, default: "ec2", desc: "ec2 or fargate."],
|
13
12
|
[:execution_role_arn, desc: "execution role arn used by tasks, required for fargate."],
|
14
13
|
[:template, desc: "Custom template to use."],
|
15
14
|
[:template_mode, desc: "Template mode: replace or additive."],
|
15
|
+
[:vpc_id, desc: "Vpc id. For settings/network/default.yml."],
|
16
|
+
[:ecs_subnets, type: :array, desc: "Subnets for ECS tasks, defaults to --elb-subnets set to. For settings/network/default.yml"],
|
17
|
+
[:elb_subnets, type: :array, desc: "Subnets for ELB. For settings/network/default.yml"],
|
16
18
|
]
|
17
19
|
end
|
18
|
-
cli_options.each
|
19
|
-
class_option *args
|
20
|
-
end
|
20
|
+
cli_options.each { |o| class_option(*o) }
|
21
21
|
|
22
22
|
def setup_template_repo
|
23
23
|
return unless @options[:template]&.include?('/')
|
@@ -48,26 +48,29 @@ module Ufo
|
|
48
48
|
FileUtils.cd(dest)
|
49
49
|
end
|
50
50
|
|
51
|
+
def set_network_options
|
52
|
+
configure_network_settings
|
53
|
+
end
|
54
|
+
|
51
55
|
def init_files
|
52
56
|
# map variables
|
53
|
-
@app = options[:app]
|
57
|
+
@app = options[:app] || inferred_app
|
54
58
|
@image = options[:image]
|
55
59
|
@execution_role_arn_input = get_execution_role_arn_input
|
56
60
|
# copy the files
|
57
61
|
puts "Setting up ufo project..."
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
else
|
63
|
-
copy_file ".ufo/templates/main.json.erb"
|
64
|
-
end
|
62
|
+
exclude_pattern = File.exist?("#{Ufo.root}/Dockerfile") ?
|
63
|
+
/(\.git|Dockerfile)/ :
|
64
|
+
/(\.git)/
|
65
|
+
directory ".", exclude_pattern: exclude_pattern
|
65
66
|
end
|
66
67
|
|
67
68
|
def upsert_gitignore
|
68
69
|
text =<<-EOL
|
69
|
-
.ufo/
|
70
|
+
.ufo/current
|
70
71
|
.ufo/data
|
72
|
+
.ufo/log
|
73
|
+
.ufo/output
|
71
74
|
EOL
|
72
75
|
if File.exist?(".gitignore")
|
73
76
|
append_to_file ".gitignore", text
|
@@ -77,9 +80,7 @@ EOL
|
|
77
80
|
end
|
78
81
|
|
79
82
|
def upsert_dockerignore
|
80
|
-
text
|
81
|
-
.ufo
|
82
|
-
EOL
|
83
|
+
text = ".ufo\n"
|
83
84
|
if File.exist?(".dockerignore")
|
84
85
|
append_to_file ".dockerignore", text
|
85
86
|
else
|
@@ -90,18 +91,30 @@ EOL
|
|
90
91
|
def user_message
|
91
92
|
puts "Starter ufo files created."
|
92
93
|
puts <<-EOL
|
94
|
+
Congrats 🎉 You have successfully set up ufo for your project.
|
93
95
|
#{"="*64}
|
94
|
-
Congrats 🎉 You have successfully set up ufo for your project. To deploy to ECS:
|
95
96
|
|
96
|
-
|
97
|
+
## Task Definition Customizations
|
97
98
|
|
98
99
|
If you need to customize the ECS task definition to configure things like memory and cpu allocation. You can do this by adjusting the files the .ufo/variables folder. These variables get applied to the .ufo/templates/main.json.erb task definition json that is passed to the ECS register task definition api.
|
99
100
|
|
100
101
|
Some additional starter example roles for your apps were set up in in .ufo/task_definitions.rb. Be sure to check it out and adjust it for your needs.
|
101
102
|
|
102
|
-
|
103
|
+
## Settings files
|
104
|
+
|
105
|
+
Additionally, ufo generated starter settings files at that further allow you to customize more settings.
|
106
|
+
|
107
|
+
* .ufo/settings.yml: general settings.
|
108
|
+
* .ufo/settings/cfn/default.yml: properties of CloudFormation resources that ufo creates.
|
109
|
+
* .ufo/settings/network/default.yml: network settings.
|
110
|
+
|
111
|
+
More more info refer to: http://ufoships.com/docs/settings/
|
112
|
+
|
113
|
+
To deploy to ECS:
|
114
|
+
|
115
|
+
ufo current --service #{@app}-web
|
116
|
+
ufo ship
|
103
117
|
|
104
|
-
More info: http://ufoships.com
|
105
118
|
EOL
|
106
119
|
end
|
107
120
|
end
|
data/lib/ufo/log_group.rb
CHANGED
@@ -9,7 +9,7 @@ module Ufo
|
|
9
9
|
end
|
10
10
|
|
11
11
|
def create
|
12
|
-
puts "Ensuring log group for #{@task_definition} exists"
|
12
|
+
puts "Ensuring log group for #{@task_definition.colorize(:green)} task definition exists"
|
13
13
|
return if @options[:noop]
|
14
14
|
|
15
15
|
Ufo.check_task_definition!(@task_definition)
|
@@ -17,6 +17,7 @@ module Ufo
|
|
17
17
|
task_def["containerDefinitions"].each do |container_def|
|
18
18
|
begin
|
19
19
|
log_group_name = container_def["logConfiguration"]["options"]["awslogs-group"]
|
20
|
+
puts "Log group name: #{log_group_name}"
|
20
21
|
rescue NoMethodError
|
21
22
|
# silence when the logConfiguration is not specified
|
22
23
|
end
|
data/lib/ufo/network.rb
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
module Ufo
|
2
|
+
class Network < Command
|
3
|
+
autoload :Init, "ufo/network/init"
|
4
|
+
autoload :Helper, "ufo/network/helper"
|
5
|
+
autoload :Fetch, "ufo/network/fetch"
|
6
|
+
|
7
|
+
def self.cli_options
|
8
|
+
[
|
9
|
+
[:force, type: :boolean, desc: "Bypass overwrite are you sure prompt for existing files."],
|
10
|
+
[:subnets, type: :array, desc: "Subnets"],
|
11
|
+
[:vpc_id, desc: "Vpc id"],
|
12
|
+
[:filename, default: "default", desc: "Name of the settings file to create w/o extension."],
|
13
|
+
]
|
14
|
+
end
|
15
|
+
|
16
|
+
cli_options.each { |o| option(*o) }
|
17
|
+
|
18
|
+
desc "init", "Creates network starter settings file."
|
19
|
+
long_desc Help.text("network:init")
|
20
|
+
def init
|
21
|
+
Init.start
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
# Provides access to default network settings for a vpc: subnets and security_group
|
2
|
+
# If no @vpc_id is provided to the initializer then the default vpc is used.
|
3
|
+
class Ufo::Network
|
4
|
+
class Fetch
|
5
|
+
include Ufo::AwsService
|
6
|
+
extend Memoist
|
7
|
+
|
8
|
+
def initialize(vpc_id)
|
9
|
+
@vpc_id = vpc_id
|
10
|
+
end
|
11
|
+
|
12
|
+
def vpc_id
|
13
|
+
return @vpc_id if @vpc_id
|
14
|
+
|
15
|
+
resp = ec2.describe_vpcs(filters: [
|
16
|
+
{name: "isDefault", values: ["true"]}
|
17
|
+
])
|
18
|
+
resp.vpcs.first.vpc_id
|
19
|
+
end
|
20
|
+
memoize :vpc_id
|
21
|
+
|
22
|
+
# all subnets
|
23
|
+
def subnet_ids
|
24
|
+
resp = ec2.describe_subnets(filters: [
|
25
|
+
{name: "vpc-id", values: [vpc_id]}
|
26
|
+
])
|
27
|
+
resp.subnets.map(&:subnet_id).sort
|
28
|
+
end
|
29
|
+
memoize :subnet_ids
|
30
|
+
|
31
|
+
# default security group
|
32
|
+
def security_group_id
|
33
|
+
resp = ec2.describe_security_groups(filters: [
|
34
|
+
{name: "vpc-id", values: [vpc_id]},
|
35
|
+
{name: "group-name", values: ["default"]}
|
36
|
+
])
|
37
|
+
resp.security_groups.first.group_id
|
38
|
+
end
|
39
|
+
memoize :security_group_id
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
class Ufo::Network
|
2
|
+
module Helper
|
3
|
+
private
|
4
|
+
# for balancer default profile
|
5
|
+
def configure_network_settings
|
6
|
+
@options = @options.dup
|
7
|
+
return test_network_settings if ENV['TEST']
|
8
|
+
|
9
|
+
fetch = Fetch.new(@options[:vpc_id])
|
10
|
+
@options[:vpc_id] ||= fetch.vpc_id
|
11
|
+
@options[:ecs_subnets] ||= fetch.subnet_ids
|
12
|
+
@options[:elb_subnets] ||= fetch.subnet_ids
|
13
|
+
end
|
14
|
+
|
15
|
+
# hack for specs
|
16
|
+
def test_network_settings
|
17
|
+
@options[:vpc_id] = "vpc-111"
|
18
|
+
@options[:ecs_subnets] = ["subnet-111", "subnet-222"]
|
19
|
+
@options[:elb_subnets] = ["subnet-111", "subnet-222"]
|
20
|
+
@options
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module Ufo
|
2
|
+
class Network::Init < Thor::Group
|
3
|
+
include Thor::Actions
|
4
|
+
include Network::Helper
|
5
|
+
|
6
|
+
add_runtime_options! # force, pretend, quiet, skip options
|
7
|
+
# https://github.com/erikhuda/thor/blob/master/lib/thor/actions.rb#L49
|
8
|
+
|
9
|
+
# Interesting, when defining the options in this class it screws up the ufo balance -h menu
|
10
|
+
Network.cli_options.each do |o|
|
11
|
+
class_option *o
|
12
|
+
end
|
13
|
+
def self.source_paths
|
14
|
+
[File.expand_path("../../../template/.ufo/settings/network", __FILE__)]
|
15
|
+
end
|
16
|
+
|
17
|
+
def set_network_options
|
18
|
+
configure_network_settings
|
19
|
+
end
|
20
|
+
|
21
|
+
def starter_files
|
22
|
+
filename = @options[:filename] || "default"
|
23
|
+
template "default.yml", ".ufo/settings/network/#{filename}.yml"
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
data/lib/ufo/param.rb
CHANGED
@@ -1,5 +1,4 @@
|
|
1
1
|
require 'yaml'
|
2
|
-
require 'memoist'
|
3
2
|
|
4
3
|
module Ufo
|
5
4
|
class Param
|
@@ -13,7 +12,8 @@ module Ufo
|
|
13
12
|
upgrade_message!
|
14
13
|
|
15
14
|
result = RenderMePretty.result(@params_path, context: template_scope)
|
16
|
-
YAML.load(result)
|
15
|
+
data = YAML.load(result) || {}
|
16
|
+
data.deep_symbolize_keys
|
17
17
|
end
|
18
18
|
memoize :data
|
19
19
|
|
@@ -24,15 +24,15 @@ module Ufo
|
|
24
24
|
# Ufo version 3.3 to 3.4 added a concept of a .ufo/params.yml file to support
|
25
25
|
# fargate: https://github.com/tongueroo/ufo/pull/31
|
26
26
|
#
|
27
|
-
# Warn user and tell them to run the `ufo
|
27
|
+
# Warn user and tell them to run the `ufo upgrade v3_3to3_4` command to upgrade.
|
28
28
|
def upgrade_message!
|
29
29
|
return if File.exist?(@params_path)
|
30
30
|
|
31
31
|
puts "ERROR: Your project is missing the .ufo/params.yml.".colorize(:red)
|
32
|
-
puts "This was added in ufo version 3.4
|
32
|
+
puts "This was added in ufo version 3.4"
|
33
33
|
puts "You can find more info about the params file here: http://ufoships.com/docs/params/"
|
34
34
|
puts "To upgrade run:"
|
35
|
-
puts " ufo
|
35
|
+
puts " ufo upgrade v3_3to3_4"
|
36
36
|
exit 1
|
37
37
|
end
|
38
38
|
end
|
data/lib/ufo/ps.rb
ADDED
@@ -0,0 +1,102 @@
|
|
1
|
+
require 'text-table'
|
2
|
+
|
3
|
+
module Ufo
|
4
|
+
class Ps < Base
|
5
|
+
autoload :Task, 'ufo/ps/task'
|
6
|
+
|
7
|
+
delegate :service, to: :info
|
8
|
+
|
9
|
+
def run
|
10
|
+
unless service
|
11
|
+
puts no_service_message
|
12
|
+
return
|
13
|
+
end
|
14
|
+
|
15
|
+
summary
|
16
|
+
if task_arns.empty?
|
17
|
+
puts "There are 0 running tasks."
|
18
|
+
return
|
19
|
+
end
|
20
|
+
|
21
|
+
resp = ecs.describe_tasks(tasks: task_arns, cluster: @cluster)
|
22
|
+
display_info(resp)
|
23
|
+
|
24
|
+
display_scale_help
|
25
|
+
display_target_group_help
|
26
|
+
end
|
27
|
+
|
28
|
+
def summary
|
29
|
+
return unless @options[:summary]
|
30
|
+
puts "=> Service: #{@pretty_service_name}"
|
31
|
+
puts " Service name: #{service.service_name}"
|
32
|
+
puts " Status: #{service.status}"
|
33
|
+
puts " Running count: #{service.running_count}"
|
34
|
+
puts " Desired count: #{service.desired_count}"
|
35
|
+
puts " Launch type: #{service.launch_type}"
|
36
|
+
puts " Task definition: #{service.task_definition.split('/').last}"
|
37
|
+
elb = info.load_balancer(service)
|
38
|
+
if elb
|
39
|
+
puts " Elb: #{elb.dns_name}"
|
40
|
+
puts " Elb type: #{elb.type}"
|
41
|
+
end
|
42
|
+
puts " Route53: #{info.route53_dns}" if info.route53_dns
|
43
|
+
end
|
44
|
+
|
45
|
+
def display_target_group_help
|
46
|
+
events = service["events"][0..4]
|
47
|
+
return if events[0].message =~ /has reached a steady state/
|
48
|
+
|
49
|
+
# The error currently happens to be the 5th element.
|
50
|
+
#
|
51
|
+
# Example:
|
52
|
+
# "(service XXX) (instance i-XXX) (port 32875) is unhealthy in (target-group arn:aws:elasticloadbalancing:us-east-1:111111111111:targetgroup/devel-Targe-1111111111111/1111111111111111) due to (reason Health checks failed with these codes: [400])">]
|
53
|
+
error_event = events.find do |e|
|
54
|
+
e.message =~ /is unhealthy in/ &&
|
55
|
+
e.message =~ /targetgroup/
|
56
|
+
end
|
57
|
+
return unless error_event
|
58
|
+
|
59
|
+
puts "There are targets the target group reporting unhealthy. This can cause containers to cycle. Here's the error:"
|
60
|
+
puts error_event.message.colorize(:red)
|
61
|
+
puts "Check out the ECS console events tab for more info."
|
62
|
+
end
|
63
|
+
|
64
|
+
# If the running count less than the desired account yet, check the events
|
65
|
+
# and show a message with helpful debugging information.
|
66
|
+
def display_scale_help
|
67
|
+
return if service.running_count >= service.desired_count
|
68
|
+
|
69
|
+
events = service["events"][0..3] # only check most recent 4 messages
|
70
|
+
error_event = events.find do |e|
|
71
|
+
e.message =~ /was unable to place a task/
|
72
|
+
end
|
73
|
+
return unless error_event
|
74
|
+
|
75
|
+
puts "There is an issue scaling the #{@service.colorize(:green)} service to #{service.desired_count}. Here's the error:"
|
76
|
+
puts error_event.message.colorize(:red)
|
77
|
+
end
|
78
|
+
|
79
|
+
def display_info(resp)
|
80
|
+
table = Text::Table.new
|
81
|
+
table.head = Task.header
|
82
|
+
resp["tasks"].each do |t|
|
83
|
+
task = Task.new(t)
|
84
|
+
table.rows << task.to_a unless task.hide?
|
85
|
+
end
|
86
|
+
puts table
|
87
|
+
end
|
88
|
+
|
89
|
+
def task_arns
|
90
|
+
threads, results = [], {}
|
91
|
+
statuses = %w[RUNNING PENDING STOPPED]
|
92
|
+
statuses.each do |status|
|
93
|
+
threads << Thread.new do
|
94
|
+
resp = ecs.list_tasks(service_name: service.service_name, cluster: @cluster, desired_status: status)
|
95
|
+
results[status] = resp.task_arns
|
96
|
+
end
|
97
|
+
end
|
98
|
+
threads.map(&:join)
|
99
|
+
results.values.flatten.uniq
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
data/lib/ufo/ps/task.rb
ADDED
@@ -0,0 +1,78 @@
|
|
1
|
+
class Ufo::Ps
|
2
|
+
class Task
|
3
|
+
def self.header
|
4
|
+
%w[Id Name Release Started Status Notes]
|
5
|
+
end
|
6
|
+
|
7
|
+
def initialize(task)
|
8
|
+
@task = task
|
9
|
+
end
|
10
|
+
|
11
|
+
def to_a
|
12
|
+
[id, name, release, started, status, notes]
|
13
|
+
end
|
14
|
+
|
15
|
+
def id
|
16
|
+
@task['task_arn'].split('/').last.split('-').first
|
17
|
+
end
|
18
|
+
|
19
|
+
def name
|
20
|
+
@task["overrides"]["container_overrides"].first["name"]
|
21
|
+
rescue NoMethodError
|
22
|
+
@task["containers"].first["name"]
|
23
|
+
end
|
24
|
+
|
25
|
+
def release
|
26
|
+
@task["task_definition_arn"].split('/').last
|
27
|
+
end
|
28
|
+
|
29
|
+
def started
|
30
|
+
started = Time.parse(@task["started_at"].to_s)
|
31
|
+
relative_time(started)
|
32
|
+
rescue ArgumentError
|
33
|
+
"PENDING"
|
34
|
+
end
|
35
|
+
|
36
|
+
def started_at
|
37
|
+
Time.parse(@task["started_at"].to_s)
|
38
|
+
rescue ArgumentError
|
39
|
+
nil
|
40
|
+
end
|
41
|
+
|
42
|
+
# hide stopped tasks that are older than 10 minutes
|
43
|
+
def hide?
|
44
|
+
status == "STOPPED" && started_at < Time.now - 60 * 10
|
45
|
+
end
|
46
|
+
|
47
|
+
def status
|
48
|
+
@task["last_status"]
|
49
|
+
end
|
50
|
+
|
51
|
+
def notes
|
52
|
+
return unless @task["stopped_reason"]
|
53
|
+
|
54
|
+
if @task["stopped_reason"] =~ /Task failed ELB health checks/
|
55
|
+
"Failed ELB health check"
|
56
|
+
else
|
57
|
+
@task["stopped_reason"]
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
# https://stackoverflow.com/questions/195740/how-do-you-do-relative-time-in-rails/195894
|
62
|
+
def relative_time(start_time)
|
63
|
+
diff_seconds = Time.now - start_time
|
64
|
+
case diff_seconds
|
65
|
+
when 0 .. 59
|
66
|
+
"#{diff_seconds.to_i} seconds ago"
|
67
|
+
when 60 .. (3600-1)
|
68
|
+
"#{(diff_seconds/60).to_i} minutes ago"
|
69
|
+
when 3600 .. (3600*24-1)
|
70
|
+
"#{(diff_seconds/3600).to_i} hours ago"
|
71
|
+
when (3600*24) .. (3600*24*30)
|
72
|
+
"#{(diff_seconds/(3600*24)).to_i} days ago"
|
73
|
+
else
|
74
|
+
start_time.strftime("%m/%d/%Y")
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|