435c0d9fc8
This PR switches the Nomad repository from using govendor to Go modules for managing dependencies. Aspects of the Nomad workflow remain pretty much the same. The usual Makefile targets should continue to work as they always did. The API submodule simply defers to the parent Nomad version on the repository, keeping the semantics of API versioning that currently exists.
186 lines
3.3 KiB
Go
186 lines
3.3 KiB
Go
package util
|
|
|
|
import (
|
|
"bytes"
|
|
srand "crypto/rand"
|
|
"encoding/binary"
|
|
"encoding/json"
|
|
"fmt"
|
|
"math/rand"
|
|
"net/http"
|
|
"net/url"
|
|
"sort"
|
|
"time"
|
|
)
|
|
|
|
const dictionary = "_0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
|
|
|
|
//CreateRandomString create random string
|
|
func CreateRandomString() string {
|
|
b := make([]byte, 32)
|
|
l := len(dictionary)
|
|
|
|
_, err := srand.Read(b)
|
|
|
|
if err != nil {
|
|
// fail back to insecure rand
|
|
rand.Seed(time.Now().UnixNano())
|
|
for i := range b {
|
|
b[i] = dictionary[rand.Int()%l]
|
|
}
|
|
} else {
|
|
for i, v := range b {
|
|
b[i] = dictionary[v%byte(l)]
|
|
}
|
|
}
|
|
|
|
return string(b)
|
|
}
|
|
|
|
// Encode encodes the values into ``URL encoded'' form
|
|
// ("acl&bar=baz&foo=quux") sorted by key.
|
|
func Encode(v url.Values) string {
|
|
if v == nil {
|
|
return ""
|
|
}
|
|
var buf bytes.Buffer
|
|
keys := make([]string, 0, len(v))
|
|
for k := range v {
|
|
keys = append(keys, k)
|
|
}
|
|
sort.Strings(keys)
|
|
for _, k := range keys {
|
|
vs := v[k]
|
|
prefix := url.QueryEscape(k)
|
|
for _, v := range vs {
|
|
if buf.Len() > 0 {
|
|
buf.WriteByte('&')
|
|
}
|
|
buf.WriteString(prefix)
|
|
if v != "" {
|
|
buf.WriteString("=")
|
|
buf.WriteString(url.QueryEscape(v))
|
|
}
|
|
}
|
|
}
|
|
return buf.String()
|
|
}
|
|
|
|
// Like Encode, but key and value are not escaped
|
|
func EncodeWithoutEscape(v url.Values) string {
|
|
if v == nil {
|
|
return ""
|
|
}
|
|
var buf bytes.Buffer
|
|
keys := make([]string, 0, len(v))
|
|
for k := range v {
|
|
keys = append(keys, k)
|
|
}
|
|
sort.Strings(keys)
|
|
for _, k := range keys {
|
|
vs := v[k]
|
|
prefix := k
|
|
for _, v := range vs {
|
|
if buf.Len() > 0 {
|
|
buf.WriteByte('&')
|
|
}
|
|
buf.WriteString(prefix)
|
|
if v != "" {
|
|
buf.WriteString("=")
|
|
buf.WriteString(v)
|
|
}
|
|
}
|
|
}
|
|
return buf.String()
|
|
}
|
|
|
|
func GetGMTime() string {
|
|
return time.Now().UTC().Format(http.TimeFormat)
|
|
}
|
|
|
|
//
|
|
|
|
func randUint32() uint32 {
|
|
return randUint32Slice(1)[0]
|
|
}
|
|
|
|
func randUint32Slice(c int) []uint32 {
|
|
b := make([]byte, c*4)
|
|
|
|
_, err := srand.Read(b)
|
|
|
|
if err != nil {
|
|
// fail back to insecure rand
|
|
rand.Seed(time.Now().UnixNano())
|
|
for i := range b {
|
|
b[i] = byte(rand.Int())
|
|
}
|
|
}
|
|
|
|
n := make([]uint32, c)
|
|
|
|
for i := range n {
|
|
n[i] = binary.BigEndian.Uint32(b[i*4 : i*4+4])
|
|
}
|
|
|
|
return n
|
|
}
|
|
|
|
func toByte(n uint32, st, ed byte) byte {
|
|
return byte(n%uint32(ed-st+1) + uint32(st))
|
|
}
|
|
|
|
func toDigit(n uint32) byte {
|
|
return toByte(n, '0', '9')
|
|
}
|
|
|
|
func toLowerLetter(n uint32) byte {
|
|
return toByte(n, 'a', 'z')
|
|
}
|
|
|
|
func toUpperLetter(n uint32) byte {
|
|
return toByte(n, 'A', 'Z')
|
|
}
|
|
|
|
type convFunc func(uint32) byte
|
|
|
|
var convFuncs = []convFunc{toDigit, toLowerLetter, toUpperLetter}
|
|
|
|
// tools for generating a random ECS instance password
|
|
// from 8 to 30 char MUST contain digit upper, case letter and upper case letter
|
|
// http://docs.aliyun.com/#/pub/ecs/open-api/instance&createinstance
|
|
func GenerateRandomECSPassword() string {
|
|
|
|
// [8, 30]
|
|
l := int(randUint32()%23 + 8)
|
|
|
|
n := randUint32Slice(l)
|
|
|
|
b := make([]byte, l)
|
|
|
|
b[0] = toDigit(n[0])
|
|
b[1] = toLowerLetter(n[1])
|
|
b[2] = toUpperLetter(n[2])
|
|
|
|
for i := 3; i < l; i++ {
|
|
b[i] = convFuncs[n[i]%3](n[i])
|
|
}
|
|
|
|
s := make([]byte, l)
|
|
perm := rand.Perm(l)
|
|
for i, v := range perm {
|
|
s[v] = b[i]
|
|
}
|
|
|
|
return string(s)
|
|
|
|
}
|
|
|
|
func PrettyJson(object interface{}) string {
|
|
b, err := json.MarshalIndent(object, "", " ")
|
|
if err != nil {
|
|
fmt.Printf("ERROR: PrettyJson, %v\n %s\n", err, b)
|
|
}
|
|
return string(b)
|
|
}
|