github.com/IBM-Cloud/bluemix-go@v0.0.0-20240423071914-9e96525baef4/endpoints/endpoints.go (about)

     1  package endpoints
     2  
     3  import (
     4  	"encoding/json"
     5  	"fmt"
     6  	"io/ioutil"
     7  	"log"
     8  	"os"
     9  
    10  	"github.com/IBM-Cloud/bluemix-go/bmxerror"
    11  	"github.com/IBM-Cloud/bluemix-go/helpers"
    12  )
    13  
    14  //EndpointLocator ...
    15  type EndpointLocator interface {
    16  	AccountManagementEndpoint() (string, error)
    17  	CertificateManagerEndpoint() (string, error)
    18  	CFAPIEndpoint() (string, error)
    19  	ContainerEndpoint() (string, error)
    20  	ContainerRegistryEndpoint() (string, error)
    21  	CisEndpoint() (string, error)
    22  	GlobalSearchEndpoint() (string, error)
    23  	GlobalTaggingEndpoint() (string, error)
    24  	IAMEndpoint() (string, error)
    25  	IAMPAPEndpoint() (string, error)
    26  	ICDEndpoint() (string, error)
    27  	MCCPAPIEndpoint() (string, error)
    28  	ResourceManagementEndpoint() (string, error)
    29  	ResourceControllerEndpoint() (string, error)
    30  	ResourceCatalogEndpoint() (string, error)
    31  	UAAEndpoint() (string, error)
    32  	CseEndpoint() (string, error)
    33  	SchematicsEndpoint() (string, error)
    34  	UserManagementEndpoint() (string, error)
    35  	HpcsEndpoint() (string, error)
    36  	FunctionsEndpoint() (string, error)
    37  	SatelliteEndpoint() (string, error)
    38  }
    39  
    40  const (
    41  	//ErrCodeServiceEndpoint ...
    42  	ErrCodeServiceEndpoint = "ServiceEndpointDoesnotExist"
    43  )
    44  
    45  var regionToEndpoint = map[string]map[string]string{
    46  	"cf": {
    47  		"us-south": "https://api.ng.bluemix.net",
    48  		"us-east":  "https://api.us-east.bluemix.net",
    49  		"eu-gb":    "https://api.eu-gb.bluemix.net",
    50  		"au-syd":   "https://api.au-syd.bluemix.net",
    51  		"eu-de":    "https://api.eu-de.bluemix.net",
    52  		"jp-tok":   "https://api.jp-tok.bluemix.net",
    53  	},
    54  	"cr": {
    55  		"us-south": "us.icr.io",
    56  		"us-east":  "us.icr.io",
    57  		"eu-de":    "de.icr.io",
    58  		"au-syd":   "au.icr.io",
    59  		"eu-gb":    "uk.icr.io",
    60  		"jp-tok":   "jp.icr.io",
    61  		"jp-osa":   "jp2.icr.io",
    62  	},
    63  	"uaa": {
    64  		"us-south": "https://iam.cloud.ibm.com/cloudfoundry/login/us-south",
    65  		"us-east":  "https://iam.cloud.ibm.com/cloudfoundry/login/us-east",
    66  		"eu-gb":    "https://iam.cloud.ibm.com/cloudfoundry/login/uk-south",
    67  		"au-syd":   "https://iam.cloud.ibm.com/cloudfoundry/login/ap-south",
    68  		"eu-de":    "https://iam.cloud.ibm.com/cloudfoundry/login/eu-central",
    69  	},
    70  }
    71  var privateRegions = map[string][]string{
    72  	"accounts":              {"us-south", "us-east"},
    73  	"certificate-manager":   {"us-south", "us-east", "eu-gb", "eu-de", "jp-tok", "au-syd", "jp-osa"},
    74  	"icd":                   {"us-south", "us-east", "eu-gb", "eu-de", "jp-tok", "au-syd", "osl01", "seo01", "che01", "ca-tor"},
    75  	"schematics":            {"us-south", "us-east", "eu-de", "eu-gb"},
    76  	"global-search-tagging": {"us-south", "us-east"},
    77  	"container":             {"us-south", "us-east", "eu-gb", "eu-de", "jp-tok", "au-syd", "jp-osa", "ca-tor"},
    78  	"iam":                   {"us-south", "us-east"},
    79  	"resource":              {"us-south", "us-east"},
    80  	"satellite":             {"us-south", "us-east", "eu-gb", "eu-de"},
    81  }
    82  var cloudEndpoint = "cloud.ibm.com"
    83  
    84  func contructEndpoint(subdomain, domain string) string {
    85  	endpoint := fmt.Sprintf("https://%s.%s", subdomain, domain)
    86  	return endpoint
    87  }
    88  
    89  func validateRegion(region string, regionList []string) (string, error) {
    90  	for _, a := range regionList {
    91  		if a == region {
    92  			return a, nil
    93  		}
    94  	}
    95  	return "", fmt.Errorf("The given region %s doesnot support private endpoints", region)
    96  }
    97  
    98  func init() {
    99  	//TODO populate the endpoints which can be retrieved from given endpoints dynamically
   100  	//Example - UAA can be found from the CF endpoint
   101  }
   102  
   103  type endpointLocator struct {
   104  	region        string
   105  	visibility    string
   106  	endpointsFile map[string]interface{}
   107  }
   108  
   109  //NewEndpointLocator ...
   110  func NewEndpointLocator(region, visibility, file string) EndpointLocator {
   111  	var fileMap map[string]interface{}
   112  	if f := helpers.EnvFallBack([]string{"IBMCLOUD_ENDPOINTS_FILE_PATH", "IC_ENDPOINTS_FILE_PATH"}, file); f != "" {
   113  		jsonFile, err := os.Open(f)
   114  		if err != nil {
   115  			log.Fatalf("Unable to open endpoints file %s", err)
   116  		}
   117  		defer jsonFile.Close()
   118  		bytes, err := ioutil.ReadAll(jsonFile)
   119  		if err != nil {
   120  			log.Fatalf("Unable to read endpoints file %s", err)
   121  		}
   122  		err = json.Unmarshal([]byte(bytes), &fileMap)
   123  		if err != nil {
   124  			log.Fatalf("Unable to unmarshal endpoints file %s", err)
   125  		}
   126  	}
   127  	return &endpointLocator{region: region, visibility: visibility, endpointsFile: fileMap}
   128  }
   129  
   130  func (e *endpointLocator) AccountManagementEndpoint() (string, error) {
   131  	//As the current list of regionToEndpoint above is not exhaustive we allow to read endpoints from the env
   132  	endpoint := helpers.EnvFallBack([]string{"IBMCLOUD_ACCOUNT_MANAGEMENT_API_ENDPOINT"}, "")
   133  	if endpoint != "" {
   134  		return endpoint, nil
   135  	}
   136  	if e.endpointsFile != nil && e.visibility != "public-and-private" {
   137  		url := fileFallBack(e.endpointsFile, e.visibility, "IBMCLOUD_ACCOUNT_MANAGEMENT_API_ENDPOINT", e.region, "")
   138  		if url != "" {
   139  			return url, nil
   140  		}
   141  	}
   142  	if e.visibility == "private" || e.visibility == "public-and-private" {
   143  		r, err := validateRegion(e.region, privateRegions["accounts"])
   144  		if err != nil {
   145  			r = "us-south" // As there is no global private endpoint making default region to us-south
   146  			log.Printf("[ WARN ] There is no private endpoint support for this region %s, Defaulting to us-south", e.region)
   147  		}
   148  		return contructEndpoint(fmt.Sprintf("private.%s.accounts", r), cloudEndpoint), nil
   149  	}
   150  	return contructEndpoint("accounts", cloudEndpoint), nil
   151  }
   152  
   153  func (e *endpointLocator) CertificateManagerEndpoint() (string, error) {
   154  	//As the current list of regionToEndpoint above is not exhaustive we allow to read endpoints from the env
   155  	endpoint := helpers.EnvFallBack([]string{"IBMCLOUD_CERTIFICATE_MANAGER_API_ENDPOINT"}, "")
   156  	if endpoint != "" {
   157  		return endpoint, nil
   158  	}
   159  	if e.endpointsFile != nil && e.visibility != "public-and-private" {
   160  		url := fileFallBack(e.endpointsFile, e.visibility, "IBMCLOUD_CERTIFICATE_MANAGER_API_ENDPOINT", e.region, "")
   161  		if url != "" {
   162  			return url, nil
   163  		}
   164  	}
   165  	if e.visibility == "private" {
   166  		return contructEndpoint(fmt.Sprintf("private.%s.certificate-manager", e.region), cloudEndpoint), nil
   167  	}
   168  	if e.visibility == "public-and-private" {
   169  		r, err := validateRegion(e.region, privateRegions["certificate-manager"])
   170  		if err != nil {
   171  			return contructEndpoint(fmt.Sprintf("%s.certificate-manager", e.region), cloudEndpoint), nil
   172  		}
   173  		return contructEndpoint(fmt.Sprintf("private.%s.certificate-manager", r), cloudEndpoint), nil
   174  	}
   175  	return contructEndpoint(fmt.Sprintf("%s.certificate-manager", e.region), cloudEndpoint), nil
   176  }
   177  
   178  func (e *endpointLocator) CFAPIEndpoint() (string, error) {
   179  	//As the current list of regionToEndpoint above is not exhaustive we allow to read endpoints from the env
   180  	endpoint := helpers.EnvFallBack([]string{"IBMCLOUD_CF_API_ENDPOINT"}, "")
   181  	if endpoint != "" {
   182  		return endpoint, nil
   183  	}
   184  	if e.visibility == "private" {
   185  		return "", bmxerror.New(ErrCodeServiceEndpoint, fmt.Sprintf("Private Endpoints is not supported by this service"))
   186  	}
   187  	if ep, ok := regionToEndpoint["cf"][e.region]; ok {
   188  		return ep, nil
   189  	}
   190  	return "", bmxerror.New(ErrCodeServiceEndpoint, fmt.Sprintf("Cloud Foundry endpoint doesn't exist for region: %q", e.region))
   191  }
   192  
   193  func (e *endpointLocator) ContainerEndpoint() (string, error) {
   194  	//As the current list of regionToEndpoint above is not exhaustive we allow to read endpoints from the env
   195  	endpoint := helpers.EnvFallBack([]string{"IBMCLOUD_CS_API_ENDPOINT"}, "")
   196  	if endpoint != "" {
   197  		return endpoint, nil
   198  	}
   199  	if e.endpointsFile != nil && e.visibility != "public-and-private" {
   200  		url := fileFallBack(e.endpointsFile, e.visibility, "IBMCLOUD_CS_API_ENDPOINT", e.region, "")
   201  		if url != "" {
   202  			return url, nil
   203  		}
   204  	}
   205  	if e.visibility == "private" {
   206  		return contructEndpoint(fmt.Sprintf("private.%s.containers", e.region), fmt.Sprintf("%s/global", cloudEndpoint)), nil
   207  	}
   208  	if e.visibility == "public-and-private" {
   209  		r, err := validateRegion(e.region, privateRegions["container"])
   210  		if err != nil {
   211  			return contructEndpoint("containers", fmt.Sprintf("%s/global", cloudEndpoint)), nil
   212  		}
   213  		return contructEndpoint(fmt.Sprintf("private.%s.containers", r), fmt.Sprintf("%s/global", cloudEndpoint)), nil
   214  	}
   215  	return contructEndpoint("containers", fmt.Sprintf("%s/global", cloudEndpoint)), nil
   216  }
   217  
   218  func (e *endpointLocator) SchematicsEndpoint() (string, error) {
   219  	//As the current list of regionToEndpoint above is not exhaustive we allow to read endpoints from the env
   220  	endpoint := helpers.EnvFallBack([]string{"IBMCLOUD_SCHEMATICS_API_ENDPOINT"}, "")
   221  	if endpoint != "" {
   222  		return endpoint, nil
   223  	}
   224  	if e.endpointsFile != nil && e.visibility != "public-and-private" {
   225  		url := fileFallBack(e.endpointsFile, e.visibility, "IBMCLOUD_SCHEMATICS_API_ENDPOINT", e.region, "")
   226  		if url != "" {
   227  			return url, nil
   228  		}
   229  	}
   230  	if e.visibility == "private" || e.visibility == "public-and-private" {
   231  		r, err := validateRegion(e.region, privateRegions["schematics"])
   232  		if err != nil {
   233  			r = "us-south"
   234  			log.Printf("[ WARN ] There is no private endpoint support for this region %s, Defaulting to us-south", e.region)
   235  		}
   236  		if r == "us-south" || r == "us-east" {
   237  			return contructEndpoint("private-us.schematics", cloudEndpoint), nil
   238  		}
   239  		if r == "eu-gb" || r == "eu-de" {
   240  			return contructEndpoint("private-eu.schematics", cloudEndpoint), nil
   241  		}
   242  	}
   243  	return contructEndpoint(fmt.Sprintf("%s.schematics", e.region), cloudEndpoint), nil
   244  }
   245  
   246  func (e *endpointLocator) ContainerRegistryEndpoint() (string, error) {
   247  	//As the current list of regionToEndpoint above is not exhaustive we allow to read endpoints from the env
   248  	endpoint := helpers.EnvFallBack([]string{"IBMCLOUD_CR_API_ENDPOINT"}, "")
   249  	if endpoint != "" {
   250  		return endpoint, nil
   251  	}
   252  	if e.endpointsFile != nil && e.visibility != "public-and-private" {
   253  		url := fileFallBack(e.endpointsFile, e.visibility, "IBMCLOUD_CR_API_ENDPOINT", e.region, "")
   254  		if url != "" {
   255  			return url, nil
   256  		}
   257  	}
   258  	if ep, ok := regionToEndpoint["cr"][e.region]; ok {
   259  		return fmt.Sprintf("https://%s", ep), nil
   260  	}
   261  	if e.visibility == "private" {
   262  		if ep, ok := regionToEndpoint["cr"][e.region]; ok {
   263  			return contructEndpoint("private", ep), nil
   264  		}
   265  		return "", bmxerror.New(ErrCodeServiceEndpoint, fmt.Sprintf("Container Registry private endpoint doesn't exist for region: %q", e.region))
   266  	}
   267  	if e.visibility == "public-and-private" {
   268  		if ep, ok := regionToEndpoint["cr"][e.region]; ok {
   269  			return contructEndpoint("private", ep), nil
   270  		}
   271  		return "", bmxerror.New(ErrCodeServiceEndpoint, fmt.Sprintf("Container Registry endpoint doesn't exist for region: %q", e.region))
   272  	}
   273  	return "", bmxerror.New(ErrCodeServiceEndpoint, fmt.Sprintf("Container Registry endpoint doesn't exist for region: %q", e.region))
   274  }
   275  
   276  // Not used in Provider as we have migrated to go-sdk
   277  func (e *endpointLocator) CisEndpoint() (string, error) {
   278  	//As the current list of regionToEndpoint above is not exhaustive we allow to read endpoints from the env
   279  	endpoint := helpers.EnvFallBack([]string{"IBMCLOUD_CIS_API_ENDPOINT"}, "")
   280  	if endpoint != "" {
   281  		return endpoint, nil
   282  	}
   283  	if e.endpointsFile != nil && e.visibility != "public-and-private" {
   284  		url := fileFallBack(e.endpointsFile, e.visibility, "IBMCLOUD_CIS_API_ENDPOINT", e.region, "")
   285  		if url != "" {
   286  			return url, nil
   287  		}
   288  	}
   289  	if e.visibility == "private" || e.visibility == "public-and-private" {
   290  		return contructEndpoint("api.private.cis", cloudEndpoint), nil
   291  	}
   292  	return contructEndpoint("api.cis", cloudEndpoint), nil
   293  }
   294  
   295  func (e *endpointLocator) GlobalSearchEndpoint() (string, error) {
   296  	//As the current list of regionToEndpoint above is not exhaustive we allow to read endpoints from the env
   297  	endpoint := helpers.EnvFallBack([]string{"IBMCLOUD_GS_API_ENDPOINT"}, "")
   298  	if endpoint != "" {
   299  		return endpoint, nil
   300  	}
   301  	if e.endpointsFile != nil && e.visibility != "public-and-private" {
   302  		url := fileFallBack(e.endpointsFile, e.visibility, "IBMCLOUD_GS_API_ENDPOINT", e.region, "")
   303  		if url != "" {
   304  			return url, nil
   305  		}
   306  	}
   307  	if e.visibility == "private" || e.visibility == "public-and-private" {
   308  		r, err := validateRegion(e.region, privateRegions["global-search-tagging"])
   309  		if err != nil {
   310  			r = "us-south" // As there is no global private endpoint making default region to us-south
   311  			log.Printf("[ WARN ] There is no private endpoint support for this region %s, Defaulting to us-south", e.region)
   312  		}
   313  		return contructEndpoint(fmt.Sprintf("api.private.%s.global-search-tagging", r), cloudEndpoint), nil
   314  	}
   315  	return contructEndpoint("api.global-search-tagging", cloudEndpoint), nil
   316  }
   317  
   318  func (e *endpointLocator) GlobalTaggingEndpoint() (string, error) {
   319  	//As the current list of regionToEndpoint above is not exhaustive we allow to read endpoints from the env
   320  	endpoint := helpers.EnvFallBack([]string{"IBMCLOUD_GT_API_ENDPOINT"}, "")
   321  	if endpoint != "" {
   322  		return endpoint, nil
   323  	}
   324  	if e.endpointsFile != nil && e.visibility != "public-and-private" {
   325  		url := fileFallBack(e.endpointsFile, e.visibility, "IBMCLOUD_GT_API_ENDPOINT", e.region, "")
   326  		if url != "" {
   327  			return url, nil
   328  		}
   329  	}
   330  	if e.visibility == "private" || e.visibility == "public-and-private" {
   331  		r, err := validateRegion(e.region, privateRegions["global-search-tagging"])
   332  		if err != nil {
   333  			r = "us-south" // As there is no global private endpoint making default region to us-south
   334  			log.Printf("[ WARN ] There is no private endpoint support for this region %s, Defaulting to us-south", e.region)
   335  		}
   336  		return contructEndpoint(fmt.Sprintf("tags.private.%s.global-search-tagging", r), cloudEndpoint), nil
   337  	}
   338  	return contructEndpoint("tags.global-search-tagging", cloudEndpoint), nil
   339  }
   340  
   341  func (e *endpointLocator) IAMEndpoint() (string, error) {
   342  	//As the current list of regionToEndpoint above is not exhaustive we allow to read endpoints from the env
   343  	endpoint := helpers.EnvFallBack([]string{"IBMCLOUD_IAM_API_ENDPOINT"}, "")
   344  	if endpoint != "" {
   345  		return endpoint, nil
   346  	}
   347  	if e.endpointsFile != nil && e.visibility != "public-and-private" {
   348  		url := fileFallBack(e.endpointsFile, e.visibility, "IBMCLOUD_IAM_API_ENDPOINT", e.region, "")
   349  		if url != "" {
   350  			return url, nil
   351  		}
   352  	}
   353  	if e.visibility == "private" || e.visibility == "public-and-private" {
   354  		r, err := validateRegion(e.region, privateRegions["iam"])
   355  		if err != nil {
   356  			return contructEndpoint("private.iam", cloudEndpoint), nil
   357  		}
   358  		return contructEndpoint(fmt.Sprintf("private.%s.iam", r), cloudEndpoint), nil
   359  	}
   360  	return contructEndpoint("iam", cloudEndpoint), nil
   361  }
   362  
   363  func (e *endpointLocator) IAMPAPEndpoint() (string, error) {
   364  	//As the current list of regionToEndpoint above is not exhaustive we allow to read endpoints from the env
   365  	endpoint := helpers.EnvFallBack([]string{"IBMCLOUD_IAMPAP_API_ENDPOINT"}, "")
   366  	if endpoint != "" {
   367  		return endpoint, nil
   368  	}
   369  	if e.endpointsFile != nil && e.visibility != "public-and-private" {
   370  		url := fileFallBack(e.endpointsFile, e.visibility, "IBMCLOUD_IAMPAP_API_ENDPOINT", e.region, "")
   371  		if url != "" {
   372  			return url, nil
   373  		}
   374  	}
   375  	if e.visibility == "private" || e.visibility == "public-and-private" {
   376  		r, err := validateRegion(e.region, privateRegions["iam"])
   377  		if err != nil {
   378  			return contructEndpoint("private.iam", cloudEndpoint), nil
   379  		}
   380  		return contructEndpoint(fmt.Sprintf("private.%s.iam", r), cloudEndpoint), nil
   381  	}
   382  	return contructEndpoint("iam", cloudEndpoint), nil
   383  }
   384  
   385  func (e *endpointLocator) ICDEndpoint() (string, error) {
   386  	//As the current list of regionToEndpoint above is not exhaustive we allow to read endpoints from the env
   387  	endpoint := helpers.EnvFallBack([]string{"IBMCLOUD_ICD_API_ENDPOINT"}, "")
   388  	if endpoint != "" {
   389  		return endpoint, nil
   390  	}
   391  	if e.endpointsFile != nil && e.visibility != "public-and-private" {
   392  		url := fileFallBack(e.endpointsFile, e.visibility, "IBMCLOUD_ICD_API_ENDPOINT", e.region, "")
   393  		if url != "" {
   394  			return url, nil
   395  		}
   396  	}
   397  	if e.visibility == "private" {
   398  		return contructEndpoint(fmt.Sprintf("api.%s.private.databases", e.region), cloudEndpoint), nil
   399  	}
   400  	if e.visibility == "public-and-private" {
   401  		r, err := validateRegion(e.region, privateRegions["icd"])
   402  		if err != nil {
   403  			return contructEndpoint(fmt.Sprintf("api.%s.databases", e.region), cloudEndpoint), nil
   404  		}
   405  		return contructEndpoint(fmt.Sprintf("api.%s.private.databases", r), cloudEndpoint), nil
   406  	}
   407  	return contructEndpoint(fmt.Sprintf("api.%s.databases", e.region), cloudEndpoint), nil
   408  }
   409  
   410  func (e *endpointLocator) MCCPAPIEndpoint() (string, error) {
   411  	endpoint := helpers.EnvFallBack([]string{"IBMCLOUD_MCCP_API_ENDPOINT"}, "")
   412  	if endpoint != "" {
   413  		return endpoint, nil
   414  	}
   415  	if e.endpointsFile != nil && e.visibility != "public-and-private" {
   416  		url := fileFallBack(e.endpointsFile, e.visibility, "IBMCLOUD_MCCP_API_ENDPOINT", e.region, "")
   417  		if url != "" {
   418  			return url, nil
   419  		}
   420  	}
   421  	if e.visibility == "private" {
   422  		return "", bmxerror.New(ErrCodeServiceEndpoint, fmt.Sprintf("Private Endpoints is not supported by this service for the region %s", e.region))
   423  	}
   424  	return contructEndpoint(fmt.Sprintf("mccp.%s.cf", e.region), cloudEndpoint), nil
   425  }
   426  
   427  func (e *endpointLocator) ResourceManagementEndpoint() (string, error) {
   428  	endpoint := helpers.EnvFallBack([]string{"IBMCLOUD_RESOURCE_MANAGEMENT_API_ENDPOINT"}, "")
   429  	if endpoint != "" {
   430  		return endpoint, nil
   431  	}
   432  	if e.endpointsFile != nil && e.visibility != "public-and-private" {
   433  		url := fileFallBack(e.endpointsFile, e.visibility, "IBMCLOUD_RESOURCE_MANAGEMENT_API_ENDPOINT", e.region, "")
   434  		if url != "" {
   435  			return url, nil
   436  		}
   437  	}
   438  	if e.visibility == "private" {
   439  		r, err := validateRegion(e.region, privateRegions["resource"])
   440  		if err != nil {
   441  			fmt.Println("Private Endpint supports only us-south and us-east region specific endpoint")
   442  			return contructEndpoint("private.resource-controller", cloudEndpoint), nil
   443  		}
   444  		return contructEndpoint(fmt.Sprintf("private.%s.resource-controller", r), cloudEndpoint), nil
   445  	}
   446  	if e.visibility == "public-and-private" {
   447  		r, err := validateRegion(e.region, privateRegions["resource"])
   448  		if err != nil {
   449  			return contructEndpoint("resource-controller", cloudEndpoint), nil
   450  		}
   451  		return contructEndpoint(fmt.Sprintf("private.%s.resource-controller", r), cloudEndpoint), nil
   452  	}
   453  	return contructEndpoint("resource-controller", cloudEndpoint), nil
   454  }
   455  
   456  func (e *endpointLocator) ResourceControllerEndpoint() (string, error) {
   457  	endpoint := helpers.EnvFallBack([]string{"IBMCLOUD_RESOURCE_CONTROLLER_API_ENDPOINT"}, "")
   458  	if endpoint != "" {
   459  		return endpoint, nil
   460  	}
   461  	if e.endpointsFile != nil && e.visibility != "public-and-private" {
   462  		url := fileFallBack(e.endpointsFile, e.visibility, "IBMCLOUD_RESOURCE_CONTROLLER_API_ENDPOINT", e.region, "")
   463  		if url != "" {
   464  			return url, nil
   465  		}
   466  	}
   467  	if e.visibility == "private" {
   468  		r, err := validateRegion(e.region, privateRegions["resource"])
   469  		if err != nil {
   470  			fmt.Println("Private Endpint supports only us-south and us-east region specific endpoint")
   471  			return contructEndpoint("private.resource-controller", cloudEndpoint), nil
   472  		}
   473  		return contructEndpoint(fmt.Sprintf("private.%s.resource-controller", r), cloudEndpoint), nil
   474  	}
   475  	if e.visibility == "public-and-private" {
   476  		r, err := validateRegion(e.region, privateRegions["resource"])
   477  		if err != nil {
   478  			return contructEndpoint("resource-controller", cloudEndpoint), nil
   479  		}
   480  		return contructEndpoint(fmt.Sprintf("private.%s.resource-controller", r), cloudEndpoint), nil
   481  	}
   482  	return contructEndpoint("resource-controller", cloudEndpoint), nil
   483  }
   484  
   485  func (e *endpointLocator) ResourceCatalogEndpoint() (string, error) {
   486  	endpoint := helpers.EnvFallBack([]string{"IBMCLOUD_RESOURCE_CATALOG_API_ENDPOINT"}, "")
   487  	if endpoint != "" {
   488  		return endpoint, nil
   489  	}
   490  	if e.endpointsFile != nil && e.visibility != "public-and-private" {
   491  		url := fileFallBack(e.endpointsFile, e.visibility, "IBMCLOUD_RESOURCE_CATALOG_API_ENDPOINT", e.region, "")
   492  		if url != "" {
   493  			return url, nil
   494  		}
   495  	}
   496  	if e.visibility == "private" || e.visibility == "public-and-private" {
   497  		r, err := validateRegion(e.region, privateRegions["resource"])
   498  		if err != nil {
   499  			r = "us-south"
   500  		}
   501  		return contructEndpoint(fmt.Sprintf("private.%s.globalcatalog", r), cloudEndpoint), nil
   502  	}
   503  	return contructEndpoint("globalcatalog", cloudEndpoint), nil
   504  }
   505  
   506  func (e *endpointLocator) UAAEndpoint() (string, error) {
   507  	endpoint := helpers.EnvFallBack([]string{"IBMCLOUD_UAA_ENDPOINT"}, "")
   508  	if endpoint != "" {
   509  		return endpoint, nil
   510  	}
   511  	if e.endpointsFile != nil && e.visibility != "public-and-private" {
   512  		url := fileFallBack(e.endpointsFile, e.visibility, "IBMCLOUD_UAA_ENDPOINT", e.region, "")
   513  		if url != "" {
   514  			return url, nil
   515  		}
   516  	}
   517  	if e.visibility == "private" {
   518  		return "", bmxerror.New(ErrCodeServiceEndpoint, fmt.Sprintf("Private Endpoints is not supported by this service for the region %s", e.region))
   519  	}
   520  	if ep, ok := regionToEndpoint["uaa"][e.region]; ok {
   521  		//As the current list of regionToEndpoint above is not exhaustive we allow to read endpoints from the env
   522  		return ep, nil
   523  	}
   524  	return "", bmxerror.New(ErrCodeServiceEndpoint, fmt.Sprintf("UAA endpoint doesn't exist for region: %q", e.region))
   525  }
   526  
   527  func (e *endpointLocator) CseEndpoint() (string, error) {
   528  	endpoint := helpers.EnvFallBack([]string{"IBMCLOUD_CSE_ENDPOINT"}, "")
   529  	if endpoint != "" {
   530  		return endpoint, nil
   531  	}
   532  	if e.endpointsFile != nil && e.visibility != "public-and-private" {
   533  		url := fileFallBack(e.endpointsFile, e.visibility, "IBMCLOUD_CSE_ENDPOINT", e.region, "")
   534  		if url != "" {
   535  			return url, nil
   536  		}
   537  	}
   538  	if e.visibility == "private" {
   539  		return "", bmxerror.New(ErrCodeServiceEndpoint, fmt.Sprintf("Private Endpoints is not supported by this service"))
   540  	}
   541  	return contructEndpoint("api.serviceendpoint", cloudEndpoint), nil
   542  }
   543  
   544  func (e *endpointLocator) UserManagementEndpoint() (string, error) {
   545  	endpoint := helpers.EnvFallBack([]string{"IBMCLOUD_USER_MANAGEMENT_ENDPOINT"}, "")
   546  	if endpoint != "" {
   547  		return endpoint, nil
   548  	}
   549  	if e.endpointsFile != nil && e.visibility != "public-and-private" {
   550  		url := fileFallBack(e.endpointsFile, e.visibility, "IBMCLOUD_USER_MANAGEMENT_ENDPOINT", e.region, "")
   551  		if url != "" {
   552  			return url, nil
   553  		}
   554  	}
   555  	if e.visibility == "private" || e.visibility == "public-and-private" {
   556  		r, err := validateRegion(e.region, privateRegions["resource"])
   557  		if err != nil {
   558  			r = "us-south"
   559  		}
   560  		return contructEndpoint(fmt.Sprintf("private.%s.user-management", r), cloudEndpoint), nil
   561  	}
   562  	return contructEndpoint("user-management", cloudEndpoint), nil
   563  }
   564  
   565  func (e *endpointLocator) HpcsEndpoint() (string, error) {
   566  	endpoint := helpers.EnvFallBack([]string{"IBMCLOUD_HPCS_API_ENDPOINT"}, "")
   567  	if endpoint != "" {
   568  		return endpoint, nil
   569  	}
   570  	if e.endpointsFile != nil && e.visibility != "public-and-private" {
   571  		url := fileFallBack(e.endpointsFile, e.visibility, "IBMCLOUD_HPCS_API_ENDPOINT", e.region, "")
   572  		if url != "" {
   573  			return url, nil
   574  		}
   575  	}
   576  	if e.visibility == "private" {
   577  		return "", bmxerror.New(ErrCodeServiceEndpoint, fmt.Sprintf("Private Endpoints is not supported by this service for the region %s", e.region))
   578  	}
   579  	return fmt.Sprintf("https://%s.broker.hs-crypto.cloud.ibm.com/crypto_v2/", e.region), nil
   580  }
   581  
   582  func (e *endpointLocator) FunctionsEndpoint() (string, error) {
   583  	endpoint := helpers.EnvFallBack([]string{"IBMCLOUD_FUNCTIONS_API_ENDPOINT"}, "")
   584  	if endpoint != "" {
   585  		return endpoint, nil
   586  	}
   587  	if e.endpointsFile != nil && e.visibility != "public-and-private" {
   588  		url := fileFallBack(e.endpointsFile, e.visibility, "IBMCLOUD_FUNCTIONS_API_ENDPOINT", e.region, "")
   589  		if url != "" {
   590  			return url, nil
   591  		}
   592  	}
   593  	if e.visibility == "private" {
   594  		return "", bmxerror.New(ErrCodeServiceEndpoint, fmt.Sprintf("Private Endpoints is not supported by this service for the region %s", e.region))
   595  	}
   596  	return contructEndpoint(fmt.Sprintf("%s.functions", e.region), cloudEndpoint), nil
   597  }
   598  
   599  func (e *endpointLocator) SatelliteEndpoint() (string, error) {
   600  	//As the current list of regionToEndpoint above is not exhaustive we allow to read endpoints from the env
   601  	endpoint := helpers.EnvFallBack([]string{"IBMCLOUD_SAT_API_ENDPOINT"}, "")
   602  	if endpoint != "" {
   603  		return endpoint, nil
   604  	}
   605  	if e.endpointsFile != nil && e.visibility != "public-and-private" {
   606  		url := fileFallBack(e.endpointsFile, e.visibility, "IBMCLOUD_SAT_API_ENDPOINT", e.region, "")
   607  		if url != "" {
   608  			return url, nil
   609  		}
   610  	}
   611  	if e.visibility == "private" {
   612  		return contructEndpoint(fmt.Sprintf("private.%s.api.link.satellite", e.region), fmt.Sprintf("%s", cloudEndpoint)), nil
   613  	}
   614  	if e.visibility == "public-and-private" {
   615  		r, err := validateRegion(e.region, privateRegions["satellite"])
   616  		if err != nil {
   617  			return contructEndpoint("api.link.satellite", fmt.Sprintf("%s", cloudEndpoint)), nil
   618  		}
   619  		return contructEndpoint(fmt.Sprintf("private.%s.api.link.satellite", r), fmt.Sprintf("%s", cloudEndpoint)), nil
   620  	}
   621  	return contructEndpoint("api.link.satellite", fmt.Sprintf("%s", cloudEndpoint)), nil
   622  }
   623  
   624  func fileFallBack(fileMap map[string]interface{}, visibility, key, region, defaultValue string) string {
   625  	if val, ok := fileMap[key]; ok {
   626  		if v, ok := val.(map[string]interface{})[visibility]; ok {
   627  			if r, ok := v.(map[string]interface{})[region]; ok && r.(string) != "" {
   628  				return r.(string)
   629  			}
   630  		}
   631  	}
   632  	return defaultValue
   633  }