6
1
mirror of https://git.mills.io/saltyim/saltyim.git synced 2024-06-25 16:28:20 +00:00
prologic-saltyim/utils.go

145 lines
3.2 KiB
Go
Raw Normal View History

package saltyim
import (
"bytes"
"context"
"fmt"
"io"
"net/http"
"os"
"os/exec"
"syscall"
2022-03-20 13:54:54 +00:00
"text/template"
"time"
log "github.com/sirupsen/logrus"
)
const (
defaultRequestTimeout = time.Second * 5
)
func MustRenderString(s string, ctx interface{}) string {
out, err := RenderString(s, ctx)
if err != nil {
log.WithError(err).Fatal("error rendering string template")
}
return out
}
// DirExists returns true if the given directory exists
func DirExists(name string) bool {
stat, err := os.Stat(name)
if err != nil {
if os.IsNotExist(err) {
return false
}
return false
}
return stat.IsDir()
}
// FileExists returns true if the given file exists
func FileExists(name string) bool {
if _, err := os.Stat(name); err != nil {
if os.IsNotExist(err) {
return false
}
}
return true
}
// RenderString renders the string `s` as a `text/template` using the provided
// context `ctx` as input into the template.
// Typically used to render the results into a Markdown document.
func RenderString(s string, ctx interface{}) (string, error) {
2022-03-20 13:54:54 +00:00
t := template.Must(template.New("s").Parse(s))
buf := bytes.NewBuffer([]byte{})
err := t.Execute(buf, ctx)
if err != nil {
return "", err
}
return buf.String(), nil
}
// Request is a generic request handling function for making artbitrary HTPT
// requests to Salty endpoints for looking up Salty Addresses, Configs and
// publishing encrypted messages.
func Request(method, uri string, headers http.Header, body io.Reader) (*http.Response, error) {
req, err := http.NewRequest(method, uri, body)
if err != nil {
2022-03-19 15:24:21 +00:00
return nil, fmt.Errorf("%s: http.NewRequest fail: %s", uri, err)
}
if headers == nil {
headers = make(http.Header)
}
// Set a default User-Agent (if none set)
if headers.Get("User-Agent") == "" {
headers.Set("User-Agent", fmt.Sprintf("saltyim/%s", FullVersion()))
}
req.Header = headers
client := http.Client{
Timeout: defaultRequestTimeout,
}
res, err := client.Do(req)
if err != nil {
2022-03-19 15:24:21 +00:00
return nil, fmt.Errorf("%s: client.Do fail: %s", uri, err)
}
if res.StatusCode/100 != 2 {
2022-03-19 15:24:21 +00:00
return nil, fmt.Errorf("non-2xx response received: %s", res.Status)
}
return res, nil
}
// CmdExists ...
func CmdExists(cmd string) bool {
_, err := exec.LookPath(cmd)
return err == nil
}
// RunCmd ...
func RunCmd(timeout time.Duration, command string, stdin io.Reader, args ...string) (string, error) {
var (
ctx context.Context
cancel context.CancelFunc
)
if timeout > 0 {
ctx, cancel = context.WithTimeout(context.Background(), timeout)
} else {
ctx, cancel = context.WithCancel(context.Background())
}
defer cancel()
cmd := exec.CommandContext(ctx, command, args...)
cmd.Stdin = stdin
out, err := cmd.CombinedOutput()
if err != nil {
if exitError, ok := err.(*exec.ExitError); ok {
if ws, ok := exitError.Sys().(syscall.WaitStatus); ok && ws.Signal() == syscall.SIGKILL {
err = &ErrCommandKilled{Err: err, Signal: ws.Signal()}
} else {
err = &ErrCommandFailed{Err: err, Status: exitError.ExitCode()}
}
}
return "", err
}
return string(out), nil
}
// SetTerminalTitle sets the Terminal/Console's title
func SetTerminalTitle(format string, args ...interface{}) {
fmt.Printf("\033]0;%s\007", fmt.Sprintf(format, args...))
}