openstax_aws 1.1.0 → 1.4.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 +4 -4
- data/.github/workflows/tests.yml +31 -0
- data/CHANGELOG.md +12 -7
- data/README.md +1 -1
- data/lib/openstax/aws/deployment_base.rb +39 -2
- data/lib/openstax/aws/distribution.rb +2 -1
- data/lib/openstax/aws/git_helper.rb +14 -5
- data/lib/openstax/aws/msk_cluster.rb +4 -0
- data/lib/openstax/aws/packer_1_2_5.rb +1 -1
- data/lib/openstax/aws/packer_1_4_1.rb +60 -15
- data/lib/openstax/aws/sam_stack.rb +6 -2
- data/lib/openstax/aws/secrets.rb +1 -2
- data/lib/openstax/aws/secrets_factory.rb +1 -0
- data/lib/openstax/aws/secrets_specification.rb +3 -2
- data/lib/openstax/aws/stack_factory.rb +6 -2
- data/lib/openstax/aws/template.rb +14 -2
- data/lib/openstax/aws/version.rb +1 -1
- metadata +6 -6
- data/.travis.yml +0 -12
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 75f65f32cd2e572d1e83f624977186c7aee220c6d51924333fa08af2255543ad
|
4
|
+
data.tar.gz: bf3969a29e8fb4ff94b54bbd9685581cdff28f9c160f3ebe0fa26b92f4875575
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 76287d75f76a51cbeb635e6013f5e896174537fcba6352f5febba64c562c3cb857f82aa2a03f71af9583c5db3e8527bf0298e4e2759db9ac658b7a13c0fa6c14
|
7
|
+
data.tar.gz: f86924695c16ce1b3729e9a405e36603761477aa4c7af798ea50bd5faeffcaf18d3caca056db5f8d72127c8bf9c7edfd464d46a7e109f8597d1437ecffb2788f
|
@@ -0,0 +1,31 @@
|
|
1
|
+
name: Tests
|
2
|
+
|
3
|
+
on:
|
4
|
+
pull_request:
|
5
|
+
push:
|
6
|
+
branches:
|
7
|
+
- master
|
8
|
+
|
9
|
+
jobs:
|
10
|
+
tests:
|
11
|
+
timeout-minutes: 10
|
12
|
+
runs-on: ubuntu-18.04
|
13
|
+
|
14
|
+
steps:
|
15
|
+
- uses: actions/checkout@v2
|
16
|
+
- uses: actions/setup-ruby@v1
|
17
|
+
with:
|
18
|
+
ruby-version: 2.6
|
19
|
+
- uses: actions/cache@v2
|
20
|
+
with:
|
21
|
+
path: vendor/bundle
|
22
|
+
key: ${{ runner.os }}-gems-pr-${{ hashFiles('**/Gemfile.lock') }}
|
23
|
+
restore-keys: |
|
24
|
+
${{ runner.os }}-gems-pr-
|
25
|
+
- name: Test
|
26
|
+
run: |
|
27
|
+
gem install bundler --force --no-document --version 2.1.4
|
28
|
+
bundle config path vendor/bundle
|
29
|
+
bundle config jobs 2
|
30
|
+
bundle install
|
31
|
+
bundle exec rspec
|
data/CHANGELOG.md
CHANGED
@@ -6,16 +6,21 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
6
6
|
|
7
7
|
## [Unreleased]
|
8
8
|
|
9
|
-
## [1.
|
10
|
-
|
11
|
-
Fixed Packer debug mode by reading and printing each character from Packer instead of each line.
|
9
|
+
## [1.2.0] - 2021-01-12
|
12
10
|
|
13
|
-
|
11
|
+
- Added additional method to MskCluster resource, to return sorted list of bootstrap brokers
|
12
|
+
- Replaced Travis with GH Actions
|
13
|
+
- All secret types now default to SecureString, not just the RSA keys
|
14
|
+
- Added CloudFormation ERB templates (cfn files that end in .yml.erb)
|
15
|
+
- Gracefully handle interrupts while running Packer and return Packer's exit status from the call
|
14
16
|
|
15
|
-
|
17
|
+
## [1.1.0] - 2020-10-20
|
16
18
|
|
17
|
-
|
19
|
+
- Fixed Packer debug mode by reading and printing each character from Packer instead of each line.
|
20
|
+
- Restricted AMI search to images owned by the same account to prevent a potential security flaw.
|
21
|
+
- Gitignored Gemfile.lock.
|
22
|
+
- Removed development dependency on bundler 1.
|
18
23
|
|
19
24
|
## [1.0.0] - 2020-10-03
|
20
25
|
|
21
|
-
First official version.
|
26
|
+
- First official version.
|
data/README.md
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# aws-ruby
|
2
2
|
|
3
|
-
[](https://github.com/openstax/aws-ruby/actions?query=workflow:Tests)
|
4
4
|
|
5
5
|
The `openstax_aws` gem helps you deploy your applications to AWS using CloudFormation. It provides a layer on top of
|
6
6
|
the AWS SDKs to help coordinate common deployment steps and configurations.
|
@@ -260,6 +260,32 @@ module OpenStax::Aws
|
|
260
260
|
nil # can be overridden by the DSL
|
261
261
|
end
|
262
262
|
|
263
|
+
def failed_statuses_table
|
264
|
+
rows = []
|
265
|
+
|
266
|
+
stacks.each do |stack|
|
267
|
+
stack.status(reload: false).failed_events_since_last_user_event.each do |event|
|
268
|
+
rows.push([stack.name, event.status_text, event.status_reason])
|
269
|
+
end if stack.status.failed?
|
270
|
+
end
|
271
|
+
|
272
|
+
column_widths = [
|
273
|
+
2 + rows.reduce(0) { |result, rowdata| [result, rowdata[0].length].max },
|
274
|
+
2 + rows.reduce(0) { |result, rowdata| [result, rowdata[1].length].max },
|
275
|
+
0
|
276
|
+
]
|
277
|
+
|
278
|
+
output = []
|
279
|
+
|
280
|
+
output.push(["Stack", "Status", "Reason"].each_with_index.map { |header, index| header.ljust(column_widths[index]) }.join(''))
|
281
|
+
|
282
|
+
rows.each { |rowdata|
|
283
|
+
output.push(rowdata.each_with_index.map { |value, index| value.ljust(column_widths[index]) }.join(''))
|
284
|
+
}
|
285
|
+
|
286
|
+
output.join("\n")
|
287
|
+
end
|
288
|
+
|
263
289
|
protected
|
264
290
|
|
265
291
|
def parameter_default(parameter_name)
|
@@ -360,13 +386,24 @@ module OpenStax::Aws
|
|
360
386
|
get_image_tag(image_id: image_id, key: "sha")
|
361
387
|
end
|
362
388
|
|
363
|
-
protected
|
364
|
-
|
365
389
|
def secrets_namespace(id: 'default')
|
366
390
|
raise "Override this method in your deployment class and provide a namespace " \
|
367
391
|
"for secrets data in the AWS Parameter Store. The key there will be this namespace " \
|
368
392
|
"prefixed by the environment name and suffixed with the secret name."
|
369
393
|
end
|
370
394
|
|
395
|
+
def log_and_exit_if_failed_status
|
396
|
+
begin
|
397
|
+
yield
|
398
|
+
rescue
|
399
|
+
if status.failed?
|
400
|
+
logger.fatal("The following errors have occurred: \n#{failed_statuses_table}")
|
401
|
+
exit(1)
|
402
|
+
else
|
403
|
+
raise
|
404
|
+
end
|
405
|
+
end
|
406
|
+
end
|
407
|
+
|
371
408
|
end
|
372
409
|
end
|
@@ -34,7 +34,8 @@ module OpenStax::Aws
|
|
34
34
|
begin
|
35
35
|
Aws::CloudFront::Waiters::InvalidationCompleted.new(
|
36
36
|
client: client,
|
37
|
-
before_attempt: ->(*) { wait_message.say_it }
|
37
|
+
before_attempt: ->(*) { wait_message.say_it },
|
38
|
+
max_attempts: 60
|
38
39
|
).wait(
|
39
40
|
distribution_id: id,
|
40
41
|
id: invalidation_id
|
@@ -8,11 +8,20 @@ module OpenStax::Aws
|
|
8
8
|
::Git.ls_remote("https://github.com/#{org_slash_repo}")["branches"][branch][:sha]
|
9
9
|
end
|
10
10
|
|
11
|
-
def self.file_content_at_sha(org_slash_repo:, sha:, path:)
|
12
|
-
|
13
|
-
|
14
|
-
|
11
|
+
def self.file_content_at_sha(org_slash_repo:, sha:, path:, github_token: nil )
|
12
|
+
if github_token.blank?
|
13
|
+
location = "https://raw.githubusercontent.com/#{org_slash_repo}/#{sha}/#{path}"
|
14
|
+
file = URI.open(location)
|
15
|
+
file.read
|
16
|
+
else
|
17
|
+
uri = URI("https://raw.githubusercontent.com/#{org_slash_repo}/#{sha}/#{path}")
|
18
|
+
Net::HTTP.start(uri.host, uri.port, :use_ssl => uri.scheme == 'https') do |http|
|
19
|
+
request = Net::HTTP::Get.new uri.request_uri
|
20
|
+
request.basic_auth 'token', github_token
|
21
|
+
response = http.request request
|
22
|
+
response.body
|
23
|
+
end
|
24
|
+
end
|
15
25
|
end
|
16
|
-
|
17
26
|
end
|
18
27
|
end
|
@@ -41,36 +41,81 @@ module OpenStax::Aws
|
|
41
41
|
cmd = "PACKER_LOG=1 #{cmd}" if @verbose
|
42
42
|
cmd = "#{cmd} --debug" if @debug
|
43
43
|
|
44
|
-
cmd
|
44
|
+
cmd
|
45
45
|
end
|
46
46
|
|
47
47
|
def run
|
48
48
|
@logger.info("**** DRY RUN ****") if @dry_run
|
49
|
-
@logger.info("Running: #{command}")
|
49
|
+
@logger.info("Running: #{command} #{@absolute_file_path}")
|
50
50
|
|
51
51
|
if !@dry_run
|
52
52
|
@logger.info("Printing stderr for desired verbosity")
|
53
|
-
ami = ""
|
54
53
|
|
55
|
-
|
56
|
-
stdout_err.sync = true
|
54
|
+
tmpdir = nil
|
57
55
|
|
58
|
-
|
56
|
+
begin
|
57
|
+
config_path = @absolute_file_path
|
59
58
|
|
60
|
-
|
61
|
-
|
62
|
-
|
59
|
+
# Can't handle modifying HCL2 templates yet
|
60
|
+
if config_path.ends_with?('.json')
|
61
|
+
config = JSON.parse(File.read(config_path))
|
62
|
+
config['post-processors'] ||= []
|
63
|
+
manifest_config = (config['post-processors']).find do |processor|
|
64
|
+
processor['type'] == 'manifest'
|
65
|
+
end
|
63
66
|
|
64
|
-
|
67
|
+
# Configure a manifest post-processor if not already configured
|
68
|
+
if manifest_config.nil?
|
69
|
+
tmpdir = Dir.mktmpdir
|
65
70
|
|
66
|
-
|
67
|
-
ami = matchami.captures[0] if matchami
|
71
|
+
manifest_config = { 'type' => 'manifest', 'output' => "#{tmpdir}/manifest.json" }
|
68
72
|
|
69
|
-
|
73
|
+
config['post-processors'] << manifest_config
|
74
|
+
|
75
|
+
config_path = "#{tmpdir}/packer.json"
|
76
|
+
|
77
|
+
File.write(config_path, JSON.dump(config))
|
78
|
+
end
|
70
79
|
end
|
71
|
-
end
|
72
80
|
|
73
|
-
|
81
|
+
Open3.popen2e("#{command} #{config_path}") do |stdin, stdout_err, wait_thr|
|
82
|
+
begin
|
83
|
+
previous_interrupt_handler = Signal.trap 'INT' do
|
84
|
+
# Interrupt Packer
|
85
|
+
Process.kill 'INT', wait_thr.pid
|
86
|
+
|
87
|
+
# Restore previous interrupt handler so we don't interrupt Packer again
|
88
|
+
Signal.trap 'INT', previous_interrupt_handler
|
89
|
+
|
90
|
+
# Disable other code that restores previous interrupt
|
91
|
+
previous_interrupt_handler = nil
|
92
|
+
end
|
93
|
+
|
94
|
+
stdout_err.sync = true
|
95
|
+
|
96
|
+
# Send all packer output to STDERR
|
97
|
+
while char = stdout_err.getc do
|
98
|
+
STDERR.print char
|
99
|
+
end
|
100
|
+
ensure
|
101
|
+
# Restore previous interrupt unless we did so already
|
102
|
+
Signal.trap 'INT', previous_interrupt_handler unless previous_interrupt_handler.nil?
|
103
|
+
end
|
104
|
+
|
105
|
+
# Read the AMI ID from the manifest file and output it to STDOUT
|
106
|
+
unless manifest_config.nil?
|
107
|
+
manifest = File.read(manifest_config['output']) rescue nil
|
108
|
+
|
109
|
+
puts JSON.parse(manifest)['builds'].last['artifact_id'].split(':', 2).last \
|
110
|
+
unless manifest.nil?
|
111
|
+
end
|
112
|
+
|
113
|
+
# Return Packer's exit status wrapped in a Process::Status object
|
114
|
+
wait_thr.value
|
115
|
+
end
|
116
|
+
ensure
|
117
|
+
FileUtils.remove_entry(tmpdir) unless tmpdir.nil?
|
118
|
+
end
|
74
119
|
end
|
75
120
|
end
|
76
121
|
|
@@ -32,9 +32,12 @@ module OpenStax::Aws
|
|
32
32
|
dry_run: dry_run)
|
33
33
|
end
|
34
34
|
|
35
|
-
def build
|
35
|
+
def build(debug: false, env_vars: {})
|
36
36
|
# SAM doesn't have an API or SDK - we have to make calls to its CLI
|
37
|
+
env_vars_prefix = env_vars.map { |variable, value| "#{variable}=#{value}" }.join(' ')
|
37
38
|
command = "sam build -t #{absolute_template_path} -b #{build_directory}"
|
39
|
+
command += ' --debug' if debug
|
40
|
+
command = "#{env_vars_prefix} #{command}" if env_vars_prefix.present?
|
38
41
|
System.call(command, logger: logger, dry_run: dry_run)
|
39
42
|
end
|
40
43
|
|
@@ -50,7 +53,8 @@ module OpenStax::Aws
|
|
50
53
|
" --capabilities CAPABILITY_IAM" \
|
51
54
|
" --s3-bucket #{bucket_name}" \
|
52
55
|
" --s3-prefix #{name}" \
|
53
|
-
" --stack-name #{name}"
|
56
|
+
" --stack-name #{name}" \
|
57
|
+
" --region #{region}"
|
54
58
|
|
55
59
|
if params.any?
|
56
60
|
command += " --parameter-overrides #{self.class.format_hash_as_cli_stack_parameters(params)}"
|
data/lib/openstax/aws/secrets.rb
CHANGED
@@ -146,7 +146,7 @@ module OpenStax::Aws
|
|
146
146
|
|
147
147
|
def process_individual_spec_value(spec_value, substitutions)
|
148
148
|
generated = false
|
149
|
-
type = "
|
149
|
+
type = "SecureString"
|
150
150
|
|
151
151
|
value = case spec_value
|
152
152
|
when /^random\(hex,(\d+)\)$/
|
@@ -158,7 +158,6 @@ module OpenStax::Aws
|
|
158
158
|
num_characters = $1.to_i
|
159
159
|
SecureRandom.urlsafe_base64(num_characters)[0..num_characters-1]
|
160
160
|
when /^rsa\((\d+)\)$/
|
161
|
-
type = "SecureString"
|
162
161
|
generated = true
|
163
162
|
key_length = $1.to_i
|
164
163
|
OpenSSL::PKey::RSA.new(key_length).to_s
|
@@ -39,6 +39,7 @@ module OpenStax::Aws
|
|
39
39
|
org_slash_repo: attributes[:org_slash_repo],
|
40
40
|
sha: attributes[:sha],
|
41
41
|
path: attributes[:path],
|
42
|
+
github_token: attributes[:github_token],
|
42
43
|
format: attributes[:format].to_sym,
|
43
44
|
top_key: attributes[:top_key].to_sym,
|
44
45
|
preparser: attributes[:preparser]
|
@@ -13,11 +13,12 @@ module OpenStax::Aws
|
|
13
13
|
new(content: content, format: format, top_key: top_key, preparser: preparser)
|
14
14
|
end
|
15
15
|
|
16
|
-
def self.from_git(org_slash_repo:, sha:, path:, format:, top_key: nil, preparser: nil)
|
16
|
+
def self.from_git(org_slash_repo:, sha:, path:, github_token: nil, format:, top_key: nil, preparser: nil)
|
17
17
|
content = OpenStax::Aws::GitHelper.file_content_at_sha(
|
18
18
|
org_slash_repo: org_slash_repo,
|
19
19
|
sha: sha,
|
20
|
-
path: path
|
20
|
+
path: path,
|
21
|
+
github_token: github_token
|
21
22
|
)
|
22
23
|
new(content: content, format: format, top_key: top_key, preparser: preparser)
|
23
24
|
end
|
@@ -52,9 +52,13 @@ module OpenStax::Aws
|
|
52
52
|
path = File.join(base_directory, "#{@id}.yml")
|
53
53
|
|
54
54
|
if !File.file?(path)
|
55
|
-
path = File.join(base_directory, "#{@id}.
|
55
|
+
path = File.join(base_directory, "#{@id}.yml.erb")
|
56
|
+
|
56
57
|
if !File.file?(path)
|
57
|
-
|
58
|
+
path = File.join(base_directory, "#{@id}.json")
|
59
|
+
if !File.file?(path)
|
60
|
+
raise "Couldn't infer an existing template file for stack #{@id}"
|
61
|
+
end
|
58
62
|
end
|
59
63
|
end
|
60
64
|
end
|
@@ -26,8 +26,20 @@ module OpenStax::Aws
|
|
26
26
|
File.basename(absolute_file_path)
|
27
27
|
end
|
28
28
|
|
29
|
+
def extname
|
30
|
+
File.extname(absolute_file_path)
|
31
|
+
end
|
32
|
+
|
33
|
+
def erb?
|
34
|
+
extname == '.erb'
|
35
|
+
end
|
36
|
+
|
29
37
|
def body
|
30
|
-
@body
|
38
|
+
return @body unless @body.nil?
|
39
|
+
|
40
|
+
@body = File.read(absolute_file_path)
|
41
|
+
@body = ERB.new(@body).tap { |erb| erb.filename = absolute_file_path }.result if erb?
|
42
|
+
@body
|
31
43
|
end
|
32
44
|
|
33
45
|
def hash
|
@@ -88,7 +100,7 @@ module OpenStax::Aws
|
|
88
100
|
end
|
89
101
|
|
90
102
|
def is_sam?
|
91
|
-
body.match(/Transform: AWS::Serverless/).present?
|
103
|
+
body.match(/Transform: .?AWS::Serverless/).present?
|
92
104
|
end
|
93
105
|
|
94
106
|
protected
|
data/lib/openstax/aws/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: openstax_aws
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.4.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- JP Slavinsky
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2022-05-11 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: aws-sdk-autoscaling
|
@@ -273,8 +273,8 @@ executables:
|
|
273
273
|
extensions: []
|
274
274
|
extra_rdoc_files: []
|
275
275
|
files:
|
276
|
+
- ".github/workflows/tests.yml"
|
276
277
|
- ".gitignore"
|
277
|
-
- ".travis.yml"
|
278
278
|
- CHANGELOG.md
|
279
279
|
- Gemfile
|
280
280
|
- LICENSE.txt
|
@@ -327,7 +327,7 @@ licenses:
|
|
327
327
|
- MIT
|
328
328
|
metadata:
|
329
329
|
allowed_push_host: https://rubygems.org
|
330
|
-
post_install_message:
|
330
|
+
post_install_message:
|
331
331
|
rdoc_options: []
|
332
332
|
require_paths:
|
333
333
|
- lib
|
@@ -343,7 +343,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
343
343
|
version: '0'
|
344
344
|
requirements: []
|
345
345
|
rubygems_version: 3.1.4
|
346
|
-
signing_key:
|
346
|
+
signing_key:
|
347
347
|
specification_version: 4
|
348
348
|
summary: openstax IaC
|
349
349
|
test_files: []
|