diff --git a/.changelog/19031.txt b/.changelog/19031.txt new file mode 100644 index 000000000000..a00e116c748b --- /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 9f80acf682ba..a725faff1b98 100644 --- a/agent/structs/config_entry_discoverychain.go +++ b/agent/structs/config_entry_discoverychain.go @@ -12,6 +12,7 @@ import ( "time" "github.com/hashicorp/go-bexpr" + "github.com/hashicorp/go-multierror" "github.com/mitchellh/copystructure" "github.com/mitchellh/hashstructure" @@ -901,21 +902,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 db4ac425ebe9..47cb010b3089 100644 --- a/agent/structs/config_entry_discoverychain_test.go +++ b/agent/structs/config_entry_discoverychain_test.go @@ -1568,6 +1568,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 acc05e13e1f0..e4c8e266f80a 100644 --- a/api/config_entry_discoverychain.go +++ b/api/config_entry_discoverychain.go @@ -3,6 +3,8 @@ package api import ( "encoding/json" "time" + + "github.com/hashicorp/go-multierror" ) type ServiceRouterConfigEntry struct { @@ -182,14 +184,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) } @@ -198,20 +205,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 521494f17698..42f7a287a9b2 100644 --- a/api/config_entry_discoverychain_test.go +++ b/api/config_entry_discoverychain_test.go @@ -170,6 +170,7 @@ func TestAPI_ConfigEntry_DiscoveryChain(t *testing.T) { }, }, ConnectTimeout: 5 * time.Second, + RequestTimeout: 10 * time.Second, Meta: map[string]string{ "foo": "bar", "gir": "zim",