diff --git a/internal/cmd/make.go b/internal/cmd/make.go index a09da88..51c561e 100644 --- a/internal/cmd/make.go +++ b/internal/cmd/make.go @@ -5,6 +5,7 @@ import ( "gitea.loveuer.com/yizhisec/pkg3/logger" "github.com/spf13/cobra" + "yizhisec.com/hsv2/forge/internal/cmd/makecmd" "yizhisec.com/hsv2/forge/internal/controller/maker" "yizhisec.com/hsv2/forge/internal/opt" ) @@ -25,6 +26,10 @@ func makeCmd() *cobra.Command { logger.Warn("Running in debug mode") } + if err = os.MkdirAll(opt.Cfg.Make.Dir, 0755); err != nil { + return err + } + if opt.Cfg.Make.DisableDependencyCheck { logger.Info("Dependency check disabled") return nil @@ -35,10 +40,6 @@ func makeCmd() *cobra.Command { return err } - if err = os.MkdirAll(opt.Cfg.Make.Dir, 0755); err != nil { - return err - } - logger.Debug("Running make prerun success") return nil @@ -49,18 +50,20 @@ func makeCmd() *cobra.Command { _cmd.PersistentFlags().StringVar(&opt.Cfg.Make.Dir, "dir", "/root/hsv2-installation", "make base directory") _cmd.AddCommand( - makeImages(), - makeBinaries(), - makeDebs(), - makeFlannel(), - makeLonghorn(), - makeMysql(), - makeRedis(), - makeES(), - makeEMQX(), - makeYosguard(), - makeLessDNS(), // hs-net dependency - makeHSNet(), + makecmd.Images(), + makecmd.Binaries(), + makecmd.Debs(), + makecmd.Flannel(), + makecmd.Longhorn(), + makecmd.Mysql(), + makecmd.Redis(), + makecmd.ES(), + makecmd.EMQX(), + makecmd.Yosguard(), + makecmd.LessDNS(), + makecmd.HSNet(), + makecmd.ConfigMap(), + makecmd.App(), ) return _cmd diff --git a/internal/cmd/makecmd/app.go b/internal/cmd/makecmd/app.go new file mode 100644 index 0000000..46ae43b --- /dev/null +++ b/internal/cmd/makecmd/app.go @@ -0,0 +1,18 @@ +package makecmd + +import ( + "github.com/spf13/cobra" +) + +func App() *cobra.Command { + _cmd := &cobra.Command{ + Use: "app", + Short: "Make Apps(user, client, gateway, mie, nginx, etc...)", + } + + _cmd.AddCommand( + appUser(), + ) + + return _cmd +} diff --git a/internal/cmd/makecmd/app.user.go b/internal/cmd/makecmd/app.user.go new file mode 100644 index 0000000..c2bdeb3 --- /dev/null +++ b/internal/cmd/makecmd/app.user.go @@ -0,0 +1,25 @@ +package makecmd + +import ( + "github.com/spf13/cobra" + "yizhisec.com/hsv2/forge/internal/controller/maker" +) + +func appUser() *cobra.Command { + var ( + replica int + ) + + _cmd := &cobra.Command{ + Use: "user", + Short: "Make User App", + RunE: func(cmd *cobra.Command, args []string) error { + mk := maker.NewMaker() + return mk.AppUser(cmd.Context(), replica) + }, + } + + _cmd.Flags().IntVar(&replica, "replica-count", 2, "Replica count") + + return _cmd +} diff --git a/internal/cmd/make.binaries.go b/internal/cmd/makecmd/binaries.go similarity index 89% rename from internal/cmd/make.binaries.go rename to internal/cmd/makecmd/binaries.go index 64e9928..10057ee 100644 --- a/internal/cmd/make.binaries.go +++ b/internal/cmd/makecmd/binaries.go @@ -1,11 +1,11 @@ -package cmd +package makecmd import ( "github.com/spf13/cobra" "yizhisec.com/hsv2/forge/internal/controller/maker" ) -func makeBinaries() *cobra.Command { +func Binaries() *cobra.Command { cmd := &cobra.Command{ Use: "binaries", Aliases: []string{"bin", "B"}, diff --git a/internal/cmd/makecmd/configmap.go b/internal/cmd/makecmd/configmap.go new file mode 100644 index 0000000..0d7b24e --- /dev/null +++ b/internal/cmd/makecmd/configmap.go @@ -0,0 +1,20 @@ +package makecmd + +import ( + "github.com/spf13/cobra" + "yizhisec.com/hsv2/forge/internal/controller/maker" +) + +func ConfigMap() *cobra.Command { + _cmd := &cobra.Command{ + Use: "configmap", + Aliases: []string{"cm"}, + Short: "构建 ConfigMap", + RunE: func(cmd *cobra.Command, args []string) error { + mk := maker.NewMaker() + return mk.ConfigMap(cmd.Context()) + }, + } + + return _cmd +} diff --git a/internal/cmd/make.debs.go b/internal/cmd/makecmd/debs.go similarity index 89% rename from internal/cmd/make.debs.go rename to internal/cmd/makecmd/debs.go index e026939..9c7b25c 100644 --- a/internal/cmd/make.debs.go +++ b/internal/cmd/makecmd/debs.go @@ -1,11 +1,11 @@ -package cmd +package makecmd import ( "github.com/spf13/cobra" "yizhisec.com/hsv2/forge/internal/controller/maker" ) -func makeDebs() *cobra.Command { +func Debs() *cobra.Command { cmd := &cobra.Command{ Use: "debs", Aliases: []string{"deb"}, diff --git a/internal/cmd/make.emqx.go b/internal/cmd/makecmd/emqx.go similarity index 86% rename from internal/cmd/make.emqx.go rename to internal/cmd/makecmd/emqx.go index 59b822b..6b73313 100644 --- a/internal/cmd/make.emqx.go +++ b/internal/cmd/makecmd/emqx.go @@ -1,11 +1,11 @@ -package cmd +package makecmd import ( "github.com/spf13/cobra" "yizhisec.com/hsv2/forge/internal/controller/maker" ) -func makeEMQX() *cobra.Command { +func EMQX() *cobra.Command { _cmd := &cobra.Command{ Use: "emqx", Short: "Make EMQX", diff --git a/internal/cmd/make.es.go b/internal/cmd/makecmd/es.go similarity index 94% rename from internal/cmd/make.es.go rename to internal/cmd/makecmd/es.go index 2cad009..fa232ee 100644 --- a/internal/cmd/make.es.go +++ b/internal/cmd/makecmd/es.go @@ -1,4 +1,4 @@ -package cmd +package makecmd import ( "fmt" @@ -7,7 +7,7 @@ import ( "yizhisec.com/hsv2/forge/internal/controller/maker" ) -func makeES() *cobra.Command { +func ES() *cobra.Command { var ( makeHelper bool memRate int diff --git a/internal/cmd/make.flannel.go b/internal/cmd/makecmd/flannel.go similarity index 91% rename from internal/cmd/make.flannel.go rename to internal/cmd/makecmd/flannel.go index 30d4999..a153ef1 100644 --- a/internal/cmd/make.flannel.go +++ b/internal/cmd/makecmd/flannel.go @@ -1,11 +1,11 @@ -package cmd +package makecmd import ( "github.com/spf13/cobra" "yizhisec.com/hsv2/forge/internal/controller/maker" ) -func makeFlannel() *cobra.Command { +func Flannel() *cobra.Command { var ( _mode string ) diff --git a/internal/cmd/make.hsnet.go b/internal/cmd/makecmd/hsnet.go similarity index 87% rename from internal/cmd/make.hsnet.go rename to internal/cmd/makecmd/hsnet.go index db1d158..503d248 100644 --- a/internal/cmd/make.hsnet.go +++ b/internal/cmd/makecmd/hsnet.go @@ -1,11 +1,11 @@ -package cmd +package makecmd import ( "github.com/spf13/cobra" "yizhisec.com/hsv2/forge/internal/controller/maker" ) -func makeHSNet() *cobra.Command { +func HSNet() *cobra.Command { _cmd := &cobra.Command{ Use: "hs-net", Short: "Build hs-net", diff --git a/internal/cmd/make.images.go b/internal/cmd/makecmd/images.go similarity index 92% rename from internal/cmd/make.images.go rename to internal/cmd/makecmd/images.go index 3b3e5a9..81df10f 100644 --- a/internal/cmd/make.images.go +++ b/internal/cmd/makecmd/images.go @@ -1,4 +1,4 @@ -package cmd +package makecmd import ( "os" @@ -9,7 +9,7 @@ import ( "yizhisec.com/hsv2/forge/internal/opt" ) -func makeImages() *cobra.Command { +func Images() *cobra.Command { cmd := &cobra.Command{ Use: "images", Aliases: []string{"image"}, diff --git a/internal/cmd/make.lessdns.go b/internal/cmd/makecmd/lessdns.go similarity index 87% rename from internal/cmd/make.lessdns.go rename to internal/cmd/makecmd/lessdns.go index 37b5d25..0f536d0 100644 --- a/internal/cmd/make.lessdns.go +++ b/internal/cmd/makecmd/lessdns.go @@ -1,11 +1,11 @@ -package cmd +package makecmd import ( "github.com/spf13/cobra" "yizhisec.com/hsv2/forge/internal/controller/maker" ) -func makeLessDNS() *cobra.Command { +func LessDNS() *cobra.Command { _cmd := &cobra.Command{ Use: "lessdns", Short: "Build lessdns", diff --git a/internal/cmd/make.longhorn.go b/internal/cmd/makecmd/longhorn.go similarity index 91% rename from internal/cmd/make.longhorn.go rename to internal/cmd/makecmd/longhorn.go index b001adc..9a3eaf5 100644 --- a/internal/cmd/make.longhorn.go +++ b/internal/cmd/makecmd/longhorn.go @@ -1,11 +1,11 @@ -package cmd +package makecmd import ( "github.com/spf13/cobra" "yizhisec.com/hsv2/forge/internal/controller/maker" ) -func makeLonghorn() *cobra.Command { +func Longhorn() *cobra.Command { var ( replicaCount int ) diff --git a/internal/cmd/make.mysql.go b/internal/cmd/makecmd/mysql.go similarity index 93% rename from internal/cmd/make.mysql.go rename to internal/cmd/makecmd/mysql.go index f4d432f..5c4b3a5 100644 --- a/internal/cmd/make.mysql.go +++ b/internal/cmd/makecmd/mysql.go @@ -1,4 +1,4 @@ -package cmd +package makecmd import ( "fmt" @@ -7,8 +7,7 @@ import ( "yizhisec.com/hsv2/forge/internal/controller/maker" ) -func makeMysql() *cobra.Command { - +func Mysql() *cobra.Command { var ( replicas int storage int diff --git a/internal/cmd/make.redis.go b/internal/cmd/makecmd/redis.go similarity index 94% rename from internal/cmd/make.redis.go rename to internal/cmd/makecmd/redis.go index faa1eeb..f240017 100644 --- a/internal/cmd/make.redis.go +++ b/internal/cmd/makecmd/redis.go @@ -1,11 +1,11 @@ -package cmd +package makecmd import ( "github.com/spf13/cobra" "yizhisec.com/hsv2/forge/internal/controller/maker" ) -func makeRedis() *cobra.Command { +func Redis() *cobra.Command { var ( replicas int password string diff --git a/internal/cmd/make.yosguard.go b/internal/cmd/makecmd/yosguard.go similarity index 87% rename from internal/cmd/make.yosguard.go rename to internal/cmd/makecmd/yosguard.go index 6076fa3..248cfe6 100644 --- a/internal/cmd/make.yosguard.go +++ b/internal/cmd/makecmd/yosguard.go @@ -1,11 +1,11 @@ -package cmd +package makecmd import ( "github.com/spf13/cobra" "yizhisec.com/hsv2/forge/internal/controller/maker" ) -func makeYosguard() *cobra.Command { +func Yosguard() *cobra.Command { _cmd := &cobra.Command{ Use: "yosguard", Aliases: []string{"YOS"}, diff --git a/internal/controller/maker/app.user.go b/internal/controller/maker/app.user.go new file mode 100644 index 0000000..4f66789 --- /dev/null +++ b/internal/controller/maker/app.user.go @@ -0,0 +1,9 @@ +package maker + +import ( + "context" +) + +func (m *maker) AppUser(ctx context.Context, replica int) error { + return nil +} diff --git a/internal/controller/maker/configmap.go b/internal/controller/maker/configmap.go new file mode 100644 index 0000000..c83b66c --- /dev/null +++ b/internal/controller/maker/configmap.go @@ -0,0 +1,217 @@ +package maker + +import ( + "context" + "fmt" + "os" + "path/filepath" + "strings" + + "gitea.loveuer.com/yizhisec/pkg3/logger" + "github.com/samber/lo" + "yizhisec.com/hsv2/forge/internal/opt" + "yizhisec.com/hsv2/forge/pkg/downloader" + "yizhisec.com/hsv2/forge/pkg/extractor" + "yizhisec.com/hsv2/forge/pkg/tool/random" +) + +type ConfigMapOpt func(*configMapOpt) +type configMapOpt struct { + Vendor string +} + +func (m *maker) ConfigMap(ctx context.Context, opts ...ConfigMapOpt) error { + + const ( + sslPubCrt = `-----BEGIN PUBLIC KEY----- +MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA4QohTyK0GGjPW20T/B+K +GDfSPPCbHoy7Dpzk7NHtVgHWLds21+SRN5EN0p/6HLc5XrMGmn1eW6uMBHHn6hBX +JVuwJ4j9+mjoXqA+IwzQYI8GdFR4uge/UyAe5D2Vlo7p5bjfdSq1ZIHRiOmpct59 +GEXTtGR709gnxuP4yd9kNswwfCcanTY8N5ZS+m9jSkIOVKKShJ02Y8OaIaspvkgo +qiH7P/rwYrcB53WkvrM1+ktmHm65yJsDUxPfRgkcfo6X+2dtMQuM6leTmRHwRmnL +bwP+UE6H3cvC0hgttJApacZe2ewhZDqfR4lnBlP1zHwCTc8wjpDXnFIWIHuGnFWy +ip/24LB7noaq2r2rfr/pLX5ONcb5swAWoESQ87zQCjJSy5gxRUB0ZwyeNsVGaYKt +qyUaev1AGN4Gs5PO52QXCOOudp7R0QlJkt/UZe1e057nasrS28PJALboHuP5mpjQ +s2NL1GuOeYhwX5khvW3ghB3x7+z9Lexnd30JAywOz9y3YctQMkS6iD3D+YHNJfIu +5VLYDPKbvRnfgwzdsv5kvKy1VZZEVdWGMqLlKDTFSPZdiQ1lGk5wYKZPXKQ3DI8q +ul5FJ0pkrW3VMewOysX2Hjoakftvajpuf+Mtkz3C2vDRAsBBTXhKDJZhCGAkibVI +YxyddOvOMDfCI3Xx2VjicukCAwEAAQ== +-----END PUBLIC KEY-----` + sslWebCrt = `-----BEGIN CERTIFICATE----- +MIIBeTCCASACAQEwCgYIKoZIzj0EAwIwTTELMAkGA1UEBhMCQ04xEjAQBgNVBAgM +CUd1YW5nZG9uZzESMBAGA1UEBwwJR3Vhbmd6aG91MRYwFAYDVQQKDA1ZaVpoaSBS +b290IENBMB4XDTIyMDgyMTA4MjEzMloXDTMyMDgxODA4MjEzMlowRTELMAkGA1UE +BhMCQ04xEjAQBgNVBAgMCUd1YW5nZG9uZzESMBAGA1UEBwwJR3Vhbmd6aG91MQ4w +DAYDVQQKDAVZaVpoaTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABOI4Fy+rT8ca +AuW390kWqhfqtv1a9+KISsESg/tuUiNYile3Tl7ndMzZmBJDlIOGXt8KcFc8t7kU +Lx/nUF3g4rcwCgYIKoZIzj0EAwIDRwAwRAIgFc6wgYlcdUoFtfZDEeW8a2xloUA3 +HaPnkqCPZlKzwlACIARWSaWA64UTC+et/n3LZY9ZGWRatzxhhALToM33pewH +-----END CERTIFICATE-----` + sslClientCrt = `-----BEGIN CERTIFICATE----- +MIIBezCCASACAQEwCgYIKoZIzj0EAwIwTTELMAkGA1UEBhMCQ04xEjAQBgNVBAgM +CUd1YW5nZG9uZzESMBAGA1UEBwwJR3Vhbmd6aG91MRYwFAYDVQQKDA1ZaVpoaSBS +b290IENBMB4XDTIyMTIwMjEwMTMxNloXDTMyMTEyOTEwMTMxNlowRTELMAkGA1UE +BhMCQ04xEjAQBgNVBAgMCUd1YW5nZG9uZzESMBAGA1UEBwwJR3Vhbmd6aG91MQ4w +DAYDVQQKDAVZaVpoaTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABJ74lcE1h9K3 +6ks6PPI9TrafVySsozy/2S4HTH05hfKSMTWUGjhrPLGexy5R3YzSk9eLNpfzEHEG +2VhrCDR3wNUwCgYIKoZIzj0EAwIDSQAwRgIhAK1pvrP4uOYbZt92IPuoQXK2ESYf +w0QG+/cJlho3pj3oAiEAnGhFUlFwMhV3LIjkE9SIY4zDlJeFORC9v/BjL1m1u6U= +-----END CERTIFICATE-----` + sslClientKey = `-----BEGIN EC PARAMETERS----- +BggqhkjOPQMBBw== +-----END EC PARAMETERS----- +-----BEGIN EC PRIVATE KEY----- +MHcCAQEEIESZAIwzWT3R+6anwL8EI7l7va3LJlYCPMHWFTaSrH8OoAoGCCqGSM49 +AwEHoUQDQgAEnviVwTWH0rfqSzo88j1Otp9XJKyjPL/ZLgdMfTmF8pIxNZQaOGs8 +sZ7HLlHdjNKT14s2l/MQcQbZWGsINHfA1Q== +-----END EC PRIVATE KEY-----` + sslClientCaCrt = `-----BEGIN CERTIFICATE----- +MIIBiTCCATACCQCe3EeGhAHb+DAKBggqhkjOPQQDAjBNMQswCQYDVQQGEwJDTjES +MBAGA1UECAwJR3Vhbmdkb25nMRIwEAYDVQQHDAlHdWFuZ3pob3UxFjAUBgNVBAoM +DVlpWmhpIFJvb3QgQ0EwHhcNMjIwNzI2MDY1NzI1WhcNMzIwNzIzMDY1NzI1WjBN +MQswCQYDVQQGEwJDTjESMBAGA1UECAwJR3Vhbmdkb25nMRIwEAYDVQQHDAlHdWFu +Z3pob3UxFjAUBgNVBAoMDVlpWmhpIFJvb3QgQ0EwWTATBgcqhkjOPQIBBggqhkjO +PQMBBwNCAATg+MJSN3USPg0GF3Vrt3ci07teA7UuxxJePLXMZVKNIdZ5viH2j6cQ +S5hFhcOi48nUX/+titpKgnia1qKkHrPUMAoGCCqGSM49BAMCA0cAMEQCIA1tPS1s +qTolNOc84eyZcuc1qAAdSERKjyIW1l8yuTKDAiBWLOBKAolylbhu46yB3Z2xKdp1 +9Mv7I02zYZhbkVhcCA== +-----END CERTIFICATE-----` + sslClientCaKey = `-----BEGIN EC PARAMETERS----- +BggqhkjOPQMBBw== +-----END EC PARAMETERS----- +-----BEGIN EC PRIVATE KEY----- +MHcCAQEEIFDTepl14/ve7Ye4BsC7NS3ItVN74kgGvWDUyPKHmeKhoAoGCCqGSM49 +AwEHoUQDQgAE4PjCUjd1Ej4NBhd1a7d3ItO7XgO1LscSXjy1zGVSjSHWeb4h9o+n +EEuYRYXDouPJ1F//rYraSoJ4mtaipB6z1A== +-----END EC PRIVATE KEY-----` + upsert = `#!/bin/bash + +kubectl create configmap config-token --namespace hsv2 --from-file=token=./token --dry-run=client -o yaml | kubectl apply -f - +kubectl create configmap config-license-init --namespace hsv2 --from-file=server_license_init.conf=./server_license_init.conf --dry-run=client -o yaml | kubectl apply -f - +kubectl create configmap config-oem-data --namespace hsv2 --from-file=data.json=./oem_data.json --dry-run=client -o yaml | kubectl apply -f - + +kubectl create configmap ssl-pub-crt --namespace hsv2 --from-file=pub_key=./ssl_pub.crt --dry-run=client -o yaml | kubectl apply -f - +kubectl create configmap ssl-client-crt --namespace hsv2 --from-file=client.crt=./ssl_client.crt --dry-run=client -o yaml | kubectl apply -f - +kubectl create configmap ssl-client-key --namespace hsv2 --from-file=client.key=./ssl_client.key --dry-run=client -o yaml | kubectl apply -f - +kubectl create configmap ssl-client-ca-crt --namespace hsv2 --from-file=client.ca.crt=./ssl_client_ca.crt --dry-run=client -o yaml | kubectl apply -f - +kubectl create configmap ssl-client-ca-key --namespace hsv2 --from-file=client.ca.key=./ssl_client_ca.key --dry-run=client -o yaml | kubectl apply -f - +kubectl create configmap ssl-web-crt --namespace hsv2 --from-file=web.server.crt=./ssl_web.crt --dry-run=client -o yaml | kubectl apply -f - +` + ) + + var ( + err error + dir = filepath.Join(opt.Cfg.Make.Dir, "configmap") + vendorUrlMap = map[string]string{ + "standard": "https://artifactory.yizhisec.com/artifactory/yizhisec-release/oem/release/2.1.0-std/oem.tar.gz", + "elink": "https://artifactory.yizhisec.com/artifactory/yizhisec-release/oem/release/2.1.0-std/oem_csgElink.tar.gz", + "noah": "https://artifactory.yizhisec.com/artifactory/yizhisec-release/oem/release/2.1.0-std/oem_noah.tar.gz", + } + o = &configMapOpt{ + Vendor: "standard", + } + ) + + logger.Info("☑️ maker.ConfigMap: 开始构建 ConfigMap...") + + for _, fn := range opts { + fn(o) + } + + if _, ok := vendorUrlMap[o.Vendor]; !ok { + logger.Debug("❌ maker.ConfigMap: 不支持的 vendor: %s", o.Vendor) + return fmt.Errorf("vendor %s 不支持, 请从下面选择: %v", o.Vendor, lo.MapToSlice(vendorUrlMap, func(key string, value string) string { + return key + })) + } + + logger.Debug("☑️ maker.ConfigMap: 创建目标目录: %s", dir) + if err = os.MkdirAll(dir, 0755); err != nil { + logger.Debug("❌ maker.ConfigMap: 创建目标目录: %s 失败, 错误: %v", dir, err) + return err + } + logger.Debug("✅ maker.ConfigMap: 创建目标目录: %s 成功", dir) + + // download oem.tar.gz + logger.Debug("☑️ maker.ConfigMap: 下载 oem.tar.gz 文件: %s", vendorUrlMap[o.Vendor]) + if err = downloader.Download(ctx, vendorUrlMap[o.Vendor], filepath.Join(dir, "oem.tar.gz")); err != nil { + logger.Debug("❌ maker.ConfigMap: 下载 oem.tar.gz 文件: %s 失败, 错误: %v", vendorUrlMap[o.Vendor], err) + return err + } + logger.Debug("✅ maker.ConfigMap: 下载 oem.tar.gz 文件: %s 成功", vendorUrlMap[o.Vendor]) + + // extract oem.tar.gz + logger.Debug("☑️ maker.ConfigMap: 解压 oem.tar.gz 文件: %s", filepath.Join(dir, "oem.tar.gz")) + if err = extractor.Extract(ctx, filepath.Join(dir, "oem.tar.gz"), dir); err != nil { + logger.Debug("❌ maker.ConfigMap: 解压 oem.tar.gz 文件: %s 失败, 错误: %v", filepath.Join(dir, "oem.tar.gz"), err) + return err + } + logger.Debug("✅ maker.ConfigMap: 解压 oem.tar.gz 文件: %s 成功", filepath.Join(dir, "oem.tar.gz")) + + // mv oem/data.json ./oem_data.json + if err = os.Rename(filepath.Join(dir, "oem", "data.json"), filepath.Join(dir, "oem_data.json")); err != nil { + logger.Debug("❌ maker.ConfigMap: 移动 oem/data.json 文件: %s 失败, 错误: %v", filepath.Join(dir, "oem", "data.json"), err) + return err + } + logger.Debug("✅ maker.ConfigMap: 移动 oem/data.json 文件: %s 成功", filepath.Join(dir, "oem_data.json")) + + // generate random token 8 length, lower case + logger.Debug("☑️ maker.ConfigMap: 写入 token 文件: %s", filepath.Join(dir, "token")) + token := strings.ToLower(random.RandomString(8)) + if err = os.WriteFile(filepath.Join(dir, "token"), []byte(token), 0644); err != nil { + logger.Debug("❌ maker.ConfigMap: 写入 token 文件: %s 失败, 错误: %v", filepath.Join(dir, "token"), err) + return err + } + logger.Debug("✅ maker.ConfigMap: 写入 token 文件: %s 成功", filepath.Join(dir, "token")) + + // todo: server_license_init.conf + // example content: {"uuid": "5044e2c0-1b15-475d-a193-7ee5d9c7b3ac", "install_time": 1669976272} + + // todo: write crt, key down to file + if err = os.WriteFile(filepath.Join(dir, "ssl_pub.crt"), []byte(sslPubCrt), 0644); err != nil { + logger.Debug("❌ maker.ConfigMap: 写入 ssl_pub.crt 文件: %s 失败, 错误: %v", filepath.Join(dir, "ssl_pub.crt"), err) + return err + } + logger.Debug("✅ maker.ConfigMap: 写入 ssl_pub.crt 文件: %s 成功", filepath.Join(dir, "ssl_pub.crt")) + + if err = os.WriteFile(filepath.Join(dir, "ssl_web.crt"), []byte(sslWebCrt), 0644); err != nil { + logger.Debug("❌ maker.ConfigMap: 写入 ssl_web.crt 文件: %s 失败, 错误: %v", filepath.Join(dir, "ssl_web.crt"), err) + return err + } + logger.Debug("✅ maker.ConfigMap: 写入 ssl_web.crt 文件: %s 成功", filepath.Join(dir, "ssl_web.crt")) + + if err = os.WriteFile(filepath.Join(dir, "ssl_client.crt"), []byte(sslClientCrt), 0644); err != nil { + logger.Debug("❌ maker.ConfigMap: 写入 ssl_client.crt 文件: %s 失败, 错误: %v", filepath.Join(dir, "ssl_client.crt"), err) + return err + } + logger.Debug("✅ maker.ConfigMap: 写入 ssl_client.crt 文件: %s 成功", filepath.Join(dir, "ssl_client.crt")) + + if err = os.WriteFile(filepath.Join(dir, "ssl_client.key"), []byte(sslClientKey), 0644); err != nil { + logger.Debug("❌ maker.ConfigMap: 写入 ssl_client.key 文件: %s 失败, 错误: %v", filepath.Join(dir, "ssl_client.key"), err) + return err + } + logger.Debug("✅ maker.ConfigMap: 写入 ssl_client.key 文件: %s 成功", filepath.Join(dir, "ssl_client.key")) + + if err = os.WriteFile(filepath.Join(dir, "ssl_client_ca.crt"), []byte(sslClientCaCrt), 0644); err != nil { + logger.Debug("❌ maker.ConfigMap: 写入 ssl_client_ca.crt 文件: %s 失败, 错误: %v", filepath.Join(dir, "ssl_client_ca.crt"), err) + return err + } + logger.Debug("✅ maker.ConfigMap: 写入 ssl_client_ca.crt 文件: %s 成功", filepath.Join(dir, "ssl_client_ca.crt")) + + if err = os.WriteFile(filepath.Join(dir, "ssl_client_ca.key"), []byte(sslClientCaKey), 0644); err != nil { + logger.Debug("❌ maker.ConfigMap: 写入 ssl_client_ca.key 文件: %s 失败, 错误: %v", filepath.Join(dir, "ssl_client_ca.key"), err) + return err + } + logger.Debug("✅ maker.ConfigMap: 写入 ssl_client_ca.key 文件: %s 成功", filepath.Join(dir, "ssl_client_ca.key")) + + // upsert configmap + logger.Debug("☑️ maker.ConfigMap: 执行 upsert 脚本: %s", filepath.Join(dir, "upsert.sh")) + if err = os.WriteFile(filepath.Join(dir, "upsert.sh"), []byte(upsert), 0755); err != nil { + logger.Debug("❌ maker.ConfigMap: 写入 upsert.sh 文件: %s 失败, 错误: %v", filepath.Join(dir, "upsert.sh"), err) + return err + } + logger.Debug("✅ maker.ConfigMap: 写入 upsert.sh 文件: %s 成功", filepath.Join(dir, "upsert.sh")) + + logger.Info("✅ maker.ConfigMap: 构建 ConfigMap 成功!!!") + return nil +} diff --git a/internal/controller/maker/emqx.go b/internal/controller/maker/emqx.go index 6272539..513029e 100644 --- a/internal/controller/maker/emqx.go +++ b/internal/controller/maker/emqx.go @@ -16,18 +16,22 @@ func (m *maker) EMQX(ctx context.Context) error { location = filepath.Join(opt.Cfg.Make.Dir, "emqx") ) - logger.Info("☑️ MakeEMQX: 开始构建 emqx(mqtt) 依赖...") - + logger.Info("☑️ maker.EMQX: 开始构建 emqx(mqtt) 依赖...") + logger.Debug("☑️ maker.EMQX: 开始构建 emqx(mqtt) 依赖...") + logger.Debug("☑️ maker.EMQX: 创建目录 %s", location) if err = os.MkdirAll(location, 0755); err != nil { - logger.Debug("❌ MakeEMQX: 创建 emqx 目录失败: %v", err) + logger.Debug("❌ maker.EMQX: 创建 emqx 目录失败: %v", err) return err } + logger.Debug("✅ maker.EMQX: 创建目录 %s 成功", location) + logger.Debug("☑️ maker.EMQX: 写入 emqx.yaml 文件..., dest = %s", filepath.Join(location, "emqx.yaml")) if err = os.WriteFile(filepath.Join(location, "emqx.yaml"), resource.YAMLEMQX, 0644); err != nil { - logger.Debug("❌ MakeEMQX: 写入 emqx.yaml 失败, err: %v", err) + logger.Debug("❌ maker.EMQX: 写入 emqx.yaml 失败, err: %v", err) return err } + logger.Debug("✅ maker.EMQX: 写入 emqx.yaml 文件成功, dest = %s", filepath.Join(location, "emqx.yaml")) - logger.Info("✅ MakeEMQX: 构建 emqx(mqtt) 依赖成功!!!") + logger.Info("✅ maker.EMQX: 构建 emqx(mqtt) 依赖成功!!!") return nil } diff --git a/internal/controller/maker/hsnet.go b/internal/controller/maker/hsnet.go index 2bc6b40..7f33860 100644 --- a/internal/controller/maker/hsnet.go +++ b/internal/controller/maker/hsnet.go @@ -10,6 +10,61 @@ import ( ) func (m *maker) HSNet(ctx context.Context) error { + const ( + service = `[Unit] +Description=hs-net Container Service +Documentation=https://docs.containerd.io +After=network.target containerd.service + +[Service] +# 启动前清理旧容器 +# ExecStartPre=-/usr/local/bin/k0s ctr -n hs-net task kill hs-net +ExecStartPre=-/usr/local/bin/k0s ctr -n hs-net container rm hs-net + +# 拉取最新镜像(按需启用/注释) +# ExecStartPre=/usr/local/bin/k0s ctr -n hs-net images pull hub.yizhisec.com/hybridscope/hsnet:release_2.1.0-std + +# 容器启动命令 +ExecStart=/usr/local/bin/k0s ctr -n hs-net run \ + --net-host \ + --privileged \ + --cgroup host \ + --env LD_LIBRARY_PATH=/yizhisec/hs_net \ + --env RUSTFLAGS="-C target-cpu=nehalem" \ + --env RUST_BACKTRACE=1 \ + --mount type=bind,src=/etc/localtime,dst=/etc/localtime,options=rbind:ro \ + --mount type=bind,src=/etc/hosts,dst=/etc/hosts,options=rbind:ro \ + --mount type=bind,src=/etc/yizhisec,dst=/etc/yizhisec,options=rbind:rw \ + --mount type=bind,src=/tmp,dst=/tmp,options=rbind:rw \ + --mount type=bind,src=/etc/yosguard/uuid,dst=/etc/gateway/uuid.json,options=rbind:ro \ + --mount type=bind,src=/mnt/huge,dst=/mnt/huge,options=rbind:rw \ + --mount type=bind,src=/var/run,dst=/var/run,options=rbind:rw \ + --mount type=bind,src=/yizhisec,dst=/yizhisec,options=rbind:rw \ + --mount type=bind,src=/yizhisec/hs_net/conf,dst=/etc/hs_net,options=rbind:rw \ + hub.yizhisec.com/hybridscope/hsnet:release_2.1.0-std hs-net + +# 重启策略 +Restart=on-failure +RestartSec=5s +StartLimitInterval=60s +StartLimitBurst=5 + +# 资源限制(按需调整) +MemoryLimit=2G +CPUQuota=80% + +# 日志处理(将容器 stdout/stderr 交由 journald 管理) +StandardOutput=journal +StandardError=journal +SyslogIdentifier=hs-net + +# 清理退出的容器 +# ExecStop=/usr/local/bin/k0s ctr -n hs-net task kill hs-net +ExecStopPost=/usr/local/bin/k0s ctr -n hs-net container rm hs-net + +[Install] +WantedBy=multi-user.target` + ) var ( err error location = filepath.Join(opt.Cfg.Make.Dir, "dependency", "hs-net") diff --git a/internal/controller/maker/lessdns.go b/internal/controller/maker/lessdns.go index 16b758e..43ed51f 100644 --- a/internal/controller/maker/lessdns.go +++ b/internal/controller/maker/lessdns.go @@ -16,19 +16,22 @@ func (m *maker) LessDNS(ctx context.Context) error { location = filepath.Join(opt.Cfg.Make.Dir, "dependency", "less-dns") ) - logger.Info("MakeLessDNS: 开始构建 less-dns...") + logger.Info("☑️ maker.LessDNS: 开始构建 less-dns...") + logger.Debug("☑️ maker.LessDNS: 开始构建 less-dns...") + logger.Debug("☑️ maker.LessDNS: 创建目录 %s", location) if err = os.MkdirAll(location, 0755); err != nil { - logger.Error("MakeLessDNS: 创建目录失败s") - logger.Debug("MakeLessDNS: 创建目录失败: %s", err.Error()) + logger.Debug("❌ maker.LessDNS: 创建目录失败: %v", err) return err } + logger.Debug("✅ maker.LessDNS: 创建目录 %s 成功", location) + logger.Debug("☑️ maker.LessDNS: 写入 deployment.yaml 文件..., dest = %s", filepath.Join(location, "deployment.yaml")) if err = os.WriteFile(filepath.Join(location, "deployment.yaml"), resource.YAMLLessDNS, 0644); err != nil { - logger.Error("MakeLessDNS: 写入文件失败") - logger.Debug("MakeLessDNS: 写入文件失败: %s", err.Error()) + logger.Debug("❌ maker.LessDNS: 写入 deployment.yaml 失败, dest = %s, err = %v", filepath.Join(location, "deployment.yaml"), err) return err } + logger.Debug("✅ maker.LessDNS: 写入 deployment.yaml 文件成功, dest = %s", filepath.Join(location, "deployment.yaml")) - logger.Info("MakeLessDNS: 构建 less-dns 成功!!!") + logger.Info("✅ maker.LessDNS: 构建 less-dns 成功!!!") return nil } diff --git a/internal/controller/maker/redis.go b/internal/controller/maker/redis.go index 141cc96..fb07a09 100644 --- a/internal/controller/maker/redis.go +++ b/internal/controller/maker/redis.go @@ -95,34 +95,36 @@ metrics: chartFile := filepath.Join(redisDir, chartFilename) valuesFile := filepath.Join(redisDir, "values.yaml") + logger.Info("☑️ maker.Redis: 开始构建 Redis 资源...") + logger.Debug("☑️ maker.Redis: 开始构建 Redis 资源..., opt = %#v", o) + logger.Debug("☑️ maker.Redis: 创建目录 %s", redisDir) if err := os.MkdirAll(redisDir, 0755); err != nil { + logger.Debug("❌ maker.Redis: 创建目录失败: %v", err) return err } + logger.Debug("✅ maker.Redis: 创建目录 %s 成功", redisDir) - logger.Info("开始构建 Redis 资源...") - logger.Debug("下载地址: %s", chartURL) - logger.Debug("目标目录: %s", redisDir) - logger.Debug("Redis 副本数: %d", o.ReplicaCount) - + logger.Debug("☑️ maker.Redis: 下载 Redis chart..., url = %s, dest = %s", chartURL, chartFile) if err := downloader.Download( ctx, chartURL, chartFile, downloader.WithInsecureSkipVerify(), ); err != nil { - logger.Debug("❌ 下载 Redis chart 失败") + logger.Debug("❌ maker.Redis: 下载 Redis chart 失败, url = %s, err = %v", chartURL, err) return err } - logger.Debug("✅ 成功下载 Redis chart") + logger.Debug("✅ maker.Redis: 下载 Redis chart 成功, url = %s", chartURL) + logger.Debug("☑️ maker.Redis: 写入 values.yaml 文件..., dest = %s", valuesFile) 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 失败") + logger.Debug("❌ maker.Redis: 写入 values.yaml 文件失败, dest = %s, err = %v", valuesFile, err) return err } - logger.Debug("✅ 成功创建 values.yaml") + logger.Debug("✅ maker.Redis: 写入 values.yaml 文件成功, dest = %s", valuesFile) - logger.Info("✅ Redis 资源构建成功") + logger.Info("✅ maker.Redis: 构建 Redis 资源成功!!!") return nil } diff --git a/internal/controller/maker/yosguard.go b/internal/controller/maker/yosguard.go index 716b12b..7c01b0f 100644 --- a/internal/controller/maker/yosguard.go +++ b/internal/controller/maker/yosguard.go @@ -1,14 +1,14 @@ package maker import ( - "context" - "os" - "path/filepath" + "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" + "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) @@ -16,8 +16,8 @@ type YosguardOpt func(*yosguardOpt) type yosguardOpt struct{} func (m *maker) Yosguard(ctx context.Context, opts ...YosguardOpt) error { - const ( - configTemplate = ` + const ( + configTemplate = ` Web: # default listen in docker0 Host: 172.17.0.1 @@ -44,7 +44,7 @@ Database: DBPath: "/etc/yosguard/db/yosguard.db" SQLPath: "/etc/yosguard/db/create.sql"` - systemdService = ` + systemdService = ` [Unit] Description=YiZhiSec YOSGuard After=network.target @@ -61,44 +61,53 @@ RestartSec=15 [Install] WantedBy=multi-user.target` - binURL = "https://artifactory.yizhisec.com:443/artifactory/filestore/hsv2/bin/yosguard" - ) + binURL = "https://artifactory.yizhisec.com:443/artifactory/filestore/hsv2/bin/yosguard" + ) - location := filepath.Join(opt.Cfg.Make.Dir, "dependency", "yosguard") + location := filepath.Join(opt.Cfg.Make.Dir, "dependency", "yosguard") - logger.Info("☑️ MakeYosguard: 开始构建 yosguard...") + logger.Info("☑️ maker.Yosguard: 开始构建 yosguard...") + logger.Debug("☑️ maker.Yosguard: 创建目录 %s", location) + if err := os.MkdirAll(location, 0755); err != nil { + logger.Debug("❌ maker.Yosguard: 创建 yosguard 目录失败: %v", err) + return err + } + logger.Debug("✅ maker.Yosguard: 创建目录 %s 成功", location) - if err := os.MkdirAll(location, 0755); err != nil { - logger.Debug("❌ MakeYosguard: 创建 yosguard 目录失败: %v", err) - return err - } + logger.Debug("☑️ maker.Yosguard: 下载 yosguard 二进制文件..., url = %s, dest = %s", binURL, filepath.Join(location, "yosguard")) + if err := downloader.Download( + ctx, + binURL, + filepath.Join(location, "yosguard"), + downloader.WithInsecureSkipVerify(), + downloader.WithFileMode(0755), + ); err != nil { + logger.Debug("❌ maker.Yosguard: 下载 yosguard 失败, url = %s, err = %v", binURL, err) + return err + } + logger.Debug("✅ maker.Yosguard: 下载 yosguard 成功, url = %s", binURL) - 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 - } + logger.Debug("☑️ maker.Yosguard: 写入 config_template.yml 文件..., dest = %s", filepath.Join(location, "config_template.yml")) + if err := os.WriteFile(filepath.Join(location, "config_template.yml"), []byte(configTemplate), 0644); err != nil { + logger.Debug("❌ maker.Yosguard: 写入 config_template.yml 失败, dest = %s, err = %v", filepath.Join(location, "config_template.yml"), err) + return err + } + logger.Debug("✅ maker.Yosguard: 写入 config_template.yml 文件成功, dest = %s", filepath.Join(location, "config_template.yml")) - 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 - } + logger.Debug("☑️ maker.Yosguard: 写入 create.sql 文件..., dest = %s", filepath.Join(location, "create.sql")) + if err := os.WriteFile(filepath.Join(location, "create.sql"), resource.SQLYosguard, 0644); err != nil { + logger.Debug("❌ maker.Yosguard: 写入 create.sql 失败, dest = %s, err = %v", filepath.Join(location, "create.sql"), err) + return err + } + logger.Debug("✅ maker.Yosguard: 写入 create.sql 文件成功, dest = %s", filepath.Join(location, "create.sql")) - if err := os.WriteFile(filepath.Join(location, "create.sql"), resource.SQLYosguard, 0644); err != nil { - logger.Debug("❌ MakeYosguard: 生成 create.sql 失败: %v", err) - return err - } + logger.Debug("☑️ maker.Yosguard: 写入 yosguard.service 文件..., dest = %s", filepath.Join(location, "yosguard.service")) + if err := os.WriteFile(filepath.Join(location, "yosguard.service"), []byte(systemdService), 0644); err != nil { + logger.Debug("❌ maker.Yosguard: 写入 yosguard.service 失败, dest = %s, err = %v", filepath.Join(location, "yosguard.service"), err) + return err + } + logger.Debug("✅ maker.Yosguard: 写入 yosguard.service 文件成功, dest = %s", filepath.Join(location, "yosguard.service")) - 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 + logger.Info("✅ maker.Yosguard: 构建 yosguard 成功!!!") + return nil } diff --git a/pkg/extractor/extractor.go b/pkg/extractor/extractor.go new file mode 100644 index 0000000..dc89bd3 --- /dev/null +++ b/pkg/extractor/extractor.go @@ -0,0 +1,144 @@ +package extractor + +import ( + "archive/tar" + "compress/gzip" + "context" + "fmt" + "io" + "os" + "path/filepath" + "strings" + + "gitea.loveuer.com/yizhisec/pkg3/logger" +) + +type Options struct { + OnProgress func(filename string, index int, total int) + IsGzipped *bool +} + +type Option func(*Options) + +func WithProgress(callback func(filename string, index int, total int)) Option { + return func(o *Options) { + o.OnProgress = callback + } +} + +func WithGzipCompression(isGzipped bool) Option { + return func(o *Options) { + o.IsGzipped = &isGzipped + } +} + +func Extract(ctx context.Context, src, destDir string, opts ...Option) error { + options := &Options{} + for _, opt := range opts { + opt(options) + } + + logger.Debug("开始解压: %s -> %s", src, destDir) + + f, err := os.Open(src) + if err != nil { + logger.Debug("打开源文件失败 %s: %v", src, err) + return fmt.Errorf("failed to open source file: %w", err) + } + defer f.Close() + + var reader io.Reader = f + var isGzipped bool + + if options.IsGzipped != nil { + isGzipped = *options.IsGzipped + } else { + isGzipped = strings.HasSuffix(strings.ToLower(src), ".tar.gz") || strings.HasSuffix(strings.ToLower(src), ".tgz") + } + + if isGzipped { + gzReader, err := gzip.NewReader(f) + if err != nil { + logger.Debug("创建 gzip reader 失败: %v", err) + return fmt.Errorf("failed to create gzip reader: %w", err) + } + defer gzReader.Close() + reader = gzReader + } + + if err := extractTar(ctx, reader, destDir, options); err != nil { + return err + } + + logger.Debug("解压完成: %s", src) + return nil +} + +func extractTar(ctx context.Context, r io.Reader, destDir string, options *Options) error { + tarReader := tar.NewReader(r) + fileCount := 0 + totalFiles := 0 + + for { + if ctx.Err() != nil { + return ctx.Err() + } + + header, err := tarReader.Next() + if err == io.EOF { + break + } + if err != nil { + logger.Debug("读取 tar 条目失败: %v", err) + return fmt.Errorf("failed to read tar header: %w", err) + } + + target := filepath.Join(destDir, header.Name) + logger.Debug("解压文件: %s", header.Name) + + if options.OnProgress != nil { + options.OnProgress(header.Name, fileCount, totalFiles) + } + + switch header.Typeflag { + case tar.TypeDir: + if err := os.MkdirAll(target, os.FileMode(header.Mode)); err != nil { + logger.Debug("创建目录失败 %s: %v", target, err) + return fmt.Errorf("failed to create directory %s: %w", target, err) + } + case tar.TypeReg: + if err := os.MkdirAll(filepath.Dir(target), 0755); err != nil { + logger.Debug("创建父目录失败 %s: %v", filepath.Dir(target), err) + return fmt.Errorf("failed to create parent directory: %w", err) + } + outFile, err := os.OpenFile(target, os.O_CREATE|os.O_RDWR|os.O_TRUNC, os.FileMode(header.Mode)) + if err != nil { + logger.Debug("创建文件失败 %s: %v", target, err) + return fmt.Errorf("failed to create file %s: %w", target, err) + } + if _, err := io.Copy(outFile, tarReader); err != nil { + outFile.Close() + logger.Debug("写入文件失败 %s: %v", target, err) + return fmt.Errorf("failed to write file %s: %w", target, err) + } + outFile.Close() + fileCount++ + case tar.TypeSymlink: + if err := os.MkdirAll(filepath.Dir(target), 0755); err != nil { + logger.Debug("创建符号链接父目录失败 %s: %v", filepath.Dir(target), err) + return fmt.Errorf("failed to create parent directory for symlink: %w", err) + } + os.Remove(target) + if err := os.Symlink(header.Linkname, target); err != nil { + logger.Debug("创建符号链接失败 %s -> %s: %v", target, header.Linkname, err) + return fmt.Errorf("failed to create symlink %s -> %s: %w", target, header.Linkname, err) + } + fileCount++ + default: + logger.Debug("跳过不支持的文件类型: %s (type: %v)", header.Name, header.Typeflag) + } + } + + logger.Debug("解压完成,共 %d 个文件", fileCount) + return nil +} diff --git a/pkg/resource/seafile.yaml b/pkg/resource/seafile.yaml new file mode 100644 index 0000000..f4da43f --- /dev/null +++ b/pkg/resource/seafile.yaml @@ -0,0 +1,98 @@ +apiVersion: v1 +kind: Namespace +metadata: + name: seafile +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: memcached + namespace: seafile +spec: + replicas: 1 + selector: + matchLabels: + app: memcached + template: + metadata: + labels: + app: memcached + spec: + containers: + - name: memcached + image: hub.yizhisec.com/product/hybridscope/memcached + args: ["-m", "256"] + ports: + - containerPort: 11211 +--- +apiVersion: v1 +kind: Service +metadata: + name: memcached + namespace: seafile +spec: + selector: + app: memcached + ports: + - protocol: TCP + port: 11211 + targetPort: 11211 + +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: seafile + namespace: seafile +spec: + replicas: 1 + selector: + matchLabels: + app: seafile + template: + metadata: + labels: + app: seafile + spec: + containers: + - name: seafile + image: hub.yizhisec.com/product/hybridscope/seafile-mc:latest + imagePullPolicy: IfNotPresent + env: + - name: DB_HOST + value: "mysql-cluster-mysql-master.db-mysql" + - name: DB_ROOT_PASSWD + value: "L0hMysql." #db's password + - name: TIME_ZONE + value: "Asia/Shanghai" + - name: SEAFILE_ADMIN_EMAIL + value: "admin@yizhisec.com" #admin email + - name: SEAFILE_ADMIN_PASSWORD + value: "asecret" #admin password + - name: SEAFILE_SERVER_LETSENCRYPT + value: "false" + - name: SEAFILE_SERVER_HOSTNAME + value: "cloud.hybridscope.com" #hostname + ports: + - containerPort: 80 + volumeMounts: + - name: seafile-data + mountPath: /shared + volumes: + - name: seafile-data + persistentVolumeClaim: + claimName: seafile-data + restartPolicy: Always +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: seafile-data + namespace: seafile +spec: + accessModes: + - ReadWriteOnce + storageClassName: longhorn + resources: + requests: + storage: 10Gi diff --git a/pkg/tool/random/str.go b/pkg/tool/random/str.go new file mode 100644 index 0000000..bae28b9 --- /dev/null +++ b/pkg/tool/random/str.go @@ -0,0 +1,13 @@ +package random + +import "math/rand" + +const charset = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789" + +func RandomString(length int) string { + b := make([]byte, length) + for i := range b { + b[i] = charset[rand.Intn(len(charset))] + } + return string(b) +} diff --git a/pkg/tool/random/str_test.go b/pkg/tool/random/str_test.go new file mode 100644 index 0000000..0b2e36a --- /dev/null +++ b/pkg/tool/random/str_test.go @@ -0,0 +1,26 @@ +package random_test + +import ( + "testing" + "yizhisec.com/hsv2/forge/pkg/tool/random" +) + +func TestRandomString(t *testing.T) { + tests := []struct { + name string // description of this test case + // Named input parameters for target function. + length int + want string + }{ + // TODO: Add test cases. + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got := random.RandomString(tt.length) + // TODO: update the condition below to compare got with tt.want. + if true { + t.Errorf("RandomString() = %v, want %v", got, tt.want) + } + }) + } +}