Skip to content

Commit b0f9c68

Browse files
committed
[Misc] Web-hook: Validation code simplified
Remove unnecessary types and checks.
1 parent 72047ec commit b0f9c68

File tree

2 files changed

+133
-242
lines changed

2 files changed

+133
-242
lines changed

cmd/web-hooks/internal/handler/handler.go

Lines changed: 35 additions & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -64,52 +64,6 @@ type WebhookHandler struct {
6464
CrdClient versioned.Interface
6565
}
6666

67-
// Metadata struct for parsing
68-
type Metadata struct {
69-
Name string `json:"name"`
70-
Namespace string `json:"namespace"`
71-
Labels map[string]string `json:"labels"`
72-
}
73-
74-
type ResponseCat struct {
75-
Metadata `json:"metadata"`
76-
Spec *v1alpha1.CAPTenantSpec `json:"spec"`
77-
Status *v1alpha1.CAPTenantStatus `json:"status"`
78-
Kind string `json:"kind"`
79-
}
80-
81-
type ResponseCtout struct {
82-
Metadata `json:"metadata"`
83-
Spec *v1alpha1.CAPTenantOutputSpec `json:"spec"`
84-
Kind string `json:"kind"`
85-
}
86-
87-
type ResponseCav struct {
88-
Metadata `json:"metadata"`
89-
Spec *v1alpha1.CAPApplicationVersionSpec `json:"spec"`
90-
Kind string `json:"kind"`
91-
}
92-
93-
type ResponseCa struct {
94-
Metadata `json:"metadata"`
95-
Spec *v1alpha1.CAPApplicationSpec `json:"spec"`
96-
Kind string `json:"kind"`
97-
}
98-
99-
type ResponseDom struct {
100-
Metadata `json:"metadata"`
101-
Spec *v1alpha1.DomainSpec `json:"spec"`
102-
Kind string `json:"kind"`
103-
}
104-
105-
type responseInterface interface {
106-
isEmpty() bool
107-
}
108-
109-
func (m Metadata) isEmpty() bool {
110-
return m.Name == ""
111-
}
112-
11367
func checkWorkloadPort(workload *v1alpha1.WorkloadDetails) validateResource {
11468
if workload.DeploymentDefinition == nil {
11569
return validAdmissionReviewObj()
@@ -186,7 +140,7 @@ func checkWorkloadType(workload *v1alpha1.WorkloadDetails) validateResource {
186140
return validAdmissionReviewObj()
187141
}
188142

189-
func checkWorkloadNameLength(cavObjNew *ResponseCav, workload *v1alpha1.WorkloadDetails) validateResource {
143+
func checkWorkloadNameLength(cavObjNew *v1alpha1.CAPApplicationVersion, workload *v1alpha1.WorkloadDetails) validateResource {
190144
const maxNameLength = 63
191145

192146
// Allowed length for service name is 63 characters
@@ -248,7 +202,7 @@ func getWorkloadTypeCount(workloads []v1alpha1.WorkloadDetails) map[string]int {
248202
return workloadTypeCount
249203
}
250204

251-
func checkWorkloadTypeCount(ca *v1alpha1.CAPApplication, cavObjNew *ResponseCav) validateResource {
205+
func checkWorkloadTypeCount(ca *v1alpha1.CAPApplication, cavObjNew *v1alpha1.CAPApplicationVersion) validateResource {
252206

253207
workloadTypeCount := getWorkloadTypeCount(cavObjNew.Spec.Workloads)
254208

@@ -280,7 +234,7 @@ func checkWorkloadTypeCount(ca *v1alpha1.CAPApplication, cavObjNew *ResponseCav)
280234
return validAdmissionReviewObj()
281235
}
282236

283-
func getContentWorkloadNames(cavObjNew *ResponseCav) []string {
237+
func getContentWorkloadNames(cavObjNew *v1alpha1.CAPApplicationVersion) []string {
284238
contentJobWorkloads := []string{}
285239
for _, workload := range cavObjNew.Spec.Workloads {
286240
if workload.JobDefinition != nil && workload.JobDefinition.Type == v1alpha1.JobContent {
@@ -290,7 +244,7 @@ func getContentWorkloadNames(cavObjNew *ResponseCav) []string {
290244
return contentJobWorkloads
291245
}
292246

293-
func checkWorkloadContentJob(cavObjNew *ResponseCav) validateResource {
247+
func checkWorkloadContentJob(cavObjNew *v1alpha1.CAPApplicationVersion) validateResource {
294248

295249
contentJobWorkloads := getContentWorkloadNames(cavObjNew)
296250

@@ -328,7 +282,7 @@ func checkWorkloadContentJob(cavObjNew *ResponseCav) validateResource {
328282
return validAdmissionReviewObj()
329283
}
330284

331-
func getDeploymentPorts(cavObjNew *ResponseCav) map[string][]int32 {
285+
func getDeploymentPorts(cavObjNew *v1alpha1.CAPApplicationVersion) map[string][]int32 {
332286
deploymentPorts := make(map[string][]int32)
333287

334288
for _, workload := range cavObjNew.Spec.Workloads {
@@ -356,7 +310,7 @@ func getDeploymentPorts(cavObjNew *ResponseCav) map[string][]int32 {
356310
return deploymentPorts
357311
}
358312

359-
func checkServiceExposure(cavObjNew *ResponseCav) validateResource {
313+
func checkServiceExposure(cavObjNew *v1alpha1.CAPApplicationVersion) validateResource {
360314
// check that all the workload names and ports mentioned in service exposures are valid
361315
// check that there are no duplicate subdomains in service exposures
362316

@@ -393,7 +347,7 @@ func checkServiceExposure(cavObjNew *ResponseCav) validateResource {
393347
return validAdmissionReviewObj()
394348
}
395349

396-
func validateWorkloads(ca *v1alpha1.CAPApplication, cavObjNew *ResponseCav) validateResource {
350+
func validateWorkloads(ca *v1alpha1.CAPApplication, cavObjNew *v1alpha1.CAPApplicationVersion) validateResource {
397351
// regex pattern for workload name - based on RFC 1123 label
398352
regex, _ := regexp.Compile(`^[a-z0-9]([-a-z0-9]*[a-z0-9])?$`)
399353

@@ -444,7 +398,7 @@ func validateWorkloads(ca *v1alpha1.CAPApplication, cavObjNew *ResponseCav) vali
444398
return validAdmissionReviewObj()
445399
}
446400

447-
func getTenantOperationsFromSpec(cavObjNew *ResponseCav) map[string]int {
401+
func getTenantOperationsFromSpec(cavObjNew *v1alpha1.CAPApplicationVersion) map[string]int {
448402
specTenantOperationsCntMap := make(map[string]int)
449403
var tenantOperationsList []v1alpha1.TenantOperationWorkloadReference
450404
if cavObjNew.Spec.TenantOperations.Provisioning != nil {
@@ -471,7 +425,7 @@ func checkForTenantOpJob(tenantOperations []v1alpha1.TenantOperationWorkloadRefe
471425
})
472426
}
473427

474-
func validateWorkloadsinTenantOperations(allTenantOperationsWorkloadCntMap map[string]int, tenantOperationWorkloadCntMap map[string]int, cavObjNew *ResponseCav) validateResource {
428+
func validateWorkloadsinTenantOperations(allTenantOperationsWorkloadCntMap map[string]int, tenantOperationWorkloadCntMap map[string]int, cavObjNew *v1alpha1.CAPApplicationVersion) validateResource {
475429

476430
specTenantOperationsCntMap := getTenantOperationsFromSpec(cavObjNew)
477431

@@ -520,7 +474,7 @@ func validateWorkloadsinTenantOperations(allTenantOperationsWorkloadCntMap map[s
520474
return validAdmissionReviewObj()
521475
}
522476

523-
func validateTenantOperations(cavObjNew *ResponseCav) validateResource {
477+
func validateTenantOperations(cavObjNew *v1alpha1.CAPApplicationVersion) validateResource {
524478
// Check: If a jobDefinition of type CustomTenantOperation is part of the workloads, spec.tenantOperations must be specified. It is possible to omit spec.tenantOperations when there are no jobs of type CustomTenantOperation and only one job of type TenantOperation
525479
// If spec.tenantOperations is specified, the entries (for provisioning, upgrade and deprovisioning) must include all spec.workloads.jobDefinitions of type TenantOperation
526480
// All the entries specified in spec.tenantOperations should be a valid workload of type TenantOperation or CustomTenantOperation
@@ -563,21 +517,21 @@ func validateTenantOperations(cavObjNew *ResponseCav) validateResource {
563517
return validAdmissionReviewObj()
564518
}
565519

566-
func (wh *WebhookHandler) checkCAPAppExists(cavObjNew *ResponseCav) (ca *v1alpha1.CAPApplication, validateRes validateResource) {
567-
app, err := wh.CrdClient.SmeV1alpha1().CAPApplications(cavObjNew.Metadata.Namespace).Get(context.TODO(), cavObjNew.Spec.CAPApplicationInstance, metav1.GetOptions{})
520+
func (wh *WebhookHandler) checkCAPAppExists(cavObjNew *v1alpha1.CAPApplicationVersion) (ca *v1alpha1.CAPApplication, validateRes validateResource) {
521+
app, err := wh.CrdClient.SmeV1alpha1().CAPApplications(cavObjNew.GetNamespace()).Get(context.TODO(), cavObjNew.Spec.CAPApplicationInstance, metav1.GetOptions{})
568522
if app == nil || err != nil {
569523
return nil, validateResource{
570524
allowed: false,
571-
message: fmt.Sprintf("%s %s no valid %s found for: %s.%s", InvalidationMessage, v1alpha1.CAPApplicationVersionKind, v1alpha1.CAPApplicationKind, cavObjNew.Metadata.Namespace, cavObjNew.Metadata.Name),
525+
message: fmt.Sprintf("%s %s no valid %s found for: %s.%s", InvalidationMessage, v1alpha1.CAPApplicationVersionKind, v1alpha1.CAPApplicationKind, cavObjNew.GetNamespace(), cavObjNew.GetName()),
572526
}
573527
}
574528

575529
return app, validAdmissionReviewObj()
576530
}
577531

578532
func (wh *WebhookHandler) validateCAPApplicationVersion(w http.ResponseWriter, admissionReview *admissionv1.AdmissionReview) validateResource {
579-
cavObjOld := ResponseCav{}
580-
cavObjNew := ResponseCav{}
533+
cavObjOld := v1alpha1.CAPApplicationVersion{}
534+
cavObjNew := v1alpha1.CAPApplicationVersion{}
581535

582536
// Note: Object is nil for "DELETE" operation
583537
if admissionReview.Request.Operation == admissionv1.Create || admissionReview.Request.Operation == admissionv1.Update {
@@ -603,13 +557,13 @@ func (wh *WebhookHandler) validateCAPApplicationVersion(w http.ResponseWriter, a
603557
if admissionReview.Request.Operation == admissionv1.Update && !cmp.Equal(cavObjOld.Spec, cavObjNew.Spec) {
604558
return validateResource{
605559
allowed: false,
606-
message: fmt.Sprintf("%s %s spec cannot be modified for: %s.%s", InvalidationMessage, v1alpha1.CAPApplicationVersionKind, cavObjNew.Metadata.Namespace, cavObjNew.Metadata.Name),
560+
message: fmt.Sprintf("%s %s spec cannot be modified for: %s.%s", InvalidationMessage, v1alpha1.CAPApplicationVersionKind, cavObjNew.GetNamespace(), cavObjNew.GetName()),
607561
}
608562
}
609563
return validAdmissionReviewObj()
610564
}
611565

612-
func (wh *WebhookHandler) checkCAVCreate(cav *ResponseCav) validateResource {
566+
func (wh *WebhookHandler) checkCAVCreate(cav *v1alpha1.CAPApplicationVersion) validateResource {
613567
// Check: CAPApplication exists
614568
ca, capAppExistsValidate := wh.checkCAPAppExists(cav)
615569
if !capAppExistsValidate.allowed {
@@ -627,11 +581,11 @@ func (wh *WebhookHandler) checkCAVCreate(cav *ResponseCav) validateResource {
627581
return validateTenantOperations(cav)
628582
}
629583

630-
func (wh *WebhookHandler) checkCaIsConsistent(catObjOld ResponseCat) validateResource {
584+
func (wh *WebhookHandler) checkCaIsConsistent(catObjOld v1alpha1.CAPTenant) validateResource {
631585

632-
ca, err := wh.CrdClient.SmeV1alpha1().CAPApplications(catObjOld.Metadata.Namespace).Get(context.TODO(), catObjOld.Spec.CAPApplicationInstance, metav1.GetOptions{})
586+
ca, err := wh.CrdClient.SmeV1alpha1().CAPApplications(catObjOld.GetNamespace()).Get(context.TODO(), catObjOld.Spec.CAPApplicationInstance, metav1.GetOptions{})
633587

634-
if ca != nil && err == nil && ca.Status.State == v1alpha1.CAPApplicationStateConsistent && catObjOld.Metadata.Labels[LabelTenantType] == ProviderTenantType && catObjOld.Status.State == v1alpha1.CAPTenantStateReady {
588+
if ca != nil && err == nil && ca.Status.State == v1alpha1.CAPApplicationStateConsistent && catObjOld.GetLabels()[LabelTenantType] == ProviderTenantType && catObjOld.Status.State == v1alpha1.CAPTenantStateReady {
635589
return validateResource{
636590
allowed: false,
637591
message: fmt.Sprintf("%s provider %s %s cannot be deleted when a consistent %s %s exists. Delete the %s instead to delete all tenants", InvalidationMessage, v1alpha1.CAPTenantKind, catObjOld.Name, v1alpha1.CAPApplicationKind, ca.Name, v1alpha1.CAPApplicationKind),
@@ -665,7 +619,7 @@ func (wh *WebhookHandler) checkForDuplicateDomains(domain string, name string) v
665619
}
666620

667621
func (wh *WebhookHandler) validateClusterDomain(w http.ResponseWriter, admissionReview *admissionv1.AdmissionReview) validateResource {
668-
clusterDomObjNew := ResponseDom{}
622+
clusterDomObjNew := v1alpha1.ClusterDomain{}
669623
if admissionReview.Request.Operation == admissionv1.Create || admissionReview.Request.Operation == admissionv1.Update {
670624
if validatedResource := unmarshalRawObj(w, admissionReview.Request.Object.Raw, &clusterDomObjNew, v1alpha1.ClusterDomainKind); !validatedResource.allowed {
671625
return validatedResource
@@ -679,7 +633,7 @@ func (wh *WebhookHandler) validateClusterDomain(w http.ResponseWriter, admission
679633
}
680634

681635
func (wh *WebhookHandler) validateDomain(w http.ResponseWriter, admissionReview *admissionv1.AdmissionReview) validateResource {
682-
domObjNew := ResponseDom{}
636+
domObjNew := v1alpha1.Domain{}
683637
if admissionReview.Request.Operation == admissionv1.Create || admissionReview.Request.Operation == admissionv1.Update {
684638
if validatedResource := unmarshalRawObj(w, admissionReview.Request.Object.Raw, &domObjNew, v1alpha1.DomainKind); !validatedResource.allowed {
685639
return validatedResource
@@ -693,8 +647,8 @@ func (wh *WebhookHandler) validateDomain(w http.ResponseWriter, admissionReview
693647
}
694648

695649
func (wh *WebhookHandler) validateCAPTenant(w http.ResponseWriter, admissionReview *admissionv1.AdmissionReview) validateResource {
696-
catObjOld := ResponseCat{}
697-
catObjNew := ResponseCat{}
650+
catObjOld := v1alpha1.CAPTenant{}
651+
catObjNew := v1alpha1.CAPTenant{}
698652

699653
// Note: Object is nil for "DELETE" operation
700654
if admissionReview.Request.Operation == admissionv1.Create || admissionReview.Request.Operation == admissionv1.Update {
@@ -711,18 +665,18 @@ func (wh *WebhookHandler) validateCAPTenant(w http.ResponseWriter, admissionRevi
711665

712666
// check: CAPApplication exists on create
713667
if admissionReview.Request.Operation == admissionv1.Create {
714-
if app, err := wh.CrdClient.SmeV1alpha1().CAPApplications(catObjNew.Metadata.Namespace).Get(context.TODO(), catObjNew.Spec.CAPApplicationInstance, metav1.GetOptions{}); app == nil || err != nil {
668+
if app, err := wh.CrdClient.SmeV1alpha1().CAPApplications(catObjNew.GetNamespace()).Get(context.TODO(), catObjNew.Spec.CAPApplicationInstance, metav1.GetOptions{}); app == nil || err != nil {
715669
return validateResource{
716670
allowed: false,
717-
message: fmt.Sprintf("%s %s no valid %s found for: %s.%s", InvalidationMessage, v1alpha1.CAPTenantKind, v1alpha1.CAPApplicationKind, catObjNew.Metadata.Namespace, catObjNew.Metadata.Name),
671+
message: fmt.Sprintf("%s %s no valid %s found for: %s.%s", InvalidationMessage, v1alpha1.CAPTenantKind, v1alpha1.CAPApplicationKind, catObjNew.GetNamespace(), catObjNew.GetName()),
718672
}
719673
}
720674
}
721675
// check: update on .Spec.CapApplicationInstance
722676
if admissionReview.Request.Operation == admissionv1.Update && catObjOld.Spec.CAPApplicationInstance != catObjNew.Spec.CAPApplicationInstance {
723677
return validateResource{
724678
allowed: false,
725-
message: fmt.Sprintf("%s %s capApplicationInstance value cannot be modified for: %s.%s", InvalidationMessage, v1alpha1.CAPTenantKind, catObjNew.Metadata.Namespace, catObjNew.Metadata.Name),
679+
message: fmt.Sprintf("%s %s capApplicationInstance value cannot be modified for: %s.%s", InvalidationMessage, v1alpha1.CAPTenantKind, catObjNew.GetNamespace(), catObjNew.GetName()),
726680
}
727681
}
728682

@@ -735,7 +689,7 @@ func (wh *WebhookHandler) validateCAPTenant(w http.ResponseWriter, admissionRevi
735689
}
736690

737691
func (wh *WebhookHandler) validateCAPTenantOutput(w http.ResponseWriter, admissionReview *admissionv1.AdmissionReview) validateResource {
738-
ctoutObjNew := ResponseCtout{}
692+
ctoutObjNew := v1alpha1.CAPTenantOutput{}
739693

740694
if admissionReview.Request.Operation == admissionv1.Delete {
741695
return validAdmissionReviewObj()
@@ -767,8 +721,8 @@ func (wh *WebhookHandler) validateCAPTenantOutput(w http.ResponseWriter, admissi
767721
}
768722

769723
func (wh *WebhookHandler) validateCAPApplication(w http.ResponseWriter, admissionReview *admissionv1.AdmissionReview) validateResource {
770-
caObjOld := ResponseCa{}
771-
caObjNew := ResponseCa{}
724+
caObjOld := v1alpha1.CAPApplication{}
725+
caObjNew := v1alpha1.CAPApplication{}
772726

773727
// Note: OldObject is nil for "CONNECT" and "CREATE" operations
774728
if admissionReview.Request.Operation == admissionv1.Delete || admissionReview.Request.Operation == admissionv1.Update {
@@ -787,31 +741,31 @@ func (wh *WebhookHandler) validateCAPApplication(w http.ResponseWriter, admissio
787741
if admissionReview.Request.Operation == admissionv1.Update && !cmp.Equal(caObjNew.Spec.Provider, caObjOld.Spec.Provider) {
788742
return validateResource{
789743
allowed: false,
790-
message: fmt.Sprintf("%s %s provider details cannot be changed for: %s.%s", InvalidationMessage, v1alpha1.CAPApplicationKind, caObjNew.Metadata.Namespace, caObjNew.Metadata.Name),
744+
message: fmt.Sprintf("%s %s provider details cannot be changed for: %s.%s", InvalidationMessage, v1alpha1.CAPApplicationKind, caObjNew.GetNamespace(), caObjNew.GetName()),
791745
}
792746
}
793747

794748
// Domains are DEPRECATED
795749
if admissionReview.Request.Operation == admissionv1.Create && !cmp.Equal(caObjNew.Spec.Domains, v1alpha1.ApplicationDomains{}) {
796750
return validateResource{
797751
allowed: false,
798-
message: fmt.Sprintf(DomainsDeprecated, InvalidationMessage, v1alpha1.CAPApplicationKind, caObjNew.Metadata.Namespace, caObjNew.Metadata.Name),
752+
message: fmt.Sprintf(DomainsDeprecated, InvalidationMessage, v1alpha1.CAPApplicationKind, caObjNew.GetNamespace(), caObjNew.GetName()),
799753
}
800754
}
801755

802756
// check: cannot switch from domainRefs to domains
803757
if admissionReview.Request.Operation == admissionv1.Update && (len(caObjOld.Spec.DomainRefs) > 0 && !cmp.Equal(caObjNew.Spec.Domains, v1alpha1.ApplicationDomains{})) {
804758
return validateResource{
805759
allowed: false,
806-
message: fmt.Sprintf(DomainsDeprecated, InvalidationMessage, v1alpha1.CAPApplicationKind, caObjNew.Metadata.Namespace, caObjNew.Metadata.Name),
760+
message: fmt.Sprintf(DomainsDeprecated, InvalidationMessage, v1alpha1.CAPApplicationKind, caObjNew.GetNamespace(), caObjNew.GetName()),
807761
}
808762
}
809763

810764
return validAdmissionReviewObj()
811765
}
812766

813-
func unmarshalRawObj(w http.ResponseWriter, rawBytes []byte, response responseInterface, resourceKind string) validateResource {
814-
if err := json.Unmarshal(rawBytes, response); err != nil || response.isEmpty() {
767+
func unmarshalRawObj(w http.ResponseWriter, rawBytes []byte, response any, resourceKind string) validateResource {
768+
if err := json.Unmarshal(rawBytes, response); err != nil {
815769
return invalidAdmissionReviewObj(w, resourceKind, err)
816770
}
817771
return validAdmissionReviewObj()

0 commit comments

Comments
 (0)