package main import ( "fmt" "math/rand" "time" "ezops/config" "ezops/model" "ezops/pkg/database" "golang.org/x/crypto/bcrypt" "gorm.io/gorm" ) func main() { cfg := config.Load() db, err := database.New(cfg.Database) if err != nil { fmt.Printf("Failed to connect to database: %v\n", err) return } if err := generateMockData(db); err != nil { fmt.Printf("Failed to generate mock data: %v\n", err) return } fmt.Println("Mock data generated successfully!") } func generateMockData(db *gorm.DB) error { if err := generateUsers(db); err != nil { return err } if err := generateServers(db); err != nil { return err } if err := generateCloudAccounts(db); err != nil { return err } if err := generateDomains(db); err != nil { return err } if err := generateKubernetesClusters(db); err != nil { return err } if err := generateAlertRules(db); err != nil { return err } if err := generateNotifyChannels(db); err != nil { return err } if err := generatePipelines(db); err != nil { return err } if err := generateAppReleases(db); err != nil { return err } if err := generateCronJobs(db); err != nil { return err } if err := generateScripts(db); err != nil { return err } if err := generateApprovalTemplates(db); err != nil { return err } if err := generateNavigations(db); err != nil { return err } if err := generateBillings(db); err != nil { return err } return nil } func generateUsers(db *gorm.DB) error { users := []model.User{ {Username: "admin", Email: "admin@ezops.local", RealName: "系统管理员", Phone: "13800138000", Status: 1, IsAdmin: true}, {Username: "ops01", Email: "ops01@ezops.local", RealName: "运维工程师1", Phone: "13800138001", Status: 1, IsAdmin: false}, {Username: "ops02", Email: "ops02@ezops.local", RealName: "运维工程师2", Phone: "13800138002", Status: 1, IsAdmin: false}, {Username: "dev01", Email: "dev01@ezops.local", RealName: "开发工程师1", Phone: "13800138003", Status: 1, IsAdmin: false}, {Username: "dev02", Email: "dev02@ezops.local", RealName: "开发工程师2", Phone: "13800138004", Status: 0, IsAdmin: false}, } password, _ := bcrypt.GenerateFromPassword([]byte("123456"), bcrypt.DefaultCost) for i := range users { users[i].Password = string(password) if err := db.Create(&users[i]).Error; err != nil { return err } } fmt.Println("Generated users:", len(users)) return nil } func generateServers(db *gorm.DB) error { osTypes := []string{"CentOS 7.9", "CentOS 8.5", "Ubuntu 20.04", "Ubuntu 22.04", "Debian 11", "Rocky Linux 8.6"} statuses := []string{"running", "stopped", "maintenance"} servers := make([]model.Server, 0, 50) for i := 0; i < 50; i++ { server := model.Server{ Hostname: fmt.Sprintf("server-%03d", i+1), IP: fmt.Sprintf("10.0.%d.%d", rand.Intn(256), rand.Intn(256)), PublicIP: fmt.Sprintf("47.%d.%d.%d", rand.Intn(256), rand.Intn(256), rand.Intn(256)), OS: osTypes[rand.Intn(len(osTypes))], CPU: []int{2, 4, 8, 16, 32}[rand.Intn(5)], Memory: []int64{4096, 8192, 16384, 32768, 65536, 131072}[rand.Intn(6)], Disk: []int64{100, 200, 500, 1000}[rand.Intn(4)], Status: statuses[rand.Intn(len(statuses))], CPUUsage: rand.Float64() * 80, MemoryUsage: rand.Float64() * 80, DiskUsage: rand.Float64() * 70, Tags: fmt.Sprintf("{\"project\":\"project%d\",\"team\":\"team%d\"}", rand.Intn(10), rand.Intn(5)), Description: fmt.Sprintf("服务器 %d 描述", i+1), } servers = append(servers, server) } if err := db.Create(&servers).Error; err != nil { return err } fmt.Println("Generated servers:", len(servers)) return nil } func generateCloudAccounts(db *gorm.DB) error { accounts := []model.CloudAccount{ {Name: "阿里云主账号", Provider: "aliyun", Status: "active", MonthlyCost: 28500}, {Name: "腾讯云主账号", Provider: "tencent", Status: "active", MonthlyCost: 15800}, {Name: "AWS 账号", Provider: "aws", Status: "active", MonthlyCost: 42000}, {Name: "华为云账号", Provider: "huawei", Status: "inactive", MonthlyCost: 8900}, } for i := range accounts { accounts[i].AccessKey = "LTAI" + randomString(16) accounts[i].SecretKey = randomString(32) if err := db.Create(&accounts[i]).Error; err != nil { return err } } fmt.Println("Generated cloud accounts:", len(accounts)) return nil } func generateDomains(db *gorm.DB) error { domains := []model.Domain{ {Name: "ezops.local", Registrar: "aliyun", Status: "active", DNSProvider: "alidns"}, {Name: "api.ezops.local", Registrar: "aliyun", Status: "active", DNSProvider: "alidns"}, {Name: "app.ezops.local", Registrar: "tencent", Status: "active", DNSProvider: "dnspod"}, {Name: "monitor.ezops.local", Registrar: "aliyun", Status: "active", DNSProvider: "alidns", SSLEnabled: true}, } for i := range domains { expireDays := rand.Intn(365) + 30 expireDate := time.Now().AddDate(0, 0, expireDays) domains[i].ExpireDate = &expireDate domains[i].SSLExpireDate = &expireDate if err := db.Create(&domains[i]).Error; err != nil { return err } } fmt.Println("Generated domains:", len(domains)) return nil } func generateKubernetesClusters(db *gorm.DB) error { clusters := []model.KubernetesCluster{ {Name: "prod-cluster", Code: "prod", Version: "v1.28.0", Status: "healthy", NodeCount: 10, PodCount: 150, ServiceCount: 30, DeploymentCount: 15, APIEndpoint: "https://prod-api.ezops.local:6443", CPUUsage: 65.5, MemoryUsage: 72.3, Description: "生产环境 Kubernetes 集群"}, {Name: "staging-cluster", Code: "staging", Version: "v1.28.0", Status: "healthy", NodeCount: 5, PodCount: 80, ServiceCount: 15, DeploymentCount: 10, APIEndpoint: "https://staging-api.ezops.local:6443", CPUUsage: 45.2, MemoryUsage: 55.0, Description: "预发环境 Kubernetes 集群"}, {Name: "dev-cluster", Code: "dev", Version: "v1.27.0", Status: "warning", NodeCount: 3, PodCount: 45, ServiceCount: 8, DeploymentCount: 8, APIEndpoint: "https://dev-api.ezops.local:6443", CPUUsage: 80.1, MemoryUsage: 85.0, Description: "开发环境 Kubernetes 集群"}, {Name: "test-cluster", Code: "test", Version: "v1.27.0", Status: "error", NodeCount: 2, PodCount: 20, ServiceCount: 5, DeploymentCount: 5, APIEndpoint: "https://test-api.ezops.local:6443", CPUUsage: 30.0, MemoryUsage: 40.0, Description: "测试环境 Kubernetes 集群"}, } for i := range clusters { if err := db.Create(&clusters[i]).Error; err != nil { return err } } for _, cluster := range clusters { // 生成节点 for j := 0; j < cluster.NodeCount; j++ { node := model.KubernetesNode{ ClusterID: cluster.ID, Name: fmt.Sprintf("%s-node-%d", cluster.Code, j+1), IP: fmt.Sprintf("192.168.%d.%d", rand.Intn(256), rand.Intn(256)), Status: []string{"Ready", "Ready", "Ready", "NotReady"}[rand.Intn(4)], Role: []string{"master", "worker", "worker"}[rand.Intn(3)], CPU: []int{4, 8, 16}[rand.Intn(3)], Memory: []int64{16384, 32768, 65536}[rand.Intn(3)], Disk: []int64{100, 200, 500}[rand.Intn(3)], CPUUsage: rand.Float64() * 80, MemoryUsage: rand.Float64() * 80, DiskUsage: rand.Float64() * 70, PodCount: rand.Intn(30) + 5, MaxPods: 110, OS: "Ubuntu 22.04.3 LTS", KubeletVer: cluster.Version, } if err := db.Create(&node).Error; err != nil { return err } } // 生成 Deployments depImages := []string{ "nginx:1.25.3", "redis:7.2-alpine", "mysql:8.0.35", "kafka:3.6.0", "elasticsearch:8.11.0", "grafana/grafana:10.2.0", "prom/prometheus:v2.48.0", "busybox:1.36", "easzlab/kubeasz:3.6.1", } depNames := []string{ "nginx-deploy", "redis-cluster", "mysql-master", "mysql-slave", "kafka-broker", "es-cluster", "grafana", "prometheus", "filebeat", "logstash", "jaeger", "zipkin", "frontend", "backend-api", "gateway", } namespaces := []string{"default", "kube-system", "monitoring", "ingress-nginx", "production"} numDeps := cluster.DeploymentCount if numDeps < 5 { numDeps = 5 + rand.Intn(10) } for d := 0; d < numDeps && d < len(depNames); d++ { replicas := []int{1, 2, 3, 5}[rand.Intn(4)] available := replicas if rand.Intn(4) == 0 { available = replicas - 1 } if available < 0 { available = 0 } dep := model.KubernetesDeployment{ ClusterID: cluster.ID, Namespace: namespaces[rand.Intn(len(namespaces))], Name: depNames[d], Replicas: replicas, AvailableReplicas: available, ReadyReplicas: available, Image: depImages[rand.Intn(len(depImages))], Strategy: "RollingUpdate", } if err := db.Create(&dep).Error; err != nil { return err } } // 生成 Pods podStatuses := []string{"Running", "Running", "Running", "Running", "Pending", "CrashLoopBackOff"} numPods := cluster.PodCount if numPods > 30 { numPods = 30 } if numPods < 10 { numPods = 10 + rand.Intn(15) } for p := 0; p < numPods; p++ { status := podStatuses[rand.Intn(len(podStatuses))] pod := model.KubernetesPod{ ClusterID: cluster.ID, Namespace: namespaces[rand.Intn(len(namespaces))], Name: fmt.Sprintf("%s-pod-%d", cluster.Code, p+1), Status: status, NodeName: fmt.Sprintf("%s-node-%d", cluster.Code, rand.Intn(cluster.NodeCount)+1), IP: fmt.Sprintf("10.%d.%d.%d", rand.Intn(256), rand.Intn(256), rand.Intn(256)), RestartCount: rand.Intn(10), Image: depImages[rand.Intn(len(depImages))], CPUUsage: rand.Float64() * 500, MemoryUsage: rand.Float64() * 2048, } if err := db.Create(&pod).Error; err != nil { return err } } // 生成 Services svcTypes := []string{"ClusterIP", "NodePort", "LoadBalancer"} svcNames := []string{ "nginx-svc", "redis-svc", "mysql-svc", "kafka-svc", "es-svc", "grafana-svc", "prometheus-svc", "frontend-svc", "backend-svc", "gateway-svc", } numSvcs := cluster.ServiceCount if numSvcs > 10 { numSvcs = 10 } if numSvcs < 5 { numSvcs = 5 + rand.Intn(5) } for s := 0; s < numSvcs && s < len(svcNames); s++ { svcType := svcTypes[rand.Intn(len(svcTypes))] ports := "[]" switch rand.Intn(4) { case 0: ports = `[{"port":80,"protocol":"TCP","targetPort":80}]` case 1: ports = `[{"port":443,"protocol":"TCP","targetPort":8443}]` case 2: ports = `[{"port":8080,"protocol":"TCP","targetPort":8080},{"port":9090,"protocol":"TCP","targetPort":9090}]` default: ports = `[{"port":3306,"protocol":"TCP","targetPort":3306}]` } svc := model.KubernetesService{ ClusterID: cluster.ID, Namespace: namespaces[rand.Intn(len(namespaces))], Name: svcNames[s], Type: svcType, ClusterIP: fmt.Sprintf("10.96.%d.%d", rand.Intn(256), rand.Intn(256)), ExternalIP: "", Ports: ports, Selector: fmt.Sprintf(`{"app":"%s"}`, svcNames[s]), } if svcType == "LoadBalancer" { svc.ExternalIP = fmt.Sprintf("203.0.113.%d", rand.Intn(256)) } if svcType == "NodePort" { svc.ExternalIP = fmt.Sprintf("%d-%d", 30000+rand.Intn(1000), 32767) } if err := db.Create(&svc).Error; err != nil { return err } } // 生成 Ingresses ingNames := []string{"main-ingress", "api-ingress", "grafana-ingress", "canary-ingress"} numIngs := 2 + rand.Intn(3) for ig := 0; ig < numIngs && ig < len(ingNames); ig++ { hosts := fmt.Sprintf(`["%s.ezops.local"]`, ingNames[ig]) ing := model.KubernetesIngress{ ClusterID: cluster.ID, Namespace: namespaces[rand.Intn(len(namespaces))], Name: ingNames[ig], Hosts: hosts, Backend: fmt.Sprintf("%s-svc:80", ingNames[ig]), TLS: rand.Intn(2) == 0, } if err := db.Create(&ing).Error; err != nil { return err } } } fmt.Println("Generated K8s clusters:", len(clusters)) return nil } func generateAlertRules(db *gorm.DB) error { rules := []model.AlertRule{ {Name: "CPU 使用率告警", Type: "metric", Source: "prometheus", Expression: "cpu_usage > 80", Severity: "warning", Duration: 300, Enabled: true, Description: "CPU 使用率超过 80%"}, {Name: "CPU 使用率严重告警", Type: "metric", Source: "prometheus", Expression: "cpu_usage > 95", Severity: "critical", Duration: 120, Enabled: true, Description: "CPU 使用率超过 95%"}, {Name: "内存使用率告警", Type: "metric", Source: "prometheus", Expression: "memory_usage > 80", Severity: "warning", Duration: 300, Enabled: true, Description: "内存使用率超过 80%"}, {Name: "磁盘使用率告警", Type: "metric", Source: "prometheus", Expression: "disk_usage > 80", Severity: "warning", Duration: 600, Enabled: true, Description: "磁盘使用率超过 80%"}, {Name: "服务不可用告警", Type: "event", Source: "custom", Expression: "service_up == 0", Severity: "critical", Duration: 60, Enabled: true, Description: "服务不可用"}, {Name: "Pod 重启告警", Type: "event", Source: "kubernetes", Expression: "pod_restart > 5", Severity: "warning", Duration: 600, Enabled: true, Description: "Pod 重启次数超过 5 次"}, } for i := range rules { if err := db.Create(&rules[i]).Error; err != nil { return err } } for i := 0; i < 20; i++ { rule := rules[rand.Intn(len(rules))] event := model.AlertEvent{ RuleID: rule.ID, RuleName: rule.Name, Severity: rule.Severity, Status: []string{"firing", "resolved"}[rand.Intn(2)], Target: fmt.Sprintf("server-%03d", rand.Intn(50)+1), Message: fmt.Sprintf("告警事件 %d", i+1), Value: rand.Float64() * 100, StartedAt: time.Now().Add(-time.Duration(rand.Intn(72)) * time.Hour), } if err := db.Create(&event).Error; err != nil { return err } } fmt.Println("Generated alert rules:", len(rules)) return nil } func generateNotifyChannels(db *gorm.DB) error { channels := []model.NotifyChannel{ {Name: "运维邮件通知", Type: "email", Config: `{"recipients":["ops@ezops.com","admin@ezops.com"],"subject":"[AIOps告警]"}`, Enabled: true, TestStatus: "success"}, {Name: "短信通知", Type: "sms", Config: `{"phones":["13800138000","13900139000"],"template":"告警:{{alert_name}}"}`, Enabled: true, TestStatus: "success"}, {Name: "钉钉机器人", Type: "dingtalk", Config: `{"webhook":"https://oapi.dingtalk.com/robot/send?access_token=eZOps***","secret":"SEC***","at_all":false}`, Enabled: true, TestStatus: "success"}, {Name: "企业微信机器人", Type: "wechat", Config: `{"webhook":"https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=eZOps***"}`, Enabled: true, TestStatus: "success"}, {Name: "通用Webhook", Type: "webhook", Config: `{"url":"https://api.ezops.com/alerts/webhook","method":"POST","headers":{"Authorization":"Bearer ***"}}`, Enabled: false, TestStatus: "pending"}, } for i := range channels { if err := db.Create(&channels[i]).Error; err != nil { return err } } fmt.Println("Generated notify channels:", len(channels)) return nil } func generatePipelines(db *gorm.DB) error { pipelines := []model.Pipeline{ {Name: "前端构建", Code: "frontend-build", Type: "build", Source: "https://gitlab.com/ezops/frontend", Branch: "main", Enabled: true, Description: "前端项目构建流水线"}, {Name: "后端构建", Code: "backend-build", Type: "build", Source: "https://gitlab.com/ezops/backend", Branch: "main", Enabled: true, Description: "后端项目构建流水线"}, {Name: "部署预发", Code: "deploy-staging", Type: "deploy", Source: "https://gitlab.com/ezops/deploy", Branch: "staging", Enabled: true, Description: "部署到预发环境"}, {Name: "部署生产", Code: "deploy-production", Type: "deploy", Source: "https://gitlab.com/ezops/deploy", Branch: "main", Enabled: true, Description: "部署到生产环境"}, {Name: "集成测试", Code: "integration-test", Type: "test", Source: "https://gitlab.com/ezops/tests", Branch: "main", Enabled: true, Description: "集成测试流水线"}, } for i := range pipelines { if err := db.Create(&pipelines[i]).Error; err != nil { return err } } for _, pipeline := range pipelines { for j := 0; j < 5; j++ { run := model.PipelineRun{ PipelineID: pipeline.ID, BuildNumber: j + 1, Status: []string{"success", "success", "success", "failed", "running"}[rand.Intn(5)], Branch: pipeline.Branch, CommitID: randomString(8), CommitMsg: "Update " + randomString(6), Author: []string{"admin", "ops01", "dev01"}[rand.Intn(3)], TriggeredBy: []string{"admin", "ops01", "dev01"}[rand.Intn(3)], } if err := db.Create(&run).Error; err != nil { return err } } } fmt.Println("Generated pipelines:", len(pipelines)) return nil } func generateAppReleases(db *gorm.DB) error { apps := []string{"AIOps 前端", "AIOps 后端", "用户中心", "支付网关", "数据分析平台"} environments := []string{"dev", "test", "staging", "prod"} statuses := []string{"pending", "building", "deploying", "success", "success", "success", "failed", "rolled_back"} authors := []string{"admin", "ops01", "dev01"} releases := make([]model.AppRelease, 0, 10) for i := 0; i < 10; i++ { app := apps[i%len(apps)] env := environments[rand.Intn(len(environments))] status := statuses[rand.Intn(len(statuses))] minor := rand.Intn(20) patch := rand.Intn(10) release := model.AppRelease{ AppName: app, Version: fmt.Sprintf("v1.%d.%d", minor, patch), Environment: env, Status: status, CommitID: randomString(8), CommitMsg: fmt.Sprintf("feat: 更新 %s 功能", app), Author: authors[rand.Intn(len(authors))], Duration: rand.Intn(600) + 60, Description: fmt.Sprintf("%s %s 环境发布", app, env), } // Set timestamps and approval fields based on status now := time.Now() hoursAgo := time.Duration(rand.Intn(168)+1) * time.Hour if status == "success" || status == "failed" { approver := authors[rand.Intn(len(authors))] release.Approver = approver approvedAt := now.Add(-hoursAgo + 30*time.Minute) release.ApprovedAt = &approvedAt deployedAt := now.Add(-hoursAgo + 2*time.Hour) release.DeployedAt = &deployedAt } else if status == "rolled_back" { approver := authors[rand.Intn(len(authors))] release.Approver = approver approvedAt := now.Add(-hoursAgo + 30*time.Minute) release.ApprovedAt = &approvedAt deployedAt := now.Add(-hoursAgo + 2*time.Hour) release.DeployedAt = &deployedAt rollbackAt := now.Add(-hoursAgo + 4*time.Hour) release.RollbackAt = &rollbackAt } releases = append(releases, release) } for i := range releases { if err := db.Create(&releases[i]).Error; err != nil { return err } } fmt.Println("Generated app releases:", len(releases)) return nil } func generateCronJobs(db *gorm.DB) error { cronJobs := []model.CronJob{ {Name: "数据库备份", CronExpr: "0 2 * * *", Type: "script", Content: "/scripts/backup-db.sh", Enabled: true, Description: "每日凌晨 2 点备份数据库"}, {Name: "清理日志", CronExpr: "0 3 * * 0", Type: "command", Content: "find /var/log -mtime +30 -delete", Enabled: true, Description: "每周日凌晨 3 点清理日志"}, {Name: "数据同步", CronExpr: "*/30 * * * *", Type: "script", Content: "/scripts/sync-data.sh", Enabled: true, Description: "每 30 分钟同步数据"}, {Name: "健康检查", CronExpr: "*/5 * * * *", Type: "command", Content: "curl -sf http://localhost:8080/health", Enabled: true, Description: "每 5 分钟健康检查"}, {Name: "生成报表", CronExpr: "0 9 * * 1", Type: "script", Content: "/scripts/generate-report.sh", Enabled: false, Description: "每周一上午 9 点生成报表"}, } for i := range cronJobs { if err := db.Create(&cronJobs[i]).Error; err != nil { return err } } fmt.Println("Generated cron jobs:", len(cronJobs)) return nil } func generateScripts(db *gorm.DB) error { scripts := []model.Script{ {Name: "重启服务", Code: "restart-service", Type: "shell", Content: "#!/bin/bash\nsystemctl restart $1", Description: "重启服务脚本"}, {Name: "检查磁盘", Code: "check-disk", Type: "shell", Content: "#!/bin/bash\ndf -h", Description: "检查磁盘空间"}, {Name: "检查内存", Code: "check-memory", Type: "shell", Content: "#!/bin/bash\nfree -h", Description: "检查内存使用"}, {Name: "部署应用", Code: "deploy-app", Type: "python", Content: "#!/usr/bin/env python3\nimport sys\nprint(f'Deploying {sys.argv[1]}')", Description: "部署应用脚本"}, {Name: "备份配置", Code: "backup-config", Type: "shell", Content: "#!/bin/bash\ntar -czf /backup/config-$(date +%Y%m%d).tar.gz /etc/ezops", Description: "备份配置文件"}, } for i := range scripts { if err := db.Create(&scripts[i]).Error; err != nil { return err } } fmt.Println("Generated scripts:", len(scripts)) return nil } func generateApprovalTemplates(db *gorm.DB) error { templates := []model.ApprovalTemplate{ {Name: "服务器申请审批", Code: "server-request", Type: "server", Enabled: true, Description: "服务器资源申请审批流程"}, {Name: "发布审批", Code: "release-approval", Type: "release", Enabled: true, Description: "应用发布审批流程"}, {Name: "权限申请审批", Code: "permission-request", Type: "permission", Enabled: true, Description: "系统权限申请审批流程"}, } for i := range templates { if err := db.Create(&templates[i]).Error; err != nil { return err } } fmt.Println("Generated approval templates:", len(templates)) return nil } func generateNavigations(db *gorm.DB) error { groups := []model.NavigationGroup{ {Name: "常用工具", Code: "tools", Icon: "Tool", Sort: 1, Enabled: true}, {Name: "监控平台", Code: "monitor", Icon: "Activity", Sort: 2, Enabled: true}, {Name: "开发工具", Code: "devtools", Icon: "Code", Sort: 3, Enabled: true}, {Name: "文档中心", Code: "docs", Icon: "FileText", Sort: 4, Enabled: true}, } for i := range groups { if err := db.Create(&groups[i]).Error; err != nil { return err } } links := []model.NavigationLink{ {GroupID: groups[0].ID, Name: "GitLab", URL: "https://gitlab.com", Icon: "GitBranch", Description: "代码仓库", Sort: 1}, {GroupID: groups[0].ID, Name: "Jenkins", URL: "https://jenkins.io", Icon: "Settings", Description: "CI/CD 工具", Sort: 2}, {GroupID: groups[0].ID, Name: "Nexus", URL: "https://www.sonatype.com/nexus-repository-oss", Icon: "Package", Description: "制品库", Sort: 3}, {GroupID: groups[1].ID, Name: "Prometheus", URL: "https://prometheus.io", Icon: "Activity", Description: "监控系统", Sort: 1}, {GroupID: groups[1].ID, Name: "Grafana", URL: "https://grafana.com", Icon: "BarChart", Description: "可视化平台", Sort: 2}, {GroupID: groups[1].ID, Name: "ELK", URL: "https://www.elastic.co/what-is/elk-stack", Icon: "Search", Description: "日志分析", Sort: 3}, {GroupID: groups[2].ID, Name: "Swagger", URL: "https://swagger.io", Icon: "FileCode", Description: "API 文档", Sort: 1}, {GroupID: groups[2].ID, Name: "Postman", URL: "https://www.postman.com", Icon: "Send", Description: "API 测试", Sort: 2}, {GroupID: groups[3].ID, Name: "Confluence", URL: "https://www.atlassian.com/software/confluence", Icon: "BookOpen", Description: "知识库", Sort: 1}, } for i := range links { if err := db.Create(&links[i]).Error; err != nil { return err } } fmt.Println("Generated navigation groups:", len(groups)) fmt.Println("Generated navigation links:", len(links)) return nil } func generateBillings(db *gorm.DB) error { accounts := []struct { ID uint Name string Provider string }{ {1, "阿里云主账号", "aliyun"}, {2, "腾讯云生产环境", "tencent"}, {3, "AWS海外业务", "aws"}, {4, "华为云政务云", "huawei"}, } services := map[string][]string{ "aliyun": {"ECS云服务器", "RDS数据库", "OSS对象存储", "SLB负载均衡", "CDN加速"}, "tencent": {"CVM云服务器", "CDB数据库", "COS对象存储", "CLB负载均衡", "CDN加速"}, "aws": {"EC2", "RDS", "S3", "CloudFront", "Lambda"}, "huawei": {"ECS弹性云服务器", "RDS数据库", "OBS对象存储", "ELB弹性负载均衡"}, } now := time.Now() var billings []model.CloudBilling // 生成最近60天每天的账单 for day := 59; day >= 0; day-- { date := now.AddDate(0, 0, -day).Format("2006-01-02") for _, acc := range accounts { // 每个账号每天 1-3 条记录(不同服务) svcs := services[acc.Provider] count := 1 + rand.Intn(3) for i := 0; i < count; i++ { svc := svcs[rand.Intn(len(svcs))] cost := 50 + rand.Float64()*500 billings = append(billings, model.CloudBilling{ CloudAccountID: &acc.ID, AccountName: acc.Name, Provider: acc.Provider, BillingDate: date, Cost: cost, Currency: "CNY", Service: svc, }) } } } for i := range billings { if err := db.Create(&billings[i]).Error; err != nil { // skip duplicates continue } } fmt.Println("Generated cloud billings:", len(billings)) // 生成预警规则 rules := []model.BillingAlertRule{ {Name: "每日总成本超500元", Metric: "daily", Threshold: 500, Operator: ">", Enabled: true}, {Name: "阿里云日费用超300元", Provider: "aliyun", Metric: "daily", Threshold: 300, Operator: ">", Enabled: true}, {Name: "月度总成本超1万元", Metric: "monthly", Threshold: 10000, Operator: ">", Enabled: true}, } for i := range rules { db.Create(&rules[i]) } fmt.Println("Generated billing alert rules:", len(rules)) return nil } func randomString(length int) string { const charset = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789" b := make([]byte, length) for i := range b { b[i] = charset[rand.Intn(len(charset))] } return string(b) }