rework err
This commit is contained in:
parent
04e14928f3
commit
771a0e50bd
@ -2,6 +2,7 @@ package connection
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"net"
|
||||
@ -20,6 +21,16 @@ type SSHConn struct {
|
||||
|
||||
var _ IConnection = (*SSHConn)(nil)
|
||||
|
||||
var (
|
||||
ErrSSHDial = errors.New("unable to dial ssh addr")
|
||||
ErrSSHConn = errors.New("unable to establish a new connection")
|
||||
ErrSShCopy = errors.New("unable to copy file")
|
||||
ErrSSHSession = errors.New("unable to open a new session")
|
||||
ErrSSHReadPrivateKey = errors.New("unable to read private key")
|
||||
ErrSSHParsePrivateKey = errors.New("unable to read private key")
|
||||
ErrSSHExecute = errors.New("unable")
|
||||
)
|
||||
|
||||
func NewSSHConn(addr, user string, port int, privkey string) (SSHConn, error) {
|
||||
var newconn SSHConn
|
||||
|
||||
@ -28,20 +39,17 @@ func NewSSHConn(addr, user string, port int, privkey string) (SSHConn, error) {
|
||||
|
||||
conn, err := net.Dial("tcp", sshAddr)
|
||||
if err != nil {
|
||||
log.Err(err).Str("addr", addr).Msg("unable to dial ssh addr")
|
||||
return newconn, err
|
||||
return newconn, fmt.Errorf("%w, addr=%s, err=%v", ErrSSHDial, addr, err)
|
||||
}
|
||||
|
||||
c, err := os.ReadFile(privkey)
|
||||
if err != nil {
|
||||
log.Err(err).Str("private key", privkey).Msg("unable to read ssh private key")
|
||||
return newconn, err
|
||||
return newconn, fmt.Errorf("%w, privkey=%s, err=%v", ErrSSHReadPrivateKey, privkey, err)
|
||||
}
|
||||
|
||||
sshPrivKey, err := ssh.ParsePrivateKey(c)
|
||||
if err != nil {
|
||||
log.Err(err).Str("private key", privkey).Msg("unable to parse ssh private key")
|
||||
return newconn, err
|
||||
return newconn, fmt.Errorf("%w, privkey=%s, err=%v", ErrSSHParsePrivateKey, privkey, err)
|
||||
}
|
||||
|
||||
sshConfig := ssh.ClientConfig{
|
||||
@ -54,14 +62,12 @@ func NewSSHConn(addr, user string, port int, privkey string) (SSHConn, error) {
|
||||
|
||||
sshConn, chNewChannel, chReq, err := ssh.NewClientConn(conn, sshAddr, &sshConfig)
|
||||
if err != nil {
|
||||
log.Err(err).Str("addr", sshAddr).Msg("unable to establish a new connection to the swarm")
|
||||
return newconn, err
|
||||
return newconn, fmt.Errorf("%w, addr=%s, err=%v", ErrSSHConn, sshAddr, err)
|
||||
}
|
||||
|
||||
sshClient := ssh.NewClient(sshConn, chNewChannel, chReq)
|
||||
newconn.client = sshClient
|
||||
|
||||
log.Info().Str("addr", addr).Int("port", port).Msg("ssh connection sucessfully initialized")
|
||||
return newconn, nil
|
||||
}
|
||||
|
||||
@ -72,21 +78,18 @@ func (c *SSHConn) Close() error {
|
||||
func (c *SSHConn) CopyFile(src, dest string) error {
|
||||
sshSession, err := c.client.NewSession()
|
||||
if err != nil {
|
||||
log.Err(err).Str("addr", c.addr).Msg("unable to open an ssh session")
|
||||
return err
|
||||
return fmt.Errorf("%w, addr=%s, err=%v", ErrSSHSession, c.addr, err)
|
||||
}
|
||||
defer sshSession.Close()
|
||||
|
||||
fileInfo, err := os.Stat(src)
|
||||
if err != nil {
|
||||
log.Err(err).Str("file", src).Msg("unable to stat scp source file")
|
||||
return err
|
||||
return fmt.Errorf("unable to stat scp source file src=%s, err=%v", src, err)
|
||||
}
|
||||
|
||||
file, err := os.Open(src)
|
||||
if err != nil {
|
||||
log.Err(err).Str("file", src).Msg("unable to open scp source file")
|
||||
return err
|
||||
return fmt.Errorf("unable to open scp source file src=%s, err=%v", src, err)
|
||||
}
|
||||
defer file.Close()
|
||||
|
||||
@ -97,7 +100,7 @@ func (c *SSHConn) CopyFile(src, dest string) error {
|
||||
fmt.Fprintf(w, "C0644 %d %s\n", fileInfo.Size(), filepath.Base(dest))
|
||||
|
||||
if _, err := io.Copy(w, file); err != nil {
|
||||
log.Err(err).Str("src", src).Str("dest", dest).Msg("unable to scp src to dest")
|
||||
log.Debug().Err(err).Str("src", src).Str("dest", dest).Msg("unable to scp src to dest")
|
||||
return
|
||||
}
|
||||
|
||||
@ -105,27 +108,23 @@ func (c *SSHConn) CopyFile(src, dest string) error {
|
||||
}()
|
||||
|
||||
if err := sshSession.Run(fmt.Sprintf("scp -t %s", dest)); err != nil {
|
||||
log.Err(err).Str("addr", c.addr).Str("dest", dest).Msg("unable to run scp command")
|
||||
return err
|
||||
return fmt.Errorf("%w, addr=%s, src=%s, dest=%s, err=%v", ErrSShCopy, c.addr, src, dest, err)
|
||||
}
|
||||
|
||||
log.Info().Str("src", src).Str("dest", dest).Msg("file successfully uploaded")
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *SSHConn) Execute(cmd string) (string, error) {
|
||||
sshSession, err := c.client.NewSession()
|
||||
if err != nil {
|
||||
log.Err(err).Str("addr", c.addr).Msg("unable to open an ssh session")
|
||||
return "", err
|
||||
return "", fmt.Errorf("%w, addr=%s, err=%v", ErrSSHSession, c.addr, err)
|
||||
}
|
||||
defer sshSession.Close()
|
||||
|
||||
var buf bytes.Buffer
|
||||
sshSession.Stdout = &buf
|
||||
if err := sshSession.Run(cmd); err != nil {
|
||||
log.Err(err).Str("addr", c.addr).Str("command", cmd).Msg("unable to execute an ssh command")
|
||||
return "", err
|
||||
return "", fmt.Errorf("%w, addr=%s, cmd=%s, err=%v", ErrSSHExecute, c.addr, cmd, err)
|
||||
}
|
||||
|
||||
return "", nil
|
||||
|
||||
@ -6,11 +6,10 @@ import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/rs/zerolog/log"
|
||||
|
||||
"gitea.thegux.fr/hmdeploy/connection"
|
||||
"gitea.thegux.fr/hmdeploy/docker"
|
||||
"gitea.thegux.fr/hmdeploy/models"
|
||||
"github.com/rs/zerolog/log"
|
||||
)
|
||||
|
||||
type SwarmDeployer struct {
|
||||
@ -57,12 +56,16 @@ func (sd *SwarmDeployer) clean() (err error) {
|
||||
func (sd *SwarmDeployer) Deploy() error {
|
||||
defer sd.clean()
|
||||
|
||||
if sd.project.ImageName != "" {
|
||||
tarFile, err := sd.dcli.Save(sd.project.ImageName, sd.project.Dir)
|
||||
if imageName := sd.project.ImageName; imageName != "" {
|
||||
log.Info().Str("image", imageName).Msg("saving image for transfert...")
|
||||
|
||||
tarFile, err := sd.dcli.Save(imageName, sd.project.Dir)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
log.Info().Str("image", imageName).Str("dir", sd.project.Dir).Msg("image saved successfully")
|
||||
|
||||
defer os.Remove(tarFile)
|
||||
|
||||
tarFileBase := filepath.Base(tarFile)
|
||||
@ -91,6 +94,5 @@ func (sd *SwarmDeployer) Deploy() error {
|
||||
return err
|
||||
}
|
||||
|
||||
log.Info().Msg("project deployed successfully on swarm")
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -1,18 +1,19 @@
|
||||
package docker
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/rs/zerolog/log"
|
||||
)
|
||||
|
||||
type IClient interface {
|
||||
Save(imageName, dest string) (string, error)
|
||||
}
|
||||
|
||||
var ErrDockerClientSave = errors.New("unable to save image into tar")
|
||||
|
||||
type Client struct{}
|
||||
|
||||
var _ IClient = (*Client)(nil)
|
||||
@ -24,12 +25,11 @@ func NewClient() Client {
|
||||
func (c *Client) Save(imageName, dest string) (string, error) {
|
||||
destInfo, err := os.Stat(dest)
|
||||
if err != nil {
|
||||
log.Err(err).Str("dest", dest).Msg("unable to stat dest directory")
|
||||
return "", err
|
||||
return "", fmt.Errorf("unable to stat file, dir=%s, err=%v", dest, err)
|
||||
}
|
||||
|
||||
if !destInfo.IsDir() {
|
||||
log.Err(err).Str("dest", dest).Msg("dest directory must be a directory")
|
||||
return "", fmt.Errorf("dest file must be a directory, dir=%s, err=%v", dest, err)
|
||||
}
|
||||
|
||||
tarFile := fmt.Sprintf("%s.tar", imageName)
|
||||
@ -37,10 +37,8 @@ func (c *Client) Save(imageName, dest string) (string, error) {
|
||||
cmd := exec.Command("docker", "save", "-o", tarFile, imageName)
|
||||
cmd.Dir = dest
|
||||
if _, err := cmd.Output(); err != nil {
|
||||
log.Err(err).Str("image", imageName).Str("dest", dest).Msg("unable to save image into tar")
|
||||
return dest, err
|
||||
return "", fmt.Errorf("%w, dir=%s, image=%s, err=%v", ErrDockerClientSave, dest, imageName, err)
|
||||
}
|
||||
|
||||
log.Info().Str("image", imageName).Str("dest", dest).Msg("image successfully saved")
|
||||
return filepath.Join(dest, tarFile), nil
|
||||
}
|
||||
|
||||
9
main.go
9
main.go
@ -59,17 +59,20 @@ func main() {
|
||||
|
||||
project, err := models.ProjectFromDir(*projectDir)
|
||||
if err != nil {
|
||||
os.Exit(1)
|
||||
log.Fatal().Str("dir", *projectDir).Err(err).Msg("unable to init project from directory")
|
||||
}
|
||||
log.Info().Str("dir", project.Dir).Str("name", project.Name).Msg("project initialized with success")
|
||||
|
||||
dcli := docker.NewClient()
|
||||
|
||||
sd, err := deployers.NewSwarmDeployer(ctx, &dcli, swarmNet, &project)
|
||||
if err != nil {
|
||||
os.Exit(1)
|
||||
log.Fatal().Err(err).Msg("unable to init swarm deployer")
|
||||
}
|
||||
|
||||
if err := sd.Deploy(); err != nil {
|
||||
os.Exit(1)
|
||||
log.Fatal().Err(err).Msg("unable to deploy project")
|
||||
}
|
||||
|
||||
log.Info().Str("name", project.Name).Msg("project deployed successfully")
|
||||
}
|
||||
|
||||
@ -2,8 +2,6 @@ package models
|
||||
|
||||
import (
|
||||
"net"
|
||||
|
||||
"github.com/rs/zerolog/log"
|
||||
)
|
||||
|
||||
type HMNetInfo struct {
|
||||
@ -28,7 +26,6 @@ type HMMap struct {
|
||||
func (hm *HMMap) GetSwarmNetInfo() *HMNetInfo {
|
||||
data, ok := hm.VM["swarm"]
|
||||
if !ok {
|
||||
log.Error().Msg("unable to get swarm net info, check your configuration")
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
@ -21,11 +21,7 @@ const (
|
||||
ConfFile = "hmdeploy.json"
|
||||
)
|
||||
|
||||
var (
|
||||
ErrInvalidEnvFile = errors.New("unable to stat .env file")
|
||||
ErrInvalidComposeFile = errors.New("unable to stat compose file")
|
||||
ErrInvalidNginxFile = errors.New("unable to stat nginx file")
|
||||
)
|
||||
var ErrProjectConfFile = errors.New("project error")
|
||||
|
||||
func getFileInfo(baseDir, filePath string) (fs.FileInfo, error) {
|
||||
var fInf fs.FileInfo
|
||||
@ -33,14 +29,14 @@ func getFileInfo(baseDir, filePath string) (fs.FileInfo, error) {
|
||||
filePath = filepath.Clean(filePath)
|
||||
filePath = filepath.Join(baseDir, filePath)
|
||||
|
||||
composePath, err := filepath.Abs(filePath)
|
||||
fileAbsPath, err := filepath.Abs(filePath)
|
||||
if err != nil {
|
||||
return fInf, fmt.Errorf("%w, %v", ErrInvalidComposeFile, err)
|
||||
return fInf, fmt.Errorf("%w, file=%s, err=%v", ErrProjectConfFile, fileAbsPath, err)
|
||||
}
|
||||
|
||||
fInf, err = os.Stat(composePath)
|
||||
fInf, err = os.Stat(fileAbsPath)
|
||||
if err != nil {
|
||||
return fInf, fmt.Errorf("%w, %v", ErrInvalidComposeFile, err)
|
||||
return fInf, fmt.Errorf("%w, unable to stat file=%s, err=%v", ErrProjectConfFile, fileAbsPath, err)
|
||||
}
|
||||
|
||||
return fInf, nil
|
||||
@ -65,23 +61,23 @@ type Project struct {
|
||||
func (p *Project) validate() error {
|
||||
cfs, err := getFileInfo(p.Dir, p.Deps.ComposeFile)
|
||||
if err != nil {
|
||||
return fmt.Errorf("%w, %v", ErrInvalidComposeFile, err)
|
||||
return err
|
||||
}
|
||||
p.Deps.ComposeFileInfo = cfs
|
||||
|
||||
if p.Deps.EnvFile != "" {
|
||||
efs, err := getFileInfo(p.Dir, p.Deps.EnvFile)
|
||||
if err != nil {
|
||||
return fmt.Errorf("%w, %v", ErrInvalidEnvFile, err)
|
||||
return err
|
||||
}
|
||||
p.Deps.EnvFileInfo = efs
|
||||
} else {
|
||||
log.Warn().Msg("no .env file provided, hoping one is set elsewhere...")
|
||||
log.Warn().Msg("no .env file provided, hoping one it's set elsewhere...")
|
||||
}
|
||||
|
||||
nfs, err := getFileInfo(p.Dir, p.Deps.EnvFile)
|
||||
nfs, err := getFileInfo(p.Dir, p.Deps.NginxFile)
|
||||
if err != nil {
|
||||
return fmt.Errorf("%w, %v", ErrInvalidNginxFile, err)
|
||||
return err
|
||||
}
|
||||
p.Deps.NginxFileInfo = nfs
|
||||
|
||||
@ -96,18 +92,15 @@ func ProjectFromDir(dir string) (Project, error) {
|
||||
|
||||
content, err := os.ReadFile(filepath.Join(dir, ConfFile))
|
||||
if err != nil {
|
||||
log.Err(err).Str("dir", dir).Str("conf", ConfFile).Msg("unable to read conf file")
|
||||
return p, err
|
||||
return p, fmt.Errorf("%w, unable to read conf file=%s, err=%v", ErrProjectConfFile, ConfFile, err)
|
||||
}
|
||||
|
||||
if err := json.Unmarshal(content, &p); err != nil {
|
||||
log.Err(err).Str("dir", dir).Str("conf", ConfFile).Msg("unable to parse conf file")
|
||||
return p, err
|
||||
return p, fmt.Errorf("%w, unable to parse conf file=%s, err=%v", ErrProjectConfFile, ConfFile, err)
|
||||
}
|
||||
|
||||
if err := p.validate(); err != nil {
|
||||
log.Err(err).Str("dir", dir).Msg("unable to validate project")
|
||||
return p, err
|
||||
return p, fmt.Errorf("%w, unable to validate project, name=%s, dir=%s, err=%v", ErrProjectConfFile, p.Name, p.Dir, err)
|
||||
}
|
||||
|
||||
return p, nil
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user