初始提交:OCI 面板后端(含 GenAI 网关一期)

This commit is contained in:
Wang Defa
2026-07-09 15:31:04 +08:00
commit b9a3e97e84
168 changed files with 31794 additions and 0 deletions
+98
View File
@@ -0,0 +1,98 @@
package oci
import (
"fmt"
"strings"
)
// Credentials 是调用 OCI API 所需的完整凭据,私钥为 PEM 明文。
// CompartmentID 限定资源操作的目标 compartment,空表示租户根;
// 只影响 compute / 网络 / 块存储等资源查询,身份与订阅类调用始终走租户根。
type Credentials struct {
TenancyOCID string
UserOCID string
Region string
Fingerprint string
PrivateKey string
Passphrase string
CompartmentID string
// Proxy 非 nil 时该租户全部 SDK 出站请求经此代理
Proxy *ProxySpec
}
// EffectiveCompartment 返回资源操作的目标 compartment,未指定时为租户根。
func (c Credentials) EffectiveCompartment() *string {
if c.CompartmentID != "" {
id := c.CompartmentID
return &id
}
id := c.TenancyOCID
return &id
}
// Validate 检查凭据必填字段。
func (c Credentials) Validate() error {
switch {
case c.TenancyOCID == "":
return fmt.Errorf("credentials: tenancy is empty")
case c.UserOCID == "":
return fmt.Errorf("credentials: user is empty")
case c.Region == "":
return fmt.Errorf("credentials: region is empty")
case c.Fingerprint == "":
return fmt.Errorf("credentials: fingerprint is empty")
case !strings.Contains(c.PrivateKey, "PRIVATE KEY"):
return fmt.Errorf("credentials: private key is not a PEM")
}
return nil
}
// ParseConfigINI 解析 OCI 标准 configini)文本的 [DEFAULT] 段。
// key_file 只在本机指向文件,导入场景私钥内容必须单独提供,因此忽略该行。
func ParseConfigINI(text string) (Credentials, error) {
var cred Credentials
section := "DEFAULT"
for _, line := range strings.Split(text, "\n") {
line = strings.TrimSpace(line)
if line == "" || strings.HasPrefix(line, "#") || strings.HasPrefix(line, ";") {
continue
}
if strings.HasPrefix(line, "[") && strings.HasSuffix(line, "]") {
section = strings.TrimSpace(line[1 : len(line)-1])
continue
}
if !strings.EqualFold(section, "DEFAULT") {
continue
}
applyConfigLine(&cred, line)
}
if cred.TenancyOCID == "" && cred.UserOCID == "" {
return cred, fmt.Errorf("parse oci config: no recognizable fields")
}
return cred, nil
}
func applyConfigLine(cred *Credentials, line string) {
key, value, ok := strings.Cut(line, "=")
if !ok {
return
}
// OCID、指纹、region 值里不含 #,可安全去掉行尾注释
if i := strings.Index(value, "#"); i >= 0 {
value = value[:i]
}
key = strings.TrimSpace(strings.ToLower(key))
value = strings.TrimSpace(value)
switch key {
case "user":
cred.UserOCID = value
case "tenancy":
cred.TenancyOCID = value
case "fingerprint":
cred.Fingerprint = value
case "region":
cred.Region = value
case "pass_phrase":
cred.Passphrase = value
}
}