From 9acdd15c1e62a883b170a0404029b6f74a69e40b Mon Sep 17 00:00:00 2001 From: Madray Haven Date: Fri, 27 Sep 2024 15:12:04 +0800 Subject: [PATCH 1/2] feat: pre command for ssh deploy --- internal/deployer/ssh.go | 49 +++++++++++++------ ui/package.json | 2 +- ui/src/components/certimate/AccessSSHForm.tsx | 19 +++++++ ui/src/domain/access.ts | 1 + 4 files changed, 54 insertions(+), 17 deletions(-) diff --git a/internal/deployer/ssh.go b/internal/deployer/ssh.go index 7aa04cac..7890ad77 100644 --- a/internal/deployer/ssh.go +++ b/internal/deployer/ssh.go @@ -19,14 +19,15 @@ type ssh struct { } type sshAccess struct { - Host string `json:"host"` - Username string `json:"username"` - Password string `json:"password"` - Key string `json:"key"` - Port string `json:"port"` - Command string `json:"command"` - CertPath string `json:"certPath"` - KeyPath string `json:"keyPath"` + Host string `json:"host"` + Username string `json:"username"` + Password string `json:"password"` + Key string `json:"key"` + Port string `json:"port"` + PreCommand string `json:"preCommand"` + Command string `json:"command"` + CertPath string `json:"certPath"` + KeyPath string `json:"keyPath"` } func NewSSH(option *DeployerOption) (Deployer, error) { @@ -56,6 +57,7 @@ func (s *ssh) Deploy(ctx context.Context) error { access.CertPath = strings.ReplaceAll(access.CertPath, key, v) access.KeyPath = strings.ReplaceAll(access.KeyPath, key, v) access.Command = strings.ReplaceAll(access.Command, key, v) + access.PreCommand = strings.ReplaceAll(access.PreCommand, key, v) } // 连接 @@ -67,14 +69,24 @@ func (s *ssh) Deploy(ctx context.Context) error { s.infos = append(s.infos, toStr("ssh连接成功", nil)) - // 上传 - session, err := client.NewSession() - if err != nil { - return fmt.Errorf("failed to create session: %w", err) - } - defer session.Close() + // 执行前置命令 + if access.PreCommand != "" { + session, err := client.NewSession() + if err != nil { + return fmt.Errorf("failed to create session: %w", err) + } + defer session.Close() + var stdoutBuf bytes.Buffer + session.Stdout = &stdoutBuf + var stderrBuf bytes.Buffer + session.Stderr = &stderrBuf - s.infos = append(s.infos, toStr("ssh创建session成功", nil)) + s.infos = append(s.infos, toStr("ssh为前置命令创建session成功", nil)) + + if err := session.Run(access.PreCommand); err != nil { + return fmt.Errorf("failed to run pre-command: %w, stdout: %s, stderr: %s", err, stdoutBuf.String(), stderrBuf.String()) + } + } // 上传证书 if err := s.upload(client, s.option.Certificate.Certificate, access.CertPath); err != nil { @@ -91,11 +103,16 @@ func (s *ssh) Deploy(ctx context.Context) error { s.infos = append(s.infos, toStr("ssh上传私钥成功", nil)) // 执行命令 + session, err := client.NewSession() + if err != nil { + return fmt.Errorf("failed to create session: %w", err) + } + defer session.Close() var stdoutBuf bytes.Buffer session.Stdout = &stdoutBuf var stderrBuf bytes.Buffer session.Stderr = &stderrBuf - + s.infos = append(s.infos, toStr("ssh创建session成功", nil)) if err := session.Run(access.Command); err != nil { return fmt.Errorf("failed to run command: %w, stdout: %s, stderr: %s", err, stdoutBuf.String(), stderrBuf.String()) } diff --git a/ui/package.json b/ui/package.json index 5c66202f..1d34d979 100644 --- a/ui/package.json +++ b/ui/package.json @@ -4,7 +4,7 @@ "version": "0.0.0", "type": "module", "scripts": { - "dev": "vite", + "dev": "vite --host", "build": "tsc -b && vite build", "lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0", "preview": "vite preview" diff --git a/ui/src/components/certimate/AccessSSHForm.tsx b/ui/src/components/certimate/AccessSSHForm.tsx index b7af5b4e..cf055b44 100644 --- a/ui/src/components/certimate/AccessSSHForm.tsx +++ b/ui/src/components/certimate/AccessSSHForm.tsx @@ -79,6 +79,7 @@ const AccessSSHForm = ({ key: z.string().min(0).max(20480), keyFile: z.any().optional(), command: z.string().min(1).max(2048), + preCommand: z.string().min(0).max(2048).optional(), certPath: z.string().min(0).max(2048), keyPath: z.string().min(0).max(2048), }); @@ -90,6 +91,7 @@ const AccessSSHForm = ({ password: "", key: "", keyFile: "", + preCommand: "", command: "sudo service nginx restart", certPath: "/etc/nginx/ssl/certificate.crt", keyPath: "/etc/nginx/ssl/private.key", @@ -112,6 +114,7 @@ const AccessSSHForm = ({ certPath: config.certPath, keyPath: config.keyPath, command: config.command, + preCommand: config.preCommand, }, }); @@ -133,6 +136,7 @@ const AccessSSHForm = ({ password: data.password, key: data.key, command: data.command, + preCommand: data.preCommand, certPath: data.certPath, keyPath: data.keyPath, }, @@ -468,6 +472,21 @@ const AccessSSHForm = ({ )} /> + ( + + 前置 Command + +