diff options
Diffstat (limited to 'utils/utils.go')
-rw-r--r-- | utils/utils.go | 116 |
1 files changed, 91 insertions, 25 deletions
diff --git a/utils/utils.go b/utils/utils.go index 07b8f6a3d0..1fe2e87b4f 100644 --- a/utils/utils.go +++ b/utils/utils.go @@ -2,6 +2,7 @@ package utils import ( "bytes" + "crypto/rand" "crypto/sha1" "crypto/sha256" "encoding/hex" @@ -24,6 +25,11 @@ import ( "time" ) +type KeyValuePair struct { + Key string + Value string +} + // A common interface to access the Fatal method of // both testing.B and testing.T. type Fataler interface { @@ -493,6 +499,34 @@ func TruncateID(id string) string { return id[:shortLen] } +// GenerateRandomID returns an unique id +func GenerateRandomID() string { + for { + id := make([]byte, 32) + if _, err := io.ReadFull(rand.Reader, id); err != nil { + panic(err) // This shouldn't happen + } + value := hex.EncodeToString(id) + // if we try to parse the truncated for as an int and we don't have + // an error then the value is all numberic and causes issues when + // used as a hostname. ref #3869 + if _, err := strconv.Atoi(TruncateID(value)); err == nil { + continue + } + return value + } +} + +func ValidateID(id string) error { + if id == "" { + return fmt.Errorf("Id can't be empty") + } + if strings.Contains(id, ":") { + return fmt.Errorf("Invalid character in id: ':'") + } + return nil +} + // Code c/c from io.Copy() modified to handle escape sequence func CopyEscapable(dst io.Writer, src io.ReadCloser) (written int64, err error) { buf := make([]byte, 32*1024) @@ -685,7 +719,7 @@ func IsURL(str string) bool { } func IsGIT(str string) bool { - return strings.HasPrefix(str, "git://") || strings.HasPrefix(str, "github.com/") + return strings.HasPrefix(str, "git://") || strings.HasPrefix(str, "github.com/") || strings.HasPrefix(str, "git@github.com:") || (strings.HasSuffix(str, ".git") && IsURL(str)) } // GetResolvConf opens and read the content of /etc/resolv.conf. @@ -702,54 +736,78 @@ func GetResolvConf() ([]byte, error) { // CheckLocalDns looks into the /etc/resolv.conf, // it returns true if there is a local nameserver or if there is no nameserver. func CheckLocalDns(resolvConf []byte) bool { - var parsedResolvConf = StripComments(resolvConf, []byte("#")) - if !bytes.Contains(parsedResolvConf, []byte("nameserver")) { - return true - } - for _, ip := range [][]byte{ - []byte("127.0.0.1"), - []byte("127.0.1.1"), - } { - if bytes.Contains(parsedResolvConf, ip) { - return true + for _, line := range GetLines(resolvConf, []byte("#")) { + if !bytes.Contains(line, []byte("nameserver")) { + continue + } + for _, ip := range [][]byte{ + []byte("127.0.0.1"), + []byte("127.0.1.1"), + } { + if bytes.Contains(line, ip) { + return true + } } + return false } - return false + return true } -// StripComments parses input into lines and strips away comments. -func StripComments(input []byte, commentMarker []byte) []byte { +// GetLines parses input into lines and strips away comments. +func GetLines(input []byte, commentMarker []byte) [][]byte { lines := bytes.Split(input, []byte("\n")) - var output []byte + var output [][]byte for _, currentLine := range lines { var commentIndex = bytes.Index(currentLine, commentMarker) if commentIndex == -1 { - output = append(output, currentLine...) + output = append(output, currentLine) } else { - output = append(output, currentLine[:commentIndex]...) + output = append(output, currentLine[:commentIndex]) } - output = append(output, []byte("\n")...) } return output } -// GetNameserversAsCIDR returns nameservers (if any) listed in -// /etc/resolv.conf as CIDR blocks (e.g., "1.2.3.4/32") -// This function's output is intended for net.ParseCIDR -func GetNameserversAsCIDR(resolvConf []byte) []string { - var parsedResolvConf = StripComments(resolvConf, []byte("#")) +// GetNameservers returns nameservers (if any) listed in /etc/resolv.conf +func GetNameservers(resolvConf []byte) []string { nameservers := []string{} re := regexp.MustCompile(`^\s*nameserver\s*(([0-9]+\.){3}([0-9]+))\s*$`) - for _, line := range bytes.Split(parsedResolvConf, []byte("\n")) { + for _, line := range GetLines(resolvConf, []byte("#")) { var ns = re.FindSubmatch(line) if len(ns) > 0 { - nameservers = append(nameservers, string(ns[1])+"/32") + nameservers = append(nameservers, string(ns[1])) } } + return nameservers +} +// GetNameserversAsCIDR returns nameservers (if any) listed in +// /etc/resolv.conf as CIDR blocks (e.g., "1.2.3.4/32") +// This function's output is intended for net.ParseCIDR +func GetNameserversAsCIDR(resolvConf []byte) []string { + nameservers := []string{} + for _, nameserver := range GetNameservers(resolvConf) { + nameservers = append(nameservers, nameserver+"/32") + } return nameservers } +// GetSearchDomains returns search domains (if any) listed in /etc/resolv.conf +// If more than one search line is encountered, only the contents of the last +// one is returned. +func GetSearchDomains(resolvConf []byte) []string { + re := regexp.MustCompile(`^\s*search\s*(([^\s]+\s*)*)$`) + domains := []string{} + for _, line := range GetLines(resolvConf, []byte("#")) { + match := re.FindSubmatch(line) + if match == nil { + continue + } + domains = strings.Fields(string(match[1])) + } + return domains +} + // FIXME: Change this not to receive default value as parameter func ParseHost(defaultHost string, defaultUnix, addr string) (string, error) { var ( @@ -1018,3 +1076,11 @@ func ReadSymlinkedDirectory(path string) (string, error) { } return realPath, nil } + +func ParseKeyValueOpt(opt string) (string, string, error) { + parts := strings.SplitN(opt, "=", 2) + if len(parts) != 2 { + return "", "", fmt.Errorf("Unable to parse key/value option: %s", opt) + } + return strings.TrimSpace(parts[0]), strings.TrimSpace(parts[1]), nil +} |