Class: Chimp::Connection

Inherits:
Object
  • Object
show all
Includes:
Singleton
Defined in:
lib/right_chimp/resources/connection.rb

Overview

This class contains all the necessary to make calls to api1.5 via the right_api_client gem or obtain a list of instances via api1.6 calls.

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initializeConnection

Returns a new instance of Connection.



14
15
# File 'lib/right_chimp/resources/connection.rb', line 14

def initialize
end

Instance Attribute Details

#all_instancesObject

Returns the value of attribute all_instances.



12
13
14
# File 'lib/right_chimp/resources/connection.rb', line 12

def all_instances
  @all_instances
end

#clientObject

Returns the value of attribute client.



12
13
14
# File 'lib/right_chimp/resources/connection.rb', line 12

def client
  @client
end

#retryObject

Returns the value of attribute retry.



12
13
14
# File 'lib/right_chimp/resources/connection.rb', line 12

def retry
  @retry
end

Class Method Details

.all_instancesObject

Returns every single operational instance in the account



91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
# File 'lib/right_chimp/resources/connection.rb', line 91

def self.all_instances()
  begin
    Log.debug "[#{Chimp.get_job_uuid}] Requesting all instances"

    filters_list = "state=operational"
    filters = CGI::escape(filters_list)

    query="/api/instances?view=full&filter="+filters

    all_instances = Connection.api16_call(query)

  rescue Exception => e
    Log.error "[#{Chimp.get_job_uuid}] self.all_instaces"
    Log.error "[#{Chimp.get_job_uuid}] #{e.message}"
  end

  return all_instances
end

.api16_call(query) ⇒ Object

Provides a way to make an api1.6 call directly



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
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
# File 'lib/right_chimp/resources/connection.rb', line 134

def Connection.api16_call(query)
  Thread.current[:retry] = true
  Thread.current[:response] = nil
  retries = 5
  attempts = 0
  sleep_for = 20

  begin
    get = Net::HTTP::Get.new(query)
    if @client.access_token
      # auth using oauth access token
      get['Authorization'] = 'Bearer ' + @client.access_token
    else
      get['Cookie']        = @client.cookies.map { |key, value| "%s=%s" % [key, value] }.join(';')
    end
    get['X-Api_Version'] = '1.6'
    get['X-Account']     = @client.

    http = Net::HTTP.new(@endpoint, 443)
    http.use_ssl = true

    Log.debug "[#{Chimp.get_job_uuid}] Querying API for: #{query}"

    while attempts < retries
      Log.debug "[#{Chimp.get_job_uuid}] Attempt is: #{attempts.to_s}"
      Log.debug "[#{Chimp.get_job_uuid}] Retry is: #{Thread.current[:retry].to_s}"
      if Thread.current[:retry]
        if attempts > 0
          Log.debug "[#{Chimp.get_job_uuid}] Retrying..."
          sleep_time = sleep_for * attempts
          # Add a random amount to avoid staggering calls
          sleep_time += rand(15)

          Log.debug "[#{Chimp.get_job_uuid}] Sleeping between retries for #{sleep_time}"
          sleep(sleep_time)
        end

        Log.debug "[#{Chimp.get_job_uuid}] Attempt # #{attempts+1} at querying the API" unless attempts == 0

        Log.debug "[#{Chimp.get_job_uuid}] HTTP Making http request"
        start_time = Time.now
        Thread.current[:response] = http.request(get)
        end_time = Time.now
        total_time = end_time - start_time

        Log.debug "[#{Chimp.get_job_uuid}] HTTP Request complete"
        attempts += 1

        Log.debug "[#{Chimp.get_job_uuid}] API Request time: #{total_time} seconds"
        Log.debug "[#{Chimp.get_job_uuid}] API Query was: #{query}"

        # Validate API response
        Log.debug "[#{Chimp.get_job_uuid}] Validating..."
        instances = validate_response(Thread.current[:response], query)
      else
        # We dont retry, exit the loop.
        Log.debug "[#{Chimp.get_job_uuid}] Not retrying, exiting the loop."
        Thread.current[:retry] = false
        break
      end
    end

    if attempts == retries

      Log.error "[#{Chimp.get_job_uuid}] Api call failed more than #{retries} times."

      Chimp.set_failure(true)
      Log.error "[#{Chimp.get_job_uuid}] Set failure to true because of max retries"

      instances = []
      raise "[#{Chimp.get_job_uuid}] Api call failed more than #{retries} times."
    end

    if instances.nil?
      Log.error "[#{Chimp.get_job_uuid}] instances is nil!"
    else
      Log.debug "[#{Chimp.get_job_uuid}] API matched #{instances.count} instances"
    end

  rescue Exception => e
    Log.error "[#{Chimp.get_job_uuid}] #{e.message}"
    Log.error "[#{Chimp.get_job_uuid}] Catched exception on http request to the api, retrying"

    instances = []
    attempts += 1
    retry
  end

  return instances
end

.audit_urlObject



84
85
86
# File 'lib/right_chimp/resources/connection.rb', line 84

def self.audit_url
  @audit_url
end

.clientObject



76
77
78
# File 'lib/right_chimp/resources/connection.rb', line 76

def self.client
  @client
end

.connectObject



32
33
34
# File 'lib/right_chimp/resources/connection.rb', line 32

def self.connect
  self.start_right_api_client
end

.connect_and_cacheObject



17
18
19
20
21
22
23
24
25
26
27
28
29
30
# File 'lib/right_chimp/resources/connection.rb', line 17

def self.connect_and_cache

  self.start_right_api_client

  Log.debug "Making initial Api1.6 call to cache entries."

  result = self.all_instances
  if result.empty? || result.nil?
    Log.error "Couldnt contact API1.6 correctly, will now exit."
    exit -1
  else
    Log.debug "API lists #{result.count} operational instances in the account"
  end
end

.endpointObject



80
81
82
# File 'lib/right_chimp/resources/connection.rb', line 80

def self.endpoint
  @endpoint
end

.instances(extra_filters) ⇒ Object

Returns every single operational instance in the account, matching the filters passed.



113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
# File 'lib/right_chimp/resources/connection.rb', line 113

def self.instances(extra_filters)
  Log.debug "[#{Chimp.get_job_uuid}] Requesting some instances"
  begin
    filters_list = "state=operational&"+extra_filters
    filters = CGI::escape(filters_list)

    query="/api/instances?view=full&filter="+filters

    instances = Connection.api16_call(query)

  rescue Exception => e
    Log.error "[#{Chimp.get_job_uuid}] self.instances"
    Log.error "[#{Chimp.get_job_uuid}] #{e.message}"
  end

  return instances
end

.start_right_api_clientObject



36
37
38
39
40
41
42
43
44
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
# File 'lib/right_chimp/resources/connection.rb', line 36

def self.start_right_api_client
  require 'yaml'
  require 'right_api_client'

  begin
    creds = YAML.load_file("#{ENV['HOME']}/.rest_connection/rest_api_config.yaml")

    # Extract the account
    creds[:account] = File.basename(creds[:api_url])

    # Figure out url to hit:
    creds[:api_url] = "https://"+URI.parse(creds[:api_url]).host

    @audit_url = creds[:api_url] + "/acct/" + creds[:account]

    @endpoint = URI.parse(creds[:api_url]).host

    Log.debug "Logging into Api 1.5 right_api_client"
    if creds[:refresh_token] then
      # no account id extraction, must be specified in config file
      # refresh_token must be specified in config
      @client = RightApi::Client.new(refresh_token: creds[:refresh_token],
                                     account_id: creds[:account], api_url: creds[:api_url],
                                     timeout: 60, enable_retry: true)
    else
      @client = RightApi::Client.new(email: creds[:user], password: creds[:pass],
                                     account_id: creds[:account], api_url: creds[:api_url],
                                     timeout: 60, enable_retry: true)
    end
  rescue
    puts "##############################################################################"
    puts "Error: "
    puts " - credentials file could not be loaded correctly"
    puts "or                           "
    puts " - connection couldnt be establishhed"
    puts "##############################################################################"
    exit -1
  end
end

.validate_response(response, query) ⇒ Object

Verify the results are valid JSON



228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
# File 'lib/right_chimp/resources/connection.rb', line 228

def Connection.validate_response(response, query)

  resp_code = response.code
  # handle response codes we want to work with (200 or 404) and verify json hash from github
  if resp_code == "200" || resp_code == "404"
    body_data = response.body
    # verify json hash is valid and operate accordingly
    begin
      result = JSON.parse(body_data)
      if result.is_a?(Array)
        # Operate on a 200 or 404 with valid JSON response, catch error messages from github in json hash
        if result.include? 'message'
          Log.error "[#{Chimp.get_job_uuid}] [CONTENT] Errot: Problem with API request: '#{resp_code} #{response.body}'."
          raise "[#{Chimp.get_job_uuid}] [CONTENT] Error: Problem with API request: '#{resp_code} #{response.body}'"
        end
        if result.include? 'Error'
          Log.error "[#{Chimp.get_job_uuid}] [CONTENT] Warning BAD CONTENT: Response content: '#{response.body}'."
          return {} # Return an empty json
        end

        # Log.debug "We received a valid JSON response, therefore returning it."

        Thread.current[:retry] = false

        Log.debug "[#{Chimp.get_job_uuid}] Validated and returning size of #{result.size} "
        return result
      end
    rescue JSON::ParserError
      Log.error "[#{Chimp.get_job_uuid}] Warning: Expected JSON response but was unable to parse!"
      #Log.error "Warning: #{response.body}!"

      return {} # Return an empty result
    end

  elsif resp_code == "502"
    Log.debug "[#{Chimp.get_job_uuid}] Api returned code: 502"
    Log.debug "[#{Chimp.get_job_uuid}] Query was: #{query}"

    Thread.current[:retry] = true

  elsif resp_code == "500"
    Log.debug "[#{Chimp.get_job_uuid}] Api returned code: 500"
    Log.debug "[#{Chimp.get_job_uuid}] Query was: #{query}"

    Thread.current[:retry] = true

  elsif resp_code == "504"
      Log.debug "[#{Chimp.get_job_uuid}] Api returned code: 504"
      Log.debug "[#{Chimp.get_job_uuid}] Query was: #{query}"

      Thread.current[:retry] = true

  else
    # We are here because response was not 200 or 404
    # Any http response code that is not 200 / 404 / 500 / 502 should error out.
    Log.error "[#{Chimp.get_job_uuid}] ERROR: Got '#{resp_code} #{response.msg}' response from api!  "
    Log.error "[#{Chimp.get_job_uuid}] Query was: #{query}"
    raise "[#{Chimp.get_job_uuid}] Couldnt contact the API"
    return {}
  end
end