Class: Ridley::Connection

Inherits:
Faraday::Connection
  • Object
show all
Includes:
Celluloid
Defined in:
lib/ridley/connection.rb

Constant Summary collapse

VALID_OPTIONS =
[
  :retries,
  :retry_interval,
  :ssl,
  :proxy
]

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(server_url, client_name, client_key, options = {}) ⇒ Connection

Returns a new instance of Connection.

Parameters:

  • server_url (String)
  • client_name (String)
  • client_key (String)
  • options (Hash) (defaults to: {})

    a customizable set of options

Options Hash (options):

  • :retries (Integer) — default: 5

    retry requests on 5XX failures

  • :retry_interval (Float) — default: 0.5

    how often we should pause between retries

  • :ssl (Hash)
    • :verify (Boolean) [true] set to false to disable SSL verification

  • :proxy (URI, String, Hash)

    URI, String, or Hash of HTTP proxy options



45
46
47
48
49
50
51
52
53
54
55
56
57
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
85
86
# File 'lib/ridley/connection.rb', line 45

def initialize(server_url, client_name, client_key, options = {})
  options         = options.reverse_merge(retries: 5, retry_interval: 0.5)
  @client_name    = client_name
  @client_key     = client_key
  @retries        = options.delete(:retries)
  @retry_interval = options.delete(:retry_interval)

  options[:builder] = Faraday::RackBuilder.new do |b|
    b.request :retry,
      max: @retries,
      interval: @retry_interval,
      exceptions: [
        Ridley::Errors::HTTP5XXError,
        Errno::ETIMEDOUT,
        Faraday::Error::TimeoutError
      ]
    b.request :chef_auth, client_name, client_key

    b.response :parse_json
    b.response :gzip
    b.response :chef_response

    b.adapter :net_http_persistent
  end

  uri_hash = Ridley::Helpers.options_slice(Addressable::URI.parse(server_url).to_hash, :scheme, :host, :port)

  unless uri_hash[:port]
    uri_hash[:port] = (uri_hash[:scheme] == "https" ? 443 : 80)
  end

  if org_match = server_url.match(/.*\/organizations\/(.*)/)
    @organization = org_match[1]
  end

  unless @organization.nil?
    uri_hash[:path] = "/organizations/#{@organization}"
  end

  super(Addressable::URI.new(uri_hash), options)
  @headers[:user_agent] = "Ridley v#{Ridley::VERSION}"
end

Instance Attribute Details

#client_keyString (readonly)

Returns:

  • (String)


23
24
25
# File 'lib/ridley/connection.rb', line 23

def client_key
  @client_key
end

#client_nameString (readonly)

Returns:

  • (String)


25
26
27
# File 'lib/ridley/connection.rb', line 25

def client_name
  @client_name
end

#organizationString (readonly)

Returns:

  • (String)


21
22
23
# File 'lib/ridley/connection.rb', line 21

def organization
  @organization
end

#retriesInteger (readonly)

Returns how many retries to attempt on HTTP requests.

Returns:

  • (Integer)

    how many retries to attempt on HTTP requests



28
29
30
# File 'lib/ridley/connection.rb', line 28

def retries
  @retries
end

#retry_intervalFloat (readonly)

Returns time to wait between retries.

Returns:

  • (Float)

    time to wait between retries



31
32
33
# File 'lib/ridley/connection.rb', line 31

def retry_interval
  @retry_interval
end

Instance Method Details

#api_typeSymbol

Returns:

  • (Symbol)


89
90
91
# File 'lib/ridley/connection.rb', line 89

def api_type
  organization.nil? ? :foss : :hosted
end

#foss?Boolean

Returns:

  • (Boolean)


99
100
101
# File 'lib/ridley/connection.rb', line 99

def foss?
  api_type == :foss
end

#hosted?Boolean

Returns:

  • (Boolean)


94
95
96
# File 'lib/ridley/connection.rb', line 94

def hosted?
  api_type == :hosted
end

#run_request(*args) ⇒ Object

Override Faraday::Connection#run_request to catch exceptions from Middleware that we expect. Caught exceptions are re-raised with Celluloid#abort so we don’t crash the connection.



105
106
107
108
109
110
111
112
113
114
115
# File 'lib/ridley/connection.rb', line 105

def run_request(*args)
  super
rescue Errors::HTTPError => ex
  abort ex
rescue Faraday::Error::ConnectionFailed => ex
  abort Errors::ConnectionFailed.new(ex)
rescue Faraday::Error::TimeoutError => ex
  abort Errors::TimeoutError.new(ex)
rescue Faraday::Error::ClientError => ex
  abort Errors::ClientError.new(ex)
end

#server_urlObject



117
118
119
# File 'lib/ridley/connection.rb', line 117

def server_url
  self.url_prefix.to_s
end

#stream(target, destination) ⇒ Boolean

Stream the response body of a remote URL to a file on the local file system

Parameters:

  • target (String)

    a URL to stream the response body from

  • destination (String)

    a location on disk to stream the content of the response body to

Returns:

  • (Boolean)

    true when the destination file exists



129
130
131
132
133
134
135
136
137
138
139
140
141
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
# File 'lib/ridley/connection.rb', line 129

def stream(target, destination)
  FileUtils.mkdir_p(File.dirname(destination))

  target  = Addressable::URI.parse(target)
  headers = Middleware::ChefAuth.authentication_headers(
    client_name,
    client_key,
    http_method: "GET",
    host: target.host,
    path: target.path
  )

  unless ssl[:verify]
    headers.merge!(ssl_verify_mode: OpenSSL::SSL::VERIFY_NONE)
  end

  local = Tempfile.new('ridley-stream')
  local.binmode

  Retryable.retryable(tries: retries, on: OpenURI::HTTPError, sleep: retry_interval) do
    open(target, 'rb', headers) do |remote|
      body = remote.read
      case remote.content_encoding
      when ['gzip']
        body = Zlib::GzipReader.new(StringIO.new(body), encoding: 'ASCII-8BIT').read
      when ['deflate']
        body = Zlib::Inflate.inflate(body)
      end
      local.write(body)
    end
  end

  local.flush

  FileUtils.cp(local.path, destination)
  File.exists?(destination)
rescue OpenURI::HTTPError => ex
  abort(ex)
ensure
  local.close(true) unless local.nil?
end