mirror of
https://github.com/fleetdm/fleet
synced 2026-04-21 13:37:30 +00:00
Add hostname to calendar event (maintenance window) bodies (#20235)
## Addresses #19281 <img width="825" alt="Screenshot 2024-07-05 at 10 47 25 AM" src="https://github.com/fleetdm/fleet/assets/61553566/d50ad460-b358-48aa-8e93-2f6d09472d87"> - [x] Changes file added for user-visible changes in `changes/`, - [x] Added/updated tests - [x] Manual QA for all new/changed functionality --------- Co-authored-by: Jacob Shandling <jacob@fleetdm.com>
This commit is contained in:
parent
28ca463d13
commit
20e1e4edfe
7 changed files with 41 additions and 24 deletions
Binary file not shown.
|
Before Width: | Height: | Size: 135 KiB After Width: | Height: | Size: 137 KiB |
1
changes/19281-add-host-name-to-event-descriptions
Normal file
1
changes/19281-add-host-name-to-event-descriptions
Normal file
|
|
@ -0,0 +1 @@
|
|||
* Add host's display name to calendar event descriptions
|
||||
|
|
@ -63,7 +63,7 @@ const CalendarEventPreviewModal = ({
|
|||
</div>
|
||||
<div className={`${baseClass}__preview-info__text`}>
|
||||
{orgName} reserved this time to make some changes to your work
|
||||
computer.
|
||||
computer (Anna's MacBook Pro).
|
||||
<br />
|
||||
<br />
|
||||
Please leave your device on and connected to power.
|
||||
|
|
|
|||
|
|
@ -242,8 +242,8 @@ const CalendarEventsModal = ({
|
|||
you must first connect Fleet to your Google Workspace service account.
|
||||
</div>
|
||||
<div>
|
||||
This can be configured in{" "}
|
||||
<b>Settings > Integrations > Calendars.</b>
|
||||
This can be configured in <b>Settings</b> > <b>Integrations</b>{" "}
|
||||
> <b>Calendars.</b>
|
||||
</div>
|
||||
<CustomLink
|
||||
url="https://www.fleetdm.com/learn-more-about/calendar-events"
|
||||
|
|
|
|||
|
|
@ -706,8 +706,8 @@ func TestCalendarEvents1KHosts(t *testing.T) {
|
|||
require.Len(t, createdCalendarEvents, 0)
|
||||
}
|
||||
|
||||
// TestEventDescription tests generation of the event description.
|
||||
func TestEventDescription(t *testing.T) {
|
||||
// TestEventBody tests generation of the event body.
|
||||
func TestEventBody(t *testing.T) {
|
||||
ds := new(mock.Store)
|
||||
ctx := context.Background()
|
||||
logger := kitlog.With(kitlog.NewLogfmtLogger(os.Stdout))
|
||||
|
|
@ -805,13 +805,13 @@ func TestEventDescription(t *testing.T) {
|
|||
}, nil
|
||||
}
|
||||
|
||||
hostID1, userEmail1 := uint(100), "user1@example.com"
|
||||
hostID2, userEmail2 := uint(101), "user2@example.com"
|
||||
hostID3, userEmail3 := uint(102), "user3@example.com"
|
||||
hostID4, userEmail4 := uint(103), "user4@example.com"
|
||||
hostID5, userEmail5 := uint(104), "user5@example.com"
|
||||
hostID6, userEmail6 := uint(105), "user6@example.com"
|
||||
hostID7, userEmail7 := uint(106), "user7@example.com"
|
||||
hostID1, userEmail1, hostDisplayName1 := uint(100), "user1@example.com", "Host 1"
|
||||
hostID2, userEmail2, hostDisplayName2 := uint(101), "user2@example.com", "Host 2"
|
||||
hostID3, userEmail3, hostDisplayName3 := uint(102), "user3@example.com", "Host 3"
|
||||
hostID4, userEmail4, hostDisplayName4 := uint(103), "user4@example.com", "Host 4"
|
||||
hostID5, userEmail5, hostDisplayName5 := uint(104), "user5@example.com", "Host 5"
|
||||
hostID6, userEmail6, hostDisplayName6 := uint(105), "user6@example.com", "Host 6"
|
||||
hostID7, userEmail7, hostDisplayName7 := uint(106), "user7@example.com", "Host 7"
|
||||
|
||||
ds.GetTeamHostsPolicyMembershipsFunc = func(
|
||||
ctx context.Context, domain string, teamID uint, policyIDs []uint, _ *uint,
|
||||
|
|
@ -823,42 +823,49 @@ func TestEventDescription(t *testing.T) {
|
|||
{
|
||||
HostID: hostID1,
|
||||
Email: userEmail1,
|
||||
HostDisplayName: hostDisplayName1,
|
||||
Passing: false,
|
||||
FailingPolicyIDs: fmt.Sprintf("%d", policyID1),
|
||||
},
|
||||
{
|
||||
HostID: hostID2,
|
||||
Email: userEmail2,
|
||||
HostDisplayName: hostDisplayName2,
|
||||
Passing: false,
|
||||
FailingPolicyIDs: fmt.Sprintf("%d", policyID2),
|
||||
},
|
||||
{
|
||||
HostID: hostID3,
|
||||
Email: userEmail3,
|
||||
HostDisplayName: hostDisplayName3,
|
||||
Passing: false,
|
||||
FailingPolicyIDs: fmt.Sprintf("%d", policyID3),
|
||||
},
|
||||
{
|
||||
HostID: hostID4,
|
||||
Email: userEmail4,
|
||||
HostDisplayName: hostDisplayName4,
|
||||
Passing: false,
|
||||
FailingPolicyIDs: fmt.Sprintf("%d", policyID4),
|
||||
},
|
||||
{
|
||||
HostID: hostID5,
|
||||
Email: userEmail5,
|
||||
HostDisplayName: hostDisplayName5,
|
||||
Passing: false,
|
||||
FailingPolicyIDs: fmt.Sprintf("%d,%d,%d,%d", policyID1, policyID2, policyID3, policyID4),
|
||||
},
|
||||
{
|
||||
HostID: hostID6,
|
||||
Email: userEmail6,
|
||||
HostDisplayName: hostDisplayName6,
|
||||
Passing: false,
|
||||
FailingPolicyIDs: fmt.Sprintf("%d", policyID1),
|
||||
},
|
||||
{
|
||||
HostID: hostID7,
|
||||
Email: userEmail7,
|
||||
HostDisplayName: hostDisplayName7,
|
||||
Passing: false,
|
||||
FailingPolicyIDs: fmt.Sprintf("%d", policyID5),
|
||||
},
|
||||
|
|
@ -956,15 +963,21 @@ func TestEventDescription(t *testing.T) {
|
|||
var details map[string]string
|
||||
err = json.Unmarshal(calendarEvents[hostCalEvent.HostID].Data, &details)
|
||||
require.NoError(t, err)
|
||||
description := createdCalendarEvents[details["id"]].Description
|
||||
defaultDescriptionWithOrg := fmt.Sprintf("%s %s", orgName, fleet.CalendarDefaultDescription)
|
||||
// What Google Calendar calls the "Description" is what Fleet calls the "Body," since the Body
|
||||
// contains a description and a resolution.
|
||||
eventBody := createdCalendarEvents[details["id"]].Description
|
||||
switch hostCalEvent.HostID {
|
||||
case hostID1, hostID6:
|
||||
assert.Contains(t, description, "Description for policy 1")
|
||||
assert.Contains(t, description, "Resolution for policy 1")
|
||||
case hostID1:
|
||||
assert.Contains(t, eventBody, fmt.Sprintf(`%s %s (Host 1).`, orgName, fleet.CalendarBodyStaticHeader))
|
||||
assert.Contains(t, eventBody, "Description for policy 1")
|
||||
assert.Contains(t, eventBody, "Resolution for policy 1")
|
||||
case hostID6:
|
||||
assert.Contains(t, eventBody, fmt.Sprintf(`%s %s (Host 6).`, orgName, fleet.CalendarBodyStaticHeader))
|
||||
assert.Contains(t, eventBody, "Description for policy 1")
|
||||
assert.Contains(t, eventBody, "Resolution for policy 1")
|
||||
default:
|
||||
assert.Contains(t, description, defaultDescriptionWithOrg)
|
||||
assert.Contains(t, description, fleet.CalendarDefaultResolution)
|
||||
assert.Contains(t, eventBody, fmt.Sprintf(`%s %s (Host`, orgName, fleet.CalendarBodyStaticHeader))
|
||||
assert.Contains(t, eventBody, fleet.CalendarDefaultResolution)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ import (
|
|||
)
|
||||
|
||||
const (
|
||||
CalendarBodyStaticHeader = "reserved this time to make some changes to your work computer"
|
||||
CalendarDefaultDescription = "needs to make sure your device meets the organization's requirements."
|
||||
CalendarDefaultResolution = "During this maintenance window, you can expect updates to be applied automatically. Your device may be unavailable during this time."
|
||||
)
|
||||
|
|
|
|||
|
|
@ -33,14 +33,15 @@ func CreateUserCalendarFromConfig(ctx context.Context, config *CalendarConfig, l
|
|||
}
|
||||
|
||||
func GenerateCalendarEventBody(ctx context.Context, ds fleet.Datastore, orgName string, host fleet.HostPolicyMembershipData,
|
||||
policyIDtoPolicy *sync.Map, conflict bool, logger kitlog.Logger) string {
|
||||
policyIDtoPolicy *sync.Map, conflict bool, logger kitlog.Logger,
|
||||
) string {
|
||||
description, resolution := getCalendarEventDescriptionAndResolution(ctx, ds, orgName, host, policyIDtoPolicy, logger)
|
||||
|
||||
conflictStr := ""
|
||||
if conflict {
|
||||
conflictStr = " because there was no remaining availability"
|
||||
conflictStr = "because there was no remaining availability "
|
||||
}
|
||||
return fmt.Sprintf(`%s reserved this time to make some changes to your work computer%s.
|
||||
return fmt.Sprintf(`%s %s %s(%s).
|
||||
|
||||
Please leave your device on and connected to power.
|
||||
|
||||
|
|
@ -49,11 +50,12 @@ Please leave your device on and connected to power.
|
|||
|
||||
<b>What we'll do</b>
|
||||
%s
|
||||
`, orgName, conflictStr, description, resolution)
|
||||
`, orgName, fleet.CalendarBodyStaticHeader, conflictStr, host.HostDisplayName, description, resolution)
|
||||
}
|
||||
|
||||
func getCalendarEventDescriptionAndResolution(ctx context.Context, ds fleet.Datastore, orgName string, host fleet.HostPolicyMembershipData,
|
||||
policyIDtoPolicy *sync.Map, logger kitlog.Logger) (string, string) {
|
||||
policyIDtoPolicy *sync.Map, logger kitlog.Logger,
|
||||
) (string, string) {
|
||||
getDefaultDescription := func() string {
|
||||
return fmt.Sprintf(`%s %s`, orgName, fleet.CalendarDefaultDescription)
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue