github.com/campoy/docker@v1.8.0-rc1/pkg/parsers/parsers.go (about)

     1  package parsers
     2  
     3  import (
     4  	"fmt"
     5  	"net/url"
     6  	"path"
     7  	"runtime"
     8  	"strconv"
     9  	"strings"
    10  )
    11  
    12  // FIXME: Change this not to receive default value as parameter
    13  func ParseHost(defaultTCPAddr, defaultUnixAddr, addr string) (string, error) {
    14  	addr = strings.TrimSpace(addr)
    15  	if addr == "" {
    16  		if runtime.GOOS != "windows" {
    17  			addr = fmt.Sprintf("unix://%s", defaultUnixAddr)
    18  		} else {
    19  			// Note - defaultTCPAddr already includes tcp:// prefix
    20  			addr = fmt.Sprintf("%s", defaultTCPAddr)
    21  		}
    22  	}
    23  	addrParts := strings.Split(addr, "://")
    24  	if len(addrParts) == 1 {
    25  		addrParts = []string{"tcp", addrParts[0]}
    26  	}
    27  
    28  	switch addrParts[0] {
    29  	case "tcp":
    30  		return ParseTCPAddr(addrParts[1], defaultTCPAddr)
    31  	case "unix":
    32  		return ParseUnixAddr(addrParts[1], defaultUnixAddr)
    33  	case "fd":
    34  		return addr, nil
    35  	default:
    36  		return "", fmt.Errorf("Invalid bind address format: %s", addr)
    37  	}
    38  }
    39  
    40  func ParseUnixAddr(addr string, defaultAddr string) (string, error) {
    41  	addr = strings.TrimPrefix(addr, "unix://")
    42  	if strings.Contains(addr, "://") {
    43  		return "", fmt.Errorf("Invalid proto, expected unix: %s", addr)
    44  	}
    45  	if addr == "" {
    46  		addr = defaultAddr
    47  	}
    48  	return fmt.Sprintf("unix://%s", addr), nil
    49  }
    50  
    51  func ParseTCPAddr(addr string, defaultAddr string) (string, error) {
    52  	addr = strings.TrimPrefix(addr, "tcp://")
    53  	if strings.Contains(addr, "://") || addr == "" {
    54  		return "", fmt.Errorf("Invalid proto, expected tcp: %s", addr)
    55  	}
    56  
    57  	u, err := url.Parse("tcp://" + addr)
    58  	if err != nil {
    59  		return "", err
    60  	}
    61  	hostParts := strings.Split(u.Host, ":")
    62  	if len(hostParts) != 2 {
    63  		return "", fmt.Errorf("Invalid bind address format: %s", addr)
    64  	}
    65  	host := hostParts[0]
    66  	if host == "" {
    67  		host = defaultAddr
    68  	}
    69  
    70  	p, err := strconv.Atoi(hostParts[1])
    71  	if err != nil && p == 0 {
    72  		return "", fmt.Errorf("Invalid bind address format: %s", addr)
    73  	}
    74  	return fmt.Sprintf("tcp://%s:%d%s", host, p, u.Path), nil
    75  }
    76  
    77  // Get a repos name and returns the right reposName + tag|digest
    78  // The tag can be confusing because of a port in a repository name.
    79  //     Ex: localhost.localdomain:5000/samalba/hipache:latest
    80  //     Digest ex: localhost:5000/foo/bar@sha256:bc8813ea7b3603864987522f02a76101c17ad122e1c46d790efc0fca78ca7bfb
    81  func ParseRepositoryTag(repos string) (string, string) {
    82  	n := strings.Index(repos, "@")
    83  	if n >= 0 {
    84  		parts := strings.Split(repos, "@")
    85  		return parts[0], parts[1]
    86  	}
    87  	n = strings.LastIndex(repos, ":")
    88  	if n < 0 {
    89  		return repos, ""
    90  	}
    91  	if tag := repos[n+1:]; !strings.Contains(tag, "/") {
    92  		return repos[:n], tag
    93  	}
    94  	return repos, ""
    95  }
    96  
    97  func PartParser(template, data string) (map[string]string, error) {
    98  	// ip:public:private
    99  	var (
   100  		templateParts = strings.Split(template, ":")
   101  		parts         = strings.Split(data, ":")
   102  		out           = make(map[string]string, len(templateParts))
   103  	)
   104  	if len(parts) != len(templateParts) {
   105  		return nil, fmt.Errorf("Invalid format to parse.  %s should match template %s", data, template)
   106  	}
   107  
   108  	for i, t := range templateParts {
   109  		value := ""
   110  		if len(parts) > i {
   111  			value = parts[i]
   112  		}
   113  		out[t] = value
   114  	}
   115  	return out, nil
   116  }
   117  
   118  func ParseKeyValueOpt(opt string) (string, string, error) {
   119  	parts := strings.SplitN(opt, "=", 2)
   120  	if len(parts) != 2 {
   121  		return "", "", fmt.Errorf("Unable to parse key/value option: %s", opt)
   122  	}
   123  	return strings.TrimSpace(parts[0]), strings.TrimSpace(parts[1]), nil
   124  }
   125  
   126  func ParsePortRange(ports string) (uint64, uint64, error) {
   127  	if ports == "" {
   128  		return 0, 0, fmt.Errorf("Empty string specified for ports.")
   129  	}
   130  	if !strings.Contains(ports, "-") {
   131  		start, err := strconv.ParseUint(ports, 10, 16)
   132  		end := start
   133  		return start, end, err
   134  	}
   135  
   136  	parts := strings.Split(ports, "-")
   137  	start, err := strconv.ParseUint(parts[0], 10, 16)
   138  	if err != nil {
   139  		return 0, 0, err
   140  	}
   141  	end, err := strconv.ParseUint(parts[1], 10, 16)
   142  	if err != nil {
   143  		return 0, 0, err
   144  	}
   145  	if end < start {
   146  		return 0, 0, fmt.Errorf("Invalid range specified for the Port: %s", ports)
   147  	}
   148  	return start, end, nil
   149  }
   150  
   151  func ParseLink(val string) (string, string, error) {
   152  	if val == "" {
   153  		return "", "", fmt.Errorf("empty string specified for links")
   154  	}
   155  	arr := strings.Split(val, ":")
   156  	if len(arr) > 2 {
   157  		return "", "", fmt.Errorf("bad format for links: %s", val)
   158  	}
   159  	if len(arr) == 1 {
   160  		return val, val, nil
   161  	}
   162  	// This is kept because we can actually get an HostConfig with links
   163  	// from an already created container and the format is not `foo:bar`
   164  	// but `/foo:/c1/bar`
   165  	if strings.HasPrefix(arr[0], "/") {
   166  		_, alias := path.Split(arr[1])
   167  		return arr[0][1:], alias, nil
   168  	}
   169  	return arr[0], arr[1], nil
   170  }