From 36d5eb0a479ea0cf090be92c248a62fa31fe772a Mon Sep 17 00:00:00 2001 From: "W. Trevor King" Date: Wed, 19 Sep 2018 11:42:19 -0700 Subject: [PATCH 1/2] pkg/ipnet: Teach IPNet.String() to handle nil receivers Instead of panicking. This makes some comparisons easier, as you can see from the test changes. --- pkg/ipnet/ipnet.go | 9 +++++++++ pkg/ipnet/ipnet_test.go | 18 +++++++----------- 2 files changed, 16 insertions(+), 11 deletions(-) diff --git a/pkg/ipnet/ipnet.go b/pkg/ipnet/ipnet.go index 48ca01e6706..e6a4c3e4f5e 100644 --- a/pkg/ipnet/ipnet.go +++ b/pkg/ipnet/ipnet.go @@ -16,6 +16,15 @@ type IPNet struct { net.IPNet } +// String returns a CIDR serialization of the subnet, or an empty +// string if the subnet is nil. +func (ipnet *IPNet) String() string { + if ipnet == nil { + return "" + } + return ipnet.IPNet.String() +} + // MarshalJSON interface for an IPNet func (ipnet IPNet) MarshalJSON() (data []byte, err error) { if reflect.DeepEqual(ipnet.IPNet, emptyIPNet) { diff --git a/pkg/ipnet/ipnet_test.go b/pkg/ipnet/ipnet_test.go index 94b927d6f47..a072a4a907e 100644 --- a/pkg/ipnet/ipnet_test.go +++ b/pkg/ipnet/ipnet_test.go @@ -38,23 +38,19 @@ func TestUnmarshal(t *testing.T) { Mask: net.IPv4Mask(255, 255, 255, 0), }}, } { - data, err := json.Marshal(ipNetIn) - if err != nil { - t.Fatal(err) - } + t.Run(ipNetIn.String(), func(t *testing.T) { + data, err := json.Marshal(ipNetIn) + if err != nil { + t.Fatal(err) + } - t.Run(string(data), func(t *testing.T) { var ipNetOut *IPNet - err := json.Unmarshal(data, &ipNetOut) + err = json.Unmarshal(data, &ipNetOut) if err != nil { t.Fatal(err) } - if ipNetIn == nil { - if ipNetOut != nil { - t.Fatalf("%v != %v", ipNetOut, ipNetIn) - } - } else if ipNetOut.String() != ipNetIn.String() { + if ipNetOut.String() != ipNetIn.String() { t.Fatalf("%v != %v", ipNetOut, ipNetIn) } }) From 06739c665e9d3bc9b813ad873bed862a5bde24f1 Mon Sep 17 00:00:00 2001 From: "W. Trevor King" Date: Tue, 18 Sep 2018 13:42:00 -0700 Subject: [PATCH 2/2] pkg/ipnet: Add DeepCopy and DeepCopyInto for IPNet Devan needs DeepCopyInto on IPNet as part of embed our types into Hive's ClusterDeployment CRD [1]. You could generate these with deepcopy-gen [2], but setting up automatic code generation is a bit heavy for just these methods [3], so we're hand-coding for now. [1]: https://github.com/openshift/installer/issues/256#issue-360875062 [2]: https://godoc.org/k8s.io/gengo/examples/deepcopy-gen [3]: https://github.com/openshift/installer/pull/276#issuecomment-422871376 --- pkg/ipnet/ipnet.go | 20 ++++++++++++++++++++ pkg/ipnet/ipnet_test.go | 39 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 59 insertions(+) diff --git a/pkg/ipnet/ipnet.go b/pkg/ipnet/ipnet.go index e6a4c3e4f5e..fc66cd9360b 100644 --- a/pkg/ipnet/ipnet.go +++ b/pkg/ipnet/ipnet.go @@ -25,6 +25,26 @@ func (ipnet *IPNet) String() string { return ipnet.IPNet.String() } +// DeepCopyInto copies the receiver into out. out must be non-nil. +func (ipnet *IPNet) DeepCopyInto(out *IPNet) { + if ipnet == nil { + *out = *new(IPNet) + } else { + *out = *ipnet + } + return +} + +// DeepCopy copies the receiver, creating a new IPNet. +func (ipnet *IPNet) DeepCopy() *IPNet { + if ipnet == nil { + return nil + } + out := new(IPNet) + ipnet.DeepCopyInto(out) + return out +} + // MarshalJSON interface for an IPNet func (ipnet IPNet) MarshalJSON() (data []byte, err error) { if reflect.DeepEqual(ipnet.IPNet, emptyIPNet) { diff --git a/pkg/ipnet/ipnet_test.go b/pkg/ipnet/ipnet_test.go index a072a4a907e..e12f3abaaef 100644 --- a/pkg/ipnet/ipnet_test.go +++ b/pkg/ipnet/ipnet_test.go @@ -56,3 +56,42 @@ func TestUnmarshal(t *testing.T) { }) } } + +func TestDeepCopy(t *testing.T) { + for _, ipNetIn := range []*IPNet{ + {}, + {IPNet: net.IPNet{ + IP: net.IP{192, 168, 0, 10}, + Mask: net.IPv4Mask(255, 255, 255, 0), + }}, + } { + t.Run(ipNetIn.String(), func(t *testing.T) { + t.Run("DeepCopyInto", func(t *testing.T) { + ipNetOut := &IPNet{IPNet: net.IPNet{ + IP: net.IP{10, 0, 0, 0}, + Mask: net.IPv4Mask(255, 0, 0, 0), + }} + + ipNetIn.DeepCopyInto(ipNetOut) + if ipNetOut.String() != ipNetIn.String() { + t.Fatalf("%v != %v", ipNetOut, ipNetIn) + } + }) + + t.Run("DeepCopy", func(t *testing.T) { + ipNetOut := ipNetIn.DeepCopy() + if ipNetOut.String() != ipNetIn.String() { + t.Fatalf("%v != %v", ipNetOut, ipNetIn) + } + + ipNetIn.IPNet = net.IPNet{ + IP: net.IP{192, 168, 10, 10}, + Mask: net.IPv4Mask(255, 255, 255, 255), + } + if ipNetOut.String() == ipNetIn.String() { + t.Fatalf("%v (%q) == %v (%q)", ipNetOut, ipNetOut.String(), ipNetIn, ipNetIn.String()) + } + }) + }) + } +}