feat: Include and exclude databases

- Add filters to include and exclude strings
- Use filters to include and exclude sessions (user and databases supported)
- Add tests to filters and terminator

Signed-off-by: Julien Riou <julien@riou.xyz>
This commit is contained in:
Julien Riou 2023-01-14 09:56:38 +01:00
commit 8709ee542b
No known key found for this signature in database
GPG key ID: A2EB1F2CA8E3F677
9 changed files with 549 additions and 49 deletions

View file

@ -1,10 +1,11 @@
package terminator
import (
"github.com/jouir/pgterminate/base"
"github.com/jouir/pgterminate/log"
"strings"
"time"
"github.com/jouir/pgterminate/base"
"github.com/jouir/pgterminate/log"
)
// Terminator looks for sessions, filters actives and idles, terminate them and notify sessions channel
@ -71,30 +72,6 @@ func (t *Terminator) notify(sessions []*base.Session) {
}
}
// filterUsers removes sessions according to include and exclude users settings
// when include users slice and regex are not set, append all sessions except excluded users
// otherwise, append included users
func (t *Terminator) filterUsers(sessions []*base.Session) (filtered []*base.Session) {
includeUsers, includeRegex := t.config.IncludeUsers, t.config.IncludeUsersRegexCompiled
excludeUsers, excludeRegex := t.config.ExcludeUsers, t.config.ExcludeUsersRegexCompiled
for _, session := range sessions {
if t.config.IncludeUsers == nil && includeRegex == nil {
// append all sessions except excluded users
if !base.InSlice(session.User, excludeUsers) && (excludeRegex != nil && !excludeRegex.MatchString(session.User)) {
filtered = append(filtered, session)
}
} else {
// append included users only
if base.InSlice(session.User, includeUsers) || (includeRegex != nil && includeRegex.MatchString(session.User)) {
filtered = append(filtered, session)
}
}
}
return filtered
}
// filterListeners excludes sessions with last query starting with "LISTEN"
func (t *Terminator) filterListeners(sessions []*base.Session) (filtered []*base.Session) {
for _, session := range sessions {
@ -105,11 +82,75 @@ func (t *Terminator) filterListeners(sessions []*base.Session) (filtered []*base
return filtered
}
// filterUsers include and exclude users based on filters
func (t *Terminator) filterUsers(sessions []*base.Session) []*base.Session {
var included []*base.Session
if t.config.IncludeUsersFilters == nil {
included = sessions
} else {
for _, filter := range t.config.IncludeUsersFilters {
for _, session := range sessions {
if filter.Include(session.User) {
included = append(included, session)
}
}
}
}
var filtered []*base.Session
if t.config.ExcludeUsersFilters == nil {
filtered = included
} else {
for _, filter := range t.config.ExcludeUsersFilters {
for _, session := range included {
if filter.Include(session.User) {
filtered = append(filtered, session)
}
}
}
}
return filtered
}
// filterUsers include and exclude databases based on filters
func (t *Terminator) filterDatabases(sessions []*base.Session) []*base.Session {
var included []*base.Session
if t.config.IncludeDatabasesFilters == nil {
included = sessions
} else {
for _, filter := range t.config.IncludeDatabasesFilters {
for _, session := range sessions {
if filter.Include(session.Db) {
included = append(included, session)
}
}
}
}
var filtered []*base.Session
if t.config.ExcludeDatabasesFilters == nil {
filtered = included
} else {
for _, filter := range t.config.ExcludeDatabasesFilters {
for _, session := range included {
if filter.Include(session.Db) {
filtered = append(filtered, session)
}
}
}
}
return filtered
}
// filter executes all filter functions on a list of sessions
func (t *Terminator) filter(sessions []*base.Session) (filtered []*base.Session) {
filtered = sessions
filtered = t.filterListeners(sessions)
filtered = t.filterUsers(filtered)
filtered = t.filterListeners(filtered)
filtered = t.filterDatabases(filtered)
return filtered
}