diff --git a/.changelog/19031.txt b/.changelog/19031.txt new file mode 100644 index 0000000000..a00e116c74 --- /dev/null +++ b/.changelog/19031.txt @@ -0,0 +1,3 @@ +```release-note:bug +api: add custom marshal/unmarshal for ServiceResolverConfigEntry.RequestTimeout so config entries that set this field can be read using the API. +``` diff --git a/agent/structs/config_entry_discoverychain.go b/agent/structs/config_entry_discoverychain.go index 6dc0a05d82..ed81726830 100644 --- a/agent/structs/config_entry_discoverychain.go +++ b/agent/structs/config_entry_discoverychain.go @@ -15,6 +15,7 @@ import ( "time" "github.com/hashicorp/go-bexpr" + "github.com/hashicorp/go-multierror" "github.com/mitchellh/copystructure" "github.com/mitchellh/hashstructure" @@ -929,21 +930,22 @@ func (e *ServiceResolverConfigEntry) UnmarshalJSON(data []byte) error { }{ Alias: (*Alias)(e), } - if err := lib.UnmarshalJSON(data, &aux); err != nil { + var err error + if err = lib.UnmarshalJSON(data, &aux); err != nil { return err } - var err error + var merr *multierror.Error if aux.ConnectTimeout != "" { if e.ConnectTimeout, err = time.ParseDuration(aux.ConnectTimeout); err != nil { - return err + merr = multierror.Append(merr, err) } } if aux.RequestTimeout != "" { if e.RequestTimeout, err = time.ParseDuration(aux.RequestTimeout); err != nil { - return err + merr = multierror.Append(merr, err) } } - return nil + return merr.ErrorOrNil() } func (e *ServiceResolverConfigEntry) SubsetExists(name string) bool { diff --git a/agent/structs/config_entry_discoverychain_test.go b/agent/structs/config_entry_discoverychain_test.go index 5961446d1f..b2547a7ace 100644 --- a/agent/structs/config_entry_discoverychain_test.go +++ b/agent/structs/config_entry_discoverychain_test.go @@ -1571,6 +1571,15 @@ func TestServiceResolverConfigEntry(t *testing.T) { }, validateErr: "Bad ConnectTimeout", }, + { + name: "bad request timeout", + entry: &ServiceResolverConfigEntry{ + Kind: ServiceResolver, + Name: "test", + RequestTimeout: -1 * time.Second, + }, + validateErr: "Bad RequestTimeout", + }, } // Bulk add a bunch of similar validation cases. diff --git a/api/config_entry_discoverychain.go b/api/config_entry_discoverychain.go index 3696f7be55..eeb3a1074c 100644 --- a/api/config_entry_discoverychain.go +++ b/api/config_entry_discoverychain.go @@ -6,6 +6,8 @@ package api import ( "encoding/json" "time" + + "github.com/hashicorp/go-multierror" ) type ServiceRouterConfigEntry struct { @@ -189,14 +191,19 @@ func (e *ServiceResolverConfigEntry) MarshalJSON() ([]byte, error) { type Alias ServiceResolverConfigEntry exported := &struct { ConnectTimeout string `json:",omitempty"` + RequestTimeout string `json:",omitempty"` *Alias }{ ConnectTimeout: e.ConnectTimeout.String(), + RequestTimeout: e.RequestTimeout.String(), Alias: (*Alias)(e), } if e.ConnectTimeout == 0 { exported.ConnectTimeout = "" } + if e.RequestTimeout == 0 { + exported.RequestTimeout = "" + } return json.Marshal(exported) } @@ -205,20 +212,27 @@ func (e *ServiceResolverConfigEntry) UnmarshalJSON(data []byte) error { type Alias ServiceResolverConfigEntry aux := &struct { ConnectTimeout string + RequestTimeout string *Alias }{ Alias: (*Alias)(e), } - if err := json.Unmarshal(data, &aux); err != nil { + var err error + if err = json.Unmarshal(data, &aux); err != nil { return err } - var err error + var merr *multierror.Error if aux.ConnectTimeout != "" { if e.ConnectTimeout, err = time.ParseDuration(aux.ConnectTimeout); err != nil { - return err + merr = multierror.Append(merr, err) } } - return nil + if aux.RequestTimeout != "" { + if e.RequestTimeout, err = time.ParseDuration(aux.RequestTimeout); err != nil { + merr = multierror.Append(merr, err) + } + } + return merr.ErrorOrNil() } func (e *ServiceResolverConfigEntry) GetKind() string { return e.Kind } diff --git a/api/config_entry_discoverychain_test.go b/api/config_entry_discoverychain_test.go index e1f35e1bc3..6b4a63e97e 100644 --- a/api/config_entry_discoverychain_test.go +++ b/api/config_entry_discoverychain_test.go @@ -173,6 +173,7 @@ func TestAPI_ConfigEntry_DiscoveryChain(t *testing.T) { }, }, ConnectTimeout: 5 * time.Second, + RequestTimeout: 10 * time.Second, Meta: map[string]string{ "foo": "bar", "gir": "zim",