Less random temp dir locations; cleanup when done

This commit is contained in:
Dane Everitt 2020-08-23 20:45:07 -07:00
parent 3489088703
commit 7aaa51a14f
No known key found for this signature in database
GPG Key ID: EEA66103B3D71F53

View File

@ -16,9 +16,7 @@ import (
"golang.org/x/sync/semaphore" "golang.org/x/sync/semaphore"
"html/template" "html/template"
"io" "io"
"io/ioutil"
"os" "os"
"path"
"path/filepath" "path/filepath"
"strconv" "strconv"
"time" "time"
@ -212,12 +210,11 @@ func (ip *InstallationProcess) Run() error {
ip.Server.installer.cancel = nil ip.Server.installer.cancel = nil
}() }()
installPath, err := ip.BeforeExecute() if err := ip.BeforeExecute(); err != nil {
if err != nil {
return errors.WithStack(err) return errors.WithStack(err)
} }
cid, err := ip.Execute(installPath) cid, err := ip.Execute()
if err != nil { if err != nil {
ip.RemoveContainer() ip.RemoveContainer()
@ -233,23 +230,23 @@ func (ip *InstallationProcess) Run() error {
return nil return nil
} }
// Returns the location of the temporary data for the installation process.
func (ip *InstallationProcess) tempDir() string {
return filepath.Join(os.TempDir(), "pterodactyl/", ip.Server.Id())
}
// Writes the installation script to a temporary file on the host machine so that it // Writes the installation script to a temporary file on the host machine so that it
// can be properly mounted into the installation container and then executed. // can be properly mounted into the installation container and then executed.
func (ip *InstallationProcess) writeScriptToDisk() (string, error) { func (ip *InstallationProcess) writeScriptToDisk() error {
// Make sure the temp directory root exists before trying to make a directory within it. The // Make sure the temp directory root exists before trying to make a directory within it. The
// ioutil.TempDir call expects this base to exist, it won't create it for you. // ioutil.TempDir call expects this base to exist, it won't create it for you.
if err := os.MkdirAll(path.Join(os.TempDir(), "pterodactyl"), 0700); err != nil { if err := os.MkdirAll(ip.tempDir(), 0700); err != nil {
return "", errors.WithStack(err) return errors.Wrap(err, "could not create temporary directory for install process")
} }
d, err := ioutil.TempDir("", "pterodactyl") f, err := os.OpenFile(filepath.Join(ip.tempDir(), "install.sh"), os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0644)
if err != nil { if err != nil {
return "", errors.WithStack(err) return errors.Wrap(err, "failed to write server installation script to disk before mount")
}
f, err := os.OpenFile(filepath.Join(d, "install.sh"), os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0644)
if err != nil {
return "", errors.WithStack(err)
} }
defer f.Close() defer f.Close()
@ -261,12 +258,12 @@ func (ip *InstallationProcess) writeScriptToDisk() (string, error) {
} }
if err := scanner.Err(); err != nil { if err := scanner.Err(); err != nil {
return "", errors.WithStack(err) return errors.WithStack(err)
} }
w.Flush() w.Flush()
return d, nil return nil
} }
// Pulls the docker image to be used for the installation container. // Pulls the docker image to be used for the installation container.
@ -292,14 +289,13 @@ func (ip *InstallationProcess) pullInstallationImage() error {
// Runs before the container is executed. This pulls down the required docker container image // Runs before the container is executed. This pulls down the required docker container image
// as well as writes the installation script to the disk. This process is executed in an async // as well as writes the installation script to the disk. This process is executed in an async
// manner, if either one fails the error is returned. // manner, if either one fails the error is returned.
func (ip *InstallationProcess) BeforeExecute() (string, error) { func (ip *InstallationProcess) BeforeExecute() error {
fileName, err := ip.writeScriptToDisk() if err := ip.writeScriptToDisk(); err != nil {
if err != nil { return errors.Wrap(err, "failed to write installation script to disk")
return "", errors.Wrap(err, "failed to write installation script to disk")
} }
if err := ip.pullInstallationImage(); err != nil { if err := ip.pullInstallationImage(); err != nil {
return "", errors.Wrap(err, "failed to pull updated installation container image for server") return errors.Wrap(err, "failed to pull updated installation container image for server")
} }
opts := types.ContainerRemoveOptions{ opts := types.ContainerRemoveOptions{
@ -309,11 +305,11 @@ func (ip *InstallationProcess) BeforeExecute() (string, error) {
if err := ip.client.ContainerRemove(ip.context, ip.Server.Id()+"_installer", opts); err != nil { if err := ip.client.ContainerRemove(ip.context, ip.Server.Id()+"_installer", opts); err != nil {
if !client.IsErrNotFound(err) { if !client.IsErrNotFound(err) {
return "", errors.Wrap(err, "failed to remove existing install container for server") return errors.Wrap(err, "failed to remove existing install container for server")
} }
} }
return fileName, nil return nil
} }
// Returns the log path for the installation process. // Returns the log path for the installation process.
@ -384,7 +380,7 @@ func (ip *InstallationProcess) AfterExecute(containerId string) error {
} }
// Executes the installation process inside a specially created docker container. // Executes the installation process inside a specially created docker container.
func (ip *InstallationProcess) Execute(installPath string) (string, error) { func (ip *InstallationProcess) Execute() (string, error) {
conf := &container.Config{ conf := &container.Config{
Hostname: "installer", Hostname: "installer",
AttachStdout: true, AttachStdout: true,
@ -412,7 +408,7 @@ func (ip *InstallationProcess) Execute(installPath string) (string, error) {
}, },
{ {
Target: "/mnt/install", Target: "/mnt/install",
Source: installPath, Source: ip.tempDir(),
Type: mount.TypeBind, Type: mount.TypeBind,
ReadOnly: false, ReadOnly: false,
}, },
@ -433,7 +429,16 @@ func (ip *InstallationProcess) Execute(installPath string) (string, error) {
NetworkMode: container.NetworkMode(config.Get().Docker.Network.Mode), NetworkMode: container.NetworkMode(config.Get().Docker.Network.Mode),
} }
ip.Server.Log().WithField("install_script", installPath+"/install.sh").Info("creating install container for server process") ip.Server.Log().WithField("install_script", ip.tempDir()+"/install.sh").Info("creating install container for server process")
// Remove the temporary directory when the installation process finishes for this server container.
defer func() {
if err := os.RemoveAll(ip.tempDir()); err != nil {
if !os.IsNotExist(err) {
ip.Server.Log().WithField("error", err).Warn("failed to remove temporary data directory after install process")
}
}
}()
r, err := ip.client.ContainerCreate(ip.context, conf, hostConf, nil, ip.Server.Id()+"_installer") r, err := ip.client.ContainerCreate(ip.context, conf, hostConf, nil, ip.Server.Id()+"_installer")
if err != nil { if err != nil {
return "", errors.WithStack(err) return "", errors.WithStack(err)