diff --git a/internal/cmd/make.binaries.go b/internal/cmd/make.binaries.go index a31b96c..64e9928 100644 --- a/internal/cmd/make.binaries.go +++ b/internal/cmd/make.binaries.go @@ -1,13 +1,8 @@ package cmd import ( - "os" - "path/filepath" - - "gitea.loveuer.com/yizhisec/pkg3/logger" "github.com/spf13/cobra" - "yizhisec.com/hsv2/forge/internal/opt" - "yizhisec.com/hsv2/forge/pkg/archiver" + "yizhisec.com/hsv2/forge/internal/controller/maker" ) func makeBinaries() *cobra.Command { @@ -16,34 +11,9 @@ func makeBinaries() *cobra.Command { Aliases: []string{"bin", "B"}, Short: "Build binary files", Long: `Build all required binary files for the project.`, - PreRunE: func(cmd *cobra.Command, args []string) error { - return os.MkdirAll(filepath.Join(opt.Cfg.Make.Dir, "dependency", "bin"), 0755) - }, RunE: func(cmd *cobra.Command, args []string) error { - var ( - tarURL = "https://artifactory.yizhisec.com:443/artifactory/filestore/hsv3/k8s-bin.tar" - binDir = filepath.Join(opt.Cfg.Make.Dir, "dependency") - ) - - logger.Info("开始准备 k8s 二进制文件...") - logger.Debug("下载地址: %s", tarURL) - logger.Debug("目标目录: %s", binDir) - - logger.Info("正在下载二进制文件...") - - if err := archiver.DownloadAndExtract( - cmd.Context(), - tarURL, - binDir, - archiver.WithInsecureSkipVerify(), - archiver.WithGzipCompression(true), - ); err != nil { - logger.Info("❌ 下载并解压二进制文件失败") - return err - } - - logger.Info("✅ 成功下载并解压二进制文件") - return nil + mk := maker.NewMaker() + return mk.Binary(cmd.Context()) }, } diff --git a/internal/cmd/make.debs.go b/internal/cmd/make.debs.go index 306f46c..e026939 100644 --- a/internal/cmd/make.debs.go +++ b/internal/cmd/make.debs.go @@ -1,13 +1,8 @@ package cmd import ( - "fmt" - "path/filepath" - - "gitea.loveuer.com/yizhisec/pkg3/logger" "github.com/spf13/cobra" - "yizhisec.com/hsv2/forge/internal/opt" - "yizhisec.com/hsv2/forge/pkg/archiver" + "yizhisec.com/hsv2/forge/internal/controller/maker" ) func makeDebs() *cobra.Command { @@ -17,32 +12,8 @@ func makeDebs() *cobra.Command { Short: "Build Debian packages", Long: `Build all required Debian packages for the project.`, RunE: func(cmd *cobra.Command, args []string) error { - fmt.Println("Building Debian packages...") - var ( - tarURL = "https://artifactory.yizhisec.com:443/artifactory/filestore/hsv3/deb/docker.tar.gz" - binDir = filepath.Join(opt.Cfg.Make.Dir, "dependency", "deb") - ) - - logger.Info("开始准备 deb(docker) 文件...") - logger.Debug("下载地址: %s", tarURL) - logger.Debug("目标目录: %s", binDir) - - logger.Info("正在下载二进制文件...") - - if err := archiver.DownloadAndExtract( - cmd.Context(), - tarURL, - binDir, - archiver.WithInsecureSkipVerify(), - archiver.WithGzipCompression(true), - ); err != nil { - logger.Info("❌ 下载并解压 deb(docker) 文件失败") - logger.Debug("下载并解压 deb(docker) 文件失败: %v", err) - return err - } - - logger.Info("✅ 成功下载并解压 deb(docker) 文件") - return nil + mk := maker.NewMaker() + return mk.Deb(cmd.Context()) }, } diff --git a/internal/cmd/make.emqx.go b/internal/cmd/make.emqx.go index 8567add..59b822b 100644 --- a/internal/cmd/make.emqx.go +++ b/internal/cmd/make.emqx.go @@ -1,13 +1,8 @@ package cmd import ( - "os" - "path/filepath" - - "gitea.loveuer.com/yizhisec/pkg3/logger" "github.com/spf13/cobra" - "yizhisec.com/hsv2/forge/internal/opt" - "yizhisec.com/hsv2/forge/pkg/resource" + "yizhisec.com/hsv2/forge/internal/controller/maker" ) func makeEMQX() *cobra.Command { @@ -15,28 +10,8 @@ func makeEMQX() *cobra.Command { Use: "emqx", Short: "Make EMQX", RunE: func(cmd *cobra.Command, args []string) error { - var ( - err error - location = filepath.Join(opt.Cfg.Make.Dir, "emqx") - ) - - logger.Info("MakeEMQX: 开始构建 emqx(mqtt) 依赖...") - - if err = os.MkdirAll(location, 0755); err != nil { - logger.Error("MakeEMQX: 创建 emqx 目录失败") - logger.Debug("MakeEMQX: 创建 emqx 目录失败: %v", err) - return err - } - - if err = os.WriteFile(filepath.Join(location, "emqx.yaml"), resource.YAMLEMQX, 0644); err != nil { - logger.Error("MakeEMQX: 写入 emqx.yaml 失败") - logger.Debug("MakeEMQX: 写入 emqx.yaml 失败, err: %v", err) - return err - } - - logger.Info("MakeEMQX: 构建 emqx(mqtt) 依赖成功!!!") - - return nil + mk := maker.NewMaker() + return mk.EMQX(cmd.Context()) }, } diff --git a/internal/cmd/make.es.go b/internal/cmd/make.es.go index ea2b7f8..2cad009 100644 --- a/internal/cmd/make.es.go +++ b/internal/cmd/make.es.go @@ -2,35 +2,12 @@ package cmd import ( "fmt" - "os" - "os/exec" - "path/filepath" - "gitea.loveuer.com/yizhisec/pkg3/logger" "github.com/spf13/cobra" "yizhisec.com/hsv2/forge/internal/controller/maker" - "yizhisec.com/hsv2/forge/internal/opt" - "yizhisec.com/hsv2/forge/pkg/archiver" - "yizhisec.com/hsv2/forge/pkg/resource" ) func makeES() *cobra.Command { - const ( - dockerFile = ` -FROM docker-mirror.yizhisec.com/library/alpine:3.22.2 - -WORKDIR /data - -RUN sed -i 's/dl-cdn.alpinelinux.org/mirrors.tuna.tsinghua.edu.cn/g' /etc/apk/repositories && apk add curl - -ENV TZ=Asia/Shanghai - -COPY plugins /data/plugins -COPY create_index.sh /data/create_index.sh -RUN chmod +x /data/create_index.sh -` - ) - var ( makeHelper bool memRate int @@ -41,114 +18,19 @@ RUN chmod +x /data/create_index.sh Use: "es", Aliases: []string{"elastic", "elasticsearch"}, RunE: func(cmd *cobra.Command, args []string) error { - var ( - err error - output []byte - location = filepath.Join(opt.Cfg.Make.Dir, "dependency", "elastic") - helperTarLocation = filepath.Join(opt.Cfg.Make.Dir, "dependency", "image", "es-init-helper.alpine-3.22.2.tar") - ) - - logger.Info("MakeES: 开始构建 elasticsearch(es) 依赖...") - - if err := os.MkdirAll(location, 0755); err != nil { - logger.Error("MakeES: 创建目录失败") - logger.Debug("MakeES: 创建目录失败: %v", err) - return err - } - - if makeHelper { - tmp := filepath.Join(os.TempDir(), "make-es") - logger.Info("MakeES: 重新构建 helper 镜像...(%s)", tmp) - - if err = os.RemoveAll(tmp); err != nil { - logger.Error("MakeES: 删除临时目录失败") - logger.Debug("MakeES: 删除临时目录失败: %v", err) - return err - } - - if err = os.MkdirAll(tmp, 0755); err != nil { - logger.Error("MakeES: 创建临时目录失败") - logger.Debug("MakeES: 创建临时目录失败: %v", err) - return err - } - - if err = os.WriteFile(filepath.Join(tmp, "Dockerfile"), []byte(dockerFile), 0644); err != nil { - logger.Error("MakeES: 写入 Dockerfile 失败") - logger.Debug("MakeES: 写入 Dockerfile 失败: %v", err) - return err - } - - if err = archiver.DownloadAndExtract( - cmd.Context(), - "https://artifactory.yizhisec.com:443/artifactory/filestore/hsv3/dependency/elasticsearch/v2-es-plugins.tar.gz", - tmp, - archiver.WithInsecureSkipVerify(), - ); err != nil { - logger.Error("MakeES: 下载 es 插件失败") - logger.Debug("MakeES: 下载 es 插件失败: %v", err) - return err - } - - if err = os.WriteFile(filepath.Join(tmp, "create_index.sh"), resource.BashESInit, 0644); err != nil { - logger.Error("MakeES: 写入 create_index.sh 文件失败") - logger.Debug("MakeES: 写入 create_index.sh 文件失败: %v", err) - return err - } - - helpCmd := exec.CommandContext(cmd.Context(), "docker", "build", "-t", - "hub.yizhisec.com/hybridscope/v2/es-init-helper:alpine-3.22.2", - "-f", filepath.Join(tmp, "Dockerfile"), - tmp, - ) - - if output, err = helpCmd.CombinedOutput(); err != nil { - logger.Error("MakeES: 重新构建 helper 镜像失败") - logger.Debug("MakeES: 重新构建 helper 镜像失败: %v", err) - logger.Debug("MakeES: 重新构建 helper 镜像失败: %s", string(output)) - return err - } - - logger.Info("MakeES: 重新构建 helper 镜像成功!!!") - } - mk := maker.NewMaker() - if err = mk.Image( + return mk.Elastic( cmd.Context(), - "hub.yizhisec.com/hybridscope/v2/es-init-helper:alpine-3.22.2", - maker.WithImageSave(helperTarLocation), - ); err != nil { - logger.Error("MakeES: 准备 es init helper 镜像失败") - logger.Debug("MakeES: 准备 es init helper 镜像失败: %v", err) - return err - } - - bs := []byte(fmt.Sprintf(resource.YAMLES, - memRate, memRate*2, - memRate, memRate, - memRate*2, memRate*2, - storage, - )) - - if err = os.WriteFile(filepath.Join(opt.Cfg.Make.Dir, "dependency", "elastic", "es.yaml"), bs, 0644); err != nil { - logger.Error("MakeES: 写入 es.yaml 文件失败") - logger.Debug("MakeES: 写入 es.yaml 文件失败: %v", err) - return err - } - - if err = os.WriteFile(filepath.Join(opt.Cfg.Make.Dir, "dependency", "elastic", "kibana.yaml"), resource.YAMLKibana, 0644); err != nil { - logger.Error("MakeES: 写入 es.yaml 文件失败") - logger.Debug("MakeES: 写入 es.yaml 文件失败: %v", err) - return err - } - - logger.Info("MakeES: 构建 elastic(es) 依赖成功!!!") - return nil + maker.WithElasticMakeHelper(makeHelper), + maker.WithElasticMemRate(memRate), + maker.WithElasticStorageGi(fmt.Sprintf("%dGi", storage)), + ) }, } _cmd.Flags().BoolVar(&makeHelper, "make-helper", false, "重新构建 helper 镜像") _cmd.Flags().IntVar(&memRate, "mem-rate", 1, "内存倍率(从 1G 开始)") - _cmd.Flags().IntVar(&storage, "storage", 100, "存储空间(单位: G)") + _cmd.Flags().IntVar(&storage, "storage-size", 100, "存储空间(单位: G)") return _cmd } diff --git a/internal/cmd/make.flannel.go b/internal/cmd/make.flannel.go index 93a2cf4..30d4999 100644 --- a/internal/cmd/make.flannel.go +++ b/internal/cmd/make.flannel.go @@ -1,46 +1,26 @@ package cmd import ( - "os" - "path/filepath" - - "gitea.loveuer.com/yizhisec/pkg3/logger" "github.com/spf13/cobra" - "yizhisec.com/hsv2/forge/internal/opt" - "yizhisec.com/hsv2/forge/pkg/resource" + "yizhisec.com/hsv2/forge/internal/controller/maker" ) func makeFlannel() *cobra.Command { + var ( + _mode string + ) + cmd := &cobra.Command{ Use: "flannel", Short: "Build Flannel resources", Long: `Build and prepare Flannel network resources.`, RunE: func(cmd *cobra.Command, args []string) error { - var ( - err error - location = filepath.Join(opt.Cfg.Make.Dir, "dependency", "flannel") - ) - - logger.Info("MakeFlannel: 开始构建 flannel 资源...") - - logger.Debug("MakeFlannel location: %s", location) - if err = os.Mkdir(location, 0755); err != nil { - logger.Error("MakeFlannel: 创建目录 %s 失败", location) - logger.Debug("MakeFlannel: 创建目录 %s 失败: %v", location, err) - return err - } - - if err = os.WriteFile(filepath.Join(location, "flannel.yaml"), resource.YAMLFlannel, 0644); err != nil { - logger.Error("MakeFlannel: 创建文件 %s 失败", filepath.Join(location, "flannel.yaml")) - logger.Debug("MakeFlannel: 创建文件 %s 失败: %v", filepath.Join(location, "flannel.yaml"), err) - return err - } - - logger.Info("MakeFlannel: 构建 flannel 成功!!!") - - return nil + mk := maker.NewMaker() + return mk.Flannel(cmd.Context(), _mode) }, } + cmd.Flags().StringVar(&_mode, "mode", "host-gw", "Flannel backend mode (vxlan or host-gw)") + return cmd } diff --git a/internal/cmd/make.hsnet.go b/internal/cmd/make.hsnet.go index 29a2aa5..db1d158 100644 --- a/internal/cmd/make.hsnet.go +++ b/internal/cmd/make.hsnet.go @@ -1,12 +1,8 @@ package cmd import ( - "os" - "path/filepath" - - "gitea.loveuer.com/yizhisec/pkg3/logger" "github.com/spf13/cobra" - "yizhisec.com/hsv2/forge/internal/opt" + "yizhisec.com/hsv2/forge/internal/controller/maker" ) func makeHSNet() *cobra.Command { @@ -15,20 +11,8 @@ func makeHSNet() *cobra.Command { Short: "Build hs-net", Long: `Build hs-net`, RunE: func(cmd *cobra.Command, args []string) error { - var ( - err error - location = filepath.Join(opt.Cfg.Make.Dir, "dependency", "hs-net") - ) - - if err = os.MkdirAll(location, 0755); err != nil { - logger.Error("MakeHSNet: 创建目录失败s") - logger.Debug("MakeHSNet: 创建目录失败: %s", err.Error()) - return err - } - - logger.Fatal("MakeHSNet: 构建 hs-net 失败!!!(怎么完善,怎么完善,怎么完善???)") - - return nil + mk := maker.NewMaker() + return mk.HSNet(cmd.Context()) }, } diff --git a/internal/cmd/make.images.go b/internal/cmd/make.images.go index 4a93c9c..3b3e5a9 100644 --- a/internal/cmd/make.images.go +++ b/internal/cmd/make.images.go @@ -15,87 +15,15 @@ func makeImages() *cobra.Command { Aliases: []string{"image"}, Short: "Build and pull Docker images", Long: `Build and pull all required Docker images for the project.`, - PreRunE: func(cmd *cobra.Command, args []string) error { - return os.MkdirAll(filepath.Join(opt.Cfg.Make.Dir, "dependency", "image"), 0755) - }, RunE: func(cmd *cobra.Command, args []string) error { - type Images struct { - Name string - Fallback string - Save string - Force bool - } - var images = []*Images{ - {Name: "quay.io/k0sproject/apiserver-network-proxy-agent:v0.32.0", Fallback: "hub.yizhisec.com/external/apiserver-network-proxy-agent:v0.32.0", Save: "k0s.apiserver-network-proxy-agent.tar"}, - {Name: "quay.io/k0sproject/cni-node:1.7.1-k0s.0", Fallback: "", Save: "k0s.cni-node.tar"}, - {Name: "quay.io/k0sproject/coredns:1.12.2", Fallback: "", Save: "k0s.coredns.tar"}, - {Name: "quay.io/k0sproject/kube-proxy:v1.33.4", Fallback: "", Save: "k0s.kube-proxy.tar"}, - {Name: "quay.io/k0sproject/kube-router:v2.5.0-iptables1.8.11-0", Fallback: "", Save: "k0s.kube-router.tar"}, - {Name: "quay.io/k0sproject/metrics-server:v0.7.2-0", Fallback: "", Save: "k0s.metrics-server.tar"}, - {Name: "quay.io/k0sproject/pause:3.10.1", Fallback: "", Save: "k0s.pause.tar"}, - - {Name: "ghcr.io/flannel-io/flannel:v0.27.4", Fallback: "swr.cn-north-4.myhuaweicloud.com/ddn-k8s/ghcr.io/flannel-io/flannel:v0.27.4", Save: "flannel.tar"}, - {Name: "ghcr.io/flannel-io/flannel-cni-plugin:v1.8.0-flannel1", Fallback: "swr.cn-north-4.myhuaweicloud.com/ddn-k8s/ghcr.io/flannel-io/flannel-cni-plugin:v1.8.0-flannel1", Save: "flannel-cni-plugin.tar"}, - - {Name: "docker.io/longhornio/longhorn-engine:v1.10.0", Fallback: "docker-mirror.yizhisec.com/longhornio/longhorn-engine:v1.10.0", Save: "longhorn.longhorn-engine.tar"}, - {Name: "docker.io/longhornio/longhorn-manager:v1.10.0", Fallback: "docker-mirror.yizhisec.com/longhornio/longhorn-manager:v1.10.0", Save: "longhorn.longhorn-manager.tar"}, - {Name: "docker.io/longhornio/longhorn-instance-manager:v1.10.0", Fallback: "docker-mirror.yizhisec.com/longhornio/longhorn-instance-manager:v1.10.0", Save: "longhorn.longhorn-instance-manager.tar"}, - {Name: "docker.io/longhornio/longhorn-share-manager:v1.10.0", Fallback: "docker-mirror.yizhisec.com/longhornio/longhorn-share-manager:v1.10.0", Save: "longhorn.longhorn-share-manager.tar"}, - {Name: "docker.io/longhornio/longhorn-ui:v1.10.0", Fallback: "docker-mirror.yizhisec.com/longhornio/longhorn-ui:v1.10.0", Save: "longhorn.longhorn-ui.tar"}, - {Name: "docker.io/longhornio/csi-snapshotter:v8.3.0-20250826", Fallback: "docker-mirror.yizhisec.com/longhornio/csi-snapshotter:v8.3.0-20250826", Save: "longhorn.csi-snapshotter.tar"}, - {Name: "docker.io/longhornio/csi-resizer:v1.14.0-20250826", Fallback: "docker-mirror.yizhisec.com/longhornio/csi-resizer:v1.14.0-20250826", Save: "longhorn.csi-resizer.tar"}, - {Name: "docker.io/longhornio/csi-provisioner:v5.3.0-20250826", Fallback: "docker-mirror.yizhisec.com/longhornio/csi-provisioner:v5.3.0-20250826", Save: "longhorn.csi-provisioner.tar"}, - {Name: "docker.io/longhornio/livenessprobe:v2.16.0-20250826", Fallback: "docker-mirror.yizhisec.com/longhornio/livenessprobe:v2.16.0-20250826", Save: "longhorn.livenessprobe.tar"}, - {Name: "docker.io/longhornio/csi-node-driver-registrar:v2.14.0-20250826", Fallback: "docker-mirror.yizhisec.com/longhornio/csi-node-driver-registrar:v2.14.0-20250826", Save: "longhorn.csi-node-driver-registrar.tar"}, - {Name: "docker.io/longhornio/csi-attacher:v4.9.0-20250826", Fallback: "docker-mirror.yizhisec.com/longhornio/csi-attacher:v4.9.0-20250826", Save: "longhorn.csi-attacher.tar"}, - - {Name: "hub.yizhisec.com/external/alpine:3.22.2", Fallback: "", Save: "alpine.tar", Force: true}, - {Name: "hub.yizhisec.com/external/nginx:1.29.1-alpine3.22", Fallback: "", Save: "nginx.1.29.1-alpine3.22.tar"}, - - {Name: "docker.io/bitpoke/mysql-operator:v0.6.3", Fallback: "docker-mirror.yizhisec.com/bitpoke/mysql-operator:v0.6.3", Save: "bitpoke.mysql-operator.v0.6.3.tar"}, - {Name: "docker.io/bitpoke/mysql-operator-orchestrator:v0.6.3", Fallback: "docker-mirror.yizhisec.com/bitpoke/mysql-operator-orchestrator:v0.6.3", Save: "bitpoke.mysql-operator-orchestrator.v0.6.3.tar"}, - {Name: "docker.io/bitpoke/mysql-operator-sidecar-8.0:v0.6.3", Fallback: "docker-mirror.yizhisec.com/bitpoke/mysql-operator-sidecar-8.0:v0.6.3", Save: "bitpoke.mysql-operator-sidecar-8.0.v0.6.3.tar"}, - {Name: "docker.io/library/percona:8.0.28-20", Fallback: "docker-mirror.yizhisec.com/library/percona:8.0.28-20", Save: "percona.8.0.28-20.tar"}, - {Name: "docker.io/prom/mysqld-exporter:v0.13.0", Fallback: "docker-mirror.yizhisec.com/prom/mysqld-exporter:v0.13.0", Save: "prom.mysqld-exporter.v0.13.0.tar"}, - - {Name: "docker.io/bitnami/redis:8.2.2", Fallback: "hub.yizhisec.com/external/bitnami/redis:8.2.2", Save: "bitnami.redis.8.2.2.tar"}, - {Name: "hub.yizhisec.com/external/elasticsearch:7.17.28", Fallback: "", Save: "elasticsearch.7.17.28.tar"}, - {Name: "hub.yizhisec.com/external/kibana:7.17.28", Fallback: "", Save: "kibana.7.17.28.tar"}, - {Name: "hub.yizhisec.com/external/emqx:5.1", Fallback: "", Save: "emqx.5.1.tar"}, - - {Name: "hub.yizhisec.com/build/hybirdscope/front/admin:latest", Fallback: "", Save: "app.front.admin.tar", Force: true}, - {Name: "hub.yizhisec.com/hybridscope/v2/front-user:latest", Fallback: "", Save: "app.front.user.tar", Force: true}, - {Name: "hub.yizhisec.com/hybridscope/user_management:latest", Fallback: "", Save: "app.user.tar", Force: true}, - {Name: "hub.yizhisec.com/hybridscope/gateway_controller:latest", Fallback: "", Save: "app.gateway.tar", Force: true}, - {Name: "hub.yizhisec.com/hybridscope/client_server:latest", Fallback: "", Save: "app.client.tar", Force: true}, - {Name: "hub.yizhisec.com/hybridscope/mie-server:latest", Fallback: "", Save: "app.mie.tar", Force: true}, - {Name: "hub.yizhisec.com/hybridscope/less_dns_service:latest", Fallback: "", Save: "app.less_dns.tar", Force: true}, - {Name: "hub.yizhisec.com/hybridscope/hsnet:release_2.1.0-std", Fallback: "", Save: "app.hsnet.tar", Force: true}, - } - - for _, image := range images { - image.Save = filepath.Join(opt.Cfg.Make.Dir, "dependency", "image", image.Save) + if err := os.MkdirAll(filepath.Join(opt.Cfg.Make.Dir, "dependency", "image"), 0755); err != nil { + return err } mk := maker.NewMaker() - for _, image := range images { - opts := []maker.ImageOpt{ - maker.WithImageFallback(image.Fallback), - maker.WithImageSave(image.Save), - } - - if image.Force { - opts = append(opts, maker.WithImageForcePull()) - } - - if err := mk.Image(cmd.Context(), image.Name, opts...); err != nil { - return err - } - } - - return nil + return mk.Images(cmd.Context()) }, } diff --git a/internal/cmd/make.lessdns.go b/internal/cmd/make.lessdns.go index 58bba81..37b5d25 100644 --- a/internal/cmd/make.lessdns.go +++ b/internal/cmd/make.lessdns.go @@ -1,13 +1,8 @@ package cmd import ( - "os" - "path/filepath" - - "gitea.loveuer.com/yizhisec/pkg3/logger" "github.com/spf13/cobra" - "yizhisec.com/hsv2/forge/internal/opt" - "yizhisec.com/hsv2/forge/pkg/resource" + "yizhisec.com/hsv2/forge/internal/controller/maker" ) func makeLessDNS() *cobra.Command { @@ -16,27 +11,8 @@ func makeLessDNS() *cobra.Command { Short: "Build lessdns", Long: `Build lessdns`, RunE: func(cmd *cobra.Command, args []string) error { - var ( - err error - location = filepath.Join(opt.Cfg.Make.Dir, "dependency", "less-dns") - ) - - logger.Info("MakeLessDNS: 开始构建 less-dns...") - if err = os.MkdirAll(location, 0755); err != nil { - logger.Error("MakeLessDNS: 创建目录失败s") - logger.Debug("MakeLessDNS: 创建目录失败: %s", err.Error()) - return err - } - - if err = os.WriteFile(filepath.Join(location, "deployment.yaml"), resource.YAMLLessDNS, 0644); err != nil { - logger.Error("MakeLessDNS: 写入文件失败") - logger.Debug("MakeLessDNS: 写入文件失败: %s", err.Error()) - return err - } - - logger.Info("MakeLessDNS: 构建 less-dns 成功!!!") - - return nil + mk := maker.NewMaker() + return mk.LessDNS(cmd.Context()) }, } diff --git a/internal/cmd/make.longhorn.go b/internal/cmd/make.longhorn.go index 1f9b04b..b001adc 100644 --- a/internal/cmd/make.longhorn.go +++ b/internal/cmd/make.longhorn.go @@ -1,27 +1,11 @@ package cmd import ( - "fmt" - "os" - "path/filepath" - - "gitea.loveuer.com/yizhisec/pkg3/logger" "github.com/spf13/cobra" - "yizhisec.com/hsv2/forge/internal/opt" - "yizhisec.com/hsv2/forge/pkg/downloader" + "yizhisec.com/hsv2/forge/internal/controller/maker" ) func makeLonghorn() *cobra.Command { - const ( - valuesContent = `# 设置 Longhorn 数据存储路径 -defaultSettings: - defaultDataPath: "/data/longhorn" -# 设置默认副本数 -persistence: - reclaimPolicy: Retain - defaultClassReplicaCount: %d -` - ) var ( replicaCount int ) @@ -30,49 +14,9 @@ persistence: Use: "longhorn", Short: "Build Longhorn resources", Long: `Build and prepare Longhorn storage resources.`, - PreRunE: func(cmd *cobra.Command, args []string) error { - return os.MkdirAll(filepath.Join(opt.Cfg.Make.Dir, "dependency", "longhorn"), 0755) - }, RunE: func(cmd *cobra.Command, args []string) error { - var ( - chartURL = "https://artifactory.yizhisec.com:443/artifactory/filestore/hsv3/charts/longhorn-1.10.0.tgz" - longhornDir = filepath.Join(opt.Cfg.Make.Dir, "dependency", "longhorn") - chartFile = filepath.Join(longhornDir, "longhorn-1.10.0.tgz") - valuesFile = filepath.Join(longhornDir, "values.yaml") - ) - - logger.Info("开始准备 Longhorn 资源...") - logger.Debug("下载地址: %s", chartURL) - logger.Debug("目标目录: %s", longhornDir) - - logger.Info("正在下载 Longhorn chart...") - - // Download the chart file - if err := downloader.Download( - cmd.Context(), - chartURL, - chartFile, - downloader.WithInsecureSkipVerify(), - ); err != nil { - logger.Info("❌ 下载 Longhorn chart 失败") - return err - } - - logger.Info("✅ 成功下载 Longhorn chart") - - // Create values.yaml file - bs := []byte(fmt.Sprintf(valuesContent, replicaCount)) - logger.Debug("创建 values.yaml 文件: %s", valuesFile) - if err := os.WriteFile(valuesFile, bs, 0644); err != nil { - logger.Debug("创建 values.yaml 失败: %v", err) - logger.Info("❌ 创建 values.yaml 失败") - return err - } - - logger.Info("✅ 成功创建 values.yaml") - logger.Debug("Longhorn 资源准备完成") - - return nil + mk := maker.NewMaker() + return mk.Longhorn(cmd.Context(), replicaCount) }, } diff --git a/internal/cmd/make.mysql.go b/internal/cmd/make.mysql.go index 1197b34..f4d432f 100644 --- a/internal/cmd/make.mysql.go +++ b/internal/cmd/make.mysql.go @@ -2,79 +2,12 @@ package cmd import ( "fmt" - "os" - "path/filepath" - "gitea.loveuer.com/yizhisec/pkg3/logger" "github.com/spf13/cobra" - "yizhisec.com/hsv2/forge/internal/opt" - "yizhisec.com/hsv2/forge/pkg/downloader" + "yizhisec.com/hsv2/forge/internal/controller/maker" ) func makeMysql() *cobra.Command { - const ( - _yaml = ` -apiVersion: v1 -kind: Secret -metadata: - name: mysql-secret - namespace: db-mysql -type: Opaque -data: - ROOT_PASSWORD: TDBoTXlzcWwu ---- - -apiVersion: mysql.presslabs.org/v1alpha1 -kind: MysqlCluster -metadata: - name: mysql-cluster - namespace: db-mysql -spec: - mysqlVersion: "8.0" - replicas: %d - image: docker.io/library/percona:8.0.28-20 - secretName: mysql-secret - volumeSpec: - persistentVolumeClaim: - accessModes: ["ReadWriteOnce"] - storageClassName: longhorn - resources: - requests: - storage: %dGi -# podSpec: -# affinity: -# podAntiAffinity: -# requiredDuringSchedulingIgnoredDuringExecution: # 强制规则 -# - labelSelector: -# matchExpressions: -# - key: app.kubernetes.io/name -# operator: In -# values: ["mysql"] -# - key: app.kubernetes.io/instance -# operator: In -# values: ["mysql-cluster"] -# topologyKey: "kubernetes.io/hostname" # 确保不同节点 -# resources: -# requests: -# cpu: "2" -# memory: "2Gi" -# limits: -# cpu: "8" -# memory: "8Gi" ---- - -apiVersion: mysql.presslabs.org/v1alpha1 -kind: MysqlDatabase -metadata: - name: my-database-mie - namespace: db-mysql -spec: - database: mie - clusterRef: - name: mysql-cluster - namespace: db-mysql -` - ) var ( replicas int @@ -85,55 +18,19 @@ spec: Use: "mysql", Short: "Build MySQL resources", Long: `Build and prepare MySQL database resources.`, - PreRunE: func(cmd *cobra.Command, args []string) error { - return os.MkdirAll(filepath.Join(opt.Cfg.Make.Dir, "dependency", "mysql"), 0755) - }, RunE: func(cmd *cobra.Command, args []string) error { - var ( - err error - chartURL = "https://artifactory.yizhisec.com:443/artifactory/filestore/hsv3/charts/mysql-operator-0.6.3.tgz" - mysqlDir = filepath.Join(opt.Cfg.Make.Dir, "dependency", "mysql") - chartFile = filepath.Join(mysqlDir, "mysql-operator-0.6.3.tgz") - clusterFile = filepath.Join(mysqlDir, "cluster.yaml") - ) - - logger.Info("开始构建 MySQL 资源...") - logger.Debug("下载地址: %s", chartURL) - logger.Debug("目标目录: %s", mysqlDir) - - // Download MySQL operator chart - logger.Info("正在下载 MySQL operator chart...") - if err := downloader.Download( - cmd.Context(), - chartURL, - chartFile, - downloader.WithInsecureSkipVerify(), - ); err != nil { - logger.Info("❌ 下载 MySQL operator chart 失败") - return err - } - logger.Info("✅ 成功下载 MySQL operator chart") - - bs := []byte(fmt.Sprintf(_yaml, replicas, storage)) - - // Generate secret.yaml - if err = os.WriteFile(clusterFile, bs, 0644); err != nil { - logger.Debug("创建 database.yaml 失败: %v", err) - logger.Info("❌ 创建 database.yaml 失败") - return err + opts := []maker.MysqlOpt{ + maker.WithMySQLReplica(replicas), + maker.WithMySQLStorage(fmt.Sprintf("%dGi", storage)), } - logger.Info("✅ 成功创建 database.yaml") - - logger.Info("✅ MySQL 资源构建成功") - logger.Debug("MySQL 资源准备完成") - - return nil + mk := maker.NewMaker() + return mk.MySQL(cmd.Context(), opts...) }, } _cmd.Flags().IntVar(&replicas, "replica-count", 2, "mysql 的副本数") - _cmd.Flags().IntVar(&storage, "storage-size", 50, "mysql 的存储空间") + _cmd.Flags().IntVar(&storage, "storage-size", 50, "mysql 的存储空间(GB)") return _cmd } diff --git a/internal/cmd/make.redis.go b/internal/cmd/make.redis.go index 0bc73f8..faa1eeb 100644 --- a/internal/cmd/make.redis.go +++ b/internal/cmd/make.redis.go @@ -1,127 +1,35 @@ package cmd import ( - "fmt" - "os" - "path/filepath" - - "gitea.loveuer.com/yizhisec/pkg3/logger" "github.com/spf13/cobra" - "yizhisec.com/hsv2/forge/internal/opt" - "yizhisec.com/hsv2/forge/pkg/downloader" + "yizhisec.com/hsv2/forge/internal/controller/maker" ) func makeRedis() *cobra.Command { - const ( - valuesTemplate = `# Redis configuration -architecture: replication - -image: - registry: docker.io - repository: bitnami/redis - tag: 8.2.2 - pullPolicy: IfNotPresent - -auth: - enabled: true - password: "%s" - -master: - persistence: - enabled: true - storageClass: "longhorn" - size: 5Gi -# resources: -# requests: -# memory: "512Mi" -# cpu: "250m" -# limits: -# memory: "1Gi" -# cpu: "500m" - -replica: - replicaCount: %d - persistence: - enabled: true - storageClass: "longhorn" - size: 5Gi -# resources: -# requests: -# memory: "512Mi" -# cpu: "250m" -# limits: -# memory: "1Gi" -# cpu: "500m" - -metrics: - enabled: false - serviceMonitor: - enabled: false -` - defaultPassword = "HybridScope0xRed1s." - ) - var ( replicas int password string + storage string ) _cmd := &cobra.Command{ Use: "redis", Short: "Build Redis resources", Long: `Build and prepare Redis cache resources.`, - PreRunE: func(cmd *cobra.Command, args []string) error { - return os.MkdirAll(filepath.Join(opt.Cfg.Make.Dir, "dependency", "redis"), 0755) - }, RunE: func(cmd *cobra.Command, args []string) error { - var ( - chartURL = "https://artifactory.yizhisec.com:443/artifactory/filestore/hsv3/charts/redis-23.2.2.tgz" - redisDir = filepath.Join(opt.Cfg.Make.Dir, "dependency", "redis") - chartFile = filepath.Join(redisDir, "redis-23.2.2.tgz") - valuesFile = filepath.Join(redisDir, "values.yaml") - ) - - if password == "******" { - password = defaultPassword - } - - logger.Info("开始构建 Redis 资源...") - logger.Debug("下载地址: %s", chartURL) - logger.Debug("目标目录: %s", redisDir) - logger.Debug("Redis 副本数: %d", replicas) - - // Download Redis chart - logger.Info("正在下载 Redis chart...") - if err := downloader.Download( + mk := maker.NewMaker() + return mk.Redis( cmd.Context(), - chartURL, - chartFile, - downloader.WithInsecureSkipVerify(), - ); err != nil { - logger.Info("❌ 下载 Redis chart 失败") - return err - } - logger.Info("✅ 成功下载 Redis chart") - - // Generate values.yaml - logger.Debug("创建 values.yaml: %s", valuesFile) - valuesContent := fmt.Sprintf(valuesTemplate, password, replicas) - if err := os.WriteFile(valuesFile, []byte(valuesContent), 0644); err != nil { - logger.Debug("创建 values.yaml 失败: %v", err) - logger.Info("❌ 创建 values.yaml 失败") - return err - } - logger.Info("✅ 成功创建 values.yaml") - - logger.Info("✅ Redis 资源构建成功") - logger.Debug("Redis 资源准备完成") - - return nil + maker.WithRedisReplicaCount(replicas), + maker.WithRedisPassword(password), + maker.WithRedisStorage(storage), + ) }, } _cmd.Flags().IntVar(&replicas, "replica-count", 2, "Redis 副本数") - _cmd.Flags().StringVar(&password, "password", "******", "Redis 密码") + _cmd.Flags().StringVar(&password, "password", "", "Redis 密码") + _cmd.Flags().StringVar(&storage, "storage-size", "5Gi", "Redis 存储大小(如: 5Gi)") return _cmd } diff --git a/internal/cmd/make.yosguard.go b/internal/cmd/make.yosguard.go index 5cd03c5..6076fa3 100644 --- a/internal/cmd/make.yosguard.go +++ b/internal/cmd/make.yosguard.go @@ -1,118 +1,18 @@ package cmd import ( - "os" - "path/filepath" - - "gitea.loveuer.com/yizhisec/pkg3/logger" "github.com/spf13/cobra" - "yizhisec.com/hsv2/forge/internal/opt" - "yizhisec.com/hsv2/forge/pkg/downloader" - "yizhisec.com/hsv2/forge/pkg/resource" + "yizhisec.com/hsv2/forge/internal/controller/maker" ) func makeYosguard() *cobra.Command { - const ( - _configTemplate = ` -Web: - # default listen in docker0 - Host: 172.17.0.1 - Port: 7788 - -UUIDFilePath: /etc/yosguard/uuid - -# 心跳间隔: 单位秒,默认为5 -HeartbeatDuration: 5 - -# 控制器 yosguard 地址 -ControllerServer: - Host: dasheng.zhsftech.debug - Port: 443 - -# True: 作为控制器运行; False: 不作为控制器运行 -AsController: true - -# True: 作为网关运行; False: 不作为网关运行 -AsGateway: false - -Database: - SQLite: - DBPath: "/etc/yosguard/db/yosguard.db" - SQLPath: "/etc/yosguard/db/create.sql"` - _service = ` -[Unit] -Description=YiZhiSec YOSGuard -After=network.target - -[Service] -Type=simple -User=root -ExecStart=/usr/local/bin/yosguard web --host __host__ -StandardOutput=journal -StandardError=journal -Nice=-20 -Restart=always -RestartSec=15 - -[Install] -WantedBy=multi-user.target` - ) _cmd := &cobra.Command{ Use: "yosguard", Aliases: []string{"YOS"}, Short: "Make Yosguard", RunE: func(cmd *cobra.Command, args []string) error { - var ( - err error - location = filepath.Join(opt.Cfg.Make.Dir, "dependency", "yosguard") - ) - - logger.Info("MakeYosguard: 开始构建 yosguard...") - - if err = os.MkdirAll(location, 0755); err != nil { - logger.Error("MakeYosguard: 创建 yosguard 目录失败") - logger.Debug("MakeYosguard: 创建 yosguard 目录失败: %v", err) - return err - } - - // 1. download yosguard bin: https://artifactory.yizhisec.com:443/artifactory/filestore/hsv2/bin/yosguard - _url := "https://artifactory.yizhisec.com:443/artifactory/filestore/hsv2/bin/yosguard" - logger.Debug("MakeYosguard: start download bin from %s", _url) - if err = downloader.Download( - cmd.Context(), - _url, - filepath.Join(location, "yosguard"), - downloader.WithInsecureSkipVerify(), - downloader.WithFileMode(0755), - ); err != nil { - logger.Error("MakeYosguard: 下载 yosguard 失败") - logger.Debug("MakeYosguard: 下载 yosguard 失败: %v", err) - return err - } - - // 2. generate config_template.yml - if err = os.WriteFile(filepath.Join(location, "config_template.yml"), []byte(_configTemplate), 0644); err != nil { - logger.Error("MakeYosguard: 生成 config_template.yml 失败") - logger.Debug("MakeYosguard: 生成 config_template.yml 失败: %v", err) - return err - } - - // 3. generate create.sql - if err = os.WriteFile(filepath.Join(location, "create.sql"), resource.SQLYosguard, 0644); err != nil { - logger.Error("MakeYosguard: 生成 create.sql 失败") - logger.Debug("MakeYosguard: 生成 create.sql 失败: %v", err) - return err - } - - // 4. generate systemd file - if err = os.WriteFile(filepath.Join(location, "yosguard.service"), []byte(_service), 0644); err != nil { - logger.Error("MakeYosguard: 生成 yosguard.service 失败") - logger.Debug("MakeYosguard: 生成 yosguard.service 失败: %v", err) - return err - } - - logger.Info("MakeYosguard: 构建 yosguard成功!!!") - return nil + mk := maker.NewMaker() + return mk.Yosguard(cmd.Context()) }, } diff --git a/internal/controller/installer/installer.go b/internal/controller/installer/installer.go new file mode 100644 index 0000000..bb79b36 --- /dev/null +++ b/internal/controller/installer/installer.go @@ -0,0 +1,8 @@ +package controller + +type installer struct { +} + +func NewInstaller() *installer { + return &installer{} +} diff --git a/internal/controller/maker/binary.go b/internal/controller/maker/binary.go new file mode 100644 index 0000000..f9313e6 --- /dev/null +++ b/internal/controller/maker/binary.go @@ -0,0 +1,36 @@ +package maker + +import ( + "context" + "path/filepath" + + "gitea.loveuer.com/yizhisec/pkg3/logger" + "yizhisec.com/hsv2/forge/internal/opt" + "yizhisec.com/hsv2/forge/pkg/archiver" +) + +func (m *maker) Binary(ctx context.Context) error { + var ( + tarURL = "https://artifactory.yizhisec.com:443/artifactory/filestore/hsv3/k8s-bin.tar" + binDir = filepath.Join(opt.Cfg.Make.Dir, "dependency") + ) + + logger.Info("☑️ 开始准备 k8s 二进制文件...") + logger.Debug("下载地址: %s", tarURL) + logger.Debug("目标目录: %s", binDir) + + if err := archiver.DownloadAndExtract( + ctx, + tarURL, + binDir, + archiver.WithInsecureSkipVerify(), + archiver.WithGzipCompression(true), + ); err != nil { + logger.Info("❌ 下载并解压二进制文件失败") + return err + } + + logger.Info("✅ 准备 k8s 二进制文件成功!!!") + + return nil +} diff --git a/internal/controller/maker/deb.go b/internal/controller/maker/deb.go new file mode 100644 index 0000000..58b85a4 --- /dev/null +++ b/internal/controller/maker/deb.go @@ -0,0 +1,37 @@ +package maker + +import ( + "context" + "path/filepath" + + "gitea.loveuer.com/yizhisec/pkg3/logger" + "yizhisec.com/hsv2/forge/internal/opt" + "yizhisec.com/hsv2/forge/pkg/archiver" +) + +func (m *maker) Deb(ctx context.Context) error { + var ( + tarURL = "https://artifactory.yizhisec.com:443/artifactory/filestore/hsv3/deb/docker.tar.gz" + binDir = filepath.Join(opt.Cfg.Make.Dir, "dependency", "deb") + ) + + logger.Info("☑️ 开始准备 deb(docker) 文件...") + logger.Debug("下载地址: %s", tarURL) + logger.Debug("目标目录: %s", binDir) + + if err := archiver.DownloadAndExtract( + ctx, + tarURL, + binDir, + archiver.WithInsecureSkipVerify(), + archiver.WithGzipCompression(true), + ); err != nil { + logger.Info("❌ 下载并解压 deb(docker) 文件失败") + logger.Debug("下载并解压 deb(docker) 文件失败: %v", err) + return err + } + + logger.Info("✅ 准备 deb(docker) 文件成功!!!") + return nil + +} diff --git a/internal/controller/maker/elastic.go b/internal/controller/maker/elastic.go new file mode 100644 index 0000000..b0a9882 --- /dev/null +++ b/internal/controller/maker/elastic.go @@ -0,0 +1,184 @@ +package maker + +import ( + "context" + "fmt" + "os" + "os/exec" + "path/filepath" + "regexp" + + "gitea.loveuer.com/yizhisec/pkg3/logger" + "yizhisec.com/hsv2/forge/internal/opt" + "yizhisec.com/hsv2/forge/pkg/archiver" + "yizhisec.com/hsv2/forge/pkg/resource" +) + +type ElasticOpt func(*elasticOpt) + +type elasticOpt struct { + MakeHelper bool + MemRate int + Storage string +} + +func WithElasticMakeHelper(makeHelper bool) ElasticOpt { + return func(o *elasticOpt) { + o.MakeHelper = makeHelper + } +} + +func WithElasticMemRate(memRate int) ElasticOpt { + return func(o *elasticOpt) { + if memRate > 0 { + o.MemRate = memRate + } + } +} + +func WithElasticStorageGi(storage string) ElasticOpt { + return func(o *elasticOpt) { + if matched, _ := regexp.MatchString(`^\d+(\.\d+)?[EPTGMK]i?$`, storage); matched { + o.Storage = storage + } + } +} + +func (m *maker) Elastic(ctx context.Context, opts ...ElasticOpt) error { + const ( + dockerFile = ` +FROM docker-mirror.yizhisec.com/library/alpine:3.22.2 + +WORKDIR /data + +RUN sed -i 's/dl-cdn.alpinelinux.org/mirrors.tuna.tsinghua.edu.cn/g' /etc/apk/repositories && apk add curl + +ENV TZ=Asia/Shanghai + +COPY plugins /data/plugins +COPY create_index.sh /data/create_index.sh +RUN chmod +x /data/create_index.sh +` + helperImageName = "hub.yizhisec.com/hybridscope/v2/es-init-helper:alpine-3.22.2" + pluginUrl = "https://artifactory.yizhisec.com:443/artifactory/filestore/hsv3/dependency/elasticsearch/v2-es-plugins.tar.gz" + ) + + var ( + err error + output []byte + location = filepath.Join(opt.Cfg.Make.Dir, "dependency", "elastic") + helperTarLocation = filepath.Join(opt.Cfg.Make.Dir, "dependency", "image", "es-init-helper.alpine-3.22.2.tar") + ) + + opt := &elasticOpt{ + MemRate: 1, + Storage: "100Gi", + } + for _, fn := range opts { + fn(opt) + } + + logger.Info("☑️ maker.Elastic: 开始构建 elasticsearch(es) 依赖...") + logger.Debug("☑️ maker.Elastic: 开始构建 elasticsearch(es) 依赖..., opt = %#v", opt) + + logger.Debug("☑️ maker.Elastic: 创建目录 %s", location) + if err = os.MkdirAll(location, 0755); err != nil { + logger.Debug("❌ maker.Elastic: 创建目录失败: %v", err) + return err + } + logger.Debug("✅ maker.Elastic: 创建目录 %s 成功", location) + + if opt.MakeHelper { + tmp := filepath.Join(os.TempDir(), "make-es") + + logger.Debug("☑️ maker.Elastic: 构建 helper..., dir = %s", tmp) + + logger.Debug("☑️ maker.Elastic: 删除并创建临时目录 %s", tmp) + if err = os.RemoveAll(tmp); err != nil { + logger.Debug("❌ maker.Elastic: 删除临时目录失败: %v", err) + return err + } + + if err = os.MkdirAll(tmp, 0755); err != nil { + logger.Debug("❌ maker.Elastic: 创建临时目录失败: %v", err) + return err + } + logger.Debug("✅ maker.Elastic: 删除并创建临时目录 %s 成功", tmp) + + logger.Debug("☑️ maker.Elastic: 写入 Dockerfile ...") + if err = os.WriteFile(filepath.Join(tmp, "Dockerfile"), []byte(dockerFile), 0644); err != nil { + logger.Debug("❌ maker.Elastic: 写入 Dockerfile 失败: %v", err) + return err + } + logger.Debug("✅ maker.Elastic: 写入 Dockerfile 成功") + + logger.Debug("☑️ maker.Elastic: 下载 es 插件... url = %s", pluginUrl) + if err = archiver.DownloadAndExtract( + ctx, + pluginUrl, + tmp, + archiver.WithInsecureSkipVerify(), + ); err != nil { + logger.Debug("❌ maker.Elastic: 下载 es 插件失败: url = %s, err = %v", pluginUrl, err) + return err + } + logger.Debug("✅ maker.Elastic: 下载 es 插件成功, url = %s", pluginUrl) + + logger.Debug("☑️ maker.Elastic: 写入 create_index.sh 文件...") + if err = os.WriteFile(filepath.Join(tmp, "create_index.sh"), resource.BashESInit, 0644); err != nil { + logger.Debug("❌ maker.Elastic: 写入 create_index.sh 文件失败: %v", err) + return err + } + logger.Debug("✅ maker.Elastic: 写入 create_index.sh 文件成功") + + helpCmd := exec.CommandContext(ctx, "docker", "build", "-t", + helperImageName, + "-f", filepath.Join(tmp, "Dockerfile"), + tmp, + ) + + logger.Debug("☑️ maker.Elastic: 重新构建 helper 镜像..., cmd = %s", helpCmd.String()) + if output, err = helpCmd.CombinedOutput(); err != nil { + logger.Debug("MakeES: 重新构建 helper 镜像失败, err = %v, output = %s", err, string(output)) + return err + } + logger.Debug("✅ maker.Elastic: 重新构建 helper 镜像成功, cmd = %s", helpCmd.String()) + + logger.Debug("✅ maker.Elastic: 构建 helper 成功, dir = %s", tmp) + } + + logger.Debug("☑️ maker.Elastic: 准备 es init helper 镜像..., location = %s", helperTarLocation) + if err = m.Image( + ctx, + helperImageName, + WithImageSave(helperTarLocation), + ); err != nil { + logger.Debug("❌ maker.Elastic: 准备 es init helper 镜像失败, location = %s, err = %v", helperTarLocation, err) + return err + } + logger.Debug("✅ maker.Elastic: 准备 es init helper 镜像成功, location = %s", helperTarLocation) + + bs := []byte(fmt.Sprintf(resource.YAMLES, + opt.MemRate, opt.MemRate*2, + opt.MemRate, opt.MemRate, + opt.MemRate*2, opt.MemRate*2, + opt.Storage, + )) + + logger.Debug("☑️ maker.Elastic: 写入 es.yaml 文件...") + if err = os.WriteFile(filepath.Join(location, "es.yaml"), bs, 0644); err != nil { + logger.Debug("❌ maker.Elastic: 写入 es.yaml 文件失败: %v", err) + return err + } + logger.Debug("✅ maker.Elastic: 写入 es.yaml 文件成功") + + logger.Debug("☑️ maker.Elastic: 写入 kibana.yaml 文件...") + if err = os.WriteFile(filepath.Join(location, "kibana.yaml"), resource.YAMLKibana, 0644); err != nil { + logger.Debug("❌ maker.Elastic: 写入 kibana.yaml 文件失败: %v", err) + return err + } + logger.Debug("✅ maker.Elastic: 写入 kibana.yaml 文件成功") + + logger.Info("✅ maker.Elastic: 构建 elastic(es) 依赖成功!!!") + return nil +} diff --git a/internal/controller/maker/emqx.go b/internal/controller/maker/emqx.go new file mode 100644 index 0000000..6272539 --- /dev/null +++ b/internal/controller/maker/emqx.go @@ -0,0 +1,33 @@ +package maker + +import ( + "context" + "os" + "path/filepath" + + "gitea.loveuer.com/yizhisec/pkg3/logger" + "yizhisec.com/hsv2/forge/internal/opt" + "yizhisec.com/hsv2/forge/pkg/resource" +) + +func (m *maker) EMQX(ctx context.Context) error { + var ( + err error + location = filepath.Join(opt.Cfg.Make.Dir, "emqx") + ) + + logger.Info("☑️ MakeEMQX: 开始构建 emqx(mqtt) 依赖...") + + if err = os.MkdirAll(location, 0755); err != nil { + logger.Debug("❌ MakeEMQX: 创建 emqx 目录失败: %v", err) + return err + } + + if err = os.WriteFile(filepath.Join(location, "emqx.yaml"), resource.YAMLEMQX, 0644); err != nil { + logger.Debug("❌ MakeEMQX: 写入 emqx.yaml 失败, err: %v", err) + return err + } + + logger.Info("✅ MakeEMQX: 构建 emqx(mqtt) 依赖成功!!!") + return nil +} diff --git a/internal/controller/maker/flannel.go b/internal/controller/maker/flannel.go new file mode 100644 index 0000000..883231e --- /dev/null +++ b/internal/controller/maker/flannel.go @@ -0,0 +1,40 @@ +package maker + +import ( + "context" + "fmt" + "os" + "path/filepath" + + "gitea.loveuer.com/yizhisec/pkg3/logger" + "yizhisec.com/hsv2/forge/internal/opt" + "yizhisec.com/hsv2/forge/pkg/resource" +) + +func (m *maker) Flannel(ctx context.Context, mode string) error { + var ( + err error + location = filepath.Join(opt.Cfg.Make.Dir, "dependency", "flannel") + ) + + logger.Info("☑️ 开始构建 flannel 资源...") + + logger.Debug("MakeFlannel location: %s", location) + if err = os.Mkdir(location, 0755); err != nil { + logger.Error("MakeFlannel: 创建目录 %s 失败", location) + logger.Debug("MakeFlannel: 创建目录 %s 失败: %v", location, err) + return err + } + + bs := []byte(fmt.Sprintf(resource.YAMLFlannel, mode)) + + if err = os.WriteFile(filepath.Join(location, "flannel.yaml"), bs, 0644); err != nil { + logger.Error("MakeFlannel: 创建文件 %s 失败", filepath.Join(location, "flannel.yaml")) + logger.Debug("MakeFlannel: 创建文件 %s 失败: %v", filepath.Join(location, "flannel.yaml"), err) + return err + } + + logger.Info("✅ 构建 flannel 成功!!!") + + return nil +} diff --git a/internal/controller/maker/hsnet.go b/internal/controller/maker/hsnet.go new file mode 100644 index 0000000..2bc6b40 --- /dev/null +++ b/internal/controller/maker/hsnet.go @@ -0,0 +1,27 @@ +package maker + +import ( + "context" + "os" + "path/filepath" + + "gitea.loveuer.com/yizhisec/pkg3/logger" + "yizhisec.com/hsv2/forge/internal/opt" +) + +func (m *maker) HSNet(ctx context.Context) error { + var ( + err error + location = filepath.Join(opt.Cfg.Make.Dir, "dependency", "hs-net") + ) + + if err = os.MkdirAll(location, 0755); err != nil { + logger.Error("MakeHSNet: 创建目录失败s") + logger.Debug("MakeHSNet: 创建目录失败: %s", err.Error()) + return err + } + + logger.Fatal("MakeHSNet: 构建 hs-net 失败!!!(怎么完善,怎么完善,怎么完善???)") + + return nil +} diff --git a/internal/controller/maker/image.go b/internal/controller/maker/image.go index 517122e..69870dd 100644 --- a/internal/controller/maker/image.go +++ b/internal/controller/maker/image.go @@ -2,10 +2,13 @@ package maker import ( "context" + "os" "os/exec" + "path/filepath" "gitea.loveuer.com/yizhisec/pkg3/logger" "github.com/samber/lo" + "yizhisec.com/hsv2/forge/internal/opt" ) type imageOpt struct { @@ -36,7 +39,6 @@ func WithImageForcePull() ImageOpt { } func (m *maker) Image(ctx context.Context, name string, opts ...ImageOpt) error { - logger.Info("开始获取镜像: %s", name) var ( err error o = &imageOpt{} @@ -47,50 +49,53 @@ func (m *maker) Image(ctx context.Context, name string, opts ...ImageOpt) error fn(o) } - logger.Debug("maker.Image: name = %s, opt = %#v", name, o) + logger.Debug("📋 maker.Image: name = %s, opt = %#v", name, o) if !o.ForcePull { _cmd = exec.CommandContext(ctx, "docker", "image", "inspect", name) if err = _cmd.Run(); err == nil { - logger.Info("💾 镜像 %s 已存在", name) + logger.Debug("💿 镜像 %s 已存在", name) goto SAVE } } _cmd = exec.CommandContext(ctx, "docker", "pull", name) if err = _cmd.Run(); err != nil { - logger.Debug("获取原始镜像 %s 失败: %v", name, err) + logger.Debug("❌ 获取原始镜像 %s 失败: %v", name, err) } else { - logger.Info("✅ 成功获取镜像: %s", name) + logger.Debug("✅ 成功获取镜像: %s", name) goto SAVE } for _, fallback := range o.Fallbacks { - logger.Info("开始获取镜像: %s (%s)", name, fallback) + logger.Debug("☑️ 开始获取镜像: %s (%s)", name, fallback) _cmd := exec.CommandContext(ctx, "docker", "pull", fallback) if err = _cmd.Run(); err != nil { - logger.Debug("获取镜像 %s (%s) 失败: %v", name, fallback, err) + logger.Debug("❌ 获取镜像 %s (%s) 失败: %v", name, fallback, err) continue } // pull success, retag image _cmd = exec.CommandContext(ctx, "docker", "tag", fallback, name) if err = _cmd.Run(); err != nil { - logger.Debug("重命名镜像 %s => %s 失败: %s", fallback, name, err) + logger.Debug("❌ 重命名镜像 %s => %s 失败: %s", fallback, name, err) continue } - logger.Info("✅ 成功获取镜像: %s (%s)", name, fallback) + logger.Debug("✅ 成功获取镜像: %s (%s)", name, fallback) break } SAVE: if o.Save != "" { - logger.Debug("保存镜像 %s 到 %s", name, o.Save) + logger.Debug("☑️ 保存镜像 %s 到 %s", name, o.Save) + + _ = os.MkdirAll(filepath.Dir(o.Save), 0755) + if err = exec.CommandContext(ctx, "docker", "save", "-o", o.Save, name).Run(); err != nil { - logger.Debug("保存镜像 %s 到 %s 失败: %v", name, o.Save, err) + logger.Debug("❌ 保存镜像 %s 到 %s 失败: %v", name, o.Save, err) } else { - logger.Info("✅ 镜像 %s 保存到 %s 成功", name, o.Save) + logger.Debug("✅ 镜像 %s 保存到 %s 成功", name, o.Save) } } @@ -100,3 +105,92 @@ SAVE: return err } + +func (m *maker) Images(ctx context.Context) error { + type Images struct { + Name string + Fallback string + Save string + Force bool + } + + var images = []*Images{ + {Name: "quay.io/k0sproject/apiserver-network-proxy-agent:v0.32.0", Fallback: "hub.yizhisec.com/external/apiserver-network-proxy-agent:v0.32.0", Save: "k0s.apiserver-network-proxy-agent.tar"}, + {Name: "quay.io/k0sproject/cni-node:1.7.1-k0s.0", Fallback: "", Save: "k0s.cni-node.tar"}, + {Name: "quay.io/k0sproject/coredns:1.12.2", Fallback: "", Save: "k0s.coredns.tar"}, + {Name: "quay.io/k0sproject/kube-proxy:v1.33.4", Fallback: "", Save: "k0s.kube-proxy.tar"}, + {Name: "quay.io/k0sproject/kube-router:v2.5.0-iptables1.8.11-0", Fallback: "", Save: "k0s.kube-router.tar"}, + {Name: "quay.io/k0sproject/metrics-server:v0.7.2-0", Fallback: "", Save: "k0s.metrics-server.tar"}, + {Name: "quay.io/k0sproject/pause:3.10.1", Fallback: "", Save: "k0s.pause.tar"}, + + {Name: "ghcr.io/flannel-io/flannel:v0.27.4", Fallback: "swr.cn-north-4.myhuaweicloud.com/ddn-k8s/ghcr.io/flannel-io/flannel:v0.27.4", Save: "flannel.tar"}, + {Name: "ghcr.io/flannel-io/flannel-cni-plugin:v1.8.0-flannel1", Fallback: "swr.cn-north-4.myhuaweicloud.com/ddn-k8s/ghcr.io/flannel-io/flannel-cni-plugin:v1.8.0-flannel1", Save: "flannel-cni-plugin.tar"}, + + {Name: "docker.io/longhornio/longhorn-engine:v1.10.0", Fallback: "docker-mirror.yizhisec.com/longhornio/longhorn-engine:v1.10.0", Save: "longhorn.longhorn-engine.tar"}, + {Name: "docker.io/longhornio/longhorn-manager:v1.10.0", Fallback: "docker-mirror.yizhisec.com/longhornio/longhorn-manager:v1.10.0", Save: "longhorn.longhorn-manager.tar"}, + {Name: "docker.io/longhornio/longhorn-instance-manager:v1.10.0", Fallback: "docker-mirror.yizhisec.com/longhornio/longhorn-instance-manager:v1.10.0", Save: "longhorn.longhorn-instance-manager.tar"}, + {Name: "docker.io/longhornio/longhorn-share-manager:v1.10.0", Fallback: "docker-mirror.yizhisec.com/longhornio/longhorn-share-manager:v1.10.0", Save: "longhorn.longhorn-share-manager.tar"}, + {Name: "docker.io/longhornio/longhorn-ui:v1.10.0", Fallback: "docker-mirror.yizhisec.com/longhornio/longhorn-ui:v1.10.0", Save: "longhorn.longhorn-ui.tar"}, + {Name: "docker.io/longhornio/csi-snapshotter:v8.3.0-20250826", Fallback: "docker-mirror.yizhisec.com/longhornio/csi-snapshotter:v8.3.0-20250826", Save: "longhorn.csi-snapshotter.tar"}, + {Name: "docker.io/longhornio/csi-resizer:v1.14.0-20250826", Fallback: "docker-mirror.yizhisec.com/longhornio/csi-resizer:v1.14.0-20250826", Save: "longhorn.csi-resizer.tar"}, + {Name: "docker.io/longhornio/csi-provisioner:v5.3.0-20250826", Fallback: "docker-mirror.yizhisec.com/longhornio/csi-provisioner:v5.3.0-20250826", Save: "longhorn.csi-provisioner.tar"}, + {Name: "docker.io/longhornio/livenessprobe:v2.16.0-20250826", Fallback: "docker-mirror.yizhisec.com/longhornio/livenessprobe:v2.16.0-20250826", Save: "longhorn.livenessprobe.tar"}, + {Name: "docker.io/longhornio/csi-node-driver-registrar:v2.14.0-20250826", Fallback: "docker-mirror.yizhisec.com/longhornio/csi-node-driver-registrar:v2.14.0-20250826", Save: "longhorn.csi-node-driver-registrar.tar"}, + {Name: "docker.io/longhornio/csi-attacher:v4.9.0-20250826", Fallback: "docker-mirror.yizhisec.com/longhornio/csi-attacher:v4.9.0-20250826", Save: "longhorn.csi-attacher.tar"}, + + {Name: "hub.yizhisec.com/external/alpine:3.22.2", Fallback: "", Save: "alpine.tar", Force: true}, + {Name: "hub.yizhisec.com/external/nginx:1.29.1-alpine3.22", Fallback: "", Save: "nginx.1.29.1-alpine3.22.tar"}, + + {Name: "docker.io/bitpoke/mysql-operator:v0.6.3", Fallback: "docker-mirror.yizhisec.com/bitpoke/mysql-operator:v0.6.3", Save: "bitpoke.mysql-operator.v0.6.3.tar"}, + {Name: "docker.io/bitpoke/mysql-operator-orchestrator:v0.6.3", Fallback: "docker-mirror.yizhisec.com/bitpoke/mysql-operator-orchestrator:v0.6.3", Save: "bitpoke.mysql-operator-orchestrator.v0.6.3.tar"}, + {Name: "docker.io/bitpoke/mysql-operator-sidecar-8.0:v0.6.3", Fallback: "docker-mirror.yizhisec.com/bitpoke/mysql-operator-sidecar-8.0:v0.6.3", Save: "bitpoke.mysql-operator-sidecar-8.0.v0.6.3.tar"}, + {Name: "docker.io/library/percona:8.0.28-20", Fallback: "docker-mirror.yizhisec.com/library/percona:8.0.28-20", Save: "percona.8.0.28-20.tar"}, + {Name: "docker.io/prom/mysqld-exporter:v0.13.0", Fallback: "docker-mirror.yizhisec.com/prom/mysqld-exporter:v0.13.0", Save: "prom.mysqld-exporter.v0.13.0.tar"}, + + {Name: "docker.io/bitnami/redis:8.2.2", Fallback: "hub.yizhisec.com/external/bitnami/redis:8.2.2", Save: "bitnami.redis.8.2.2.tar"}, + {Name: "hub.yizhisec.com/external/elasticsearch:7.17.28", Fallback: "", Save: "elasticsearch.7.17.28.tar"}, + {Name: "hub.yizhisec.com/external/kibana:7.17.28", Fallback: "", Save: "kibana.7.17.28.tar"}, + {Name: "hub.yizhisec.com/external/emqx:5.1", Fallback: "", Save: "emqx.5.1.tar"}, + + {Name: "hub.yizhisec.com/build/hybirdscope/front/admin:latest", Fallback: "", Save: "app.front.admin.tar", Force: true}, + {Name: "hub.yizhisec.com/hybridscope/v2/front-user:latest", Fallback: "", Save: "app.front.user.tar", Force: true}, + {Name: "hub.yizhisec.com/hybridscope/user_management:latest", Fallback: "", Save: "app.user.tar", Force: true}, + {Name: "hub.yizhisec.com/hybridscope/gateway_controller:latest", Fallback: "", Save: "app.gateway.tar", Force: true}, + {Name: "hub.yizhisec.com/hybridscope/client_server:latest", Fallback: "", Save: "app.client.tar", Force: true}, + {Name: "hub.yizhisec.com/hybridscope/mie-server:latest", Fallback: "", Save: "app.mie.tar", Force: true}, + {Name: "hub.yizhisec.com/hybridscope/less_dns_service:latest", Fallback: "", Save: "app.less_dns.tar", Force: true}, + {Name: "hub.yizhisec.com/hybridscope/hsnet:release_2.1.0-std", Fallback: "", Save: "app.hsnet.tar", Force: true}, + } + + for _, image := range images { + image.Save = filepath.Join(opt.Cfg.Make.Dir, "dependency", "image", image.Save) + } + + logger.Info("☑️ 开始获取镜像(s)...") + + for _, image := range images { + + opts := []ImageOpt{ + WithImageFallback(image.Fallback), + WithImageSave(image.Save), + } + + if image.Force { + opts = append(opts, WithImageForcePull()) + } + + logger.Info("☑️ 获取镜像: %s", image.Name) + + if err := m.Image(ctx, image.Name, opts...); err != nil { + logger.Error("❌ 获取镜像失败: %s, 可以手动获取后重试", image.Name) + logger.Debug("❌ 获取镜像失败: %s, %v", image.Name, err) + return err + } + + logger.Info("✅ 获取镜像成功: %s", image.Name) + } + + logger.Info("✅ 获取镜像(s)成功!!!") + + return nil +} diff --git a/internal/controller/maker/lessdns.go b/internal/controller/maker/lessdns.go new file mode 100644 index 0000000..16b758e --- /dev/null +++ b/internal/controller/maker/lessdns.go @@ -0,0 +1,34 @@ +package maker + +import ( + "context" + "os" + "path/filepath" + + "gitea.loveuer.com/yizhisec/pkg3/logger" + "yizhisec.com/hsv2/forge/internal/opt" + "yizhisec.com/hsv2/forge/pkg/resource" +) + +func (m *maker) LessDNS(ctx context.Context) error { + var ( + err error + location = filepath.Join(opt.Cfg.Make.Dir, "dependency", "less-dns") + ) + + logger.Info("MakeLessDNS: 开始构建 less-dns...") + if err = os.MkdirAll(location, 0755); err != nil { + logger.Error("MakeLessDNS: 创建目录失败s") + logger.Debug("MakeLessDNS: 创建目录失败: %s", err.Error()) + return err + } + + if err = os.WriteFile(filepath.Join(location, "deployment.yaml"), resource.YAMLLessDNS, 0644); err != nil { + logger.Error("MakeLessDNS: 写入文件失败") + logger.Debug("MakeLessDNS: 写入文件失败: %s", err.Error()) + return err + } + + logger.Info("MakeLessDNS: 构建 less-dns 成功!!!") + return nil +} diff --git a/internal/controller/maker/longhorn.go b/internal/controller/maker/longhorn.go new file mode 100644 index 0000000..e8d1cf1 --- /dev/null +++ b/internal/controller/maker/longhorn.go @@ -0,0 +1,64 @@ +package maker + +import ( + "context" + "fmt" + "os" + "path/filepath" + + "gitea.loveuer.com/yizhisec/pkg3/logger" + "yizhisec.com/hsv2/forge/internal/opt" + "yizhisec.com/hsv2/forge/pkg/downloader" +) + +func (m *maker) Longhorn(ctx context.Context, replica int) error { + const ( + valuesContent = `# 设置 Longhorn 数据存储路径 +defaultSettings: + defaultDataPath: "/data/longhorn" +# 设置默认副本数 +persistence: + reclaimPolicy: Retain + defaultClassReplicaCount: %d +` + ) + + var ( + err error + chartURL = "https://artifactory.yizhisec.com:443/artifactory/filestore/hsv3/charts/longhorn-1.10.0.tgz" + longhornDir = filepath.Join(opt.Cfg.Make.Dir, "dependency", "longhorn") + chartFile = filepath.Join(longhornDir, "longhorn-1.10.0.tgz") + valuesFile = filepath.Join(longhornDir, "values.yaml") + ) + + logger.Info("☑️ 开始准备 Longhorn 资源...") + logger.Debug("下载地址: %s", chartURL) + logger.Debug("目标目录: %s", longhornDir) + + if err = os.MkdirAll(filepath.Join(opt.Cfg.Make.Dir, "dependency", "longhorn"), 0755); err != nil { + return err + } + + // Download the chart file + if err = downloader.Download( + ctx, + chartURL, + chartFile, + downloader.WithInsecureSkipVerify(), + ); err != nil { + logger.Info("❌ 下载 Longhorn chart 失败") + return err + } + + // Create values.yaml file + bs := []byte(fmt.Sprintf(valuesContent, replica)) + if err := os.WriteFile(valuesFile, bs, 0644); err != nil { + logger.Debug("创建 values.yaml 失败: %v", err) + logger.Info("❌ 创建 values.yaml 失败") + return err + } + + logger.Info("✅ 成功创建 longhorn 资源!!!") + + return nil +} diff --git a/internal/controller/maker/mysql.go b/internal/controller/maker/mysql.go new file mode 100644 index 0000000..21738c7 --- /dev/null +++ b/internal/controller/maker/mysql.go @@ -0,0 +1,164 @@ +package maker + +import ( + "context" + "encoding/base64" + "fmt" + "os" + "path/filepath" + "regexp" + + "gitea.loveuer.com/yizhisec/pkg3/logger" + "yizhisec.com/hsv2/forge/internal/opt" + "yizhisec.com/hsv2/forge/pkg/downloader" +) + +type MysqlOpt func(*mysqlOpt) + +type mysqlOpt struct { + Replica int + Storage string + Password string +} + +func WithMySQLReplica(replica int) MysqlOpt { + return func(o *mysqlOpt) { + o.Replica = replica + } +} + +func WithMySQLStorage(storage string) MysqlOpt { + return func(o *mysqlOpt) { + // validate Kubernetes storage size string (e.g., "50Gi", "100Mi") + if matched, _ := regexp.MatchString(`^\d+(\.\d+)?[EPTGMK]i?$`, storage); matched { + o.Storage = storage + } + } +} + +func WithMySQLPassword(password string) MysqlOpt { + return func(o *mysqlOpt) { + if password != "" { + o.Password = password + } + } +} + +func (m *maker) MySQL(ctx context.Context, opts ...MysqlOpt) error { + const ( + _yaml = ` +apiVersion: v1 +kind: Secret +metadata: + name: mysql-secret + namespace: db-mysql +type: Opaque +data: + ROOT_PASSWORD: %s +--- + +apiVersion: mysql.presslabs.org/v1alpha1 +kind: MysqlCluster +metadata: + name: mysql-cluster + namespace: db-mysql +spec: + mysqlVersion: "8.0" + replicas: %d + image: docker.io/library/percona:8.0.28-20 + secretName: mysql-secret + volumeSpec: + persistentVolumeClaim: + accessModes: ["ReadWriteOnce"] + storageClassName: longhorn + resources: + requests: + storage: %s + podSpec: + resources: + requests: + cpu: "250m" + memory: "250Mi" + limits: + cpu: "2" + memory: "4Gi" +# affinity: +# podAntiAffinity: +# requiredDuringSchedulingIgnoredDuringExecution: # 强制规则 +# - labelSelector: +# matchExpressions: +# - key: app.kubernetes.io/name +# operator: In +# values: ["mysql"] +# - key: app.kubernetes.io/instance +# operator: In +# values: ["mysql-cluster"] +# topologyKey: "kubernetes.io/hostname" # 确保不同节点 +--- + +apiVersion: mysql.presslabs.org/v1alpha1 +kind: MysqlDatabase +metadata: + name: my-database-mie + namespace: db-mysql +spec: + database: mie + clusterRef: + name: mysql-cluster + namespace: db-mysql +` + ) + + var ( + o = &mysqlOpt{ + Replica: 2, + Storage: "50Gi", + Password: "L0hMysql.", + } + + err error + chartURL = "https://artifactory.yizhisec.com:443/artifactory/filestore/hsv3/charts/mysql-operator-0.6.3.tgz" + mysqlDir = filepath.Join(opt.Cfg.Make.Dir, "dependency", "mysql") + chartFile = filepath.Join(mysqlDir, "mysql-operator-0.6.3.tgz") + clusterFile = filepath.Join(mysqlDir, "cluster.yaml") + ) + + for _, fn := range opts { + fn(o) + } + + logger.Info("☑️ 开始构建 MySQL 资源...") + + if err = os.MkdirAll(mysqlDir, 0755); err != nil { + return err + } + + o.Password = base64.StdEncoding.EncodeToString([]byte(o.Password)) + + logger.Debug("正在下载 MySQL operator chart..., url = %s, dir = %s", chartURL, mysqlDir) + if err = downloader.Download( + ctx, + chartURL, + chartFile, + downloader.WithInsecureSkipVerify(), + ); err != nil { + logger.Info("❌ 下载 MySQL operator chart 失败") + return err + } + logger.Debug("✅ 成功下载 MySQL operator chart") + + bs := []byte(fmt.Sprintf(_yaml, o.Password, o.Replica, o.Storage)) + + // Generate secret.yaml + if err = os.WriteFile(clusterFile, bs, 0644); err != nil { + logger.Debug("创建 database.yaml 失败: %v", err) + logger.Info("❌ 创建 database.yaml 失败") + return err + } + + logger.Debug("✅ 成功创建 database.yaml") + + logger.Info("✅ MySQL 资源构建成功!!!") + + return nil +} diff --git a/internal/controller/maker/redis.go b/internal/controller/maker/redis.go new file mode 100644 index 0000000..141cc96 --- /dev/null +++ b/internal/controller/maker/redis.go @@ -0,0 +1,128 @@ +package maker + +import ( + "context" + "fmt" + "os" + "path/filepath" + "regexp" + + "gitea.loveuer.com/yizhisec/pkg3/logger" + "yizhisec.com/hsv2/forge/internal/opt" + "yizhisec.com/hsv2/forge/pkg/downloader" +) + +type RedisOpt func(*redisOpt) + +type redisOpt struct { + ReplicaCount int + Password string + Storage string +} + +func WithRedisReplicaCount(replica int) RedisOpt { + return func(o *redisOpt) { + if replica > 0 { + o.ReplicaCount = replica + } + } +} + +func WithRedisPassword(password string) RedisOpt { + return func(o *redisOpt) { + if password != "" { + o.Password = password + } + } +} + +func WithRedisStorage(storage string) RedisOpt { + return func(o *redisOpt) { + if matched, _ := regexp.MatchString(`^\d+(\.\d+)?[EPTGMK]i?$`, storage); matched { + o.Storage = storage + } + } +} + +func (m *maker) Redis(ctx context.Context, opts ...RedisOpt) error { + const ( + valuesTemplate = `# Redis configuration +architecture: replication + +image: + registry: docker.io + repository: bitnami/redis + tag: 8.2.2 + pullPolicy: IfNotPresent + +auth: + enabled: true + password: "%s" + +master: + persistence: + enabled: true + storageClass: "longhorn" + size: %s + +replica: + replicaCount: %d + persistence: + enabled: true + storageClass: "longhorn" + size: %s + +metrics: + enabled: false + serviceMonitor: + enabled: false +` + defaultPassword = "HybridScope0xRed1s." + chartURL = "https://artifactory.yizhisec.com:443/artifactory/filestore/hsv3/charts/redis-23.2.2.tgz" + chartFilename = "redis-23.2.2.tgz" + ) + + o := &redisOpt{ + ReplicaCount: 2, + Password: "HybridScope0xRed1s.", + Storage: "5Gi", + } + for _, fn := range opts { + fn(o) + } + + redisDir := filepath.Join(opt.Cfg.Make.Dir, "dependency", "redis") + chartFile := filepath.Join(redisDir, chartFilename) + valuesFile := filepath.Join(redisDir, "values.yaml") + + if err := os.MkdirAll(redisDir, 0755); err != nil { + return err + } + + logger.Info("开始构建 Redis 资源...") + logger.Debug("下载地址: %s", chartURL) + logger.Debug("目标目录: %s", redisDir) + logger.Debug("Redis 副本数: %d", o.ReplicaCount) + + if err := downloader.Download( + ctx, + chartURL, + chartFile, + downloader.WithInsecureSkipVerify(), + ); err != nil { + logger.Debug("❌ 下载 Redis chart 失败") + return err + } + logger.Debug("✅ 成功下载 Redis chart") + + bs := fmt.Sprintf(valuesTemplate, o.Password, o.Storage, o.ReplicaCount, o.Storage) + if err := os.WriteFile(valuesFile, []byte(bs), 0644); err != nil { + logger.Info("❌ 创建 values.yaml 失败") + return err + } + logger.Debug("✅ 成功创建 values.yaml") + + logger.Info("✅ Redis 资源构建成功") + + return nil +} diff --git a/internal/controller/maker/yosguard.go b/internal/controller/maker/yosguard.go new file mode 100644 index 0000000..716b12b --- /dev/null +++ b/internal/controller/maker/yosguard.go @@ -0,0 +1,104 @@ +package maker + +import ( + "context" + "os" + "path/filepath" + + "gitea.loveuer.com/yizhisec/pkg3/logger" + "yizhisec.com/hsv2/forge/internal/opt" + "yizhisec.com/hsv2/forge/pkg/downloader" + "yizhisec.com/hsv2/forge/pkg/resource" +) + +type YosguardOpt func(*yosguardOpt) + +type yosguardOpt struct{} + +func (m *maker) Yosguard(ctx context.Context, opts ...YosguardOpt) error { + const ( + configTemplate = ` +Web: + # default listen in docker0 + Host: 172.17.0.1 + Port: 7788 + +UUIDFilePath: /etc/yosguard/uuid + +# 心跳间隔: 单位秒,默认为5 +HeartbeatDuration: 5 + +# 控制器 yosguard 地址 +ControllerServer: + Host: dasheng.zhsftech.debug + Port: 443 + +# True: 作为控制器运行; False: 不作为控制器运行 +AsController: true + +# True: 作为网关运行; False: 不作为网关运行 +AsGateway: false + +Database: + SQLite: + DBPath: "/etc/yosguard/db/yosguard.db" + SQLPath: "/etc/yosguard/db/create.sql"` + + systemdService = ` +[Unit] +Description=YiZhiSec YOSGuard +After=network.target + +[Service] +Type=simple +User=root +ExecStart=/usr/local/bin/yosguard web --host __host__ +StandardOutput=journal +StandardError=journal +Nice=-20 +Restart=always +RestartSec=15 + +[Install] +WantedBy=multi-user.target` + binURL = "https://artifactory.yizhisec.com:443/artifactory/filestore/hsv2/bin/yosguard" + ) + + location := filepath.Join(opt.Cfg.Make.Dir, "dependency", "yosguard") + + logger.Info("☑️ MakeYosguard: 开始构建 yosguard...") + + if err := os.MkdirAll(location, 0755); err != nil { + logger.Debug("❌ MakeYosguard: 创建 yosguard 目录失败: %v", err) + return err + } + + if err := downloader.Download( + ctx, + binURL, + filepath.Join(location, "yosguard"), + downloader.WithInsecureSkipVerify(), + downloader.WithFileMode(0755), + ); err != nil { + logger.Debug("❌ MakeYosguard: 下载 yosguard 失败: %v", err) + return err + } + + if err := os.WriteFile(filepath.Join(location, "config_template.yml"), []byte(configTemplate), 0644); err != nil { + logger.Debug("❌ MakeYosguard: 生成 config_template.yml 失败: %v", err) + return err + } + + if err := os.WriteFile(filepath.Join(location, "create.sql"), resource.SQLYosguard, 0644); err != nil { + logger.Debug("❌ MakeYosguard: 生成 create.sql 失败: %v", err) + return err + } + + if err := os.WriteFile(filepath.Join(location, "yosguard.service"), []byte(systemdService), 0644); err != nil { + logger.Debug("❌ MakeYosguard: 生成 yosguard.service 失败: %v", err) + return err + } + + logger.Info("✅ MakeYosguard: 构建 yosguard成功!!!") + return nil +} diff --git a/pkg/resource/es.yaml b/pkg/resource/es.yaml index ef4a465..cbaab6c 100644 --- a/pkg/resource/es.yaml +++ b/pkg/resource/es.yaml @@ -81,7 +81,7 @@ spec: storageClassName: longhorn resources: requests: - storage: %dGi + storage: %s --- apiVersion: v1 kind: Service diff --git a/pkg/resource/flannel.yaml b/pkg/resource/flannel.yaml index d69fb3f..a7c2945 100644 --- a/pkg/resource/flannel.yaml +++ b/pkg/resource/flannel.yaml @@ -84,7 +84,8 @@ data: "Network": "10.244.0.0/16", "EnableNFTables": false, "Backend": { - "Type": "vxlan" + "Type": "%s", + "DirectRouting": true } } kind: ConfigMap diff --git a/pkg/resource/kibana.yaml b/pkg/resource/kibana.yaml index a443d41..825d0e5 100644 --- a/pkg/resource/kibana.yaml +++ b/pkg/resource/kibana.yaml @@ -4,7 +4,7 @@ metadata: name: kibana namespace: db-es spec: - replicas: 0 + replicas: 1 selector: matchLabels: app: kibana diff --git a/pkg/resource/resource.go b/pkg/resource/resource.go index 0506164..ebec061 100644 --- a/pkg/resource/resource.go +++ b/pkg/resource/resource.go @@ -6,7 +6,7 @@ import ( var ( //go:embed flannel.yaml - YAMLFlannel []byte + YAMLFlannel string //go:embed es.yaml YAMLES string