stax 0.1.7 → 0.1.10
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/bin/stax +3 -1
- data/lib/stax/aws/cfn.rb +4 -1
- data/lib/stax/base.rb +7 -1
- data/lib/stax/cli/ls.rb +17 -11
- data/lib/stax/cli.rb +1 -0
- data/lib/stax/mixin/rds.rb +84 -4
- data/lib/stax/stack/changeset.rb +44 -0
- data/lib/stax/stack/{imports.rb → exports.rb} +9 -3
- data/lib/stax/stack/parameters.rb +1 -1
- data/lib/stax/version.rb +1 -1
- data/lib/stax.rb +1 -1
- metadata +4 -4
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: e17c465590b04d1db946eb5cf12e660fb01a63c348aefcfadca2b5d98e568e52
|
|
4
|
+
data.tar.gz: d585924ea4d53397cc817cda8a617f7a14c430d84befa9f485ee5440a64653af
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 4d71a59e526634d2c27d768db9e979569482e53bfeb43ae3907326dd851ba983c3498d5b04ec11727461abcdee5e1dfcf7f634a0c1b6338901718b9092652fb0
|
|
7
|
+
data.tar.gz: eb8469a0fd373332b3d51171324e9ec9857c77e8a75cdf50c1f6414304af84bcfde1628087ea1866acf6a63b29f4ca5fa9cc13364ec7d8de59e2d330cd20555a
|
data/bin/stax
CHANGED
|
@@ -5,6 +5,8 @@ require 'stax'
|
|
|
5
5
|
Stax.load_staxfile
|
|
6
6
|
begin
|
|
7
7
|
Stax::Cli.start(ARGV)
|
|
8
|
-
rescue Aws::CloudFormation::Errors::ExpiredToken
|
|
8
|
+
rescue Aws::CloudFormation::Errors::ExpiredToken,
|
|
9
|
+
Aws::CloudFormation::Errors::ValidationError,
|
|
10
|
+
Aws::Errors::MissingCredentialsError => e
|
|
9
11
|
abort(e.message)
|
|
10
12
|
end
|
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/ls.rb
CHANGED
|
@@ -2,37 +2,43 @@ module Stax
|
|
|
2
2
|
class Cli < Base
|
|
3
3
|
|
|
4
4
|
no_commands do
|
|
5
|
+
## fields to show in output
|
|
6
|
+
def ls_stack_fields(s)
|
|
7
|
+
[ s.stack_name, s.creation_time, color(s.stack_status, Aws::Cfn::COLORS) ]
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
## list stacks from Staxfile in given order
|
|
5
11
|
def ls_staxfile_stacks
|
|
6
|
-
stacks = Aws::Cfn.stacks.each_with_object({}) { |s, h| h[s.stack_name] = s }
|
|
7
12
|
print_table Stax.stack_list.map { |id|
|
|
8
13
|
name = stack(id).stack_name
|
|
9
|
-
if (s =
|
|
10
|
-
|
|
14
|
+
if (s = Aws::Cfn.describe(name))
|
|
15
|
+
ls_stack_fields(s)
|
|
11
16
|
else
|
|
12
|
-
|
|
17
|
+
[ name, '-' ]
|
|
13
18
|
end
|
|
14
|
-
}
|
|
19
|
+
}
|
|
15
20
|
end
|
|
16
21
|
|
|
22
|
+
## list all extant stacks we think match our prefix
|
|
17
23
|
def ls_stacks_with_prefix(prefix)
|
|
18
24
|
print_table Aws::Cfn.stacks.select { |s|
|
|
19
25
|
s.stack_name.start_with?(prefix || stack_prefix)
|
|
20
26
|
}.map { |s|
|
|
21
|
-
|
|
27
|
+
ls_stack_fields(s)
|
|
22
28
|
}.sort
|
|
23
29
|
end
|
|
24
30
|
|
|
31
|
+
## list all stacks in account
|
|
25
32
|
def ls_account_stacks
|
|
26
33
|
print_table Aws::Cfn.stacks.map { |s|
|
|
27
|
-
|
|
34
|
+
ls_stack_fields(s)
|
|
28
35
|
}.sort
|
|
29
36
|
end
|
|
30
37
|
end
|
|
31
38
|
|
|
32
39
|
desc 'ls [PREFIX]', 'list stacks'
|
|
33
|
-
method_option :
|
|
34
|
-
method_option :
|
|
35
|
-
method_option :account, aliases: '-A', type: :boolean, default: false, desc: 'list all running stacks in account'
|
|
40
|
+
method_option :all, aliases: '-a', type: :boolean, default: false, desc: 'list all running stacks with our prefix'
|
|
41
|
+
method_option :account, aliases: '-A', type: :boolean, default: false, desc: 'list all running stacks in account'
|
|
36
42
|
def ls(prefix = nil)
|
|
37
43
|
if options[:account]
|
|
38
44
|
ls_account_stacks
|
|
@@ -44,4 +50,4 @@ module Stax
|
|
|
44
50
|
end
|
|
45
51
|
|
|
46
52
|
end
|
|
47
|
-
end
|
|
53
|
+
end
|
data/lib/stax/cli.rb
CHANGED
|
@@ -9,6 +9,7 @@ module Stax
|
|
|
9
9
|
class Cli < Base
|
|
10
10
|
class_option :branch, type: :string, default: Git.branch, desc: 'git branch to use'
|
|
11
11
|
class_option :app, type: :string, default: File.basename(Git.toplevel), desc: 'application name'
|
|
12
|
+
|
|
12
13
|
## silence deprecation warning
|
|
13
14
|
## https://github.com/erikhuda/thor/blob/fb625b223465692a9d8a88cc2a483e126f1a8978/CHANGELOG.md#100
|
|
14
15
|
def self.exit_on_failure?
|
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,67 @@ 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
|
+
|
|
161
|
+
desc 'write-forwarding', 'control write-forwarding'
|
|
162
|
+
method_option :disable, aliases: '-d', type: :boolean, desc: 'disable write-forwarding'
|
|
163
|
+
method_option :enable, aliases: '-e', type: :boolean, desc: 'enable write-forwarding'
|
|
164
|
+
def write_forwarding
|
|
165
|
+
stack_db_clusters.map(&:physical_resource_id).each do |cluster|
|
|
166
|
+
if options[:enable]
|
|
167
|
+
puts "#{cluster} enabling write-forwarding"
|
|
168
|
+
Aws::Rds.client.modify_db_cluster(db_cluster_identifier: cluster, enable_global_write_forwarding: true)
|
|
169
|
+
elsif options[:disable]
|
|
170
|
+
puts "#{cluster} disabling write-forwarding"
|
|
171
|
+
Aws::Rds.client.modify_db_cluster(db_cluster_identifier: cluster, enable_global_write_forwarding: false)
|
|
172
|
+
else
|
|
173
|
+
print_table Aws::Rds.client.describe_db_clusters(db_cluster_identifier: cluster).db_clusters.map { |c|
|
|
174
|
+
[ c.db_cluster_identifier, c.global_write_forwarding_status || '-' ]
|
|
175
|
+
}
|
|
176
|
+
end
|
|
177
|
+
end
|
|
178
|
+
end
|
|
179
|
+
|
|
100
180
|
end
|
|
101
181
|
end
|
|
102
|
-
end
|
|
182
|
+
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
|
|
@@ -94,5 +111,32 @@ module Stax
|
|
|
94
111
|
change_set_lock
|
|
95
112
|
end
|
|
96
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
|
+
|
|
97
141
|
end
|
|
98
142
|
end
|
|
@@ -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
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.10
|
|
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: 2022-03-17 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: bundler
|
|
@@ -582,7 +582,7 @@ files:
|
|
|
582
582
|
- lib/stax/stack/changeset.rb
|
|
583
583
|
- lib/stax/stack/crud.rb
|
|
584
584
|
- lib/stax/stack/drift.rb
|
|
585
|
-
- lib/stax/stack/
|
|
585
|
+
- lib/stax/stack/exports.rb
|
|
586
586
|
- lib/stax/stack/outputs.rb
|
|
587
587
|
- lib/stax/stack/parameters.rb
|
|
588
588
|
- lib/stax/stack/resources.rb
|
|
@@ -610,7 +610,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
610
610
|
- !ruby/object:Gem::Version
|
|
611
611
|
version: '0'
|
|
612
612
|
requirements: []
|
|
613
|
-
rubygems_version: 3.1.
|
|
613
|
+
rubygems_version: 3.1.6
|
|
614
614
|
signing_key:
|
|
615
615
|
specification_version: 4
|
|
616
616
|
summary: Control Cloudformation stack and other stuff.
|