package maker import ( "context" "fmt" "os" "path/filepath" "strings" "gitea.loveuer.com/yizhisec/pkg3/logger" "github.com/samber/lo" "yizhisec.com/hsv2/forge/pkg/resource" ) type clientPKGDownload struct { URL string Name string } type ClientPKGOption func(*clientPKGOption) type clientPKGOption struct { Downloads []*clientPKGDownload CMDs []string } func WithClientPKGDownload(url, location string) ClientPKGOption { return func(o *clientPKGOption) { if url == "" || location == "" { return } o.Downloads = append(o.Downloads, &clientPKGDownload{ URL: url, Name: location, }) } } func WithClientPKGCMD(cmd string) ClientPKGOption { return func(o *clientPKGOption) { if cmd == "" { return } o.CMDs = append(o.CMDs, cmd) } } func (m *maker) ClientPKG(ctx context.Context, _os string, _version string, api string, opts ...ClientPKGOption) error { const ( Dockerfile = ` FROM hub.yizhisec.com/external/nginx:1.29.4-alpine3.23 RUN mkdir -p /data %s %s COPY nginx.conf /etc/nginx/nginx.conf ` ) if !lo.Contains([]string{"mac", "win", "linux"}, _os) { return fmt.Errorf("invalid os: %s", _os) } var ( o = &clientPKGOption{ Downloads: []*clientPKGDownload{}, CMDs: []string{}, } err error location = filepath.Join(m.workdir, "client", _os) _file string _content string _cmds = "" ) for _, fn := range opts { fn(o) } logger.Info("☑️ maker.ClientPKG: start build client pkg, os = %s, version = %s, location = %s", _os, _version, location) if err = os.MkdirAll(location, 0755); err != nil { logger.Debug("❌ maker.ClientPKG: create directory failed, directory = %s, err = %s", location, err.Error()) return err } if err = os.WriteFile(filepath.Join(location, "version.txt"), []byte(_version), 0644); err != nil { logger.Debug("❌ maker.ClientPKG: write file failed, file = %s, err = %s", filepath.Join(location, "version.txt"), err.Error()) return err } _file = filepath.Join(location, "nginx.conf") _content = fmt.Sprintf(resource.NGINXClientPKG, api) logger.Debug("☑️ maker.ClientPKG: start write file = %s", _file) if os.WriteFile(_file, []byte(_content), 0644); err != nil { logger.Debug("❌ maker.ClientPKG: write file failed, file = %s, err = %s", _file, err.Error()) return err } logger.Debug("✅ maker.ClientPKG: write file success, file = %s", _file) lines := lo.Map(o.Downloads, func(d *clientPKGDownload, index int) string { return fmt.Sprintf("RUN wget -O /data/%s %s", d.Name, d.URL) }) if len(o.CMDs) > 0 { _cmds = fmt.Sprintf("RUN %s", strings.Join(o.CMDs, " && ")) } _file = filepath.Join(location, "Dockerfile") _content = fmt.Sprintf(Dockerfile, strings.Join(lines, "\n"), _cmds) logger.Debug("☑️ maker.ClientPKG: start write file = %s", _file) if os.WriteFile(_file, []byte(_content), 0644); err != nil { logger.Debug("❌ maker.ClientPKG: write file failed, file = %s, err = %s", _file, err.Error()) return err } logger.Debug("✅ maker.ClientPKG: write file success, file = %s", _file) imgName := fmt.Sprintf("hub.yizhisec.com/hsv2/client/%s:%s", _os, _version) logger.Debug("☑️ maker.ClientPKG: build docker image, os = %s, version = %s, full_name = %s", _os, _version, imgName) _cmd := fmt.Sprintf("docker build --network host -t %s -f Dockerfile .", imgName) if err = m.RunCommand(ctx, location, _cmd); err != nil { logger.Debug("❌ maker.ClientPKG: run command failed, cmd = %s, err = %s", _cmd, err.Error()) return err } imgLocation := filepath.Join(location, _os+".tar") logger.Debug("☑️ maker.ClientPKG: save img to %s", imgLocation) _cmd = fmt.Sprintf("docker save hub.yizhisec.com/hsv2/client/%s:%s -o %s", _os, _version, imgLocation) if err = m.RunCommand(ctx, location, _cmd); err != nil { logger.Debug("❌ maker.ClientPKG: run command failed, cmd = %s, err = %s", _cmd, err.Error()) return err } imgNameInCluster := fmt.Sprintf("10.96.123.45:80/hsv2/client/%s:%s", _os, _version) deployment := filepath.Join(location, "deployment.yaml") _content = strings.ReplaceAll( fmt.Sprintf( resource.YAMLClientPKG, 1, // replica 先默认 1 就够了 imgNameInCluster, ), "__os__", _os, ) if err = os.WriteFile(deployment, []byte(_content), 0644); err != nil { logger.Debug("❌ maker.ClientPKG: write file failed, file = %s, err = %s", deployment, err.Error()) return err } logger.Info("️✅ maker.ClientPKG: build client pkg success, os = %s, version = %s, location = %s", _os, _version, location) return nil }