Skip to content

Commit 6c8e028

Browse files
authored
Add ptr package (#443)
This has a helper utility wrapper for pointers. We want this to help make it a bit cleaner when dealing with pointers and trying to prevent nil pointer dereferences.
1 parent b602f43 commit 6c8e028

File tree

3 files changed

+161
-2
lines changed

3 files changed

+161
-2
lines changed

cloud/ociutil/ptr/from_ptr.go

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
package ptr
2+
3+
import infrastructurev1beta2 "github.com/oracle/cluster-api-provider-oci/api/v1beta2"
4+
5+
// ToString returns string value dereferenced if the passed
6+
// in pointer was not nil. Returns a string zero value if the
7+
// pointer was nil.
8+
func ToString(p *string) (v string) {
9+
if p == nil {
10+
return v
11+
}
12+
13+
return *p
14+
}
15+
16+
// ToStringSlice returns a slice of string values, that are
17+
// dereferenced if the passed in pointer was not nil. Returns a string
18+
// zero value if the pointer was nil.
19+
func ToStringSlice(vs []*string) []string {
20+
ps := make([]string, len(vs))
21+
for i, v := range vs {
22+
ps[i] = ToString(v)
23+
}
24+
25+
return ps
26+
}
27+
28+
// ToNSGSlice returns a slice of NSG values, that are
29+
// dereferenced if the passed in pointer was not nil. Returns an empty slice
30+
// zero value if the pointer was nil.
31+
func ToNSGSlice(vs []*infrastructurev1beta2.NSG) []infrastructurev1beta2.NSG {
32+
ps := make([]infrastructurev1beta2.NSG, len(vs))
33+
for i, v := range vs {
34+
if v != nil {
35+
ps[i] = *v
36+
}
37+
}
38+
39+
return ps
40+
}

cloud/ociutil/ptr/from_ptr_test.go

Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
package ptr
2+
3+
import (
4+
"testing"
5+
6+
infrastructurev1beta2 "github.com/oracle/cluster-api-provider-oci/api/v1beta2"
7+
)
8+
9+
func TestToString(t *testing.T) {
10+
tests := []struct {
11+
name string
12+
input *string
13+
want string
14+
}{
15+
{
16+
name: "nil pointer",
17+
input: nil,
18+
want: "",
19+
},
20+
{
21+
name: "non-nil pointer",
22+
input: func() *string { s := "test"; return &s }(),
23+
want: "test",
24+
},
25+
}
26+
27+
for _, tt := range tests {
28+
t.Run(tt.name, func(t *testing.T) {
29+
if got := ToString(tt.input); got != tt.want {
30+
t.Errorf("ToString() = %v, want %v", got, tt.want)
31+
}
32+
})
33+
}
34+
}
35+
36+
func TestToStringSlice(t *testing.T) {
37+
tests := []struct {
38+
name string
39+
input []*string
40+
want []string
41+
}{
42+
{
43+
name: "nil slice",
44+
input: nil,
45+
want: []string{},
46+
},
47+
{
48+
name: "empty slice",
49+
input: []*string{},
50+
want: []string{},
51+
},
52+
{
53+
name: "slice with nil elements",
54+
input: []*string{nil, nil},
55+
want: []string{"", ""},
56+
},
57+
{
58+
name: "slice with non-nil elements",
59+
input: []*string{func() *string { s := "test1"; return &s }(), func() *string { s := "test2"; return &s }()},
60+
want: []string{"test1", "test2"},
61+
},
62+
{
63+
name: "slice with mixed nil and non-nil elements",
64+
input: []*string{nil, func() *string { s := "test"; return &s }(), nil},
65+
want: []string{"", "test", ""},
66+
},
67+
}
68+
69+
for _, tt := range tests {
70+
t.Run(tt.name, func(t *testing.T) {
71+
if got := ToStringSlice(tt.input); len(got) != len(tt.want) || (len(got) > 0 && got[0] != tt.want[0]) {
72+
t.Errorf("ToStringSlice() = %v, want %v", got, tt.want)
73+
}
74+
})
75+
}
76+
}
77+
78+
func TestToNSGSlice(t *testing.T) {
79+
tests := []struct {
80+
name string
81+
input []*infrastructurev1beta2.NSG
82+
want []infrastructurev1beta2.NSG
83+
}{
84+
{
85+
name: "nil slice",
86+
input: nil,
87+
want: []infrastructurev1beta2.NSG{},
88+
},
89+
{
90+
name: "empty slice",
91+
input: []*infrastructurev1beta2.NSG{},
92+
want: []infrastructurev1beta2.NSG{},
93+
},
94+
{
95+
name: "slice with nil elements",
96+
input: []*infrastructurev1beta2.NSG{nil, nil},
97+
want: []infrastructurev1beta2.NSG{{}, {}},
98+
},
99+
{
100+
name: "slice with non-nil elements",
101+
input: []*infrastructurev1beta2.NSG{&infrastructurev1beta2.NSG{}, &infrastructurev1beta2.NSG{}},
102+
want: []infrastructurev1beta2.NSG{{}, {}},
103+
},
104+
{
105+
name: "slice with mixed nil and non-nil elements",
106+
input: []*infrastructurev1beta2.NSG{nil, &infrastructurev1beta2.NSG{}, nil},
107+
want: []infrastructurev1beta2.NSG{{}, {}, {}},
108+
},
109+
}
110+
111+
for _, tt := range tests {
112+
t.Run(tt.name, func(t *testing.T) {
113+
if got := ToNSGSlice(tt.input); len(got) != len(tt.want) {
114+
t.Errorf("ToNSGSlice() length = %v, want %v", len(got), len(tt.want))
115+
}
116+
})
117+
}
118+
}

cloud/scope/load_balancer_reconciler.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import (
2222

2323
infrastructurev1beta2 "github.com/oracle/cluster-api-provider-oci/api/v1beta2"
2424
"github.com/oracle/cluster-api-provider-oci/cloud/ociutil"
25+
"github.com/oracle/cluster-api-provider-oci/cloud/ociutil/ptr"
2526
"github.com/oracle/oci-go-sdk/v65/common"
2627
"github.com/oracle/oci-go-sdk/v65/loadbalancer"
2728
"github.com/pkg/errors"
@@ -183,8 +184,8 @@ func (s *ClusterScope) CreateLB(ctx context.Context, lb infrastructurev1beta2.Lo
183184
DefinedTags: s.GetDefinedTags(),
184185
}
185186
nsgs := make([]string, 0)
186-
for _, nsg := range s.OCIClusterAccessor.GetNetworkSpec().Vcn.NetworkSecurityGroup.List {
187-
if nsg != nil && nsg.Role == infrastructurev1beta2.ControlPlaneEndpointRole {
187+
for _, nsg := range ptr.ToNSGSlice(s.OCIClusterAccessor.GetNetworkSpec().Vcn.NetworkSecurityGroup.List) {
188+
if nsg.Role == infrastructurev1beta2.ControlPlaneEndpointRole {
188189
if nsg.ID != nil {
189190
nsgs = append(nsgs, *nsg.ID)
190191
}

0 commit comments

Comments
 (0)