@@ -5,13 +5,15 @@ package deleter
5
5
6
6
import (
7
7
"context"
8
+ "errors"
8
9
"fmt"
9
10
"strconv"
11
+ "strings"
10
12
"time"
11
13
12
14
"github.com/go-logr/logr"
13
15
corev1 "k8s.io/api/core/v1"
14
- "k8s.io/apimachinery/pkg/api/errors"
16
+ apierrors "k8s.io/apimachinery/pkg/api/errors"
15
17
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
16
18
"k8s.io/apimachinery/pkg/util/wait"
17
19
"sigs.k8s.io/cluster-api/api/v1beta1"
@@ -22,6 +24,8 @@ import (
22
24
"github.com/d2iq-labs/capi-runtime-extensions/pkg/k8s/annotations"
23
25
)
24
26
27
+ var ErrFailedToDeleteService = errors .New ("kubernetes Services deletion failed" )
28
+
25
29
type Deleter struct {
26
30
cluster * v1beta1.Cluster
27
31
client client.Client
@@ -31,14 +35,12 @@ type Deleter struct {
31
35
type objectMetaList []metav1.ObjectMeta
32
36
33
37
func (ol objectMetaList ) asCommaSeparatedString () string {
34
- out := ""
35
- separator := ""
38
+ names := make ([]string , 0 , len (ol ))
36
39
for n := range ol {
37
- object := ol [n ]
38
- out += fmt .Sprintf ("%s%s/%s" , separator , object .Namespace , object .Name )
39
- separator = ", "
40
+ obj := ol [n ]
41
+ names = append (names , fmt .Sprintf ("%s/%s" , obj .Namespace , obj .Name ))
40
42
}
41
- return out
43
+ return strings . Join ( names , ", " )
42
44
}
43
45
44
46
func New (log logr.Logger , cluster * v1beta1.Cluster , remoteClient client.Client ) Deleter {
@@ -50,11 +52,7 @@ func New(log logr.Logger, cluster *v1beta1.Cluster, remoteClient client.Client)
50
52
}
51
53
52
54
func (d * Deleter ) DeleteServicesWithLoadBalancer (ctx context.Context ) error {
53
- err := deleteServicesWithLoadBalancer (ctx , d .client , d .log )
54
- if err != nil {
55
- return err
56
- }
57
- return nil
55
+ return deleteServicesWithLoadBalancer (ctx , d .client , d .log )
58
56
}
59
57
60
58
func deleteServicesWithLoadBalancer (
@@ -69,7 +67,7 @@ func deleteServicesWithLoadBalancer(
69
67
return fmt .Errorf ("error listing Services: %w" , err )
70
68
}
71
69
72
- svcsFailedToBeDeleted := make ( objectMetaList , 0 )
70
+ var svcsFailedToBeDeleted objectMetaList
73
71
for i := range services .Items {
74
72
svc := & services .Items [i ]
75
73
if needsDelete (svc ) {
@@ -120,36 +118,35 @@ func waitForServiceDeletion(
120
118
ctx context.Context ,
121
119
c client.Client ,
122
120
service * corev1.Service ,
123
- ) ( err error ) {
121
+ ) error {
124
122
backoff := wait.Backoff {
125
123
Duration : 1 * time .Second ,
126
124
Factor : 1.5 ,
127
125
Jitter : 0 ,
128
126
Steps : 13 ,
129
127
}
130
- // the error is always nil to retry but is captured in the named return err
131
- _ = wait .ExponentialBackoff (backoff , func () (bool , error ) {
128
+ return wait .ExponentialBackoff (backoff , func () (bool , error ) {
132
129
key := client.ObjectKey {
133
130
Namespace : service .Namespace ,
134
131
Name : service .Name ,
135
132
}
136
- err = c .Get (ctx , key , service )
133
+ err : = c .Get (ctx , key , service )
137
134
if err != nil {
138
- if errors .IsNotFound (err ) {
139
- err = nil
135
+ if apierrors .IsNotFound (err ) {
140
136
return true , nil
141
137
}
138
+ return false , err
142
139
}
143
140
return false , nil
144
141
})
145
-
146
- return
147
142
}
148
143
149
144
func failedToDeleteServicesError (svcsFailedToBeDeleted objectMetaList ) error {
150
- //nolint:goerr113 // This error is specific to this function
151
- return fmt .Errorf ("the following Services could not be deleted " +
152
- "and must cleaned up manually before deleting the cluster: %s" , svcsFailedToBeDeleted .asCommaSeparatedString ())
145
+ return fmt .Errorf ("%w: the following Services could not be deleted " +
146
+ "and must cleaned up manually before deleting the cluster: %s" ,
147
+ ErrFailedToDeleteService ,
148
+ svcsFailedToBeDeleted .asCommaSeparatedString (),
149
+ )
153
150
}
154
151
155
152
func ShouldDeleteServicesWithLoadBalancer (cluster * v1beta1.Cluster ) (bool , error ) {
@@ -168,14 +165,14 @@ func ShouldDeleteServicesWithLoadBalancer(cluster *v1beta1.Cluster) (bool, error
168
165
)
169
166
}
170
167
171
- // use the Cluster phase to determine if its safe to skip deleting
168
+ // use the Cluster phase to determine if it's safe to skip deleting
172
169
//
173
170
// when ClusterPhasePending or ClusterPhaseProvisioning Kubernetes API has not been created
174
171
// and the user would not have been able to create any Kubernetes resources that would prevent cleanup
175
172
//nolint:lll // long URL cannot be split up
176
173
// https://github.com/kubernetes-sigs/cluster-api/blob/7f879be68d15737e335b6cb39d380d1d163e06e6/controllers/cluster_controller_phases.go#L44-L50
177
174
//
178
- // when ClusterPhaseDeleting its too late to try to cleanup
175
+ // when ClusterPhaseDeleting it's too late to try to cleanup
179
176
phase := cluster .Status .GetTypedPhase ()
180
177
skipDeleteBasedOnPhase := phase == v1beta1 .ClusterPhasePending ||
181
178
phase == v1beta1 .ClusterPhaseProvisioning ||
0 commit comments