utils

package module
v0.0.0-...-2f52068 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Mar 5, 2025 License: MIT Imports: 50 Imported by: 15

Documentation

Index

Constants

View Source
const (
	TimeISO8601LayOut     = "2006-01-02T15:04:05-0700"
	AUTimeLayout          = "02/01/2006 15:04:05 MST"
	CleanStringDateLayout = "2006-01-02-150405"
	LetterBytes           = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#%^()-,."
)

TimeISO8601LayOut

Variables

View Source
var GoTemplateFuncMap = htmltemplate.FuncMap{

	"inc":      tmpl_inc,
	"add":      tmpl_add,
	"title":    tmpl_title,
	"lower":    tmpl_lower,
	"upper":    tmpl_upper,
	"time_fmt": tmpl_time_fmt,
	"now":      tmpl_now,
	"raw_html": func(html string) htmltemplate.HTML {
		return htmltemplate.HTML(html)
	},
	"unsafe_raw_html": func(html string) htmltemplate.HTML {
		return htmltemplate.HTML(html)
	},
	"if_ie": func() htmltemplate.HTML {
		return htmltemplate.HTML("<!--[if IE]>")
	},
	"end_if_ie": func() htmltemplate.HTML {
		return htmltemplate.HTML("<![endif]-->")
	},
	"join": tmpl_join,
	"truncatechars": func(length int, in string) htmltemplate.HTML {
		return htmltemplate.HTML(ChunkString(in, length)[0])
	},
	"cycle": func(idx int, vals ...string) htmltemplate.HTML {
		_idx := idx % len(vals)
		return htmltemplate.HTML(vals[_idx])
	},
	"replace": func(data, old, new string) htmltemplate.HTML {
		o := strings.ReplaceAll(data, old, new)
		return htmltemplate.HTML(o)
	},
	"contains": func(data, subStr string) bool {
		return strings.Contains(data, subStr)
	},
	"int_range": tmpl_int_range,
	"basename":  tmpl_basename,
	"dirname":   tmpl_dirname,
	"regex_search": func(regex string, s string) bool {
		match, _ := regexp.MatchString(regex, s)
		return match
	},
	"regex_replace": func(regex string, repl string, s string) string {
		r := regexp.MustCompile(regex)
		return r.ReplaceAllString(s, repl)
	},
}

Common usefull go html template funcs

View Source
var GoTextTemplateFuncMap = template.FuncMap{
	"inc":           tmpl_inc,
	"add":           tmpl_add,
	"title":         tmpl_title,
	"lower":         tmpl_lower,
	"upper":         tmpl_upper,
	"time_fmt":      tmpl_time_fmt,
	"now":           tmpl_now,
	"join":          tmpl_join,
	"truncatechars": tmpl_truncatechars,
	"cycle":         tmpl_cycle,
	"replace":       tmpl_replace,
	"contains":      tmpl_contains,
	"int_range":     tmpl_int_range,
	"basename":      tmpl_basename,
	"dirname":       tmpl_dirname,
	"to_yaml":       tmpl_toyaml,
	"to_nice_yaml":  tmpl_to_niceyaml,
	"to_json":       tmpl_tojson,
	"indent":        indent,
	"nindent": func(spaces int, v string) string {
		return "\n" + indent(spaces, v)
	},
	"regex_search": func(regex string, s string) bool {
		match, _ := regexp.MatchString(regex, s)
		return match
	},
	"regex_replace": func(regex string, repl string, s string) string {
		r := regexp.MustCompile(regex)
		return r.ReplaceAllString(s, repl)
	},
}

Common func for go text template

View Source
var MaskCredentialPattern *regexp.Regexp = regexp.MustCompile(`(?i)(password|token|pass|passkey|secret|secret_key|access_key|PAT)([:=]{1,1})[\s]*[^\s]+`)

MaskCredential RegexPattern

Functions

func Assert

func Assert(cond bool, msg string, fatal bool) bool

func AssertInt64ValueForMap

func AssertInt64ValueForMap(input map[string]interface{}) map[string]interface{}

func BcryptCheckPasswordHash

func BcryptCheckPasswordHash(password, hash string) bool

func BcryptHashPassword

func BcryptHashPassword(password string, cost int) (string, error)

func BlockInFile

func BlockInFile(filename string, upper_bound_pattern, lower_bound_pattern []string, marker any, replText string, keepBoundaryLines bool, backup bool) (oldBlock string)

Find a block text matching and replace content with replText. Return the old text block. Use ExtractTextBlockContains under the hood to get the text block see that func for help. Remember marker and lower is important, if not care about upper_bound_pattern pass a empty slice []string{} and set the marker same as the upper (start pattern).

func CamelCaseToWords

func CamelCaseToWords(s string) []string

CamelCaseToWords converts a camel case string into a list of words.

func CheckErr

func CheckErr(err error, location string)

func CheckErrNonFatal

func CheckErrNonFatal(err error, location string) error

func CheckNonErrIfMatch

func CheckNonErrIfMatch(err error, ptn, location string) error

func ChunkString

func ChunkString(s string, chunkSize int) []string

ChunkString -

func CloneSliceOfMap

func CloneSliceOfMap(a []any) (output []any)

CloneSliceOfMap

func ComputeHash

func ComputeHash(plainText string, salt []byte) string

func ConvertListIfaceToListStr

func ConvertListIfaceToListStr(in interface{}) []string

Function to convert interface{} => list string

func ConvertStruct2Map

func ConvertStruct2Map[T any](t T) ([]string, map[string]any)

Take a struct and convert into a map[string]any - the key of the map is the struct field name, and the value is the struct field value. This is useful to pass it to the gop template to render the struct value

func Copy

func Copy(srcFile, dstFile string) error

func CopyDirectory

func CopyDirectory(scrDir, dest string) error

CopyDirectory copy the content of src => dest. Both src and dest dir need to exists

func CopySymLink(source, dest string) error

func CreateDirTree

func CreateDirTree(srcDirpath, targetRoot string) error

CreateDirTree take the directory structure from the source and create it in the target Path should be absolute path. They should not overlap to avoid recursive loop

func CreateIfNotExists

func CreateIfNotExists(dir string, perm os.FileMode) error

func Curl

func Curl(method, url, data, savefilename string, headers []string) (string, error)

Make a HTTP request to url and get data. Emulate the curl command. Take the env var CURL_DEBUG - set to 'yes' if u need more debugging. CA_CERT_FILE, SSL_KEY_FILE, SSL_CERT_FILE correspondingly if required To ignore cert check set INSECURE_SKIP_VERIFY to yes data set it to empty string if you do not need to send any data. savefilename if you do not want to save to a file, set it to empty string Same as header array it is a list of string with : as separator. Eg. []string{"Authorization: Bearer <myToken>"}

func CustomJsonMarshal

func CustomJsonMarshal(v interface{}) ([]byte, error)

Custom JSON marshalling function

func CustomJsonMarshalIndent

func CustomJsonMarshalIndent(v interface{}, indent int) ([]byte, error)

func Decrypt

func Decrypt(ciphertextBase64 string, key string) (string, error)

AES decrypt a ciphertext base64 encoded string

func Encrypt

func Encrypt(text, key string) string

AES encrypt a string. Output is cipher text base64 encoded

func Exists

func Exists(filePath string) bool

func ExtractLineInLines

func ExtractLineInLines(blocklines []string, start, line, end string) [][]string

ExtractLineInLines will find a line match a pattern with capture (or not). The pattern is in between a start pattern and end pattern to narrow down search range. Return the result of FindAllStringSubmatch func of the match line This is simpler as it does not support multiple pattern as a marker like the other func eg ExtractTextBlockContains so input should be small and pattern match should be unique. Use the other function to devide it into small range and then use this func. start and line can be the same pattern. Same as line and end; it will return the match of start (or end) pattern

func ExtractTextBlock

func ExtractTextBlock(filename string, start_pattern, end_pattern []string) (block string, start_line_no int, end_line_no int, datalines []string)

ExtractTextBlock extract a text from two set regex patterns. The text started with the line matched start_pattern and when hit the match for end_pattern it will stop not including_endlines

func ExtractTextBlockContains

func ExtractTextBlockContains(filename string, upper_bound_pattern, lower_bound_pattern []string, marker interface{}) (block string, start_line_no int, end_line_no int, datalines []string)

Extract a text block which contains marker which could be an int or a list of pattern. if it is an int it is the line number. First we get the text from the line number or search for a match to the marker pattern. If we found we will search upward (to index 0) for the upper_bound_pattern, and when found, search for the lower_bound_pattern. The marker should be in the middle Return the text within the upper and lower, but not including the lower bound. Also return the line number range and full file content as datalines marker and lower is important; you can ignore upper_bound_pattern by using a empty []string{}

func FileExists

func FileExists(name string) (bool, error)

FileExists test if file 'name' exists

func FileExistsV2

func FileExistsV2(name string) error

This is short version of FileExists - meant to be use in Ternery like Ternary(FileExistsV2(path) == nil, "something", "somethingelse")

func FileNameWithoutExtension

func FileNameWithoutExtension(fileName string) string

return strings.TrimSuffix(fileName, filepath.Ext(fileName))

func FileTouch

func FileTouch(fileName string) error

FileTouch is similar the unix command 'touch'. If file does not exists, an empty file will be created

func GenRandomString

func GenRandomString(n int) string

GenRandomString generates a random string with length 'n'

func GenSelfSignedKey

func GenSelfSignedKey(keyfilename string)

Crypto utils

func Getenv

func Getenv(key, fallback string) string

func GoFindExec

func GoFindExec(directories []string, path_pattern []string, callback func(filename string) error)

GoFindExec take a directory path and list of regex pattern to match the file name. If it matches then it call the callback function for that file name. filetype is parsed from the directory prefix, file:// for file, dir:// for directory

func GoTemplateFile

func GoTemplateFile(src, dest string, data map[string]interface{}, fileMode os.FileMode)

This func use text/template to avoid un-expected html escaping.

func GoTemplateString

func GoTemplateString(srcString string, data any) string

This func use text/template to avoid un-expected html escaping.

func InsertItemAfter

func InsertItemAfter[T any](slice []T, index int, item T) []T

InsertItemAfter inserts an item into a slice after a specified index

func InsertItemBefore

func InsertItemBefore[T any](slice []T, index int, item T) []T

InsertItemBefore inserts an item into a slice before a specified index

func InterfaceToStringList

func InterfaceToStringList(in []interface{}) []string

func InterfaceToStringMap

func InterfaceToStringMap(in map[string]interface{}) map[string]string

func IsBinaryFile

func IsBinaryFile(filePath string) (bool, error)

func IsBinaryFileSimple

func IsBinaryFileSimple(filePath string) (bool, error)

func ItemExists

func ItemExists[T comparable](item T, set map[T]any) bool

Check if key of type T exists in a map[T]any

func JsonByteToMap

func JsonByteToMap(jsonByte []byte) map[string]any

JsonByteToMap take a json as []bytes and decode it into a map[string]any.

func JsonDump

func JsonDump(obj interface{}, indent string) string

func JsonDumpByte

func JsonDumpByte(obj interface{}, indent string) []byte

func JsonToMap

func JsonToMap(jsonStr string) map[string]interface{}

JsonToMap take a json string and decode it into a map[string]interface{}. Note that the value if numeric will be cast it to int64. If it is not good for your case, use the func JsonByteToMap which does not manipulate this data

func LineInFile

func LineInFile(filename string, opt *LineInfileOpt) (err error, changed bool)

Simulate ansible lineinfile module. There are some difference intentionaly to avoid confusing behaviour and reduce complexbility No option backref, the default behaviour is yes. That is when Regex is set it never add new line. To add new line use search_string or insert_after, insert_before opts. TODO bugs still when state=absent :P

func LineInLines

func LineInLines(datalines []string, search_pattern string, replace string) (output []string)

Edit line in a set of lines using simple regex and replacement

func LoadConfigIntoEnv

func LoadConfigIntoEnv(configFile string) map[string]interface{}

LoadConfigIntoEnv load the json/yaml config file 'configFile' and export env var - var name is the key and value is the json value

func MakePassword

func MakePassword(length int) string

MakePassword -

func MakeRandNum

func MakeRandNum(max int) int

MakeRandNum -

func MakeRequest

func MakeRequest(method string, config map[string]interface{}, data []byte, jar *cookiejar.Jar) map[string]interface{}

MakeRequest make a http request with method (POST or GET etc...). It support sessions - if you have existing session stored in cookie jar then pass it to the `jar` param otherwise a new cookie ja session will be created. config has these keys: - timeout - set the time out of time int. Default is 600 secs - url - the URL that the request will be sent to - token - string - the Authorization token if required. It will make the header 'Authorization' using the token - headers - a map[string]string to pass any arbitrary reuqets headers Key : Value Return value is the response. If it is a json of type list then it will be put into the key "results" This is used to make API REST requests and expect response as json. To download or do more general things, use the function Curl above instead

func MakeSalt

func MakeSalt(length int8) (salt *[]byte)

func MapKeysToSlice

func MapKeysToSlice(m map[string]interface{}) []string

Similar to the python dict.keys()

func MapLookup

func MapLookup(m map[string]any, key string, default_val any) any

MapLookup search a key in a map and return the value if found, otherwise return the default_val

func MaskCredential

func MaskCredential(inputstr string) string

Mask all credentials pattern

func Md5Sum

func Md5Sum(key string) string

func MergeAttributes

func MergeAttributes(a, b []interface{}, action string) []interface{}

Add or delete attrbs set in a to b. action can be 'add'; if it is empty it will do a delete. a and b is a list of map of items having two fields, key and value. If key does not exists in b and action is add - it will add it to b If key is matched found and If key is not nil and b will be updated or delete per action If key is nil and value matched and action is not add - the item will be removed

func Must

func Must[T any](res T, err error) T

Must wraps two values pair with second one is an error, check if error is nil then return the first, otherwise panic with error message

func MustOpenFile

func MustOpenFile(f string) *os.File

func NsToTime

func NsToTime(ns int64) time.Time

NsToTime -

func ParseConfig

func ParseConfig(configFile string) map[string]interface{}

ParseConfig loads the json/yaml config file 'configFile' into a map json is tried first and then yaml

func ParseJsonReqBodyToMap

func ParseJsonReqBodyToMap(r *http.Request) map[string]interface{}

func ParseJsonReqBodyToStruct

func ParseJsonReqBodyToStruct[T any](r *http.Request) *T

ParseJSON parses the raw JSON body from an HTTP request into the specified struct.

func ParseTimeRange

func ParseTimeRange(durationStr, tz string) (time.Time, time.Time)

Given a duration string return a tuple of start time, end time satisfy the duration. If duration string is dd/mm/yyyy hh:mm:ss - dd/mm/yyyy hh:mm:ss it simply return two time object. If duration is like 15m then endtime is now, start time is 15 minutes ago. This applies for all case if input is not parsable

func PickLinesInFile

func PickLinesInFile(filename string, line_no, count int) (lines []string)

PickLinesInFile - Pick some lines from a line number with count. If count is -1 pick to the end, -2 then to the end - 1 etc..

func RandomHex

func RandomHex(n int) (string, error)

func ReadFileToBase64Content

func ReadFileToBase64Content(filename string) string

func ReadFileToLines

func ReadFileToLines(filename string, cleanline bool) []string

ReadFileToLines will read a file and return content as a slice of lines. If cleanline is true then each line will be trim and empty line will be removed

func ReadFirstLineWithPrefix

func ReadFirstLineWithPrefix(filePath string, prefix []string) (firstLine string, temp_file, matchedPrefix string, err error)

ReadFirstLine read the first line in a file. Optimized for performance thus we do not re-use PickLinesInFile Also return the reader to the caller if caller need to

func RemoveDuplicate

func RemoveDuplicate[T comparable](slice []T) []T

RemoveDuplicate remove duplicated item in a slice

func RemoveItem

func RemoveItem(s []interface{}, i int) []interface{}

RemoveItem This func is depricated Use RemoveItemByIndex. Remove an item of the index i in a slice

func RemoveItemByIndex

func RemoveItemByIndex[T comparable](s []T, i int) []T

RemoveItemByIndex removes an item from a slice of any type. Using the index of the item.

func RemoveItemByVal

func RemoveItemByVal[T comparable](slice []T, item T) []T

RemoveItemByVal removes an item from a slice of any type

func ReplaceAllFuncN

func ReplaceAllFuncN(re *regexp.Regexp, src []byte, repl func([]int, [][]byte) []byte, n int) ([]byte, int)

ReplaceAllFuncN extends regexp.Regexp to support count of replacements for []byte

func ReplacePattern

func ReplacePattern(input []byte, pattern string, repl string, count int) ([]byte, int)

Quickly replace. Normally if you want to re-use the regex ptn then better compile the pattern first and used the standard lib regex replace func. This only save u some small typing. the 'repl' can contain capture using $1 or $2 for first group etc..

func RunDSL

func RunDSL(dbc *sql.DB, sql string) map[string]interface{}

func RunSQL

func RunSQL(dbc *sql.DB, sql string) map[string]interface{}

Run SELECT and return map[string]interface{}{"result": []interface{}, "error": error}

func RunSystemCommand

func RunSystemCommand(cmd string, verbose bool) (output string)

RunSystemCommand run the command 'cmd'. It will use 'bash -c <the-command>' thus requires bash installed On windows you need to install bash or mingw64 shell If command exec get error it will panic!

func RunSystemCommandV2

func RunSystemCommandV2(cmd string, verbose bool) (output string, err error)

RunSystemCommandV2 run the command 'cmd'. It will use 'bash -c <the-command>' thus requires bash installed On windows you need to install bash or mingw64 shell The only differrence with RunSystemCommand is that it returns an error if error happened and it wont panic

func RunSystemCommandV3

func RunSystemCommandV3(command *exec.Cmd, verbose bool) (output string, err error)

RunSystemCommandV3. Unlike the other two, this one you craft the exec.Cmd object and pass it to this function This allows you to customize the exec.Cmd object before calling this function, eg, passing more env vars into it like command.Env = append(os.Environ(), "MYVAR=MYVAL"). You might not need bash to run for example but run directly

func SearchPatternListInStrings

func SearchPatternListInStrings(datalines []string, pattern []string, start_line, max_line, direction int) (found_marker bool, start_line_no int, linestr string)

Given a list of string of regex pattern and a list of string, find the coninuous match in that input list and return the start line of the match and the line content

max_line defined the maximum line to search; set to 0 to use the len of input lines which is full

start_line is the line to start searching; set to 0 to start from begining start_line should be smaller than max_line

direction is the direction of the search -1 is upward; otherwise is down. If it is not 0 then the value is used for the step jump while searching eg. 1 for every line, 2 for every 2 lines, -2 is backward every two lines

func SearchReplaceFile

func SearchReplaceFile(filename, ptn, repl string, count int, backup bool) int

Same as ReplacePattern but do regex search and replace in a file

func SearchReplaceString

func SearchReplaceString(instring, ptn, repl string, count int) string

Same as ReplacePattern but operates on string rather than []byte

func SendMail

func SendMail(from string, to []string, subject, body string, attachmentPaths []string, smtpServerInfo, username, password string, useSSL bool) error

SendMail sends an email with a text body and multiple attachments over SSL/TLS if requested

func Sha1Sum

func Sha1Sum(in string) string

func Sha256Sum

func Sha256Sum(in string) string

func Sha512Sum

func Sha512Sum(in string) string

func Sleep

func Sleep(duration string)

func SliceMap

func SliceMap[T, V any](ts []T, fn func(T) *V) []V

Take a slice and a function return new slice with the value is the result of the function called for each item Similar to list walk in python

func SliceToMap

func SliceToMap[T comparable](slice []T) map[T]interface{}

SliceToMap convert a slice of any comparable into a map which can set the value later on

func SplitFirstLine

func SplitFirstLine(text string) (string, string)

SplitFirstLine return the first line from a text block. Line ending can be unix based or windows based The rest of the block is return also as the second output

func SplitTextByPattern

func SplitTextByPattern(text, pattern string, includeMatch bool) []string

SplitTextByPattern splits a multiline text into sections based on a regex pattern. If includeMatch is true, the matching lines are included in the result. pattern should a multiline pattern like `(?m)^Header line.*`

func Ternary

func Ternary[T any](expr bool, x, y T) T

Mimic the Ternary in other languages but only support simple form so nobody can abuse it

func Unzip

func Unzip(src, dest string) error

Unzip will unzip the 'src' file into the directory 'dest' This version is pure go - so no need to have the zip command.

func Upload

func Upload(client *http.Client, url string, values map[string]io.Reader, mimetype map[string]string, headers map[string]string) (err error)

Prepare a form that you will submit to that URL. client if it is nil then new http client will be used url is the url the POST request to values is a map which key is the postform field name. The value of the map should be any io.Reader to read data from like *os.File to post attachment etc.. mimetype if set which has the key is the file name in the values above, and the value is the mime type of that file headers is extra header in the format key/value pair. note the header 'Content-Type' should be automatically added Note: This is not working for report portal (RP) basically golang somehow send it using : Content type 'application/octet-stream' (or the server complain about that not supported). There are two parts each of them has different content type and it seems golang implementation does not fully support it? (the jsonPaths must be application-json). For whatever it is, even the header printed out correct - server complain. Curl work though so we will use curl for now I think golang behaviour is correct it should be 'application/octet-stream' for the file part, but the RP java server does not behave. So we add a manual set header map in for this case

func ValidateInterfaceWithStringKeys

func ValidateInterfaceWithStringKeys(val interface{}) (interface{}, error)

Pass an interface, return same interface if they are map of string to interface or list of string as key

func VerifyHash

func VerifyHash(password string, passwordHashString string, saltLength int) bool

func ZipDecrypt

func ZipDecrypt(filePath ...string) error

ZipDecrypt decrypt the zip file. First arg is the file name, second is the key used to encrypt it. Requires the command 'unzip' installed

func ZipEncript

func ZipEncript(filePath ...string) string

Encrypt zip files. The password will be automtically generated and return to the caller Requires command 'zip' available in the system

Types

type AppConfigProperties

type AppConfigProperties map[string]string

func ReadPropertiesFile

func ReadPropertiesFile(filename string) (AppConfigProperties, error)

ReadPropertiesFile read from a file with content format like 'key=value' and return AppConfigProperties which is a map[string]string

func ReadPropertiesString

func ReadPropertiesString(inputString string) (AppConfigProperties, error)

ReadPropertiesString read from a string with format like 'key=value' and return AppConfigProperties which is a map[string]string

type ArrayFlags

type ArrayFlags []string

ArrayFlags to be used for standard golang flag to store multiple values. Something like -f file1 -f file2 will store list of file1, file2 in the var of this type. Example:

var myvar ArrayFlags flag.Var(&myvar, "-f", "", "File names")

func (*ArrayFlags) Set

func (i *ArrayFlags) Set(value string) error

func (*ArrayFlags) String

func (i *ArrayFlags) String() string

type LineInfileOpt

type LineInfileOpt struct {
	Insertafter   string
	Insertbefore  string
	Line          string
	LineNo        int
	Path          string
	Regexp        string
	Search_string string
	State         string
	Backup        bool
	ReplaceAll    bool
}

func NewLineInfileOpt

func NewLineInfileOpt(opt *LineInfileOpt) *LineInfileOpt

type StructInfo

type StructInfo struct {
	// Name of the struct
	Name string
	// List of all struct field names
	FieldName []string
	// map lookup by field name => field type
	FieldType map[string]string
	// map lookup by field name => field value
	FieldValue map[string]any
	// map lookup by field name => the capture of struct tags. When calling ReflectStruct you give it the tagPtn
	// here is what you get by using FindAllStringSubmatch of that regex ptn.
	TagCapture map[string][][]string
}

StructInfo hold information about a struct

func ReflectStruct

func ReflectStruct(astruct any, tagPtn string) StructInfo

Give it a struct and a tag pattern to capture the tag content - return a StructInfo obj

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL