From c6e2e8d6c42493ab985fc5a2aac07c9609cf1f75 Mon Sep 17 00:00:00 2001 From: Lucas Manuel Rodriguez Date: Fri, 22 Mar 2024 14:16:08 -0300 Subject: [PATCH] Always create event next 3rd Tuesday (#17799) Fix to always create events for next 3rd Tuesday #17441 --- cmd/fleet/calendar_cron.go | 32 +++------ cmd/fleet/calendar_cron_test.go | 113 +++++++++++++++++++------------- 2 files changed, 77 insertions(+), 68 deletions(-) diff --git a/cmd/fleet/calendar_cron.go b/cmd/fleet/calendar_cron.go index 17962f1847..238260ea3a 100644 --- a/cmd/fleet/calendar_cron.go +++ b/cmd/fleet/calendar_cron.go @@ -198,7 +198,6 @@ func processCalendarFailingHosts( hostCalendarEvent, calendarEvent, err := ds.GetHostCalendarEventByEmail(ctx, host.Email) expiredEvent := false - webhookAlreadyFiredThisMonth := false if err == nil { if hostCalendarEvent.HostID != host.HostID { // This calendar event belongs to another host with this associated email, @@ -217,7 +216,6 @@ func processCalendarFailingHosts( // we give a grace period of one day for the host before we schedule a new event. continue // continue with next host } - webhookAlreadyFiredThisMonth = webhookAlreadyFired && sameMonth(now, calendarEvent.StartTime) if calendarEvent.EndTime.Before(now) { expiredEvent = true } @@ -237,7 +235,7 @@ func processCalendarFailingHosts( } case fleet.IsNotFound(err) || expiredEvent: if err := processFailingHostCreateCalendarEvent( - ctx, ds, userCalendar, orgName, host, webhookAlreadyFiredThisMonth, + ctx, ds, userCalendar, orgName, host, ); err != nil { level.Info(logger).Log("msg", "process failing host create calendar event", "err", err) continue // continue with next host @@ -357,21 +355,14 @@ func sameDate(t1 time.Time, t2 time.Time) bool { return y1 == y2 && m1 == m2 && d1 == d2 } -func sameMonth(t1 time.Time, t2 time.Time) bool { - y1, m1, _ := t1.Date() - y2, m2, _ := t2.Date() - return y1 == y2 && m1 == m2 -} - func processFailingHostCreateCalendarEvent( ctx context.Context, ds fleet.Datastore, userCalendar fleet.UserCalendar, orgName string, host fleet.HostPolicyMembershipData, - webhookAlreadyFiredThisMonth bool, ) error { - calendarEvent, err := attemptCreatingEventOnUserCalendar(orgName, host, userCalendar, webhookAlreadyFiredThisMonth) + calendarEvent, err := attemptCreatingEventOnUserCalendar(orgName, host, userCalendar) if err != nil { return fmt.Errorf("create event on user calendar: %w", err) } @@ -385,10 +376,9 @@ func attemptCreatingEventOnUserCalendar( orgName string, host fleet.HostPolicyMembershipData, userCalendar fleet.UserCalendar, - webhookAlreadyFiredThisMonth bool, ) (*fleet.CalendarEvent, error) { year, month, today := time.Now().Date() - preferredDate := getPreferredCalendarEventDate(year, month, today, webhookAlreadyFiredThisMonth) + preferredDate := getPreferredCalendarEventDate(year, month, today) for { calendarEvent, err := userCalendar.CreateEvent( preferredDate, func(conflict bool) string { @@ -408,10 +398,7 @@ func attemptCreatingEventOnUserCalendar( } } -func getPreferredCalendarEventDate( - year int, month time.Month, today int, - webhookAlreadyFired bool, -) time.Time { +func getPreferredCalendarEventDate(year int, month time.Month, today int) time.Time { const ( // 3rd Tuesday of Month preferredWeekDay = time.Tuesday @@ -425,12 +412,13 @@ func getPreferredCalendarEventDate( } preferredDate := firstDayOfMonth.AddDate(0, 0, offset+(7*(preferredOrdinal-1))) if today > preferredDate.Day() { - today_ := time.Date(year, month, today, 0, 0, 0, 0, time.UTC) - if webhookAlreadyFired { - nextMonth := today_.AddDate(0, 1, 0) // move to next month - return getPreferredCalendarEventDate(nextMonth.Year(), nextMonth.Month(), 1, false) + // We are past the preferred date, so we move to next month and calculate again. + month := month + 1 + if month == 13 { + month = 1 + year += 1 } - preferredDate = addBusinessDay(today_) + return getPreferredCalendarEventDate(year, month, 1) } return preferredDate } diff --git a/cmd/fleet/calendar_cron_test.go b/cmd/fleet/calendar_cron_test.go index 905b79c879..84f5ece527 100644 --- a/cmd/fleet/calendar_cron_test.go +++ b/cmd/fleet/calendar_cron_test.go @@ -12,72 +12,93 @@ func TestGetPreferredCalendarEventDate(t *testing.T) { return time.Date(year, month, day, 0, 0, 0, 0, time.UTC) } for _, tc := range []struct { - name string - year int - month time.Month - daysStart int - daysEnd int - webhookFiredThisMonth bool + name string + year int + month time.Month + daysStart int + daysEnd int expected time.Time }{ { - name: "March 2024 (webhook hasn't fired)", - year: 2024, - month: 3, - daysStart: 1, - daysEnd: 31, - webhookFiredThisMonth: false, + name: "March 2024 (before 3rd Tuesday)", + year: 2024, + month: 3, + daysStart: 1, + daysEnd: 19, expected: date(2024, 3, 19), }, { - name: "March 2024 (webhook has fired, days before 3rd Tuesday)", - year: 2024, - month: 3, - daysStart: 1, - daysEnd: 18, - webhookFiredThisMonth: true, - - expected: date(2024, 3, 19), - }, - { - name: "March 2024 (webhook has fired, days after 3rd Tuesday)", - year: 2024, - month: 3, - daysStart: 20, - daysEnd: 30, - webhookFiredThisMonth: true, + name: "March 2024 (past 3rd Tuesday)", + year: 2024, + month: 3, + daysStart: 20, + daysEnd: 31, expected: date(2024, 4, 16), }, { - name: "April 2024 (webhook hasn't fired)", - year: 2024, - month: 4, - daysEnd: 30, - webhookFiredThisMonth: false, + name: "April 2024 (before 3rd Tuesday)", + year: 2024, + month: 4, + daysStart: 1, + daysEnd: 16, expected: date(2024, 4, 16), }, + { + name: "April 2024 (after 3rd Tuesday)", + year: 2024, + month: 4, + daysStart: 17, + daysEnd: 30, + + expected: date(2024, 5, 21), + }, + { + name: "May 2024 (before 3rd Tuesday)", + year: 2024, + month: 5, + daysStart: 1, + daysEnd: 21, + + expected: date(2024, 5, 21), + }, + { + name: "May 2024 (after 3rd Tuesday)", + year: 2024, + month: 5, + daysStart: 22, + daysEnd: 31, + + expected: date(2024, 6, 18), + }, + { + name: "Dec 2024 (before 3rd Tuesday)", + year: 2024, + month: 12, + daysStart: 1, + daysEnd: 17, + + expected: date(2024, 12, 17), + }, + { + name: "Dec 2024 (after 3rd Tuesday)", + year: 2024, + month: 12, + daysStart: 18, + daysEnd: 31, + + expected: date(2025, 1, 21), + }, } { t.Run(tc.name, func(t *testing.T) { for day := tc.daysStart; day <= tc.daysEnd; day++ { - actual := getPreferredCalendarEventDate(tc.year, tc.month, day, tc.webhookFiredThisMonth) + actual := getPreferredCalendarEventDate(tc.year, tc.month, day) require.NotEqual(t, actual.Weekday(), time.Saturday) require.NotEqual(t, actual.Weekday(), time.Sunday) - if day <= tc.expected.Day() || tc.webhookFiredThisMonth { - require.Equal(t, tc.expected, actual) - } else { - today := date(tc.year, tc.month, day) - if weekday := today.Weekday(); weekday == time.Friday { - require.Equal(t, today.AddDate(0, 0, +3), actual) - } else if weekday == time.Saturday { - require.Equal(t, today.AddDate(0, 0, +2), actual) - } else { - require.Equal(t, today.AddDate(0, 0, +1), actual) - } - } + require.Equal(t, tc.expected, actual) } }) }