moonshot 1.1.0.beta4 → 2.0.0.beta1

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: 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