Skip to content

Commit 6e5ff39

Browse files
committed
[f5] fix entity deletion handling
1 parent d64ba62 commit 6e5ff39

File tree

2 files changed

+331
-30
lines changed

2 files changed

+331
-30
lines changed

internal/driver/f5/declaration.go

Lines changed: 78 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ import (
1818
"github.com/sapcc/andromeda/models"
1919
)
2020

21+
var errEntityPendingDeletion = errors.New("this entity has been marked as either PENDING_DELETE or DELETED and therefore must be excluded from the AS3 declaration")
22+
2123
type as3CommonTenantBuilderFunc func(s AndromedaF5Store, datacenters []*rpcmodels.Datacenter, domains []*rpcmodels.Domain) (
2224
as3.Tenant, []*server.ProvisioningStatusRequest_ProvisioningStatus, error)
2325

@@ -51,25 +53,67 @@ func buildAS3Declaration(f5Config config.F5Config, s AndromedaF5Store, ctbFunc a
5153
// build all /domain_{domainID} keys
5254
for _, domain := range domains {
5355
domainTenant, domainTenantRPCUpdates, err := dtbFunc(f5Config, datacentersByID, domain)
54-
if err != nil {
56+
// not a soft error: the declaration cannot be built
57+
if err != nil && err != errEntityPendingDeletion {
5558
return adc, rpcRequest, err
5659
}
60+
// only the active domains may be included in the declaration.
61+
// domains pending deletion are excluded (and thus deleted by AS3).
62+
if err != errEntityPendingDeletion {
63+
adc.AddTenant(as3DeclarationGSLBDomainTenantKey(domain.Id), domainTenant)
64+
}
5765
rpcUpdates = append(rpcUpdates, domainTenantRPCUpdates...)
58-
adc.AddTenant(as3DeclarationGSLBDomainTenantKey(domain.Id), domainTenant)
5966
}
6067
rpcRequest.ProvisioningStatus = rpcUpdates
6168
return adc, rpcRequest, nil
6269
}
6370

71+
// buildAS3DomainTenant builds one domain tenant ("domain_{domainID}" keys of AS3 declaration).
72+
//
73+
// If the given domain has been either scheduled for deletion or marked as
74+
// deleted, the returned tenant (first return value) should be considered a
75+
// zero value to be discarded. This condition can be checked for by comparing
76+
// the return error (third return value) to errEntityPendingDeletion.
77+
//
78+
// In case the domain provisioning status is set as PENDING_DELETE, the
79+
// returned slice of provisioning status requests will include an entry for
80+
// this domain, which shall be sent over RPC to the Andromeda Server
81+
// immediately after the next successful posting of the AS3 declaration.
6482
func buildAS3DomainTenant(
6583
f5Config config.F5Config,
6684
datacentersByID map[string]*rpcmodels.Datacenter,
6785
domain *rpcmodels.Domain) (as3.Tenant, []*server.ProvisioningStatusRequest_ProvisioningStatus, error) {
6886
tenant := as3.Tenant{}
6987
rpcUpdates := []*server.ProvisioningStatusRequest_ProvisioningStatus{}
88+
switch domain.ProvisioningStatus {
89+
case server.ProvisioningStatusRequest_ProvisioningStatus_DELETED.String(),
90+
server.ProvisioningStatusRequest_ProvisioningStatus_PENDING_DELETE.String():
91+
if domain.ProvisioningStatus == server.ProvisioningStatusRequest_ProvisioningStatus_PENDING_DELETE.String() {
92+
rpcUpdates = append(rpcUpdates, &server.ProvisioningStatusRequest_ProvisioningStatus{
93+
Id: domain.Id,
94+
Model: server.ProvisioningStatusRequest_ProvisioningStatus_DOMAIN,
95+
Status: server.ProvisioningStatusRequest_ProvisioningStatus_DELETED,
96+
})
97+
}
98+
// by excluding the entity from the AS3 declaration the API will delete it from the F5 device
99+
return tenant, rpcUpdates, errEntityPendingDeletion
100+
}
70101
application := as3.Application{}
71102
as3PoolReferences := []as3.PointerGSLBPool{}
72103
for _, p := range domain.Pools {
104+
switch p.ProvisioningStatus {
105+
case server.ProvisioningStatusRequest_ProvisioningStatus_PENDING_DELETE.String(),
106+
server.ProvisioningStatusRequest_ProvisioningStatus_DELETED.String():
107+
if p.ProvisioningStatus == server.ProvisioningStatusRequest_ProvisioningStatus_PENDING_DELETE.String() {
108+
rpcUpdates = append(rpcUpdates, &server.ProvisioningStatusRequest_ProvisioningStatus{
109+
Id: p.Id,
110+
Model: server.ProvisioningStatusRequest_ProvisioningStatus_POOL,
111+
Status: server.ProvisioningStatusRequest_ProvisioningStatus_DELETED,
112+
})
113+
}
114+
// by excluding the entity from the AS3 declaration the API will delete it from the F5 device
115+
continue
116+
}
73117
rpcUpdates = append(rpcUpdates, &server.ProvisioningStatusRequest_ProvisioningStatus{
74118
Id: p.Id,
75119
Model: server.ProvisioningStatusRequest_ProvisioningStatus_POOL,
@@ -132,6 +176,19 @@ func buildAS3CommonTenant(
132176
for _, pool := range domain.Pools {
133177
monitorsByPoolID[pool.Id] = pool.Monitors
134178
for _, monitor := range pool.Monitors {
179+
switch monitor.ProvisioningStatus {
180+
case server.ProvisioningStatusRequest_ProvisioningStatus_PENDING_DELETE.String(),
181+
server.ProvisioningStatusRequest_ProvisioningStatus_DELETED.String():
182+
if monitor.ProvisioningStatus == server.ProvisioningStatusRequest_ProvisioningStatus_PENDING_DELETE.String() {
183+
rpcUpdates = append(rpcUpdates, &server.ProvisioningStatusRequest_ProvisioningStatus{
184+
Id: monitor.Id,
185+
Model: server.ProvisioningStatusRequest_ProvisioningStatus_MONITOR,
186+
Status: server.ProvisioningStatusRequest_ProvisioningStatus_DELETED,
187+
})
188+
}
189+
// by excluding the entity from the AS3 declaration the API will delete it from the F5 device
190+
continue
191+
}
135192
monitorKey := as3DeclarationGSLBMonitorKey(monitor.Id)
136193
application.SetEntity(monitorKey, as3.GSLBMonitor{
137194
Class: "GSLB_Monitor",
@@ -156,9 +213,28 @@ func buildAS3CommonTenant(
156213
return tenant, rpcUpdates, err
157214
}
158215
for _, member := range members {
216+
switch member.ProvisioningStatus {
217+
case server.ProvisioningStatusRequest_ProvisioningStatus_PENDING_DELETE.String(),
218+
server.ProvisioningStatusRequest_ProvisioningStatus_DELETED.String():
219+
if member.ProvisioningStatus == server.ProvisioningStatusRequest_ProvisioningStatus_PENDING_DELETE.String() {
220+
rpcUpdates = append(rpcUpdates, &server.ProvisioningStatusRequest_ProvisioningStatus{
221+
Id: member.Id,
222+
Model: server.ProvisioningStatusRequest_ProvisioningStatus_MEMBER,
223+
Status: server.ProvisioningStatusRequest_ProvisioningStatus_DELETED,
224+
})
225+
}
226+
// by excluding the entity from the AS3 declaration the API will delete it from the F5 device
227+
continue
228+
}
159229
monitorPointers := []as3.PointerGSLBMonitor{}
160230
if monitors, ok := monitorsByPoolID[member.PoolId]; ok {
161231
for _, monitor := range monitors {
232+
switch monitor.ProvisioningStatus {
233+
case server.ProvisioningStatusRequest_ProvisioningStatus_PENDING_DELETE.String(),
234+
server.ProvisioningStatusRequest_ProvisioningStatus_DELETED.String():
235+
// these monitors are not part of the declaration (see GSLB_Monitor setup above)
236+
continue
237+
}
162238
monitorPointers = append(monitorPointers, as3.PointerGSLBMonitor{
163239
Use: as3DeclarationGSLBMonitorKey(monitor.Id),
164240
})

0 commit comments

Comments
 (0)