Class: Skylight::NativeExtFetcher
- Includes:
- FileUtils
- Defined in:
- lib/skylight/native_ext_fetcher.rb
Overview
Utility class for fetching the native extension from a URL
Defined Under Namespace
Classes: FetchError
Constant Summary collapse
- BASE_URL =
"https://s3.amazonaws.com/skylight-agent-packages/skylight-native".freeze
- MAX_REDIRECTS =
5- MAX_RETRIES =
3
Class Method Summary collapse
-
.fetch(**args) ⇒ Object
Creates a new fetcher and fetches.
Instance Method Summary collapse
- #basename ⇒ Object
-
#deconstruct_uri(uri) ⇒ Array<String>
Split the uri string into its component parts.
-
#error(msg, err = nil) ⇒ void
Log an ‘error` to the `logger`.
-
#fetch ⇒ String
Fetch the native extension, verify, inflate, and save (if applicable).
- #fetch_native_ext(uri, out, attempts, redirects) ⇒ Object
-
#http_get(host, port, use_ssl, path, out) ⇒ Object
Get with ‘Net::HTTP`.
-
#initialize(source:, target:, version:, checksum:, arch:, logger:, required: false, platform: nil) ⇒ NativeExtFetcher
constructor
A new instance of NativeExtFetcher.
-
#log(msg) ⇒ void
Log an ‘info` to the `logger`.
-
#maybe_raise(err) ⇒ void
Log an error and raise if ‘required` is `true`.
-
#source_uri ⇒ Object
The url that will be fetched.
-
#verify_checksum(actual) ⇒ Boolean
Verify the checksum of the archive.
Constructor Details
#initialize(source:, target:, version:, checksum:, arch:, logger:, required: false, platform: nil) ⇒ NativeExtFetcher
Returns a new instance of NativeExtFetcher.
39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 |
# File 'lib/skylight/native_ext_fetcher.rb', line 39 def initialize(source:, target:, version:, checksum:, arch:, logger:, required: false, platform: nil) raise "source required" unless source raise "target required" unless target raise "checksum required" unless checksum raise "arch required" unless arch @source = source @target = target @version = version @checksum = checksum @required = required @platform = platform @arch = arch @logger = logger end |
Class Method Details
Instance Method Details
#basename ⇒ Object
210 211 212 |
# File 'lib/skylight/native_ext_fetcher.rb', line 210 def basename "skylight_#{@arch}.tar.gz" end |
#deconstruct_uri(uri) ⇒ Array<String>
Split the uri string into its component parts
225 226 227 228 |
# File 'lib/skylight/native_ext_fetcher.rb', line 225 def deconstruct_uri(uri) uri = URI(uri) [uri.host, uri.port, uri.scheme == "https", uri.request_uri] end |
#error(msg, err = nil) ⇒ void
This method returns an undefined value.
Log an ‘error` to the `logger`
254 255 256 257 258 |
# File 'lib/skylight/native_ext_fetcher.rb', line 254 def error(msg, err = nil) msg = "[SKYLIGHT] #{msg}" msg << "\n#{err.backtrace.join("\n")}" if err @logger.error msg end |
#fetch ⇒ String
Fetch the native extension, verify, inflate, and save (if applicable)
58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 |
# File 'lib/skylight/native_ext_fetcher.rb', line 58 def fetch log "fetching native ext; curr-platform=#{@platform}; " \ "requested-arch=#{@arch}; version=#{@version}" tar_gz = "#{@target}/#{basename}" unless (sha2 = fetch_native_ext(source_uri, tar_gz, MAX_RETRIES, MAX_REDIRECTS)) maybe_raise "could not fetch native extension" return end unless verify_checksum(sha2) maybe_raise "could not verify checksum" return end Dir.chdir File.dirname(tar_gz) do cmd = "tar xzvf #{tar_gz}" out, _status = Open3.capture2e(cmd) log cmd log out end true ensure rm_f tar_gz if tar_gz end |
#fetch_native_ext(uri, out, attempts, redirects) ⇒ Object
86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 |
# File 'lib/skylight/native_ext_fetcher.rb', line 86 def fetch_native_ext(uri, out, attempts, redirects) redirects.times do # Ensure the location is available mkdir_p File.dirname(out) rm_f out remaining_attempts = attempts log "attempting to fetch from remote; uri=#{uri}" begin host, port, use_ssl, path = deconstruct_uri(uri) File.open out, "w" do |f| res, extra = http_get(host, port, use_ssl, path, f) case res when :success log "successfully downloaded native ext; out=#{out}" return extra when :redirect log "fetching native ext; uri=#{uri}; redirected=#{res}" uri = extra next end end rescue StandardError => e remaining_attempts -= 1 error "failed to fetch native extension; uri=#{uri}; msg=#{e.}; " \ "remaining-attempts=#{remaining_attempts}", e if remaining_attempts > 0 sleep 2 retry end return end end log "exceeded max redirects" nil end |
#http_get(host, port, use_ssl, path, out) ⇒ Object
Get with ‘Net::HTTP`
If ‘ENV` is set, it will be used as a proxy for this request.
142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 |
# File 'lib/skylight/native_ext_fetcher.rb', line 142 def http_get(host, port, use_ssl, path, out) if (http_proxy = Util::Proxy.detect_url(ENV)) log "connecting with proxy: #{http_proxy}" uri = URI.parse(http_proxy) p_host = uri.host p_port = uri.port p_user, p_pass = uri.userinfo.split(/:/) if uri.userinfo end opts = { use_ssl: use_ssl } if use_ssl # Create a cert store that doesn't enable CRL checking. # OpenSSL 3.x may enable CRL checking by default, which fails when # the CRL distribution point is unreachable. begin cert_store = OpenSSL::X509::Store.new cert_store.set_default_paths ca_file = Util::SSL.ca_cert_file_or_default cert_store.add_file(ca_file) if ca_file && File.exist?(ca_file) opts[:cert_store] = cert_store rescue OpenSSL::X509::StoreError => e log "failed to configure cert store: #{e.}, using defaults" end opts[:verify_mode] = OpenSSL::SSL::VERIFY_PEER end Net::HTTP.start(host, port, p_host, p_port, p_user, p_pass, **opts) do |http| http.request_get path do |resp| case resp when Net::HTTPSuccess digest = Digest::SHA2.new resp.read_body do |chunk| digest << chunk out.write chunk end return :success, digest.hexdigest when Net::HTTPRedirection unless (location = resp["location"]) raise "received redirect but no location" end return :redirect, location else raise "received HTTP status code #{resp.code}" end end end end |
#log(msg) ⇒ void
This method returns an undefined value.
Log an ‘info` to the `logger`
244 245 246 247 |
# File 'lib/skylight/native_ext_fetcher.rb', line 244 def log(msg) msg = "[SKYLIGHT] #{msg}" @logger.info msg end |
#maybe_raise(err) ⇒ void
This method returns an undefined value.
Log an error and raise if ‘required` is `true`
234 235 236 237 238 |
# File 'lib/skylight/native_ext_fetcher.rb', line 234 def maybe_raise(err) error err raise err if @required end |
#source_uri ⇒ Object
The url that will be fetched
217 218 219 |
# File 'lib/skylight/native_ext_fetcher.rb', line 217 def source_uri "#{@source}/#{@version}/#{basename}" end |
#verify_checksum(actual) ⇒ Boolean
Verify the checksum of the archive
198 199 200 201 202 203 204 205 206 207 208 |
# File 'lib/skylight/native_ext_fetcher.rb', line 198 def verify_checksum(actual) unless @checksum == actual log "checksum mismatch; expected=#{@checksum}; actual=#{actual}" return false end true rescue Exception => e error "failed to read skylight agent archive; e=#{e.}" false end |