ruby_api_pack_cloudways 0.3.0 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
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