diff --git a/.features/fix-http-timeoutseconds-templating.yaml b/.features/fix-http-timeoutseconds-templating.yaml new file mode 100644 index 000000000000..02e32ffc0b38 --- /dev/null +++ b/.features/fix-http-timeoutseconds-templating.yaml @@ -0,0 +1,18 @@ +issue: 15024 +component: workflow +kind: bugfix + +tldr: Add support for templated string values for http.timeoutSeconds. + +previousBehavior: | + The `timeoutSeconds` field only accepted numeric JSON values. + When templated parameters resolved to strings (e.g. `"1800"` instead of `1800`), + unmarshalling failed with: + `json: cannot unmarshal string into Go struct field HTTP.timeoutSeconds of type int64`. + +newBehavior: | + The `HTTP` type now accepts both numeric and string representations for `timeoutSeconds`. + A custom JSON unmarshaller converts string integer values into `int64`, + making templated parameters fully supported while keeping the public API unchanged. + +backwardsCompatible: true diff --git a/pkg/apis/workflow/v1alpha1/http_types.go b/pkg/apis/workflow/v1alpha1/http_types.go index 79f9c3e29ec9..9ab6c34ecd41 100644 --- a/pkg/apis/workflow/v1alpha1/http_types.go +++ b/pkg/apis/workflow/v1alpha1/http_types.go @@ -4,6 +4,7 @@ import ( "net/http" v1 "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/util/intstr" ) type HTTPHeaderSource struct { @@ -43,7 +44,7 @@ type HTTP struct { // Headers are an optional list of headers to send with HTTP requests Headers HTTPHeaders `json:"headers,omitempty" protobuf:"bytes,3,rep,name=headers"` // TimeoutSeconds is request timeout for HTTP Request. Default is 30 seconds - TimeoutSeconds *int64 `json:"timeoutSeconds,omitempty" protobuf:"bytes,4,opt,name=timeoutSeconds"` + TimeoutSeconds *intstr.IntOrString `json:"timeoutSeconds,omitempty" protobuf:"bytes,4,opt,name=timeoutSeconds"` // SuccessCondition is an expression if evaluated to true is considered successful SuccessCondition string `json:"successCondition,omitempty" protobuf:"bytes,6,opt,name=successCondition"` // Body is content of the HTTP Request diff --git a/pkg/apis/workflow/v1alpha1/http_types_test.go b/pkg/apis/workflow/v1alpha1/http_types_test.go new file mode 100644 index 000000000000..4793deefbe18 --- /dev/null +++ b/pkg/apis/workflow/v1alpha1/http_types_test.go @@ -0,0 +1,41 @@ +package v1alpha1 + +import ( + "encoding/json" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func TestHTTPUnmarshalJSON_TimeoutSeconds_Number(t *testing.T) { + jsonData := []byte(`{"timeoutSeconds": 10}`) + + var httpTemplate HTTP + err := json.Unmarshal(jsonData, &httpTemplate) + require.NoError(t, err) + + if assert.NotNil(t, httpTemplate.TimeoutSeconds) { + assert.Equal(t, int64(10), *httpTemplate.TimeoutSeconds) + } +} + +func TestHTTPUnmarshalJSON_TimeoutSeconds_StringNumeric(t *testing.T) { + jsonData := []byte(`{"timeoutSeconds": "15"}`) + + var httpTemplate HTTP + err := json.Unmarshal(jsonData, &httpTemplate) + require.NoError(t, err) + + if assert.NotNil(t, httpTemplate.TimeoutSeconds) { + assert.Equal(t, int64(15), *httpTemplate.TimeoutSeconds) + } +} + +func TestHTTPUnmarshalJSON_TimeoutSeconds_InvalidString(t *testing.T) { + jsonData := []byte(`{"timeoutSeconds": "not-a-number"}`) + + var httpTemplate HTTP + err := json.Unmarshal(jsonData, &httpTemplate) + require.Error(t, err) +}