Skip to content

Commit dffa08d

Browse files
author
George Vine
committed
BUG/MEDIUM: support multiple force-persist statements in backends
1 parent 66a0a48 commit dffa08d

File tree

1 file changed

+76
-32
lines changed

1 file changed

+76
-32
lines changed

handlers/backend.go

Lines changed: 76 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -67,37 +67,85 @@ func logDeprecatedFieldsWarning(b *models.Backend) {
6767
if b.HTTPServerClose != "" {
6868
log.Warningf("Field HTTPServerClose is deprecated. Use HTTPConnectionMode.")
6969
}
70+
if b.ForcePersist != nil {
71+
log.Warningf("Field force_persist is deprecated. Use force_persist_list.")
72+
}
7073
if b.IgnorePersist != nil {
7174
log.Warningf("Field ignore_persist is deprecated. Use ignore_persist_list.")
7275
}
7376
}
7477

75-
// handleDeprecatedBackendFields adds backward compatibility support for the field ignore_persist,
76-
// which is deprecated in favour of ignore_persist_list.
78+
// handleDeprecatedBackendFields adds backward compatibility support for the fields
79+
// force_persist and ignore_persist that are deprecated in favour of force_persist_list
80+
// and ignore_persist_list.
7781
func handleDeprecatedBackendFields(method string, payload *models.Backend, onDisk *models.Backend) {
78-
switch method {
79-
case http.MethodGet:
82+
// A fair amount of code duplication in this function is tolerated because this code is expected to be
83+
// short-lived - it should be removed at the end of the sunset period for the deprecated fields.
84+
85+
if method == http.MethodGet {
86+
// Populate force_persist with the first element of force_persist_list if it is present.
87+
if len(payload.ForcePersistList) > 0 {
88+
payload.ForcePersist = &models.BackendForcePersist{
89+
Cond: payload.ForcePersistList[0].Cond,
90+
CondTest: payload.ForcePersistList[0].CondTest,
91+
}
92+
}
8093
// Populate ignore_persist with the first element of ignore_persist_list if it is present.
8194
if len(payload.IgnorePersistList) > 0 {
8295
payload.IgnorePersist = &models.BackendIgnorePersist{
8396
Cond: payload.IgnorePersistList[0].Cond,
8497
CondTest: payload.IgnorePersistList[0].CondTest,
8598
}
8699
}
87-
case http.MethodPost, http.MethodPut:
88-
// Do nothing if ignore_persist is not present in the payload.
89-
if payload.IgnorePersist == nil {
90-
return
91-
}
92-
// If both ignore_persist and ignore_persist_list are present, ignore and remove ignore_persist.
93-
if len(payload.IgnorePersistList) > 0 {
94-
payload.IgnorePersist = nil
95-
return
100+
return
101+
}
102+
103+
if payload.ForcePersist != nil && len(payload.ForcePersistList) == 0 {
104+
if method == http.MethodPost || (method == http.MethodPut && (onDisk == nil || len(onDisk.ForcePersistList) == 0)) {
105+
// Deprecated force_persist is present in a POST payload, or in a PUT payload when force_persist_list does not yet exist in the backend.
106+
// Transform it into force_persist_list with the only element.
107+
payload.ForcePersistList = []*models.ForcePersist{{
108+
Cond: payload.ForcePersist.Cond,
109+
CondTest: payload.ForcePersist.CondTest,
110+
}}
111+
} else {
112+
// Deprecated force_persist is present in a PUT payload, and force_persist_list already exists in the backend.
113+
// Preserve the existing force_persist_list, and add or reposition the submitted force_persist to be its first element.
114+
found := -1
115+
for i, item := range onDisk.ForcePersistList {
116+
if *item.Cond == *payload.ForcePersist.Cond && *item.CondTest == *payload.ForcePersist.CondTest {
117+
found = i
118+
break
119+
}
120+
}
121+
switch found {
122+
case -1:
123+
// force_persist value is not part of existing force_persist_list - insert it in the first position.
124+
payload.ForcePersistList = slices.Insert(onDisk.ForcePersistList, 0, &models.ForcePersist{
125+
Cond: payload.ForcePersist.Cond,
126+
CondTest: payload.ForcePersist.CondTest,
127+
})
128+
case 0:
129+
// force_persist value matches the first element of force_persist_list - preserve it without modification.
130+
payload.ForcePersistList = onDisk.ForcePersistList
131+
default:
132+
// force_persist value matches another element of force_persist_list - move it to the first position.
133+
payload.ForcePersistList = slices.Concat(onDisk.ForcePersistList[found:found+1], onDisk.ForcePersistList[:found], onDisk.ForcePersistList[found+1:])
134+
}
96135
}
136+
}
97137

98-
if method == http.MethodPut && onDisk != nil && len(onDisk.IgnorePersistList) > 0 {
99-
// Preserve ignore_persist_list if it exists prior to modification.
100-
// Add or reposition the value of ignore_persist unless it is already present as the first element.
138+
if payload.IgnorePersist != nil && len(payload.IgnorePersistList) == 0 {
139+
if method == http.MethodPost || (method == http.MethodPut && (onDisk == nil || len(onDisk.IgnorePersistList) == 0)) {
140+
// Deprecated ignore_persist is present in a POST payload, or in a PUT payload when ignore_persist_list does not yet exist in the backend.
141+
// Transform it into ignore_persist_list with the only element.
142+
payload.IgnorePersistList = []*models.IgnorePersist{{
143+
Cond: payload.IgnorePersist.Cond,
144+
CondTest: payload.IgnorePersist.CondTest,
145+
}}
146+
} else {
147+
// Deprecated ignore_persist is present in a PUT payload, and ignore_persist_list already exists in the backend.
148+
// Preserve the existing ignore_persist_list, and add or reposition the submitted ignore_persist to be its first element.
101149
found := -1
102150
for i, item := range onDisk.IgnorePersistList {
103151
if *item.Cond == *payload.IgnorePersist.Cond && *item.CondTest == *payload.IgnorePersist.CondTest {
@@ -119,17 +167,13 @@ func handleDeprecatedBackendFields(method string, payload *models.Backend, onDis
119167
// ignore_persist value matches another element of ignore_persist_list - move it to the first position.
120168
payload.IgnorePersistList = slices.Concat(onDisk.IgnorePersistList[found:found+1], onDisk.IgnorePersistList[:found], onDisk.IgnorePersistList[found+1:])
121169
}
122-
} else {
123-
// Otherwise, add ignore_persist_list with the value of the provided ignore_persist as its only element.
124-
payload.IgnorePersistList = []*models.IgnorePersist{{
125-
Cond: payload.IgnorePersist.Cond,
126-
CondTest: payload.IgnorePersist.CondTest,
127-
}}
128170
}
129-
130-
// Remove ignore_persist from the payload.
131-
payload.IgnorePersist = nil
132171
}
172+
173+
// Remove force_persist and ignore_persist from the payload - at this point, they were either processed,
174+
// or not present in the payload, or will be ignored because non-deprecated variants were submitted at the same time.
175+
payload.ForcePersist = nil
176+
payload.IgnorePersist = nil
133177
}
134178

135179
// Handle executing the request and returning a response
@@ -161,8 +205,8 @@ func (h *CreateBackendHandlerImpl) Handle(params backend.CreateBackendParams, pr
161205
return backend.NewCreateBackendDefault(int(*e.Code)).WithPayload(e)
162206
}
163207

164-
// Populate ignore_persist_list if the deprecated ignore_persist field
165-
// is present in the request payload.
208+
// Populate force_persist_list and ignore_persist_list if the corresponding
209+
// deprecated fields force_persist or ignore_persist are present in the request payload.
166210
handleDeprecatedBackendFields(http.MethodPost, params.Data, nil)
167211

168212
err = configuration.CreateBackend(params.Data, t, v)
@@ -252,7 +296,7 @@ func (h *GetBackendHandlerImpl) Handle(params backend.GetBackendParams, principa
252296
return backend.NewGetBackendDefault(int(*e.Code)).WithPayload(e)
253297
}
254298

255-
// Populate deprecated ignore_persist field in returned response.
299+
// Populate deprecated force_persist and ignore_persist fields in returned response.
256300
handleDeprecatedBackendFields(http.MethodGet, bck, nil)
257301

258302
return backend.NewGetBackendOK().WithPayload(&backend.GetBackendOKBody{Version: v, Data: bck})
@@ -277,7 +321,7 @@ func (h *GetBackendsHandlerImpl) Handle(params backend.GetBackendsParams, princi
277321
return backend.NewGetBackendsDefault(int(*e.Code)).WithPayload(e)
278322
}
279323

280-
// Populate deprecated ignore_persist field in returned response.
324+
// Populate deprecated force_persist and ignore_persist fields in returned response.
281325
for _, bck := range bcks {
282326
handleDeprecatedBackendFields(http.MethodGet, bck, nil)
283327
}
@@ -314,9 +358,9 @@ func (h *ReplaceBackendHandlerImpl) Handle(params backend.ReplaceBackendParams,
314358
return backend.NewReplaceBackendDefault(int(*e.Code)).WithPayload(e)
315359
}
316360

317-
// Populate or modify ignore_persist_list if the deprecated ignore_persist field
318-
// is present in the request payload.
319-
if params.Data.IgnorePersist != nil {
361+
// Populate or modify force_persist_list and ignore_persist_list if the corresponding
362+
// deprecated fields force_persist or ignore_persist are present in the request payload.
363+
if params.Data.ForcePersist != nil || params.Data.IgnorePersist != nil {
320364
_, onDisk, confErr := configuration.GetBackend(params.Data.Name, t)
321365
if confErr != nil {
322366
e := misc.HandleError(confErr)

0 commit comments

Comments
 (0)