mirror of
https://github.com/davidallendj/magellan.git
synced 2025-12-20 03:27:03 -07:00
Refactored/reorganized utils
This commit is contained in:
parent
fe3c339195
commit
aefce13f57
5 changed files with 196 additions and 151 deletions
37
internal/util/auth.go
Normal file
37
internal/util/auth.go
Normal file
|
|
@ -0,0 +1,37 @@
|
||||||
|
package util
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
|
||||||
|
"github.com/spf13/viper"
|
||||||
|
)
|
||||||
|
|
||||||
|
// LoadAccessToken() tries to load a JWT string from an environment
|
||||||
|
// variable, file, or config in that order. If loading the token
|
||||||
|
// fails with one options, it will fallback to the next option until
|
||||||
|
// all options are exhausted.
|
||||||
|
//
|
||||||
|
// Returns a token as a string with no error if successful.
|
||||||
|
// Alternatively, returns an empty string with an error if a token is
|
||||||
|
// not able to be loaded.
|
||||||
|
func LoadAccessToken(path string) (string, error) {
|
||||||
|
// try to load token from env var
|
||||||
|
testToken := os.Getenv("ACCESS_TOKEN")
|
||||||
|
if testToken != "" {
|
||||||
|
return testToken, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// try reading access token from a file
|
||||||
|
b, err := os.ReadFile(path)
|
||||||
|
if err == nil {
|
||||||
|
return string(b), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: try to load token from config
|
||||||
|
testToken = viper.GetString("access_token")
|
||||||
|
if testToken != "" {
|
||||||
|
return testToken, nil
|
||||||
|
}
|
||||||
|
return "", fmt.Errorf("failed toload token from environment variable, file, or config")
|
||||||
|
}
|
||||||
25
internal/util/error.go
Normal file
25
internal/util/error.go
Normal file
|
|
@ -0,0 +1,25 @@
|
||||||
|
package util
|
||||||
|
|
||||||
|
import "fmt"
|
||||||
|
|
||||||
|
// FormatErrorList() is a wrapper function that unifies error list formatting
|
||||||
|
// and makes printing error lists consistent.
|
||||||
|
//
|
||||||
|
// NOTE: The error returned IS NOT an error in itself and may be a bit misleading.
|
||||||
|
// Instead, it is a single condensed error composed of all of the errors included
|
||||||
|
// in the errList argument.
|
||||||
|
func FormatErrorList(errList []error) error {
|
||||||
|
var err error
|
||||||
|
for i, e := range errList {
|
||||||
|
err = fmt.Errorf("\t[%d] %v\n", i, e)
|
||||||
|
i += 1
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// HasErrors() is a simple wrapper function to check if an error list contains
|
||||||
|
// errors. Having a function that clearly states its purpose helps to improve
|
||||||
|
// readibility although it may seem pointless.
|
||||||
|
func HasErrors(errList []error) bool {
|
||||||
|
return len(errList) > 0
|
||||||
|
}
|
||||||
64
internal/util/net.go
Normal file
64
internal/util/net.go
Normal file
|
|
@ -0,0 +1,64 @@
|
||||||
|
package util
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"crypto/tls"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"net"
|
||||||
|
"net/http"
|
||||||
|
)
|
||||||
|
|
||||||
|
// GetNextIP() returns the next IP address, but does not account
|
||||||
|
// for net masks.
|
||||||
|
func GetNextIP(ip *net.IP, inc uint) *net.IP {
|
||||||
|
if ip == nil {
|
||||||
|
return &net.IP{}
|
||||||
|
}
|
||||||
|
i := ip.To4()
|
||||||
|
v := uint(i[0])<<24 + uint(i[1])<<16 + uint(i[2])<<8 + uint(i[3])
|
||||||
|
v += inc
|
||||||
|
v3 := byte(v & 0xFF)
|
||||||
|
v2 := byte((v >> 8) & 0xFF)
|
||||||
|
v1 := byte((v >> 16) & 0xFF)
|
||||||
|
v0 := byte((v >> 24) & 0xFF)
|
||||||
|
// return &net.IP{[]byte{v0, v1, v2, v3}}
|
||||||
|
r := net.IPv4(v0, v1, v2, v3)
|
||||||
|
return &r
|
||||||
|
}
|
||||||
|
|
||||||
|
// MakeRequest() is a wrapper function that condenses simple HTTP
|
||||||
|
// requests done to a single call. It expects an optional HTTP client,
|
||||||
|
// URL, HTTP method, request body, and request headers. This function
|
||||||
|
// is useful when making many requests where only these few arguments
|
||||||
|
// are changing.
|
||||||
|
//
|
||||||
|
// Returns a HTTP response object, response body as byte array, and any
|
||||||
|
// error that may have occurred with making the request.
|
||||||
|
func MakeRequest(client *http.Client, url string, httpMethod string, body []byte, headers map[string]string) (*http.Response, []byte, error) {
|
||||||
|
// use defaults if no client provided
|
||||||
|
if client == nil {
|
||||||
|
client = http.DefaultClient
|
||||||
|
client.Transport = &http.Transport{
|
||||||
|
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
req, err := http.NewRequest(httpMethod, url, bytes.NewBuffer(body))
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, fmt.Errorf("failed to create new HTTP request: %v", err)
|
||||||
|
}
|
||||||
|
req.Header.Add("User-Agent", "magellan")
|
||||||
|
for k, v := range headers {
|
||||||
|
req.Header.Add(k, v)
|
||||||
|
}
|
||||||
|
res, err := client.Do(req)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, fmt.Errorf("failed to make request: %v", err)
|
||||||
|
}
|
||||||
|
b, err := io.ReadAll(res.Body)
|
||||||
|
res.Body.Close()
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, fmt.Errorf("failed to read response body: %v", err)
|
||||||
|
}
|
||||||
|
return res, b, err
|
||||||
|
}
|
||||||
70
internal/util/path.go
Normal file
70
internal/util/path.go
Normal file
|
|
@ -0,0 +1,70 @@
|
||||||
|
package util
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
// PathExists() is a wrapper function that simplifies checking
|
||||||
|
// if a file or directory already exists at the provided path.
|
||||||
|
//
|
||||||
|
// Returns whether the path exists and no error if successful,
|
||||||
|
// otherwise, it returns false with an error.
|
||||||
|
func PathExists(path string) (bool, error) {
|
||||||
|
_, err := os.Stat(path)
|
||||||
|
if err == nil {
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
if os.IsNotExist(err) {
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// SplitPathForViper() is an utility function to split a path into 3 parts:
|
||||||
|
// - directory
|
||||||
|
// - filename
|
||||||
|
// - extension
|
||||||
|
// The intent was to break a path into a format that's more easily consumable
|
||||||
|
// by spf13/viper's API. See the "LoadConfig()" function in internal/config.go
|
||||||
|
// for more details.
|
||||||
|
//
|
||||||
|
// TODO: Rename function to something more generalized.
|
||||||
|
func SplitPathForViper(path string) (string, string, string) {
|
||||||
|
filename := filepath.Base(path)
|
||||||
|
ext := filepath.Ext(filename)
|
||||||
|
return filepath.Dir(path), strings.TrimSuffix(filename, ext), strings.TrimPrefix(ext, ".")
|
||||||
|
}
|
||||||
|
|
||||||
|
// MakeOutputDirectory() creates a new directory at the path argument if
|
||||||
|
// the path does not exist
|
||||||
|
//
|
||||||
|
// TODO: Refactor this function for hive partitioning or possibly move into
|
||||||
|
// the logging package.
|
||||||
|
// TODO: Add an option to force overwriting the path.
|
||||||
|
func MakeOutputDirectory(path string) (string, error) {
|
||||||
|
// get the current data + time using Go's stupid formatting
|
||||||
|
t := time.Now()
|
||||||
|
dirname := t.Format("2006-01-01 15:04:05")
|
||||||
|
final := path + "/" + dirname
|
||||||
|
|
||||||
|
// check if path is valid and directory
|
||||||
|
pathExists, err := PathExists(final)
|
||||||
|
if err != nil {
|
||||||
|
return final, fmt.Errorf("failed to check for existing path: %v", err)
|
||||||
|
}
|
||||||
|
if pathExists {
|
||||||
|
// make sure it is directory with 0o644 permissions
|
||||||
|
return final, fmt.Errorf("found existing path: %v", final)
|
||||||
|
}
|
||||||
|
|
||||||
|
// create directory with data + time
|
||||||
|
err = os.MkdirAll(final, 0766)
|
||||||
|
if err != nil {
|
||||||
|
return final, fmt.Errorf("failed to make directory: %v", err)
|
||||||
|
}
|
||||||
|
return final, nil
|
||||||
|
}
|
||||||
|
|
@ -1,151 +0,0 @@
|
||||||
package util
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"crypto/tls"
|
|
||||||
"fmt"
|
|
||||||
"io"
|
|
||||||
"net"
|
|
||||||
"net/http"
|
|
||||||
"os"
|
|
||||||
"path/filepath"
|
|
||||||
"strings"
|
|
||||||
"time"
|
|
||||||
)
|
|
||||||
|
|
||||||
// PathExists() is a wrapper function that simplifies checking
|
|
||||||
// if a file or directory already exists at the provided path.
|
|
||||||
//
|
|
||||||
// Returns whether the path exists and no error if successful,
|
|
||||||
// otherwise, it returns false with an error.
|
|
||||||
func PathExists(path string) (bool, error) {
|
|
||||||
_, err := os.Stat(path)
|
|
||||||
if err == nil {
|
|
||||||
return true, nil
|
|
||||||
}
|
|
||||||
if os.IsNotExist(err) {
|
|
||||||
return false, nil
|
|
||||||
}
|
|
||||||
return false, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetNextIP() returns the next IP address, but does not account
|
|
||||||
// for net masks.
|
|
||||||
func GetNextIP(ip *net.IP, inc uint) *net.IP {
|
|
||||||
if ip == nil {
|
|
||||||
return &net.IP{}
|
|
||||||
}
|
|
||||||
i := ip.To4()
|
|
||||||
v := uint(i[0])<<24 + uint(i[1])<<16 + uint(i[2])<<8 + uint(i[3])
|
|
||||||
v += inc
|
|
||||||
v3 := byte(v & 0xFF)
|
|
||||||
v2 := byte((v >> 8) & 0xFF)
|
|
||||||
v1 := byte((v >> 16) & 0xFF)
|
|
||||||
v0 := byte((v >> 24) & 0xFF)
|
|
||||||
// return &net.IP{[]byte{v0, v1, v2, v3}}
|
|
||||||
r := net.IPv4(v0, v1, v2, v3)
|
|
||||||
return &r
|
|
||||||
}
|
|
||||||
|
|
||||||
// MakeRequest() is a wrapper function that condenses simple HTTP
|
|
||||||
// requests done to a single call. It expects an optional HTTP client,
|
|
||||||
// URL, HTTP method, request body, and request headers. This function
|
|
||||||
// is useful when making many requests where only these few arguments
|
|
||||||
// are changing.
|
|
||||||
//
|
|
||||||
// Returns a HTTP response object, response body as byte array, and any
|
|
||||||
// error that may have occurred with making the request.
|
|
||||||
func MakeRequest(client *http.Client, url string, httpMethod string, body []byte, headers map[string]string) (*http.Response, []byte, error) {
|
|
||||||
// use defaults if no client provided
|
|
||||||
if client == nil {
|
|
||||||
client = http.DefaultClient
|
|
||||||
client.Transport = &http.Transport{
|
|
||||||
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
req, err := http.NewRequest(httpMethod, url, bytes.NewBuffer(body))
|
|
||||||
if err != nil {
|
|
||||||
return nil, nil, fmt.Errorf("failed to create new HTTP request: %v", err)
|
|
||||||
}
|
|
||||||
req.Header.Add("User-Agent", "magellan")
|
|
||||||
for k, v := range headers {
|
|
||||||
req.Header.Add(k, v)
|
|
||||||
}
|
|
||||||
res, err := client.Do(req)
|
|
||||||
if err != nil {
|
|
||||||
return nil, nil, fmt.Errorf("failed to make request: %v", err)
|
|
||||||
}
|
|
||||||
b, err := io.ReadAll(res.Body)
|
|
||||||
res.Body.Close()
|
|
||||||
if err != nil {
|
|
||||||
return nil, nil, fmt.Errorf("failed to read response body: %v", err)
|
|
||||||
}
|
|
||||||
return res, b, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// MakeOutputDirectory() creates a new directory at the path argument if
|
|
||||||
// the path does not exist
|
|
||||||
//
|
|
||||||
// TODO: Refactor this function for hive partitioning or possibly move into
|
|
||||||
// the logging package.
|
|
||||||
// TODO: Add an option to force overwriting the path.
|
|
||||||
func MakeOutputDirectory(path string) (string, error) {
|
|
||||||
// get the current data + time using Go's stupid formatting
|
|
||||||
t := time.Now()
|
|
||||||
dirname := t.Format("2006-01-01 15:04:05")
|
|
||||||
final := path + "/" + dirname
|
|
||||||
|
|
||||||
// check if path is valid and directory
|
|
||||||
pathExists, err := PathExists(final)
|
|
||||||
if err != nil {
|
|
||||||
return final, fmt.Errorf("failed to check for existing path: %v", err)
|
|
||||||
}
|
|
||||||
if pathExists {
|
|
||||||
// make sure it is directory with 0o644 permissions
|
|
||||||
return final, fmt.Errorf("found existing path: %v", final)
|
|
||||||
}
|
|
||||||
|
|
||||||
// create directory with data + time
|
|
||||||
err = os.MkdirAll(final, 0766)
|
|
||||||
if err != nil {
|
|
||||||
return final, fmt.Errorf("failed to make directory: %v", err)
|
|
||||||
}
|
|
||||||
return final, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// SplitPathForViper() is an utility function to split a path into 3 parts:
|
|
||||||
// - directory
|
|
||||||
// - filename
|
|
||||||
// - extension
|
|
||||||
// The intent was to break a path into a format that's more easily consumable
|
|
||||||
// by spf13/viper's API. See the "LoadConfig()" function in internal/config.go
|
|
||||||
// for more details.
|
|
||||||
//
|
|
||||||
// TODO: Rename function to something more generalized.
|
|
||||||
func SplitPathForViper(path string) (string, string, string) {
|
|
||||||
filename := filepath.Base(path)
|
|
||||||
ext := filepath.Ext(filename)
|
|
||||||
return filepath.Dir(path), strings.TrimSuffix(filename, ext), strings.TrimPrefix(ext, ".")
|
|
||||||
}
|
|
||||||
|
|
||||||
// FormatErrorList() is a wrapper function that unifies error list formatting
|
|
||||||
// and makes printing error lists consistent.
|
|
||||||
//
|
|
||||||
// NOTE: The error returned IS NOT an error in itself and may be a bit misleading.
|
|
||||||
// Instead, it is a single condensed error composed of all of the errors included
|
|
||||||
// in the errList argument.
|
|
||||||
func FormatErrorList(errList []error) error {
|
|
||||||
var err error
|
|
||||||
for i, e := range errList {
|
|
||||||
err = fmt.Errorf("\t[%d] %v\n", i, e)
|
|
||||||
i += 1
|
|
||||||
}
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// HasErrors() is a simple wrapper function to check if an error list contains
|
|
||||||
// errors. Having a function that clearly states its purpose helps to improve
|
|
||||||
// readibility although it may seem pointless.
|
|
||||||
func HasErrors(errList []error) bool {
|
|
||||||
return len(errList) > 0
|
|
||||||
}
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue