firespring_dev_commands 2.1.26.pre.alpha.2 → 2.1.27.pre.alpha.2

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
  SHA256:
3
- metadata.gz: b68163bb71bf29450c83939ecdc3181f8003ac39731839c0c67dd5808c2f9331
4
- data.tar.gz: c956a7f6c49ce1d0478df460e54d24a5c12598b4c24b905f959e489c289515f3
3
+ metadata.gz: fce5da47cf928179b220c2d30c295fb5c853aee03ca1cad7bbf9684f8b8aea3a
4
+ data.tar.gz: 33100d5b2127c7cb422f6695e19e85b3f8bfe41d0dd13f7f0ab4f4721351286b
5
5
  SHA512:
6
- metadata.gz: 7f62bd98a204af676eb9bec3cf64c4783c20ad265115df7fbf4e13964a5f5bd9ce3ceb89f3ecb505c478f06fcab1b7635814ebeb999e62e133c63728bf6d7f7e
7
- data.tar.gz: 92b52d27ab0b6a15ebdb16098296259010284326d20719d45d10b41d4f0e73801ec00b1a48ad7f7a0cd941db47b4541bbdad7024cf593aff403324791908a8bb
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(:check_aws_resources, :product_versions, :manual_dates) do
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, :check_aws_resources, :product_versions
29
+ attr_accessor :url, :products, :product_versions
31
30
 
32
- def initialize(check_aws_resources: self.class.config.check_aws_resources, product_versions: self.class.config.product_versions)
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
- checks_to_perform = product_versions.clone
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
- class Common
3
- # Class which returns information about the current platform
4
- class Platform
5
- # Constant containing all supported architectures
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
- # Normalize the ruby platform to return a docker platform architecture format
9
- def determine_compute_architecture
10
- case RUBY_PLATFORM
11
- when /x86_64|amd64|x64-mingw/
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
- # Determine the platform architecture
21
- # If one was specified in the DOCKER_ARCHITECTURE variable, use it
22
- # Otherwise, use the RUBY_PLATFORM built-in to auto-detect and architecture
23
- def architecture
24
- docker_architecture = ENV['DOCKER_ARCHITECTURE'].to_s.strip.downcase
25
- if docker_architecture.empty?
26
- determine_compute_architecture
27
- else
28
- raise "Missing 'linux/' prefix in DOCKER_ARCHITECTURE: #{docker_architecture}" unless docker_architecture.start_with?('linux/')
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
- architecture_name = docker_architecture.split('/')[1]
31
- unless ALLOWED_ARCHITECTURES.include?(architecture_name)
32
- raise "Invalid DOCKER_ARCHITECTURE: #{architecture_name}. Allowed architectures are #{ALLOWED_ARCHITECTURES.join(', ')}"
33
- end
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
- docker_architecture
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
- # Set the EOL library to also check AWS resources
97
+ # Create the rake task for the eol method
98
98
  def create_eol_task!
99
- return if exclude.include?(:eol)
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
- Dev::EndOfLife.config { |c| c.check_aws_resources = true }
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
@@ -6,6 +6,6 @@ module Dev
6
6
  # Use 'v.v.v.pre.alpha.v' for pre-release vesions
7
7
  # Use 'v.v.v.beta.v for beta versions
8
8
  # Use semantic versioning for any releases (https://semver.org/)
9
- VERSION = '2.1.26.pre.alpha.2'.freeze
9
+ VERSION = '2.1.27.pre.alpha.2'.freeze
10
10
  end
11
11
  end
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.26.pre.alpha.2
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-16 00:00:00.000000000 Z
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