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.
80 lines
2.3 KiB
Go
80 lines
2.3 KiB
Go
package services
|
|
|
|
import (
|
|
"fmt"
|
|
"io"
|
|
"regexp"
|
|
"strconv"
|
|
"strings"
|
|
|
|
"gopkg.in/yaml.v3"
|
|
)
|
|
|
|
var retentionPeriodPattern = regexp.MustCompile(`^([1-9][0-9]*)(d|h)$`)
|
|
|
|
// parseRetentionYAML 仅接收 limits_config.retention_period,避免把任意配置或凭证写入部署。
|
|
func parseRetentionYAML(source string) (int, error) {
|
|
var fragment struct {
|
|
LimitsConfig *struct {
|
|
RetentionPeriod string `yaml:"retention_period"`
|
|
} `yaml:"limits_config"`
|
|
}
|
|
decoder := yaml.NewDecoder(strings.NewReader(source))
|
|
decoder.KnownFields(true)
|
|
if err := decoder.Decode(&fragment); err != nil {
|
|
return 0, fmt.Errorf("YAML 格式无效: %w", err)
|
|
}
|
|
var extra interface{}
|
|
if err := decoder.Decode(&extra); err != io.EOF {
|
|
return 0, fmt.Errorf("只允许一段 limits_config YAML")
|
|
}
|
|
if fragment.LimitsConfig == nil {
|
|
return 0, fmt.Errorf("缺少 limits_config.retention_period")
|
|
}
|
|
match := retentionPeriodPattern.FindStringSubmatch(fragment.LimitsConfig.RetentionPeriod)
|
|
if match == nil {
|
|
return 0, fmt.Errorf("retention_period 须使用正整数天数,如 90d;也支持 2160h")
|
|
}
|
|
value, err := strconv.Atoi(match[1])
|
|
if err != nil {
|
|
return 0, fmt.Errorf("保留时长超出范围")
|
|
}
|
|
if match[2] == "h" {
|
|
if value%24 != 0 {
|
|
return 0, fmt.Errorf("小时数必须是 24 的倍数")
|
|
}
|
|
value /= 24
|
|
}
|
|
if value < 1 || value > 36500 {
|
|
return 0, fmt.Errorf("保留天数须在 1 到 36500 之间")
|
|
}
|
|
return value, nil
|
|
}
|
|
|
|
// UpdateRetention 保存 Loki 的保留时长;apply 为 true 时触发当前部署重新生成并应用配置。
|
|
func (s *DeploymentService) UpdateRetention(id uint, source string, apply bool) (int, error) {
|
|
days, err := parseRetentionYAML(source)
|
|
if err != nil {
|
|
return 0, err
|
|
}
|
|
deployment, err := s.Get(id)
|
|
if err != nil {
|
|
return 0, err
|
|
}
|
|
if deployment.Status == "deploying" {
|
|
return 0, fmt.Errorf("部署正在进行中,请稍后编辑")
|
|
}
|
|
if apply && deployment.Status != "running" {
|
|
return 0, fmt.Errorf("当前部署未运行,请仅保存后再部署")
|
|
}
|
|
if err := s.Update(id, map[string]interface{}{"retentionDays": float64(days)}); err != nil {
|
|
return 0, err
|
|
}
|
|
if apply {
|
|
if err := s.StartDeploy(id); err != nil {
|
|
return days, fmt.Errorf("保留配置已保存,但重新部署失败: %w", err)
|
|
}
|
|
}
|
|
return days, nil
|
|
}
|