Module: OCI::Regions

Defined in:
lib/oci/regions.rb,
lib/oci/regions_definitions.rb
more...

Overview

Module defining available regions

Constant Summary collapse

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
DEFAULT_REALM_ENV_VAR =

Default Realm environment variable name

'OCI_DEFAULT_REALM'.freeze
REGION_ENUM =
[
  REGION_AP_CHUNCHEON_1 = 'ap-chuncheon-1'.freeze,
  REGION_AP_HYDERABAD_1 = 'ap-hyderabad-1'.freeze,
  REGION_AP_MELBOURNE_1 = 'ap-melbourne-1'.freeze,
  REGION_AP_MUMBAI_1 = 'ap-mumbai-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_ME_DUBAI_1 = 'me-dubai-1'.freeze,
  REGION_SA_SAOPAULO_1 = 'sa-saopaulo-1'.freeze,
  REGION_UK_CARDIFF_1 = 'uk-cardiff-1'.freeze,
  REGION_UK_LONDON_1 = 'uk-london-1'.freeze,
  REGION_US_ASHBURN_1 = 'us-ashburn-1'.freeze,
  REGION_US_PHOENIX_1 = 'us-phoenix-1'.freeze,
  REGION_US_SANJOSE_1 = 'us-sanjose-1'.freeze,
  REGION_SA_VINHEDO_1 = 'sa-vinhedo-1'.freeze,
  REGION_SA_SANTIAGO_1 = 'sa-santiago-1'.freeze,
  REGION_IL_JERUSALEM_1 = 'il-jerusalem-1'.freeze,
  REGION_EU_MARSEILLE_1 = 'eu-marseille-1'.freeze,
  REGION_AP_SINGAPORE_1 = 'ap-singapore-1'.freeze,
  REGION_ME_ABUDHABI_1 = 'me-abudhabi-1'.freeze,
  REGION_EU_MILAN_1 = 'eu-milan-1'.freeze,
  REGION_EU_STOCKHOLM_1 = 'eu-stockholm-1'.freeze,
  REGION_AF_JOHANNESBURG_1 = 'af-johannesburg-1'.freeze,
  REGION_EU_PARIS_1 = 'eu-paris-1'.freeze,
  REGION_MX_QUERETARO_1 = 'mx-queretaro-1'.freeze,
  REGION_EU_MADRID_1 = 'eu-madrid-1'.freeze,
  REGION_US_CHICAGO_1 = 'us-chicago-1'.freeze,
  REGION_MX_MONTERREY_1 = 'mx-monterrey-1'.freeze,
  REGION_US_SALTLAKE_2 = 'us-saltlake-2'.freeze,
  REGION_SA_BOGOTA_1 = 'sa-bogota-1'.freeze,
  REGION_SA_VALPARAISO_1 = 'sa-valparaiso-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_CHICAGO_1 = 'us-gov-chicago-1'.freeze,
  REGION_US_GOV_PHOENIX_1 = 'us-gov-phoenix-1'.freeze,
  REGION_UK_GOV_LONDON_1 = 'uk-gov-london-1'.freeze,
  REGION_UK_GOV_CARDIFF_1 = 'uk-gov-cardiff-1'.freeze,
  REGION_AP_CHIYODA_1 = 'ap-chiyoda-1'.freeze,
  REGION_AP_IBARAKI_1 = 'ap-ibaraki-1'.freeze,
  REGION_ME_DCC_MUSCAT_1 = 'me-dcc-muscat-1'.freeze,
  REGION_AP_DCC_CANBERRA_1 = 'ap-dcc-canberra-1'.freeze,
  REGION_EU_DCC_MILAN_1 = 'eu-dcc-milan-1'.freeze,
  REGION_EU_DCC_MILAN_2 = 'eu-dcc-milan-2'.freeze,
  REGION_EU_DCC_DUBLIN_2 = 'eu-dcc-dublin-2'.freeze,
  REGION_EU_DCC_RATING_2 = 'eu-dcc-rating-2'.freeze,
  REGION_EU_DCC_RATING_1 = 'eu-dcc-rating-1'.freeze,
  REGION_EU_DCC_DUBLIN_1 = 'eu-dcc-dublin-1'.freeze,
  REGION_AP_DCC_GAZIPUR_1 = 'ap-dcc-gazipur-1'.freeze,
  REGION_EU_MADRID_2 = 'eu-madrid-2'.freeze,
  REGION_EU_FRANKFURT_2 = 'eu-frankfurt-2'.freeze,
  REGION_EU_JOVANOVAC_1 = 'eu-jovanovac-1'.freeze,
  REGION_ME_DCC_DOHA_1 = 'me-dcc-doha-1'.freeze,
  REGION_EU_DCC_ZURICH_1 = 'eu-dcc-zurich-1'.freeze,
  REGION_ME_ABUDHABI_3 = 'me-abudhabi-3'.freeze
]
REGION_SHORT_NAMES_TO_LONG_NAMES =
{
  'yny': REGION_AP_CHUNCHEON_1,
  'hyd': REGION_AP_HYDERABAD_1,
  'mel': REGION_AP_MELBOURNE_1,
  'bom': REGION_AP_MUMBAI_1,
  'kix': REGION_AP_OSAKA_1,
  'icn': REGION_AP_SEOUL_1,
  'syd': REGION_AP_SYDNEY_1,
  'nrt': REGION_AP_TOKYO_1,
  'yul': REGION_CA_MONTREAL_1,
  'yyz': REGION_CA_TORONTO_1,
  'ams': REGION_EU_AMSTERDAM_1,
  'fra': REGION_EU_FRANKFURT_1,
  'zrh': REGION_EU_ZURICH_1,
  'jed': REGION_ME_JEDDAH_1,
  'dxb': REGION_ME_DUBAI_1,
  'gru': REGION_SA_SAOPAULO_1,
  'cwl': REGION_UK_CARDIFF_1,
  'lhr': REGION_UK_LONDON_1,
  'iad': REGION_US_ASHBURN_1,
  'phx': REGION_US_PHOENIX_1,
  'sjc': REGION_US_SANJOSE_1,
  'vcp': REGION_SA_VINHEDO_1,
  'scl': REGION_SA_SANTIAGO_1,
  'mtz': REGION_IL_JERUSALEM_1,
  'mrs': REGION_EU_MARSEILLE_1,
  'sin': REGION_AP_SINGAPORE_1,
  'auh': REGION_ME_ABUDHABI_1,
  'lin': REGION_EU_MILAN_1,
  'arn': REGION_EU_STOCKHOLM_1,
  'jnb': REGION_AF_JOHANNESBURG_1,
  'cdg': REGION_EU_PARIS_1,
  'qro': REGION_MX_QUERETARO_1,
  'mad': REGION_EU_MADRID_1,
  'ord': REGION_US_CHICAGO_1,
  'mty': REGION_MX_MONTERREY_1,
  'aga': REGION_US_SALTLAKE_2,
  'bog': REGION_SA_BOGOTA_1,
  'vap': REGION_SA_VALPARAISO_1,
  'lfi': REGION_US_LANGLEY_1,
  'luf': REGION_US_LUKE_1,
  'ric': REGION_US_GOV_ASHBURN_1,
  'pia': REGION_US_GOV_CHICAGO_1,
  'tus': REGION_US_GOV_PHOENIX_1,
  'ltn': REGION_UK_GOV_LONDON_1,
  'brs': REGION_UK_GOV_CARDIFF_1,
  'nja': REGION_AP_CHIYODA_1,
  'ukb': REGION_AP_IBARAKI_1,
  'mct': REGION_ME_DCC_MUSCAT_1,
  'wga': REGION_AP_DCC_CANBERRA_1,
  'bgy': REGION_EU_DCC_MILAN_1,
  'mxp': REGION_EU_DCC_MILAN_2,
  'snn': REGION_EU_DCC_DUBLIN_2,
  'dtm': REGION_EU_DCC_RATING_2,
  'dus': REGION_EU_DCC_RATING_1,
  'ork': REGION_EU_DCC_DUBLIN_1,
  'dac': REGION_AP_DCC_GAZIPUR_1,
  'vll': REGION_EU_MADRID_2,
  'str': REGION_EU_FRANKFURT_2,
  'beg': REGION_EU_JOVANOVAC_1,
  'doh': REGION_ME_DCC_DOHA_1,
  'avz': REGION_EU_DCC_ZURICH_1,
  'ahu': REGION_ME_ABUDHABI_3
}
REGION_REALM_MAPPING =

— Start of region realm mapping —

{
  'ap-chuncheon-1': 'oc1'.freeze,
  'ap-hyderabad-1': 'oc1'.freeze,
  'ap-melbourne-1': 'oc1'.freeze,
  'ap-mumbai-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,
  'me-dubai-1': 'oc1'.freeze,
  'sa-saopaulo-1': 'oc1'.freeze,
  'uk-cardiff-1': 'oc1'.freeze,
  'uk-london-1': 'oc1'.freeze,
  'us-ashburn-1': 'oc1'.freeze,
  'us-phoenix-1': 'oc1'.freeze,
  'us-sanjose-1': 'oc1'.freeze,
  'sa-vinhedo-1': 'oc1'.freeze,
  'sa-santiago-1': 'oc1'.freeze,
  'il-jerusalem-1': 'oc1'.freeze,
  'eu-marseille-1': 'oc1'.freeze,
  'ap-singapore-1': 'oc1'.freeze,
  'me-abudhabi-1': 'oc1'.freeze,
  'eu-milan-1': 'oc1'.freeze,
  'eu-stockholm-1': 'oc1'.freeze,
  'af-johannesburg-1': 'oc1'.freeze,
  'eu-paris-1': 'oc1'.freeze,
  'mx-queretaro-1': 'oc1'.freeze,
  'eu-madrid-1': 'oc1'.freeze,
  'us-chicago-1': 'oc1'.freeze,
  'mx-monterrey-1': 'oc1'.freeze,
  'us-saltlake-2': 'oc1'.freeze,
  'sa-bogota-1': 'oc1'.freeze,
  'sa-valparaiso-1': 'oc1'.freeze,

  'us-langley-1': 'oc2'.freeze,
  'us-luke-1': 'oc2'.freeze,

  'us-gov-ashburn-1': 'oc3'.freeze,
  'us-gov-chicago-1': 'oc3'.freeze,
  'us-gov-phoenix-1': 'oc3'.freeze,

  'uk-gov-london-1': 'oc4'.freeze,
  'uk-gov-cardiff-1': 'oc4'.freeze,

  'ap-chiyoda-1': 'oc8'.freeze,
  'ap-ibaraki-1': 'oc8'.freeze,

  'me-dcc-muscat-1': 'oc9'.freeze,

  'ap-dcc-canberra-1': 'oc10'.freeze,

  'eu-dcc-milan-1': 'oc14'.freeze,
  'eu-dcc-milan-2': 'oc14'.freeze,
  'eu-dcc-dublin-2': 'oc14'.freeze,
  'eu-dcc-rating-2': 'oc14'.freeze,
  'eu-dcc-rating-1': 'oc14'.freeze,
  'eu-dcc-dublin-1': 'oc14'.freeze,

  'ap-dcc-gazipur-1': 'oc15'.freeze,

  'eu-madrid-2': 'oc19'.freeze,
  'eu-frankfurt-2': 'oc19'.freeze,

  'eu-jovanovac-1': 'oc20'.freeze,

  'me-dcc-doha-1': 'oc21'.freeze,

  'eu-dcc-zurich-1': 'oc24'.freeze,

  'me-abudhabi-3': 'oc26'.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,
  'oc9': 'oraclecloud9.com'.freeze,
  'oc10': 'oraclecloud10.com'.freeze,
  'oc14': 'oraclecloud14.com'.freeze,
  'oc15': 'oraclecloud15.com'.freeze,
  'oc19': 'oraclecloud.eu'.freeze,
  'oc20': 'oraclecloud20.com'.freeze,
  'oc21': 'oraclecloud21.com'.freeze,
  'oc24': 'oraclecloud24.com'.freeze,
  'oc26': 'oraclecloud26.com'.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

[View source]

151
152
153
154
155
156
157
# File 'lib/oci/regions.rb', line 151

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

[View source]

246
247
248
249
250
251
252
253
254
255
256
257
258
259
# File 'lib/oci/regions.rb', line 246

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

[View source]

276
277
278
# File 'lib/oci/regions.rb', line 276

def self.
  @opt_in_for_imds = true
end

.format_endpoint(prefix, region) ⇒ Object

[View source]

109
110
111
112
# File 'lib/oci/regions.rb', line 109

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

[View source]

120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
# File 'lib/oci/regions.rb', line 120

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

  # get realm from region, default to oc1
  if REGION_REALM_MAPPING.key?(symbolised_region)
    realm = REGION_REALM_MAPPING[symbolised_region]
    # return second level domain if exists
    symbolised_realm = realm.to_sym
    return REALM_DOMAIN_MAPPING[symbolised_realm] if REALM_DOMAIN_MAPPING.key?(symbolised_realm)
  end

  # check if Default Realm exists in environment env, otherwise return oc1 domain by default
  return ENV[DEFAULT_REALM_ENV_VAR] if ENV.key?(DEFAULT_REALM_ENV_VAR)

  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

[View source]

72
73
74
75
76
77
78
79
80
# File 'lib/oci/regions.rb', line 72

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

[View source]

89
90
91
92
93
94
95
96
97
98
99
100
101
# File 'lib/oci/regions.rb', line 89

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

[View source]

242
243
244
# File 'lib/oci/regions.rb', line 242

def self.()
  JSON.parse()
end

.region_from_instance_metadata_service(region) ⇒ Object

Read region from instance metadata service

[View source]

189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
# File 'lib/oci/regions.rb', line 189

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

[View source]

160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
# File 'lib/oci/regions.rb', line 160

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.

[View source]

220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
# File 'lib/oci/regions.rb', line 220

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

[View source]

280
281
282
283
# File 'lib/oci/regions.rb', line 280

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

.update_regions_map(metadata, region) ⇒ Object

[View source]

261
262
263
264
265
266
267
268
269
270
271
272
273
274
# File 'lib/oci/regions.rb', line 261

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

[View source]

105
106
107
# File 'lib/oci/regions.rb', line 105

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