package oci import ( "errors" "regexp" "strings" "github.com/oracle/oci-go-sdk/v65/common" ) // ociErrorHints 把常见 OCI 错误码翻译成给用户看的中文提示。 var ociErrorHints = map[string]string{ "IncorrectState": "资源当前状态不允许该操作,通常是仍被其他资源占用或正在变更中", "NotAuthorizedOrNotFound": "无权限或资源不存在(可能已被删除)", "LimitExceeded": "已达到服务配额上限", "QuotaExceeded": "compartment 配额不足", "OutOfHostCapacity": "该可用域容量不足,可稍后重试或改用抢机任务", "TooManyRequests": "请求过于频繁,请稍后再试", "InvalidParameter": "请求参数无效", "InternalError": "OCI 服务内部错误,请稍后重试", "Conflict": "资源正在变更中,请稍后重试", } // ocidRe 匹配消息中的完整 OCID(unique 段 20 位以上才压缩,避免误伤短标识)。 var ocidRe = regexp.MustCompile(`ocid1\.([a-z0-9]+)\.[a-z0-9]*\.[a-z0-9-]*\.{1,2}[a-z0-9]{20,}`) // shortenOcids 把消息里的长 OCID 压缩为「ocid1.<类型>…<尾6位>」, // 保留资源类型与可比对的尾部,避免整条错误被 OCID 撑爆。 func shortenOcids(s string) string { return ocidRe.ReplaceAllStringFunc(s, func(m string) string { i := strings.Index(m, ".") typ := m[i+1:] if j := strings.Index(typ, "."); j > 0 { typ = typ[:j] } return "ocid1." + typ + "…" + m[len(m)-6:] }) } // CompactError 把含 OCI ServiceError 的错误链提炼成短消息: // 操作前缀 + 服务端消息,剥掉 SDK 附加的错误码、排障链接、 // 时间戳、SDK 版本等长文(错误码另经 API 的 ociCode 字段透出); // 消息中的长 OCID 压缩为类型加尾位的短形式。非 OCI 错误原样返回。 func CompactError(err error) string { var svcErr common.ServiceError if !errors.As(err, &svcErr) { return shortenOcids(err.Error()) } prefix := err.Error() if i := strings.Index(prefix, ": Error returned by"); i > 0 { prefix = prefix[:i] + ": " } else { prefix = "" } return shortenOcids(prefix + svcErr.GetMessage()) } // ErrorHint 返回常见 OCI 错误的中文提示;未识别返回空串。 // 容量不足常以 code=InternalError 返回,按消息内容归到容量提示。 func ErrorHint(err error) string { var svcErr common.ServiceError if !errors.As(err, &svcErr) { return "" } if strings.Contains(svcErr.GetMessage(), "Out of host capacity") { return ociErrorHints["OutOfHostCapacity"] } return ociErrorHints[svcErr.GetCode()] } // ServiceStatus 返回错误链中 OCI ServiceError 的 HTTP 状态码;非服务端错误 ok=false。 func ServiceStatus(err error) (int, bool) { var svcErr common.ServiceError if errors.As(err, &svcErr) { return svcErr.GetHTTPStatusCode(), true } return 0, false }