From 19940fd4e984ea30218446b6f6bf71953882bc14 Mon Sep 17 00:00:00 2001 From: "R.B. Boyer" Date: Tue, 8 Aug 2023 15:44:00 -0500 Subject: [PATCH] validate timeouts and retries --- internal/mesh/internal/types/grpc_route.go | 31 ++++---- internal/mesh/internal/types/http_route.go | 88 ++++++++++++++++++---- 2 files changed, 88 insertions(+), 31 deletions(-) diff --git a/internal/mesh/internal/types/grpc_route.go b/internal/mesh/internal/types/grpc_route.go index 7cdd25d18413d..5373b8260d053 100644 --- a/internal/mesh/internal/types/grpc_route.go +++ b/internal/mesh/internal/types/grpc_route.go @@ -5,7 +5,6 @@ package types import ( "errors" - "fmt" "github.com/hashicorp/go-multierror" @@ -187,23 +186,23 @@ func ValidateGRPCRoute(res *pbresource.Resource) error { } if rule.Timeouts != nil { - // TODO(rb): validate timeouts + for _, err := range validateHTTPTimeouts(rule.Timeouts) { + merr = multierror.Append(merr, wrapRuleErr( + resource.ErrInvalidField{ + Name: "timeouts", + Wrapped: err, + }, + )) + } } if rule.Retries != nil { - // TODO(rb): validate retries - for j, condition := range rule.Retries.OnConditions { - if !isValidRetryCondition(condition) { - merr = multierror.Append(merr, wrapRuleErr( - resource.ErrInvalidListElement{ - Name: "retries", - Index: j, - Wrapped: resource.ErrInvalidField{ - Name: "on_conditions", - Wrapped: fmt.Errorf("not a valid retry condition: %q", condition), - }, - }, - )) - } + for _, err := range validateHTTPRetries(rule.Retries) { + merr = multierror.Append(merr, wrapRuleErr( + resource.ErrInvalidField{ + Name: "retries", + Wrapped: err, + }, + )) } } } diff --git a/internal/mesh/internal/types/http_route.go b/internal/mesh/internal/types/http_route.go index c9391ffcbb695..6ed904f5ccbcc 100644 --- a/internal/mesh/internal/types/http_route.go +++ b/internal/mesh/internal/types/http_route.go @@ -290,23 +290,23 @@ func ValidateHTTPRoute(res *pbresource.Resource) error { } if rule.Timeouts != nil { - // TODO(rb): validate timeouts + for _, err := range validateHTTPTimeouts(rule.Timeouts) { + merr = multierror.Append(merr, wrapRuleErr( + resource.ErrInvalidField{ + Name: "timeouts", + Wrapped: err, + }, + )) + } } if rule.Retries != nil { - // TODO(rb): validate retries - for j, condition := range rule.Retries.OnConditions { - if !isValidRetryCondition(condition) { - merr = multierror.Append(merr, wrapRuleErr( - resource.ErrInvalidListElement{ - Name: "retries", - Index: j, - Wrapped: resource.ErrInvalidField{ - Name: "on_conditions", - Wrapped: fmt.Errorf("not a valid retry condition: %q", condition), - }, - }, - )) - } + for _, err := range validateHTTPRetries(rule.Retries) { + merr = multierror.Append(merr, wrapRuleErr( + resource.ErrInvalidField{ + Name: "retries", + Wrapped: err, + }, + )) } } } @@ -314,6 +314,64 @@ func ValidateHTTPRoute(res *pbresource.Resource) error { return merr } +func validateHTTPTimeouts(timeouts *pbmesh.HTTPRouteTimeouts) []error { + if timeouts == nil { + return nil + } + + var errs []error + + if timeouts.Request != nil { + val := timeouts.Request.AsDuration() + if val < 0 { + errs = append(errs, resource.ErrInvalidField{ + Name: "request", + Wrapped: fmt.Errorf("timeout cannot be negative: %v", val), + }) + } + } + if timeouts.BackendRequest != nil { + val := timeouts.BackendRequest.AsDuration() + if val < 0 { + errs = append(errs, resource.ErrInvalidField{ + Name: "request", + Wrapped: fmt.Errorf("timeout cannot be negative: %v", val), + }) + } + } + if timeouts.Idle != nil { + val := timeouts.Idle.AsDuration() + if val < 0 { + errs = append(errs, resource.ErrInvalidField{ + Name: "idle", + Wrapped: fmt.Errorf("timeout cannot be negative: %v", val), + }) + } + } + + return errs +} + +func validateHTTPRetries(retries *pbmesh.HTTPRouteRetries) []error { + if retries == nil { + return nil + } + + var errs []error + + for i, condition := range retries.OnConditions { + if !isValidRetryCondition(condition) { + errs = append(errs, resource.ErrInvalidListElement{ + Name: "on_conditions", + Index: i, + Wrapped: fmt.Errorf("not a valid retry condition: %q", condition), + }) + } + } + + return errs +} + func validateBackendRef(backendRef *pbmesh.BackendReference) []error { var errs []error if backendRef == nil {