@@ -5,6 +5,7 @@ package v1alpha1
55
66import (
77 "context"
8+ "errors"
89 "fmt"
910 "net"
1011 "net/netip"
@@ -13,6 +14,8 @@ import (
1314 kclient "sigs.k8s.io/controller-runtime/pkg/client"
1415)
1516
17+ var ErrInvalidGW = errors .New ("invalid gateway" )
18+
1619// NOTE: json tags are required. Any new fields you add must have json tags for the fields to be serialized.
1720
1821// GatewaySpec defines the desired state of Gateway.
@@ -88,92 +91,92 @@ func (gw *Gateway) Default() {
8891func (gw * Gateway ) Validate (ctx context.Context , kube kclient.Reader ) error {
8992 protoIP , err := netip .ParsePrefix (gw .Spec .ProtocolIP )
9093 if err != nil {
91- return fmt .Errorf ("invalid ProtocolIP %s: %w" , gw .Spec .ProtocolIP , err )
94+ return fmt .Errorf ("invalid ProtocolIP %s: %w" , gw .Spec .ProtocolIP , errors . Join ( err , ErrInvalidGW ) )
9295 }
9396 if protoIP .Bits () != 32 {
94- return fmt .Errorf ("ProtocolIP %s must be a /32 prefix" , gw .Spec .ProtocolIP ) //nolint:goerr113
97+ return fmt .Errorf ("ProtocolIP %s must be a /32 prefix: %w " , gw .Spec .ProtocolIP , ErrInvalidGW )
9598 }
9699 if ! protoIP .Addr ().Is4 () {
97- return fmt .Errorf ("ProtocolIP %s must be an IPv4 address" , gw .Spec .ProtocolIP ) //nolint:goerr113
100+ return fmt .Errorf ("ProtocolIP %s must be an IPv4 address: %w " , gw .Spec .ProtocolIP , ErrInvalidGW )
98101 }
99102
100103 vtepIP , err := netip .ParsePrefix (gw .Spec .VTEPIP )
101104 if err != nil {
102- return fmt .Errorf ("invalid VTEPIP %s: %w" , gw .Spec .VTEPIP , err )
105+ return fmt .Errorf ("invalid VTEPIP %s: %w" , gw .Spec .VTEPIP , errors . Join ( err , ErrInvalidGW ) )
103106 }
104107 if vtepIP .Bits () != 32 {
105- return fmt .Errorf ("VTEPIP %s must be a /32 prefix" , gw .Spec .VTEPIP ) //nolint:goerr113
108+ return fmt .Errorf ("VTEPIP %s must be a /32 prefix: %w " , gw .Spec .VTEPIP , ErrInvalidGW )
106109 }
107110 if ! vtepIP .Addr ().Is4 () {
108- return fmt .Errorf ("VTEPIP %s must be an IPv4 address" , gw .Spec .VTEPIP ) //nolint:goerr113
111+ return fmt .Errorf ("VTEPIP %s must be an IPv4 address: %w " , gw .Spec .VTEPIP , ErrInvalidGW )
109112 }
110113 if vtepIP .Addr ().IsMulticast () || vtepIP .Addr ().IsLoopback () || vtepIP .Addr ().IsUnspecified () {
111- return fmt .Errorf ("VTEPIP %s must be a unicast IPv4 address" , gw .Spec .VTEPIP ) //nolint:goerr113
114+ return fmt .Errorf ("VTEPIP %s must be a unicast IPv4 address: %w " , gw .Spec .VTEPIP , ErrInvalidGW )
112115 }
113116 localhostNet , err := netip .ParsePrefix ("127.0.0.0/8" )
114117 if err != nil {
115118 return fmt .Errorf ("internal error: cannot parse localhost network: %w" , err )
116119 }
117120 if localhostNet .Contains (vtepIP .Addr ()) {
118- return fmt .Errorf ("VTEPIP %s must not be in the localhost range" , gw .Spec .VTEPIP ) //nolint:goerr113
121+ return fmt .Errorf ("VTEPIP %s must not be in the localhost range: %w " , gw .Spec .VTEPIP , ErrInvalidGW )
119122 }
120123
121124 if gw .Spec .VTEPMAC == "" {
122- return fmt .Errorf ("VTEPMAC must be set" ) //nolint:goerr113
125+ return fmt .Errorf ("VTEPMAC must be set: %w" , ErrInvalidGW )
123126 }
124127 vtepMAC , err := net .ParseMAC (gw .Spec .VTEPMAC )
125128 if err != nil {
126- return fmt .Errorf ("invalid VTEPMAC %s: %w" , gw .Spec .VTEPMAC , err )
129+ return fmt .Errorf ("invalid VTEPMAC %s: %w" , gw .Spec .VTEPMAC , errors . Join ( err , ErrInvalidGW ) )
127130 }
128131 if vtepMAC .String () == "00:00:00:00:00:00" {
129- return fmt .Errorf ("VTEPMAC must not be all zeros" ) //nolint:goerr113
132+ return fmt .Errorf ("VTEPMAC must not be all zeros: %w" , ErrInvalidGW )
130133 }
131134 if (vtepMAC [0 ] & 1 ) == 1 {
132- return fmt .Errorf ("VTEPMAC %s must be a unicast MAC address" , gw .Spec .VTEPMAC ) //nolint:goerr113
135+ return fmt .Errorf ("VTEPMAC %s must be a unicast MAC address: %w " , gw .Spec .VTEPMAC , ErrInvalidGW )
133136 }
134137
135138 if gw .Spec .ASN == 0 {
136- return fmt .Errorf ("ASN must be set" ) //nolint:goerr113
139+ return fmt .Errorf ("ASN must be set: %w" , ErrInvalidGW )
137140 }
138141
139142 if len (gw .Spec .Interfaces ) == 0 {
140- return fmt .Errorf ("at least one interface must be defined" ) //nolint:goerr113
143+ return fmt .Errorf ("at least one interface must be defined: %w" , ErrInvalidGW )
141144 }
142145 for name , iface := range gw .Spec .Interfaces {
143146 if len (iface .IPs ) == 0 {
144- return fmt .Errorf ("interface %s must have at least one IP address" , name ) //nolint:goerr113
147+ return fmt .Errorf ("interface %s must have at least one IP address: %w " , name , ErrInvalidGW )
145148 }
146149 for _ , ifaceIP := range iface .IPs {
147150 ifaceIP , err := netip .ParsePrefix (ifaceIP )
148151 if err != nil {
149- return fmt .Errorf ("invalid interface %s IP %s: %w" , name , ifaceIP , err )
152+ return fmt .Errorf ("invalid interface %s IP %s: %w" , name , ifaceIP , errors . Join ( err , ErrInvalidGW ) )
150153 }
151154 if ! ifaceIP .Addr ().Is4 () {
152- return fmt .Errorf ("interface %s IP %s must be an IPv4 address" , name , ifaceIP ) //nolint:goerr113
155+ return fmt .Errorf ("interface %s IP %s must be an IPv4 address: %w " , name , ifaceIP , ErrInvalidGW )
153156 }
154157 }
155158 }
156159
157160 if len (gw .Spec .Neighbors ) == 0 {
158- return fmt .Errorf ("at least one BGP neighbor must be defined" ) //nolint:goerr113
161+ return fmt .Errorf ("at least one BGP neighbor must be defined: %w" , ErrInvalidGW )
159162 }
160163 for _ , neigh := range gw .Spec .Neighbors {
161164 if neigh .IP == "" {
162- return fmt .Errorf ("BGP neighbor must have an IP address" ) //nolint:goerr113
165+ return fmt .Errorf ("BGP neighbor must have an IP address: %w" , ErrInvalidGW )
163166 }
164167 neighIP , err := netip .ParseAddr (neigh .IP )
165168 if err != nil {
166- return fmt .Errorf ("invalid neighbor IP %s: %w" , neigh .IP , err )
169+ return fmt .Errorf ("invalid neighbor IP %s: %w" , neigh .IP , errors . Join ( err , ErrInvalidGW ) )
167170 }
168171 if ! neighIP .Is4 () {
169- return fmt .Errorf ("BGP neighbor IP %s must be an IPv4 address" , neigh .IP ) //nolint:goerr113
172+ return fmt .Errorf ("BGP neighbor IP %s must be an IPv4 address: %w " , neigh .IP , ErrInvalidGW )
170173 }
171174 if neighIP .IsMulticast () || neighIP .IsUnspecified () {
172- return fmt .Errorf ("BGP neighbor IP %s must be a unicast IPv4 address" , neigh .IP ) //nolint:goerr113
175+ return fmt .Errorf ("BGP neighbor IP %s must be a unicast IPv4 address: %w " , neigh .IP , ErrInvalidGW )
173176 }
174177
175178 if neigh .ASN == 0 {
176- return fmt .Errorf ("BGP neighbor %s must have an ASN" , neigh .IP ) //nolint:goerr113
179+ return fmt .Errorf ("BGP neighbor %s must have an ASN: %w " , neigh .IP , ErrInvalidGW )
177180 }
178181 }
179182
@@ -202,10 +205,10 @@ func (gw *Gateway) Validate(ctx context.Context, kube kclient.Reader) error {
202205 }
203206 }
204207 if _ , exist := protocolIPs [protoIP .Addr ()]; exist {
205- return fmt .Errorf ("gateway %s protocol IP %s is already in use" , gw .Name , protoIP ) //nolint:goerr113
208+ return fmt .Errorf ("gateway %s protocol IP %s is already in use: %w " , gw .Name , protoIP , ErrInvalidGW )
206209 }
207210 if _ , exist := vtepIPs [vtepIP .Addr ()]; exist {
208- return fmt .Errorf ("gateway %s VTEP IP %s is already in use" , gw .Name , vtepIP ) //nolint:goerr113
211+ return fmt .Errorf ("gateway %s VTEP IP %s is already in use: %w " , gw .Name , vtepIP , ErrInvalidGW )
209212 }
210213 }
211214
0 commit comments