gouick/helpers/dependencies/swagger.go
2022-07-25 20:43:53 +00:00

283 lines
5.8 KiB
Go

package dependencies
import (
"fmt"
"io/ioutil"
"os"
"os/exec"
"path/filepath"
"regexp"
"runtime"
"strings"
"github.com/blang/semver"
"github.com/juju/errors"
log "github.com/sirupsen/logrus"
)
// minimum minor required for the app to work
const minimumSwaggerVersion = "0.29.0"
// installation directory for fresh install.
// will be prefixed by $HOME
const defaultSwaggerInstallDir = "/bin"
var regexSwaggerVersion = regexp.MustCompile(`^version: v(\d+\.\d+\.\d+)`)
type Swagger struct{}
// regroup all swagger dependencies function
// GetName
func (s Swagger) GetName() string {
return "Go Swagger"
}
// GetMinimumVersion
func (s Swagger) GetMinimumVersion() string {
return minimumSwaggerVersion
}
// IsInstalled
func (s Swagger) IsInstalled() (bool, error) {
_, err := s.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 (s Swagger) GetBinaryPath() (string, error) {
log.Debug("looking for swagger binary")
path, err := exec.LookPath("swagger")
if err != nil {
return "", errors.Trace(err)
}
log.Debug("found swagger binary in", path)
return path, nil
}
// GetVersion
func (s Swagger) GetVersion() (string, error) {
isInstalled, err := s.IsInstalled()
if err != nil {
return "", errors.Trace(err)
}
if !isInstalled {
return "", errors.NotFoundf("swagger is not installed on the system")
}
binaryPath, err := s.GetBinaryPath()
if err != nil {
return "", errors.Trace(err)
}
log.Debug("executing swagger version command")
cmd := exec.Command(binaryPath, "version")
stdout, err := cmd.Output()
if err != nil {
return "", errors.Trace(err)
}
cleanOut := strings.TrimSpace(string(stdout))
log.Debugf("swagger version returned %s", cleanOut)
parseOutput := regexSwaggerVersion.FindStringSubmatch(cleanOut)
if len(parseOutput) != 2 {
return "", errors.NotSupportedf("failed to parse swagger version output: %s", cleanOut)
}
return parseOutput[1], nil
}
// IsVersionSupported
func (s Swagger) IsVersionSupported() (bool, error) {
isInstalled, err := s.IsInstalled()
if err != nil {
return false, errors.Trace(err)
}
if !isInstalled {
return false, nil
}
version, err := s.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(minimumSwaggerVersion)
if err != nil {
return false, errors.Trace(err)
}
if installedVersion.LT(requiredVersion) {
return false, nil
}
return true, nil
}
// CanBeInstalled
func (s Swagger) CanBeInstalled() bool {
return true
}
// DescribeInstall
func (s Swagger) DescribeInstall(path string) string {
commands := []string{
"The following commands will be executed",
fmt.Sprintf("rm -rf %s/swagger ", path),
fmt.Sprintf("wget %s -O %s/swagger", s.getDownloadUrl(), path),
fmt.Sprintf("chmod 644 %s/swagger", path),
}
return strings.Join(commands, "\n")
}
// Install
func (s Swagger) Install(path string) error {
downloadUrl := s.getDownloadUrl()
content, err := downloadFile(downloadUrl)
if err != nil {
log.Warnf("fail to download file from %s", downloadUrl)
return errors.Trace(err)
}
fh, err := os.OpenFile(
filepath.Join(path, "swagger"),
os.O_RDWR|os.O_CREATE|os.O_TRUNC,
0744,
)
if err != nil {
return errors.Trace(err)
}
defer fh.Close()
bContent, err := ioutil.ReadAll(content)
if err != nil {
return errors.Trace(err)
}
_, err = fh.Write(bContent)
if err != nil {
return errors.Trace(err)
}
return nil
}
// DescribePostInstall
func (s Swagger) DescribePostInstall(path string) string {
return `For your environment to work correctly, we will add if needed the following environment variable to your .bashrc:
PATH=\"$HOME/bin:$PATH\"
You will have to reopen a new terminal to apply the changes or execute the following command:
source $HOME/.bashrc
`
}
// PostInstall
func (s Swagger) PostInstall(path string) error {
lineBashRc := []string{
"# Swagger - Added by gouick",
}
// checking if swagger binary is found after installation
// if not it's probably not in the path
isInstalled, err := s.IsInstalled()
if err != nil {
return errors.Trace(err)
}
if !isInstalled {
lineBashRc = append(lineBashRc, "PATH=\"$HOME/bin:$PATH\"")
}
homeDir, err := os.UserHomeDir()
if err != nil {
return errors.Trace(err)
}
if len(lineBashRc) > 1 {
log.Debug("Adding env variable to .bashrc")
fh, err := os.OpenFile(
filepath.Join(homeDir, ".bashrc"),
os.O_APPEND|os.O_CREATE|os.O_WRONLY,
0644,
)
if err != nil {
return errors.Trace(err)
}
defer fh.Close()
_, err = fh.WriteString(
fmt.Sprintf("\n\n%s\n", strings.Join(lineBashRc, "\n")),
)
if err != nil {
return errors.Trace(err)
}
}
return nil
}
// GetInstallDirectory will try to find the current swagger 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 (s Swagger) GetInstallDirectory() (string, error) {
homeDir, err := os.UserHomeDir()
if err != nil {
return "", errors.Trace(err)
}
isInstalled, err := s.IsInstalled()
if err != nil {
return "", errors.Trace(err)
}
// concat default install dir with home and we have our path
if !isInstalled {
return filepath.Join(homeDir, defaultSwaggerInstallDir), nil
}
// now let's play and find the current install path
binaryPath, err := s.GetBinaryPath()
if err != nil {
return "", errors.Trace(err)
}
return strings.TrimSuffix(binaryPath, "/swagger"), nil
}
func (s Swagger) getDownloadUrl() string {
return fmt.Sprintf("https://github.com/go-swagger/go-swagger/releases/download/v%s/swagger_%s_%s", minimumSwaggerVersion, runtime.GOOS, runtime.GOARCH)
}