moonshot 1.1.0.beta4 → 2.0.0.beta1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: bcd7bf169cbf27f74b4e6e4f16c59905fb8ed42c
4
- data.tar.gz: 5ba58bf877dbbc8e339ef7ff0241633fa1ab5fc2
3
+ metadata.gz: 5d2a30d2ed3a9a3f146a0bcf4972f0bfc9baff41
4
+ data.tar.gz: 0087b7d90297d013cffd9b787f88b720dc357212
5
5
  SHA512:
6
- metadata.gz: 46ed5758422fcad2d667c00936c776fb98f9215e4adfee08595a209bba25101db5414cc0dbcc9b074df1be8693f1ac15abdbb628e59cb1ec8c88b4513f1f7fae
7
- data.tar.gz: 1ba2463d5e468c8564d6c07b75b736d4ff69d3454f7ec5a2a260ffcd3f446e83305576e95d8d127c39d6a7a3dc42c21e74dd4e0a21fb71e1c4397422898a6a8f
6
+ metadata.gz: 6c1e1938bd414ec74f03185c824cf45e4c3f101b7b4acbaabbec46d71f17bf018b56600201eb1445c6b8b9c14c9c81223819c428a4667f4f67e69a90ddde5ba2
7
+ data.tar.gz: c7262c61bd51cf6febe8f31cee9a8ef64831580aeaacba2b883725b5f36d38389db5337d456ba693c03249c1f24d68df3c29ab9d47cb088930793dd23aa9cfed
@@ -16,7 +16,8 @@ module Moonshot
16
16
  parser = build_parser(handler)
17
17
  parser.parse!
18
18
 
19
- unless @args.size == handler.method(:execute).arity
19
+ req_arguments = handler.method(:execute).parameters.select { |arg| arg[0] == :req }
20
+ if ARGV.size < req_arguments.size
20
21
  warn handler.parser.help
21
22
  raise "Invalid command line for '#{@command}'."
22
23
  end
@@ -307,9 +307,13 @@ class Moonshot::DeploymentMechanism::CodeDeploy # rubocop:disable ClassLength
307
307
  inst_summary.lifecycle_events.each do |event|
308
308
  next unless event.status == 'Failed'
309
309
 
310
- ilog.error(event.diagnostics.message)
311
- event.diagnostics.log_tail.each_line do |line|
312
- ilog.error(line)
310
+ if event.diagnostics.nil?
311
+ ilog.error('Lifecycle event chain is not available.')
312
+ else
313
+ ilog.error(event.diagnostics.message)
314
+ event.diagnostics.log_tail.each_line do |line|
315
+ ilog.error(line)
316
+ end
313
317
  end
314
318
  end
315
319
  end
@@ -1,23 +1,24 @@
1
1
  require 'rubygems/package'
2
2
  require 'zlib'
3
+ require 'yaml'
3
4
 
4
5
  module Moonshot
5
6
  module Plugins
6
7
  # Moonshot plugin class for deflating and uploading files on given hooks
7
- class Backup
8
+ class Backup # rubocop:disable Metrics/ClassLength
8
9
  include Moonshot::CredsHelper
9
10
 
10
11
  attr_accessor :bucket,
11
12
  :buckets,
12
13
  :files,
13
14
  :hooks,
14
- :target_name
15
+ :target_name,
16
+ :backup_parameters,
17
+ :backup_template
15
18
 
16
19
  def initialize
17
20
  yield self if block_given?
18
- raise ArgumentError \
19
- if @files.nil? || @files.empty? || @hooks.nil? || !(@bucket.nil? ^ @buckets.nil?)
20
-
21
+ validate_configuration
21
22
  @target_name ||= '%{app_name}_%{timestamp}_%{user}.tar.gz'
22
23
  end
23
24
 
@@ -29,10 +30,8 @@ module Moonshot
29
30
  raise ArgumentError if bucket.nil? || bucket.empty?
30
31
  Moonshot::Plugins::Backup.new do |b|
31
32
  b.bucket = bucket
32
- b.files = [
33
- 'cloud_formation/%{app_name}.json',
34
- 'cloud_formation/parameters/%{stack_name}.yml'
35
- ]
33
+ b.backup_parameters = true
34
+ b.backup_template = true
36
35
  b.hooks = [:post_create, :post_update]
37
36
  end
38
37
  end
@@ -44,10 +43,11 @@ module Moonshot
44
43
  def backup(resources)
45
44
  raise ArgumentError if resources.nil?
46
45
 
47
- @app_name = resources.stack.app_name
46
+ @app_name = resources.controller.config.app_name
48
47
  @stack_name = resources.stack.name
49
48
  @target_name = render(@target_name)
50
49
  @target_bucket = define_bucket
50
+ @parameters = resources.stack.parameters
51
51
 
52
52
  return if @target_bucket.nil?
53
53
 
@@ -58,7 +58,7 @@ module Moonshot
58
58
  upload(zip_out)
59
59
 
60
60
  s.success("#{log_message} succeeded.")
61
- rescue StandardError => e
61
+ rescue => e
62
62
  s.failure("#{log_message} failed: #{e}")
63
63
  ensure
64
64
  tar_out.close unless tar_out.nil?
@@ -90,18 +90,59 @@ module Moonshot
90
90
  def tar(target_files)
91
91
  tar_stream = StringIO.new
92
92
  Gem::Package::TarWriter.new(tar_stream) do |writer|
93
- target_files.each do |file|
94
- file = render(file)
95
-
96
- writer.add_file(File.basename(file), 0644) do |io|
97
- File.open(file, 'r') { |f| io.write(f.read) }
93
+ # adding user files
94
+ unless target_files.nil? || target_files.empty?
95
+ target_files.each do |file|
96
+ file = render(file)
97
+ add_file_to_tar(writer, file)
98
98
  end
99
99
  end
100
+
101
+ # adding parameters
102
+ if @backup_parameters
103
+ add_str_to_tar(
104
+ writer,
105
+ render('%{stack_name}-parameters.yml'),
106
+ @parameters
107
+ )
108
+ end
109
+
110
+ # adding template file
111
+ if @backup_template
112
+ template_file_path = render('cloud_formation/%{app_name}.json')
113
+ add_file_to_tar(writer, template_file_path)
114
+ end
100
115
  end
101
116
  tar_stream.seek(0)
102
117
  tar_stream
103
118
  end
104
119
 
120
+ # Helper method to add a file to an inmemory tar archive.
121
+ #
122
+ # @param writer [TarWriter]
123
+ # @param file_name [String]
124
+ def add_file_to_tar(writer, file_name)
125
+ writer.add_file(File.basename(file_name), 0644) do |io|
126
+ begin
127
+ File.open(file_name, 'r') { |f| io.write(f.read) }
128
+ rescue Errno::ENOENT
129
+ warn "'#{file_name}' was not found."
130
+ end
131
+ end
132
+ end
133
+
134
+ # Helper method to add a file based on an input String as content
135
+ # to an inmemory tar archive.
136
+ #
137
+ # @param writer [TarWriter]
138
+ # @param target_filename [String]
139
+ # @param content [String]
140
+ def add_str_to_tar(writer, target_filename, content)
141
+ writer.add_file(File.basename(target_filename), 0644) do |io|
142
+ io.write(content.to_yaml)
143
+ end
144
+ end
145
+
105
146
  # Create a zip archive in memory, returning the IO object pointing at the
106
147
  # beginning of the zipfile.
107
148
  #
@@ -168,6 +209,38 @@ module Moonshot
168
209
  def bucket_by_account(account)
169
210
  @buckets[account]
170
211
  end
212
+
213
+ def validate_configuration
214
+ validate_buckets
215
+ validate_redundant_configuration
216
+ validate_targets
217
+ validate_hooks
218
+ end
219
+
220
+ def validate_buckets
221
+ raise ArgumentError, 'You must specify a target bucket.' \
222
+ if (@bucket.nil? || @bucket.empty?) \
223
+ && (@buckets.nil? || @buckets.empty?)
224
+ end
225
+
226
+ def validate_redundant_configuration
227
+ raise ArgumentError, 'You can not specify both `bucket` and `buckets`.' \
228
+ if @bucket && @buckets
229
+ end
230
+
231
+ def validate_targets
232
+ raise ArgumentError, 'You must specify files to back up.' \
233
+ if (@files.nil? || @files.empty?) \
234
+ && (!@backup_parameters && !@backup_template)
235
+ end
236
+
237
+ def validate_hooks
238
+ raise ArgumentError, 'You must specify a hook / hooks to run the backup on.' \
239
+ if hooks.nil? || hooks.empty?
240
+
241
+ raise ArgumentError, '`pre_create` and `post_delete` hooks are not supported.' \
242
+ if hooks.include?(:pre_create) || hooks.include?(:post_delete)
243
+ end
171
244
  end
172
245
  end
173
246
  end
@@ -20,92 +20,98 @@
20
20
  # c.parameter_sources['KMSKey1'] = Moonshot::AlwaysUseDefaultSource.new
21
21
  # end
22
22
  module Moonshot
23
- class EncryptedParameters
24
- # @param [String] kms_key_parameter_name
25
- # The parameter name to store the KMS Key ARN as.
26
- # @param [Array<String>] parameters
27
- # Names of parameters to encrypt, if they are not already set.
28
- def initialize(kms_key_parameter_name, parameters)
29
- @kms_key_parameter_name = kms_key_parameter_name
30
- @parameters = parameters
31
- @delete_key = true
32
- end
23
+ module Plugins
24
+ class EncryptedParameters
25
+ # @param [String] kms_key_parameter_name
26
+ # The parameter name to store the KMS Key ARN as.
27
+ # @param [Array<String>] parameters
28
+ # Names of parameters to encrypt, if they are not already set.
29
+ def initialize(kms_key_parameter_name, parameters)
30
+ @kms_key_parameter_name = kms_key_parameter_name
31
+ @parameters = parameters
32
+ @delete_key = true
33
+ end
33
34
 
34
- def pre_create(res)
35
- @ilog = res.ilog
35
+ def pre_create(res)
36
+ @ilog = res.ilog
36
37
 
37
- key_arn = find_or_create_kms_key
38
- pe = ParameterEncrypter.new(key_arn)
38
+ key_arn = find_or_create_kms_key
39
+ pe = ParameterEncrypter.new(key_arn)
39
40
 
40
- @parameters.each do |parameter_name|
41
- sp = Moonshot.config.parameters[parameter_name]
42
- raise "No such parameter #{parameter_name}" unless sp
41
+ @parameters.each do |parameter_name|
42
+ sp = Moonshot.config.parameters[parameter_name]
43
+ raise "No such parameter #{parameter_name}" unless sp
43
44
 
44
- @ilog.start_threaded "Handling encrypted parameter #{parameter_name.blue}..." do |s|
45
- if sp.use_previous?
46
- # TODO: Remove this and the one below when the upstream race is fixed.
47
- # See https://github.com/askreet/interactive-logger/issues/7
48
- sleep 0.05
49
- s.success "Using previous encrypted value for #{parameter_name.blue}."
50
- elsif !sp.set? && !sp.default?
51
- # If the parameter isn't set, we can't encrypt it. Doing
52
- # nothing means we will give the user a friendly error message
53
- # about unset parameters when the controller resumes.
54
- sleep 0.05
55
- s.failure "No value to encrypt for #{parameter_name.blue}!"
56
- else
57
- s.continue "Encrypting new value for parameter #{parameter_name.blue}..."
58
- Moonshot.config.parameters[sp.name].set(pe.encrypt(sp.value))
59
- s.success "Encrypted new value for parameter #{parameter_name.blue}!"
45
+ @ilog.start_threaded "Handling encrypted parameter #{parameter_name.blue}..." do |s|
46
+ if sp.use_previous?
47
+ # TODO: Remove this and the one below when the upstream race is fixed.
48
+ # See https://github.com/askreet/interactive-logger/issues/7
49
+ sleep 0.05
50
+ s.success "Using previous encrypted value for #{parameter_name.blue}."
51
+ elsif !sp.set? && !sp.default?
52
+ # If the parameter isn't set, we can't encrypt it. Doing
53
+ # nothing means we will give the user a friendly error message
54
+ # about unset parameters when the controller resumes.
55
+ sleep 0.05
56
+ s.failure "No value to encrypt for #{parameter_name.blue}!"
57
+ else
58
+ s.continue "Encrypting new value for parameter #{parameter_name.blue}..."
59
+ Moonshot.config.parameters[sp.name].set(pe.encrypt(sp.value))
60
+ s.success "Encrypted new value for parameter #{parameter_name.blue}!"
61
+ end
60
62
  end
61
63
  end
62
64
  end
63
- end
64
- alias pre_update pre_create
65
+ alias pre_update pre_create
65
66
 
66
- def post_delete(res)
67
- key_arn = Moonshot.config.parameters[@kms_key_parameter_name].value
67
+ def post_delete(res)
68
+ key_arn = Moonshot.config.parameters[@kms_key_parameter_name].value
68
69
 
69
- res.ilog.start_threaded "Cleaning up KMS Key #{@kms_key_parameter_name.blue}..." do |s|
70
- if @delete_key
71
- KmsKey.new(key_arn).delete
72
- s.success "Deleted KMS Key #{@kms_key_parameter_name.blue}!"
73
- else
74
- # TODO: See above.
75
- sleep 0.05
76
- s.success "Retained KMS Key #{@kms_key_parameter_name.blue}."
70
+ res.ilog.start_threaded "Cleaning up KMS Key #{@kms_key_parameter_name.blue}..." do |s|
71
+ if @delete_key
72
+ KmsKey.new(key_arn).delete
73
+ s.success "Deleted KMS Key #{@kms_key_parameter_name.blue}!"
74
+ else
75
+ # TODO: See above.
76
+ sleep 0.05
77
+ s.success "Retained KMS Key #{@kms_key_parameter_name.blue}."
78
+ end
77
79
  end
78
80
  end
79
- end
80
81
 
81
- def delete_cli_hook(parser)
82
- parser.on('--retain-kms-key', TrueClass, 'Do not delete the KMS Key for this environment.') do
83
- @delete_key = false
82
+ def delete_cli_hook(parser)
83
+ parser.on(
84
+ '--retain-kms-key',
85
+ TrueClass,
86
+ 'Do not delete the KMS Key for this environment.'
87
+ ) do
88
+ @delete_key = false
89
+ end
84
90
  end
85
- end
86
91
 
87
- private
92
+ private
88
93
 
89
- def find_or_create_kms_key
90
- key_arn = nil
94
+ def find_or_create_kms_key
95
+ key_arn = nil
91
96
 
92
- @ilog.start_threaded "Checking for KMS Key #{@kms_key_parameter_name}" do |s|
93
- if Moonshot.config.parameters.key?(@kms_key_parameter_name)
94
- if 'Auto' == Moonshot.config.parameters[@kms_key_parameter_name].value
95
- s.continue "Auto-generating KMS Key for #{@kms_key_parameter_name.blue}... "
96
- key_arn = KmsKey.create.arn
97
- Moonshot.config.parameters[@kms_key_parameter_name].set(key_arn)
98
- s.success "Created a new KMS Key for #{@kms_key_parameter_name.blue}!"
99
- else
100
- key_arn = KmsKey.new(Moonshot.config.parameters[@kms_key_parameter_name].value).arn
101
- s.success "Using existing KMS Key for #{@kms_key_parameter_name.blue}!"
97
+ @ilog.start_threaded "Checking for KMS Key #{@kms_key_parameter_name}" do |s|
98
+ if Moonshot.config.parameters.key?(@kms_key_parameter_name)
99
+ if 'Auto' == Moonshot.config.parameters[@kms_key_parameter_name].value
100
+ s.continue "Auto-generating KMS Key for #{@kms_key_parameter_name.blue}... "
101
+ key_arn = KmsKey.create.arn
102
+ Moonshot.config.parameters[@kms_key_parameter_name].set(key_arn)
103
+ s.success "Created a new KMS Key for #{@kms_key_parameter_name.blue}!"
104
+ else
105
+ key_arn = KmsKey.new(Moonshot.config.parameters[@kms_key_parameter_name].value).arn
106
+ s.success "Using existing KMS Key for #{@kms_key_parameter_name.blue}!"
107
+ end
102
108
  end
103
109
  end
104
- end
105
110
 
106
- raise "No such Stack Parameter #{@kms_key_parameter_name}!" unless key_arn
111
+ raise "No such Stack Parameter #{@kms_key_parameter_name}!" unless key_arn
107
112
 
108
- key_arn
113
+ key_arn
114
+ end
109
115
  end
110
116
  end
111
117
  end
@@ -1,23 +1,25 @@
1
1
  module Moonshot
2
- class EncryptedParameters
3
- # Class that manages KMS keys in AWS.
4
- class KmsKey
5
- attr_reader :arn
2
+ module Plugins
3
+ class EncryptedParameters
4
+ # Class that manages KMS keys in AWS.
5
+ class KmsKey
6
+ attr_reader :arn
6
7
 
7
- def initialize(arn)
8
- @arn = arn
9
- @kms_client = Aws::KMS::Client.new
10
- end
8
+ def initialize(arn)
9
+ @arn = arn
10
+ @kms_client = Aws::KMS::Client.new
11
+ end
11
12
 
12
- def self.create
13
- resp = Aws::KMS::Client.new.create_key
14
- arn = resp.key_metadata.arn
13
+ def self.create
14
+ resp = Aws::KMS::Client.new.create_key
15
+ arn = resp.key_metadata.arn
15
16
 
16
- new(arn)
17
- end
17
+ new(arn)
18
+ end
18
19
 
19
- def delete
20
- @kms_client.schedule_key_deletion(key_id: @arn, pending_window_in_days: 7)
20
+ def delete
21
+ @kms_client.schedule_key_deletion(key_id: @arn, pending_window_in_days: 7)
22
+ end
21
23
  end
22
24
  end
23
25
  end
@@ -1,23 +1,25 @@
1
1
  require 'base64'
2
2
  module Moonshot
3
- class EncryptedParameters
4
- # Class that can encrypt and decrypt parameters using KMS.
5
- class ParameterEncrypter
6
- # @param [String] key_arn The ARN for the KMS key.
7
- def initialize(key_arn)
8
- @kms_client = Aws::KMS::Client.new
9
- @key_arn = key_arn
10
- end
3
+ module Plugins
4
+ class EncryptedParameters
5
+ # Class that can encrypt and decrypt parameters using KMS.
6
+ class ParameterEncrypter
7
+ # @param [String] key_arn The ARN for the KMS key.
8
+ def initialize(key_arn)
9
+ @kms_client = Aws::KMS::Client.new
10
+ @key_arn = key_arn
11
+ end
11
12
 
12
- # Encrypt and base64 encode the parameter value.
13
- #
14
- # @param [String] param_value The parameter to encrypt.
15
- # @return [String] base64 encoded encrypted ciphertext.
16
- def encrypt(param_value)
17
- resp = @kms_client.encrypt(key_id: @key_arn, plaintext: param_value)
13
+ # Encrypt and base64 encode the parameter value.
14
+ #
15
+ # @param [String] param_value The parameter to encrypt.
16
+ # @return [String] base64 encoded encrypted ciphertext.
17
+ def encrypt(param_value)
18
+ resp = @kms_client.encrypt(key_id: @key_arn, plaintext: param_value)
18
19
 
19
- # Use strict here to avoid newlines which cause issues with parameters.
20
- Base64.strict_encode64(resp.ciphertext_blob)
20
+ # Use strict here to avoid newlines which cause issues with parameters.
21
+ Base64.strict_encode64(resp.ciphertext_blob)
22
+ end
21
23
  end
22
24
  end
23
25
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: moonshot
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.0.beta4
4
+ version: 2.0.0.beta1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Cloud Engineering <engineering@acquia.com>
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-01-12 00:00:00.000000000 Z
11
+ date: 2017-02-07 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: aws-sdk