requester.rb 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136
  1. module Import
  2. module OTRS
  3. # @!attribute [rw] retry_sleep
  4. # @return [Number] the sleep time between the request retries
  5. module Requester
  6. extend Import::Helper
  7. extend self
  8. attr_accessor :retry_sleep
  9. # Loads entries of the given object.
  10. #
  11. # @param object [String] the name of OTRS object
  12. # @param [Hash] opts the options to load entries.
  13. # @option opts [String] :limit the maximum amount of entries that should get loaded
  14. # @option opts [String] :offset the offset where the entry listing should start
  15. # @option opts [Boolean] :diff request only changed/added entries since the last import
  16. #
  17. # @example
  18. # Import::OTRS::Requester.load('State', offset: '0', limit: '50')
  19. # #=> [{'Name':'pending reminder', ...}, ...]
  20. #
  21. # @return [Array<Hash{String => String, Number, nil, Hash, Array}>]
  22. def load(object, opts = {})
  23. @cache ||= {}
  24. if opts.blank? && @cache[object]
  25. return @cache[object]
  26. end
  27. result = request_result(
  28. Subaction: 'Export',
  29. Object: object,
  30. Limit: opts[:limit] || '',
  31. Offset: opts[:offset] || '',
  32. Diff: opts[:diff] ? 1 : 0
  33. )
  34. return result if opts.present?
  35. @cache[object] = result
  36. @cache[object]
  37. end
  38. # Lists the OTRS objects and their amount of importable entries.
  39. #
  40. # @example
  41. # Import::OTRS::Requester.list #=> {'DynamicFields' => 5, ...}
  42. #
  43. # @return [Hash{String => Number}] key = OTRS object, value = amount
  44. def list
  45. request_result(Subaction: 'List')
  46. end
  47. # Checks if the connection to the OTRS export endpoint works.
  48. #
  49. # @todo Refactor to something like .connected?
  50. #
  51. # @example
  52. # Import::OTRS::Requester.connection_test #=> true
  53. #
  54. # @raise [RuntimeError] if the API key is not valid
  55. #
  56. # @return [true] always returns true
  57. def connection_test
  58. result = request_json({})
  59. raise 'API key not valid!' if !result['Success']
  60. true
  61. end
  62. private
  63. def request_result(params)
  64. tries ||= 1
  65. response = request_json(params)
  66. response['Result']
  67. rescue
  68. # stop after 3 tries
  69. raise if tries == 3
  70. # try again
  71. tries += 1
  72. sleep tries * (retry_sleep || 15)
  73. retry
  74. end
  75. def request_json(params)
  76. response = post(params)
  77. result = handle_response(response)
  78. raise 'Invalid response' if !result
  79. result
  80. end
  81. def handle_response(response)
  82. encoded_body = response.body.to_utf8
  83. # remove null bytes otherwise PostgreSQL will fail
  84. encoded_body.delete('\u0000')
  85. JSON.parse(encoded_body)
  86. end
  87. def post(params)
  88. url = Setting.get('import_otrs_endpoint')
  89. params[:Action] = 'ZammadMigrator'
  90. params[:Key] = Setting.get('import_otrs_endpoint_key')
  91. log 'POST: ' + url
  92. log 'PARAMS: ' + params.inspect
  93. response = UserAgent.post(
  94. url,
  95. params,
  96. {
  97. open_timeout: 10,
  98. read_timeout: 120,
  99. total_timeout: 360,
  100. user: Setting.get('import_otrs_user'),
  101. password: Setting.get('import_otrs_password'),
  102. },
  103. )
  104. if !response
  105. raise "Can't connect to Zammad Migrator"
  106. end
  107. if !response.success?
  108. log "ERROR: #{response.error}"
  109. raise 'Zammad Migrator returned an error'
  110. end
  111. response
  112. end
  113. end
  114. end
  115. end