stax 0.1.5 → 0.1.9
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/lib/stax/aws/cfn.rb +4 -1
- data/lib/stax/base.rb +7 -1
- data/lib/stax/cli/crud.rb +3 -2
- data/lib/stax/mixin/rds.rb +65 -4
- data/lib/stax/stack/changeset.rb +51 -3
- data/lib/stax/stack/crud.rb +23 -19
- data/lib/stax/stack/{imports.rb → exports.rb} +9 -3
- data/lib/stax/version.rb +1 -1
- data/lib/stax.rb +1 -1
- data/stax.gemspec +0 -1
- metadata +4 -18
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 184e068dc00c13a187864710303862b2049ec3f353cdf7bda094dc94fe711201
|
4
|
+
data.tar.gz: a2fa06ab9dad658167b57cfbbaf7411a73cbfeccf1cb2eb4ab4c5a50beea9c97
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6491ccdb338d2883cc657eceab4255d14b6202bea65494f3a9ef71a6e459affa813252a5bdb766fb9e12a10d4d3a2121ebe39b80f7ef7803c0f0894b10eba326
|
7
|
+
data.tar.gz: 76e87f6dc9e8569d025ab23fc6ac662e30bb00439b8f06c6e7cfb7a0cc42c7e12046a76627e7de3c6b0f493764ecef8f77e52a66fb7e68d98c0899266d6340fe
|
data/lib/stax/aws/cfn.rb
CHANGED
@@ -7,6 +7,7 @@ module Stax
|
|
7
7
|
CREATE_IN_PROGRESS CREATE_FAILED CREATE_COMPLETE
|
8
8
|
ROLLBACK_IN_PROGRESS ROLLBACK_FAILED ROLLBACK_COMPLETE
|
9
9
|
DELETE_IN_PROGRESS DELETE_FAILED
|
10
|
+
IMPORT_IN_PROGRESS IMPORT_COMPLETE IMPORT_ROLLBACK_IN_PROGRESS IMPORT_ROLLBACK_FAILED IMPORT_ROLLBACK_COMPLETE
|
10
11
|
UPDATE_IN_PROGRESS UPDATE_COMPLETE_CLEANUP_IN_PROGRESS UPDATE_COMPLETE
|
11
12
|
UPDATE_ROLLBACK_IN_PROGRESS UPDATE_ROLLBACK_FAILED UPDATE_ROLLBACK_COMPLETE_CLEANUP_IN_PROGRESS UPDATE_ROLLBACK_COMPLETE
|
12
13
|
REVIEW_IN_PROGRESS
|
@@ -17,6 +18,7 @@ module Stax
|
|
17
18
|
CREATE_COMPLETE: :green,
|
18
19
|
DELETE_COMPLETE: :green,
|
19
20
|
UPDATE_COMPLETE: :green,
|
21
|
+
IMPORT_COMPLETE: :green,
|
20
22
|
CREATE_FAILED: :red,
|
21
23
|
DELETE_FAILED: :red,
|
22
24
|
UPDATE_FAILED: :red,
|
@@ -24,6 +26,7 @@ module Stax
|
|
24
26
|
ROLLBACK_COMPLETE: :red,
|
25
27
|
## resource action
|
26
28
|
Add: :green,
|
29
|
+
Import: :green,
|
27
30
|
Modify: :yellow,
|
28
31
|
Remove: :red,
|
29
32
|
}
|
@@ -170,4 +173,4 @@ module Stax
|
|
170
173
|
|
171
174
|
end
|
172
175
|
end
|
173
|
-
end
|
176
|
+
end
|
data/lib/stax/base.rb
CHANGED
@@ -1,6 +1,9 @@
|
|
1
1
|
require 'thor'
|
2
2
|
require 'stax/aws/sts'
|
3
3
|
|
4
|
+
## clean exit on ctrl-c for all methods
|
5
|
+
trap('SIGINT', 'EXIT')
|
6
|
+
|
4
7
|
module Stax
|
5
8
|
class Base < Thor
|
6
9
|
|
@@ -68,7 +71,9 @@ module Stax
|
|
68
71
|
end
|
69
72
|
end
|
70
73
|
|
71
|
-
|
74
|
+
## color a string according to current class COLORS hash
|
75
|
+
def color(string, hash = nil)
|
76
|
+
hash ||= self.class::COLORS
|
72
77
|
set_color(string, hash.fetch(string.to_sym, :yellow))
|
73
78
|
end
|
74
79
|
|
@@ -118,6 +123,7 @@ module Stax
|
|
118
123
|
|
119
124
|
## convert a diff in seconds to d h m s
|
120
125
|
def human_time_diff(t, n = 5)
|
126
|
+
t = t.round # handle fractional seconds
|
121
127
|
mm, ss = t.divmod(60)
|
122
128
|
hh, mm = mm.divmod(60)
|
123
129
|
dd, hh = hh.divmod(24)
|
data/lib/stax/cli/crud.rb
CHANGED
@@ -56,10 +56,11 @@ module Stax
|
|
56
56
|
end
|
57
57
|
|
58
58
|
desc 'delete', 'meta delete task'
|
59
|
+
method_option :notail, aliases: '-n', type: :boolean, default: false, description: 'do not tail stack events'
|
59
60
|
def delete
|
60
61
|
stack_objects.reverse.each do |s|
|
61
62
|
if s.exists?
|
62
|
-
s.delete
|
63
|
+
s.invoke(:delete, [], options)
|
63
64
|
else
|
64
65
|
say("#{s.stack_name} does not exist", :green)
|
65
66
|
end
|
@@ -67,4 +68,4 @@ module Stax
|
|
67
68
|
end
|
68
69
|
|
69
70
|
end
|
70
|
-
end
|
71
|
+
end
|
data/lib/stax/mixin/rds.rb
CHANGED
@@ -14,6 +14,7 @@ module Stax
|
|
14
14
|
|
15
15
|
COLORS = {
|
16
16
|
available: :green,
|
17
|
+
'in-sync': :green,
|
17
18
|
Complete: :green,
|
18
19
|
Active: :green,
|
19
20
|
}
|
@@ -40,13 +41,36 @@ module Stax
|
|
40
41
|
def stack_db_subnet_groups
|
41
42
|
Aws::Cfn.resources_by_type(my.stack_name, 'AWS::RDS::DBSubnetGroup')
|
42
43
|
end
|
44
|
+
|
45
|
+
def print_rds_events(opt)
|
46
|
+
Aws::Rds.client.describe_events(opt).map(&:events).flatten.map do |e|
|
47
|
+
[ e.date, e.message ]
|
48
|
+
end.tap(&method(:print_table))
|
49
|
+
end
|
50
|
+
|
51
|
+
end
|
52
|
+
|
53
|
+
desc 'ls', 'list clusters with members'
|
54
|
+
def ls
|
55
|
+
debug("RDS databases for #{my.stack_name}")
|
56
|
+
stack_rds_clusters.map do |c|
|
57
|
+
cluster = [ c.db_cluster_identifier, 'cluster', color(c.status), c.engine ]
|
58
|
+
instances = c.db_cluster_members.map do |m|
|
59
|
+
role = m.is_cluster_writer ? 'writer' : 'reader'
|
60
|
+
i = Aws::Rds.instances(filters: [ { name: 'db-instance-id', values: [ m.db_instance_identifier ] } ]).first
|
61
|
+
[ '- ' + i.db_instance_identifier, role, color(i.db_instance_status), i.engine, i.availability_zone, i.db_instance_class ]
|
62
|
+
end
|
63
|
+
[ cluster ] + instances
|
64
|
+
end.flatten(1).tap do |list|
|
65
|
+
print_table list
|
66
|
+
end
|
43
67
|
end
|
44
68
|
|
45
69
|
desc 'clusters', 'list db clusters for stack'
|
46
70
|
def clusters
|
47
71
|
debug("RDS DB clusters for #{my.stack_name}")
|
48
72
|
print_table stack_rds_clusters.map { |c|
|
49
|
-
[c.db_cluster_identifier, c.engine, c.engine_version, color(c.status
|
73
|
+
[c.db_cluster_identifier, c.engine, c.engine_version, color(c.status), c.cluster_create_time]
|
50
74
|
}
|
51
75
|
end
|
52
76
|
|
@@ -65,7 +89,7 @@ module Stax
|
|
65
89
|
def instances
|
66
90
|
debug("RDS DB instances for #{my.stack_name}")
|
67
91
|
print_table stack_rds_instances.map { |i|
|
68
|
-
[i.db_instance_identifier, i.engine, i.engine_version, color(i.db_instance_status
|
92
|
+
[i.db_instance_identifier, i.engine, i.engine_version, color(i.db_instance_status), i.db_instance_class, i.db_subnet_group&.vpc_id, i.availability_zone]
|
69
93
|
}
|
70
94
|
end
|
71
95
|
|
@@ -92,11 +116,48 @@ module Stax
|
|
92
116
|
end.flatten.each do |g|
|
93
117
|
debug("Subnets for group #{g.db_subnet_group_name}")
|
94
118
|
print_table g.subnets.map { |s|
|
95
|
-
[s&.subnet_availability_zone&.name, s&.subnet_identifier, color(s&.subnet_status
|
119
|
+
[s&.subnet_availability_zone&.name, s&.subnet_identifier, color(s&.subnet_status)]
|
96
120
|
}
|
97
121
|
end
|
98
122
|
end
|
99
123
|
|
124
|
+
desc 'failover', 'failover clusters'
|
125
|
+
method_option :target, type: :string, default: nil, desc: 'id of instance to promote'
|
126
|
+
def failover
|
127
|
+
stack_rds_clusters.each do |c|
|
128
|
+
if yes?("Failover #{c.db_cluster_identifier}?", :yellow)
|
129
|
+
resp = Aws::Rds.client.failover_db_cluster(db_cluster_identifier: c.db_cluster_identifier, target_db_instance_identifier: options[:target])
|
130
|
+
puts "failing over #{resp.db_cluster.db_cluster_identifier}"
|
131
|
+
end
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
desc 'snapshots', 'list snapshots for stack clusters'
|
136
|
+
def snapshots
|
137
|
+
stack_db_clusters.map(&:physical_resource_id).each do |id|
|
138
|
+
debug("Snapshots for cluster #{id}")
|
139
|
+
Aws::Rds.client.describe_db_cluster_snapshots(db_cluster_identifier: id).map(&:db_cluster_snapshots).flatten.map do |s|
|
140
|
+
[ s.db_cluster_snapshot_identifier, s.snapshot_create_time, "#{s.allocated_storage}G", color(s.status), s.snapshot_type ]
|
141
|
+
end.tap do |list|
|
142
|
+
print_table list
|
143
|
+
end
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
desc 'events', 'list rds events for this stack'
|
148
|
+
option :duration, aliases: '-d', type: :numeric, default: 60*24, desc: 'duration in mins to show'
|
149
|
+
def events
|
150
|
+
stack_db_clusters.map(&:physical_resource_id).each do |id|
|
151
|
+
debug("Events for cluster #{id}")
|
152
|
+
print_rds_events(duration: options[:duration], source_type: 'db-cluster', source_identifier: id)
|
153
|
+
end
|
154
|
+
|
155
|
+
stack_db_instances.map(&:physical_resource_id).each do |id|
|
156
|
+
debug("Events for instance #{id}")
|
157
|
+
print_rds_events(duration: options[:duration], source_type: 'db-instance', source_identifier: id)
|
158
|
+
end
|
159
|
+
end
|
160
|
+
|
100
161
|
end
|
101
162
|
end
|
102
|
-
end
|
163
|
+
end
|
data/lib/stax/stack/changeset.rb
CHANGED
@@ -30,6 +30,23 @@ module Stax
|
|
30
30
|
fail_task(e.message)
|
31
31
|
end
|
32
32
|
|
33
|
+
## create change set to import a resource
|
34
|
+
def change_set_import(resource)
|
35
|
+
Aws::Cfn.changeset(
|
36
|
+
change_set_type: :IMPORT,
|
37
|
+
resources_to_import: [ resource ],
|
38
|
+
stack_name: stack_name,
|
39
|
+
template_body: cfn_template_body,
|
40
|
+
template_url: cfn_template_url,
|
41
|
+
parameters: cfn_parameters_update,
|
42
|
+
capabilities: cfn_capabilities,
|
43
|
+
notification_arns: cfn_notification_arns,
|
44
|
+
change_set_name: change_set_name,
|
45
|
+
).id
|
46
|
+
rescue ::Aws::CloudFormation::Errors::ValidationError => e
|
47
|
+
fail_task(e.message)
|
48
|
+
end
|
49
|
+
|
33
50
|
## wait and return true if changeset ready for execute
|
34
51
|
def change_set_complete?(id)
|
35
52
|
begin
|
@@ -71,11 +88,15 @@ module Stax
|
|
71
88
|
end
|
72
89
|
|
73
90
|
def change_set_unlock
|
74
|
-
|
91
|
+
unless stack_policy_during_update.nil?
|
92
|
+
Aws::Cfn.set_policy(stack_name: stack_name, stack_policy_body: stack_policy_during_update)
|
93
|
+
end
|
75
94
|
end
|
76
95
|
|
77
96
|
def change_set_lock
|
78
|
-
|
97
|
+
unless stack_policy.nil?
|
98
|
+
Aws::Cfn.set_policy(stack_name: stack_name, stack_policy_body: stack_policy)
|
99
|
+
end
|
79
100
|
end
|
80
101
|
end
|
81
102
|
|
@@ -90,5 +111,32 @@ module Stax
|
|
90
111
|
change_set_lock
|
91
112
|
end
|
92
113
|
|
114
|
+
desc 'import', 'create and execute changeset to import a resource'
|
115
|
+
option :type, aliases: '-t', type: :string, default: nil, desc: 'cfn resource (e.g. AWS::DynamoDB::Table)'
|
116
|
+
option :id, aliases: '-i', type: :string, default: nil, desc: 'logical id (e.g. OrdersTable)'
|
117
|
+
option :key, aliases: '-k', type: :string, default: nil, desc: 'resource key (e.g. TableName)'
|
118
|
+
option :value, aliases: '-v', type: :string, default: nil, desc: 'resource value (e.g. orders)'
|
119
|
+
def import
|
120
|
+
## prompt for missing options
|
121
|
+
%i[type id key value].each do |opt|
|
122
|
+
options[opt] ||= ask("Resource #{opt}?", :yellow)
|
123
|
+
end
|
124
|
+
|
125
|
+
## create import changeset
|
126
|
+
debug("Creating import change set for #{stack_name}")
|
127
|
+
id = change_set_import(
|
128
|
+
resource_type: options[:type],
|
129
|
+
logical_resource_id: options[:id],
|
130
|
+
resource_identifier: {
|
131
|
+
options[:key] => options[:value]
|
132
|
+
}
|
133
|
+
)
|
134
|
+
|
135
|
+
## wait for changeset, prompt for changes, and execute
|
136
|
+
change_set_complete?(id) || fail_task(change_set_reason(id))
|
137
|
+
change_set_changes(id)
|
138
|
+
change_set_execute(id) && tail && update_warn_imports
|
139
|
+
end
|
140
|
+
|
93
141
|
end
|
94
|
-
end
|
142
|
+
end
|
data/lib/stax/stack/crud.rb
CHANGED
@@ -24,28 +24,31 @@ module Stax
|
|
24
24
|
}
|
25
25
|
end
|
26
26
|
|
27
|
-
## policy to lock the stack to all updates
|
27
|
+
## policy to lock the stack to all updates, for example:
|
28
|
+
## {
|
29
|
+
## Statement: [
|
30
|
+
## Effect: 'Deny',
|
31
|
+
## Action: 'Update:*',
|
32
|
+
## Principal: '*',
|
33
|
+
## Resource: '*'
|
34
|
+
## ]
|
35
|
+
## }.to_json
|
28
36
|
def stack_policy
|
29
|
-
|
30
|
-
Statement: [
|
31
|
-
Effect: 'Deny',
|
32
|
-
Action: 'Update:*',
|
33
|
-
Principal: '*',
|
34
|
-
Resource: '*'
|
35
|
-
]
|
36
|
-
}.to_json
|
37
|
+
nil
|
37
38
|
end
|
38
39
|
|
39
|
-
##
|
40
|
+
## tmp policy during updates, in case a deny was set in stack_policy()
|
41
|
+
## for example:
|
42
|
+
## {
|
43
|
+
## Statement: [
|
44
|
+
## Effect: 'Allow',
|
45
|
+
## Action: 'Update:*',
|
46
|
+
## Principal: '*',
|
47
|
+
## Resource: '*'
|
48
|
+
## ]
|
49
|
+
## }.to_json
|
40
50
|
def stack_policy_during_update
|
41
|
-
|
42
|
-
Statement: [
|
43
|
-
Effect: 'Allow',
|
44
|
-
Action: 'Update:*',
|
45
|
-
Principal: '*',
|
46
|
-
Resource: '*'
|
47
|
-
]
|
48
|
-
}.to_json
|
51
|
+
nil
|
49
52
|
end
|
50
53
|
|
51
54
|
## cleanup sometimes needs to wait
|
@@ -206,11 +209,12 @@ module Stax
|
|
206
209
|
end
|
207
210
|
|
208
211
|
desc 'delete', 'delete stack'
|
212
|
+
method_option :notail, aliases: '-n', type: :boolean, default: false, description: 'do not tail stack events'
|
209
213
|
def delete
|
210
214
|
delete_warn_imports
|
211
215
|
if yes? "Really delete stack #{stack_name}?", :yellow
|
212
216
|
Aws::Cfn.delete(stack_name)
|
213
|
-
tail
|
217
|
+
tail unless options[:notail]
|
214
218
|
end
|
215
219
|
rescue ::Aws::CloudFormation::Errors::ValidationError => e
|
216
220
|
fail_task(e.message)
|
@@ -21,8 +21,8 @@ module Stax
|
|
21
21
|
end
|
22
22
|
end
|
23
23
|
|
24
|
-
desc '
|
25
|
-
def
|
24
|
+
desc 'exports', 'list exports from this stack, and stacks that import them'
|
25
|
+
def exports
|
26
26
|
debug("Stacks that import from #{stack_name}")
|
27
27
|
print_table Aws::Cfn.exports(stack_name).map { |e|
|
28
28
|
imports = (i = Aws::Cfn.imports(e.export_name)).empty? ? '-' : i.join(' ')
|
@@ -30,5 +30,11 @@ module Stax
|
|
30
30
|
}.sort
|
31
31
|
end
|
32
32
|
|
33
|
+
desc 'imports', 'deprecated: use exports'
|
34
|
+
def imports
|
35
|
+
warn("deprecated method: please use 'exports' instead")
|
36
|
+
exports
|
37
|
+
end
|
38
|
+
|
33
39
|
end
|
34
|
-
end
|
40
|
+
end
|
data/lib/stax/version.rb
CHANGED
data/lib/stax.rb
CHANGED
data/stax.gemspec
CHANGED
@@ -23,7 +23,6 @@ Gem::Specification.new do |spec|
|
|
23
23
|
|
24
24
|
spec.add_development_dependency "bundler"
|
25
25
|
spec.add_development_dependency "rake", "~> 10.0"
|
26
|
-
spec.add_development_dependency "docile", "1.2.0"
|
27
26
|
spec.add_development_dependency "stax-examples"
|
28
27
|
|
29
28
|
spec.add_dependency('aws-sdk-cloudformation')
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: stax
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.9
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Richard Lister
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2021-10-25 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -38,20 +38,6 @@ dependencies:
|
|
38
38
|
- - "~>"
|
39
39
|
- !ruby/object:Gem::Version
|
40
40
|
version: '10.0'
|
41
|
-
- !ruby/object:Gem::Dependency
|
42
|
-
name: docile
|
43
|
-
requirement: !ruby/object:Gem::Requirement
|
44
|
-
requirements:
|
45
|
-
- - '='
|
46
|
-
- !ruby/object:Gem::Version
|
47
|
-
version: 1.2.0
|
48
|
-
type: :development
|
49
|
-
prerelease: false
|
50
|
-
version_requirements: !ruby/object:Gem::Requirement
|
51
|
-
requirements:
|
52
|
-
- - '='
|
53
|
-
- !ruby/object:Gem::Version
|
54
|
-
version: 1.2.0
|
55
41
|
- !ruby/object:Gem::Dependency
|
56
42
|
name: stax-examples
|
57
43
|
requirement: !ruby/object:Gem::Requirement
|
@@ -596,7 +582,7 @@ files:
|
|
596
582
|
- lib/stax/stack/changeset.rb
|
597
583
|
- lib/stax/stack/crud.rb
|
598
584
|
- lib/stax/stack/drift.rb
|
599
|
-
- lib/stax/stack/
|
585
|
+
- lib/stax/stack/exports.rb
|
600
586
|
- lib/stax/stack/outputs.rb
|
601
587
|
- lib/stax/stack/parameters.rb
|
602
588
|
- lib/stax/stack/resources.rb
|
@@ -624,7 +610,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
624
610
|
- !ruby/object:Gem::Version
|
625
611
|
version: '0'
|
626
612
|
requirements: []
|
627
|
-
rubygems_version: 3.1.
|
613
|
+
rubygems_version: 3.1.4
|
628
614
|
signing_key:
|
629
615
|
specification_version: 4
|
630
616
|
summary: Control Cloudformation stack and other stuff.
|