Skip to content

Commit

Permalink
Merge pull request #22312 from ewbankkit/add-rand-ip-address
Browse files Browse the repository at this point in the history
helper/acctest: Add function to return random IP address
  • Loading branch information
radeksimko authored Aug 8, 2019
2 parents 7861cc6 + 949a6ae commit db7d182
Show file tree
Hide file tree
Showing 2 changed files with 94 additions and 0 deletions.
36 changes: 36 additions & 0 deletions helper/acctest/random.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,13 @@ import (
"fmt"
"math/big"
"math/rand"
"net"
"strings"
"time"

"golang.org/x/crypto/ssh"

"github.com/apparentlymart/go-cidr/cidr"
)

func init() {
Expand Down Expand Up @@ -105,6 +108,39 @@ func RandTLSCert(orgName string) (string, string, error) {
return certPEM, privateKeyPEM, nil
}

// RandIpAddress returns a random IP address in the specified CIDR block.
// The prefix length must be less than 31.
func RandIpAddress(s string) (string, error) {
_, network, err := net.ParseCIDR(s)
if err != nil {
return "", err
}

firstIp, lastIp := cidr.AddressRange(network)
first := &big.Int{}
first.SetBytes([]byte(firstIp))
last := &big.Int{}
last.SetBytes([]byte(lastIp))
r := &big.Int{}
r.Sub(last, first)
if len := r.BitLen(); len > 31 {
return "", fmt.Errorf("CIDR range is too large: %d", len)
}

max := int(r.Int64())
if max == 0 {
// panic: invalid argument to Int31n
return firstIp.String(), nil
}

host, err := cidr.Host(network, RandIntRange(0, max))
if err != nil {
return "", err
}

return host.String(), nil
}

func genPrivateKey() (*rsa.PrivateKey, string, error) {
privateKey, err := rsa.GenerateKey(crand.Reader, 1024)
if err != nil {
Expand Down
58 changes: 58 additions & 0 deletions helper/acctest/random_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
package acctest

import (
"regexp"
"testing"
)

func TestRandIpAddress(t *testing.T) {
testCases := []struct {
s string
expected *regexp.Regexp
expectedErr string
}{
{
s: "1.1.1.1/32",
expected: regexp.MustCompile(`^1\.1\.1\.1$`),
},
{
s: "10.0.0.0/8",
expected: regexp.MustCompile(`^10\.\d{1,3}\.\d{1,3}\.\d{1,3}$`),
},
{
s: "0.0.0.0/0",
expectedErr: "CIDR range is too large: 32",
},
{
s: "449d:e5f1:14b1:ddf3:8525:7e9e:4a0d:4a82/128",
expected: regexp.MustCompile(`^449d:e5f1:14b1:ddf3:8525:7e9e:4a0d:4a82$`),
},
{
s: "2001:db8::/112",
expected: regexp.MustCompile(`^2001:db8::[[:xdigit:]]{1,4}$`),
},
{
s: "2001:db8::/64",
expectedErr: "CIDR range is too large: 64",
},
{
s: "abcdefg",
expectedErr: "invalid CIDR address: abcdefg",
},
}

for i, tc := range testCases {
v, err := RandIpAddress(tc.s)
if err != nil {
msg := err.Error()
if tc.expectedErr == "" {
t.Fatalf("expected test case %d to succeed but got error %q, ", i, msg)
}
if msg != tc.expectedErr {
t.Fatalf("expected test case %d to fail with %q but got %q", i, tc.expectedErr, msg)
}
} else if !tc.expected.MatchString(v) {
t.Fatalf("expected test case %d to return %q but got %q", i, tc.expected, v)
}
}
}

0 comments on commit db7d182

Please sign in to comment.