Skip to content

Commit

Permalink
Clarify active vs total playbooks
Browse files Browse the repository at this point in the history
  • Loading branch information
hanzei committed Nov 13, 2024
1 parent 74aea61 commit c0fbabb
Show file tree
Hide file tree
Showing 9 changed files with 134 additions and 53 deletions.
4 changes: 2 additions & 2 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,8 @@ require (
github.com/jmoiron/sqlx v1.4.0
github.com/lib/pq v1.10.9
github.com/mattermost/mattermost-plugin-playbooks/client v0.7.0
github.com/mattermost/mattermost/server/public v0.1.8
github.com/mattermost/mattermost/server/v8 v8.0.0-20241112090719-5eef415a39e1
github.com/mattermost/mattermost/server/public v0.1.9
github.com/mattermost/mattermost/server/v8 v8.0.0-20241113102039-053d0b5f0ad5
github.com/mattermost/morph v1.1.0
github.com/mitchellh/mapstructure v1.5.0
github.com/pkg/errors v0.9.1
Expand Down
8 changes: 4 additions & 4 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -295,10 +295,10 @@ github.com/mattermost/ldap v0.0.0-20231116144001-0f480c025956 h1:Y1Tu/swM31pVwwb
github.com/mattermost/ldap v0.0.0-20231116144001-0f480c025956/go.mod h1:SRl30Lb7/QoYyohYeVBuqYvvmXSZJxZgiV3Zf6VbxjI=
github.com/mattermost/logr/v2 v2.0.21 h1:CMHsP+nrbRlEC4g7BwOk1GAnMtHkniFhlSQPXy52be4=
github.com/mattermost/logr/v2 v2.0.21/go.mod h1:kZkB/zqKL9e+RY5gB3vGpsyenC+TpuiOenjMkvJJbzc=
github.com/mattermost/mattermost/server/public v0.1.8 h1:Z2PUXR4YGquuSo3ojNUl0aazOMSRqALjyMaf20jNIy4=
github.com/mattermost/mattermost/server/public v0.1.8/go.mod h1:SkTKbMul91Rq0v2dIxe8mqzUOY+3KwlwwLmAlxDfGCk=
github.com/mattermost/mattermost/server/v8 v8.0.0-20241112090719-5eef415a39e1 h1:qNW9//+lx3kwCETTCvqjrFgQ3SH0DyHusE3PnGJfHVE=
github.com/mattermost/mattermost/server/v8 v8.0.0-20241112090719-5eef415a39e1/go.mod h1:B4pQsrbZs6yO4GpWY6nCJPNG7myB0r3gvlFWWlGABmc=
github.com/mattermost/mattermost/server/public v0.1.9 h1:l/OKPRVuFeqL0yqRVC/JpveG5sLNKcT9llxqMkO9e+s=
github.com/mattermost/mattermost/server/public v0.1.9/go.mod h1:SkTKbMul91Rq0v2dIxe8mqzUOY+3KwlwwLmAlxDfGCk=
github.com/mattermost/mattermost/server/v8 v8.0.0-20241113102039-053d0b5f0ad5 h1:XVePV2EZhapQ6JIGFycfTd1QgxICvDs8rRUy3pqxagQ=
github.com/mattermost/mattermost/server/v8 v8.0.0-20241113102039-053d0b5f0ad5/go.mod h1:B4pQsrbZs6yO4GpWY6nCJPNG7myB0r3gvlFWWlGABmc=
github.com/mattermost/morph v1.1.0 h1:Q9vrJbeM3s2jfweGheq12EFIzdNp9a/6IovcbvOQ6Cw=
github.com/mattermost/morph v1.1.0/go.mod h1:gD+EaqX2UMyyuzmF4PFh4r33XneQ8Nzi+0E8nXjMa3A=
github.com/mattermost/rsc v0.0.0-20160330161541-bbaefb05eaa0 h1:G9tL6JXRBMzjuD1kkBtcnd42kUiT6QDwxfFYu7adM6o=
Expand Down
6 changes: 6 additions & 0 deletions server/app/playbook.go
Original file line number Diff line number Diff line change
Expand Up @@ -347,6 +347,9 @@ type PlaybookService interface {
// GetPlaybooks retrieves all playbooks
GetPlaybooks() ([]Playbook, error)

// GetActivePlaybooks retrieves all active playbooks
GetActivePlaybooks() ([]Playbook, error)

// GetPlaybooksForTeam retrieves all playbooks on the specified team given the provided options
GetPlaybooksForTeam(requesterInfo RequesterInfo, teamID string, opts PlaybookFilterOptions) (GetPlaybooksResults, error)

Expand Down Expand Up @@ -389,6 +392,9 @@ type PlaybookStore interface {
// GetPlaybooks retrieves all playbooks
GetPlaybooks() ([]Playbook, error)

// GetActivePlaybooks retrieves all active playbooks
GetActivePlaybooks() ([]Playbook, error)

// GetPlaybooksForTeam retrieves all playbooks on the specified team
GetPlaybooksForTeam(requesterInfo RequesterInfo, teamID string, opts PlaybookFilterOptions) (GetPlaybooksResults, error)

Expand Down
4 changes: 4 additions & 0 deletions server/app/playbook_service.go
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,10 @@ func (s *playbookService) GetPlaybooks() ([]Playbook, error) {
return s.store.GetPlaybooks()
}

func (s *playbookService) GetActivePlaybooks() ([]Playbook, error) {
return s.store.GetActivePlaybooks()
}

func (s *playbookService) GetPlaybooksForTeam(requesterInfo RequesterInfo, teamID string, opts PlaybookFilterOptions) (GetPlaybooksResults, error) {
return s.store.GetPlaybooksForTeam(requesterInfo, teamID, opts)
}
Expand Down
2 changes: 1 addition & 1 deletion server/command/command.go
Original file line number Diff line number Diff line change
Expand Up @@ -1154,7 +1154,7 @@ And... yes, of course, we have emojis
return
}

gotPlaybooks, err := r.playbookService.GetPlaybooks()
gotPlaybooks, err := r.playbookService.GetActivePlaybooks()
if err != nil {
r.postCommandResponse("There was an error while retrieving all playbooks. Err: " + err.Error())
return
Expand Down
108 changes: 66 additions & 42 deletions server/sqlstore/playbook.go
Original file line number Diff line number Diff line change
Expand Up @@ -334,58 +334,82 @@ func (p *playbookStore) Get(id string) (app.Playbook, error) {
return playbook, nil
}

func selectAllPlaybooks(builder sq.StatementBuilderType) sq.SelectBuilder {
return builder.Select(
"p.ID",
"p.Title",
"p.Description",
"p.TeamID",
"p.Public",
"p.CreatePublicIncident AS CreatePublicPlaybookRun",
"p.CreateAt",
"p.DeleteAt",
"p.NumStages",
"p.NumSteps",
"COUNT(i.ID) AS NumRuns",
"COALESCE(MAX(i.CreateAt), 0) AS LastRunAt",
`(
1 + -- Channel creation is hard-coded
CASE WHEN p.InviteUsersEnabled THEN 1 ELSE 0 END +
CASE WHEN p.DefaultCommanderEnabled THEN 1 ELSE 0 END +
CASE WHEN p.BroadcastEnabled THEN 1 ELSE 0 END +
CASE WHEN p.WebhookOnCreationEnabled THEN 1 ELSE 0 END +
CASE WHEN p.MessageOnJoinEnabled THEN 1 ELSE 0 END +
CASE WHEN p.WebhookOnStatusUpdateEnabled THEN 1 ELSE 0 END +
CASE WHEN p.SignalAnyKeywordsEnabled THEN 1 ELSE 0 END +
CASE WHEN p.CategorizeChannelEnabled THEN 1 ELSE 0 END +
CASE WHEN p.CreateChannelMemberOnNewParticipant THEN 1 ELSE 0 END +
CASE WHEN p.RemoveChannelMemberOnRemovedParticipant THEN 1 ELSE 0 END
) AS NumActions`,
"COALESCE(ChannelNameTemplate, '') ChannelNameTemplate",
"COALESCE(s.DefaultPlaybookAdminRole, 'playbook_admin') DefaultPlaybookAdminRole",
"COALESCE(s.DefaultPlaybookMemberRole, 'playbook_member') DefaultPlaybookMemberRole",
"COALESCE(s.DefaultRunAdminRole, 'run_admin') DefaultRunAdminRole",
"COALESCE(s.DefaultRunMemberRole, 'run_member') DefaultRunMemberRole",
).
From("IR_Playbook AS p").
LeftJoin("IR_Incident AS i ON p.ID = i.PlaybookID").
LeftJoin("Teams t ON t.Id = p.TeamID").
LeftJoin("Schemes s ON t.SchemeId = s.Id").
GroupBy("p.ID").
GroupBy("s.Id")
}

// GetPlaybooks retrieves all playbooks that are not deleted.
// Members are not retrieved for this as the query would be large and we don't need it for this for now.
// This is only used for the keywords feature
func (p *playbookStore) GetPlaybooks() ([]app.Playbook, error) {
func (p *playbookStore) GetActivePlaybooks() ([]app.Playbook, error) {
tx, err := p.store.db.Beginx()
if err != nil {
return nil, errors.Wrap(err, "could not begin transaction")
}
defer p.store.finalizeTransaction(tx)

var playbooks []app.Playbook
err = p.store.selectBuilder(tx, &playbooks, p.store.builder.
Select(
"p.ID",
"p.Title",
"p.Description",
"p.TeamID",
"p.Public",
"p.CreatePublicIncident AS CreatePublicPlaybookRun",
"p.CreateAt",
"p.DeleteAt",
"p.NumStages",
"p.NumSteps",
"COUNT(i.ID) AS NumRuns",
"COALESCE(MAX(i.CreateAt), 0) AS LastRunAt",
`(
1 + -- Channel creation is hard-coded
CASE WHEN p.InviteUsersEnabled THEN 1 ELSE 0 END +
CASE WHEN p.DefaultCommanderEnabled THEN 1 ELSE 0 END +
CASE WHEN p.BroadcastEnabled THEN 1 ELSE 0 END +
CASE WHEN p.WebhookOnCreationEnabled THEN 1 ELSE 0 END +
CASE WHEN p.MessageOnJoinEnabled THEN 1 ELSE 0 END +
CASE WHEN p.WebhookOnStatusUpdateEnabled THEN 1 ELSE 0 END +
CASE WHEN p.SignalAnyKeywordsEnabled THEN 1 ELSE 0 END +
CASE WHEN p.CategorizeChannelEnabled THEN 1 ELSE 0 END +
CASE WHEN p.CreateChannelMemberOnNewParticipant THEN 1 ELSE 0 END +
CASE WHEN p.RemoveChannelMemberOnRemovedParticipant THEN 1 ELSE 0 END
) AS NumActions`,
"COALESCE(ChannelNameTemplate, '') ChannelNameTemplate",
"COALESCE(s.DefaultPlaybookAdminRole, 'playbook_admin') DefaultPlaybookAdminRole",
"COALESCE(s.DefaultPlaybookMemberRole, 'playbook_member') DefaultPlaybookMemberRole",
"COALESCE(s.DefaultRunAdminRole, 'run_admin') DefaultRunAdminRole",
"COALESCE(s.DefaultRunMemberRole, 'run_member') DefaultRunMemberRole",
).
From("IR_Playbook AS p").
LeftJoin("IR_Incident AS i ON p.ID = i.PlaybookID").
LeftJoin("Teams t ON t.Id = p.TeamID").
LeftJoin("Schemes s ON t.SchemeId = s.Id").
Where(sq.Eq{"p.DeleteAt": 0}).
GroupBy("p.ID").
GroupBy("s.Id"))
err = p.store.selectBuilder(tx, &playbooks,
selectAllPlaybooks(p.store.builder).Where(sq.Eq{"p.DeleteAt": 0}),
)
if err == sql.ErrNoRows {
return nil, errors.Wrap(app.ErrNotFound, "no playbooks found")
} else if err != nil {
return nil, errors.Wrap(err, "failed to get playbooks")
}

return playbooks, nil
}

// GetPlaybooks retrieves all playbooks, even deleted ones.
// Members are not retrieved for this as the query would be large and we don't need it for this for now.
func (p *playbookStore) GetPlaybooks() ([]app.Playbook, error) {
tx, err := p.store.db.Beginx()
if err != nil {
return nil, errors.Wrap(err, "could not begin transaction")
}
defer p.store.finalizeTransaction(tx)

var playbooks []app.Playbook
err = p.store.selectBuilder(tx, &playbooks,
selectAllPlaybooks(p.store.builder),
)
if err == sql.ErrNoRows {
return nil, errors.Wrap(app.ErrNotFound, "no playbooks found")
} else if err != nil {
Expand Down
8 changes: 4 additions & 4 deletions server/sqlstore/playbook_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -879,7 +879,7 @@ func TestGetPlaybooksForTeam(t *testing.T) {
playbookStore := setupPlaybookStore(t, db)

t.Run(driverName+" - zero playbooks", func(t *testing.T) {
result, err := playbookStore.GetPlaybooks()
result, err := playbookStore.GetActivePlaybooks()
require.NoError(t, err)
require.ElementsMatch(t, []app.Playbook{}, result)
})
Expand Down Expand Up @@ -1343,7 +1343,7 @@ func TestGetPlaybooksForKeywords(t *testing.T) {
playbookStore := setupPlaybookStore(t, db)

t.Run("zero playbooks", func(t *testing.T) {
result, err := playbookStore.GetPlaybooks()
result, err := playbookStore.GetActivePlaybooks()
require.NoError(t, err)
require.ElementsMatch(t, []app.Playbook{}, result)
})
Expand Down Expand Up @@ -1420,7 +1420,7 @@ func TestGetTimeLastUpdated(t *testing.T) {
playbookStore := setupPlaybookStore(t, db)

t.Run("zero playbooks", func(t *testing.T) {
result, err := playbookStore.GetPlaybooks()
result, err := playbookStore.GetActivePlaybooks()
require.NoError(t, err)
require.ElementsMatch(t, []app.Playbook{}, result)

Expand Down Expand Up @@ -1539,7 +1539,7 @@ func TestGetPlaybookIDsForUser(t *testing.T) {
playbookStore := setupPlaybookStore(t, db)

t.Run("zero playbooks", func(t *testing.T) {
result, err := playbookStore.GetPlaybooks()
result, err := playbookStore.GetActivePlaybooks()
require.NoError(t, err)
require.ElementsMatch(t, []app.Playbook{}, result)
})
Expand Down
8 changes: 8 additions & 0 deletions server/support_packet.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ type SupportPacket struct {
Version string `yaml:"version"`
// The total number of playbooks.
TotalPlaybooks int64 `yaml:"total_playbooks"`
// The number of active playbooks.
ActivePlaybooks int64 `yaml:"active_playbooks"`
// The total number of playbook runs.
TotalPlaybookRuns int64 `yaml:"total_playbook_runs"`
}
Expand All @@ -28,6 +30,11 @@ func (p *Plugin) GenerateSupportData(_ *plugin.Context) ([]*model.FileData, erro
result = multierror.Append(result, errors.Wrap(err, "Failed to get total number of playbooks for Support Packet"))
}

activePlaybooks, err := p.playbookService.GetActivePlaybooks()
if err != nil {
result = multierror.Append(result, errors.Wrap(err, "Failed to get number of active playbooks for Support Packet"))
}

playbookRuns, err := p.playbookRunService.GetPlaybookRuns(app.RequesterInfo{IsAdmin: true}, app.PlaybookRunFilterOptions{SkipExtras: true})
if err != nil {
result = multierror.Append(result, errors.Wrap(err, "Failed to get total number of playbook runs for Support Packet"))
Expand All @@ -36,6 +43,7 @@ func (p *Plugin) GenerateSupportData(_ *plugin.Context) ([]*model.FileData, erro
diagnostics := SupportPacket{
Version: manifest.Version,
TotalPlaybooks: int64(len(playbooks)),
ActivePlaybooks: int64(len(activePlaybooks)),
TotalPlaybookRuns: int64(playbookRuns.TotalCount),
}
b, err := yaml.Marshal(diagnostics)
Expand Down
39 changes: 39 additions & 0 deletions server/support_packet_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package main

import (
"archive/zip"
"bytes"
"context"
"path"
"testing"

"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"gopkg.in/yaml.v3"
)

func TestGenerateSupportData(t *testing.T) {
e := Setup(t)
e.CreateBasic()

data, _, err := e.ServerAdminClient.GenerateSupportPacket(context.Background())
require.NoError(t, err)
require.NotEmpty(t, data)

zr, err := zip.NewReader(bytes.NewReader(data), int64(len(data)))
require.NoError(t, err)
require.NotNil(t, zr)

f, err := zr.Open(path.Join(manifest.Id, "diagnostics.yaml"))
require.NoError(t, err)
require.NotNil(t, f)

var sp SupportPacket
err = yaml.NewDecoder(f).Decode(&sp)
require.NoError(t, err)

assert.Equal(t, manifest.Version, sp.Version)
assert.Equal(t, int64(4), sp.TotalPlaybooks)
assert.Equal(t, int64(3), sp.ActivePlaybooks)
assert.Equal(t, int64(1), sp.TotalPlaybookRuns)
}

0 comments on commit c0fbabb

Please sign in to comment.