firespring_dev_commands 2.1.26.pre.alpha.2 → 2.1.27.pre.alpha.2
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/lib/firespring_dev_commands/certificate.rb +59 -0
- data/lib/firespring_dev_commands/docker/status.rb +20 -0
- data/lib/firespring_dev_commands/docker.rb +38 -0
- data/lib/firespring_dev_commands/eol.rb +4 -13
- data/lib/firespring_dev_commands/platform.rb +25 -32
- data/lib/firespring_dev_commands/templates/aws.rb +15 -3
- data/lib/firespring_dev_commands/templates/certificate.rb +41 -0
- data/lib/firespring_dev_commands/templates/git.rb +0 -17
- data/lib/firespring_dev_commands/version.rb +1 -1
- metadata +4 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: fce5da47cf928179b220c2d30c295fb5c853aee03ca1cad7bbf9684f8b8aea3a
|
4
|
+
data.tar.gz: 33100d5b2127c7cb422f6695e19e85b3f8bfe41d0dd13f7f0ab4f4721351286b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: fb735b569248c55a15bd51bb971054107ea1d885fb08e4a2da43bafdc3093b86daf00c42962fcb0ce4aeb543e76afff8ca06be4359bbbd4c489dc83c09d46bc6
|
7
|
+
data.tar.gz: 4e43a5eee15f6dbbbeab27c006a0dbdb1802be2c882008627b4d1025f99e72a52d3855c8121eba967b21fba4f766daf1e2f0e90e11bb06ab32f7c6e110f86d7e
|
@@ -0,0 +1,59 @@
|
|
1
|
+
module Dev
|
2
|
+
# Class contains methods for requesting a certificate from route53.
|
3
|
+
# You must have a hosted zone defined for the desired domain
|
4
|
+
class Certificate
|
5
|
+
attr_accessor :domains, :email
|
6
|
+
|
7
|
+
def initialize(domains, email)
|
8
|
+
@domains = Array(domains)
|
9
|
+
@email = email
|
10
|
+
raise 'No certificate domains specified' if domains.empty?
|
11
|
+
end
|
12
|
+
|
13
|
+
# Request the certificate using the route53 docker image
|
14
|
+
# Certificate is stored in /etc/letsencrypt
|
15
|
+
def request
|
16
|
+
puts
|
17
|
+
puts 'Getting SSL Certs For:'
|
18
|
+
puts domains.join("\n")
|
19
|
+
puts
|
20
|
+
puts 'This process can take up to 10 minutes'
|
21
|
+
puts
|
22
|
+
puts Time.now
|
23
|
+
|
24
|
+
# TODO: Really should use the docker api for this
|
25
|
+
cmd = %w(docker run -it --rm --name certbot)
|
26
|
+
cmd << '-e' << 'AWS_ACCESS_KEY_ID'
|
27
|
+
cmd << '-e' << 'AWS_SECRET_ACCESS_KEY'
|
28
|
+
cmd << '-e' << 'AWS_SESSION_TOKEN'
|
29
|
+
cmd << '-v' << '/etc/letsencrypt:/etc/letsencrypt'
|
30
|
+
cmd << 'certbot/dns-route53:latest'
|
31
|
+
cmd << 'certonly'
|
32
|
+
cmd << '-n'
|
33
|
+
cmd << '--agree-tos'
|
34
|
+
cmd << '--dns-route53'
|
35
|
+
cmd << '-d' << domains.join(',')
|
36
|
+
cmd << '--email' << email
|
37
|
+
cmd << '--server' << 'https://acme-v02.api.letsencrypt.org/directory'
|
38
|
+
puts cmd.join(' ')
|
39
|
+
Dev::Common.new.run_command(cmd)
|
40
|
+
end
|
41
|
+
|
42
|
+
# Saves the latest version of the certificate into the given dest_dir
|
43
|
+
def save(dest_dir)
|
44
|
+
raise "directory #{dest_dir} must be an existing directory" unless File.directory?(dest_dir)
|
45
|
+
|
46
|
+
domain = domains.first.sub(/^\*\./, '') # Need to strip off the '*.' if this is a wildcard cert
|
47
|
+
directories = Dir.glob("/etc/letsencrypt/live/#{domain}*/")
|
48
|
+
no_suffix = directories.delete("/etc/letsencrypt/live/#{domain}/")
|
49
|
+
biggest_suffix = directories.max
|
50
|
+
source_dir = biggest_suffix || no_suffix
|
51
|
+
raise "unable to determine certificate directory for #{domain}" unless source_dir
|
52
|
+
|
53
|
+
FileUtils.cp("#{source_dir}privkey.pem", dest_dir, verbose: true)
|
54
|
+
FileUtils.cp("#{source_dir}cert.pem", dest_dir, verbose: true)
|
55
|
+
FileUtils.cp("#{source_dir}chain.pem", dest_dir, verbose: true)
|
56
|
+
FileUtils.cp("#{source_dir}fullchain.pem", dest_dir, verbose: true)
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
@@ -33,6 +33,26 @@ module Dev
|
|
33
33
|
EXITED,
|
34
34
|
DEAD
|
35
35
|
].freeze
|
36
|
+
|
37
|
+
# TODO: Can we use 'curses' here and overwrite the correct line?
|
38
|
+
def response_callback(response)
|
39
|
+
response.split("\n").each do |line|
|
40
|
+
data = JSON.parse(line)
|
41
|
+
if data.include?('status')
|
42
|
+
if data['id']
|
43
|
+
LOG.info "#{data['id']}: #{data['status']}"
|
44
|
+
else
|
45
|
+
LOG.info (data['status']).to_s
|
46
|
+
end
|
47
|
+
elsif data.include?('errorDetail')
|
48
|
+
raise data['errorDetail']['message']
|
49
|
+
elsif data.include?('aux')
|
50
|
+
next
|
51
|
+
else
|
52
|
+
raise "Unrecognized message from docker: #{data}"
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
36
56
|
end
|
37
57
|
end
|
38
58
|
end
|
@@ -117,6 +117,44 @@ module Dev
|
|
117
117
|
format('%.1f %s', size.to_f / (1024**exp), units[exp])
|
118
118
|
end
|
119
119
|
|
120
|
+
# Push the local version of the docker image to the defined remote repository
|
121
|
+
def push_image(image, name, tag = nil)
|
122
|
+
unless tag
|
123
|
+
if name.include?(':')
|
124
|
+
name, tag = name.split(':')
|
125
|
+
else
|
126
|
+
tag = 'latest'
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
puts "Pushing to #{name}:#{tag}"
|
131
|
+
image.push(::Docker.creds, repo_tag: "#{name}:#{tag}") { |response| Dev::Docker::Status.new.response_callback(response) }
|
132
|
+
end
|
133
|
+
|
134
|
+
# Push the remote version of the docker image from the defined remote repository
|
135
|
+
def pull_image(name, tag = nil)
|
136
|
+
unless tag
|
137
|
+
if name.include?(':')
|
138
|
+
name, tag = name.split(':')
|
139
|
+
else
|
140
|
+
tag = 'latest'
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
puts "\nPulling #{name}:#{tag}"
|
145
|
+
opts = {
|
146
|
+
fromImage: "#{name}:#{tag}",
|
147
|
+
platform: Dev::Platform.new.architecture
|
148
|
+
}
|
149
|
+
::Docker::Image.create(**opts) { |response| Dev::Docker::Status.new.response_callback(response) }
|
150
|
+
end
|
151
|
+
|
152
|
+
# Remove the local version of the given docker image
|
153
|
+
def untag_image(image, name, tag)
|
154
|
+
puts "Untagging #{name}:#{tag}"
|
155
|
+
image.remove(name: "#{name}:#{tag}")
|
156
|
+
end
|
157
|
+
|
120
158
|
# Remove docker images with the "force" option set to true
|
121
159
|
# This will remove the images even if they are currently in use and cause unintended side effects.
|
122
160
|
def force_remove_images(name_and_tag)
|
@@ -5,9 +5,8 @@ module Dev
|
|
5
5
|
END_OF_LIFE_API_URL = 'https://endoflife.date/api'.freeze
|
6
6
|
|
7
7
|
# Config object for setting top level git config options
|
8
|
-
Config = Struct.new(:
|
8
|
+
Config = Struct.new(:product_versions, :manual_dates) do
|
9
9
|
def initialize
|
10
|
-
self.check_aws_resources = false
|
11
10
|
self.product_versions = []
|
12
11
|
self.manual_dates = {}
|
13
12
|
end
|
@@ -27,10 +26,9 @@ module Dev
|
|
27
26
|
alias_method :configure, :config
|
28
27
|
end
|
29
28
|
|
30
|
-
attr_accessor :url, :products, :
|
29
|
+
attr_accessor :url, :products, :product_versions
|
31
30
|
|
32
|
-
def initialize(
|
33
|
-
@check_aws_resources = check_aws_resources
|
31
|
+
def initialize(product_versions: self.class.config.product_versions)
|
34
32
|
@product_versions = Array(product_versions)
|
35
33
|
raise 'product version must be of type Dev::EndOfLife::ProductVersions' unless @product_versions.all?(Dev::EndOfLife::ProductVersion)
|
36
34
|
end
|
@@ -52,14 +50,7 @@ module Dev
|
|
52
50
|
# Raises an error if any products are EOL
|
53
51
|
def check
|
54
52
|
puts
|
55
|
-
|
56
|
-
if check_aws_resources
|
57
|
-
account_id = Dev::Aws::Profile.new.current
|
58
|
-
account_name = Dev::Aws::Account.new.name_by_account(account_id)
|
59
|
-
LOG.info " Current AWS Account is #{account_name} (#{account_id})\n".light_yellow
|
60
|
-
checks_to_perform.concat(Dev::EndOfLife::Aws.new.default_products)
|
61
|
-
end
|
62
|
-
checks_to_perform.sort_by(&:name).each(&:print_status)
|
53
|
+
product_versions.sort_by(&:name).each(&:print_status)
|
63
54
|
puts
|
64
55
|
raise 'found EOL versions' if product_versions.any?(&:eol)
|
65
56
|
end
|
@@ -1,40 +1,33 @@
|
|
1
1
|
module Dev
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
ALLOWED_ARCHITECTURES = %w(arm64 amd64).freeze
|
2
|
+
# Class which returns information about the current platform
|
3
|
+
class Platform
|
4
|
+
# Constant containing all supported architectures
|
5
|
+
ALLOWED_ARCHITECTURES = %w(linux/arm64 linux/amd64).freeze
|
7
6
|
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
'linux/amd64' # 64-bit Intel/AMD architecture
|
13
|
-
when /arm|aarch64/
|
14
|
-
'linux/arm64' # ARM architecture
|
15
|
-
else
|
16
|
-
raise 'Unknown or unsupported architecture'
|
17
|
-
end
|
18
|
-
end
|
7
|
+
# If an architecture was specified in the ENV, use that. Otherwise auto-deted based of the OS reported architecture
|
8
|
+
def architecture
|
9
|
+
arch = env_architecture || os_architecture
|
10
|
+
raise "Invalid DOCKER_ARCHITECTURE: #{arch} (allowed are #{ALLOWED_ARCHITECTURES.join(', ')})" unless ALLOWED_ARCHITECTURES.include?(arch)
|
19
11
|
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
12
|
+
arch
|
13
|
+
end
|
14
|
+
|
15
|
+
# Check to see if a docker architecture has been specified in the ENV
|
16
|
+
# If it has, verify the format and the value
|
17
|
+
private def env_architecture
|
18
|
+
arch = ENV['DOCKER_ARCHITECTURE'].to_s.strip.downcase
|
19
|
+
return nil if arch.empty?
|
20
|
+
|
21
|
+
"linux/#{arch}" unless arch.start_with?('linux/')
|
22
|
+
arch
|
23
|
+
end
|
29
24
|
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
25
|
+
# Returns a valid docker architecture based off the RUBY_PLATFORM
|
26
|
+
private def os_architecture
|
27
|
+
return 'linux/amd64' if RUBY_PLATFORM.match?(/x86_64|amd64|x64-mingw/)
|
28
|
+
return 'linux/arm64' if RUBY_PLATFORM.match?(/arm|aarch64/)
|
34
29
|
|
35
|
-
|
36
|
-
end
|
37
|
-
end
|
30
|
+
raise 'Unknown or unsupported architecture'
|
38
31
|
end
|
39
32
|
end
|
40
33
|
end
|
@@ -94,11 +94,23 @@ module Dev
|
|
94
94
|
end
|
95
95
|
# rubocop:enable Metrics/MethodLength
|
96
96
|
|
97
|
-
#
|
97
|
+
# Create the rake task for the eol method
|
98
98
|
def create_eol_task!
|
99
|
-
|
99
|
+
# Have to set a local variable to be accessible inside of the instance_eval block
|
100
|
+
exclude = @exclude
|
101
|
+
|
102
|
+
DEV_COMMANDS_TOP_LEVEL.instance_eval do
|
103
|
+
return if exclude.include?(:eol)
|
100
104
|
|
101
|
-
|
105
|
+
desc 'Compares the current date to the EOL date for supported resources'
|
106
|
+
task eol: %w(init ensure_aws_credentials) do
|
107
|
+
account_id = Dev::Aws::Profile.new.current
|
108
|
+
account_name = Dev::Aws::Account.new.name_by_account(account_id)
|
109
|
+
LOG.info " Current AWS Account is #{account_name} (#{account_id})".light_yellow
|
110
|
+
|
111
|
+
Dev::EndOfLife.new(product_versions: Dev::EndOfLife::Aws.new.default_products).check
|
112
|
+
end
|
113
|
+
end
|
102
114
|
end
|
103
115
|
end
|
104
116
|
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
require_relative 'base_interface'
|
2
|
+
|
3
|
+
module Dev
|
4
|
+
module Template
|
5
|
+
# Class contains rake templates for managing configured certificates
|
6
|
+
class Certificate < Dev::Template::BaseInterface
|
7
|
+
attr_reader :domains, :email, :paths
|
8
|
+
|
9
|
+
def initialize(domains, email:, paths:, exclude: [])
|
10
|
+
@domains = domains
|
11
|
+
@email = email
|
12
|
+
@paths = Array(paths)
|
13
|
+
|
14
|
+
super(exclude:)
|
15
|
+
end
|
16
|
+
|
17
|
+
# Create the rake task for the generate method
|
18
|
+
def create_generate_task!
|
19
|
+
# Have to set a local variable to be accessible inside of the instance_eval block
|
20
|
+
domains = @domains
|
21
|
+
email = @email
|
22
|
+
paths = @paths
|
23
|
+
exclude = @exclude
|
24
|
+
|
25
|
+
DEV_COMMANDS_TOP_LEVEL.instance_eval do
|
26
|
+
return if exclude.include?(:generate)
|
27
|
+
|
28
|
+
namespace :certificate do
|
29
|
+
desc 'Requests a new certificate for the configured domain using the route53 validation and deposits it in the configured paths'
|
30
|
+
task generate: %w(init_docker ensure_aws_credentials) do
|
31
|
+
Dev::Docker.new.pull_image('certbot/dns-route53', 'latest')
|
32
|
+
c = Dev::Certificate.new(domains, email)
|
33
|
+
c.request
|
34
|
+
paths.each { |path| c.save(path) }
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -4,23 +4,6 @@ module Dev
|
|
4
4
|
module Template
|
5
5
|
# Class contains rake templates for managing your git project
|
6
6
|
class Git < Dev::Template::BaseInterface
|
7
|
-
# Create the rake task for cloning all defined repos
|
8
|
-
def create_clone_task!
|
9
|
-
# Have to set a local variable to be accessible inside of the instance_eval block
|
10
|
-
exclude = @exclude
|
11
|
-
|
12
|
-
DEV_COMMANDS_TOP_LEVEL.instance_eval do
|
13
|
-
namespace :git do
|
14
|
-
return if exclude.include?(:clone)
|
15
|
-
|
16
|
-
desc 'Make sure all repos are cloned'
|
17
|
-
task :clone do
|
18
|
-
Dev::Git.new.clone_repos
|
19
|
-
end
|
20
|
-
end
|
21
|
-
end
|
22
|
-
end
|
23
|
-
|
24
7
|
# Create the rake task for the git checkout method
|
25
8
|
def create_checkout_task!
|
26
9
|
# Have to set a local variable to be accessible inside of the instance_eval block
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: firespring_dev_commands
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.1.
|
4
|
+
version: 2.1.27.pre.alpha.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Firespring
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-02-
|
11
|
+
date: 2024-02-19 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activesupport
|
@@ -332,6 +332,7 @@ files:
|
|
332
332
|
- lib/firespring_dev_commands/bloom_growth/seat.rb
|
333
333
|
- lib/firespring_dev_commands/bloom_growth/user.rb
|
334
334
|
- lib/firespring_dev_commands/boolean.rb
|
335
|
+
- lib/firespring_dev_commands/certificate.rb
|
335
336
|
- lib/firespring_dev_commands/common.rb
|
336
337
|
- lib/firespring_dev_commands/coverage/base.rb
|
337
338
|
- lib/firespring_dev_commands/coverage/cobertura.rb
|
@@ -383,6 +384,7 @@ files:
|
|
383
384
|
- lib/firespring_dev_commands/target_process/user_story_history.rb
|
384
385
|
- lib/firespring_dev_commands/templates/aws.rb
|
385
386
|
- lib/firespring_dev_commands/templates/base_interface.rb
|
387
|
+
- lib/firespring_dev_commands/templates/certificate.rb
|
386
388
|
- lib/firespring_dev_commands/templates/ci.rb
|
387
389
|
- lib/firespring_dev_commands/templates/config.rb
|
388
390
|
- lib/firespring_dev_commands/templates/docker/application.rb
|