1
0
mirror of https://github.com/rancher/steve.git synced 2025-08-01 14:48:30 +00:00

changing ParseHumanDuration to support timestamp values too (#684)

This commit is contained in:
Felipe Gehrke 2025-06-18 14:57:49 -03:00 committed by GitHub
parent b3539616e0
commit 4212386e13
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 34 additions and 10 deletions

View File

@ -6,11 +6,20 @@ import (
"time"
)
func ParseHumanReadableDuration(s string) (time.Duration, error) {
// ParseTimestampOrHumanReadableDuration can do one of three things with an incoming string:
// 1. Recognize it's an absolute timestamp and calculate a relative `time.Duration`
// 2. Recognize it's a human-readable duration (like 3m) and convert to a relative `time.Duration`
// 3. Return an error because it doesn't recognize the input
func ParseTimestampOrHumanReadableDuration(s string) (time.Duration, error) {
var total time.Duration
var val int
var unit byte
parsedTime, err := time.Parse(time.RFC3339, s)
if err == nil {
return time.Since(parsedTime), nil
}
r := strings.NewReader(s)
for r.Len() > 0 {
if _, err := fmt.Fscanf(r, "%d%c", &val, &unit); err != nil {

View File

@ -7,7 +7,7 @@ import (
"github.com/stretchr/testify/assert"
)
func TestParseHumanDuration(t *testing.T) {
func TestParseHumanReadableDuration(t *testing.T) {
testCases := []struct {
name string
input string
@ -63,7 +63,7 @@ func TestParseHumanDuration(t *testing.T) {
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
output, err := ParseHumanReadableDuration(tc.input)
output, err := ParseTimestampOrHumanReadableDuration(tc.input)
if tc.expectedErr {
assert.Error(t, err)
} else {
@ -71,4 +71,8 @@ func TestParseHumanDuration(t *testing.T) {
}
})
}
// Testing timestamp parsing separately
_, err := ParseTimestampOrHumanReadableDuration("2024-02-12T15:19:21Z")
assert.NoError(t, err)
}

View File

@ -247,29 +247,37 @@ func convertMetadataTimestampFields(request *types.APIRequest, gvk schema2.Group
curValue, got, err := unstructured.NestedSlice(unstr.Object, "metadata", "fields")
if err != nil {
logrus.Errorf("failed to get metadata.fields slice from unstr.Object: %s", err.Error())
logrus.Warnf("failed to get metadata.fields slice from unstr.Object: %s", err.Error())
return
}
if !got {
logrus.Debugf("couldn't find metadata.fields at unstr.Object")
logrus.Warnf("couldn't find metadata.fields at unstr.Object")
return
}
timeValue, ok := curValue[index].(string)
if !ok {
logrus.Debugf("time field isn't a string")
logrus.Warnf("time field isn't a string")
return
}
millis, err := strconv.ParseInt(timeValue, 10, 64)
if err != nil {
logrus.Warnf("failed to convert timestamp value: %s", err.Error())
logrus.Warnf("convert timestamp value: %s failed with error: %s", timeValue, err.Error())
return
}
timestamp := time.Unix(0, millis*int64(time.Millisecond))
dur := time.Since(timestamp)
curValue[index] = duration.HumanDuration(dur)
humanDuration := duration.HumanDuration(dur)
if humanDuration == "<invalid>" {
logrus.Warnf("couldn't convert value %d into human duration for column %s", int64(dur), col.Name)
return
}
curValue[index] = humanDuration
if err := unstructured.SetNestedSlice(unstr.Object, curValue, "metadata", "fields"); err != nil {
logrus.Errorf("failed to set value back to metadata.fields slice: %s", err.Error())
return

View File

@ -11,6 +11,7 @@ import (
"github.com/rancher/steve/pkg/resources/virtual/clusters"
"github.com/rancher/steve/pkg/resources/virtual/common"
"github.com/rancher/steve/pkg/resources/virtual/events"
"github.com/sirupsen/logrus"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/client-go/tools/cache"
@ -64,9 +65,11 @@ func (t *TransformBuilder) GetTransformFunc(gvk schema.GroupVersionKind, columns
if !cast {
return nil, fmt.Errorf("could not cast metadata.fields %d to string", index)
}
duration, err := rescommon.ParseHumanReadableDuration(value)
duration, err := rescommon.ParseTimestampOrHumanReadableDuration(value)
if err != nil {
return nil, err
logrus.Errorf("parse timestamp %s, failed with error: %s", value, err)
return obj, nil
}
curValue[index] = fmt.Sprintf("%d", now.Add(-duration).UnixMilli())