github.com/chnsz/golangsdk@v0.0.0-20240506093406-85a3fbfa605b/openstack/client.go (about) 1 package openstack 2 3 import ( 4 "fmt" 5 "net/url" 6 "reflect" 7 "regexp" 8 "strings" 9 10 "github.com/chnsz/golangsdk" 11 tokens2 "github.com/chnsz/golangsdk/openstack/identity/v2/tokens" 12 "github.com/chnsz/golangsdk/openstack/identity/v3/catalog" 13 "github.com/chnsz/golangsdk/openstack/identity/v3/domains" 14 "github.com/chnsz/golangsdk/openstack/identity/v3/projects" 15 tokens3 "github.com/chnsz/golangsdk/openstack/identity/v3/tokens" 16 "github.com/chnsz/golangsdk/openstack/utils" 17 "github.com/chnsz/golangsdk/pagination" 18 ) 19 20 const ( 21 // v2 represents Keystone v2. 22 // It should never increase beyond 2.0. 23 v2 = "v2.0" 24 25 // v3 represents Keystone v3. 26 // The version can be anything from v3 to v3.x. 27 v3 = "v3" 28 29 // provider represents the suffix of endpoint url 30 provider = "myhuaweicloud.com" 31 ) 32 33 /* 34 NewClient prepares an unauthenticated ProviderClient instance. 35 Most users will probably prefer using the AuthenticatedClient function 36 instead. 37 38 This is useful if you wish to explicitly control the version of the identity 39 service that's used for authentication explicitly, for example. 40 41 A basic example of using this would be: 42 43 ao, err := openstack.AuthOptionsFromEnv() 44 provider, err := openstack.NewClient(ao.IdentityEndpoint) 45 client, err := openstack.NewIdentityV3(provider, golangsdk.EndpointOpts{}) 46 */ 47 func NewClient(endpoint string) (*golangsdk.ProviderClient, error) { 48 u, err := url.Parse(endpoint) 49 if err != nil { 50 return nil, err 51 } 52 53 u.RawQuery, u.Fragment = "", "" 54 55 var base string 56 versionRe := regexp.MustCompile("v[0-9.]+/?") 57 if version := versionRe.FindString(u.Path); version != "" { 58 base = strings.Replace(u.String(), version, "", -1) 59 } else { 60 base = u.String() 61 } 62 63 endpoint = golangsdk.NormalizeURL(endpoint) 64 base = golangsdk.NormalizeURL(base) 65 66 p := new(golangsdk.ProviderClient) 67 p.IdentityBase = base 68 p.IdentityEndpoint = endpoint 69 p.UseTokenLock() 70 71 return p, nil 72 } 73 74 /* 75 AuthenticatedClient logs in to an OpenStack cloud found at the identity endpoint 76 specified by the options, acquires a token, and returns a Provider Client 77 instance that's ready to operate. 78 79 If the full path to a versioned identity endpoint was specified (example: 80 http://example.com:5000/v3), that path will be used as the endpoint to query. 81 82 If a versionless endpoint was specified (example: http://example.com:5000/), 83 the endpoint will be queried to determine which versions of the identity service 84 are available, then chooses the most recent or most supported version. 85 86 Example: 87 88 ao, err := openstack.AuthOptionsFromEnv() 89 provider, err := openstack.AuthenticatedClient(ao) 90 client, err := openstack.NewNetworkV2(client, golangsdk.EndpointOpts{ 91 Region: os.Getenv("OS_REGION_NAME"), 92 }) 93 */ 94 func AuthenticatedClient(options golangsdk.AuthOptions) (*golangsdk.ProviderClient, error) { 95 client, err := NewClient(options.IdentityEndpoint) 96 if err != nil { 97 return nil, err 98 } 99 100 err = Authenticate(client, options) 101 if err != nil { 102 return nil, err 103 } 104 return client, nil 105 } 106 107 // Authenticate or re-authenticate against the most recent identity service 108 // supported at the provided endpoint. 109 func Authenticate(client *golangsdk.ProviderClient, options golangsdk.AuthOptionsProvider) error { 110 versions := []*utils.Version{ 111 {ID: v2, Priority: 20, Suffix: "/v2.0/"}, 112 {ID: v3, Priority: 30, Suffix: "/v3/"}, 113 } 114 115 chosen, endpoint, err := utils.ChooseVersion(client, versions) 116 if err != nil { 117 return err 118 } 119 120 authOptions, isTokenAuthOptions := options.(golangsdk.AuthOptions) 121 122 if isTokenAuthOptions { 123 switch chosen.ID { 124 case v2: 125 return v2auth(client, endpoint, authOptions, golangsdk.EndpointOpts{}) 126 case v3: 127 if authOptions.AgencyDomainName != "" && authOptions.AgencyName != "" { 128 return v3authWithAgency(client, endpoint, &authOptions, golangsdk.EndpointOpts{}) 129 } 130 return v3auth(client, endpoint, &authOptions, golangsdk.EndpointOpts{}) 131 default: 132 // The switch statement must be out of date from the versions list. 133 return fmt.Errorf("Unrecognized identity version: %s", chosen.ID) 134 } 135 } else { 136 akskAuthOptions, isAkSkOptions := options.(golangsdk.AKSKAuthOptions) 137 138 if isAkSkOptions { 139 if akskAuthOptions.AgencyDomainName != "" && akskAuthOptions.AgencyName != "" { 140 return authWithAgencyByAKSK(client, endpoint, akskAuthOptions, golangsdk.EndpointOpts{}) 141 } 142 return v3AKSKAuth(client, endpoint, akskAuthOptions, golangsdk.EndpointOpts{}) 143 144 } 145 return fmt.Errorf("Unrecognized auth options provider: %s", reflect.TypeOf(options)) 146 } 147 148 } 149 150 // AuthenticateV2 explicitly authenticates against the identity v2 endpoint. 151 func AuthenticateV2(client *golangsdk.ProviderClient, options golangsdk.AuthOptions, eo golangsdk.EndpointOpts) error { 152 return v2auth(client, "", options, eo) 153 } 154 155 func v2auth(client *golangsdk.ProviderClient, endpoint string, options golangsdk.AuthOptions, eo golangsdk.EndpointOpts) error { 156 v2Client, err := NewIdentityV2(client, eo) 157 if err != nil { 158 return err 159 } 160 161 if endpoint != "" { 162 v2Client.Endpoint = endpoint 163 } 164 165 v2Opts := tokens2.AuthOptions{ 166 IdentityEndpoint: options.IdentityEndpoint, 167 Username: options.Username, 168 Password: options.Password, 169 TenantID: options.TenantID, 170 TenantName: options.TenantName, 171 AllowReauth: options.AllowReauth, 172 TokenID: options.TokenID, 173 } 174 175 result := tokens2.Create(v2Client, v2Opts) 176 177 token, err := result.ExtractToken() 178 if err != nil { 179 return err 180 } 181 182 catalog, err := result.ExtractServiceCatalog() 183 if err != nil { 184 return err 185 } 186 187 if options.AllowReauth { 188 client.ReauthFunc = func() error { 189 client.TokenID = "" 190 return v2auth(client, endpoint, options, eo) 191 } 192 } 193 client.TokenID = token.ID 194 client.ProjectID = token.Tenant.ID 195 client.EndpointLocator = func(opts golangsdk.EndpointOpts) (string, error) { 196 return V2EndpointURL(catalog, opts) 197 } 198 199 return nil 200 } 201 202 // AuthenticateV3 explicitly authenticates against the identity v3 service. 203 func AuthenticateV3(client *golangsdk.ProviderClient, options tokens3.AuthOptionsBuilder, eo golangsdk.EndpointOpts) error { 204 return v3auth(client, "", options, eo) 205 } 206 207 func v3auth(client *golangsdk.ProviderClient, endpoint string, opts tokens3.AuthOptionsBuilder, eo golangsdk.EndpointOpts) error { 208 // Override the generated service endpoint with the one returned by the version endpoint. 209 v3Client, err := NewIdentityV3(client, eo) 210 if err != nil { 211 return err 212 } 213 214 if endpoint != "" { 215 v3Client.Endpoint = endpoint 216 } 217 218 result := tokens3.Create(v3Client, opts) 219 220 token, err := result.ExtractToken() 221 if err != nil { 222 return err 223 } 224 225 project, err := result.ExtractProject() 226 if err != nil { 227 return err 228 } 229 230 catalog, err := result.ExtractServiceCatalog() 231 if err != nil { 232 return err 233 } 234 235 client.TokenID = token.ID 236 if project != nil { 237 client.ProjectID = project.ID 238 client.DomainID = project.Domain.ID 239 } 240 241 if opts.CanReauth() { 242 client.ReauthFunc = func() error { 243 client.TokenID = "" 244 return v3auth(client, endpoint, opts, eo) 245 } 246 } 247 client.EndpointLocator = func(opts golangsdk.EndpointOpts) (string, error) { 248 return V3EndpointURL(catalog, opts) 249 } 250 251 return nil 252 } 253 254 func v3authWithAgency(client *golangsdk.ProviderClient, endpoint string, opts *golangsdk.AuthOptions, eo golangsdk.EndpointOpts) error { 255 if opts.TokenID == "" { 256 err := v3auth(client, endpoint, opts, eo) 257 if err != nil { 258 return err 259 } 260 } else { 261 client.TokenID = opts.TokenID 262 } 263 264 opts1 := golangsdk.AgencyAuthOptions{ 265 AgencyName: opts.AgencyName, 266 AgencyDomainName: opts.AgencyDomainName, 267 DelegatedProject: opts.DelegatedProject, 268 } 269 270 return v3auth(client, endpoint, &opts1, eo) 271 } 272 273 func getEntryByServiceId(entries []tokens3.CatalogEntry, serviceId string) *tokens3.CatalogEntry { 274 if entries == nil { 275 return nil 276 } 277 278 for idx := range entries { 279 if entries[idx].ID == serviceId { 280 return &entries[idx] 281 } 282 } 283 284 return nil 285 } 286 287 func getProjectID(client *golangsdk.ServiceClient, name string) (string, error) { 288 opts := projects.ListOpts{ 289 Name: name, 290 } 291 allPages, err := projects.List(client, opts).AllPages() 292 if err != nil { 293 return "", err 294 } 295 296 projects, err := projects.ExtractProjects(allPages) 297 if err != nil { 298 return "", err 299 } 300 301 if len(projects) < 1 { 302 err := &golangsdk.ErrResourceNotFound{} 303 err.ResourceType = "IAM project ID" 304 err.Name = name 305 return "", err 306 } 307 308 return projects[0].ID, nil 309 } 310 311 func v3AKSKAuth(client *golangsdk.ProviderClient, endpoint string, options golangsdk.AKSKAuthOptions, eo golangsdk.EndpointOpts) error { 312 v3Client, err := NewIdentityV3(client, eo) 313 if err != nil { 314 return err 315 } 316 317 // Override the generated service endpoint with the one returned by the version endpoint. 318 if endpoint != "" { 319 v3Client.Endpoint = endpoint 320 } 321 322 // update AKSKAuthOptions of ProviderClient 323 // ProviderClient(client) is a reference to the ServiceClient(v3Client) 324 defer func() { 325 client.AKSKAuthOptions.ProjectId = options.ProjectId 326 client.AKSKAuthOptions.DomainID = options.DomainID 327 }() 328 329 client.AKSKAuthOptions = options 330 client.AKSKAuthOptions.DomainID = "" 331 332 if options.ProjectId == "" && options.ProjectName != "" { 333 id, err := getProjectID(v3Client, options.ProjectName) 334 if err != nil { 335 return err 336 } 337 options.ProjectId = id 338 client.AKSKAuthOptions.ProjectId = options.ProjectId 339 } 340 341 if options.DomainID == "" && options.Domain != "" { 342 id, err := getDomainID(v3Client, options.Domain) 343 if err != nil { 344 return err 345 } 346 options.DomainID = id 347 } 348 349 if options.BssDomainID == "" && options.BssDomain != "" { 350 id, err := getDomainID(v3Client, options.BssDomain) 351 if err != nil { 352 return err 353 } 354 options.BssDomainID = id 355 } 356 357 client.ProjectID = options.ProjectId 358 client.DomainID = options.BssDomainID 359 360 if !options.WithUserCatalog { 361 var entries = make([]tokens3.CatalogEntry, 0, 1) 362 err = catalog.List(v3Client).EachPage(func(page pagination.Page) (bool, error) { 363 catalogList, err := catalog.ExtractServiceCatalog(page) 364 if err != nil { 365 return false, err 366 } 367 368 entries = append(entries, catalogList...) 369 return true, nil 370 }) 371 372 if err != nil { 373 return err 374 } 375 376 client.EndpointLocator = func(opts golangsdk.EndpointOpts) (string, error) { 377 return V3EndpointURL(&tokens3.ServiceCatalog{ 378 Entries: entries, 379 }, opts) 380 } 381 } 382 383 return nil 384 } 385 386 func authWithAgencyByAKSK(client *golangsdk.ProviderClient, endpoint string, opts golangsdk.AKSKAuthOptions, eo golangsdk.EndpointOpts) error { 387 388 err := v3AKSKAuth(client, endpoint, opts, eo) 389 if err != nil { 390 return err 391 } 392 393 v3Client, err := NewIdentityV3(client, eo) 394 if err != nil { 395 return err 396 } 397 398 if v3Client.AKSKAuthOptions.DomainID == "" { 399 return fmt.Errorf("Must config domain name") 400 } 401 402 opts2 := golangsdk.AgencyAuthOptions{ 403 AgencyName: opts.AgencyName, 404 AgencyDomainName: opts.AgencyDomainName, 405 DelegatedProject: opts.DelegatedProject, 406 } 407 result := tokens3.Create(v3Client, &opts2) 408 token, err := result.ExtractToken() 409 if err != nil { 410 return err 411 } 412 413 project, err := result.ExtractProject() 414 if err != nil { 415 return err 416 } 417 418 catalog, err := result.ExtractServiceCatalog() 419 if err != nil { 420 return err 421 } 422 423 client.TokenID = token.ID 424 if project != nil { 425 client.ProjectID = project.ID 426 } 427 428 client.ReauthFunc = func() error { 429 client.TokenID = "" 430 return authWithAgencyByAKSK(client, endpoint, opts, eo) 431 } 432 433 client.EndpointLocator = func(opts golangsdk.EndpointOpts) (string, error) { 434 return V3EndpointURL(catalog, opts) 435 } 436 437 client.AKSKAuthOptions.AccessKey = "" 438 return nil 439 } 440 441 func getDomainID(client *golangsdk.ServiceClient, name string) (string, error) { 442 old := client.Endpoint 443 defer func() { client.Endpoint = old }() 444 445 client.Endpoint = old + "auth/" 446 447 // the List request does not support query options 448 allPages, err := domains.List(client, nil).AllPages() 449 if err != nil { 450 return "", fmt.Errorf("List domains failed, err=%s", err) 451 } 452 453 all, err := domains.ExtractDomains(allPages) 454 if err != nil { 455 return "", fmt.Errorf("Extract domains failed, err=%s", err) 456 } 457 458 count := len(all) 459 switch count { 460 case 0: 461 err := &golangsdk.ErrResourceNotFound{} 462 err.ResourceType = "IAM domain ID" 463 err.Name = name 464 return "", err 465 case 1: 466 if name != "" && name != all[0].Name { 467 err := &golangsdk.ErrResourceNotFound{} 468 err.ResourceType = "IAM domain ID" 469 err.Name = name 470 return "", err 471 } 472 return all[0].ID, nil 473 default: 474 err := &golangsdk.ErrMultipleResourcesFound{} 475 err.ResourceType = "IAM domain ID" 476 err.Name = name 477 err.Count = count 478 return "", err 479 } 480 } 481 482 // NewIdentityV2 creates a ServiceClient that may be used to interact with the 483 // v2 identity service. 484 func NewIdentityV2(client *golangsdk.ProviderClient, eo golangsdk.EndpointOpts) (*golangsdk.ServiceClient, error) { 485 endpoint := client.IdentityBase + "v2.0/" 486 clientType := "identity" 487 var err error 488 if !reflect.DeepEqual(eo, golangsdk.EndpointOpts{}) { 489 eo.ApplyDefaults(clientType) 490 endpoint, err = client.EndpointLocator(eo) 491 if err != nil { 492 return nil, err 493 } 494 } 495 496 return &golangsdk.ServiceClient{ 497 ProviderClient: client, 498 Endpoint: endpoint, 499 Type: clientType, 500 }, nil 501 } 502 503 // NewIdentityV3 creates a ServiceClient that may be used to access the v3 504 // identity service. 505 func NewIdentityV3(client *golangsdk.ProviderClient, eo golangsdk.EndpointOpts) (*golangsdk.ServiceClient, error) { 506 endpoint := client.IdentityBase + "v3/" 507 clientType := "identity" 508 var err error 509 if !reflect.DeepEqual(eo, golangsdk.EndpointOpts{}) { 510 eo.ApplyDefaults(clientType) 511 endpoint, err = client.EndpointLocator(eo) 512 if err != nil { 513 return nil, err 514 } 515 } 516 517 // Ensure endpoint still has a suffix of v3. 518 // This is because EndpointLocator might have found a versionless 519 // endpoint and requests will fail unless targeted at /v3. 520 if !strings.HasSuffix(endpoint, "v3/") { 521 endpoint = endpoint + "v3/" 522 } 523 524 return &golangsdk.ServiceClient{ 525 ProviderClient: client, 526 Endpoint: endpoint, 527 Type: clientType, 528 }, nil 529 } 530 531 func initClientOpts(client *golangsdk.ProviderClient, eo golangsdk.EndpointOpts, clientType string) (*golangsdk.ServiceClient, error) { 532 sc := new(golangsdk.ServiceClient) 533 eo.ApplyDefaults(clientType) 534 url, err := client.EndpointLocator(eo) 535 if err != nil { 536 return sc, err 537 } 538 sc.ProviderClient = client 539 sc.Endpoint = url 540 sc.Type = clientType 541 return sc, nil 542 } 543 544 // initcommonServiceClient create a ServiceClient which can not get from clientType directly. 545 // firstly, we initialize a service client by "volumev2" type, the endpoint likes https://evs.{region}.{xxx.com}/v2/{project_id} 546 // then we replace the endpoint with the specified srv and version. 547 func initcommonServiceClient(client *golangsdk.ProviderClient, eo golangsdk.EndpointOpts, srv string, version string) (*golangsdk.ServiceClient, error) { 548 sc, err := initClientOpts(client, eo, "volumev2") 549 if err != nil { 550 return nil, err 551 } 552 553 e := strings.Replace(sc.Endpoint, "v2", version, 1) 554 sc.Endpoint = strings.Replace(e, "evs", srv, 1) 555 sc.ResourceBase = sc.Endpoint 556 return sc, err 557 } 558 559 // InitServiceClientByName create a ServiceClient which was assembled by service and region name for huaweicloud. 560 // the endpoint likes https://{eo.Name}.{eo.Region}.myhuaweicloud.com/{apiVersion}/{project_id} 561 func InitServiceClientByName(client *golangsdk.ProviderClient, eo golangsdk.EndpointOpts, apiVersion string) (*golangsdk.ServiceClient, error) { 562 if eo.Name == "" || apiVersion == "" { 563 return nil, fmt.Errorf("must specify the service name and api version") 564 } 565 566 sc := new(golangsdk.ServiceClient) 567 sc.ProviderClient = client 568 sc.Endpoint = fmt.Sprintf("https://%s.%s.%s", eo.Name, eo.Region, provider) 569 sc.ResourceBase = fmt.Sprintf("%s/%s/%s/", sc.Endpoint, apiVersion, client.ProjectID) 570 571 return sc, nil 572 } 573 574 func NewSDKClient(c *golangsdk.ProviderClient, eo golangsdk.EndpointOpts, serviceType string) (*golangsdk.ServiceClient, error) { 575 switch serviceType { 576 case "mls": 577 return NewMLSV1(c, eo) 578 case "dws": 579 return NewDWSClient(c, eo) 580 case "nat": 581 return NewNatV2(c, eo) 582 } 583 584 return initClientOpts(c, eo, serviceType) 585 } 586 587 // ApiGateWayV1 creates a service client that is used for Huawei cloud for API gateway. 588 // TODO: Need to change to apig client type from apig once available 589 func ApiGateWayV1(client *golangsdk.ProviderClient, eo golangsdk.EndpointOpts) (*golangsdk.ServiceClient, error) { 590 sc, err := initClientOpts(client, eo, "network") 591 sc.Endpoint = strings.Replace(sc.Endpoint, "vpc", "apig", 1) 592 sc.ResourceBase = sc.Endpoint + "v1.0/apigw/" 593 return sc, err 594 } 595 596 // NewComputeV2 creates a ServiceClient that may be used with the openstack nova compute v2 package. 597 func NewComputeV2(client *golangsdk.ProviderClient, eo golangsdk.EndpointOpts) (*golangsdk.ServiceClient, error) { 598 return initClientOpts(client, eo, "compute") 599 } 600 601 // NewComputeV1 creates a ServiceClient that may be used with the ecs v1 package. 602 // Deprecated: use NewEcsV1 instead 603 func NewComputeV1(client *golangsdk.ProviderClient, eo golangsdk.EndpointOpts) (*golangsdk.ServiceClient, error) { 604 sc, err := initClientOpts(client, eo, "network") 605 sc.Endpoint = strings.Replace(sc.Endpoint, "vpc", "ecs", 1) 606 sc.Endpoint = sc.Endpoint + "v1/" 607 sc.ResourceBase = sc.Endpoint + client.ProjectID + "/" 608 return sc, err 609 } 610 611 // NewEcsV1 creates a ServiceClient that may be used with the ecs v1 package. 612 func NewEcsV1(client *golangsdk.ProviderClient, eo golangsdk.EndpointOpts) (*golangsdk.ServiceClient, error) { 613 sc, err := initClientOpts(client, eo, "ecs") 614 return sc, err 615 } 616 617 // NewComputeV11 creates a ServiceClient that may be used with the ecs v1.1 package. 618 func NewComputeV11(client *golangsdk.ProviderClient, eo golangsdk.EndpointOpts) (*golangsdk.ServiceClient, error) { 619 sc, err := initClientOpts(client, eo, "ecsv1.1") 620 return sc, err 621 } 622 623 // NewNetworkV2 creates a ServiceClient that may be used with the openstack neutron v2.0 package. 624 func NewNetworkV2(client *golangsdk.ProviderClient, eo golangsdk.EndpointOpts) (*golangsdk.ServiceClient, error) { 625 sc, err := initClientOpts(client, eo, "network") 626 sc.ResourceBase = sc.Endpoint + "v2.0/" 627 return sc, err 628 } 629 630 // NewNetworkV1 creates a ServiceClient that may be used with the vpc v1 package. 631 func NewNetworkV1(client *golangsdk.ProviderClient, eo golangsdk.EndpointOpts) (*golangsdk.ServiceClient, error) { 632 sc, err := initClientOpts(client, eo, "network") 633 sc.ResourceBase = sc.Endpoint + "v1/" 634 return sc, err 635 } 636 637 // NewVPCV1 creates a ServiceClient that may be used with the vpc v1 package. 638 func NewVPCV1(client *golangsdk.ProviderClient, eo golangsdk.EndpointOpts) (*golangsdk.ServiceClient, error) { 639 sc, err := initClientOpts(client, eo, "vpc") 640 return sc, err 641 } 642 643 // NewBlockStorageV1 creates a ServiceClient that may be used to access the v1 644 // block storage service. 645 func NewBlockStorageV1(client *golangsdk.ProviderClient, eo golangsdk.EndpointOpts) (*golangsdk.ServiceClient, error) { 646 return initClientOpts(client, eo, "volume") 647 } 648 649 // NewBlockStorageV2 creates a ServiceClient that may be used to access the v2 650 // block storage service. 651 func NewBlockStorageV2(client *golangsdk.ProviderClient, eo golangsdk.EndpointOpts) (*golangsdk.ServiceClient, error) { 652 return initClientOpts(client, eo, "volumev2") 653 } 654 655 // NewBlockStorageV3 creates a ServiceClient that may be used to access the v3 block storage service. 656 func NewBlockStorageV3(client *golangsdk.ProviderClient, eo golangsdk.EndpointOpts) (*golangsdk.ServiceClient, error) { 657 return initClientOpts(client, eo, "volumev3") 658 } 659 660 // NewSharedFileSystemV2 creates a ServiceClient that may be used to access the v2 shared file system service. 661 func NewSharedFileSystemV2(client *golangsdk.ProviderClient, eo golangsdk.EndpointOpts) (*golangsdk.ServiceClient, error) { 662 return initClientOpts(client, eo, "sharev2") 663 } 664 665 // NewHwSFSV2 creates a service client that is used for Huawei cloud for SFS, it replaces the EVS type. 666 // TODO: Need to change to sfs client type from evs once available 667 func NewHwSFSV2(client *golangsdk.ProviderClient, eo golangsdk.EndpointOpts) (*golangsdk.ServiceClient, error) { 668 sc, err := initClientOpts(client, eo, "network") 669 sc.Endpoint = strings.Replace(sc.Endpoint, "vpc", "sfs", 1) 670 sc.ResourceBase = sc.Endpoint + "v2/" + client.ProjectID + "/" 671 return sc, err 672 } 673 674 // NewHwSFSTurboV1 creates a service client that is used for Huawei cloud for SFS Turbo. 675 func NewHwSFSTurboV1(client *golangsdk.ProviderClient, eo golangsdk.EndpointOpts) (*golangsdk.ServiceClient, error) { 676 sc, err := initClientOpts(client, eo, "network") 677 sc.Endpoint = strings.Replace(sc.Endpoint, "vpc", "sfs-turbo", 1) 678 sc.ResourceBase = sc.Endpoint + "v1/" + client.ProjectID + "/" 679 return sc, err 680 } 681 682 // NewObjectStorageV1 creates a ServiceClient that may be used with the v1 683 // object storage package. 684 func NewObjectStorageV1(client *golangsdk.ProviderClient, eo golangsdk.EndpointOpts) (*golangsdk.ServiceClient, error) { 685 return initClientOpts(client, eo, "object-store") 686 } 687 688 // NewOBSService creates a ServiceClient that may be used to access the Object Storage Service. 689 func NewOBSService(client *golangsdk.ProviderClient, eo golangsdk.EndpointOpts) (*golangsdk.ServiceClient, error) { 690 sc, err := initClientOpts(client, eo, "object") 691 return sc, err 692 } 693 694 // NewImageServiceV1 creates a ServiceClient that may be used to access the v1 695 // image service. 696 func NewImageServiceV1(client *golangsdk.ProviderClient, eo golangsdk.EndpointOpts) (*golangsdk.ServiceClient, error) { 697 sc, err := initClientOpts(client, eo, "image") 698 sc.ResourceBase = sc.Endpoint + "v1/" 699 return sc, err 700 } 701 702 // NewImageServiceV2 creates a ServiceClient that may be used to access the v2 703 // image service. 704 func NewImageServiceV2(client *golangsdk.ProviderClient, eo golangsdk.EndpointOpts) (*golangsdk.ServiceClient, error) { 705 sc, err := initClientOpts(client, eo, "image") 706 sc.ResourceBase = sc.Endpoint + "v2/" 707 return sc, err 708 } 709 710 // NewLoadBalancerV2 creates a ServiceClient that may be used to access the v2 711 // load balancer service. 712 func NewLoadBalancerV2(client *golangsdk.ProviderClient, eo golangsdk.EndpointOpts) (*golangsdk.ServiceClient, error) { 713 sc, err := initClientOpts(client, eo, "load-balancer") 714 sc.ResourceBase = sc.Endpoint + "v2.0/" 715 return sc, err 716 } 717 718 // NewElbV1 creates a ServiceClient that may be used with the v1 network package. 719 func NewElbV1(client *golangsdk.ProviderClient, eo golangsdk.EndpointOpts, otctype string) (*golangsdk.ServiceClient, error) { 720 sc, err := initClientOpts(client, eo, "compute") 721 sc.Endpoint = strings.Replace(strings.Replace(sc.Endpoint, "ecs", otctype, 1), "/v2/", "/v1.0/", 1) 722 sc.ResourceBase = sc.Endpoint 723 sc.Type = otctype 724 return sc, err 725 } 726 727 // NewELBV1 creates a ServiceClient that may be used to access the ELB service. 728 func NewELBV1(client *golangsdk.ProviderClient, eo golangsdk.EndpointOpts) (*golangsdk.ServiceClient, error) { 729 sc, err := initClientOpts(client, eo, "elbv1") 730 return sc, err 731 } 732 733 func NewElasticLoadBalancer(client *golangsdk.ProviderClient, eo golangsdk.EndpointOpts) (*golangsdk.ServiceClient, error) { 734 sc, err := initClientOpts(client, eo, "network") 735 if err != nil { 736 return sc, err 737 } 738 sc.Endpoint = strings.Replace(sc.Endpoint, "vpc", "elb", 1) 739 sc.Endpoint = strings.Replace(sc.Endpoint, "myhwclouds", "myhuaweicloud", 1) 740 sc.ResourceBase = sc.Endpoint + "v1.0/" 741 return sc, err 742 } 743 744 // NewDBV1 creates a ServiceClient that may be used to access the v1 DB service. 745 func NewDBV1(client *golangsdk.ProviderClient, eo golangsdk.EndpointOpts) (*golangsdk.ServiceClient, error) { 746 return initClientOpts(client, eo, "database") 747 } 748 749 // NewRDSV1 creates a ServiceClient that may be used to access the RDS service. 750 func NewRDSV1(client *golangsdk.ProviderClient, eo golangsdk.EndpointOpts) (*golangsdk.ServiceClient, error) { 751 sc, err := initClientOpts(client, eo, "rdsv1") 752 if err != nil { 753 return initcommonServiceClient(client, eo, "rds", "rds/v1") 754 } 755 return sc, nil 756 } 757 758 // NewRDSV3 creates a ServiceClient that may be used to access the RDS service. 759 func NewRDSV3(client *golangsdk.ProviderClient, eo golangsdk.EndpointOpts) (*golangsdk.ServiceClient, error) { 760 sc, err := initClientOpts(client, eo, "rdsv3") 761 return sc, err 762 } 763 764 // NewRdsServiceV1 creates the a ServiceClient that may be used to access the v1 765 // rds service which is a service of db instances management. 766 func NewRdsServiceV1(client *golangsdk.ProviderClient, eo golangsdk.EndpointOpts) (*golangsdk.ServiceClient, error) { 767 newsc, err := initClientOpts(client, eo, "compute") 768 rdsendpoint := strings.Replace(strings.Replace(newsc.Endpoint, "ecs", "rds", 1), "/v2/", "/rds/v1/", 1) 769 newsc.Endpoint = rdsendpoint 770 newsc.ResourceBase = rdsendpoint 771 newsc.Type = "rds" 772 return newsc, err 773 } 774 775 func NewRdsTagV1(client *golangsdk.ProviderClient, eo golangsdk.EndpointOpts) (*golangsdk.ServiceClient, error) { 776 sc, err := initClientOpts(client, eo, "network") 777 sc.Endpoint = strings.Replace(sc.Endpoint, "vpc", "rds", 1) 778 sc.Endpoint = sc.Endpoint + "v1/" 779 sc.ResourceBase = sc.Endpoint + client.ProjectID + "/rds/" 780 return sc, err 781 } 782 783 // NewCESClient creates a ServiceClient that may be used with the v1 CES service. 784 func NewCESClient(client *golangsdk.ProviderClient, eo golangsdk.EndpointOpts) (*golangsdk.ServiceClient, error) { 785 sc, err := initClientOpts(client, eo, "cesv1") 786 if err != nil { 787 return initcommonServiceClient(client, eo, "ces", "V1.0") 788 } 789 return sc, nil 790 } 791 792 // NewDRSServiceV2 creates a ServiceClient that may be used to access the v2 Data Replication Service. 793 func NewDRSServiceV2(client *golangsdk.ProviderClient, eo golangsdk.EndpointOpts) (*golangsdk.ServiceClient, error) { 794 sc, err := initClientOpts(client, eo, "volumev2") 795 return sc, err 796 } 797 798 // NewAutoScalingService creates a ServiceClient that may be used to access the 799 // auto-scaling service of huawei public cloud 800 func NewAutoScalingService(client *golangsdk.ProviderClient, eo golangsdk.EndpointOpts) (*golangsdk.ServiceClient, error) { 801 sc, err := initClientOpts(client, eo, "asv1") 802 if err != nil { 803 return initcommonServiceClient(client, eo, "as", "autoscaling-api/v1") 804 } 805 return sc, nil 806 } 807 808 // NewKMSV1 creates a ServiceClient that may be used to access the KMS service. 809 func NewKMSV1(client *golangsdk.ProviderClient, eo golangsdk.EndpointOpts) (*golangsdk.ServiceClient, error) { 810 sc, err := initClientOpts(client, eo, "kms") 811 return sc, err 812 } 813 814 // NewKmsKeyV1 creates a ServiceClient that may be used to access the kms key service. 815 // **only used for HCS** 816 func NewKmsKeyV1(client *golangsdk.ProviderClient, eo golangsdk.EndpointOpts) (*golangsdk.ServiceClient, error) { 817 sc, err := initClientOpts(client, eo, "compute") 818 sc.Endpoint = strings.Replace(sc.Endpoint, "ecs", "kms", 1) 819 sc.Endpoint = sc.Endpoint[:strings.LastIndex(sc.Endpoint, "v2")+3] 820 sc.Endpoint = strings.Replace(sc.Endpoint, "v2", "v1.0", 1) 821 sc.ResourceBase = sc.Endpoint 822 sc.Type = "kms" 823 return sc, err 824 } 825 826 // NewOrchestrationV1 creates a ServiceClient that may be used to access the v1 827 // orchestration service. 828 func NewOrchestrationV1(client *golangsdk.ProviderClient, eo golangsdk.EndpointOpts) (*golangsdk.ServiceClient, error) { 829 return initClientOpts(client, eo, "orchestration") 830 } 831 832 // NewDNSV2 creates a ServiceClient that may be used to access the v2 DNS 833 // service. 834 func NewDNSV2(client *golangsdk.ProviderClient, eo golangsdk.EndpointOpts) (*golangsdk.ServiceClient, error) { 835 sc, err := initClientOpts(client, eo, "dns") 836 sc.ResourceBase = sc.Endpoint + "v2/" 837 return sc, err 838 } 839 840 // NewNatV2 creates a ServiceClient that may be used with the v2 nat package. 841 func NewNatV2(client *golangsdk.ProviderClient, eo golangsdk.EndpointOpts) (*golangsdk.ServiceClient, error) { 842 sc, err := initClientOpts(client, eo, "network") 843 sc.Endpoint = strings.Replace(sc.Endpoint, "vpc", "nat", 1) 844 sc.Endpoint = strings.Replace(sc.Endpoint, "myhwclouds", "myhuaweicloud", 1) 845 sc.ResourceBase = sc.Endpoint + "v2.0/" 846 return sc, err 847 } 848 849 // MapReduceV1 creates a ServiceClient that may be used with the v1 MapReduce service. 850 func MapReduceV1(client *golangsdk.ProviderClient, eo golangsdk.EndpointOpts) (*golangsdk.ServiceClient, error) { 851 sc, err := initClientOpts(client, eo, "network") 852 sc.Endpoint = strings.Replace(sc.Endpoint, "vpc", "mrs", 1) 853 sc.Endpoint = sc.Endpoint + "v1.1/" 854 sc.ResourceBase = sc.Endpoint + client.ProjectID + "/" 855 return sc, err 856 } 857 858 // NewMapReduceV1 creates a ServiceClient that may be used with the v1 MapReduce service. 859 func NewMapReduceV1(client *golangsdk.ProviderClient, eo golangsdk.EndpointOpts) (*golangsdk.ServiceClient, error) { 860 sc, err := initClientOpts(client, eo, "mrs") 861 sc.ResourceBase = sc.Endpoint + client.ProjectID + "/" 862 return sc, err 863 } 864 865 // NewAntiDDoSV1 creates a ServiceClient that may be used with the v1 Anti DDoS Service package. 866 func NewAntiDDoSV1(client *golangsdk.ProviderClient, eo golangsdk.EndpointOpts) (*golangsdk.ServiceClient, error) { 867 sc, err := initClientOpts(client, eo, "antiddos") 868 if err != nil { 869 return initcommonServiceClient(client, eo, "antiddos", "v1") 870 } 871 return sc, nil 872 } 873 874 // NewAntiDDoSV2 creates a ServiceClient that may be used with the v2 Anti DDoS Service package. 875 func NewAntiDDoSV2(client *golangsdk.ProviderClient, eo golangsdk.EndpointOpts) (*golangsdk.ServiceClient, error) { 876 sc, err := initClientOpts(client, eo, "antiddos") 877 sc.ResourceBase = sc.Endpoint + "v2/" + client.ProjectID + "/" 878 return sc, err 879 } 880 881 // NewCCE creates a ServiceClient that may be used to access the CCE service. 882 func NewCCE(client *golangsdk.ProviderClient, eo golangsdk.EndpointOpts) (*golangsdk.ServiceClient, error) { 883 sc, err := initClientOpts(client, eo, "ccev2.0") 884 sc.ResourceBase = sc.Endpoint + "api/v3/projects/" + client.ProjectID + "/" 885 return sc, err 886 } 887 888 func NewCCEV3(client *golangsdk.ProviderClient, eo golangsdk.EndpointOpts) (*golangsdk.ServiceClient, error) { 889 sc, err := initClientOpts(client, eo, "network") 890 sc.Endpoint = strings.Replace(sc.Endpoint, "vpc", "cce", 1) 891 sc.Endpoint = strings.Replace(sc.Endpoint, "myhwclouds", "myhuaweicloud", 1) 892 sc.ResourceBase = sc.Endpoint + "api/v3/projects/" + client.ProjectID + "/" 893 return sc, err 894 } 895 896 func NewCCEAddonV3(client *golangsdk.ProviderClient, eo golangsdk.EndpointOpts) (*golangsdk.ServiceClient, error) { 897 sc, err := initClientOpts(client, eo, "network") 898 sc.Endpoint = strings.Replace(sc.Endpoint, "vpc", "cce", 1) 899 sc.Endpoint = strings.Replace(sc.Endpoint, "myhwclouds", "myhuaweicloud", 1) 900 sc.ResourceBase = sc.Endpoint + "api/v3/" 901 return sc, err 902 } 903 904 // NewDMSServiceV1 creates a ServiceClient that may be used to access the v1 Distributed Message Service. 905 func NewDMSServiceV1(client *golangsdk.ProviderClient, eo golangsdk.EndpointOpts) (*golangsdk.ServiceClient, error) { 906 sc, err := initClientOpts(client, eo, "network") 907 sc.Endpoint = strings.Replace(sc.Endpoint, "vpc", "dms", 1) 908 sc.ResourceBase = sc.Endpoint + "v1.0/" + client.ProjectID + "/" 909 return sc, err 910 } 911 912 // NewDCSServiceV1 creates a ServiceClient that may be used to access the v1 Distributed Cache Service. 913 func NewDCSServiceV1(client *golangsdk.ProviderClient, eo golangsdk.EndpointOpts) (*golangsdk.ServiceClient, error) { 914 sc, err := initClientOpts(client, eo, "network") 915 sc.Endpoint = strings.Replace(sc.Endpoint, "vpc", "dcs", 1) 916 sc.ResourceBase = sc.Endpoint + "v1.0/" + client.ProjectID + "/" 917 return sc, err 918 } 919 920 func NewBMSV2(client *golangsdk.ProviderClient, eo golangsdk.EndpointOpts) (*golangsdk.ServiceClient, error) { 921 sc, err := initClientOpts(client, eo, "compute") 922 e := strings.Replace(sc.Endpoint, "v2", "v2.1", 1) 923 sc.Endpoint = e 924 sc.ResourceBase = e 925 return sc, err 926 } 927 928 // NewDeHServiceV1 creates a ServiceClient that may be used to access the v1 Dedicated Hosts service. 929 func NewDeHServiceV1(client *golangsdk.ProviderClient, eo golangsdk.EndpointOpts) (*golangsdk.ServiceClient, error) { 930 sc, err := initClientOpts(client, eo, "deh") 931 return sc, err 932 } 933 934 // NewCSBSService creates a ServiceClient that can be used to access the Cloud Server Backup service. 935 func NewCSBSService(client *golangsdk.ProviderClient, eo golangsdk.EndpointOpts) (*golangsdk.ServiceClient, error) { 936 sc, err := initClientOpts(client, eo, "data-protect") 937 return sc, err 938 } 939 940 // NewHwCSBSServiceV1 creates a ServiceClient that may be used to access the Huawei Cloud Server Backup service. 941 func NewHwCSBSServiceV1(client *golangsdk.ProviderClient, eo golangsdk.EndpointOpts) (*golangsdk.ServiceClient, error) { 942 sc, err := initClientOpts(client, eo, "compute") 943 sc.Endpoint = strings.Replace(sc.Endpoint, "ecs", "csbs", 1) 944 e := strings.Replace(sc.Endpoint, "v2", "v1", 1) 945 sc.Endpoint = e 946 sc.ResourceBase = e 947 return sc, err 948 } 949 950 func NewMLSV1(client *golangsdk.ProviderClient, eo golangsdk.EndpointOpts) (*golangsdk.ServiceClient, error) { 951 sc, err := initClientOpts(client, eo, "network") 952 sc.Endpoint = strings.Replace(sc.Endpoint, "vpc", "mls", 1) 953 sc.ResourceBase = sc.Endpoint + "v1.0/" + client.ProjectID + "/" 954 return sc, err 955 } 956 957 func NewDWSClient(client *golangsdk.ProviderClient, eo golangsdk.EndpointOpts) (*golangsdk.ServiceClient, error) { 958 sc, err := initcommonServiceClient(client, eo, "dws", "v1.0") 959 return sc, err 960 } 961 962 // NewVBSV2 creates a ServiceClient that may be used to access the VBS service 963 func NewVBSV2(client *golangsdk.ProviderClient, eo golangsdk.EndpointOpts) (*golangsdk.ServiceClient, error) { 964 sc, err := initClientOpts(client, eo, "vbsv2") 965 if err != nil { 966 return initcommonServiceClient(client, eo, "vbs", "v2") 967 } 968 return sc, nil 969 } 970 971 // NewCTSService creates a ServiceClient that can be used to access the Cloud Trace service. 972 func NewCTSService(client *golangsdk.ProviderClient, eo golangsdk.EndpointOpts) (*golangsdk.ServiceClient, error) { 973 sc, err := initClientOpts(client, eo, "cts") 974 return sc, err 975 } 976 977 // NewSMNV2 creates a ServiceClient that may be used to access the SMN service. 978 func NewSMNV2(client *golangsdk.ProviderClient, eo golangsdk.EndpointOpts) (*golangsdk.ServiceClient, error) { 979 sc, err := initClientOpts(client, eo, "smnv2") 980 if err != nil { 981 sc, err = initcommonServiceClient(client, eo, "smn", "v2") 982 } 983 sc.ResourceBase = sc.Endpoint + "notifications/" 984 return sc, err 985 } 986 987 // NewWAFV1 creates a ServiceClient that may be used to access the WAF service. 988 func NewWAFV1(client *golangsdk.ProviderClient, eo golangsdk.EndpointOpts) (*golangsdk.ServiceClient, error) { 989 sc, err := initClientOpts(client, eo, "waf") 990 sc.ResourceBase = sc.Endpoint + "v1/" + client.ProjectID + "/waf/" 991 return sc, err 992 } 993 994 // NewSDRSV1 creates a ServiceClient that may be used to access the SDRS service. 995 func NewSDRSV1(client *golangsdk.ProviderClient, eo golangsdk.EndpointOpts) (*golangsdk.ServiceClient, error) { 996 sc, err := initClientOpts(client, eo, "sdrs") 997 if err != nil { 998 return initcommonServiceClient(client, eo, "sdrs", "v1") 999 } 1000 return sc, nil 1001 } 1002 1003 // CCIV1 creates a ServiceClient that may be used with the v1 CCI service. 1004 func CCIV1(client *golangsdk.ProviderClient, eo golangsdk.EndpointOpts) (*golangsdk.ServiceClient, error) { 1005 sc, err := initClientOpts(client, eo, "network") 1006 sc.Endpoint = strings.Replace(sc.Endpoint, "vpc", "cci", 1) 1007 sc.Endpoint = sc.Endpoint + "apis/networking.cci.io/v1beta1/" 1008 sc.ResourceBase = sc.Endpoint 1009 return sc, err 1010 } 1011 1012 // NewBSSV1 creates a ServiceClient that may be used to access the BSS service. 1013 func NewBSSV1(client *golangsdk.ProviderClient, eo golangsdk.EndpointOpts) (*golangsdk.ServiceClient, error) { 1014 sc, err := initClientOpts(client, eo, "bssv1") 1015 return sc, err 1016 } 1017 1018 // NewDDSV3 creates a ServiceClient that may be used to access the DDS service. 1019 func NewDDSV3(client *golangsdk.ProviderClient, eo golangsdk.EndpointOpts) (*golangsdk.ServiceClient, error) { 1020 sc, err := initClientOpts(client, eo, "ddsv3") 1021 return sc, err 1022 } 1023 1024 // NewLTSV2 creates a ServiceClient that may be used to access the LTS service. 1025 func NewLTSV2(client *golangsdk.ProviderClient, eo golangsdk.EndpointOpts) (*golangsdk.ServiceClient, error) { 1026 sc, err := initcommonServiceClient(client, eo, "lts", "v2.0") 1027 return sc, err 1028 } 1029 1030 // NewHuaweiLTSV2 creates a ServiceClient that may be used to access the Huawei Cloud LTS service. 1031 func NewHuaweiLTSV2(client *golangsdk.ProviderClient, eo golangsdk.EndpointOpts) (*golangsdk.ServiceClient, error) { 1032 sc, err := initcommonServiceClient(client, eo, "lts", "v2") 1033 return sc, err 1034 } 1035 1036 // NewFGSV2 creates a ServiceClient that may be used with the v2 as 1037 // package. 1038 func NewFGSV2(client *golangsdk.ProviderClient, eo golangsdk.EndpointOpts) (*golangsdk.ServiceClient, error) { 1039 sc, err := initClientOpts(client, eo, "fgsv2") 1040 return sc, err 1041 } 1042 1043 // NewMAASV1 creates a ServiceClient that may be used to access the MAAS service. 1044 func NewMAASV1(client *golangsdk.ProviderClient, eo golangsdk.EndpointOpts) (*golangsdk.ServiceClient, error) { 1045 sc, err := initClientOpts(client, eo, "maasv1") 1046 return sc, err 1047 } 1048 1049 // MAASV1 creates a ServiceClient that may be used with the v1 MAAS service. 1050 func MAASV1(client *golangsdk.ProviderClient, eo golangsdk.EndpointOpts) (*golangsdk.ServiceClient, error) { 1051 sc, err := initClientOpts(client, eo, "network") 1052 sc.Endpoint = "https://oms.myhuaweicloud.com/v1/" 1053 sc.ResourceBase = sc.Endpoint + client.ProjectID + "/" 1054 return sc, err 1055 } 1056 1057 // NewCDNV1 creates a ServiceClient that may be used to access the v1 1058 // CDN service. 1059 func NewCDNV1(client *golangsdk.ProviderClient, eo golangsdk.EndpointOpts) (*golangsdk.ServiceClient, error) { 1060 sc, err := initClientOpts(client, eo, "network") 1061 sc.Endpoint = "https://cdn.myhuaweicloud.com/" 1062 sc.ResourceBase = sc.Endpoint + "v1.0/" 1063 return sc, err 1064 } 1065 1066 // TMSV1 creates a ServiceClient that may be used with the v1 TMS service. 1067 func TMSV1(client *golangsdk.ProviderClient, eo golangsdk.EndpointOpts) (*golangsdk.ServiceClient, error) { 1068 sc, err := initClientOpts(client, eo, "network") 1069 sc.Endpoint = "https://tms.myhuaweicloud.com/v1.0/" 1070 sc.ResourceBase = sc.Endpoint 1071 return sc, err 1072 } 1073 1074 // NewGeminiDBV3 creates a ServiceClient that may be used with the GeminiDB service. 1075 func NewGeminiDBV3(client *golangsdk.ProviderClient, eo golangsdk.EndpointOpts) (*golangsdk.ServiceClient, error) { 1076 sc := new(golangsdk.ServiceClient) 1077 sc.ProviderClient = client 1078 sc.Endpoint = fmt.Sprintf("https://gaussdb-nosql.%s.myhuaweicloud.com", eo.Region) 1079 sc.ResourceBase = fmt.Sprintf("%s/v3/%s/", sc.Endpoint, client.ProjectID) 1080 1081 return sc, nil 1082 }