Просмотр исходного кода

Merge branch 'develop' into circle_ci_removal

Matt Ray 3 лет назад
Родитель
Сommit
7289f9a633
4 измененных файлов с 47 добавлено и 1 удалено
  1. 1 1
      docs/swagger.json
  2. 18 0
      pkg/kubecost/window.go
  3. 12 0
      pkg/kubecost/window_test.go
  4. 16 0
      pkg/util/timeutil/timeutil.go

+ 1 - 1
docs/swagger.json

@@ -69,7 +69,7 @@
           {
           {
           "name": "aggregate",
           "name": "aggregate",
           "in": "query",
           "in": "query",
-          "description": "Field by which to aggregate the results. Accepts: `cluster`, `namespace`, `controllerKind`, `controller`, `service`, `label:<name>`, and `annotation:<name>`. Also accepts comma-separated lists for multi-aggregation, like `namespace,label:app`.",
+          "description": "Field by which to aggregate the results. Accepts: `cluster`, `node`, `namespace`, `controllerKind`, `controller`, `service`, `pod`, `container`, `label:<name>`, and `annotation:<name>`. Also accepts comma-separated lists for multi-aggregation, like `namespace,label:app`.",
           "required": false,
           "required": false,
           "style": "form",
           "style": "form",
           "explode": true,
           "explode": true,

+ 18 - 0
pkg/kubecost/window.go

@@ -34,6 +34,10 @@ var (
 // in the given time's timezone.
 // in the given time's timezone.
 // e.g. 2020-01-01T12:37:48-0700, 24h = 2020-01-01T00:00:00-0700
 // e.g. 2020-01-01T12:37:48-0700, 24h = 2020-01-01T00:00:00-0700
 func RoundBack(t time.Time, resolution time.Duration) time.Time {
 func RoundBack(t time.Time, resolution time.Duration) time.Time {
+	// if the duration is a week - roll back to the following Sunday
+	if resolution == timeutil.Week {
+		return timeutil.RoundToStartOfWeek(t)
+	}
 	_, offSec := t.Zone()
 	_, offSec := t.Zone()
 	return t.Add(time.Duration(offSec) * time.Second).Truncate(resolution).Add(-time.Duration(offSec) * time.Second)
 	return t.Add(time.Duration(offSec) * time.Second).Truncate(resolution).Add(-time.Duration(offSec) * time.Second)
 }
 }
@@ -42,6 +46,11 @@ func RoundBack(t time.Time, resolution time.Duration) time.Time {
 // in the given time's timezone.
 // in the given time's timezone.
 // e.g. 2020-01-01T12:37:48-0700, 24h = 2020-01-02T00:00:00-0700
 // e.g. 2020-01-01T12:37:48-0700, 24h = 2020-01-02T00:00:00-0700
 func RoundForward(t time.Time, resolution time.Duration) time.Time {
 func RoundForward(t time.Time, resolution time.Duration) time.Time {
+	// if the duration is a week - roll forward to the following Sunday
+	if resolution == timeutil.Week {
+		return timeutil.RoundToStartOfFollowingWeek(t)
+	}
+
 	back := RoundBack(t, resolution)
 	back := RoundBack(t, resolution)
 	if back.Equal(t) {
 	if back.Equal(t) {
 		// The given time is exactly a multiple of the given resolution
 		// The given time is exactly a multiple of the given resolution
@@ -233,6 +242,9 @@ func parseWindow(window string, now time.Time) (Window, error) {
 		if match[2] == "d" {
 		if match[2] == "d" {
 			dur = 24 * time.Hour
 			dur = 24 * time.Hour
 		}
 		}
+		if match[2] == "w" {
+			dur = timeutil.Week
+		}
 
 
 		num, _ := strconv.ParseInt(match[1], 10, 64)
 		num, _ := strconv.ParseInt(match[1], 10, 64)
 
 
@@ -254,6 +266,9 @@ func parseWindow(window string, now time.Time) (Window, error) {
 		if match[4] == "d" {
 		if match[4] == "d" {
 			offUnit = 24 * time.Hour
 			offUnit = 24 * time.Hour
 		}
 		}
+		if match[4] == "w" {
+			offUnit = 24 * timeutil.Week
+		}
 
 
 		offNum, _ := strconv.ParseInt(match[3], 10, 64)
 		offNum, _ := strconv.ParseInt(match[3], 10, 64)
 
 
@@ -266,6 +281,9 @@ func parseWindow(window string, now time.Time) (Window, error) {
 		if match[2] == "d" {
 		if match[2] == "d" {
 			durUnit = 24 * time.Hour
 			durUnit = 24 * time.Hour
 		}
 		}
+		if match[2] == "w" {
+			durUnit = timeutil.Week
+		}
 
 
 		durNum, _ := strconv.ParseInt(match[1], 10, 64)
 		durNum, _ := strconv.ParseInt(match[1], 10, 64)
 
 

+ 12 - 0
pkg/kubecost/window_test.go

@@ -88,6 +88,12 @@ func TestRoundBack(t *testing.T) {
 	if !tb.Equal(time.Date(2020, time.January, 1, 0, 0, 0, 0, time.UTC)) {
 	if !tb.Equal(time.Date(2020, time.January, 1, 0, 0, 0, 0, time.UTC)) {
 		t.Fatalf("RoundBack: expected 2020-01-01T00:00:00Z; actual %s", tb)
 		t.Fatalf("RoundBack: expected 2020-01-01T00:00:00Z; actual %s", tb)
 	}
 	}
+
+	to = time.Date(2020, time.January, 1, 23, 59, 0, 0, time.UTC)
+	tb = RoundBack(to, timeutil.Week)
+	if !tb.Equal(time.Date(2019, time.December, 29, 0, 0, 0, 0, time.UTC)) {
+		t.Fatalf("RoundForward: expected 2019-12-29T00:00:00Z; actual %s", tb)
+	}
 }
 }
 
 
 func TestRoundForward(t *testing.T) {
 func TestRoundForward(t *testing.T) {
@@ -165,6 +171,12 @@ func TestRoundForward(t *testing.T) {
 	if !tb.Equal(time.Date(2020, time.January, 2, 0, 0, 0, 0, time.UTC)) {
 	if !tb.Equal(time.Date(2020, time.January, 2, 0, 0, 0, 0, time.UTC)) {
 		t.Fatalf("RoundForward: expected 2020-01-02T00:00:00Z; actual %s", tb)
 		t.Fatalf("RoundForward: expected 2020-01-02T00:00:00Z; actual %s", tb)
 	}
 	}
+
+	to = time.Date(2020, time.January, 1, 23, 59, 0, 0, time.UTC)
+	tb = RoundForward(to, timeutil.Week)
+	if !tb.Equal(time.Date(2020, time.January, 5, 0, 0, 0, 0, time.UTC)) {
+		t.Fatalf("RoundForward: expected 2020-01-05T00:00:00Z; actual %s", tb)
+	}
 }
 }
 
 
 func TestParseWindowUTC(t *testing.T) {
 func TestParseWindowUTC(t *testing.T) {

+ 16 - 0
pkg/util/timeutil/timeutil.go

@@ -37,6 +37,8 @@ const (
 
 
 	// Day expresses 24 hours
 	// Day expresses 24 hours
 	Day = time.Hour * 24.0
 	Day = time.Hour * 24.0
+
+	Week = Day * 7.0
 )
 )
 
 
 // DurationString converts a duration to a Prometheus-compatible string in
 // DurationString converts a duration to a Prometheus-compatible string in
@@ -262,6 +264,20 @@ func FormatDurationStringDaysToHours(param string) (string, error) {
 	return param, nil
 	return param, nil
 }
 }
 
 
+// RoundToStartOfWeek creates a new time.Time for the preceding Monday 00:00 UTC
+func RoundToStartOfWeek(t time.Time) time.Time {
+	date := time.Date(t.Year(), t.Month(), t.Day(), 0, 0, 0, 0, time.UTC)
+	daysFromMonday := int(date.Weekday())
+	return date.Add(-1 * time.Duration(daysFromMonday) * Day)
+}
+
+// RoundToStartOfFollowingWeek creates a new time.Time for the following Monday 00:00 UTC
+func RoundToStartOfFollowingWeek(t time.Time) time.Time {
+	date := time.Date(t.Year(), t.Month(), t.Day(), 0, 0, 0, 0, time.UTC)
+	daysFromSunday := 7 - int(date.Weekday())
+	return date.Add(time.Duration(daysFromSunday) * Day)
+}
+
 // JobTicker is a ticker used to synchronize the next run of a repeating
 // JobTicker is a ticker used to synchronize the next run of a repeating
 // process. The designated use-case is for infinitely-looping selects,
 // process. The designated use-case is for infinitely-looping selects,
 // where a timeout or an exit channel might cancel the process, but otherwise
 // where a timeout or an exit channel might cancel the process, but otherwise