-
Notifications
You must be signed in to change notification settings - Fork 12
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
add network.[Must]GetDataNetworkIP; add popular param types. (#12)
- Loading branch information
Showing
6 changed files
with
212 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
package network | ||
|
||
import ( | ||
"fmt" | ||
"net" | ||
) | ||
|
||
// GetDataNetworkIP examines the local network interfaces, and tries to find our | ||
// assigned IP within the data network. | ||
// | ||
// This function returns the IP and a nil error if found. If running in | ||
// a sidecar-less environment, the error ErrNoTrafficShaping is returned. | ||
func (c *Client) GetDataNetworkIP() (net.IP, error) { | ||
re := c.runenv | ||
if !re.TestSidecar { | ||
return nil, ErrNoTrafficShaping | ||
} | ||
|
||
ifaces, err := net.Interfaces() | ||
if err != nil { | ||
return nil, fmt.Errorf("unable to get local network interfaces: %s", err) | ||
} | ||
|
||
for _, i := range ifaces { | ||
addrs, err := i.Addrs() | ||
if err != nil { | ||
re.RecordMessage("error getting addrs for interface: %s", err) | ||
continue | ||
} | ||
for _, a := range addrs { | ||
switch v := a.(type) { | ||
case *net.IPNet: | ||
ip := v.IP.To4() | ||
if ip == nil { | ||
re.RecordMessage("ignoring non ip4 addr %s", v) | ||
continue | ||
} | ||
if re.TestSubnet.Contains(ip) { | ||
re.RecordMessage("detected data network IP: %s", v) | ||
return v.IP, nil | ||
} else { | ||
re.RecordMessage("%s not in data subnet %s, ignoring", ip, re.TestSubnet.String()) | ||
} | ||
} | ||
} | ||
} | ||
return nil, fmt.Errorf("unable to determine data network IP. no interface found with IP in %s", re.TestSubnet.String()) | ||
} | ||
|
||
// MustGetDataNetworkIP calls GetDataNetworkIP, and panics if it | ||
// errors. It is suitable to use with runner.Invoke/InvokeMap, as long as | ||
// this method is called from the main goroutine of the test plan. | ||
func (c *Client) MustGetDataNetworkIP() net.IP { | ||
ip, err := c.GetDataNetworkIP() | ||
if err != nil { | ||
panic(err) | ||
} | ||
return ip | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
// Package ptypes contains types that are commonplace in test plan parameters. | ||
package ptypes |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
package ptypes | ||
|
||
import ( | ||
"encoding/json" | ||
"errors" | ||
"time" | ||
) | ||
|
||
// Duration wraps a time.Duration and provides JSON marshal logic. | ||
type Duration struct { | ||
time.Duration | ||
} | ||
|
||
var ( | ||
_ json.Marshaler = Duration{} | ||
_ json.Unmarshaler = &Duration{} | ||
) | ||
|
||
func (d Duration) MarshalJSON() ([]byte, error) { | ||
return json.Marshal(d.String()) | ||
} | ||
|
||
func (d *Duration) UnmarshalJSON(b []byte) error { | ||
var v interface{} | ||
if err := json.Unmarshal(b, &v); err != nil { | ||
return err | ||
} | ||
switch value := v.(type) { | ||
case float64: | ||
d.Duration = time.Duration(value) | ||
return nil | ||
case string: | ||
var err error | ||
d.Duration, err = time.ParseDuration(value) | ||
if err != nil { | ||
return err | ||
} | ||
return nil | ||
default: | ||
return errors.New("invalid duration") | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
package ptypes | ||
|
||
import ( | ||
"encoding/json" | ||
"errors" | ||
"fmt" | ||
"strconv" | ||
"strings" | ||
"time" | ||
"unicode" | ||
) | ||
|
||
// Rate is a param that's parsed as "quantity/interval", where `quantity` is a | ||
// float and `interval` is a string parsable by time.ParseDuration, e.g. "1s". | ||
// | ||
// You can omit the numeric component of the interval to default to 1, e.g. | ||
// "100/s" is the same as "100/1s". | ||
// | ||
// Examples of valid Rate strings include: "100/s", "0.5/m", "500/5m". | ||
type Rate struct { | ||
Quantity float64 | ||
Interval time.Duration | ||
} | ||
|
||
var ( | ||
_ json.Marshaler = Duration{} | ||
_ json.Unmarshaler = &Duration{} | ||
) | ||
|
||
func (r Rate) MarshalJSON() ([]byte, error) { | ||
return nil, nil | ||
} | ||
func (r *Rate) UnmarshalJSON(b []byte) error { | ||
var v interface{} | ||
if err := json.Unmarshal(b, &v); err != nil { | ||
return err | ||
} | ||
|
||
str, ok := v.(string) | ||
if !ok { | ||
return errors.New("invalid rate param, must be string") | ||
} | ||
|
||
strs := strings.Split(str, "/") | ||
if len(strs) != 2 { | ||
return errors.New("invalid rate param. Must be in format 'quantity / interval'") | ||
} | ||
|
||
q, err := strconv.ParseFloat(strs[0], 64) | ||
if err != nil { | ||
return fmt.Errorf("error parsing quantity portion of rate: %s", err) | ||
} | ||
intervalStr := strings.TrimSpace(strs[1]) | ||
if !unicode.IsDigit(rune(intervalStr[0])) { | ||
intervalStr = "1" + intervalStr | ||
} | ||
|
||
i, err := time.ParseDuration(intervalStr) | ||
if err != nil { | ||
return fmt.Errorf("error parsing interval portion of rate: %s", err) | ||
} | ||
|
||
r.Quantity = q | ||
r.Interval = i | ||
return nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
package ptypes | ||
|
||
import ( | ||
"encoding/json" | ||
"errors" | ||
|
||
"github.com/dustin/go-humanize" | ||
) | ||
|
||
// Size is a type that unmarshals human-readable binary sizes like "100 KB" | ||
// into an uint64, where the unit is bytes. | ||
type Size uint64 | ||
|
||
var ( | ||
_ json.Marshaler = Duration{} | ||
_ json.Unmarshaler = &Duration{} | ||
) | ||
|
||
func (s Size) MarshalJSON() ([]byte, error) { | ||
return nil, nil | ||
} | ||
|
||
func (s *Size) UnmarshalJSON(b []byte) error { | ||
var v interface{} | ||
if err := json.Unmarshal(b, &v); err != nil { | ||
return err | ||
} | ||
str, ok := v.(string) | ||
if !ok { | ||
return errors.New("invalid size param, must be string") | ||
} | ||
n, err := humanize.ParseBytes(str) | ||
if err != nil { | ||
return err | ||
} | ||
*s = Size(n) | ||
return nil | ||
} |