fix: 完善多云同步验证与实例统计
- 修复华为云签名、账单字段与区域映射缓存 - 按真实云实例更新账号服务器数并补充并发测试
This commit is contained in:
1 parent
132fe9ba97
commit
9b895efee3
6 files changed
+226
-64
No files matched your search
+26
-12
@@ -8,15 +8,20 @@ import (
|
||||
"net/http"
|
||||
"sort"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
// HuaweiProvider 通过华为云 AK/SK 签名 API 同步项目区域与 ECS 实例。 // Logan.Li
|
||||
type HuaweiProvider struct{ accessKey, secretKey string }
|
||||
type HuaweiProvider struct {
|
||||
accessKey, secretKey string
|
||||
regionMu sync.RWMutex
|
||||
regionByProject map[string]string
|
||||
}
|
||||
|
||||
// NewHuaweiProvider 创建华为云 Provider。 // Logan.Li
|
||||
func NewHuaweiProvider(accessKey, secretKey string) *HuaweiProvider {
|
||||
return &HuaweiProvider{accessKey, secretKey}
|
||||
return &HuaweiProvider{accessKey: accessKey, secretKey: secretKey, regionByProject: make(map[string]string)}
|
||||
}
|
||||
|
||||
// Name 返回华为云厂商标识。 // Logan.Li
|
||||
@@ -32,7 +37,11 @@ func (p *HuaweiProvider) signedGet(rawURL, _ string) ([]byte, error) {
|
||||
host := u.URL.Host
|
||||
canonicalHeaders := "host:" + host + "\n" + "x-sdk-date:" + now + "\n"
|
||||
signedHeaders := "host;x-sdk-date"
|
||||
canonicalRequest := "GET\n" + u.URL.EscapedPath() + "\n" + u.URL.Query().Encode() + "\n" + canonicalHeaders + "\n" + signedHeaders + "\n" + sha256Hex("")
|
||||
canonicalURI := u.URL.EscapedPath()
|
||||
if !strings.HasSuffix(canonicalURI, "/") {
|
||||
canonicalURI += "/"
|
||||
}
|
||||
canonicalRequest := "GET\n" + canonicalURI + "\n" + u.URL.Query().Encode() + "\n" + canonicalHeaders + "\n" + signedHeaders + "\n" + sha256Hex("")
|
||||
stringToSign := "SDK-HMAC-SHA256\n" + now + "\n" + sha256Hex(canonicalRequest)
|
||||
signature := hex.EncodeToString(hmacSHA256([]byte(p.secretKey), stringToSign))
|
||||
u.Header.Set("X-Sdk-Date", now)
|
||||
@@ -68,28 +77,33 @@ func (p *HuaweiProvider) ListRegions() ([]CloudRegion, error) {
|
||||
return nil, fmt.Errorf("解析华为云区域响应失败: %w", err)
|
||||
}
|
||||
regions := []CloudRegion{}
|
||||
regionByProject := make(map[string]string, len(result.Projects))
|
||||
for _, project := range result.Projects {
|
||||
if project.ID == "" || project.Name == "" {
|
||||
continue
|
||||
}
|
||||
regions = append(regions, CloudRegion{RegionID: project.ID, LocalName: project.Name, Endpoint: "https://ecs." + project.Name + ".myhuaweicloud.com", Status: "active"})
|
||||
regionByProject[project.ID] = project.Name
|
||||
}
|
||||
p.regionMu.Lock()
|
||||
p.regionByProject = regionByProject
|
||||
p.regionMu.Unlock()
|
||||
sort.Slice(regions, func(i, j int) bool { return regions[i].LocalName < regions[j].LocalName })
|
||||
return regions, nil
|
||||
}
|
||||
|
||||
// ListInstances 获取指定华为云项目中的 ECS 实例。 // Logan.Li
|
||||
func (p *HuaweiProvider) ListInstances(projectID string) ([]CloudInstance, error) {
|
||||
regions, err := p.ListRegions()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
regionName := ""
|
||||
for _, region := range regions {
|
||||
if region.RegionID == projectID {
|
||||
regionName = region.LocalName
|
||||
break
|
||||
p.regionMu.RLock()
|
||||
regionName := p.regionByProject[projectID]
|
||||
p.regionMu.RUnlock()
|
||||
if regionName == "" {
|
||||
if _, err := p.ListRegions(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
p.regionMu.RLock()
|
||||
regionName = p.regionByProject[projectID]
|
||||
p.regionMu.RUnlock()
|
||||
}
|
||||
if regionName == "" {
|
||||
return nil, fmt.Errorf("未找到华为云项目 %s", projectID)
|
||||
|
||||
Reference in new issue
Block a user