ruby_api_pack_cloudways 0.3.0 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 55bab48c0d619f7918865a2a4e3f73a8384253844892e29231fe00843e4168b2
4
- data.tar.gz: 44054862918fd30db13413b2b8d344e59a44e7f522add84b13d31c93afa5d9e5
3
+ metadata.gz: 6765ce6819c078879372426341ea342075ff9affdb4bba5d0b975cb9bb6a9490
4
+ data.tar.gz: 2686e6ab99b91918efec326913b6e47efc0f6362f783d0e81f96c32d2392fa10
5
5
  SHA512:
6
- metadata.gz: 97fbbb96b0ebc20a12ce6af6912e08f1a9962d95c319fe40a6f48c3a4de41c1d45b66ad2fa3b1b2a17402051e700df54f4eb2500664cee3182871b80705f40c9
7
- data.tar.gz: 0b85aeeb9211ffab7c946fdf219a4015f8ab3c937274700f356f0e39d5e769e77588a0c172d608e7e05628b5ee6abbed4d98b2f2f82385c19b2713fea555732a
6
+ metadata.gz: c146cd133b425c9b233b2140d154ec607c7c3cd720466b70300338b22a7f338e934f25cd49633199fe8de3d492f3a0de74d008853780e21f089060843b8266fb
7
+ data.tar.gz: 4f6a16799faae8d64f844b312cd7b2775fa4428a62c5f1abb3cf193d508873ba31763ae5b3e216ae31f8669ae113e86ef50439386d3dc98b231a4aa18a6f632b
@@ -1,15 +1,19 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'ruby_api_pack_cloudways/handlers/response_validator'
4
+
3
5
  module RubyApiPackCloudways
4
6
  module Api
5
7
  class CwLists
8
+ extend RubyApiPackCloudways::Handlers::ResponseValidator
9
+
6
10
  # List endpoints
7
11
  ENDPOINTS = {
8
12
  apps: '/apps',
9
13
  backup_frequencies: '/backup-frequencies',
10
14
  countries: '/countries',
11
- monitor_durations: '/monitoring/durations',
12
- monitor_targets: '/monitoring/targets',
15
+ monitor_durations: '/monitor_durations',
16
+ monitor_targets: '/monitor_targets',
13
17
  packages: '/packages',
14
18
  providers: '/providers',
15
19
  regions: '/regions',
@@ -19,52 +23,54 @@ module RubyApiPackCloudways
19
23
 
20
24
  # Fetch list of applications available
21
25
  def self.app_list
22
- fetch_resource(ENDPOINTS[:apps])['apps']
26
+ validate_response(fetch_resource(ENDPOINTS[:apps]), 'apps')
23
27
  end
24
28
 
25
29
  # Fetch list of available backup frequencies
26
30
  def self.backup_frequency_list
27
- fetch_resource(ENDPOINTS[:backup_frequencies])['frequencies']
31
+ validate_response(fetch_resource(ENDPOINTS[:backup_frequencies]), 'frequencies')
28
32
  end
29
33
 
30
34
  # Fetch list of supported countries
31
35
  def self.country_list
32
- fetch_resource(ENDPOINTS[:countries])['countries']
36
+ response = fetch_resource(ENDPOINTS[:countries])
37
+ wrapped_response = { 'countries' => response } if response.is_a?(Array)
38
+ validate_response(wrapped_response || response, 'countries')
33
39
  end
34
40
 
35
41
  # Fetch list of monitoring durations
36
42
  def self.monitor_duration_list
37
- fetch_resource(ENDPOINTS[:monitor_durations])['durations']
43
+ validate_response(fetch_resource(ENDPOINTS[:monitor_durations]), 'durations')
38
44
  end
39
45
 
40
46
  # Fetch list of monitoring targets
41
47
  def self.monitor_target_list
42
- fetch_resource(ENDPOINTS[:monitor_targets])['targets']
48
+ validate_response(fetch_resource(ENDPOINTS[:monitor_targets]), 'targets')
43
49
  end
44
50
 
45
51
  # Fetch list of available packages
46
52
  def self.package_list
47
- fetch_resource(ENDPOINTS[:packages])['packages']
53
+ validate_response(fetch_resource(ENDPOINTS[:packages]), 'packages')
48
54
  end
49
55
 
50
56
  # Fetch list of providers
51
57
  def self.provider_list
52
- fetch_resource(ENDPOINTS[:providers])['providers']
58
+ validate_response(fetch_resource(ENDPOINTS[:providers]), 'providers')
53
59
  end
54
60
 
55
61
  # Fetch list of regions
56
62
  def self.region_list
57
- fetch_resource(ENDPOINTS[:regions])['regions']
63
+ validate_response(fetch_resource(ENDPOINTS[:regions]), 'regions')
58
64
  end
59
65
 
60
66
  # Fetch list of server sizes
61
67
  def self.server_size_list
62
- fetch_resource(ENDPOINTS[:server_sizes])['sizes']
68
+ validate_response(fetch_resource(ENDPOINTS[:server_sizes]), 'sizes')
63
69
  end
64
70
 
65
71
  # Fetch list of available settings
66
72
  def self.setting_list
67
- fetch_resource(ENDPOINTS[:settings])['settings']
73
+ validate_response(fetch_resource(ENDPOINTS[:settings]), 'settings')
68
74
  end
69
75
 
70
76
  # Private method to fetch resources from a specified endpoint
@@ -1,5 +1,9 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'httparty'
4
+ require 'oj'
5
+ require 'openssl'
6
+
3
7
  module RubyApiPackCloudways
4
8
  module Connection
5
9
  class CwConnect
@@ -17,9 +21,16 @@ module RubyApiPackCloudways
17
21
  token = CwToken.new.cw_api_token
18
22
  response = HTTParty.get(
19
23
  "#{@cw_api_url_base}#{@cw_api_path}",
20
- headers: { 'Authorization' => "Bearer #{token}" }
24
+ headers: { 'Authorization' => "Bearer #{token}" },
25
+ ssl_version: :TLSv1_2,
26
+ debug_output: $stdout
21
27
  )
22
28
  handle_response(response)
29
+ rescue RuntimeError => e
30
+ raise unless e.message.include?('Rate limit exceeded')
31
+
32
+ sleep(60)
33
+ retry
23
34
  end
24
35
 
25
36
  # POST request to Cloudways API
@@ -28,7 +39,9 @@ module RubyApiPackCloudways
28
39
  response = HTTParty.post(
29
40
  "#{@cw_api_url_base}#{@cw_api_path}",
30
41
  headers: { 'Authorization' => "Bearer #{token}", 'Content-Type' => 'application/json' },
31
- body: params.to_json
42
+ body: params.to_json,
43
+ ssl_version: :TLSv1_2,
44
+ debug_output: $stdout
32
45
  )
33
46
  handle_response(response)
34
47
  end
@@ -47,9 +60,12 @@ module RubyApiPackCloudways
47
60
 
48
61
  # Parse response from Cloudways API
49
62
  def parse_response(response)
63
+ content_type = response.headers&.fetch('content-type', nil)
64
+ raise "Unexpected response: #{response.body}" unless content_type&.include?('application/json')
65
+
50
66
  Oj.load(response.body, mode: :strict)
51
67
  rescue Oj::ParseError => e
52
- raise "Error parsing response: #{e.message}"
68
+ raise "Error parsing response: #{e.message}. Raw body: #{response.body}"
53
69
  end
54
70
  end
55
71
  end
@@ -3,6 +3,9 @@
3
3
  module RubyApiPackCloudways
4
4
  module Connection
5
5
  class CwToken
6
+ # Buffer time before token expiration to fetch a new token
7
+ TOKEN_EXPIRATION_BUFFER = 300
8
+
6
9
  attr_reader :cw_api_url_base, :cw_url_path_auth, :cw_user_email, :cw_user_key
7
10
 
8
11
  def initialize
@@ -10,23 +13,53 @@ module RubyApiPackCloudways
10
13
  @cw_url_path_auth = RubyApiPackCloudways.configuration.api_path_token
11
14
  @cw_user_email = RubyApiPackCloudways.configuration.api_email
12
15
  @cw_user_key = RubyApiPackCloudways.configuration.api_key
16
+ @cached_token = nil
17
+ @token_expiry = nil
13
18
  end
14
19
 
20
+ # Fetch the API token, using caching to avoid unnecessary requests
15
21
  def cw_api_token
22
+ # Use cached token if valid and not near expiration
23
+ return @cached_token if valid_cached_token?
24
+
25
+ # Fetch a new token
16
26
  response = HTTParty.post(
17
27
  "#{@cw_api_url_base}#{@cw_url_path_auth}",
18
28
  headers: { 'Content-Type' => 'application/x-www-form-urlencoded' },
19
- body: { email: @cw_user_email, api_key: @cw_user_key }
29
+ body: { email: @cw_user_email, api_key: @cw_user_key },
30
+ debug_output: $stdout # Enable debug output for troubleshooting
20
31
  )
21
- parse_response(response)['access_token']
32
+
33
+ if response.code == 200
34
+ # Parse the response and cache the token
35
+ parsed_response = parse_response(response)
36
+ @cached_token = parsed_response['access_token']
37
+ @token_expiry = Time.now + parsed_response['expires_in']
38
+ @cached_token
39
+ else
40
+ handle_error_response(response)
41
+ end
22
42
  end
23
43
 
24
44
  private
25
45
 
46
+ # Check if the cached token is still valid
47
+ def valid_cached_token?
48
+ @cached_token && @token_expiry && Time.now < (@token_expiry - TOKEN_EXPIRATION_BUFFER)
49
+ end
50
+
51
+ # Parse the API response
26
52
  def parse_response(response)
27
53
  Oj.load(response.body, mode: :strict)
28
54
  rescue Oj::ParseError => e
29
- raise "Error parsing response: #{e.message}"
55
+ raise "Error parsing response: #{e.message}. Raw body: #{response.body}"
56
+ end
57
+
58
+ # Handle non-200 responses
59
+ def handle_error_response(response)
60
+ error_message = "Failed to fetch token: #{response.code} - #{response.body}"
61
+ puts error_message
62
+ raise error_message
30
63
  end
31
64
  end
32
65
  end
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RubyApiPackCloudways
4
+ module Handlers
5
+ module ResponseValidator
6
+ def validate_response(response, expected_key)
7
+ raise "Unexpected response format: #{response.inspect}" unless response.is_a?(Hash) && response.key?(expected_key)
8
+
9
+ result = response[expected_key]
10
+ raise "Expected '#{expected_key}' to be an Array, got #{result.class}: #{result.inspect}" unless result.is_a?(Array)
11
+
12
+ result
13
+ rescue StandardError => e
14
+ log_error("Error validating response: #{e.message}")
15
+ raise "An error occurred while processing the response: #{e.message}"
16
+ end
17
+
18
+ private
19
+
20
+ def log_error(message)
21
+ if defined?(Rails)
22
+ Rails.logger.error(message)
23
+ else
24
+ puts "[ERROR] #{message}"
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module RubyApiPackCloudways
4
- VERSION = '0.3.0'
4
+ VERSION = '0.4.0'
5
5
  end
@@ -4,6 +4,7 @@ require 'httparty'
4
4
  require 'oj'
5
5
 
6
6
  require_relative 'ruby_api_pack_cloudways/configuration'
7
+ require_relative 'ruby_api_pack_cloudways/handlers/response_validator'
7
8
  require_relative 'ruby_api_pack_cloudways/connection/cw_token'
8
9
  require_relative 'ruby_api_pack_cloudways/connection/cw_connect'
9
10
  require_relative 'ruby_api_pack_cloudways/api/cw_lists'
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ruby_api_pack_cloudways
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0
4
+ version: 0.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - PHCDevworks
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2024-11-01 00:00:00.000000000 Z
12
+ date: 2024-11-17 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: httparty
@@ -58,6 +58,7 @@ files:
58
58
  - lib/ruby_api_pack_cloudways/configuration.rb
59
59
  - lib/ruby_api_pack_cloudways/connection/cw_connect.rb
60
60
  - lib/ruby_api_pack_cloudways/connection/cw_token.rb
61
+ - lib/ruby_api_pack_cloudways/handlers/response_validator.rb
61
62
  - lib/ruby_api_pack_cloudways/version.rb
62
63
  homepage: https://github.com/phcdevworks/ruby_api_pack_cloudways/wiki
63
64
  licenses:
@@ -82,7 +83,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
82
83
  - !ruby/object:Gem::Version
83
84
  version: '0'
84
85
  requirements: []
85
- rubygems_version: 3.3.27
86
+ rubygems_version: 3.4.19
86
87
  signing_key:
87
88
  specification_version: 4
88
89
  summary: API Pack for Cloudways