cfndk 0.0.7 → 0.1.0

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 8bc91fcc47784316274ae3615941dcf15bdacd29
4
- data.tar.gz: 5bca96e74b5166f921b8d8c0a24dec0024d99f90
3
+ metadata.gz: 566120c36a4fa9b6267bdf60fa537cc542246b34
4
+ data.tar.gz: 1ba3f83d708122867135ba13bcd5fa5dab3be1a3
5
5
  SHA512:
6
- metadata.gz: 760f92e0e910445531c334e368932e6f0a96711c76bf5ffd63ff60f926bb50d6ba28ad418daf41ba5af4ac7790e1e932728038d17a2ac95cb4120d1e02abd063
7
- data.tar.gz: e58c1ab2a5a18cb27ae1a5a857ccccf095f5fc8168055ff3bd8be26e62f0a181540a85dfddca15eb6c632014637ab40062bbccdf658c338c2e5def1e404d6542
6
+ metadata.gz: 3971374374b13a9834974dc6f68221d7b42bfa9cd77d8efcfca557ad02c1c29c1644b2235fe47176c10b5ba6b351e77d9883036a2b7f45b242af657d17a31808
7
+ data.tar.gz: de54298f5cc8ca0b591709ab100c3749a036d6dab5ec80382aeaad1c66166f0fbacdaf6d2ae71fc162341035bd82e4751c1d79ee3ec85ca533a023fbda34074d
@@ -0,0 +1,68 @@
1
+ # Ruby CircleCI 2.0 configuration file
2
+ #
3
+ # Check https://circleci.com/docs/2.0/language-ruby/ for more details
4
+ #
5
+ version: 2
6
+ jobs:
7
+ test:
8
+ docker:
9
+ # specify the version you desire here
10
+ - image: circleci/ruby:2.4.1-node-browsers
11
+
12
+ # Specify service dependencies here if necessary
13
+ # CircleCI maintains a library of pre-built images
14
+ # documented at https://circleci.com/docs/2.0/circleci-images/
15
+ # - image: circleci/postgres:9.4
16
+ parallelism: 1
17
+ working_directory: ~/repo
18
+
19
+ steps:
20
+ - checkout
21
+
22
+ # Download and cache dependencies
23
+ - restore_cache:
24
+ keys:
25
+ - v1-dependencies-{{ checksum "Gemfile.lock" }}
26
+ # fallback to using the latest cache if no exact match is found
27
+ - v1-dependencies-
28
+
29
+ - run:
30
+ name: install dependencies
31
+ command: |
32
+ bundle install --jobs=4 --retry=3 --path vendor/bundle
33
+
34
+ - save_cache:
35
+ paths:
36
+ - ./vendor/bundle
37
+ key: v1-dependencies-{{ checksum "Gemfile.lock" }}
38
+
39
+ # run tests!
40
+ - run:
41
+ name: run tests
42
+ command: |
43
+ export AWS_REGION=ap-northeast-1
44
+ CFNDK_COVERAGE=1 bundle exec rspec \
45
+ --format p \
46
+ --format html \
47
+ --out /tmp/test-results/rspec.html
48
+
49
+ # collect reports
50
+ - store_test_results:
51
+ path: /tmp/test-results
52
+ - store_artifacts:
53
+ path: /tmp/test-results
54
+ destination: test-results
55
+ - store_test_results:
56
+ path: ~/repo/coverage
57
+ - store_artifacts:
58
+ path: ~/repo/coverage
59
+ destination: test-coverage
60
+ workflows:
61
+ version: 2
62
+ my_workflow:
63
+ jobs:
64
+ - HOLD-TEST:
65
+ type: approval
66
+ - test:
67
+ requires:
68
+ - HOLD-TEST
@@ -0,0 +1,9 @@
1
+ SimpleCov.merge_timeout 7200
2
+ SimpleCov.command_name "rspec_#{Process.pid.to_s}"
3
+
4
+ SimpleCov.start do
5
+ add_filter 'spec'
6
+ add_filter '.simplecov'
7
+
8
+ add_group 'Libraries', 'lib'
9
+ end
data/Gemfile CHANGED
@@ -1,4 +1,13 @@
1
1
  source 'https://rubygems.org'
2
2
 
3
- # Specify your gem's dependencies in xpub.gemspec
4
3
  gemspec
4
+
5
+ group :development, :test do
6
+ gem 'rake'
7
+ # Code Coverage
8
+ gem 'simplecov'
9
+ # Test api
10
+ gem 'rspec'
11
+ gem 'aruba'
12
+ gem 'awspec'
13
+ end
data/README.md CHANGED
@@ -6,8 +6,8 @@ This is easy operation/integration support tool for AWS CloudFormation.
6
6
 
7
7
  kumogata, SparkleFormation, CoffeeFormation など、CloudFormationのテンプレートを書かずにDSLで表現するツールには様々な物があります。
8
8
  しかし、これらのツールはサードパーティツールであるため、CloudFormationの対応への追従に不安がのこります。
9
- 本ツールは、標準のCloudFromationテンプレートの枠組みを変えずに、その利用を支援するツールとなっています。
10
- 最悪このツールが使えなくなっても僅かなコストで標準のAWS CLIを使ってオペレーションを続行することが可能です。
9
+ 本ツールは、標準のCloudFromationテンプレートの枠組みを変えずに、その利用を支援するツールをを目指しています。
10
+ 最悪の場合、このツールが使えなくなっても僅かなコストで標準のAWS CLIを使いオペレーションを続行することが可能です
11
11
 
12
12
  ## ハイライト
13
13
 
@@ -15,6 +15,7 @@ kumogata, SparkleFormation, CoffeeFormation など、CloudFormationのテンプ
15
15
  * 複数のスタックの依存関係を考慮した操作
16
16
  * CloudFormationでバージョンコントロールシステムと連動した継続的インテグレーションのための基盤対応
17
17
  * Keypairの作成/削除
18
+ * コマンド、サブコマンド、冪統性を考慮したコマンドライン体系、オプションの整理、ヘルプの追加
18
19
 
19
20
  ## インストール
20
21
 
@@ -31,7 +32,7 @@ $ cfndk init
31
32
  $ export AWS_REGION=ap-northeast-1
32
33
  $ export AWS_PROFILE=default
33
34
  $ cfndk create
34
- $ cfndk report-event
35
+ $ cfndk report
35
36
  $ cfndk destroy -f
36
37
  ```
37
38
 
@@ -52,55 +53,30 @@ $ cfndk destroy -f
52
53
 
53
54
  ## コマンド
54
55
 
55
- ```
56
- cfndk [cmd] [options]
57
- ```
58
-
59
- ### [cmd]
60
-
61
- #### ```init```
62
-
63
- カレントディレクトリにcfndk.yamlのひな形を作成します。
56
+ ### ```init```
64
57
 
65
- ```
66
- cfndk init [option]
67
- ```
68
-
69
- #### ```create```
70
-
71
- cfndk.yamlで定義されているスタックを作成します。
58
+ カレントディレクトリにcfndk.ymlのひな形を作成します。
72
59
 
73
60
  ```
74
- cfndk create [option]
61
+ cfndk init
75
62
  ```
76
63
 
77
- #### ```update```
78
-
79
- cfndk.yamlで定義されているスタックを更新します。
64
+ ### ```create```
80
65
 
81
- ```
82
- cfndk update [option]
83
- ```
84
-
85
- #### ```create-or-changeset```
66
+ cfndk.ymlで定義されているスタックを作成します。
86
67
 
87
- cfndk.yamlで定義されているスタックが存在しない場合は作成を、存在する場合はチェンジセットを作成します。
88
- チェンジセットの実行は行いません。
89
- コマンドを実行後に手動で実行する必要があります。
68
+ ```cfndk create [option]```
90
69
 
91
- ```
92
- cfndk create-or-changeset [option]
93
- ```
94
70
 
95
- #### ```destroy```
71
+ ### ```destroy```
96
72
 
97
- cfndk.yamlで定義されているスタックを削除します。
73
+ cfndk.ymlで定義されているスタックを削除します。
98
74
 
99
75
  ```
100
76
  cfndk destroy [option]
101
77
  ```
102
78
 
103
- #### ```generate-uuid```
79
+ ### ```generate-uuid```
104
80
 
105
81
  UUIDを生成して標準出力に出力します。
106
82
 
@@ -117,32 +93,12 @@ cfndk destroy
117
93
  unset CFNDK_UUID
118
94
  ```
119
95
 
120
- #### ```validate```
121
-
122
- cfndk.yamlで定義されているスタックのテンプレートをvalidationします。
123
-
124
- #### ```report-event```
125
-
126
- cfndk.yamlで定義されているスタックのイベント情報をレポートします。
127
-
128
- ```
129
- cfndk report-event [option]
130
- ```
131
-
132
- #### ```report-stack```
133
-
134
- cfndk.yamlで定義されているスタックの情報をレポートします。
135
-
136
- ```
137
- cfndk report-stack [option]
138
- ```
139
-
140
- #### ```report-stack-resource```
96
+ ### ```report```
141
97
 
142
- cfndk.yamlで定義されているスタックのリソース情報をレポートします。
98
+ cfndk.ymlで定義されているスタックについてレポートします。
143
99
 
144
100
  ```
145
- cfndk report-stack-resource [option]
101
+ cfndk report [option]
146
102
  ```
147
103
 
148
104
  ### [option]
@@ -151,33 +107,31 @@ cfndk report-stack-resource [option]
151
107
 
152
108
  実行時に詳細な情報を表示します。
153
109
 
154
- #### ```-c, --config_path cfndi.yml```
110
+ #### ```-c, --config-path=cfndk.yml```
155
111
 
156
112
  カレントディレクトリのcfndi.ymlの代わりに、ファイルを指定します。
157
113
 
158
- #### ```-p, --properties name=value```
114
+ #### ```-p, --properties=name:value```
159
115
 
160
116
  プロパティを追加します。
161
117
  cfndi.ymlのparametersのerb内で値で参照することができます。
162
118
 
163
- #### ```-a, --auto-uuid```
164
-
165
- UUIDを自動生成し使用します。
166
- UUIDが指定されるとスタック名に付加されます。
167
- またcfndi.ymlのparametersの値で参照することができます。
168
- ```-a```と```-u```は最後に指定されたものが有効になります。
169
-
170
119
  #### ```-u, --uuid uuid```
171
120
 
172
121
  指定されたUUIDを使用します。
173
122
  UUIDが指定されるとスタック名に付加されます。
174
123
  またcfndi.ymlのparametersの値で参照することができます。
175
- ```-a```と```-u```は最後に指定されたものが有効になります。
124
+ ```-u```は最後に指定されたものが有効になります。
176
125
 
177
- #### ```-s, --stack-names name1,name2```
126
+ #### ```--stack-names=name1 name2```
178
127
 
179
128
  指定されたスタック名のみを操作します。
180
129
 
130
+ #### ```--keypair-names=name1 name2```
131
+
132
+ 指定されたキーペア名のみを操作します。
133
+
134
+
181
135
  #### ```--no-color```
182
136
 
183
137
  メッセージ出力でカラーを抑制します。
@@ -191,10 +145,10 @@ UUIDが指定されるとスタック名に付加されます。
191
145
  ### ```CFNDK_UUID```
192
146
 
193
147
  この環境変数が指定されている場合、```--uuid $CFNDK_UUID```が指定されたものとして動作します。
194
- ```-a```や```-u```のほうが優先されます。
148
+ ```-u```のほうが優先されます。
195
149
 
196
150
 
197
- ## cfndk.yaml
151
+ ## cfndk.yml
198
152
 
199
153
  * example
200
154
 
@@ -280,11 +234,11 @@ UUIDを利用すると、```[Stack Original Name]-[UUID]```のような形式の
280
234
 
281
235
  #### template_file
282
236
 
283
- 必須。CloudFormationテンプレートファイルのパスをcfndk.yamlからの相対パスで指定します。
237
+ 必須。CloudFormationテンプレートファイルのパスをcfndk.ymlからの相対パスで指定します。
284
238
 
285
239
  #### parameter_input
286
240
 
287
- 必須。CloudFormationのパラメータJSONファイルをcfndk.yamlからの相対パスで指定します。
241
+ 必須。CloudFormationのパラメータJSONファイルをcfndk.ymlからの相対パスで指定します。
288
242
 
289
243
  #### parameters
290
244
 
@@ -327,7 +281,7 @@ Parameter Valueではerbの記法が利用できます。
327
281
  スタックに依存している別のスタックを指定します。
328
282
  複数指定することができます。
329
283
  dependsを指定すると、create,update,create-or-changeset,destoryのコマンドを実行する際に、依存関係に従ってスタックを処理します。
330
- dependsが循環するような指定をすることはできません。
284
+ 存在しないタスタックやdependsが循環するような指定をすることはできません。
331
285
 
332
286
  ```
333
287
  depends:
@@ -360,3 +314,16 @@ dependsが循環するような指定をすることはできません。
360
314
  * ```properties(key)```
361
315
 
362
316
  オプション```--properties```で指定したキーに対応する値を参照することができます。
317
+
318
+
319
+ ## テスト
320
+
321
+ cfndkコマンドのテストを行うことができます。
322
+ CFNDK_COVERAGE環境変数に1を設定することで、カバレッジを取ることができます。
323
+
324
+ ```
325
+ export AWS_REGION=ap-northeast-1
326
+ export AWS_PROFILE=default
327
+ export CFNDK_COVERAGE=1
328
+ bundle exec rspec
329
+ ```
data/bin/cfndk CHANGED
@@ -1,22 +1,7 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
- require 'bundler/setup'
4
-
5
- require 'rainbow/ext/string'
6
- require 'optparse'
7
- require 'fileutils'
8
- require 'pathname'
9
- require 'erb'
10
- require 'yaml'
11
- require 'json'
12
- require 'aws-sdk'
13
- require 'terminal-table'
14
- require 'securerandom'
15
- require 'logger'
16
-
17
- require 'cfndk.rb'
18
-
19
3
  $LOAD_PATH.unshift File.dirname(__FILE__) + '/../lib'
20
4
 
21
- c = CFnDK::Command.new
22
- exit c.execute
5
+ require 'cfndk'
6
+
7
+ exit CFnDK::Command.start(ARGV)
@@ -18,11 +18,16 @@ Gem::Specification.new do |spec|
18
18
  spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
19
  spec.require_paths = ['lib']
20
20
 
21
- spec.add_development_dependency 'bundler', '~> 1.7'
22
- spec.add_development_dependency 'rake', '~> 11.1.2'
21
+ spec.add_development_dependency 'bundler'
22
+ spec.add_development_dependency 'rake'
23
+ spec.add_development_dependency 'rspec'
24
+ spec.add_development_dependency 'aruba'
25
+ spec.add_development_dependency 'simplecov'
26
+ spec.add_development_dependency 'awspec'
23
27
 
24
- spec.add_dependency 'rainbow', '~> 3.0.0'
25
- spec.add_dependency 'aws-sdk', '~> 3'
26
- spec.add_dependency 'camelizable', '~> 0.0.3'
27
- spec.add_dependency 'terminal-table', '~> 1'
28
+ spec.add_dependency 'thor'
29
+ spec.add_dependency 'rainbow'
30
+ spec.add_dependency 'aws-sdk'
31
+ spec.add_dependency 'camelizable'
32
+ spec.add_dependency 'terminal-table'
28
33
  end
@@ -1,3 +1,24 @@
1
+ require 'bundler/setup'
2
+
3
+ require 'rainbow/ext/string'
4
+ require 'camelizable'
5
+ require 'fileutils'
6
+ require 'pathname'
7
+ require 'erb'
8
+ require 'yaml'
9
+ require 'json'
10
+ require 'aws-sdk'
11
+ require 'terminal-table'
12
+ require 'securerandom'
13
+ require 'logger'
14
+ require 'thor'
15
+
16
+ if ENV['CFNDK_COVERAGE']
17
+ require 'simplecov'
18
+ root = File.expand_path('../../', __FILE__)
19
+ SimpleCov.root(root)
20
+ end
21
+
1
22
  require 'cfndk/version'
2
23
  require 'cfndk/stack'
3
24
  require 'cfndk/stacks'
@@ -1,136 +1,300 @@
1
1
  module CFnDK
2
- class Command
3
- def initialize
4
- @cur_dir = Dir.getwd
5
- @option = {
6
- config_path: "#{@cur_dir}/cfndk.yml",
7
- uuid: ENV['CFNDK_UUID'] || nil,
8
- properties: {},
9
- stack_names: nil,
10
- force: false,
11
- }
12
-
13
- @opt = OptionParser.new do |o|
14
- o.version = CFnDK::VERSION
15
- o.summary_indent = ' ' * 4
16
- o.banner = "Version: #{CFnDK::VERSION} \nUsage: cfndk [cmd] [options]"
17
- o.on_head('[cmd]',
18
- ' init create config YAML file',
19
- ' create create stacks',
20
- ' update update stacks',
21
- ' create-or-changeset create stacks or create changeset',
22
- ' destroy destroy stacks',
23
- ' generate-uuid generate UUID',
24
- ' report-event report stack event',
25
- ' report-stack report stack',
26
- ' report-stack-resource report stack resource',
27
- '[enviroment variables]',
28
- " AWS_PROFILE: #{ENV['AWS_PROFILE']}",
29
- " AWS_DEFAULT_REGION: #{ENV['AWS_DEFAULT_REGION']}",
30
- " AWS_REGION: #{ENV['AWS_REGION']}",
31
- " AWS_ACCESS_KEY_ID: #{ENV['AWS_ACCESS_KEY_ID']}",
32
- " AWS_SECRET_ACCESS_KEY: #{ENV['AWS_SECRET_ACCESS_KEY']}",
33
- " AWS_SESSION_TOKEN: #{ENV['AWS_SECRET_ACCESS_KEY']}",
34
- " AWS_CONTAINER_CREDENTIALS_RELATIVE_URI: #{ENV['AWS_CONTAINER_CREDENTIALS_RELATIVE_URI']}",
35
- '[options]')
36
- o.on('-v', '--verbose', 'verbose mode') { |v| @option[:v] = v }
37
- o.on('-c', '--config_path cfndi.yml', "config path (default: #{@option[:config_path]})") { |v| @option[:config_path] = v }
38
- o.on('-p', '--properties name=value', 'properties') do |v|
39
- md = v.match(/^([a-zA-Z_]+[a-zA-Z0-9_]*)=(.*)$/)
40
- if md
41
- @option[:properties][md[0]] = md[1]
42
- else
43
- raise "invalid properties: '#{v}'" unless md
44
- end
45
- end
46
- o.on('-a', '--auto-uuid') { @option[:uuid] = SecureRandom.uuid }
47
- o.on('-u', '--uuid uuid') { |v| @option[:uuid] = v }
48
- o.on('-n', '--stack-names name1,name2') { |v| @option[:stack_names] = v.split(/\s*,\s*/) }
49
- o.on('--no-color') { |b| Rainbow.enabled = false }
50
- o.on('-f', '--force') { |b| @option[:force] = true }
51
- o.permute!(ARGV)
2
+ module SubcommandHelpReternable
3
+ module ClassMethods
4
+ def subcommand_help(cmd)
5
+ desc 'help [COMMAND]', 'Describe subcommands or one specific subcommand'
6
+ class_eval "
7
+ def help(command = nil, subcommand = true); super; return 2; end
8
+ "
52
9
  end
53
- @logger = CFnDK::Logger.new(@option)
54
10
  end
11
+ extend ClassMethods
12
+ def self.included(klass)
13
+ klass.extend ClassMethods
14
+ end
15
+ end
55
16
 
56
- def execute
57
- if ARGV.length != 1
58
- puts @opt.help
59
- return 2
60
- elsif ARGV[0] == 'generate-uuid'
61
- puts SecureRandom.uuid
17
+ module ConfigFileLoadable
18
+ private
19
+
20
+ def load_config_data(options)
21
+ raise "File does not exist. #{options[:config_path]}" unless File.file?(options[:config_path])
22
+ data = open(options[:config_path], 'r') { |f| YAML.load(f) }
23
+ return data if data
24
+ CFnDK.logger.error "File is empty. #{options[:config_path]}".color(:red)
25
+ nil
26
+ end
27
+ end
28
+
29
+ class KeyPairCommand < Thor
30
+ include SubcommandHelpReternable
31
+ include ConfigFileLoadable
32
+ class_option :verbose, type: :boolean, aliases: 'v', desc: 'More verbose output.'
33
+ class_option :color, type: :boolean, default: true, desc: 'Use colored output'
34
+ class_option :config_path, type: :string, aliases: 'c', default: "#{Dir.getwd}/cfndk.yml", desc: 'The configuration file to use'
35
+ class_option :uuid, type: :string, aliases: 'u', default: ENV['CFNDK_UUID'] || nil, desc: 'Use UUID'
36
+ class_option :keypair_names, type: :array, desc: 'Target keypair names'
37
+
38
+ desc 'create', 'Create keypair'
39
+ option :properties, type: :hash, aliases: 'p', default: {}, desc: 'Set property'
40
+ def create
41
+ CFnDK.logger.info 'create...'.color(:green)
42
+ data = load_config_data(options)
43
+
44
+ credentials = CFnDK::CredentialProviderChain.new.resolve
45
+ keypairs = CFnDK::KeyPairs.new(data, options, credentials)
46
+ keypairs.create
47
+ return 0
48
+ rescue => e
49
+ CFnDK.logger.error e.message.color(:red)
50
+ CFnDK.logger.debug e.backtrace
51
+ return 1
52
+ end
53
+
54
+ desc 'destroy', 'Destroy keypair'
55
+ option :force, type: :boolean, aliases: 'f', default: false, desc: 'Say yes to all prompts for confirmation'
56
+ def destroy
57
+ CFnDK.logger.info 'destroy...'.color(:green)
58
+ data = load_config_data(options)
59
+
60
+ credentials = CFnDK::CredentialProviderChain.new.resolve
61
+ keypairs = CFnDK::KeyPairs.new(data, options, credentials)
62
+
63
+ if options[:force] || yes?('Are you sure you want to destroy? (y/n)', :yellow)
64
+ keypairs.destroy
62
65
  return 0
63
- elsif ARGV[0] == 'init'
64
- if File.file?(@option[:config_path])
65
- @logger.error "File exist. #{@option[:config_path]}".color(:red)
66
- return 1
67
- end
68
- @logger.info 'init...'.color(:green)
69
- FileUtils.cp_r(Dir.glob(File.dirname(__FILE__) + '/../../skel/*'), './')
70
- @logger.info "create #{@option[:config_path]}".color(:green)
66
+ else
67
+ CFnDK.logger.info 'destroy command was canceled'.color(:green)
68
+ return 2
69
+ end
70
+ rescue => e
71
+ CFnDK.logger.error e.message.color(:red)
72
+ CFnDK.logger.debug e.backtrace
73
+ return 1
74
+ end
75
+ end
76
+
77
+ class StackCommand < Thor
78
+ include SubcommandHelpReternable
79
+ include ConfigFileLoadable
80
+
81
+ class_option :verbose, type: :boolean, aliases: 'v', desc: 'More verbose output.'
82
+ class_option :color, type: :boolean, default: true, desc: 'Use colored output'
83
+ class_option :config_path, type: :string, aliases: 'c', default: "#{Dir.getwd}/cfndk.yml", desc: 'The configuration file to use'
84
+ class_option :stack_names, type: :array, desc: 'Target stack names'
85
+
86
+ desc 'create', 'Create stack'
87
+ option :uuid, type: :string, aliases: 'u', default: ENV['CFNDK_UUID'] || nil, desc: 'Use UUID'
88
+ option :properties, type: :hash, aliases: 'p', default: {}, desc: 'Set property'
89
+ def create
90
+ CFnDK.logger.info 'create...'.color(:green)
91
+ data = load_config_data(options)
92
+
93
+ credentials = CFnDK::CredentialProviderChain.new.resolve
94
+ stacks = CFnDK::Stacks.new(data, options, credentials)
95
+ stacks.validate
96
+ stacks.create
97
+ return 0
98
+ rescue => e
99
+ CFnDK.logger.error e.message.color(:red)
100
+ CFnDK.logger.debug e.backtrace
101
+ return 1
102
+ end
103
+
104
+ desc 'update', 'Update stack'
105
+ option :uuid, type: :string, aliases: 'u', default: ENV['CFNDK_UUID'] || nil, desc: 'Use UUID'
106
+ option :properties, type: :hash, aliases: 'p', default: {}, desc: 'Set property'
107
+ def update
108
+ CFnDK.logger.info 'update...'.color(:green)
109
+ data = load_config_data(options)
110
+
111
+ credentials = CFnDK::CredentialProviderChain.new.resolve
112
+ stacks = CFnDK::Stacks.new(data, options, credentials)
113
+ stacks.validate
114
+ stacks.update
115
+ return 0
116
+ rescue => e
117
+ CFnDK.logger.error e.message.color(:red)
118
+ CFnDK.logger.debug e.backtrace
119
+ return 1
120
+ end
121
+
122
+ desc 'destroy', 'Destroy stack'
123
+ option :force, type: :boolean, aliases: 'f', default: false, desc: 'Say yes to all prompts for confirmation'
124
+ option :uuid, type: :string, aliases: 'u', default: ENV['CFNDK_UUID'] || nil, desc: 'Use UUID'
125
+ def destroy
126
+ CFnDK.logger.info 'destroy...'.color(:green)
127
+ data = load_config_data(options)
128
+
129
+ credentials = CFnDK::CredentialProviderChain.new.resolve
130
+ stacks = CFnDK::Stacks.new(data, options, credentials)
131
+
132
+ if options[:force] || yes?('Are you sure you want to destroy? (y/n)', :yellow)
133
+ stacks.destroy
71
134
  return 0
135
+ else
136
+ CFnDK.logger.info 'destroy command was canceled'.color(:green)
137
+ return 2
72
138
  end
139
+ rescue => e
140
+ CFnDK.logger.error e.message.color(:red)
141
+ CFnDK.logger.debug e.backtrace
142
+ return 1
143
+ end
144
+
145
+ desc 'validate', 'Validate stack'
146
+ def validate
147
+ CFnDK.logger.info 'validate...'.color(:green)
148
+ data = load_config_data(options)
149
+ credentials = CFnDK::CredentialProviderChain.new.resolve
150
+ stacks = CFnDK::Stacks.new(data, options, credentials)
151
+ stacks.validate
152
+ return 0
153
+ rescue => e
154
+ CFnDK.logger.error e.message.color(:red)
155
+ CFnDK.logger.debug e.backtrace
156
+ return 1
157
+ end
158
+
159
+ desc 'report', 'Report stack'
160
+ option :uuid, type: :string, aliases: 'u', default: ENV['CFNDK_UUID'] || nil, desc: 'Use UUID'
161
+ def report
162
+ CFnDK.logger.info 'report...'.color(:green)
163
+ data = load_config_data(options)
164
+ credentials = CFnDK::CredentialProviderChain.new.resolve
165
+ stacks = CFnDK::Stacks.new(data, options, credentials)
166
+ stacks.report
167
+ return 0
168
+ rescue => e
169
+ CFnDK.logger.error e.message.color(:red)
170
+ CFnDK.logger.debug e.backtrace
171
+ return 1
172
+ end
173
+ end
174
+
175
+ class Command < Thor
176
+ include Thor::Actions
177
+ include ConfigFileLoadable
178
+ class << self
179
+ def exit_on_failure?
180
+ true
181
+ end
182
+ end
183
+
184
+ def help(command = nil, subcommand = false)
185
+ super(command, subcommand)
186
+ 2
187
+ end
188
+
189
+ class_option :verbose, type: :boolean, aliases: 'v', desc: 'More verbose output.'
190
+ class_option :color, type: :boolean, default: true, desc: 'Use colored output'
191
+
192
+ desc 'generate-uuid', 'Print UUID'
193
+ def generate_uuid
194
+ puts SecureRandom.uuid
195
+ 0
196
+ end
197
+
198
+ desc 'version', 'Print version'
199
+ def version
200
+ puts CFnDK::VERSION
201
+ 0
202
+ end
73
203
 
74
- unless File.file?(@option[:config_path])
75
- @logger.error "File does not exist. #{@option[:config_path]}".color(:red)
204
+ desc 'init', 'Craete sample cfndk.yml & CloudFormation yaml & json files.'
205
+ def init
206
+ config_path = "#{Dir.getwd}/cfndk.yml"
207
+ if File.file?(config_path)
208
+ CFnDK.logger.error "File exist. #{config_path}".color(:red)
76
209
  return 1
77
210
  end
211
+ CFnDK.logger.info 'init...'.color(:green)
212
+ FileUtils.cp_r(Dir.glob(File.dirname(__FILE__) + '/../../skel/*'), './')
213
+ CFnDK.logger.info "create #{config_path}".color(:green)
214
+ end
215
+
216
+ desc 'create', 'Create keypair & stack'
217
+ option :config_path, type: :string, aliases: 'c', default: "#{Dir.getwd}/cfndk.yml", desc: 'The configuration file to use'
218
+ option :uuid, type: :string, aliases: 'u', default: ENV['CFNDK_UUID'] || nil, desc: 'Use UUID'
219
+ option :properties, type: :hash, aliases: 'p', default: {}, desc: 'Set property'
220
+ option :stack_names, type: :array, desc: 'Target stack names'
221
+ option :keypair_names, type: :array, desc: 'Target keypair names'
222
+ def create
223
+ CFnDK.logger.info 'create...'.color(:green)
224
+ data = load_config_data(options)
225
+
226
+ credentials = CFnDK::CredentialProviderChain.new.resolve
227
+ stacks = CFnDK::Stacks.new(data, options, credentials)
228
+ keypairs = CFnDK::KeyPairs.new(data, options, credentials)
229
+
230
+ stacks.validate
231
+ keypairs.create
232
+ stacks.create
233
+ return 0
234
+ rescue => e
235
+ CFnDK.logger.error e.message.color(:red)
236
+ CFnDK.logger.debug e.backtrace
237
+ return 1
238
+ end
239
+
240
+ desc 'destroy', 'Destroy keypair & stack'
241
+ option :config_path, type: :string, aliases: 'c', default: "#{Dir.getwd}/cfndk.yml", desc: 'The configuration file to use'
242
+ option :force, type: :boolean, aliases: 'f', default: false, desc: 'Say yes to all prompts for confirmation'
243
+ option :uuid, type: :string, aliases: 'u', default: ENV['CFNDK_UUID'] || nil, desc: 'Use UUID'
244
+ option :stack_names, type: :array, desc: 'Target stack names'
245
+ option :keypair_names, type: :array, desc: 'Target keypair names'
246
+ def destroy
247
+ CFnDK.logger.info 'destroy...'.color(:green)
248
+ data = load_config_data(options)
78
249
 
79
- data = open(@option[:config_path], 'r') { |f| YAML.load(f) } if File.file?(@option[:config_path])
80
250
  credentials = CFnDK::CredentialProviderChain.new.resolve
81
- stacks = CFnDK::Stacks.new(data, @option, credentials)
82
- keypairs = CFnDK::KeyPairs.new(data, @option, credentials)
83
-
84
- if ARGV[0] == 'create'
85
- @logger.info 'create...'.color(:green)
86
- stacks.validate
87
- keypairs.create
88
- stacks.create
89
- elsif ARGV[0] == 'update'
90
- @logger.info 'update...'.color(:green)
91
- stacks.validate
92
- stacks.update
93
- elsif ARGV[0] == 'create-or-changeset'
94
- @logger.info 'create or changeset...'.color(:green)
95
- stacks.validate
96
- stacks.create_or_changeset
97
- elsif ARGV[0] == 'destroy'
98
- @logger.info 'destroy...'.color(:green)
99
- if destroy?
100
- stacks.destroy
101
- keypairs.destroy
102
- end
103
- elsif ARGV[0] == 'validate'
104
- @logger.info 'validate...'.color(:green)
105
- stacks.validate
106
- elsif ARGV[0] == 'report-event'
107
- @logger.info 'report event...'.color(:green)
108
- stacks.report_event
109
- elsif ARGV[0] == 'report-stack'
110
- @logger.info 'report stack...'.color(:green)
111
- stacks.report_stack
112
- elsif ARGV[0] == 'report-stack-resource'
113
- @logger.info 'report stack resource...'.color(:green)
114
- stacks.report_stack_resource
251
+ stacks = CFnDK::Stacks.new(data, options, credentials)
252
+ keypairs = CFnDK::KeyPairs.new(data, options, credentials)
253
+
254
+ if options[:force] || yes?('Are you sure you want to destroy? (y/n)', :yellow)
255
+ stacks.destroy
256
+ keypairs.destroy
257
+ return 0
115
258
  else
116
- puts @opt.help
259
+ CFnDK.logger.info 'destroy command was canceled'.color(:green)
117
260
  return 2
118
261
  end
119
- 0
262
+ rescue => e
263
+ CFnDK.logger.error "(#{e.class}) #{e.message}".color(:red)
264
+ CFnDK.logger.debug e.backtrace
265
+ return 1
120
266
  end
121
267
 
122
- def destroy?
123
- return true if @option[:force]
124
- loop do
125
- print 'destroy? [yes|no]:'
126
- res = STDIN.gets
127
- case res
128
- when /^yes/
129
- return true
130
- when /^no/, /^$/
131
- return false
132
- end
268
+ desc 'report', 'Report stack'
269
+ option :config_path, type: :string, aliases: 'c', default: "#{Dir.getwd}/cfndk.yml", desc: 'The configuration file to use'
270
+ option :uuid, type: :string, aliases: 'u', default: ENV['CFNDK_UUID'] || nil, desc: 'Use UUID'
271
+ option :stack_names, type: :array, desc: 'Target stack names'
272
+ def report
273
+ CFnDK.logger.info 'report...'.color(:green)
274
+
275
+ data = load_config_data(options)
276
+
277
+ credentials = CFnDK::CredentialProviderChain.new.resolve
278
+ stacks = CFnDK::Stacks.new(data, options, credentials)
279
+ stacks.report
280
+ return 0
281
+ rescue => e
282
+ CFnDK.logger.error e.message.color(:red)
283
+ CFnDK.logger.debug e.backtrace
284
+ return 1
285
+ end
286
+
287
+ no_commands do
288
+ def invoke_command(command, *args)
289
+ CFnDK.logger = CFnDKLogger.new(options)
290
+ Rainbow.enabled = false unless options[:color]
291
+ super
133
292
  end
134
293
  end
294
+
295
+ desc 'keypair SUBCOMMAND ...ARGS', 'Manage keypair'
296
+ subcommand 'keypair', KeyPairCommand
297
+ desc 'stack SUBCOMMAND ...ARGS', 'Manage stack'
298
+ subcommand 'stack', StackCommand
135
299
  end
136
300
  end