restructure json conf + deploy nginx assets
This commit is contained in:
parent
0dae6ae400
commit
07f096a0a5
3
.gitignore
vendored
3
.gitignore
vendored
@ -1,3 +1,4 @@
|
||||
map.json
|
||||
|
||||
hmdeploy
|
||||
hmdeploy
|
||||
hmdeploy-linux*
|
||||
@ -10,7 +10,10 @@ import (
|
||||
"github.com/rs/zerolog/log"
|
||||
)
|
||||
|
||||
var ErrContextDone = errors.New("unable to execute, context done")
|
||||
var (
|
||||
ErrContextDone = errors.New("unable to execute, context done")
|
||||
ErrEmptyArchive = errors.New("no file to add to the archive")
|
||||
)
|
||||
|
||||
type IDeployer interface {
|
||||
Type() DeployerType
|
||||
@ -48,7 +51,8 @@ type deployer struct { //nolint:govet // ll
|
||||
type_ DeployerType
|
||||
errFlag error
|
||||
|
||||
project *models.Project
|
||||
project *models.Project
|
||||
archivePath string
|
||||
}
|
||||
|
||||
func newDeployer(ctx context.Context, type_ DeployerType, project *models.Project) *deployer {
|
||||
|
||||
@ -3,9 +3,12 @@ package deployers
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"gitea.thegux.fr/hmdeploy/connection"
|
||||
"gitea.thegux.fr/hmdeploy/models"
|
||||
"gitea.thegux.fr/hmdeploy/utils"
|
||||
"github.com/rs/zerolog/log"
|
||||
)
|
||||
|
||||
@ -40,12 +43,28 @@ func NewNginxDeployer(
|
||||
return nd, nil
|
||||
}
|
||||
|
||||
func (nd NginxDeployer) getConfPath() string {
|
||||
return nd.project.GetNginxConfPath()
|
||||
}
|
||||
|
||||
func (nd NginxDeployer) getAssetsPath() string {
|
||||
return nd.project.GetNginxAssetsPath()
|
||||
}
|
||||
|
||||
func (nd *NginxDeployer) close() error {
|
||||
return nd.conn.Close()
|
||||
}
|
||||
|
||||
func (nd *NginxDeployer) clean() (err error) {
|
||||
_, err = nd.conn.Execute("rm -f " + nd.project.Name + ".conf")
|
||||
if err = os.Remove(nd.archivePath); err != nil {
|
||||
log.Err(err).Str("archive", nd.archivePath).Msg("unable to clean local nginx archive file")
|
||||
}
|
||||
|
||||
cmd := "rm -rf nginx.conf build/ *.tar.gz"
|
||||
if ap := nd.getAssetsPath(); ap != "" {
|
||||
cmd += " " + filepath.Base(nd.getAssetsPath())
|
||||
}
|
||||
_, err = nd.conn.Execute(cmd)
|
||||
return
|
||||
}
|
||||
|
||||
@ -75,20 +94,36 @@ func (nd *NginxDeployer) Build() error {
|
||||
default:
|
||||
}
|
||||
|
||||
nginxConf := nd.project.Name + ".conf"
|
||||
log.Info().Msg("building nginx archive for deployment...")
|
||||
|
||||
log.Info().Str("nginx", nginxConf).Msg("transferring nginx conf...")
|
||||
filesToArchive := []string{}
|
||||
if ap := nd.getAssetsPath(); ap != "" {
|
||||
filesToArchive = append(filesToArchive, ap)
|
||||
}
|
||||
if cp := nd.getConfPath(); cp != "" {
|
||||
filesToArchive = append(filesToArchive, cp)
|
||||
}
|
||||
|
||||
if err := nd.conn.CopyFile(nd.project.Deps.NginxFile, nginxConf); err != nil {
|
||||
nd.setDone(err)
|
||||
if len(filesToArchive) == 0 {
|
||||
return ErrEmptyArchive
|
||||
}
|
||||
|
||||
archivePath, err := utils.CreateArchive(
|
||||
nd.project.Dir,
|
||||
fmt.Sprintf("%s-%s", nd.project.Name, "nginx"),
|
||||
filesToArchive...,
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
log.Info().Str("nginx", nginxConf).Msg("nginx conf transferred with success")
|
||||
nd.archivePath = archivePath
|
||||
|
||||
log.Info().Str("archive", archivePath).Msg("nginx archive built")
|
||||
return nil
|
||||
}
|
||||
|
||||
func (nd *NginxDeployer) Deploy() (err error) {
|
||||
func (nd *NginxDeployer) Deploy() error {
|
||||
nd.processing.Store(true)
|
||||
defer nd.processing.Store(false)
|
||||
|
||||
@ -99,25 +134,55 @@ func (nd *NginxDeployer) Deploy() (err error) {
|
||||
default:
|
||||
}
|
||||
|
||||
nginxConf := nd.project.Name + ".conf"
|
||||
|
||||
log.Info().Str("nginx", nginxConf).Msg("deploying nginx conf...")
|
||||
|
||||
_, err = nd.conn.Execute(
|
||||
fmt.Sprintf(
|
||||
"cp %s /etc/nginx/sites-available && ln -sf /etc/nginx/sites-available/%s /etc/nginx/sites-enabled/%s",
|
||||
nginxConf,
|
||||
nginxConf,
|
||||
nginxConf,
|
||||
),
|
||||
)
|
||||
nd.setDone(err)
|
||||
|
||||
if err == nil {
|
||||
log.Info().Str("nginx", nginxConf).Msg("nginx conf successfully deployed")
|
||||
archiveDestPath := filepath.Base(nd.archivePath)
|
||||
if err := nd.conn.CopyFile(nd.archivePath, archiveDestPath); err != nil {
|
||||
nd.setDone(err)
|
||||
return err
|
||||
}
|
||||
|
||||
return err
|
||||
if _, err := nd.conn.Execute(fmt.Sprintf("tar xzvf %s", archiveDestPath)); err != nil {
|
||||
nd.setDone(err)
|
||||
return err
|
||||
}
|
||||
|
||||
if ap := nd.getAssetsPath(); ap != "" {
|
||||
log.Info().Msg("deploying nginx assets...")
|
||||
|
||||
if _, err := nd.conn.Execute(
|
||||
fmt.Sprintf(
|
||||
"rm -rf /var/www/static/%s/* && mkdir -p /var/www/static/%s && mv %s/* /var/www/static/%s",
|
||||
nd.project.Name,
|
||||
nd.project.Name,
|
||||
filepath.Base(nd.getAssetsPath()),
|
||||
nd.project.Name,
|
||||
),
|
||||
); err != nil {
|
||||
nd.setDone(err)
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if cp := nd.getConfPath(); cp != "" {
|
||||
nginxConf := nd.project.Name + ".conf"
|
||||
log.Info().Str("nginx", nginxConf).Msg("deploying nginx conf...")
|
||||
|
||||
if _, err := nd.conn.Execute(
|
||||
fmt.Sprintf(
|
||||
"mv %s /etc/nginx/sites-available/%s && ln -sf /etc/nginx/sites-available/%s /etc/nginx/sites-enabled/%s",
|
||||
filepath.Base(cp),
|
||||
nginxConf,
|
||||
nginxConf,
|
||||
nginxConf,
|
||||
),
|
||||
); err != nil {
|
||||
nd.setDone(err)
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
log.Info().Msg("nginx project successfully deployed")
|
||||
nd.setDone(nil)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (nd *NginxDeployer) Destroy() (err error) {
|
||||
|
||||
@ -19,10 +19,9 @@ var ErrSwarmDeployerNoArchive = errors.New("no archive found to be deployed")
|
||||
// SwarmDeployer handles the deployment of a Docker service on the swarm instance.
|
||||
type SwarmDeployer struct {
|
||||
*deployer
|
||||
conn connection.IConnection
|
||||
dloc docker.IClient
|
||||
drem *docker.RemoteClient
|
||||
archivePath string
|
||||
conn connection.IConnection
|
||||
dloc docker.IClient
|
||||
drem *docker.RemoteClient
|
||||
}
|
||||
|
||||
var _ IDeployer = (*SwarmDeployer)(nil)
|
||||
@ -54,6 +53,14 @@ func NewSwarmDeployer(
|
||||
return sd, nil
|
||||
}
|
||||
|
||||
func (sd SwarmDeployer) getComposePath() string {
|
||||
return sd.project.GetComposePath()
|
||||
}
|
||||
|
||||
func (sd SwarmDeployer) getEnvPath() string {
|
||||
return sd.project.GetEnvPath()
|
||||
}
|
||||
|
||||
func (sd *SwarmDeployer) close() error {
|
||||
return sd.conn.Close()
|
||||
}
|
||||
@ -119,7 +126,7 @@ func (sd *SwarmDeployer) Build() error {
|
||||
log.Info().Str("image", tarFile).Msg("image transferred with success")
|
||||
}
|
||||
|
||||
if envFilePath := sd.project.Deps.EnvFile; envFilePath != "" {
|
||||
if envFilePath := sd.getEnvPath(); envFilePath != "" {
|
||||
filesToArchive = append(
|
||||
filesToArchive,
|
||||
envFilePath,
|
||||
@ -129,7 +136,7 @@ func (sd *SwarmDeployer) Build() error {
|
||||
|
||||
filesToArchive = append(
|
||||
filesToArchive,
|
||||
sd.project.Deps.ComposeFile,
|
||||
sd.getComposePath(),
|
||||
)
|
||||
|
||||
archivePath, err := utils.CreateArchive(
|
||||
@ -171,9 +178,6 @@ func (sd *SwarmDeployer) Deploy() error {
|
||||
}
|
||||
|
||||
archiveDestPath := filepath.Base(sd.archivePath)
|
||||
log.Info().
|
||||
Str("archive", sd.archivePath).
|
||||
Msg("archive built with success, tranferring to swarm for deployment...")
|
||||
if err := sd.conn.CopyFile(sd.archivePath, archiveDestPath); err != nil {
|
||||
sd.setDone(err)
|
||||
return err
|
||||
@ -185,7 +189,7 @@ func (sd *SwarmDeployer) Deploy() error {
|
||||
}
|
||||
|
||||
log.Info().Str("project", sd.project.Name).Msg("deploying swarm project...")
|
||||
composeFileBase := filepath.Base(sd.project.Deps.ComposeFile)
|
||||
composeFileBase := filepath.Base(sd.getComposePath())
|
||||
if err := sd.drem.DeployStack(sd.ctx, sd.project.Name, composeFileBase, docker.WithCheckState()); err != nil {
|
||||
sd.setDone(err)
|
||||
return err
|
||||
|
||||
@ -18,7 +18,7 @@ import (
|
||||
|
||||
const (
|
||||
stateTickDuration = 4 * time.Second
|
||||
defaultStateTimeout = 30 * time.Second
|
||||
defaultStateTimeout = 10 * time.Minute
|
||||
)
|
||||
|
||||
var (
|
||||
|
||||
13
hmdeploy.example.json
Normal file
13
hmdeploy.example.json
Normal file
@ -0,0 +1,13 @@
|
||||
{
|
||||
"name": "my-api",
|
||||
"dependencies": {
|
||||
"swarm": {
|
||||
"env": ".env",
|
||||
"compose": "docker-compose.deploy.yml"
|
||||
},
|
||||
"nginx": {
|
||||
"conf": "nginx.conf",
|
||||
"assets": "assets/"
|
||||
}
|
||||
}
|
||||
}
|
||||
66
main.go
66
main.go
@ -136,10 +136,13 @@ func (d *Deployers) generateTasksTree() scheduler.Tasks {
|
||||
func (d *Deployers) waitForCompletion(s *scheduler.Scheduler) error {
|
||||
var wg sync.WaitGroup
|
||||
|
||||
deps := []deployers.IDeployer{d.sd}
|
||||
deps := []deployers.IDeployer{}
|
||||
if d.nd != nil {
|
||||
deps = append(deps, d.nd)
|
||||
}
|
||||
if d.sd != nil {
|
||||
deps = append(deps, d.sd)
|
||||
}
|
||||
|
||||
for idx := range deps {
|
||||
if d := deps[idx]; d != nil {
|
||||
@ -238,14 +241,40 @@ func loadHMMap() (models.HMMap, error) {
|
||||
return hmmap, nil
|
||||
}
|
||||
|
||||
func initSwarmDeployer(
|
||||
ctx context.Context,
|
||||
project *models.Project,
|
||||
swarmNet *models.HMNetInfo,
|
||||
fnCancel context.CancelFunc,
|
||||
) (deployers.SwarmDeployer, error) {
|
||||
dloc := docker.NewLocalClient()
|
||||
drem, err := docker.NewRemoteClient(swarmNet)
|
||||
if err != nil {
|
||||
return deployers.SwarmDeployer{}, err
|
||||
}
|
||||
|
||||
sd, err := deployers.NewSwarmDeployer(ctx, project, swarmNet, &dloc, &drem)
|
||||
if err != nil {
|
||||
return deployers.SwarmDeployer{}, fmt.Errorf(
|
||||
"%w, unable to init swarm deployer, err=%v",
|
||||
ErrDeployerInit,
|
||||
err,
|
||||
)
|
||||
}
|
||||
|
||||
if fnCancel != nil {
|
||||
sd.SetCancellationFunc(fnCancel)
|
||||
}
|
||||
|
||||
return sd, nil
|
||||
}
|
||||
|
||||
// initDeployers instanciates from `Project` and `HMMap` needed deployers and returns them.
|
||||
//
|
||||
// You can provide as an optional arg:
|
||||
// - WithGlobalCancellation(fnCancel context.CancelFunc): close the global context, notifying all deployers to stop
|
||||
// - WithNoSwarm(): disable Swarm deployment
|
||||
// - WithNoNginx(): disable Nginx deployment
|
||||
//
|
||||
//nolint:funlen // not that so much...
|
||||
func initDeployers(
|
||||
ctx context.Context,
|
||||
hmmap *models.HMMap,
|
||||
@ -261,34 +290,21 @@ func initDeployers(
|
||||
destroy: opt.destroy,
|
||||
}
|
||||
|
||||
swarmNet := hmmap.GetSwarmNetInfo()
|
||||
if swarmNet == nil {
|
||||
return deps, fmt.Errorf("%w, swarm net info does not exist", ErrNetInfoNotFound)
|
||||
}
|
||||
if !opt.noSwarm && project.GetComposePath() != "" {
|
||||
swarmNet := hmmap.GetSwarmNetInfo()
|
||||
if swarmNet == nil {
|
||||
return deps, fmt.Errorf("%w, swarm net info does not exist", ErrNetInfoNotFound)
|
||||
}
|
||||
|
||||
dloc := docker.NewLocalClient()
|
||||
drem, err := docker.NewRemoteClient(swarmNet)
|
||||
if err != nil {
|
||||
return deps, err
|
||||
}
|
||||
|
||||
if !opt.noSwarm {
|
||||
sd, err := deployers.NewSwarmDeployer(ctx, project, swarmNet, &dloc, &drem)
|
||||
sd, err := initSwarmDeployer(ctx, project, swarmNet, opt.fnCancel)
|
||||
if err != nil {
|
||||
return deps, fmt.Errorf(
|
||||
"%w, unable to init swarm deployer, err=%v",
|
||||
ErrDeployerInit,
|
||||
err,
|
||||
)
|
||||
return deps, err
|
||||
}
|
||||
deps.sd = &sd
|
||||
|
||||
if opt.fnCancel != nil {
|
||||
sd.SetCancellationFunc(opt.fnCancel)
|
||||
}
|
||||
deps.sd = &sd
|
||||
}
|
||||
|
||||
if !opt.noNginx && project.Deps.NginxFile != "" {
|
||||
if !opt.noNginx && project.GetNginxConfPath() != "" {
|
||||
nginxNet := hmmap.GetNginxNetInfo()
|
||||
if nginxNet == nil {
|
||||
return deps, fmt.Errorf("%w, nginx net info does not exist", ErrNetInfoNotFound)
|
||||
|
||||
@ -22,10 +22,26 @@ const (
|
||||
|
||||
var ErrProjectConfFile = errors.New("project error")
|
||||
|
||||
func getFilepath(baseDir, filePath string) (string, error) {
|
||||
filePath = filepath.Join(baseDir, filePath)
|
||||
type filepathOption struct {
|
||||
isDir bool
|
||||
}
|
||||
|
||||
type fnFilepathOption func(*filepathOption)
|
||||
|
||||
func IsDir() fnFilepathOption {
|
||||
return func(fo *filepathOption) {
|
||||
fo.isDir = true
|
||||
}
|
||||
}
|
||||
|
||||
func getFilepath(baseDir, filePath string, options ...fnFilepathOption) (string, error) {
|
||||
var opts filepathOption
|
||||
for _, opt := range options {
|
||||
opt(&opts)
|
||||
}
|
||||
|
||||
if !filepath.IsAbs(filePath) {
|
||||
filePath = filepath.Join(baseDir, filePath)
|
||||
filePath, err := filepath.Abs(filePath) //nolint: govet
|
||||
if err != nil {
|
||||
return filePath, fmt.Errorf(
|
||||
@ -47,7 +63,7 @@ func getFilepath(baseDir, filePath string) (string, error) {
|
||||
)
|
||||
}
|
||||
|
||||
if fileInfo.IsDir() {
|
||||
if fileInfo.IsDir() && !opts.isDir {
|
||||
return filePath, fmt.Errorf(
|
||||
"%w, file=%s, err=%s",
|
||||
ErrProjectConfFile,
|
||||
@ -56,6 +72,15 @@ func getFilepath(baseDir, filePath string) (string, error) {
|
||||
)
|
||||
}
|
||||
|
||||
if !fileInfo.IsDir() && opts.isDir {
|
||||
return filePath, fmt.Errorf(
|
||||
"%w, file=%s, err=%s",
|
||||
ErrProjectConfFile,
|
||||
filePath,
|
||||
"must be a dir",
|
||||
)
|
||||
}
|
||||
|
||||
return filePath, nil
|
||||
}
|
||||
|
||||
@ -64,43 +89,73 @@ type Project struct {
|
||||
Name string `json:"name"`
|
||||
Dir string
|
||||
Deps struct {
|
||||
EnvFile string `json:"env"`
|
||||
ComposeFile string `json:"compose"`
|
||||
NginxFile string `json:"nginx"`
|
||||
Swarm struct {
|
||||
EnvFile string `json:"env"`
|
||||
ComposeFile string `json:"compose"`
|
||||
} `json:"swarm"`
|
||||
Nginx struct {
|
||||
Conf string `json:"conf"`
|
||||
Assets string `json:"assets"`
|
||||
}
|
||||
} `json:"dependencies"`
|
||||
ImageNames []string `json:"images"`
|
||||
}
|
||||
|
||||
func (p *Project) validate() error {
|
||||
cpath, err := getFilepath(p.Dir, p.Deps.ComposeFile)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
p.Deps.ComposeFile = cpath
|
||||
|
||||
if p.Deps.EnvFile != "" {
|
||||
epath, err := getFilepath(p.Dir, p.Deps.EnvFile)
|
||||
if compf := p.Deps.Swarm.ComposeFile; compf != "" {
|
||||
cpath, err := getFilepath(p.Dir, compf)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
p.Deps.EnvFile = epath
|
||||
|
||||
p.Deps.Swarm.ComposeFile = cpath
|
||||
} else {
|
||||
log.Warn().Msg("no .env file provided, hoping one it's set elsewhere...")
|
||||
log.Warn().Msg("no docker-compose file provided, Swarm deployment discards")
|
||||
}
|
||||
|
||||
if p.Deps.NginxFile != "" {
|
||||
npath, err := getFilepath(p.Dir, p.Deps.NginxFile)
|
||||
if env := p.Deps.Swarm.EnvFile; env != "" {
|
||||
epath, err := getFilepath(p.Dir, env)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
p.Deps.NginxFile = npath
|
||||
} else {
|
||||
log.Warn().Msg("no Nginx conf file provided, Nginx deployment discarded")
|
||||
p.Deps.Swarm.EnvFile = epath
|
||||
}
|
||||
|
||||
if conf := p.Deps.Nginx.Conf; conf != "" {
|
||||
npath, err := getFilepath(p.Dir, conf)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
p.Deps.Nginx.Conf = npath
|
||||
}
|
||||
|
||||
if assets := p.Deps.Nginx.Assets; assets != "" {
|
||||
apath, err := getFilepath(p.Dir, assets, IsDir())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
p.Deps.Nginx.Assets = apath
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p Project) GetComposePath() string {
|
||||
return p.Deps.Swarm.ComposeFile
|
||||
}
|
||||
|
||||
func (p Project) GetEnvPath() string {
|
||||
return p.Deps.Swarm.EnvFile
|
||||
}
|
||||
|
||||
func (p Project) GetNginxConfPath() string {
|
||||
return p.Deps.Nginx.Conf
|
||||
}
|
||||
|
||||
func (p Project) GetNginxAssetsPath() string {
|
||||
return p.Deps.Nginx.Assets
|
||||
}
|
||||
|
||||
// ProjectFromDir instantiates a new project from a directory path.
|
||||
//
|
||||
// The directory path must refers to the path including the `.homeserver` dir not
|
||||
|
||||
@ -17,25 +17,75 @@ import (
|
||||
|
||||
const confirmChar = "Y"
|
||||
|
||||
func addToArchive(tw *tar.Writer, filename string) error {
|
||||
file, err := os.Open(filename)
|
||||
// addToArchive adds a file or directory (recursively) to the tar writer.
|
||||
// The baseName is the desired root name in the archive.
|
||||
//
|
||||
//nolint:funlen // it's ok
|
||||
func addToArchive(tw *tar.Writer, filename, baseName, basePath string) error {
|
||||
// resolve the absolute path to eliminate relative components like ../
|
||||
absPath, err := filepath.Abs(filename)
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to resolve absolute path for %s: %v", filename, err)
|
||||
}
|
||||
|
||||
file, err := os.Open(absPath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer file.Close() //nolint: errcheck // defered
|
||||
defer file.Close() //nolint: errcheck // deferred
|
||||
|
||||
info, err := file.Stat()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
header, err := tar.FileInfoHeader(info, info.Name())
|
||||
// compute the relative path within the archive
|
||||
// start with baseName and append the relative path from basePath
|
||||
relPath, err := filepath.Rel(basePath, absPath)
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to compute relative path for %s: %v", absPath, err)
|
||||
}
|
||||
|
||||
// combine baseName with the relative path
|
||||
if relPath == "." {
|
||||
relPath = baseName
|
||||
} else {
|
||||
relPath = filepath.Join(baseName, relPath)
|
||||
}
|
||||
|
||||
relPath = filepath.ToSlash(relPath)
|
||||
|
||||
if info.IsDir() {
|
||||
header, err := tar.FileInfoHeader(info, "") //nolint:govet // shadow ok
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
header.Name = relPath
|
||||
if err := tw.WriteHeader(header); err != nil { //nolint:govet // shadow ok
|
||||
return err
|
||||
}
|
||||
|
||||
entries, err := os.ReadDir(absPath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, entry := range entries {
|
||||
entryPath := filepath.Join(absPath, entry.Name())
|
||||
if err := addToArchive(tw, entryPath, baseName, basePath); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
header, err := tar.FileInfoHeader(info, "")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
header.Name = filepath.Base(file.Name())
|
||||
|
||||
if err = tw.WriteHeader(header); err != nil {
|
||||
header.Name = relPath
|
||||
if err := tw.WriteHeader(header); err != nil { //nolint:govet // shadow ok
|
||||
return err
|
||||
}
|
||||
|
||||
@ -43,7 +93,8 @@ func addToArchive(tw *tar.Writer, filename string) error {
|
||||
return err
|
||||
}
|
||||
|
||||
// CreateArchive creates a gzip tar archive in the `destDir` path including `files`.
|
||||
// CreateArchive creates a gzip tar archive in the `destDir` path including `files` and returns
|
||||
// the generated archive path.
|
||||
func CreateArchive(destDir, name string, files ...string) (string, error) {
|
||||
now := time.Now().UTC()
|
||||
archivePath := filepath.Join(
|
||||
@ -55,16 +106,22 @@ func CreateArchive(destDir, name string, files ...string) (string, error) {
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("unable to create archive=%s, err=%v", archivePath, err)
|
||||
}
|
||||
defer file.Close() //nolint: errcheck // defered
|
||||
defer file.Close() //nolint: errcheck // deferred
|
||||
|
||||
gw := gzip.NewWriter(file)
|
||||
defer gw.Close() //nolint: errcheck // defered
|
||||
defer gw.Close() //nolint: errcheck // deferred
|
||||
|
||||
tw := tar.NewWriter(gw)
|
||||
defer tw.Close() //nolint: errcheck // defered
|
||||
defer tw.Close() //nolint: errcheck // deferred
|
||||
|
||||
for _, f := range files {
|
||||
if err := addToArchive(tw, f); err != nil {
|
||||
absPath, err := filepath.Abs(f)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("unable to resolve absolute path for %s: %v", f, err)
|
||||
}
|
||||
|
||||
baseName := filepath.Base(f)
|
||||
if err := addToArchive(tw, f, baseName, absPath); err != nil {
|
||||
return "", fmt.Errorf(
|
||||
"unable to add file=%s to archive=%s, err=%v",
|
||||
f,
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user