diff --git a/pkg/util/net.go b/pkg/util/net.go index 31c18a342f0..53e3c64e366 100644 --- a/pkg/util/net.go +++ b/pkg/util/net.go @@ -19,6 +19,7 @@ package util import ( "fmt" "net" + "strings" ) // IP adapts net.IP for use as a flag. @@ -29,9 +30,26 @@ func (ip IP) String() string { } func (ip *IP) Set(value string) error { - *ip = IP(net.ParseIP(value)) + *ip = IP(net.ParseIP(strings.TrimSpace(value))) if *ip == nil { return fmt.Errorf("invalid IP address: '%s'", value) } return nil } + +// IPNet adapts net.IPNet for use as a flag. +type IPNet net.IPNet + +func (ipnet IPNet) String() string { + n := net.IPNet(ipnet) + return n.String() +} + +func (ipnet *IPNet) Set(value string) error { + _, n, err := net.ParseCIDR(strings.TrimSpace(value)) + if err != nil { + return err + } + *ipnet = IPNet(*n) + return nil +} diff --git a/pkg/util/net_test.go b/pkg/util/net_test.go new file mode 100644 index 00000000000..972770f1260 --- /dev/null +++ b/pkg/util/net_test.go @@ -0,0 +1,106 @@ +/* +Copyright 2014 Google Inc. All rights reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package util + +import ( + "flag" + "testing" +) + +func TestIP(t *testing.T) { + testCases := []struct { + input string + success bool + expected string + }{ + {"0.0.0.0", true, "0.0.0.0"}, + {" 0.0.0.0 ", true, "0.0.0.0"}, + {"1.2.3.4", true, "1.2.3.4"}, + {"127.0.0.1", true, "127.0.0.1"}, + {"255.255.255.255", true, "255.255.255.255"}, + {"", false, ""}, + {"0", false, ""}, + {"localhost", false, ""}, + {"0.0.0", false, ""}, + {"0.0.0.", false, ""}, + {"0.0.0.0.", false, ""}, + {"0.0.0.256", false, ""}, + {"0 . 0 . 0 . 0", false, ""}, + } + + for i := range testCases { + tc := &testCases[i] + var f flag.Value = &IP{} + err := f.Set(tc.input) + if err != nil && tc.success == true { + t.Errorf("expected success, got %q", err) + continue + } else if err == nil && tc.success == false { + t.Errorf("expected failure") + continue + } else if tc.success { + if f.String() != tc.expected { + t.Errorf("expected %q, got %q", tc.expected, f.String()) + } + } + } +} + +func TestIPNet(t *testing.T) { + testCases := []struct { + input string + success bool + expected string + }{ + {"0.0.0.0/0", true, "0.0.0.0/0"}, + {" 0.0.0.0/0 ", true, "0.0.0.0/0"}, + {"1.2.3.4/8", true, "1.0.0.0/8"}, + {"127.0.0.1/16", true, "127.0.0.0/16"}, + {"255.255.255.255/19", true, "255.255.224.0/19"}, + {"255.255.255.255/32", true, "255.255.255.255/32"}, + {"", false, ""}, + {"/0", false, ""}, + {"0", false, ""}, + {"0/0", false, ""}, + {"localhost/0", false, ""}, + {"0.0.0/4", false, ""}, + {"0.0.0./8", false, ""}, + {"0.0.0.0./12", false, ""}, + {"0.0.0.256/16", false, ""}, + {"0.0.0.0 /20", false, ""}, + {"0.0.0.0/ 24", false, ""}, + {"0 . 0 . 0 . 0 / 28", false, ""}, + {"0.0.0.0/33", false, ""}, + } + + for i := range testCases { + tc := &testCases[i] + var f flag.Value = &IPNet{} + err := f.Set(tc.input) + if err != nil && tc.success == true { + t.Errorf("expected success, got %q", err) + continue + } else if err == nil && tc.success == false { + t.Errorf("expected failure") + continue + } else if tc.success { + if f.String() != tc.expected { + t.Errorf("expected %q, got %q", tc.expected, f.String()) + } + } + } +}