123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141 |
- // Package parsers provides helper functions to parse and validate different type
- // of string. It can be hosts, unix addresses, tcp addresses, filters, kernel
- // operating system versions.
- package parsers
- import (
- "fmt"
- "path"
- "strconv"
- "strings"
- )
- // PartParser parses and validates the specified string (data) using the specified template
- // e.g. ip:public:private -> 192.168.0.1:80:8000
- func PartParser(template, data string) (map[string]string, error) {
- // ip:public:private
- var (
- templateParts = strings.Split(template, ":")
- parts = strings.Split(data, ":")
- out = make(map[string]string, len(templateParts))
- )
- if len(parts) != len(templateParts) {
- return nil, fmt.Errorf("Invalid format to parse. %s should match template %s", data, template)
- }
- for i, t := range templateParts {
- value := ""
- if len(parts) > i {
- value = parts[i]
- }
- out[t] = value
- }
- return out, nil
- }
- // ParseKeyValueOpt parses and validates the specified string as a key/value pair (key=value)
- 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
- }
- // ParsePortRange parses and validates the specified string as a port-range (8000-9000)
- func ParsePortRange(ports string) (uint64, uint64, error) {
- if ports == "" {
- return 0, 0, fmt.Errorf("Empty string specified for ports.")
- }
- if !strings.Contains(ports, "-") {
- start, err := strconv.ParseUint(ports, 10, 16)
- end := start
- return start, end, err
- }
- parts := strings.Split(ports, "-")
- start, err := strconv.ParseUint(parts[0], 10, 16)
- if err != nil {
- return 0, 0, err
- }
- end, err := strconv.ParseUint(parts[1], 10, 16)
- if err != nil {
- return 0, 0, err
- }
- if end < start {
- return 0, 0, fmt.Errorf("Invalid range specified for the Port: %s", ports)
- }
- return start, end, nil
- }
- // ParseLink parses and validates the specified string as a link format (name:alias)
- func ParseLink(val string) (string, string, error) {
- if val == "" {
- return "", "", fmt.Errorf("empty string specified for links")
- }
- arr := strings.Split(val, ":")
- if len(arr) > 2 {
- return "", "", fmt.Errorf("bad format for links: %s", val)
- }
- if len(arr) == 1 {
- return val, val, nil
- }
- // This is kept because we can actually get an HostConfig with links
- // from an already created container and the format is not `foo:bar`
- // but `/foo:/c1/bar`
- if strings.HasPrefix(arr[0], "/") {
- _, alias := path.Split(arr[1])
- return arr[0][1:], alias, nil
- }
- return arr[0], arr[1], nil
- }
- // ParseUintList parses and validates the specified string as the value
- // found in some cgroup file (e.g. `cpuset.cpus`, `cpuset.mems`), which could be
- // one of the formats below. Note that duplicates are actually allowed in the
- // input string. It returns a `map[int]bool` with available elements from `val`
- // set to `true`.
- // Supported formats:
- // 7
- // 1-6
- // 0,3-4,7,8-10
- // 0-0,0,1-7
- // 03,1-3 <- this is gonna get parsed as [1,2,3]
- // 3,2,1
- // 0-2,3,1
- func ParseUintList(val string) (map[int]bool, error) {
- if val == "" {
- return map[int]bool{}, nil
- }
- availableInts := make(map[int]bool)
- split := strings.Split(val, ",")
- errInvalidFormat := fmt.Errorf("invalid format: %s", val)
- for _, r := range split {
- if !strings.Contains(r, "-") {
- v, err := strconv.Atoi(r)
- if err != nil {
- return nil, errInvalidFormat
- }
- availableInts[v] = true
- } else {
- split := strings.SplitN(r, "-", 2)
- min, err := strconv.Atoi(split[0])
- if err != nil {
- return nil, errInvalidFormat
- }
- max, err := strconv.Atoi(split[1])
- if err != nil {
- return nil, errInvalidFormat
- }
- if max < min {
- return nil, errInvalidFormat
- }
- for i := min; i <= max; i++ {
- availableInts[i] = true
- }
- }
- }
- return availableInts, nil
- }
|