4
4
package common
5
5
6
6
import (
7
+ "encoding/json"
7
8
"fmt"
9
+ "io/ioutil"
10
+ "os"
11
+ "path"
8
12
"regexp"
9
13
"strings"
10
14
)
@@ -35,6 +39,8 @@ const (
35
39
RegionAPSeoul1 Region = "ap-seoul-1"
36
40
//RegionAPMumbai1 region for mumbai
37
41
RegionAPMumbai1 Region = "ap-mumbai-1"
42
+ //RegionAPHyderabad1 region for Hyderabad
43
+ RegionAPHyderabad1 Region = "ap-hyderabad-1"
38
44
//RegionAPMelbourne1 region for Melbourne
39
45
RegionAPMelbourne1 Region = "ap-melbourne-1"
40
46
//RegionAPSydney1 region for Sydney
@@ -60,6 +66,25 @@ const (
60
66
RegionUSGovPhoenix1 Region = "us-gov-phoenix-1"
61
67
//RegionUKGovLondon1 gov region London
62
68
RegionUKGovLondon1 Region = "uk-gov-london-1"
69
+
70
+ //RegionUKGovCardiff1 gov region Cardiff
71
+ RegionUKGovCardiff1 Region = "uk-gov-cardiff-1"
72
+
73
+ //RegionUSTacoma1 region for us-tacoma-1
74
+ RegionUSTacoma1 Region = "us-tacoma-1"
75
+
76
+ // Region Metadata Configuration File
77
+ regionMetadataCfgDirName = ".oci"
78
+ regionMetadataCfgFileName = "regions-config.json"
79
+
80
+ // Region Metadata Environment Variable
81
+ regionMetadataEnvVarName = "OCI_REGION_METADATA"
82
+
83
+ // Region Metadata
84
+ regionIdentifierPropertyName = "regionIdentifier" // e.g. "ap-sydney-1"
85
+ realmKeyPropertyName = "realmKey" // e.g. "oc1"
86
+ realmDomainComponentPropertyName = "realmDomainComponent" // e.g. "oraclecloud.com"
87
+ regionKeyPropertyName = "regionKey" // e.g. "SYD"
63
88
)
64
89
65
90
var realm = map [string ]string {
@@ -81,6 +106,7 @@ var regionRealm = map[Region]string{
81
106
RegionAPSeoul1 : "oc1" ,
82
107
RegionAPSydney1 : "oc1" ,
83
108
RegionAPMumbai1 : "oc1" ,
109
+ RegionAPHyderabad1 : "oc1" ,
84
110
RegionAPMelbourne1 : "oc1" ,
85
111
RegionMEJeddah1 : "oc1" ,
86
112
RegionEUZurich1 : "oc1" ,
@@ -100,7 +126,7 @@ func (region Region) Endpoint(service string) string {
100
126
return fmt .Sprintf ("%s.%s.%s" , service , region , region .secondLevelDomain ())
101
127
}
102
128
103
- // EndpointForTemplate returns a endpoint for a service based on template
129
+ // EndpointForTemplate returns a endpoint for a service based on template, only unknown region name can fall back to "oc1", but not short code region name.
104
130
func (region Region ) EndpointForTemplate (service string , serviceEndpointTemplate string ) string {
105
131
if serviceEndpointTemplate == "" {
106
132
return region .Endpoint (service )
@@ -154,6 +180,8 @@ func StringToRegion(stringRegion string) (r Region) {
154
180
r = RegionAPSeoul1
155
181
case "bom" , "ap-mumbai-1" :
156
182
r = RegionAPMumbai1
183
+ case "hyd" , "ap-hyderabad-1" :
184
+ r = RegionAPHyderabad1
157
185
case "mel" , "ap-melbourne-1" :
158
186
r = RegionAPMelbourne1
159
187
case "syd" , "ap-sydney-1" :
@@ -179,8 +207,8 @@ func StringToRegion(stringRegion string) (r Region) {
179
207
case "ltn" , "uk-gov-london-1" :
180
208
r = RegionUKGovLondon1
181
209
default :
182
- r = Region (stringRegion )
183
210
Debugf ("region named: %s, is not recognized" , stringRegion )
211
+ r = checkAndAddRegionMetadata (stringRegion )
184
212
}
185
213
return
186
214
}
@@ -195,3 +223,121 @@ func canStringBeRegion(stringRegion string) (region string, err error) {
195
223
}
196
224
return stringRegion , nil
197
225
}
226
+
227
+ // check region info from original map
228
+ func checkAndAddRegionMetadata (region string ) Region {
229
+ switch {
230
+ case SetRegionMetadataFromCfgFile (& region ):
231
+ case SetRegionMetadataFromEnvVar (& region ):
232
+ case SetRegionFromInstanceMetadataService (& region ):
233
+ default :
234
+ //err := fmt.Errorf("failed to get region metadata information.")
235
+ return Region (region )
236
+ }
237
+ return Region (region )
238
+ }
239
+
240
+ // SetRegionMetadataFromEnvVar checks if region metadata env variable is provided, once it's there, parse and added it to region map
241
+ func SetRegionMetadataFromEnvVar (region * string ) bool {
242
+ // check from env variable
243
+ if jsonStr , existed := os .LookupEnv (regionMetadataEnvVarName ); existed {
244
+ Debugf ("Raw content of region metadata env var:" , jsonStr )
245
+ var regionSchema map [string ]string
246
+ if err := json .Unmarshal ([]byte (jsonStr ), & regionSchema ); err != nil {
247
+ Debugf ("Can't unmarshal env var, the error info is" , err )
248
+ return false
249
+ }
250
+ // check if the specified region is in the env var.
251
+ if checkSchemaItems (regionSchema ) {
252
+ // set mapping table
253
+ addRegionSchema (regionSchema )
254
+ if regionSchema [regionKeyPropertyName ] == * region ||
255
+ regionSchema [regionIdentifierPropertyName ] == * region {
256
+ * region = regionSchema [regionIdentifierPropertyName ]
257
+ return true
258
+ }
259
+ }
260
+ return false
261
+ }
262
+ Debugf ("The Region Metadata Schema wasn't set in env variable - OCI_REGION_METADATA." )
263
+ return false
264
+ }
265
+
266
+ // SetRegionMetadataFromCfgFile checks if region metadata config file is provided, once it's there, parse and added it to region map
267
+ func SetRegionMetadataFromCfgFile (region * string ) bool {
268
+ homeFolder := getHomeFolder ()
269
+ configFile := path .Join (homeFolder , regionMetadataCfgDirName , regionMetadataCfgFileName )
270
+ if jsonArr , ok := readAndParseConfigFile (& configFile ); ok {
271
+ added := false
272
+ for _ , jsonItem := range jsonArr {
273
+ if checkSchemaItems (jsonItem ) {
274
+ addRegionSchema (jsonItem )
275
+ if jsonItem [regionKeyPropertyName ] == * region ||
276
+ jsonItem [regionIdentifierPropertyName ] == * region {
277
+ * region = jsonItem [regionIdentifierPropertyName ]
278
+ added = true
279
+ }
280
+ }
281
+ }
282
+ return added
283
+ }
284
+ return false
285
+ }
286
+
287
+ func readAndParseConfigFile (configFileName * string ) (fileContent []map [string ]string , ok bool ) {
288
+
289
+ if content , err := ioutil .ReadFile (* configFileName ); err == nil {
290
+ Debugf ("Raw content of region metadata config file content:" , string (content [:]))
291
+ if err := json .Unmarshal (content , & fileContent ); err != nil {
292
+ Debugf ("Can't unmarshal env var, the error info is" , err )
293
+ return
294
+ }
295
+ ok = true
296
+ return
297
+ }
298
+ Debugf ("No Region Metadata Config File provided." )
299
+ return
300
+
301
+ }
302
+
303
+ // check map regionRealm's region name, if it's already there, no need to add it.
304
+ func addRegionSchema (regionSchema map [string ]string ) {
305
+ r := Region (strings .ToLower (regionSchema [regionIdentifierPropertyName ]))
306
+ if _ , ok := regionRealm [r ]; ! ok {
307
+ // set mapping table
308
+ realm [regionSchema [realmKeyPropertyName ]] = regionSchema [realmDomainComponentPropertyName ]
309
+ regionRealm [r ] = regionSchema [realmKeyPropertyName ]
310
+ return
311
+ }
312
+ Debugf ("Region {} has already been added, no need to add again." , regionSchema [regionIdentifierPropertyName ])
313
+ }
314
+
315
+ // check region schema content if all the required contents are provided
316
+ func checkSchemaItems (regionSchema map [string ]string ) bool {
317
+ if checkSchemaItem (regionSchema , regionIdentifierPropertyName ) &&
318
+ checkSchemaItem (regionSchema , realmKeyPropertyName ) &&
319
+ checkSchemaItem (regionSchema , realmDomainComponentPropertyName ) &&
320
+ checkSchemaItem (regionSchema , regionKeyPropertyName ) {
321
+ return true
322
+ }
323
+ return false
324
+ }
325
+
326
+ // check region schema item is valid, if so, convert it to lower case.
327
+ func checkSchemaItem (regionSchema map [string ]string , key string ) bool {
328
+ if val , ok := regionSchema [key ]; ok {
329
+ if val != "" {
330
+ regionSchema [key ] = strings .ToLower (val )
331
+ return true
332
+ }
333
+ Debugf ("Region metadata schema {} is provided,but content is empty." , key )
334
+ return false
335
+ }
336
+ Debugf ("Region metadata schema {} is not provided, please update the content" , key )
337
+ return false
338
+ }
339
+
340
+ // SetRegionFromInstanceMetadataService checks if region metadata can be provided from InstanceMetadataService.
341
+ func SetRegionFromInstanceMetadataService (region * string ) bool {
342
+ return false
343
+ }
0 commit comments