lono 6.1.11 → 7.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.cody/acceptance.sh +19 -3
- data/.gitignore +2 -2
- data/CHANGELOG.md +16 -1
- data/README.md +18 -20
- data/Rakefile +1 -0
- data/lib/lono.rb +7 -5
- data/lib/lono/abstract_base.rb +25 -0
- data/lib/lono/api/client.rb +30 -0
- data/lib/lono/api/proxy.rb +58 -0
- data/lib/lono/api/repos.rb +8 -0
- data/lib/lono/api/verify.rb +13 -0
- data/lib/lono/app_file/base.rb +4 -11
- data/lib/lono/app_file/build.rb +1 -1
- data/lib/lono/app_file/upload.rb +1 -4
- data/lib/lono/autoloader.rb +3 -1
- data/lib/lono/aws_services.rb +9 -9
- data/lib/lono/aws_services/helper.rb +14 -0
- data/lib/lono/aws_services/{util.rb → stack.rb} +1 -9
- data/lib/lono/aws_services/stack_set.rb +41 -0
- data/lib/lono/blueprint.rb +2 -2
- data/lib/lono/blueprint/configset/loader.rb +7 -0
- data/lib/lono/blueprint/helper.rb +8 -2
- data/lib/lono/blueprint/meta.rb +4 -12
- data/lib/lono/blueprint/new.rb +3 -3
- data/lib/lono/blueprint/root.rb +6 -26
- data/lib/lono/bundle.rb +54 -0
- data/lib/lono/cfn.rb +31 -75
- data/lib/lono/cfn/base.rb +39 -136
- data/lib/lono/cfn/cancel.rb +14 -9
- data/lib/lono/cfn/create.rb +15 -19
- data/lib/lono/cfn/delete.rb +9 -9
- data/lib/lono/cfn/deploy.rb +4 -4
- data/lib/lono/cfn/download.rb +27 -9
- data/lib/lono/cfn/opts.rb +80 -0
- data/lib/lono/cfn/preview/changeset.rb +23 -23
- data/lib/lono/cfn/preview/codediff.rb +5 -6
- data/lib/lono/cfn/preview/param.rb +10 -10
- data/lib/lono/cfn/rollback.rb +5 -5
- data/lib/lono/cfn/status.rb +0 -10
- data/lib/lono/cfn/update.rb +22 -27
- data/lib/lono/clean.rb +3 -3
- data/lib/lono/cli.rb +69 -34
- data/lib/lono/code.rb +22 -0
- data/lib/lono/command.rb +7 -0
- data/lib/lono/config_location.rb +6 -13
- data/lib/lono/configset.rb +9 -0
- data/lib/lono/configset/combiner.rb +128 -0
- data/lib/lono/configset/evaluate_file.rb +8 -0
- data/lib/lono/configset/list.rb +67 -0
- data/lib/lono/configset/loader.rb +98 -0
- data/lib/lono/configset/loader/dsl.rb +9 -0
- data/lib/lono/configset/materializer/final.rb +10 -0
- data/lib/lono/configset/materializer/gems_builder.rb +81 -0
- data/lib/lono/configset/materializer/jade.rb +15 -0
- data/lib/lono/configset/materializer/source.rb +54 -0
- data/lib/lono/configset/meta.rb +19 -0
- data/lib/lono/configset/meta/dsl.rb +12 -0
- data/lib/lono/configset/new.rb +84 -0
- data/lib/lono/configset/preparer.rb +44 -0
- data/lib/lono/configset/register/base.rb +121 -0
- data/lib/lono/configset/register/blueprint.rb +16 -0
- data/lib/lono/configset/register/dsl.rb +15 -0
- data/lib/lono/configset/register/project.rb +12 -0
- data/lib/lono/configset/registry.rb +34 -0
- data/lib/lono/configset/resolver.rb +42 -0
- data/lib/lono/conventions.rb +18 -7
- data/lib/lono/core.rb +16 -20
- data/lib/lono/default/settings.yml +2 -3
- data/lib/lono/ext/bundler.rb +7 -0
- data/lib/lono/file_uploader.rb +8 -5
- data/lib/lono/finder/base.rb +140 -0
- data/lib/lono/finder/blueprint.rb +11 -0
- data/lib/lono/finder/blueprint/configset.rb +17 -0
- data/lib/lono/finder/configset.rb +11 -0
- data/lib/lono/generate.rb +93 -0
- data/lib/lono/help/blueprint/new.md +0 -1
- data/lib/lono/help/cfn/delete.md +1 -1
- data/lib/lono/help/cfn/deploy.md +5 -76
- data/lib/lono/help/cfn/status.md +0 -4
- data/lib/lono/help/cfn/update.md +1 -1
- data/lib/lono/help/code/convert.md +51 -0
- data/lib/lono/help/code/import.md +30 -0
- data/lib/lono/help/configsets.md +24 -0
- data/lib/lono/help/generate.md +4 -4
- data/lib/lono/help/new.md +1 -2
- data/lib/lono/help/sets/delete.md +8 -0
- data/lib/lono/help/sets/deploy.md +76 -0
- data/lib/lono/help/sets/instances/delete.md +21 -0
- data/lib/lono/help/sets/instances/list.md +14 -0
- data/lib/lono/help/sets/instances/status.md +15 -0
- data/lib/lono/help/sets/instances/sync.md +88 -0
- data/lib/lono/help/sets/status.md +23 -0
- data/lib/lono/help/upgrade.md +1 -0
- data/lib/lono/importer.rb +22 -0
- data/lib/lono/importer/base.rb +59 -0
- data/lib/lono/importer/converter.rb +19 -0
- data/lib/lono/importer/download.rb +46 -0
- data/lib/lono/importer/dsl.rb +36 -0
- data/lib/lono/importer/erb.rb +31 -0
- data/lib/lono/importer/params.rb +56 -0
- data/lib/lono/importer/service/coder.rb +81 -0
- data/lib/lono/inspector/base.rb +12 -22
- data/lib/lono/inspector/graph.rb +1 -1
- data/lib/lono/inspector/summary.rb +41 -17
- data/lib/lono/jade.rb +103 -0
- data/lib/lono/jade/circular.rb +26 -0
- data/lib/lono/jadespec.rb +41 -0
- data/lib/lono/new.rb +2 -2
- data/lib/lono/opts.rb +43 -0
- data/lib/lono/output/template.rb +48 -0
- data/lib/lono/param.rb +3 -5
- data/lib/lono/param/generator.rb +13 -33
- data/lib/lono/pro.rb +15 -0
- data/lib/lono/pro/base.rb +16 -0
- data/lib/lono/pro/repo.rb +27 -0
- data/lib/lono/project_checker.rb +4 -29
- data/lib/lono/registration.rb +15 -0
- data/lib/lono/registration/base.rb +37 -0
- data/lib/lono/registration/check.rb +15 -0
- data/lib/lono/registration/temp.rb +60 -0
- data/lib/lono/registration/user.rb +54 -0
- data/lib/lono/script/base.rb +1 -10
- data/lib/lono/script/upload.rb +2 -12
- data/lib/lono/seed.rb +2 -11
- data/lib/lono/seed/base.rb +55 -110
- data/lib/lono/sets.rb +38 -0
- data/lib/lono/sets/base.rb +45 -0
- data/lib/lono/sets/create.rb +30 -0
- data/lib/lono/sets/delete.rb +47 -0
- data/lib/lono/sets/deploy.rb +11 -0
- data/lib/lono/sets/instances.rb +33 -0
- data/lib/lono/sets/instances/base.rb +30 -0
- data/lib/lono/sets/instances/delete.rb +69 -0
- data/lib/lono/sets/instances/list.rb +13 -0
- data/lib/lono/sets/instances/opts.rb +29 -0
- data/lib/lono/sets/instances/status.rb +12 -0
- data/lib/lono/sets/instances/sync.rb +182 -0
- data/lib/lono/sets/list.rb +35 -0
- data/lib/lono/sets/opts.rb +18 -0
- data/lib/lono/sets/preview/codediff.rb +35 -0
- data/lib/lono/sets/preview/param.rb +32 -0
- data/lib/lono/sets/status.rb +116 -0
- data/lib/lono/sets/status/instance.rb +20 -0
- data/lib/lono/sets/status/instance/base.rb +120 -0
- data/lib/lono/sets/status/instance/completed.rb +35 -0
- data/lib/lono/sets/status/instance/deleted.rb +32 -0
- data/lib/lono/sets/status/instance/show.rb +7 -0
- data/lib/lono/sets/status/instances.rb +111 -0
- data/lib/lono/sets/summarize.rb +20 -0
- data/lib/lono/sets/time_spent.rb +11 -0
- data/lib/lono/sets/update.rb +81 -0
- data/lib/lono/template.rb +5 -7
- data/lib/lono/template/configset_injector.rb +50 -0
- data/lib/lono/template/context.rb +4 -4
- data/lib/lono/template/context/loader.rb +4 -16
- data/lib/lono/template/evaluate.rb +2 -1
- data/lib/lono/template/generator.rb +17 -15
- data/lib/lono/template/helper.rb +7 -7
- data/lib/lono/template/post_processor.rb +2 -12
- data/lib/lono/template/strategy/base.rb +4 -0
- data/lib/lono/template/{dsl.rb → strategy/dsl.rb} +4 -6
- data/lib/lono/template/{dsl → strategy/dsl}/builder.rb +11 -15
- data/lib/lono/template/{dsl → strategy/dsl}/builder/fn.rb +1 -1
- data/lib/lono/template/strategy/dsl/builder/helpers.rb +11 -0
- data/lib/lono/template/strategy/dsl/builder/helpers/core_helper.rb +14 -0
- data/lib/lono/template/strategy/dsl/builder/helpers/file_helper.rb +48 -0
- data/lib/lono/template/strategy/dsl/builder/helpers/lookup_helper.rb +27 -0
- data/lib/lono/template/strategy/dsl/builder/helpers/s3_helper.rb +13 -0
- data/lib/lono/template/strategy/dsl/builder/helpers/tags_helper.rb +39 -0
- data/lib/lono/template/{dsl/builder → strategy/dsl/builder/section}/base.rb +6 -17
- data/lib/lono/template/{dsl/builder → strategy/dsl/builder/section}/condition.rb +1 -1
- data/lib/lono/template/strategy/dsl/builder/section/extensions.rb +9 -0
- data/lib/lono/template/{dsl/builder → strategy/dsl/builder/section}/mapping.rb +1 -1
- data/lib/lono/template/{dsl/builder/section_methods.rb → strategy/dsl/builder/section/methods.rb} +9 -2
- data/lib/lono/template/{dsl/builder → strategy/dsl/builder/section}/output.rb +1 -1
- data/lib/lono/template/strategy/dsl/builder/section/parameter.rb +69 -0
- data/lib/lono/template/{dsl/builder → strategy/dsl/builder/section}/resource.rb +1 -1
- data/lib/lono/template/{dsl/builder → strategy/dsl/builder/section}/resource/property_mover.rb +1 -1
- data/lib/lono/template/{dsl/builder → strategy/dsl/builder/section}/section.rb +1 -1
- data/lib/lono/template/{dsl → strategy/dsl}/builder/squeezer.rb +1 -1
- data/lib/lono/template/strategy/dsl/builder/stringify.rb +15 -0
- data/lib/lono/template/{dsl → strategy/dsl}/builder/syntax.rb +3 -2
- data/lib/lono/template/strategy/dsl/finalizer.rb +12 -0
- data/lib/lono/template/strategy/dsl/finalizer/parameter_groups.rb +56 -0
- data/lib/lono/template/{erb.rb → strategy/erb.rb} +5 -5
- data/lib/lono/template/strategy/source.rb +8 -0
- data/lib/lono/template/template.rb +1 -1
- data/lib/lono/template/upload.rb +4 -9
- data/lib/lono/template/util.rb +0 -40
- data/lib/lono/upgrade.rb +12 -10
- data/lib/lono/user_data.rb +4 -4
- data/lib/lono/utils/pretty_time.rb +14 -0
- data/lib/lono/utils/sure.rb +23 -0
- data/lib/lono/version.rb +1 -1
- data/lib/lono/yamler/loader.rb +52 -0
- data/lib/lono/yamler/validator.rb +51 -0
- data/lib/templates/blueprint/%blueprint_name%.gemspec.tt +4 -0
- data/lib/templates/blueprint/README.md.tt +1 -1
- data/lib/templates/blueprint/seed/configs.rb +2 -2
- data/lib/templates/blueprint_types/dsl/app/templates/%blueprint_name%.rb +17 -18
- data/lib/templates/blueprint_types/erb/app/templates/%blueprint_name%.yml +63 -4
- data/lib/templates/configset/%configset_name%.gemspec.tt +41 -0
- data/lib/templates/configset/.gitignore +11 -0
- data/lib/templates/configset/CHANGELOG.md +7 -0
- data/lib/templates/configset/Gemfile +4 -0
- data/lib/templates/configset/README.md.tt +3 -0
- data/lib/templates/configset/Rakefile.tt +9 -0
- data/lib/templates/configset/lib/configset.yml +20 -0
- data/lib/templates/skeleton/.gitignore +1 -0
- data/lib/templates/skeleton/Gemfile +0 -1
- data/lib/templates/skeleton/README.md +4 -4
- data/lib/templates/skeleton/configs/settings.yml +1 -1
- data/lono.gemspec +1 -4
- metadata +146 -79
- data/Guardfile +0 -19
- data/lib/lono/app_file.rb +0 -5
- data/lib/lono/blueprint/find.rb +0 -90
- data/lib/lono/blueprint/info.rb +0 -10
- data/lib/lono/blueprint/list.rb +0 -14
- data/lib/lono/cfn/current.rb +0 -95
- data/lib/lono/cfn/preview.rb +0 -4
- data/lib/lono/cfn/suffix.rb +0 -67
- data/lib/lono/cfn/util.rb +0 -27
- data/lib/lono/help/cfn/current.md +0 -18
- data/lib/lono/help/upgrade4.md +0 -25
- data/lib/lono/inspector.rb +0 -4
- data/lib/lono/output_template.rb +0 -35
- data/lib/lono/template/base.rb +0 -13
- data/lib/lono/template/dsl/builder/helpers.rb +0 -8
- data/lib/lono/template/dsl/builder/helpers/core_helper.rb +0 -107
- data/lib/lono/template/dsl/builder/helpers/param_helper.rb +0 -61
- data/lib/lono/template/dsl/builder/parameter.rb +0 -39
- data/lib/lono/upgrade/upgrade4.rb +0 -175
- data/lib/lono/upgrade/upgrade42.rb +0 -36
- data/lib/lono/upgrade/upgrade5.rb +0 -55
- data/lib/templates/blueprint/.meta/config.yml.tt +0 -4
- data/lib/templates/skeleton/Guardfile +0 -12
- data/lib/templates/upgrade5/blueprints/main/.lono/config.yml +0 -3
- data/lib/templates/upgrade5/blueprints/main/.meta/config.yml +0 -3
@@ -0,0 +1,32 @@
|
|
1
|
+
module Lono::Sets::Preview
|
2
|
+
# Inherits from Lono::Cfn::Preview::Param and override what's needed:
|
3
|
+
#
|
4
|
+
# stack_parameters
|
5
|
+
#
|
6
|
+
class Param < Lono::Cfn::Preview::Param
|
7
|
+
def run
|
8
|
+
return unless stack_set_exists?(@stack)
|
9
|
+
|
10
|
+
generated_parameters # eager call generated_parameters so its output is above Parameter Diff Preview
|
11
|
+
puts "Parameter Diff Preview:".color(:green)
|
12
|
+
if @options[:noop]
|
13
|
+
puts "NOOP CloudFormation parameters preview for #{@stack} update"
|
14
|
+
return
|
15
|
+
end
|
16
|
+
|
17
|
+
write_to_tmp(existing_path, existing_params)
|
18
|
+
write_to_tmp(new_path, new_params)
|
19
|
+
|
20
|
+
show_diff(existing_path, new_path)
|
21
|
+
end
|
22
|
+
|
23
|
+
def stack_parameters
|
24
|
+
stack_set_parameters
|
25
|
+
end
|
26
|
+
|
27
|
+
def stack_set_parameters
|
28
|
+
resp = cfn.describe_stack_set(stack_set_name: @stack)
|
29
|
+
resp.stack_set.parameters
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,116 @@
|
|
1
|
+
class Lono::Sets
|
2
|
+
class Status
|
3
|
+
extend Memoist
|
4
|
+
include Lono::AwsServices
|
5
|
+
include Summarize
|
6
|
+
include TimeSpent
|
7
|
+
|
8
|
+
attr_reader :operation_id
|
9
|
+
def initialize(options={})
|
10
|
+
@options = options
|
11
|
+
@stack, @operation_id = options[:stack], options[:operation_id]
|
12
|
+
@shown = []
|
13
|
+
@output = "" # for say method and specs
|
14
|
+
end
|
15
|
+
|
16
|
+
def wait
|
17
|
+
status = nil
|
18
|
+
until completed?(status)
|
19
|
+
resp = display_one
|
20
|
+
stack_set_operation = resp.stack_set_operation
|
21
|
+
status = stack_set_operation.status
|
22
|
+
# always sleep delay even if completed to provide start_instances_status_waiter some extra time to complete
|
23
|
+
sleep 5
|
24
|
+
if completed?(status)
|
25
|
+
show_time_spent(stack_set_operation)
|
26
|
+
else
|
27
|
+
start_instances_status_waiter
|
28
|
+
end
|
29
|
+
end
|
30
|
+
status == "SUCCEEDED"
|
31
|
+
end
|
32
|
+
|
33
|
+
def display_one
|
34
|
+
resp = cfn.describe_stack_set_operation(
|
35
|
+
stack_set_name: @stack,
|
36
|
+
operation_id: operation_id,
|
37
|
+
)
|
38
|
+
stack_set_operation = resp.stack_set_operation
|
39
|
+
show_stack_set_operation(stack_set_operation)
|
40
|
+
@shown << stack_set_operation
|
41
|
+
resp
|
42
|
+
end
|
43
|
+
|
44
|
+
def show
|
45
|
+
display_one
|
46
|
+
o = @options.merge(show_time_spent: false)
|
47
|
+
instances_status = Lono::Sets::Instances::Status.new(o)
|
48
|
+
instances_status.run
|
49
|
+
summarize(operation_id)
|
50
|
+
end
|
51
|
+
|
52
|
+
@@instances_status_waiter_started = false
|
53
|
+
def start_instances_status_waiter
|
54
|
+
return if @@instances_status_waiter_started
|
55
|
+
if stack_instances.empty?
|
56
|
+
@@instances_status_waiter_started = true
|
57
|
+
return
|
58
|
+
end
|
59
|
+
|
60
|
+
Thread.new do
|
61
|
+
# show_time_spent because we already show it in this status class. Dont want it to show twice.
|
62
|
+
o = @options.merge(start_on_outdated: true, show_time_spent: false)
|
63
|
+
instances_status = Lono::Sets::Instances::Status.new(o)
|
64
|
+
instances_status.run
|
65
|
+
end
|
66
|
+
@@instances_status_waiter_started = true
|
67
|
+
end
|
68
|
+
|
69
|
+
def show_stack_set_operation(stack_set_operation)
|
70
|
+
already_shown = @shown.detect do |o|
|
71
|
+
o[:status] == stack_set_operation[:status]
|
72
|
+
end
|
73
|
+
return if already_shown
|
74
|
+
|
75
|
+
say "Stack Set Operation Status: #{stack_set_operation.status}"
|
76
|
+
end
|
77
|
+
|
78
|
+
def say(text)
|
79
|
+
ENV["LONO_TEST"] ? @output << "#{text}\n" : puts(text)
|
80
|
+
end
|
81
|
+
|
82
|
+
# describe_stack_set_operation stack_set_operation.status is
|
83
|
+
# one of RUNNING, SUCCEEDED, FAILED, STOPPING, STOPPED
|
84
|
+
def completed?(status)
|
85
|
+
completed_statuses = %w[SUCCEEDED FAILED STOPPED]
|
86
|
+
completed_statuses.include?(status)
|
87
|
+
end
|
88
|
+
|
89
|
+
def stack_set_status
|
90
|
+
resp = cfn.describe_stack_set_operation(
|
91
|
+
stack_set_name: @stack,
|
92
|
+
operation_id: operation_id,
|
93
|
+
)
|
94
|
+
# describe_stack_set_operation stack_set_operation.status is
|
95
|
+
# status one of RUNNING, SUCCEEDED, FAILED, STOPPING, STOPPED
|
96
|
+
resp.stack_set_operation.status
|
97
|
+
end
|
98
|
+
|
99
|
+
def operation_id
|
100
|
+
@operation_id ||= latest_operation_id
|
101
|
+
end
|
102
|
+
|
103
|
+
def latest_operation_id
|
104
|
+
resp = cfn.list_stack_set_operations(
|
105
|
+
stack_set_name: @stack,
|
106
|
+
max_results: 1,
|
107
|
+
)
|
108
|
+
resp.summaries.first.operation_id
|
109
|
+
end
|
110
|
+
|
111
|
+
def stack_instances
|
112
|
+
Lono::Sets::Status::Instances.new(@options).stack_instances
|
113
|
+
end
|
114
|
+
memoize :stack_instances
|
115
|
+
end
|
116
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
class Lono::Sets::Status
|
2
|
+
class Instance
|
3
|
+
def initialize(stack_instance)
|
4
|
+
@stack_instance = stack_instance
|
5
|
+
end
|
6
|
+
|
7
|
+
def tail(to="completed")
|
8
|
+
case to
|
9
|
+
when "completed"
|
10
|
+
Completed.new(@stack_instance).tail
|
11
|
+
when "deleted"
|
12
|
+
Deleted.new(@stack_instance).tail
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def show
|
17
|
+
Show.new(@stack_instance).run
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,120 @@
|
|
1
|
+
# The Completed and Deleted classes inherit from Base.
|
2
|
+
# They implement `tail` and should not override `show`.
|
3
|
+
#
|
4
|
+
# They guarantee at least one status line is shown.
|
5
|
+
# After which they start a thread that tails until a "terminal" status is detected. However, describe_stack_instance
|
6
|
+
# resp.stack_instance.status returns:
|
7
|
+
#
|
8
|
+
# CURRENT, OUTDATED, INOPERABLE
|
9
|
+
#
|
10
|
+
# There is no well-defined terminal status. For example, sometimes the terminal status is `CURRENT`, when the stack
|
11
|
+
# instance updates successfully:
|
12
|
+
#
|
13
|
+
# CURRENT -> OUTDATED -> CURRENT (terminal)
|
14
|
+
#
|
15
|
+
# But sometimes the terminal state is `OUTDATED`, when the stack instance fails to update:
|
16
|
+
#
|
17
|
+
# CURRENT -> OUTDATED (terminal)
|
18
|
+
#
|
19
|
+
# Essentially, the `describe_stack_instance` resp does not provide enough information to determine the completion of
|
20
|
+
# the `tail` logic.
|
21
|
+
#
|
22
|
+
# Hence the Completed and Deleted classes cannot be used to control the end of the polling loop. Instead, the calling
|
23
|
+
# logic is responsible for and should control when to end the polling loop.
|
24
|
+
#
|
25
|
+
# Example in Lono::Sets::Status::Instances:
|
26
|
+
#
|
27
|
+
# with_instances do |instance|
|
28
|
+
# Thread.new { instance.tail(to) }
|
29
|
+
# end.map(&:join)
|
30
|
+
# wait_until_stack_set_operation_complete
|
31
|
+
#
|
32
|
+
# The Instances logic waits on the operation results instead because its more accurate. We know from
|
33
|
+
# `describe_stack_set_operation` when the status is actually complete. The describe_stack_set_operation
|
34
|
+
# stack_set_operation.status is one of RUNNING, SUCCEEDED, FAILED, STOPPING, STOPPED.
|
35
|
+
#
|
36
|
+
# In this case, there are threads within threads. The first thread at the Instances level starts polling status
|
37
|
+
# in parallel. The instance.tail delegates to the Completed and Deleted classes.
|
38
|
+
#
|
39
|
+
# Finally, the Completed and Deleted classes are designed to block with the first poll request. So it can show at
|
40
|
+
# least one status line. Then it starts it's own thread to poll for more statuses. Those latter statuses are not
|
41
|
+
# guaranteed to be shown. This is the responsibility of the Instances class since it has the information required to
|
42
|
+
# determine when to finish the polling loop.
|
43
|
+
#
|
44
|
+
class Lono::Sets::Status::Instance
|
45
|
+
class Base
|
46
|
+
include Lono::AwsServices
|
47
|
+
|
48
|
+
class_attribute :show_time_progress
|
49
|
+
class_attribute :delay_factor
|
50
|
+
|
51
|
+
def initialize(stack_instance)
|
52
|
+
@stack_instance = stack_instance
|
53
|
+
@shown = []
|
54
|
+
@output = "" # for say method and specs
|
55
|
+
end
|
56
|
+
|
57
|
+
def show_instance(stack_instance)
|
58
|
+
already_shown = @shown.detect do |o|
|
59
|
+
o[:account] == stack_instance[:account] &&
|
60
|
+
o[:region] == stack_instance[:region] &&
|
61
|
+
o[:status] == stack_instance[:status] &&
|
62
|
+
o[:status_reason] == stack_instance[:status_reason]
|
63
|
+
end
|
64
|
+
return if already_shown
|
65
|
+
|
66
|
+
s = stack_instance
|
67
|
+
say status_line(s.account, s.region, s.status, s.status_reason)
|
68
|
+
end
|
69
|
+
|
70
|
+
def show_time_progress
|
71
|
+
self.class.show_time_progress
|
72
|
+
end
|
73
|
+
|
74
|
+
def status_line(account, region, status, reason=nil)
|
75
|
+
time = Time.now.strftime("%F %I:%M:%S%p") if show_time_progress
|
76
|
+
items = [
|
77
|
+
time,
|
78
|
+
"Stack Instance:",
|
79
|
+
"account".color(:purple), account,
|
80
|
+
"region".color(:purple), region,
|
81
|
+
"status".color(:purple), status,
|
82
|
+
]
|
83
|
+
items += ["reason".color(:purple), reason] if reason
|
84
|
+
items.compact.join(" ")
|
85
|
+
end
|
86
|
+
|
87
|
+
def say(text)
|
88
|
+
ENV["LONO_TEST"] ? @output << "#{text}\n" : puts(text)
|
89
|
+
end
|
90
|
+
|
91
|
+
def describe_stack_instance
|
92
|
+
retries = 0
|
93
|
+
begin
|
94
|
+
cfn.describe_stack_instance(
|
95
|
+
stack_instance_account: @stack_instance.account,
|
96
|
+
stack_instance_region: @stack_instance.region,
|
97
|
+
stack_set_name: @stack_instance.stack_set_id)
|
98
|
+
rescue Aws::CloudFormation::Errors::Throttling => e
|
99
|
+
retries += 1
|
100
|
+
delay = 2 ** retries
|
101
|
+
if ENV['LONO_DEBUG_THROTTLE']
|
102
|
+
puts "#{e.class}: #{e.message}"
|
103
|
+
puts "Backing off for #{delay}s and will retry"
|
104
|
+
end
|
105
|
+
sleep delay
|
106
|
+
retry
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
def delay
|
111
|
+
# delay factor based on number of stack instances
|
112
|
+
factor = self.class.delay_factor || 1
|
113
|
+
base = 4.5
|
114
|
+
delay = factor * base
|
115
|
+
delay = [delay, 30].min # limit the delay to a max
|
116
|
+
puts "Sleeping for #{delay}s..." if ENV['LONO_DEBUG_THROTTLE']
|
117
|
+
sleep delay
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
# Refer to Lono::Sets::Status::Instance::Base for more detailed docs.
|
2
|
+
class Lono::Sets::Status::Instance
|
3
|
+
class Completed < Base
|
4
|
+
def tail
|
5
|
+
display_one
|
6
|
+
Thread.new do
|
7
|
+
loop!
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
def loop!
|
12
|
+
# resp.stack_instance.status : one of CURRENT, OUTDATED, INOPERABLE
|
13
|
+
status = nil
|
14
|
+
until completed?(status)
|
15
|
+
resp = display_one
|
16
|
+
status = resp.stack_instance.status
|
17
|
+
delay unless completed?(status)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def display_one
|
22
|
+
resp = describe_stack_instance
|
23
|
+
stack_instance = resp.stack_instance
|
24
|
+
show_instance(stack_instance)
|
25
|
+
@shown << stack_instance
|
26
|
+
resp
|
27
|
+
end
|
28
|
+
|
29
|
+
# status: one of CURRENT, OUTDATED, INOPERABLE
|
30
|
+
def completed?(status)
|
31
|
+
completed_statuses = %w[CURRENT INOPERABLE]
|
32
|
+
completed_statuses.include?(status)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
# Refer to Lono::Sets::Status::Instance::Base for more detailed docs.
|
2
|
+
class Lono::Sets::Status::Instance
|
3
|
+
class Deleted < Base
|
4
|
+
def tail
|
5
|
+
display_one
|
6
|
+
Thread.new do
|
7
|
+
loop!
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
def loop!
|
12
|
+
# resp.stack_instance.status : one of CURRENT, OUTDATED, INOPERABLE
|
13
|
+
while true
|
14
|
+
begin
|
15
|
+
display_one
|
16
|
+
rescue Aws::CloudFormation::Errors::StackInstanceNotFoundException
|
17
|
+
say status_line(@stack_instance.account, @stack_instance.region, "DELETED")
|
18
|
+
break
|
19
|
+
end
|
20
|
+
delay
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def display_one
|
25
|
+
resp = describe_stack_instance
|
26
|
+
stack_instance = resp.stack_instance
|
27
|
+
show_instance(stack_instance)
|
28
|
+
@shown << stack_instance
|
29
|
+
resp
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,111 @@
|
|
1
|
+
class Lono::Sets::Status
|
2
|
+
class Instances
|
3
|
+
include Lono::AwsServices
|
4
|
+
include Lono::Sets::TimeSpent
|
5
|
+
|
6
|
+
def initialize(options={})
|
7
|
+
@options = options
|
8
|
+
@stack, @operation_id = options[:stack], options[:operation_id]
|
9
|
+
@show_time_spent = options[:show_time_spent].nil? ? true : options[:show_time_spent]
|
10
|
+
end
|
11
|
+
|
12
|
+
def wait(to="completed")
|
13
|
+
puts "Stack Instance statuses... (takes a while)"
|
14
|
+
wait_until_outdated if @options[:start_on_outdated]
|
15
|
+
|
16
|
+
with_instances do |instance|
|
17
|
+
Thread.new { instance.tail(to) }
|
18
|
+
end.map(&:join)
|
19
|
+
wait_until_stack_set_operation_complete
|
20
|
+
end
|
21
|
+
|
22
|
+
def show
|
23
|
+
if stack_instances.empty?
|
24
|
+
# Note: no access to @blueprint here
|
25
|
+
puts <<~EOL
|
26
|
+
There are 0 stack instances associated with the #{@stack} stack set. Add files
|
27
|
+
Add accounts and regions configs use `lono sets instances sync` to add stack instances.
|
28
|
+
EOL
|
29
|
+
return
|
30
|
+
end
|
31
|
+
|
32
|
+
with_instances do |instance|
|
33
|
+
Thread.new { instance.show }
|
34
|
+
end.map(&:join)
|
35
|
+
wait_until_stack_set_operation_complete
|
36
|
+
end
|
37
|
+
|
38
|
+
def with_instances
|
39
|
+
stack_instances.map do |stack_instance|
|
40
|
+
instance = Instance.new(stack_instance)
|
41
|
+
yield(instance)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def wait_until_stack_set_operation_complete
|
46
|
+
status, stack_set_operation = nil, nil
|
47
|
+
until completed?(status)
|
48
|
+
resp = cfn.describe_stack_set_operation(
|
49
|
+
stack_set_name: @stack,
|
50
|
+
operation_id: operation_id,
|
51
|
+
)
|
52
|
+
stack_set_operation = resp.stack_set_operation
|
53
|
+
status = stack_set_operation.status
|
54
|
+
# puts "DEBUG: wait_until_stack_set_operation_complete"
|
55
|
+
unless completed?(status)
|
56
|
+
sleep 5
|
57
|
+
end
|
58
|
+
end
|
59
|
+
if @show_time_spent # or else it double shows from `lono sets deploy`. Do want it to show for `lono sets instances sync` though
|
60
|
+
show_time_spent(stack_set_operation)
|
61
|
+
puts "Stack set operation completed."
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
# describe_stack_set_operation stack_set_operation.status is
|
66
|
+
# one of RUNNING, SUCCEEDED, FAILED, STOPPING, STOPPED
|
67
|
+
def completed?(status)
|
68
|
+
completed_statuses = %w[SUCCEEDED FAILED STOPPED]
|
69
|
+
completed_statuses.include?(status)
|
70
|
+
end
|
71
|
+
|
72
|
+
# If we dont wait until OUTDATED, during a `lono sets deploy` it'll immediately think that the instance statuses are done
|
73
|
+
def wait_until_outdated
|
74
|
+
outdated = false
|
75
|
+
until outdated
|
76
|
+
outdated = stack_instances.detect { |stack_instance| stack_instance.status == "OUTDATED" }
|
77
|
+
sleep 5
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
def instances
|
82
|
+
stack_instances.map { |stack_instance| Instance.new(stack_instance) }
|
83
|
+
end
|
84
|
+
|
85
|
+
def stack_instances
|
86
|
+
resp = cfn.list_stack_instances(stack_set_name: @stack)
|
87
|
+
summaries = resp.summaries
|
88
|
+
# filter is really only used internally. So it's fine to keep it as complex data structure since that's what we
|
89
|
+
# build it up as in Lono::Sets::Instances::Deploy
|
90
|
+
filter = @options[:filter] # [["112233445566", "us-west-1"],["112233445566", "us-west-2"]]
|
91
|
+
return summaries unless filter
|
92
|
+
|
93
|
+
summaries.reject do |s|
|
94
|
+
intersect = [[s.account, s.region]] & filter
|
95
|
+
intersect.empty?
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
def operation_id
|
100
|
+
@operation_id ||= latest_operation_id
|
101
|
+
end
|
102
|
+
|
103
|
+
def latest_operation_id
|
104
|
+
resp = cfn.list_stack_set_operations(
|
105
|
+
stack_set_name: @stack,
|
106
|
+
max_results: 1,
|
107
|
+
)
|
108
|
+
resp.summaries.first.operation_id
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|