Skip to content

Commit d0e2685

Browse files
committed
Add webhook validation for external Keystone API
This commit adds webhook validation to ensure proper configuration when using external Keystone API. The validation: - Requires service override configuration when ExternalKeystoneAPI is true - Ensures both public and internal endpoints are defined - Ensures both endpoints have EndpointURL set This prevents reconciliation from starting with invalid configuration and avoids template rendering failures in services (like Glance) that depend on both endpoints. The validation is integrated into both ValidateCreate and ValidateUpdate webhook functions to catch configuration errors early. Related: PR comments requesting early validation for external Keystone API
1 parent a731b7f commit d0e2685

File tree

1 file changed

+70
-0
lines changed

1 file changed

+70
-0
lines changed

api/v1beta1/keystoneapi_webhook.go

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,9 @@ func (spec *KeystoneAPISpecCore) ValidateCreate(basePath *field.Path, namespace
115115
// referenced because is not supported
116116
allErrs = append(allErrs, spec.ValidateTopology(basePath, namespace)...)
117117

118+
// Validate external Keystone API configuration
119+
allErrs = append(allErrs, spec.ValidateExternalKeystoneAPI(basePath)...)
120+
118121
return allErrs
119122
}
120123

@@ -158,6 +161,9 @@ func (spec *KeystoneAPISpecCore) ValidateUpdate(_ KeystoneAPISpecCore, basePath
158161
// referenced because is not supported
159162
allErrs = append(allErrs, spec.ValidateTopology(basePath, namespace)...)
160163

164+
// Validate external Keystone API configuration
165+
allErrs = append(allErrs, spec.ValidateExternalKeystoneAPI(basePath)...)
166+
161167
return allErrs
162168
}
163169

@@ -169,6 +175,70 @@ func (r *KeystoneAPI) ValidateDelete() (admission.Warnings, error) {
169175
return nil, nil
170176
}
171177

178+
// ValidateExternalKeystoneAPI validates the external Keystone API configuration
179+
func (spec *KeystoneAPISpecCore) ValidateExternalKeystoneAPI(basePath *field.Path) field.ErrorList {
180+
var allErrs field.ErrorList
181+
182+
if !spec.ExternalKeystoneAPI {
183+
// No validation needed when external Keystone API is not enabled
184+
return allErrs
185+
}
186+
187+
overridePath := basePath.Child("override").Child("service")
188+
189+
// When ExternalKeystoneAPI is true, service overrides must be provided
190+
if spec.Override.Service == nil || len(spec.Override.Service) == 0 {
191+
allErrs = append(allErrs, field.Required(
192+
overridePath,
193+
"external Keystone API requires service override configuration",
194+
))
195+
return allErrs
196+
}
197+
198+
// Both public and internal endpoints must be defined with EndpointURL set
199+
// This ensures services that depend on both endpoints (like Glance) don't fail
200+
// when rendering templates
201+
hasPublic := false
202+
hasInternal := false
203+
204+
for endpointType, overrideSpec := range spec.Override.Service {
205+
if endpointType == service.EndpointPublic {
206+
hasPublic = true
207+
if overrideSpec.EndpointURL == nil || *overrideSpec.EndpointURL == "" {
208+
allErrs = append(allErrs, field.Required(
209+
overridePath.Key(string(endpointType)).Child("endpointURL"),
210+
"external Keystone API requires endpointURL to be set for public endpoint",
211+
))
212+
}
213+
}
214+
if endpointType == service.EndpointInternal {
215+
hasInternal = true
216+
if overrideSpec.EndpointURL == nil || *overrideSpec.EndpointURL == "" {
217+
allErrs = append(allErrs, field.Required(
218+
overridePath.Key(string(endpointType)).Child("endpointURL"),
219+
"external Keystone API requires endpointURL to be set for internal endpoint",
220+
))
221+
}
222+
}
223+
}
224+
225+
if !hasPublic {
226+
allErrs = append(allErrs, field.Required(
227+
overridePath,
228+
fmt.Sprintf("external Keystone API requires %s endpoint to be defined", service.EndpointPublic),
229+
))
230+
}
231+
232+
if !hasInternal {
233+
allErrs = append(allErrs, field.Required(
234+
overridePath,
235+
fmt.Sprintf("external Keystone API requires %s endpoint to be defined", service.EndpointInternal),
236+
))
237+
}
238+
239+
return allErrs
240+
}
241+
172242
// SetDefaultRouteAnnotations sets HAProxy timeout values of the route
173243
func (spec *KeystoneAPISpecCore) SetDefaultRouteAnnotations(annotations map[string]string) {
174244
const haProxyAnno = "haproxy.router.openshift.io/timeout"

0 commit comments

Comments
 (0)