@@ -2,12 +2,26 @@ package helpers
22
33import (
44 "context"
5+ "errors"
56 "fmt"
67 "os/exec"
78 "strings"
89 "time"
910)
1011
12+ var (
13+ // ErrPodNotRunning is returned when a pod does not reach Running state
14+ ErrPodNotRunning = errors .New ("pod did not reach Running state" )
15+ // ErrPodNoIP is returned when a pod has no IP address assigned
16+ ErrPodNoIP = errors .New ("pod has no IP address assigned" )
17+ // ErrPodNoEth1IP is returned when a pod has no eth1 IP address (delegated subnet not configured)
18+ ErrPodNoEth1IP = errors .New ("pod has no eth1 IP address (delegated subnet not configured?)" )
19+ // ErrPodContainerNotReady is returned when a pod container is not ready
20+ ErrPodContainerNotReady = errors .New ("pod container not ready" )
21+ // ErrMTPNCStuckDeletion is returned when MTPNC resources are stuck and not deleted
22+ ErrMTPNCStuckDeletion = errors .New ("MTPNC resources should have been deleted but were found" )
23+ )
24+
1125func runAzCommand (cmd string , args ... string ) (string , error ) {
1226 out , err := exec .Command (cmd , args ... ).CombinedOutput ()
1327 if err != nil {
@@ -32,11 +46,6 @@ func GetSubnetGUID(rg, vnet, subnet string) (string, error) {
3246 return runAzCommand ("az" , "resource" , "show" , "--ids" , subnetID , "--api-version" , "2023-09-01" , "--query" , "properties.serviceAssociationLinks[0].properties.subnetId" , "-o" , "tsv" )
3347}
3448
35- func GetSubnetToken (rg , vnet , subnet string ) (string , error ) {
36- // Optionally implement if you use subnet token override
37- return "" , nil
38- }
39-
4049// GetClusterNodes returns a slice of node names from a cluster using the given kubeconfig
4150func GetClusterNodes (kubeconfig string ) ([]string , error ) {
4251 cmd := exec .Command ("kubectl" , "--kubeconfig" , kubeconfig , "get" , "nodes" , "-o" , "name" )
@@ -70,7 +79,7 @@ func EnsureNamespaceExists(kubeconfig, namespace string) error {
7079 cmd = exec .Command ("kubectl" , "--kubeconfig" , kubeconfig , "create" , "namespace" , namespace )
7180 out , err := cmd .CombinedOutput ()
7281 if err != nil {
73- return fmt .Errorf ("failed to create namespace %s: %s \n %s" , namespace , err , string (out ))
82+ return fmt .Errorf ("failed to create namespace %s: %w \n Output: %s" , namespace , err , string (out ))
7483 }
7584
7685 return nil
@@ -87,20 +96,20 @@ func DeletePod(kubeconfig, namespace, podName string) error {
8796 cmd := exec .CommandContext (ctx , "kubectl" , "--kubeconfig" , kubeconfig , "delete" , "pod" , podName , "-n" , namespace , "--ignore-not-found=true" )
8897 out , err := cmd .CombinedOutput ()
8998 if err != nil {
90- if ctx .Err () == context .DeadlineExceeded {
99+ if errors . Is ( ctx .Err (), context .DeadlineExceeded ) {
91100 fmt .Printf ("kubectl delete pod command timed out after 90s, attempting force delete...\n " )
92101 } else {
93- return fmt .Errorf ("failed to delete pod %s in namespace %s: %s \n %s" , podName , namespace , err , string (out ))
102+ return fmt .Errorf ("failed to delete pod %s in namespace %s: %w \n Output: %s" , podName , namespace , err , string (out ))
94103 }
95104 }
96105
97106 // Wait for pod to be completely gone (critical for IP release)
98107 fmt .Printf ("Waiting for pod %s to be fully removed...\n " , podName )
99108 for attempt := 1 ; attempt <= 30 ; attempt ++ {
100- ctx , cancel := context .WithTimeout (context .Background (), 10 * time .Second )
101- checkCmd := exec .CommandContext (ctx , "kubectl" , "--kubeconfig" , kubeconfig , "get" , "pod" , podName , "-n" , namespace , "--ignore-not-found=true" , "-o" , "name" )
109+ checkCtx , checkCancel := context .WithTimeout (context .Background (), 10 * time .Second )
110+ checkCmd := exec .CommandContext (checkCtx , "kubectl" , "--kubeconfig" , kubeconfig , "get" , "pod" , podName , "-n" , namespace , "--ignore-not-found=true" , "-o" , "name" )
102111 checkOut , _ := checkCmd .CombinedOutput ()
103- cancel ()
112+ checkCancel ()
104113
105114 if strings .TrimSpace (string (checkOut )) == "" {
106115 fmt .Printf ("Pod %s fully removed after %d seconds\n " , podName , attempt * 2 )
@@ -140,7 +149,7 @@ func DeletePodNetworkInstance(kubeconfig, namespace, pniName string) error {
140149 cmd := exec .Command ("kubectl" , "--kubeconfig" , kubeconfig , "delete" , "podnetworkinstance" , pniName , "-n" , namespace , "--ignore-not-found=true" )
141150 out , err := cmd .CombinedOutput ()
142151 if err != nil {
143- return fmt .Errorf ("failed to delete PodNetworkInstance %s: %s \n %s" , pniName , err , string (out ))
152+ return fmt .Errorf ("failed to delete PodNetworkInstance %s: %w \n Output: %s" , pniName , err , string (out ))
144153 }
145154
146155 // Wait for PNI to be completely gone (it may take time for DNC to release reservations)
@@ -191,7 +200,7 @@ func DeletePodNetwork(kubeconfig, pnName string) error {
191200 cmd := exec .Command ("kubectl" , "--kubeconfig" , kubeconfig , "delete" , "podnetwork" , pnName , "--ignore-not-found=true" )
192201 out , err := cmd .CombinedOutput ()
193202 if err != nil {
194- return fmt .Errorf ("failed to delete PodNetwork %s: %s \n %s" , pnName , err , string (out ))
203+ return fmt .Errorf ("failed to delete PodNetwork %s: %w \n Output: %s" , pnName , err , string (out ))
195204 }
196205
197206 // Wait for PN to be completely gone
@@ -231,7 +240,7 @@ func DeleteNamespace(kubeconfig, namespace string) error {
231240 cmd := exec .Command ("kubectl" , "--kubeconfig" , kubeconfig , "delete" , "namespace" , namespace , "--ignore-not-found=true" )
232241 out , err := cmd .CombinedOutput ()
233242 if err != nil {
234- return fmt .Errorf ("failed to delete namespace %s: %s \n %s" , namespace , err , string (out ))
243+ return fmt .Errorf ("failed to delete namespace %s: %w \n Output: %s" , namespace , err , string (out ))
235244 }
236245
237246 // Wait for namespace to be completely gone
@@ -304,7 +313,7 @@ func WaitForPodRunning(kubeconfig, namespace, podName string, maxRetries, sleepS
304313 }
305314 }
306315
307- return fmt .Errorf ("pod %s did not reach Running state after %d attempts" , podName , maxRetries )
316+ return fmt .Errorf ("%w: pod %s after %d attempts" , ErrPodNotRunning , podName , maxRetries )
308317}
309318
310319// GetPodIP retrieves the IP address of a pod
@@ -321,7 +330,7 @@ func GetPodIP(kubeconfig, namespace, podName string) (string, error) {
321330
322331 ip := strings .TrimSpace (string (out ))
323332 if ip == "" {
324- return "" , fmt .Errorf ("pod %s in namespace %s has no IP address assigned" , podName , namespace )
333+ return "" , fmt .Errorf ("%w: pod %s in namespace %s" , ErrPodNoIP , podName , namespace )
325334 }
326335
327336 return ip , nil
@@ -346,7 +355,7 @@ func GetPodDelegatedIP(kubeconfig, namespace, podName string) (string, error) {
346355 if ip != "" {
347356 return ip , nil
348357 }
349- return "" , fmt .Errorf ("pod %s in namespace %s has no eth1 IP address (delegated subnet not configured?)" , podName , namespace )
358+ return "" , fmt .Errorf ("%w: pod %s in namespace %s" , ErrPodNoEth1IP , podName , namespace )
350359 }
351360
352361 // Check for retryable errors: container not found, signal killed, context deadline exceeded
@@ -365,7 +374,7 @@ func GetPodDelegatedIP(kubeconfig, namespace, podName string) (string, error) {
365374 return "" , fmt .Errorf ("failed to get eth1 IP for %s in namespace %s: %w\n Output: %s" , podName , namespace , err , string (out ))
366375 }
367376
368- return "" , fmt .Errorf ("pod %s container not ready after %d attempts" , podName , maxRetries )
377+ return "" , fmt .Errorf ("%w: pod %s after %d attempts" , ErrPodContainerNotReady , podName , maxRetries )
369378}
370379
371380// ExecInPod executes a command in a pod and returns the output
@@ -410,7 +419,7 @@ func VerifyNoMTPNC(kubeconfig, buildID string) error {
410419 }
411420
412421 if len (mtpncNames ) > 0 {
413- return fmt .Errorf ("found %d MTPNC resources with build ID '%s' that should have been deleted. This may indicate stuck MTPNC deletion" , len (mtpncNames ), buildID )
422+ return fmt .Errorf ("%w: found %d MTPNC resources with build ID '%s'" , ErrMTPNCStuckDeletion , len (mtpncNames ), buildID )
414423 }
415424 }
416425
0 commit comments