github.com/uber/kraken@v0.1.4/utils/netutil/netutil.go (about)

     1  // Copyright (c) 2016-2019 Uber Technologies, Inc.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  package netutil
    15  
    16  import (
    17  	"errors"
    18  	"fmt"
    19  	"net"
    20  	"time"
    21  )
    22  
    23  // _supportedInterfaces is an ordered list of ip interfaces from which
    24  // host ip is determined.
    25  var _supportedInterfaces = []string{"eth0", "ib0"}
    26  
    27  func min(a, b time.Duration) time.Duration {
    28  	if a < b {
    29  		return a
    30  	}
    31  	return b
    32  }
    33  
    34  // WithRetry executes f maxRetries times until it returns non-nil error, sleeping
    35  // for the given delay between retries with exponential backoff until maxDelay is
    36  // reached.
    37  func WithRetry(maxRetries uint, delay time.Duration, maxDelay time.Duration, f func() error) error {
    38  	var retries uint
    39  	for {
    40  		err := f()
    41  		if err == nil {
    42  			return nil
    43  		}
    44  		if retries > maxRetries {
    45  			return err
    46  		}
    47  		time.Sleep(min(delay*(1<<retries), maxDelay))
    48  		retries++
    49  	}
    50  }
    51  
    52  // GetIP looks up the ip of host.
    53  func GetIP(host string) (net.IP, error) {
    54  	ips, err := net.LookupIP(host)
    55  	if err != nil {
    56  		return nil, fmt.Errorf("net: %s", err)
    57  	}
    58  	for _, ip := range ips {
    59  		if ip == nil || ip.IsLoopback() {
    60  			continue
    61  		}
    62  		return ip, nil
    63  	}
    64  	return nil, errors.New("no ips found")
    65  }
    66  
    67  // GetLocalIP returns the ip address of the local machine.
    68  func GetLocalIP() (string, error) {
    69  	ifaces, err := net.Interfaces()
    70  	if err != nil {
    71  		return "", fmt.Errorf("interfaces: %s", err)
    72  	}
    73  	ips := map[string]string{}
    74  	for _, i := range ifaces {
    75  		addrs, err := i.Addrs()
    76  		if err != nil {
    77  			return "", fmt.Errorf("addrs: %s", err)
    78  		}
    79  		for _, addr := range addrs {
    80  			var ip net.IP
    81  			switch v := addr.(type) {
    82  			case *net.IPNet:
    83  				ip = v.IP
    84  			case *net.IPAddr:
    85  				ip = v.IP
    86  			}
    87  			if ip == nil || ip.IsLoopback() {
    88  				continue
    89  			}
    90  			ip = ip.To4()
    91  			if ip == nil {
    92  				continue
    93  			}
    94  			ips[i.Name] = ip.String()
    95  			break
    96  		}
    97  	}
    98  	for _, i := range _supportedInterfaces {
    99  		if ip, ok := ips[i]; ok {
   100  			return ip, nil
   101  		}
   102  	}
   103  	return "", errors.New("no ip found")
   104  }