Class: ApiManager

Inherits:
Object
  • Object
show all
Defined in:
lib/ibm_appconfiguration_ruby_sdk/core/api_manager.rb

Overview

This module provides the methods to facilitate the API requests to the App Configuration service.

The ApiManager class handles:

  • IAM authentication using IBM Cloud SDK Core

  • HTTP request headers construction

  • BaseService client management with retry logic

  • Bearer token retrieval for WebSocket connections

ApiManager facilitates API requests to IBM App Configuration service. Manages authentication, HTTP clients, and request headers.

Examples:

Basic usage

ApiManager.set_authenticator
client = ApiManager.base_service_client
token = ApiManager.token

Constant Summary collapse

SDK_VERSION =

SDK version for User-Agent header

IbmAppconfigurationRubySdk::VERSION

Class Attribute Summary collapse

Class Method Summary collapse

Class Attribute Details

.iam_authenticatorIBMCloudSdkCore::IamAuthenticator? (readonly)

Get the IAM Authenticator instance

Examples:

authenticator = ApiManager.iam_authenticator
if authenticator
  puts "Authenticator is configured"
end

Returns:

  • (IBMCloudSdkCore::IamAuthenticator, nil)

    The IAM authenticator or nil if not set



250
251
252
# File 'lib/ibm_appconfiguration_ruby_sdk/core/api_manager.rb', line 250

def iam_authenticator
  @iam_authenticator
end

Class Method Details

.base_service_clientIBMCloudSdkCore::BaseService

Get the BaseService client with retry configuration

Creates a new BaseService client if one doesn’t exist, configured with:

  • The IAM authenticator

  • Retry logic (max 3 retries with exponential backoff)

  • Base service URL from UrlBuilder

Examples:

client = ApiManager.base_service_client
response = client.request(
  method: 'GET',
  url: '/apprapp/feature/v1/instances/guid/config',
  headers: ApiManager.headers
)

Returns:

  • (IBMCloudSdkCore::BaseService)

    The configured BaseService client

Raises:

  • (StandardError)

    If authenticator is not set



131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
# File 'lib/ibm_appconfiguration_ruby_sdk/core/api_manager.rb', line 131

def base_service_client
  if @base_service_client.nil?
    raise "Authenticator not set. Call set_authenticator first." if @iam_authenticator.nil?

    @url_builder ||= UrlBuilder.instance

    @base_service_client = IBMCloudSdkCore::BaseService.new(
      service_name: "app_configuration",
      authenticator: @iam_authenticator,
      service_url: @url_builder.base_service_url
    )

    # Configure retry settings
    # Note: Ruby SDK Core v1.3.0 uses configure_http_client for retry settings
    @base_service_client.configure_http_client(
      timeout: { connect: 60, read: 60, write: 60 }
    )
  end

  @base_service_client
end

.headers(is_post = false) ⇒ Hash

Get the request headers for API calls

Examples:

GET request headers

headers = ApiManager.headers
# => { 'Accept' => 'application/json', 'User-Agent' => 'appconfiguration-ruby-sdk/0.1.0' }

POST request headers

headers = ApiManager.headers(true)
# => { 'Accept' => 'application/json', 'User-Agent' => '...', 'Content-Type' => 'application/json' }

Parameters:

  • is_post (Boolean) (defaults to: false)

    Whether this is a POST request (adds Content-Type header)

Returns:

  • (Hash)

    Hash containing required headers



65
66
67
68
69
70
71
72
# File 'lib/ibm_appconfiguration_ruby_sdk/core/api_manager.rb', line 65

def headers(is_post = false)
  headers = {
    "Accept" => "application/json",
    "User-Agent" => "appconfiguration-ruby-sdk/#{SDK_VERSION}"
  }
  headers["Content-Type"] = "application/json" if is_post
  headers
end

.post_metering(url, metering_data, _apikey) ⇒ IBMCloudSdkCore::DetailedResponse

Post metering data to the App Configuration service

Sends usage metrics for feature and property evaluations to the billing server.

Examples:

data = {
  'collection_id' => 'coll-1',
  'environment_id' => 'env-prod',
  'usages' => [...]
}
response = ApiManager.post_metering(url, data, apikey)

Parameters:

  • url (String)

    The full metering endpoint URL

  • data (Hash)

    The metering data to send

  • apikey (String)

    The API key for authentication

Returns:

  • (IBMCloudSdkCore::DetailedResponse)

    The HTTP response

Raises:

  • (StandardError)

    If the request fails



219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
# File 'lib/ibm_appconfiguration_ruby_sdk/core/api_manager.rb', line 219

def post_metering(url, metering_data, _apikey)
  require "json"

  # Extract the path from the full URL
  uri = URI.parse(url)
  path = uri.path

  # The IBM Cloud Ruby SDK's BaseService.request method signature:
  # request(method:, url:, headers: nil, params: nil, json: nil, data: nil)
  # For POST with JSON body, we should use the 'json' parameter (not 'body')
  client = base_service_client

  client.request(
    method: "POST",
    url: path,
    headers: headers(true),
    json: metering_data # Use 'json' parameter for JSON body
  )
end

.reset!void

This method returns an undefined value.

Reset the ApiManager state (useful for testing)

Clears all cached instances, forcing re-initialization on next use.

Examples:

ApiManager.reset!
# All instances cleared, will be recreated on next access


263
264
265
266
267
# File 'lib/ibm_appconfiguration_ruby_sdk/core/api_manager.rb', line 263

def reset!
  @iam_authenticator = nil
  @base_service_client = nil
  @url_builder = nil
end

.set_authenticatorvoid

This method returns an undefined value.

Sets the IAM Authenticator using the API key from UrlBuilder

This method initializes the IBM Cloud IAM authenticator with the API key and IAM URL configured in the UrlBuilder singleton.

Examples:

url_builder = UrlBuilder.instance
url_builder.apikey = 'your-api-key'
url_builder.region = 'us-south'
ApiManager.set_authenticator

Raises:

  • (StandardError)

    If UrlBuilder is not properly configured



89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
# File 'lib/ibm_appconfiguration_ruby_sdk/core/api_manager.rb', line 89

def set_authenticator
  @url_builder = UrlBuilder.instance

  # Create authenticator with apikey and optional URL
  authenticator_options = {
    apikey: @url_builder.apikey
  }

  # Add URL if it's not the default production URL
  # Check for test/staging environment (iam.test.cloud.ibm.com) or custom URLs
  iam_url = @url_builder.iam_url
  default_prod_url = "#{UrlBuilder::HTTPS_PROTOCOL}#{UrlBuilder::IAM_PROD_URL}"

  if iam_url && iam_url != default_prod_url
    authenticator_options[:url] = iam_url
    puts "🔧 Using custom IAM URL: #{iam_url}"
  else
    puts "🔧 Using default IAM URL: #{default_prod_url}"
  end

  @iam_authenticator = IBMCloudSdkCore::IamAuthenticator.new(authenticator_options)
end

.tokenString

Get the IAM bearer token for WebSocket authentication

This method authenticates with IAM and retrieves the bearer token that can be used for WebSocket connections.

Examples:

token = ApiManager.token
# => "Bearer eyJraWQiOiIyMDIxMDQyNjE4..."

# Use with WebSocket connection
headers = { 'Authorization' => token }

Returns:

  • (String)

    The Bearer token (format: “Bearer <token>”)

Raises:

  • (StandardError)

    If authentication fails



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
# File 'lib/ibm_appconfiguration_ruby_sdk/core/api_manager.rb', line 169

def token
  raise "Authenticator not set. Call set_authenticator first." if @iam_authenticator.nil?

  begin
    # Create an empty request hash - the SDK will populate it
    request = {}

    # Force token refresh by setting force_refresh option
    # This ensures we get a fresh token, especially important for reconnections
    # The IBM Cloud SDK Core will check token expiration and refresh if needed
    @iam_authenticator.authenticate(request)

    # The Ruby SDK puts the Authorization header directly in the request hash
    # Try both string and symbol keys for compatibility
    authorization = request["Authorization"] || request[:Authorization]

    raise StandardError.new("Authentication succeeded but no Authorization header was set. Request: #{request.inspect}") if authorization.nil?

    # Log token info for debugging (first 20 chars only for security)
    token_preview = authorization[0..19] if authorization
    puts "🔑 Token obtained: #{token_preview}..."

    authorization
  rescue StandardError => e
    error_msg = "Failed to get authentication token for websocket connect. Error: #{e.message}"
    puts "❌ Token error details: #{e.class.name} - #{e.message}"
    puts "   Backtrace: #{e.backtrace.first(3).join("\n   ")}" if e.backtrace
    raise StandardError.new(error_msg)
  end
end