From 7d36924419d4b4d8838cb1cb13b98ac20fafd166 Mon Sep 17 00:00:00 2001 From: Kristin Laemmert Date: Thu, 24 Oct 2024 14:46:48 -0400 Subject: [PATCH] api options --- src/pkg/domains/api/api.go | 5 ++--- src/pkg/domains/api/spec.go | 36 ++++++++++++++++++++++++++++++------ src/pkg/domains/api/types.go | 6 +++++- 3 files changed, 37 insertions(+), 10 deletions(-) diff --git a/src/pkg/domains/api/api.go b/src/pkg/domains/api/api.go index 418fda8ff..e8b9b3366 100644 --- a/src/pkg/domains/api/api.go +++ b/src/pkg/domains/api/api.go @@ -8,7 +8,6 @@ import ( "io" "net/http" "net/url" - "time" "github.com/defenseunicorns/lula/src/types" ) @@ -34,8 +33,8 @@ func (a ApiDomain) makeRequests(_ context.Context) (types.DomainResources, error } defaultClient := &http.Client{Transport: transport} - if defaultOpts.Timeout != 0 { - defaultClient.Timeout = time.Duration(defaultOpts.Timeout) * time.Second + if defaultOpts.timeout != nil { + defaultClient.Timeout = *defaultOpts.timeout } for _, request := range a.Spec.Requests { diff --git a/src/pkg/domains/api/spec.go b/src/pkg/domains/api/spec.go index 50290bfcf..d76d9b783 100644 --- a/src/pkg/domains/api/spec.go +++ b/src/pkg/domains/api/spec.go @@ -3,27 +3,51 @@ package api import ( "errors" "fmt" + "time" ) -func validateSpec(spec *ApiSpec) error { +// validateAndMutateSpec validates the spec values and applies any defaults or +// other mutations necessary. The original values are not modified. +// validateAndMutateSpec will validate the entire object and may return multiple +// errors. +func validateAndMutateSpec(spec *ApiSpec) (errs error) { if spec == nil { return errors.New("spec is required") } if len(spec.Requests) == 0 { - return errors.New("some requests must be specified") + errs = errors.Join(errors.New("some requests must be specified")) } + + if spec.Options != nil { + if spec.Options.Timeout != "" { + duration, err := time.ParseDuration(spec.Options.Timeout) + if err != nil { + errs = errors.Join(fmt.Errorf("invalid wait timeout string: %s", spec.Options.Timeout)) + } + spec.Options.timeout = &duration + } + } else { + // add an Options struct with a sane default timeout + spec.Options = &ApiOpts{} + } + if spec.Options.timeout == nil { + d := 30 * time.Second + spec.Options.timeout = &d + } + for _, request := range spec.Requests { if request.Name == "" { - return errors.New("request name cannot be empty") + errs = errors.Join(errors.New("request name cannot be empty")) } if request.URL == "" { - return errors.New("request url cannot be empty") + errs = errors.Join(errors.New("request url cannot be empty")) } if request.Method != "" { if request.Method != "Get" && request.Method != "Head" && request.Method != "Post" && request.Method != "PostForm" { - return fmt.Errorf("unsupported method: %s", request.Method) + errs = errors.Join(fmt.Errorf("unsupported method: %s", request.Method)) } } } - return nil + + return errs } diff --git a/src/pkg/domains/api/types.go b/src/pkg/domains/api/types.go index ca7fb2d3f..1b83cdc9a 100644 --- a/src/pkg/domains/api/types.go +++ b/src/pkg/domains/api/types.go @@ -2,6 +2,7 @@ package api import ( "context" + "time" "github.com/defenseunicorns/lula/src/types" ) @@ -14,7 +15,7 @@ type ApiDomain struct { func CreateApiDomain(spec *ApiSpec) (types.Domain, error) { // Check validity of spec - err := validateSpec(spec) + err := validateAndMutateSpec(spec) if err != nil { return nil, err } @@ -57,4 +58,7 @@ type ApiOpts struct { Timeout string `json:"timeout,omitempty" yaml:"timeout,omitempty"` Proxy string `json:"proxy,omitempty" yaml:"proxy,omitempty"` Headers []string `json:"headers,omitempty" yaml:"headers,omitempty"` + + // internally-managed options + timeout *time.Duration }