stack_master 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +18 -0
- data/.rspec +2 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +208 -0
- data/Rakefile +11 -0
- data/apply_demo.gif +0 -0
- data/bin/stack_master +16 -0
- data/example/simple/Gemfile +3 -0
- data/example/simple/parameters/myapp_vpc.yml +1 -0
- data/example/simple/parameters/myapp_web.yml +2 -0
- data/example/simple/stack_master.yml +13 -0
- data/example/simple/templates/myapp_vpc.rb +39 -0
- data/example/simple/templates/myapp_web.rb +16 -0
- data/features/apply.feature +241 -0
- data/features/delete.feature +43 -0
- data/features/diff.feature +191 -0
- data/features/events.feature +38 -0
- data/features/init.feature +6 -0
- data/features/outputs.feature +49 -0
- data/features/region_aliases.feature +66 -0
- data/features/resources.feature +45 -0
- data/features/stack_defaults.feature +88 -0
- data/features/status.feature +124 -0
- data/features/step_definitions/stack_steps.rb +50 -0
- data/features/support/env.rb +14 -0
- data/lib/stack_master.rb +81 -0
- data/lib/stack_master/aws_driver/cloud_formation.rb +56 -0
- data/lib/stack_master/cli.rb +164 -0
- data/lib/stack_master/command.rb +13 -0
- data/lib/stack_master/commands/apply.rb +104 -0
- data/lib/stack_master/commands/delete.rb +53 -0
- data/lib/stack_master/commands/diff.rb +31 -0
- data/lib/stack_master/commands/events.rb +39 -0
- data/lib/stack_master/commands/init.rb +109 -0
- data/lib/stack_master/commands/list_stacks.rb +16 -0
- data/lib/stack_master/commands/outputs.rb +27 -0
- data/lib/stack_master/commands/resources.rb +33 -0
- data/lib/stack_master/commands/status.rb +47 -0
- data/lib/stack_master/commands/validate.rb +17 -0
- data/lib/stack_master/config.rb +86 -0
- data/lib/stack_master/ctrl_c.rb +4 -0
- data/lib/stack_master/parameter_loader.rb +17 -0
- data/lib/stack_master/parameter_resolver.rb +45 -0
- data/lib/stack_master/parameter_resolvers/secret.rb +42 -0
- data/lib/stack_master/parameter_resolvers/security_group.rb +20 -0
- data/lib/stack_master/parameter_resolvers/sns_topic_name.rb +29 -0
- data/lib/stack_master/parameter_resolvers/stack_output.rb +53 -0
- data/lib/stack_master/prompter.rb +14 -0
- data/lib/stack_master/security_group_finder.rb +29 -0
- data/lib/stack_master/sns_topic_finder.rb +27 -0
- data/lib/stack_master/stack.rb +96 -0
- data/lib/stack_master/stack_definition.rb +49 -0
- data/lib/stack_master/stack_differ.rb +80 -0
- data/lib/stack_master/stack_events/fetcher.rb +45 -0
- data/lib/stack_master/stack_events/presenter.rb +27 -0
- data/lib/stack_master/stack_events/streamer.rb +55 -0
- data/lib/stack_master/stack_states.rb +34 -0
- data/lib/stack_master/template_compiler.rb +21 -0
- data/lib/stack_master/test_driver/cloud_formation.rb +139 -0
- data/lib/stack_master/testing.rb +7 -0
- data/lib/stack_master/utils.rb +31 -0
- data/lib/stack_master/validator.rb +25 -0
- data/lib/stack_master/version.rb +3 -0
- data/logo.png +0 -0
- data/script/buildkite/bundle.sh +5 -0
- data/script/buildkite/clean.sh +3 -0
- data/script/buildkite_rspec.sh +27 -0
- data/spec/fixtures/parameters/myapp_vpc.yml +1 -0
- data/spec/fixtures/stack_master.yml +35 -0
- data/spec/fixtures/templates/myapp_vpc.json +1 -0
- data/spec/spec_helper.rb +99 -0
- data/spec/stack_master/commands/apply_spec.rb +92 -0
- data/spec/stack_master/commands/delete_spec.rb +40 -0
- data/spec/stack_master/commands/init_spec.rb +17 -0
- data/spec/stack_master/commands/status_spec.rb +38 -0
- data/spec/stack_master/commands/validate_spec.rb +26 -0
- data/spec/stack_master/config_spec.rb +81 -0
- data/spec/stack_master/parameter_loader_spec.rb +81 -0
- data/spec/stack_master/parameter_resolver_spec.rb +58 -0
- data/spec/stack_master/parameter_resolvers/secret_spec.rb +66 -0
- data/spec/stack_master/parameter_resolvers/security_group_spec.rb +17 -0
- data/spec/stack_master/parameter_resolvers/sns_topic_name_spec.rb +43 -0
- data/spec/stack_master/parameter_resolvers/stack_output_spec.rb +77 -0
- data/spec/stack_master/security_group_finder_spec.rb +49 -0
- data/spec/stack_master/sns_topic_finder_spec.rb +25 -0
- data/spec/stack_master/stack_definition_spec.rb +37 -0
- data/spec/stack_master/stack_differ_spec.rb +34 -0
- data/spec/stack_master/stack_events/fetcher_spec.rb +65 -0
- data/spec/stack_master/stack_events/presenter_spec.rb +18 -0
- data/spec/stack_master/stack_events/streamer_spec.rb +33 -0
- data/spec/stack_master/stack_spec.rb +157 -0
- data/spec/stack_master/template_compiler_spec.rb +48 -0
- data/spec/stack_master/test_driver/cloud_formation_spec.rb +24 -0
- data/spec/stack_master/utils_spec.rb +30 -0
- data/spec/stack_master/validator_spec.rb +38 -0
- data/stack_master.gemspec +38 -0
- data/stacktemplates/parameter_region.yml +3 -0
- data/stacktemplates/parameter_stack_name.yml +3 -0
- data/stacktemplates/stack.json.erb +20 -0
- data/stacktemplates/stack_master.yml.erb +6 -0
- metadata +427 -0
@@ -0,0 +1,124 @@
|
|
1
|
+
Feature: Status command
|
2
|
+
|
3
|
+
Background:
|
4
|
+
Given a file named "stack_master.yml" with:
|
5
|
+
"""
|
6
|
+
stacks:
|
7
|
+
us_east_1:
|
8
|
+
stack1:
|
9
|
+
template: stack1.json
|
10
|
+
stack2:
|
11
|
+
template: stack2.json
|
12
|
+
stack3:
|
13
|
+
template: stack3.json
|
14
|
+
"""
|
15
|
+
And a directory named "parameters"
|
16
|
+
And a file named "parameters/stack1.yml" with:
|
17
|
+
"""
|
18
|
+
KeyName: my-key
|
19
|
+
"""
|
20
|
+
And a directory named "templates"
|
21
|
+
And a file named "templates/stack1.json" with:
|
22
|
+
"""
|
23
|
+
{
|
24
|
+
"AWSTemplateFormatVersion": "2010-09-09",
|
25
|
+
"Description": "Test template",
|
26
|
+
"Parameters": {
|
27
|
+
"InstanceTypeParameter" : { "Type" : "String" }
|
28
|
+
},
|
29
|
+
"Mappings": {},
|
30
|
+
"Resources": {
|
31
|
+
"MyAwesomeQueue" : {
|
32
|
+
"Type" : "AWS::SQS::Queue",
|
33
|
+
"Properties" : {
|
34
|
+
"VisibilityTimeout" : "1"
|
35
|
+
}
|
36
|
+
}
|
37
|
+
},
|
38
|
+
"Outputs": {}
|
39
|
+
}
|
40
|
+
"""
|
41
|
+
And a file named "templates/stack2.json" with:
|
42
|
+
"""
|
43
|
+
{
|
44
|
+
"AWSTemplateFormatVersion": "2010-09-09",
|
45
|
+
"Description": "Test template",
|
46
|
+
"Parameters": {},
|
47
|
+
"Mappings": {},
|
48
|
+
"Resources": {
|
49
|
+
"MoarQueue" : {
|
50
|
+
"Type" : "AWS::SQS::Queue",
|
51
|
+
"Properties" : {
|
52
|
+
"VisibilityTimeout" : "1"
|
53
|
+
}
|
54
|
+
}
|
55
|
+
},
|
56
|
+
"Outputs": {}
|
57
|
+
}
|
58
|
+
"""
|
59
|
+
And a file named "templates/stack3.json" with:
|
60
|
+
"""
|
61
|
+
{
|
62
|
+
}
|
63
|
+
"""
|
64
|
+
And I set the environment variables to:
|
65
|
+
| variable | value |
|
66
|
+
| STUB_AWS | true |
|
67
|
+
|
68
|
+
Scenario: Run status command and get a list of stack statuii
|
69
|
+
Given I set the environment variables to:
|
70
|
+
| variable | value |
|
71
|
+
| ANSWER | y |
|
72
|
+
And I stub the following stacks:
|
73
|
+
| stack_id | stack_name | parameters | region | stack_status |
|
74
|
+
| 1 | stack1 | KeyName=my-key | us-east-1 | CREATE_COMPLETE |
|
75
|
+
| 2 | stack2 | | us-east-1 | UPDATE_COMPLETE |
|
76
|
+
And I stub a template for the stack "stack1":
|
77
|
+
"""
|
78
|
+
{
|
79
|
+
"AWSTemplateFormatVersion": "2010-09-09",
|
80
|
+
"Description": "Test template",
|
81
|
+
"Parameters": {
|
82
|
+
"InstanceTypeParameter" : { "Type" : "String" }
|
83
|
+
},
|
84
|
+
"Mappings": {},
|
85
|
+
"Resources": {
|
86
|
+
"MyAwesomeQueue" : {
|
87
|
+
"Type" : "AWS::SQS::Queue",
|
88
|
+
"Properties" : {
|
89
|
+
"VisibilityTimeout" : "7"
|
90
|
+
}
|
91
|
+
}
|
92
|
+
},
|
93
|
+
"Outputs": {}
|
94
|
+
}
|
95
|
+
"""
|
96
|
+
And I stub a template for the stack "stack2":
|
97
|
+
"""
|
98
|
+
{
|
99
|
+
"AWSTemplateFormatVersion": "2010-09-09",
|
100
|
+
"Description": "Test template",
|
101
|
+
"Parameters": {},
|
102
|
+
"Mappings": {},
|
103
|
+
"Resources": {
|
104
|
+
"MoarQueue" : {
|
105
|
+
"Type" : "AWS::SQS::Queue",
|
106
|
+
"Properties" : {
|
107
|
+
"VisibilityTimeout" : "1"
|
108
|
+
}
|
109
|
+
}
|
110
|
+
},
|
111
|
+
"Outputs": {}
|
112
|
+
}
|
113
|
+
"""
|
114
|
+
|
115
|
+
When I run `stack_master status --trace` interactively
|
116
|
+
And the output should contain all of these lines:
|
117
|
+
| REGION \| STACK_NAME \| STACK_STATUS \| DIFFERENT |
|
118
|
+
| ----------\|------------\|-----------------\|---------- |
|
119
|
+
| us-east-1 \| stack1 \| CREATE_COMPLETE \| Yes |
|
120
|
+
| us-east-1 \| stack2 \| UPDATE_COMPLETE \| No |
|
121
|
+
| us-east-1 \| stack3 \| \| Yes |
|
122
|
+
|
123
|
+
Then the exit status should be 0
|
124
|
+
|
@@ -0,0 +1,50 @@
|
|
1
|
+
Given(/^I stub the following stack events:$/) do |table|
|
2
|
+
table.hashes.each do |row|
|
3
|
+
row.symbolize_keys!
|
4
|
+
StackMaster.cloud_formation_driver.add_stack_event(row)
|
5
|
+
end
|
6
|
+
end
|
7
|
+
|
8
|
+
Given(/^I stub the following stack resources:$/) do |table|
|
9
|
+
table.hashes.each do |row|
|
10
|
+
row.symbolize_keys!
|
11
|
+
StackMaster.cloud_formation_driver.add_stack_resource(row)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def extract_hash_from_kv_string(string)
|
16
|
+
string.to_s.split(',').inject({}) do |hash, kv|
|
17
|
+
key, value = kv.split('=')
|
18
|
+
hash[key] = value
|
19
|
+
hash
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
|
24
|
+
Given(/^I stub the following stacks:$/) do |table|
|
25
|
+
table.hashes.each do |row|
|
26
|
+
row.symbolize_keys!
|
27
|
+
row[:parameters] = StackMaster::Utils.hash_to_aws_parameters(extract_hash_from_kv_string(row[:parameters]))
|
28
|
+
outputs = extract_hash_from_kv_string(row[:outputs]).inject([]) do |array, (k, v)|
|
29
|
+
array << OpenStruct.new(output_key: k, output_value: v)
|
30
|
+
array
|
31
|
+
end
|
32
|
+
row[:outputs] = outputs
|
33
|
+
StackMaster.cloud_formation_driver.add_stack(row)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
Given(/^I stub a template for the stack "([^"]*)":$/) do |stack_name, template_body|
|
38
|
+
StackMaster.cloud_formation_driver.set_template(stack_name, template_body)
|
39
|
+
end
|
40
|
+
|
41
|
+
Then(/^the stack "([^"]*)" should have a policy with the following:$/) do |stack_name, policy|
|
42
|
+
stack_policy_body = StackMaster.cloud_formation_driver.get_stack_policy(stack_name: stack_name).stack_policy_body
|
43
|
+
expect(stack_policy_body).to eq policy
|
44
|
+
end
|
45
|
+
|
46
|
+
Then(/^the stack "([^"]*)" should contain this notification ARN "([^"]*)"$/) do |stack_name, notification_arn|
|
47
|
+
stack = StackMaster.cloud_formation_driver.describe_stacks(stack_name: stack_name).stacks.first
|
48
|
+
expect(stack).to be
|
49
|
+
expect(stack.notification_arns).to include notification_arn
|
50
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
require 'aruba/cucumber'
|
2
|
+
require 'stack_master'
|
3
|
+
require 'stack_master/testing'
|
4
|
+
require 'aruba/in_process'
|
5
|
+
require 'pry'
|
6
|
+
|
7
|
+
Aruba.configure do |config|
|
8
|
+
config.command_launcher = :in_process
|
9
|
+
config.main_class = StackMaster::CLI
|
10
|
+
end
|
11
|
+
|
12
|
+
Before do
|
13
|
+
StackMaster.cloud_formation_driver.reset
|
14
|
+
end
|
data/lib/stack_master.rb
ADDED
@@ -0,0 +1,81 @@
|
|
1
|
+
require "commander"
|
2
|
+
require "yaml"
|
3
|
+
require "virtus"
|
4
|
+
require "aws-sdk"
|
5
|
+
require "diffy"
|
6
|
+
require "colorize"
|
7
|
+
require "table_print"
|
8
|
+
require 'active_support/core_ext/string'
|
9
|
+
require "erb"
|
10
|
+
require 'sparkle_formation'
|
11
|
+
require 'dotgpg'
|
12
|
+
|
13
|
+
require "stack_master/ctrl_c"
|
14
|
+
require "stack_master/command"
|
15
|
+
require "stack_master/version"
|
16
|
+
require "stack_master/stack"
|
17
|
+
require "stack_master/prompter"
|
18
|
+
require "stack_master/aws_driver/cloud_formation"
|
19
|
+
require "stack_master/test_driver/cloud_formation"
|
20
|
+
require "stack_master/stack_events/fetcher"
|
21
|
+
require "stack_master/stack_events/presenter"
|
22
|
+
require "stack_master/stack_events/streamer"
|
23
|
+
require "stack_master/stack_states"
|
24
|
+
require "stack_master/sns_topic_finder"
|
25
|
+
require "stack_master/security_group_finder"
|
26
|
+
require "stack_master/parameter_loader"
|
27
|
+
require "stack_master/parameter_resolver"
|
28
|
+
require "stack_master/parameter_resolvers/stack_output"
|
29
|
+
require "stack_master/parameter_resolvers/secret"
|
30
|
+
require "stack_master/parameter_resolvers/sns_topic_name"
|
31
|
+
require "stack_master/parameter_resolvers/security_group"
|
32
|
+
require "stack_master/utils"
|
33
|
+
require "stack_master/config"
|
34
|
+
require "stack_master/stack_definition"
|
35
|
+
require "stack_master/template_compiler"
|
36
|
+
require "stack_master/commands/apply"
|
37
|
+
require "stack_master/commands/events"
|
38
|
+
require "stack_master/commands/outputs"
|
39
|
+
require "stack_master/commands/init"
|
40
|
+
require "stack_master/commands/diff"
|
41
|
+
require "stack_master/commands/list_stacks"
|
42
|
+
require "stack_master/commands/validate"
|
43
|
+
require "stack_master/commands/resources"
|
44
|
+
require "stack_master/commands/delete"
|
45
|
+
require "stack_master/commands/status"
|
46
|
+
require "stack_master/stack_differ"
|
47
|
+
require "stack_master/validator"
|
48
|
+
require "stack_master/cli"
|
49
|
+
|
50
|
+
module StackMaster
|
51
|
+
extend self
|
52
|
+
|
53
|
+
def base_dir
|
54
|
+
File.expand_path(File.join(File.dirname(__FILE__), ".."))
|
55
|
+
end
|
56
|
+
|
57
|
+
def cloud_formation_driver
|
58
|
+
@cloud_formation_driver ||= AwsDriver::CloudFormation.new
|
59
|
+
end
|
60
|
+
|
61
|
+
def cloud_formation_driver=(value)
|
62
|
+
@cloud_formation_driver = value
|
63
|
+
end
|
64
|
+
|
65
|
+
def stdout
|
66
|
+
@stdout || $stdout
|
67
|
+
end
|
68
|
+
|
69
|
+
def stdout=(io)
|
70
|
+
@stdout = io
|
71
|
+
end
|
72
|
+
|
73
|
+
def stderr
|
74
|
+
@stderr || $stderr
|
75
|
+
end
|
76
|
+
|
77
|
+
def stderr=(io)
|
78
|
+
@stderr = io
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
@@ -0,0 +1,56 @@
|
|
1
|
+
module StackMaster
|
2
|
+
module AwsDriver
|
3
|
+
class CloudFormation
|
4
|
+
def set_region(region)
|
5
|
+
@region = region
|
6
|
+
@cf = nil
|
7
|
+
end
|
8
|
+
|
9
|
+
def delete_stack(options)
|
10
|
+
cf.delete_stack(options)
|
11
|
+
end
|
12
|
+
|
13
|
+
def describe_stacks(options)
|
14
|
+
cf.describe_stacks(options)
|
15
|
+
end
|
16
|
+
|
17
|
+
def cancel_update_stack(options)
|
18
|
+
cf.cancel_update_stack(options)
|
19
|
+
end
|
20
|
+
|
21
|
+
def describe_stack_resources(options)
|
22
|
+
cf.describe_stack_resources(options)
|
23
|
+
end
|
24
|
+
|
25
|
+
def get_template(options)
|
26
|
+
cf.get_template(options)
|
27
|
+
end
|
28
|
+
|
29
|
+
def get_stack_policy(options)
|
30
|
+
cf.get_stack_policy(options)
|
31
|
+
end
|
32
|
+
|
33
|
+
def describe_stack_events(options)
|
34
|
+
cf.describe_stack_events(options)
|
35
|
+
end
|
36
|
+
|
37
|
+
def update_stack(options)
|
38
|
+
cf.update_stack(options)
|
39
|
+
end
|
40
|
+
|
41
|
+
def create_stack(options)
|
42
|
+
cf.create_stack(options)
|
43
|
+
end
|
44
|
+
|
45
|
+
def validate_template(options)
|
46
|
+
cf.validate_template(options)
|
47
|
+
end
|
48
|
+
|
49
|
+
private
|
50
|
+
|
51
|
+
def cf
|
52
|
+
@cf ||= Aws::CloudFormation::Client.new(region: @region)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
@@ -0,0 +1,164 @@
|
|
1
|
+
require 'commander'
|
2
|
+
|
3
|
+
module StackMaster
|
4
|
+
class CLI
|
5
|
+
include Commander::Methods
|
6
|
+
|
7
|
+
def initialize(argv, stdin=STDIN, stdout=STDOUT, stderr=STDERR, kernel=Kernel)
|
8
|
+
@argv, @stdin, @stdout, @stderr, @kernel = argv, stdin, stdout, stderr, kernel
|
9
|
+
Commander::Runner.instance_variable_set('@singleton', Commander::Runner.new(argv))
|
10
|
+
StackMaster.stdout = @stdout
|
11
|
+
StackMaster.stderr = @stderr
|
12
|
+
TablePrint::Config.io = StackMaster.stdout
|
13
|
+
end
|
14
|
+
|
15
|
+
def execute!
|
16
|
+
program :name, 'StackMaster'
|
17
|
+
program :version, '0.0.1'
|
18
|
+
program :description, 'AWS Stack Management'
|
19
|
+
|
20
|
+
global_option '-c', '--config FILE', 'Config file to use'
|
21
|
+
|
22
|
+
command :apply do |c|
|
23
|
+
c.syntax = 'stack_master apply [region_or_alias] [stack_name]'
|
24
|
+
c.summary = 'Creates or updates a stack'
|
25
|
+
c.description = "Creates or updates a stack. Shows a diff of the proposed stack's template and parameters. Tails stack events until CloudFormation has completed."
|
26
|
+
c.example 'update a stack named myapp-vpc in us-east-1', 'stack_master apply us-east-1 myapp-vpc'
|
27
|
+
c.action do |args, options|
|
28
|
+
execute_stack_command(StackMaster::Commands::Apply, args, options)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
command :outputs do |c|
|
33
|
+
c.syntax = 'stack_master outputs [region_or_alias] [stack_name]'
|
34
|
+
c.summary = 'Displays outputs for a stack'
|
35
|
+
c.description = "Displays outputs for a stack"
|
36
|
+
c.action do |args, options|
|
37
|
+
execute_stack_command(StackMaster::Commands::Outputs, args, options)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
command :init do |c|
|
42
|
+
c.syntax = 'stack_master init [region_or_alias] [stack_name]'
|
43
|
+
c.summary = 'Initialises the expected directory structure and stack_master.yml file'
|
44
|
+
c.description = 'Initialises the expected directory structure and stack_master.yml file'
|
45
|
+
c.option('--overwrite', 'Overwrite existing files')
|
46
|
+
c.action do |args, options|
|
47
|
+
unless args.size == 2
|
48
|
+
say "Invalid arguments. stack_master init [region] [stack_name]"
|
49
|
+
else
|
50
|
+
StackMaster::Commands::Init.perform(options.overwrite, *args)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
command :diff do |c|
|
56
|
+
c.syntax = 'stack_master diff [region_or_alias] [stack_name]'
|
57
|
+
c.summary = "Shows a diff of the proposed stack's template and parameters"
|
58
|
+
c.description = "Shows a diff of the proposed stack's template and parameters"
|
59
|
+
c.example 'diff a stack named myapp-vpc in us-east-1', 'stack_master diff us-east-1 myapp-vpc'
|
60
|
+
c.action do |args, options|
|
61
|
+
execute_stack_command(StackMaster::Commands::Diff, args, options)
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
command :events do |c|
|
66
|
+
c.syntax = 'stack_master events [region_or_alias] [stack_name]'
|
67
|
+
c.summary = "Shows events for a stack"
|
68
|
+
c.description = "Shows events for a stack"
|
69
|
+
c.example 'show events for myapp-vpc in us-east-1', 'stack_master events us-east-1 myapp-vpc'
|
70
|
+
c.option '--number Integer', Integer, 'Number of recent events to show'
|
71
|
+
c.option '--all', 'Show all events'
|
72
|
+
c.option '--tail', 'Tail events'
|
73
|
+
c.action do |args, options|
|
74
|
+
execute_stack_command(StackMaster::Commands::Events, args, options)
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
command :resources do |c|
|
79
|
+
c.syntax = 'stack_master resources [region] [stack_name]'
|
80
|
+
c.summary = "Shows stack resources"
|
81
|
+
c.description = "Shows stack resources"
|
82
|
+
c.action do |args, options|
|
83
|
+
execute_stack_command(StackMaster::Commands::Resources, args, options)
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
command :list do |c|
|
88
|
+
c.syntax = 'stack_master list'
|
89
|
+
c.summary = 'List stack definitions'
|
90
|
+
c.description = 'List stack definitions'
|
91
|
+
c.action do |args, options|
|
92
|
+
say "Invalid arguments." if args.size > 0
|
93
|
+
config = load_config(options.config)
|
94
|
+
StackMaster::Commands::ListStacks.perform(config)
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
command :validate do |c|
|
99
|
+
c.syntax = 'stack_master validate [region_or_alias] [stack_name]'
|
100
|
+
c.summary = 'Validate a template'
|
101
|
+
c.description = 'Validate a template'
|
102
|
+
c.example 'validate a stack named myapp-vpc in us-east-1', 'stack_master validate us-east-1 myapp-vpc'
|
103
|
+
c.action do |args, options|
|
104
|
+
execute_stack_command(StackMaster::Commands::Validate, args, options)
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
command :status do |c|
|
109
|
+
c.syntax = 'stack_master status'
|
110
|
+
c.summary = 'Check the current status stacks.'
|
111
|
+
c.description = 'Checks the status of all stacks defined in the stack_master.yml file. Warning this operation can be somewhat slow.'
|
112
|
+
c.example 'description', 'Check the status of all stack definitions'
|
113
|
+
c.action do |args, options|
|
114
|
+
say "Invalid arguments. stack_master status" and return unless args.size == 0
|
115
|
+
config = load_config(options.config)
|
116
|
+
StackMaster::Commands::Status.perform(config)
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
command :delete do |c|
|
121
|
+
c.syntax = 'stack_master delete [region] [stack_name]'
|
122
|
+
c.summary = 'Delete an existing stack'
|
123
|
+
c.description = 'Deletes a stack. The stack does not necessarily have to appear in the stack_master.yml file.'
|
124
|
+
c.example 'description', 'Delete a stack'
|
125
|
+
c.action do |args, options|
|
126
|
+
unless args.size == 2
|
127
|
+
say "Invalid arguments. stack_master delete [region] [stack_name]"
|
128
|
+
return
|
129
|
+
end
|
130
|
+
StackMaster.cloud_formation_driver.set_region(args[0])
|
131
|
+
StackMaster::Commands::Delete.perform(*args)
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
run!
|
136
|
+
end
|
137
|
+
|
138
|
+
def load_config(file)
|
139
|
+
stack_file = file || 'stack_master.yml'
|
140
|
+
StackMaster::Config.load!(stack_file)
|
141
|
+
rescue Errno::ENOENT => e
|
142
|
+
say "Failed to load config file #{stack_file}"
|
143
|
+
exit 1
|
144
|
+
end
|
145
|
+
|
146
|
+
def execute_stack_command(command, args, options)
|
147
|
+
unless args.size == 2
|
148
|
+
say "Invalid arguments. stack_master #{command.name.split('::').last.downcase} [region] [stack_name]"
|
149
|
+
return
|
150
|
+
end
|
151
|
+
config = load_config(options.config)
|
152
|
+
aliased_region, stack_name = args
|
153
|
+
region = Utils.underscore_to_hyphen(config.unalias_region(aliased_region))
|
154
|
+
stack_name = Utils.underscore_to_hyphen(stack_name)
|
155
|
+
StackMaster.cloud_formation_driver.set_region(region)
|
156
|
+
stack_definition ||= config.find_stack(region, stack_name)
|
157
|
+
if stack_definition.nil?
|
158
|
+
say "Could not find stack definition #{stack_name} in region #{region}"
|
159
|
+
return
|
160
|
+
end
|
161
|
+
command.perform(config, stack_definition, options)
|
162
|
+
end
|
163
|
+
end
|
164
|
+
end
|