Add the Loki query UI, access policies, ingress insights, alert and registry settings, and their backend APIs. Include the related Kubernetes deployment and collector updates required by the integrated application. Validated with go test ./..., npm run build, and npm run lint.
132 lines
4.2 KiB
Go
132 lines
4.2 KiB
Go
package services
|
|
|
|
// 镜像仓库源 — 全局设置(参照 kuboard 的国内/海外镜像选择):
|
|
// overseas = docker.io 官方源;cn = daocloud 国内镜像;custom = 用户自填 registry 前缀。
|
|
// 影响平台拉取的全部镜像:Loki / Grafana / Promtail / Fluent Bit。
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"strings"
|
|
|
|
"opsxloki/models"
|
|
"opsxloki/repository"
|
|
)
|
|
|
|
const (
|
|
imageRegistrySettingKey = "image_registry"
|
|
RegistryOverseas = "overseas" // docker.io
|
|
RegistryCN = "cn" // docker.m.daocloud.io(国内加速)
|
|
RegistryCustom = "custom" // 用户私有仓库前缀
|
|
daocloudPrefix = "docker.m.daocloud.io"
|
|
)
|
|
|
|
// ImageRegistryConfig 镜像源配置
|
|
type ImageRegistryConfig struct {
|
|
Mode string `json:"mode"` // overseas | cn | custom
|
|
CustomHost string `json:"customHost"` // custom 模式下的仓库前缀,如 swr.cn-east-2.myhuaweicloud.com/xxx
|
|
}
|
|
|
|
type ImageRegistryPublic struct {
|
|
Mode string `json:"mode"`
|
|
CustomHost string `json:"customHost"`
|
|
// 示例预览(前端展示生效镜像)
|
|
SampleLoki string `json:"sampleLoki"`
|
|
SampleGrafana string `json:"sampleGrafana"`
|
|
SamplePromtail string `json:"samplePromtail"`
|
|
SampleFluentBit string `json:"sampleFluentBit"`
|
|
}
|
|
|
|
func GetImageRegistry() *ImageRegistryConfig {
|
|
db := repository.GetDB()
|
|
if db == nil {
|
|
return &ImageRegistryConfig{Mode: RegistryOverseas}
|
|
}
|
|
db.RLock()
|
|
var raw string
|
|
for i := range db.Settings {
|
|
if db.Settings[i].Key == imageRegistrySettingKey {
|
|
raw = db.Settings[i].Value
|
|
break
|
|
}
|
|
}
|
|
db.RUnlock()
|
|
cfg := &ImageRegistryConfig{Mode: RegistryOverseas}
|
|
if raw != "" {
|
|
_ = json.Unmarshal([]byte(raw), cfg)
|
|
}
|
|
if cfg.Mode == "" {
|
|
cfg.Mode = RegistryOverseas
|
|
}
|
|
return cfg
|
|
}
|
|
|
|
func SaveImageRegistry(mode, customHost string) error {
|
|
if mode != RegistryOverseas && mode != RegistryCN && mode != RegistryCustom {
|
|
return fmt.Errorf("无效的镜像源模式")
|
|
}
|
|
if mode == RegistryCustom {
|
|
customHost = strings.TrimSuffix(strings.TrimSpace(customHost), "/")
|
|
if customHost == "" || !strings.Contains(customHost, ".") {
|
|
return fmt.Errorf("自定义镜像仓库地址无效(需含域名,如 swr.cn-east-2.myhuaweicloud.com/your-ns)")
|
|
}
|
|
}
|
|
data, _ := json.Marshal(&ImageRegistryConfig{Mode: mode, CustomHost: customHost})
|
|
db := repository.GetDB()
|
|
newID := db.NextID("settings")
|
|
db.Lock()
|
|
defer db.Unlock()
|
|
for i := range db.Settings {
|
|
if db.Settings[i].Key == imageRegistrySettingKey {
|
|
db.Settings[i].Value = string(data)
|
|
db.RequestSave()
|
|
return nil
|
|
}
|
|
}
|
|
db.Settings = append(db.Settings, models.SystemSetting{ID: newID, Key: imageRegistrySettingKey, Value: string(data)})
|
|
db.RequestSave()
|
|
return nil
|
|
}
|
|
|
|
// ResolveImage 按当前镜像源解析镜像地址:docker.io/grafana/loki:3.4.0 形式的官方镜像
|
|
// 会按 mode 重写前缀;已带私有仓库前缀(含镜像源域名)的地址原样返回。
|
|
func ResolveImage(official string) string {
|
|
cfg := GetImageRegistry()
|
|
switch cfg.Mode {
|
|
case RegistryCN:
|
|
if strings.HasPrefix(official, "docker.io/") {
|
|
return daocloudPrefix + "/" + strings.TrimPrefix(official, "docker.io/")
|
|
}
|
|
if !strings.Contains(strings.SplitN(official, "/", 2)[0], ".") {
|
|
// 无仓库前缀的官方镜像(grafana/loki:tag)
|
|
return daocloudPrefix + "/" + official
|
|
}
|
|
return official
|
|
case RegistryCustom:
|
|
if strings.HasPrefix(official, "docker.io/") {
|
|
return cfg.CustomHost + "/" + strings.TrimPrefix(official, "docker.io/")
|
|
}
|
|
if !strings.Contains(strings.SplitN(official, "/", 2)[0], ".") {
|
|
return cfg.CustomHost + "/" + official
|
|
}
|
|
return official
|
|
default:
|
|
if strings.HasPrefix(official, "docker.io/") {
|
|
return official // 官方模式保留全限定名
|
|
}
|
|
return official
|
|
}
|
|
}
|
|
|
|
// ImageRegistryPublicConfig 对外输出(含示例预览)
|
|
func ImageRegistryPublicConfig() *ImageRegistryPublic {
|
|
cfg := GetImageRegistry()
|
|
return &ImageRegistryPublic{
|
|
Mode: cfg.Mode,
|
|
CustomHost: cfg.CustomHost,
|
|
SampleLoki: ResolveImage("docker.io/grafana/loki:3.4.0"),
|
|
SampleGrafana: ResolveImage("docker.io/grafana/grafana:11.3.0"),
|
|
SamplePromtail: ResolveImage("docker.io/grafana/promtail:3.4.0"),
|
|
SampleFluentBit: ResolveImage("docker.io/fluent/fluent-bit:5.1.5"),
|
|
}
|
|
}
|