300 lines
6.9 KiB
Go
300 lines
6.9 KiB
Go
package api
|
|
|
|
import (
|
|
"archive/tar"
|
|
"archive/zip"
|
|
"compress/gzip"
|
|
b64 "encoding/base64"
|
|
"fmt"
|
|
"io"
|
|
"io/ioutil"
|
|
"log"
|
|
"net/http"
|
|
"os"
|
|
"path/filepath"
|
|
"regexp"
|
|
"strings"
|
|
"time"
|
|
|
|
"github.com/pkg/errors"
|
|
)
|
|
|
|
func checkExists(filename string) os.FileInfo {
|
|
info, err := os.Stat(filename)
|
|
if os.IsNotExist(err) {
|
|
return nil
|
|
}
|
|
LogDebugMessage("File exists\n")
|
|
return info
|
|
}
|
|
|
|
// FileExists checks if a file exists
|
|
func FileExists(filename string) bool {
|
|
if fe := checkExists(filename); fe != nil && !fe.IsDir() {
|
|
return true
|
|
}
|
|
return false
|
|
}
|
|
|
|
// DirExists checks if a directory exists
|
|
func DirExists(dirname string) bool {
|
|
if fe := checkExists(dirname); fe != nil && fe.IsDir() {
|
|
return true
|
|
}
|
|
return false
|
|
}
|
|
|
|
// LogDebugMessage logs a debug message
|
|
func LogDebugMessage(strMessage string, args ...interface{}) {
|
|
if os.Getenv("QLIKSENSE_DEBUG") == "true" {
|
|
fmt.Printf(strMessage, args...)
|
|
}
|
|
}
|
|
|
|
// ReadKeys reads key file from disk
|
|
func ReadKeys(keyFile string) ([]byte, error) {
|
|
keybyteArray, err := ioutil.ReadFile(keyFile)
|
|
if err != nil {
|
|
err = fmt.Errorf("There was an error reading from file: %s, %v", keyFile, err)
|
|
log.Println(err)
|
|
return nil, err
|
|
}
|
|
return keybyteArray, nil
|
|
}
|
|
|
|
// ProcessConfigArgs processes args and returns an service, key, value slice
|
|
func ProcessConfigArgs(args []string, base64Encoded bool) ([]*ServiceKeyValue, error) {
|
|
// prepare received args
|
|
// split args[0] into key and value
|
|
if len(args) == 0 {
|
|
err := fmt.Errorf("No args were provided. Please provide args to configure the current context")
|
|
return nil, err
|
|
}
|
|
notValidErr := fmt.Errorf("Please provide valid args for this command")
|
|
resultSvcKV := make([]*ServiceKeyValue, len(args))
|
|
// qliksense.mongodb=somethig
|
|
for i, arg := range args {
|
|
LogDebugMessage("Arg received: %s\n", arg)
|
|
first := strings.SplitN(arg, "=", 2)
|
|
if len(first) != 2 {
|
|
return nil, notValidErr
|
|
}
|
|
|
|
svcKey := getSvcAndKey(first[0])
|
|
if len(svcKey) != 2 {
|
|
return nil, notValidErr
|
|
}
|
|
resultValue := strings.Trim(first[1], "\"")
|
|
if base64Encoded {
|
|
if decodeByte, err := b64.StdEncoding.DecodeString(resultValue); err != nil {
|
|
return nil, err
|
|
} else {
|
|
resultValue = strings.Trim(string(decodeByte), "\n ")
|
|
}
|
|
}
|
|
resultSvcKV[i] = &ServiceKeyValue{
|
|
SvcName: svcKey[0],
|
|
Key: svcKey[1],
|
|
Value: resultValue,
|
|
}
|
|
}
|
|
return resultSvcKV, nil
|
|
}
|
|
|
|
// input should be svc[key]
|
|
func getSvcAndKey(arg string) []string {
|
|
// for key
|
|
re := regexp.MustCompile(`\[(.*)\]`)
|
|
// for service
|
|
re2 := regexp.MustCompile(`(.*)\[`)
|
|
|
|
keys := re.FindStringSubmatch(arg)
|
|
|
|
svcs := re2.FindStringSubmatch(arg)
|
|
if len(svcs) != 2 || len(keys) != 2 {
|
|
return strings.SplitN(arg, ".", 2)
|
|
}
|
|
if svcs[1] == "" || keys[1] == "" {
|
|
return []string{}
|
|
}
|
|
return []string{svcs[1], keys[1]}
|
|
}
|
|
|
|
func ExecuteTaskWithBlinkingStdoutFeedback(task func() (interface{}, error), feedback string) (result interface{}, err error) {
|
|
taskDone := make(chan bool)
|
|
go func() {
|
|
result, err = task()
|
|
taskDone <- true
|
|
}()
|
|
progressOnTicker := time.NewTicker(500 * time.Millisecond)
|
|
progressOffTicker := time.NewTicker(1000 * time.Millisecond)
|
|
printProgress := func(on bool) {
|
|
if on {
|
|
fmt.Printf("%s\r", feedback)
|
|
} else {
|
|
fmt.Printf("%s\r", strings.Repeat(" ", len(feedback)))
|
|
}
|
|
}
|
|
for {
|
|
select {
|
|
case <-taskDone:
|
|
progressOnTicker.Stop()
|
|
progressOffTicker.Stop()
|
|
printProgress(false)
|
|
return result, err
|
|
case <-progressOnTicker.C:
|
|
printProgress(true)
|
|
case <-progressOffTicker.C:
|
|
printProgress(false)
|
|
}
|
|
}
|
|
}
|
|
|
|
func DownloadFile(url, baseFolder, installerName string) error {
|
|
var (
|
|
out *os.File
|
|
err error
|
|
resp *http.Response
|
|
)
|
|
// Create the file
|
|
fileName := filepath.Join(baseFolder, installerName)
|
|
LogDebugMessage("Installer Filename: %s\n", fileName)
|
|
if out, err = os.Create(fileName); err != nil {
|
|
return err
|
|
}
|
|
defer out.Close()
|
|
|
|
// Get the data
|
|
if resp, err = http.Get(url); err != nil {
|
|
return err
|
|
}
|
|
defer resp.Body.Close()
|
|
|
|
if resp.StatusCode != http.StatusOK {
|
|
err = fmt.Errorf("unable to download the file from URL: %s, status: %s", url, resp.Status)
|
|
log.Println(err)
|
|
return err
|
|
}
|
|
|
|
// Write the body to file
|
|
if _, err = io.Copy(out, resp.Body); err != nil {
|
|
return err
|
|
}
|
|
err = os.Chmod(fileName, os.ModePerm)
|
|
if err != nil {
|
|
log.Println(err)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func ExplodePackage(destination, fileToUntar string) error {
|
|
LogDebugMessage("Destination: %s\n", destination)
|
|
LogDebugMessage("fileToUntar: %s\n", fileToUntar)
|
|
|
|
if strings.HasSuffix(fileToUntar, "zip") {
|
|
LogDebugMessage("This is a windows file : %s", fileToUntar)
|
|
err := UnZipFile(destination, fileToUntar)
|
|
if err != nil {
|
|
return nil
|
|
}
|
|
} else if strings.HasSuffix(fileToUntar, "tar.gz") {
|
|
LogDebugMessage("This is a mac/linux file: %s", fileToUntar)
|
|
err := UntarGzFile(destination, fileToUntar)
|
|
if err != nil {
|
|
return nil
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func UntarGzFile(destination, fileToUntar string) error {
|
|
lFile, err := os.Open(fileToUntar)
|
|
if err != nil {
|
|
err = errors.Wrapf(err, "unable to read the local file %s", fileToUntar)
|
|
log.Fatal(err)
|
|
return err
|
|
}
|
|
|
|
gzReader, err := gzip.NewReader(lFile)
|
|
if err != nil {
|
|
err = errors.Wrap(err, "unable to load the file into a gz reader")
|
|
log.Fatal(err)
|
|
return err
|
|
}
|
|
defer gzReader.Close()
|
|
|
|
tarReader := tar.NewReader(gzReader)
|
|
for {
|
|
header, err := tarReader.Next()
|
|
switch {
|
|
case err == io.EOF:
|
|
return nil
|
|
case err != nil:
|
|
err = errors.Wrap(err, "error during untar")
|
|
log.Fatal(err)
|
|
return err
|
|
case header == nil:
|
|
continue
|
|
}
|
|
|
|
fileInLoop := filepath.Join(destination, header.Name)
|
|
switch header.Typeflag {
|
|
case tar.TypeDir:
|
|
if _, err := os.Stat(fileInLoop); err != nil {
|
|
if err := os.MkdirAll(fileInLoop, 0755); err != nil {
|
|
err = errors.Wrapf(err, "error creating directory %s", fileInLoop)
|
|
log.Fatal(err)
|
|
return err
|
|
}
|
|
}
|
|
case tar.TypeReg:
|
|
fileAtLoc, err := os.OpenFile(fileInLoop, os.O_CREATE|os.O_RDWR, os.FileMode(header.Mode))
|
|
if err != nil {
|
|
err = errors.Wrapf(err, "error opening file %s", fileInLoop)
|
|
log.Fatal(err)
|
|
return err
|
|
}
|
|
|
|
if _, err := io.Copy(fileAtLoc, tarReader); err != nil {
|
|
err = errors.Wrapf(err, "error writing file %s", fileInLoop)
|
|
log.Fatal(err)
|
|
return err
|
|
}
|
|
fileAtLoc.Close()
|
|
fileAtLoc.Chmod(os.ModePerm)
|
|
}
|
|
}
|
|
}
|
|
|
|
func UnZipFile(destination, fileToUnzip string) error {
|
|
zipReader, _ := zip.OpenReader(fileToUnzip)
|
|
for _, file := range zipReader.Reader.File {
|
|
|
|
zippedFile, err := file.Open()
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
defer zippedFile.Close()
|
|
extractedFilePath := filepath.Join(
|
|
destination,
|
|
file.Name,
|
|
)
|
|
outputFile, err := os.OpenFile(
|
|
extractedFilePath,
|
|
os.O_WRONLY|os.O_CREATE|os.O_TRUNC,
|
|
file.Mode(),
|
|
)
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
defer outputFile.Close()
|
|
|
|
_, err = io.Copy(outputFile, zippedFile)
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
LogDebugMessage("File extracted: %s, Extracted file path: %s\n", file.Name, extractedFilePath)
|
|
}
|
|
return nil
|
|
}
|