Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 29 additions & 8 deletions tool/tsh/common/db.go
Original file line number Diff line number Diff line change
Expand Up @@ -1012,11 +1012,20 @@ func listDatabasesByName(ctx context.Context, tc *client.TeleportClient, name st
return listDatabasesWithPredicate(ctx, tc, predicate)
}

// makePrefixPredicate returns a predicate expression that matches resources
// by prefix name.
func makePrefixPredicate(prefix string) string {
if prefix == "" {
return ""
}
return fmt.Sprintf(`hasPrefix(name, %q)`, prefix)
}

// listDatabasesByPrefix lists databases that match a given name prefix.
func listDatabasesByPrefix(ctx context.Context, tc *client.TeleportClient, prefix string) (types.Databases, error) {
predicate := fmt.Sprintf(`hasPrefix(name, %q)`, prefix)
predicate := makePrefixPredicate(prefix)
databases, err := listDatabasesWithPredicate(ctx, tc, predicate)
if err == nil || !utils.IsPredicateError(err) {
if err == nil || !utils.IsPredicateError(err) || predicate == "" {
return databases, trace.Wrap(err)
}
// predicate error from using hasPrefix expression.
Expand All @@ -1039,25 +1048,37 @@ func listDatabasesByPrefix(ctx context.Context, tc *client.TeleportClient, prefi
// a given additional predicate expression. If the teleport client already
// has a predicate expression, the predicates are combined with a logical AND.
func listDatabasesWithPredicate(ctx context.Context, tc *client.TeleportClient, predicate string) (types.Databases, error) {
if predicate == "" {
predicate = tc.PredicateExpression
} else if tc.PredicateExpression != "" {
predicate = fmt.Sprintf("(%v) && (%v)", predicate, tc.PredicateExpression)
}
var databases []types.Database
err := client.RetryWithRelogin(ctx, tc, func() error {
var err error
databases, err = tc.ListDatabases(ctx, &proto.ListResourcesRequest{
Namespace: tc.Namespace,
ResourceType: types.KindDatabaseServer,
PredicateExpression: predicate,
PredicateExpression: combinePredicateExpressions(predicate, tc.PredicateExpression),
Labels: tc.Labels,
})
return trace.Wrap(err)
})
return databases, trace.Wrap(err)
}

// combinePredicateExpressions combines two predicate expressions into one
// expression as a conjunction (logical AND) of the expressions.
func combinePredicateExpressions(a, b string) string {
Comment thread
GavinFrazar marked this conversation as resolved.
Outdated
a = strings.TrimSpace(a)
b = strings.TrimSpace(b)
switch {
case a == "":
return b
case b == "":
return a
case a == b:
return a
default:
return fmt.Sprintf("(%v) && (%v)", a, b)
}
}

// getDefaultDBUser enumerates the allowed database users for a given database
// and selects one if it is the only non-wildcard database user allowed.
// Returns an error if there are no allowed database users or more than one.
Expand Down