Module: OCI::Regions

Defined in:
lib/oci/regions.rb

Overview

Module defining available regions and helper methods to get value service endpoints

Constant Summary collapse

REGION_ENUM =
[
  REGION_AP_CHIYODA_1 = 'ap-chiyoda-1'.freeze,
  REGION_AP_CHUNCHEON_1 = 'ap-chuncheon-1'.freeze,
  REGION_AP_HYDERABAD_1 = 'ap-hyderabad-1'.freeze,
  REGION_AP_MUMBAI_1 = 'ap-mumbai-1'.freeze,
  REGION_AP_MELBOURNE_1 = 'ap-melbourne-1'.freeze,
  REGION_AP_OSAKA_1 = 'ap-osaka-1'.freeze,
  REGION_AP_SEOUL_1 = 'ap-seoul-1'.freeze,
  REGION_AP_SYDNEY_1 = 'ap-sydney-1'.freeze,
  REGION_AP_TOKYO_1 = 'ap-tokyo-1'.freeze,
  REGION_CA_MONTREAL_1 = 'ca-montreal-1'.freeze,
  REGION_CA_TORONTO_1 = 'ca-toronto-1'.freeze,
  REGION_EU_AMSTERDAM_1 = 'eu-amsterdam-1'.freeze,
  REGION_EU_FRANKFURT_1 = 'eu-frankfurt-1'.freeze,
  REGION_EU_ZURICH_1 = 'eu-zurich-1'.freeze,
  REGION_ME_JEDDAH_1 = 'me-jeddah-1'.freeze,
  REGION_SA_SAOPAULO_1 = 'sa-saopaulo-1'.freeze,
  REGION_UK_GOV_LONDON_1 = 'uk-gov-london-1'.freeze,
  REGION_UK_LONDON_1 = 'uk-london-1'.freeze,
  REGION_US_PHOENIX_1 = 'us-phoenix-1'.freeze,
  REGION_US_ASHBURN_1 = 'us-ashburn-1'.freeze,
  REGION_US_LANGLEY_1 = 'us-langley-1'.freeze,
  REGION_US_LUKE_1 = 'us-luke-1'.freeze,
  REGION_US_GOV_ASHBURN_1 = 'us-gov-ashburn-1'.freeze,
  REGION_US_GOV_PHOENIX_1 = 'us-gov-phoenix-1'.freeze,
  REGION_US_GOV_CHICAGO_1 = 'us-gov-chicago-1'.freeze
]
REGION_SHORT_NAMES_TO_LONG_NAMES =
{
  'ams': REGION_EU_AMSTERDAM_1,
  'bom': REGION_AP_MUMBAI_1,
  'fra': REGION_EU_FRANKFURT_1,
  'gru': REGION_SA_SAOPAULO_1,
  'hyd': REGION_AP_HYDERABAD_1,
  'iad': REGION_US_ASHBURN_1,
  'icn': REGION_AP_SEOUL_1,
  'jed': REGION_ME_JEDDAH_1,
  'kix': REGION_AP_OSAKA_1,
  'lhr': REGION_UK_LONDON_1,
  'ltn': REGION_UK_GOV_LONDON_1,
  'mel': REGION_AP_MELBOURNE_1,
  'nja': REGION_AP_CHIYODA_1,
  'nrt': REGION_AP_TOKYO_1,
  'phx': REGION_US_PHOENIX_1,
  'syd': REGION_AP_SYDNEY_1,
  'yny': REGION_AP_CHUNCHEON_1,
  'yul': REGION_CA_MONTREAL_1,
  'yyz': REGION_CA_TORONTO_1,
  'zrh': REGION_EU_ZURICH_1
}
REGION_REALM_MAPPING =

— Start of region realm mapping —

{
  'ap-chiyoda-1': 'oc8'.freeze,
  'ap-chuncheon-1': 'oc1'.freeze,
  'ap-hyderabad-1': 'oc1'.freeze,
  'ap-mumbai-1': 'oc1'.freeze,
  'ap-melbourne-1': 'oc1'.freeze,
  'ap-osaka-1': 'oc1'.freeze,
  'ap-seoul-1': 'oc1'.freeze,
  'ap-sydney-1': 'oc1'.freeze,
  'ap-tokyo-1': 'oc1'.freeze,
  'ca-montreal-1': 'oc1'.freeze,
  'ca-toronto-1': 'oc1'.freeze,
  'eu-amsterdam-1': 'oc1'.freeze,
  'eu-frankfurt-1': 'oc1'.freeze,
  'eu-zurich-1': 'oc1'.freeze,
  'me-jeddah-1': 'oc1'.freeze,
  'sa-saopaulo-1': 'oc1'.freeze,
  'uk-gov-london-1': 'oc4'.freeze,
  'uk-london-1': 'oc1'.freeze,
  'us-phoenix-1': 'oc1'.freeze,
  'us-ashburn-1': 'oc1'.freeze,
  'us-langley-1': 'oc2'.freeze,
  'us-luke-1': 'oc2'.freeze,
  'us-gov-ashburn-1': 'oc3'.freeze,
  'us-gov-phoenix-1': 'oc3'.freeze,
  'us-gov-chicago-1': 'oc3'.freeze
}
REALM_DOMAIN_MAPPING =

— Start of realm domain mapping —

{
  'oc1': 'oraclecloud.com'.freeze,
  'oc2': 'oraclegovcloud.com'.freeze,
  'oc3': 'oraclegovcloud.com'.freeze,
  'oc4': 'oraclegovcloud.uk'.freeze,
  'oc8': 'oraclecloud8.com'.freeze
}
SERVICE_ENDPOINT_PREFIX_MAPPING =

— Start of service prefixes —

{
  AnnouncementClient: 'announcements',
  AuditClient: 'audit',
  Auth: 'auth',
  AutoScalingClient: 'autoscaling',
  BlockstorageClient: 'iaas',
  BudgetClient: 'usage',
  ComputeClient: 'iaas',
  ComputeManagementClient: 'iaas',
  ContainerEngineClient: 'containerengine',
  DatabaseClient: 'database',
  DnsClient: 'dns',
  EmailClient: 'email',
  FileStorageClient: 'filestorage',
  HealthChecksClient: 'healthchecks',
  IdentityClient: 'identity',
  KmsVaultClient: 'kms',
  LoadBalancerClient: 'iaas',
  MonitoringClient: 'telemetry',
  NotificationControlPlaneClient: 'notification',
  NotificationDataPlaneClient: 'notification',
  ObjectStorageClient: 'objectstorage',
  ResourceManagerClient: 'resourcemanager',
  ResourceSearchClient: 'query',
  StreamAdminClient: 'streams',
  StreamClient: 'streams',
  VirtualNetworkClient: 'iaas',
  WaasClient: 'waas'
}.freeze
REGION_METADATA_KEYS =

Region Metadata schema keys

%w[realmKey realmDomainComponent regionKey regionIdentifier].freeze
OCI_REGION_METADATA_VAR_NAME =

Region metadata environment variable name

'OCI_REGION_METADATA'.freeze
REGION_METADATA_CFG_FILE_LOCATION =

Region Metadata Configuration File location

"#{Dir.home}/.oci/regions-config.json".freeze

Class Method Summary collapse

Class Method Details

.check_and_add_region_metadata(region) ⇒ Object

If the region information is not available in the existing maps, following sources are checked in order: 1. Regions Configuration File at ~/.oci/regions-config.json 2. Region Metadata Environment variable 3. Instance Metadata Service

The region metadata schema is: { “realmKey” : string, “realmDomainComponent” : string, “regionKey” : string, “regionIdentifier” : string }

If the region still cannot be resolved, we fall back to OC1 realm



240
241
242
243
244
245
246
# File 'lib/oci/regions.rb', line 240

def self.(region)
  # Follow the hierarchy of sources
  return if valid_region?(region)
  return if !@has_read_cfg_file && (region)
  return if !@has_read_env_var && (region)
  return if @opt_in_for_imds && !@has_read_imds && (region)
end

.check_valid_schema(region_metadata) ⇒ Object



335
336
337
338
339
340
341
342
343
344
345
346
347
348
# File 'lib/oci/regions.rb', line 335

def self.check_valid_schema()
  REGION_METADATA_KEYS.each do |key|
    unless .key? key
      OCI.logger.debug("Key #{key} not found in region metadata") if OCI.logger
      return false
    end

    if [key].nil? || [key].empty?
      OCI.logger.debug("Value for key #{key} in region metadata is empty") if OCI.logger
      return false
    end
  end
  true
end

.enable_instance_metadata_serviceObject



365
366
367
# File 'lib/oci/regions.rb', line 365

def self.
  @opt_in_for_imds = true
end

.format_endpoint(prefix, region) ⇒ Object



197
198
199
200
# File 'lib/oci/regions.rb', line 197

def self.format_endpoint(prefix, region)
  second_level_domain = get_second_level_domain(region)
  "https://#{prefix}.#{region}.#{second_level_domain}"
end

.get_second_level_domain(region) ⇒ String

Returns a second level domain for the given region.

Parameters:

  • region (String)

    A region used to get the second level domain. This will usually correspond to a value in REGION_ENUM, but may be an arbitrary string.

Returns:

  • (String)

    A second level domain for given region, default to oraclecloud.com



208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
# File 'lib/oci/regions.rb', line 208

def self.get_second_level_domain(region)
  symbolised_region = region.to_sym

  # get realm from region, default to oc1
  realm = if REGION_REALM_MAPPING.key?(symbolised_region)
            REGION_REALM_MAPPING[symbolised_region]
          else
            'oc1'
          end

  # return second level domain if exists
  symbolised_realm = realm.to_sym

  return REALM_DOMAIN_MAPPING[symbolised_realm] if REALM_DOMAIN_MAPPING.key?(symbolised_realm)

  REALM_DOMAIN_MAPPING[:oc1]
end

.get_service_endpoint(region, service) ⇒ String

Returns an endpoint for the given region and service.

Parameters:

  • region (String)

    A region used to determine the service endpoint. This will usually correspond to a value in REGION_ENUM, but may be an arbitrary string.

  • service (Symbol)

    A symbol representing a service client class (e.g. :IdentityClient)

Returns:

  • (String)

    A fully qualified endpoint



160
161
162
163
164
165
166
167
168
# File 'lib/oci/regions.rb', line 160

def self.get_service_endpoint(region, service)
  # check if the region exists in config file, environment variable or region meta_data_service
  # and add it to the existing map of regions.
  (region)
  prefix = SERVICE_ENDPOINT_PREFIX_MAPPING[service]
  raise "Service '#{service}' is not supported." unless prefix

  format_endpoint(prefix, region)
end

.get_service_endpoint_for_template(region, endpoint_template) ⇒ String

Returns an endpoint for the given region and service endpoint template.

Parameters:

  • region (String)

    A region used to determine the service endpoint. This will usually correspond to a value in REGION_ENUM, but may be an arbitrary string.

  • endpoint_template (String)

    A service endpoint template defined by service team in spec.

Returns:

  • (String)

    A fully qualified endpoint



177
178
179
180
181
182
183
184
185
186
187
188
189
# File 'lib/oci/regions.rb', line 177

def self.get_service_endpoint_for_template(region, endpoint_template)
  # check if the region exists in config file, environment variable or region meta_data_service
  # and add it to the existing map of regions.
  (region)
  endpoint = endpoint_template.clone

  # replace the token inside service_endpoint_template if exists
  [
    ['{region}', region],
    ['{secondLevelDomain}', get_second_level_domain(region).to_s]
  ].each { |k, v| endpoint.sub!(k, v) }
  endpoint
end

.read_metadata(metadata_env) ⇒ Object



331
332
333
# File 'lib/oci/regions.rb', line 331

def self.()
  JSON.parse()
end

.region_from_instance_metadata_service(region) ⇒ Object

Read region from instance metadata service



278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
# File 'lib/oci/regions.rb', line 278

def self.(region)
  @has_read_imds = true

  region_info = {}
  begin
    url = OCI::Auth::Signers::InstancePrincipalsSecurityTokenSigner::GET_REGION_INFO_URL
    uri_region_info = URI(url)
    region_info_client = Net::HTTP.new(uri_region_info.hostname, uri_region_info.port)
    # region_info_client.max_retries = 0
    region_info_client.open_timeout = 10
    region_info_client.read_timeout = 60
    region_info_client.request(OCI::Auth::Util.(url, 'get')) do |response|
      return false unless response.is_a? Net::HTTPSuccess

      region_info = (response.body)
    end
  rescue JSON::ParserError
    OCI.logger.debug('Failed to parse json from regionInfo endpoint') if OCI.logger
    return false
  end

  if check_valid_schema(region_info)
    region_info.each { |_k, v| v.downcase! }
    return update_regions_map(region_info, region)
  end

  false
end

.region_metadata_from_cfg_file(region) ⇒ Object

Read region from metadata config file



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
# File 'lib/oci/regions.rb', line 249

def self.(region)
  @has_read_cfg_file = true
  config_file_location = File.expand_path(REGION_METADATA_CFG_FILE_LOCATION)
  unless File.file?(config_file_location)
    OCI.logger.debug('Config file does not exist.') if OCI.logger
    return false
  end

  begin
    file_hash = File.read(config_file_location)
     = (file_hash)
  rescue JSON::ParserError
    OCI.logger.debug('Failed to parse json file ' + config_file_location) if OCI.logger
    return false
  end

  # boolean flag to confirm if the region is found in the metadata array
  has_found_region = false
  .each do ||
    next unless check_valid_schema()

    .each { |_k, v| v.downcase! }
    has_region = update_regions_map(, region)
    has_found_region ||= has_region
  end
  has_found_region
end

.region_metadata_from_env_var(region) ⇒ Object

This method adds Region metadata info from OCI_REGION_METADATA environment variable to list of existing regions if the region does not exists already.



309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
# File 'lib/oci/regions.rb', line 309

def self.(region)
  begin
    @has_read_env_var = true
     = ENV[OCI_REGION_METADATA_VAR_NAME]

    # Empty value for environment variable OCI_REGION_METADATA
    return false if .nil? || .empty?

     = ()
  rescue JSON::ParserError
    OCI.logger.debug('Failed to parse json from environment variable ' + OCI_REGION_METADATA_VAR_NAME) if OCI.logger
    return false
  end

  if check_valid_schema()
    .each { |_k, v| v.downcase! }
    return update_regions_map(, region)
  end

  false
end

.reset_imds_settingsObject



369
370
371
372
# File 'lib/oci/regions.rb', line 369

def self.reset_imds_settings
  @opt_in_for_imds = false
  @has_read_imds = false
end

.update_regions_map(metadata, region) ⇒ Object



350
351
352
353
354
355
356
357
358
359
360
361
362
363
# File 'lib/oci/regions.rb', line 350

def self.update_regions_map(, region)
  region_identifier = ['regionIdentifier']
  realm_key = ['realmKey']
  region_key = ['regionKey']
  realm_domain_component = ['realmDomainComponent']

  # Add region
  REGION_ENUM.push(region_identifier) unless REGION_ENUM.include?(region_identifier)
  REGION_SHORT_NAMES_TO_LONG_NAMES[region_key.to_sym] ||= region_identifier
  REALM_DOMAIN_MAPPING[realm_key.to_sym] ||= realm_domain_component
  REGION_REALM_MAPPING[region_identifier.to_sym] ||= realm_key

  REGION_ENUM.include? region
end

.valid_region?(region) ⇒ Boolean

Returns:

  • (Boolean)

    Returns true if the given string corresponds to a known region, as defined in



193
194
195
# File 'lib/oci/regions.rb', line 193

def self.valid_region?(region)
  REGION_ENUM.include? region
end