gouick/helpers/dependencies/golang.go
2022-07-15 11:49:53 +00:00

215 lines
4.8 KiB
Go

package dependencies
import (
"fmt"
"os"
"os/exec"
"regexp"
"runtime"
"strings"
"github.com/blang/semver"
"github.com/juju/errors"
"git.home.m-and-m.ovh/mderasse/boot/helpers"
log "github.com/sirupsen/logrus"
)
// minimum minor required for the app to work
const minimumGolangVersion = "1.18.4"
// installation directory for fresh install.
// will be prefixed by $HOME
const defaultGolangInstallDir = "/local/go"
var regexGolangVersion = regexp.MustCompile(`^go version go(\d+\.\d+\.\d+)`)
type Golang struct{}
// regroup all golang dependencies function
// GetName
func (g Golang) GetName() string {
return "Golang"
}
// GetMinimumVersion
func (g Golang) GetMinimumVersion() string {
return minimumGolangVersion
}
// IsInstalled
func (g Golang) IsInstalled() (bool, error) {
_, err := g.GetBinaryPath()
if err != nil && !errors.Is(err, exec.ErrNotFound) {
return false, errors.Trace(err)
} else if err != nil && errors.Is(err, exec.ErrNotFound) {
return false, nil
}
return true, nil
}
// GetBinaryPath
func (g Golang) GetBinaryPath() (string, error) {
log.Debug("looking for golang binary")
path, err := exec.LookPath("go")
if err != nil {
return "", errors.Trace(err)
}
log.Debug("found golang binary in", path)
return path, nil
}
// GetVersion return the major, minor and patch version of Golang
func (g Golang) GetVersion() (string, error) {
isInstalled, err := g.IsInstalled()
if err != nil {
return "", errors.Trace(err)
}
if !isInstalled {
return "", errors.NotFoundf("golang is not installed on the system")
}
golangPath, err := g.GetBinaryPath()
if err != nil {
return "", errors.Trace(err)
}
log.Debug("executing go version command")
cmd := exec.Command(golangPath, "version")
stdout, err := cmd.Output()
if err != nil {
return "", errors.Trace(err)
}
cleanOut := strings.TrimSpace(string(stdout))
log.Debugf("go version returned %s", cleanOut)
parseOutput := regexGolangVersion.FindStringSubmatch(cleanOut)
if len(parseOutput) != 2 {
return "", errors.NotSupportedf("failed to parse golang version output: %s", cleanOut)
}
return parseOutput[1], nil
}
// IsVersionSupported
func (g Golang) IsVersionSupported() (bool, error) {
version, err := g.GetVersion()
if err != nil {
return false, errors.Trace(err)
}
installedVersion, err := semver.Make(version)
if err != nil {
return false, errors.Trace(err)
}
requiredVersion, _ := semver.Make(minimumGolangVersion)
if err != nil {
return false, errors.Trace(err)
}
if installedVersion.LT(*&requiredVersion) {
return false, nil
}
return true, nil
}
// DescribeInstall
func (g Golang) DescribeInstall(path string) string {
description := fmt.Sprintf("rm -rf %s/* ", path)
description = fmt.Sprintf("%s\ncurl %s | tar --strip-components=1 -C %s -zxf -", description, getDownloadUrl(), path)
return description
}
// Install
func (g Golang) Install(path string) error {
err := helpers.RemoveDirectoryContent(path)
if err != nil {
log.Warnf("fail to delete content of directory %s", path)
}
downloadUrl := getDownloadUrl()
content, err := downloadFile(downloadUrl)
if err != nil {
log.Warnf("fail to download file from %s", downloadUrl)
return errors.Trace(err)
}
gzipReader, err := unGzip(content)
if err != nil {
log.Warnf("fail to un-gzip downloaded file from %s, error:", downloadUrl)
return errors.Trace(err)
}
// XXX: unTar should take a subdir
err = unTar(gzipReader, "go/", path)
if err != nil {
log.Warnf("fail to un-tar downloaded file from %s", downloadUrl)
return errors.Trace(err)
}
return nil
}
// GetInstallDirectory will try to find the current golang directory. If it doesn't exist or if it's in a
// not userspace directory, it will provide the "default"
// It doesn't mean that the directory is "writable"
func (g Golang) GetInstallDirectory() (string, error) {
homeDir, err := os.UserHomeDir()
if err != nil {
return "", errors.Trace(err)
}
isInstalled, err := g.IsInstalled()
if err != nil {
return "", errors.Trace(err)
}
// concat default install dir with home and we have our path
if !isInstalled {
return fmt.Sprintf("%s/%s", homeDir, defaultGolangInstallDir), nil
}
// now let's play and find the current install path
golangPath, err := g.GetBinaryPath()
if err != nil {
return "", errors.Trace(err)
}
log.Debug("executing go env GOROOT command")
cmd := exec.Command(golangPath, "env", "GOROOT")
stdout, err := cmd.Output()
if err != nil {
return "", errors.Trace(err)
}
cleanOut := strings.TrimSpace(string(stdout))
if !strings.Contains(cleanOut, homeDir) {
return fmt.Sprintf("%s/%s", homeDir, defaultGolangInstallDir), nil
}
return cleanOut, nil
}
func getDownloadUrl() string {
return fmt.Sprintf("https://dl.google.com/go/go%s.%s-%s.tar.gz", minimumGolangVersion, runtime.GOOS, runtime.GOARCH)
}