158 lines
3.9 KiB
Go
158 lines
3.9 KiB
Go
package deployers
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"os"
|
|
"path/filepath"
|
|
|
|
"github.com/rs/zerolog/log"
|
|
|
|
"gitea.thegux.fr/hmdeploy/connection"
|
|
"gitea.thegux.fr/hmdeploy/docker"
|
|
"gitea.thegux.fr/hmdeploy/models"
|
|
"gitea.thegux.fr/hmdeploy/utils"
|
|
)
|
|
|
|
type SwarmDeployer struct {
|
|
conn connection.IConnection
|
|
dcli docker.IClient
|
|
|
|
project *models.Project
|
|
archivePath string
|
|
|
|
chDone chan struct{}
|
|
}
|
|
|
|
var _ IDeployer = (*SwarmDeployer)(nil)
|
|
|
|
func NewSwarmDeployer(dockerClient docker.IClient, netInfo *models.HMNetInfo, project *models.Project) (SwarmDeployer, error) {
|
|
var sd SwarmDeployer
|
|
|
|
conn, err := connection.NewSSHConn(netInfo.IP.String(), netInfo.SSH.User, netInfo.SSH.Port, netInfo.SSH.PrivKey)
|
|
if err != nil {
|
|
return sd, err
|
|
}
|
|
|
|
sd.conn = &conn
|
|
sd.dcli = dockerClient
|
|
sd.project = project
|
|
sd.chDone = make(chan struct{}, 1)
|
|
|
|
return sd, nil
|
|
}
|
|
|
|
func (sd *SwarmDeployer) close(ctx context.Context) error {
|
|
return sd.conn.Close()
|
|
}
|
|
|
|
func (sd *SwarmDeployer) clean(ctx context.Context) (err error) {
|
|
defer os.Remove(sd.archivePath)
|
|
_, err = sd.conn.Execute(fmt.Sprintf("rm -f %s %s *.tar.gz *.tar", models.ComposeFile, models.EnvFile))
|
|
return
|
|
}
|
|
|
|
func (sd *SwarmDeployer) setDone() {
|
|
sd.chDone <- struct{}{}
|
|
}
|
|
|
|
func (sd *SwarmDeployer) Done() <-chan struct{} {
|
|
return sd.chDone
|
|
}
|
|
|
|
func (sd *SwarmDeployer) Clear(ctx context.Context) error {
|
|
log.Debug().Msg("clearing swarm deployment...")
|
|
|
|
if err := sd.clean(ctx); err != nil {
|
|
log.Err(err).Msg("unable to clean swarm conf remotly")
|
|
}
|
|
|
|
if err := sd.close(ctx); err != nil {
|
|
log.Err(err).Msg("unable to close swarm conn")
|
|
}
|
|
|
|
log.Debug().Msg("clear swarm deployment done")
|
|
|
|
return nil
|
|
}
|
|
|
|
func (sd *SwarmDeployer) Build(ctx context.Context) error {
|
|
select {
|
|
case <-ctx.Done():
|
|
sd.setDone()
|
|
return fmt.Errorf("%w, swarm project build skipped", ErrContextDone)
|
|
default:
|
|
}
|
|
|
|
log.Info().Msg("building swarm archive for deployment...")
|
|
|
|
filesToArchive := []string{}
|
|
if imageName := sd.project.ImageName; imageName != "" {
|
|
tarFile, err := sd.dcli.Save(imageName, sd.project.Dir)
|
|
if err != nil {
|
|
sd.setDone()
|
|
return err
|
|
}
|
|
|
|
defer os.Remove(tarFile)
|
|
|
|
filesToArchive = append(filesToArchive, tarFile)
|
|
|
|
log.Info().Str("image", imageName).Msg("image added to archive")
|
|
}
|
|
|
|
if envFilePath := sd.project.Deps.EnvFile; envFilePath != "" {
|
|
filesToArchive = append(filesToArchive, filepath.Join(sd.project.Dir, filepath.Base(envFilePath)))
|
|
log.Info().Msg(".env file added to the archive for deployment")
|
|
}
|
|
|
|
composeFileBase := filepath.Base(sd.project.Deps.ComposeFile)
|
|
filesToArchive = append(filesToArchive, filepath.Join(sd.project.Dir, composeFileBase))
|
|
|
|
archivePath, err := utils.CreateArchive(sd.project.Dir, fmt.Sprintf("%s-%s", sd.project.Name, "swarm"), filesToArchive...)
|
|
if err != nil {
|
|
sd.setDone()
|
|
return err
|
|
}
|
|
|
|
sd.archivePath = archivePath
|
|
|
|
log.Info().Str("archive", archivePath).Msg("swarm archive built")
|
|
return nil
|
|
}
|
|
|
|
func (sd *SwarmDeployer) Deploy(ctx context.Context) error {
|
|
defer sd.setDone()
|
|
|
|
select {
|
|
case <-ctx.Done():
|
|
return fmt.Errorf("%w, nginx close ssh conn skipped", ErrContextDone)
|
|
default:
|
|
}
|
|
|
|
if sd.archivePath == "" {
|
|
return fmt.Errorf("unable to deploy, no archive to deploy")
|
|
}
|
|
|
|
log.Info().Str("archive", sd.archivePath).Msg("deploying archive to swarm...")
|
|
|
|
archiveDestPath := filepath.Base(sd.archivePath)
|
|
log.Info().Str("archive", sd.archivePath).Msg("archive built with success, tranfering to swarm for deployment...")
|
|
if err := sd.conn.CopyFile(sd.archivePath, archiveDestPath); err != nil {
|
|
return err
|
|
}
|
|
|
|
if _, err := sd.conn.Execute(fmt.Sprintf("tar xzvf %s", archiveDestPath)); err != nil {
|
|
return err
|
|
}
|
|
|
|
log.Info().Str("project", sd.project.Name).Msg("deploying swarm project...")
|
|
composeFileBase := filepath.Base(sd.project.Deps.ComposeFile)
|
|
if _, err := sd.conn.Execute(fmt.Sprintf("docker stack deploy -c %s %s", composeFileBase, sd.project.Name)); err != nil {
|
|
return err
|
|
}
|
|
|
|
log.Info().Msg("swarm deployment done with success")
|
|
return nil
|
|
}
|