Skip to content

Commit

Permalink
feat(inspect): add role-configs command to list db roles with custom …
Browse files Browse the repository at this point in the history
…settings (#2818)

* added role-configs command to list users with custom settings

* Update internal/inspect/role_configs/role_configs.go

---------

Co-authored-by: Han Qiao <[email protected]>
  • Loading branch information
encima and sweatybridge authored Oct 31, 2024
1 parent cf2136a commit 68f9c56
Show file tree
Hide file tree
Showing 5 changed files with 103 additions and 1 deletion.
10 changes: 10 additions & 0 deletions cmd/inspect.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import (
"github.com/supabase/cli/internal/inspect/long_running_queries"
"github.com/supabase/cli/internal/inspect/outliers"
"github.com/supabase/cli/internal/inspect/replication_slots"
"github.com/supabase/cli/internal/inspect/role_configs"
"github.com/supabase/cli/internal/inspect/role_connections"
"github.com/supabase/cli/internal/inspect/seq_scans"
"github.com/supabase/cli/internal/inspect/table_index_sizes"
Expand Down Expand Up @@ -194,6 +195,14 @@ var (
},
}

inspectRoleConfigsCmd = &cobra.Command{
Use: "role-configs",
Short: "Show configuration settings for database roles when they have been modified",
RunE: func(cmd *cobra.Command, args []string) error {
return role_configs.Run(cmd.Context(), flags.DbConfig, afero.NewOsFs())
},
}

inspectRoleConnectionsCmd = &cobra.Command{
Use: "role-connections",
Short: "Show number of active connections for all database roles",
Expand Down Expand Up @@ -247,6 +256,7 @@ func init() {
inspectDBCmd.AddCommand(inspectTableRecordCountsCmd)
inspectDBCmd.AddCommand(inspectBloatCmd)
inspectDBCmd.AddCommand(inspectVacuumStatsCmd)
inspectDBCmd.AddCommand(inspectRoleConfigsCmd)
inspectDBCmd.AddCommand(inspectRoleConnectionsCmd)
inspectCmd.AddCommand(inspectDBCmd)
reportCmd.Flags().StringVar(&outputDir, "output-dir", "", "Path to save CSV files in")
Expand Down
5 changes: 4 additions & 1 deletion internal/inspect/report_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import (
"github.com/supabase/cli/internal/inspect/long_running_queries"
"github.com/supabase/cli/internal/inspect/outliers"
"github.com/supabase/cli/internal/inspect/replication_slots"
"github.com/supabase/cli/internal/inspect/role_configs"
"github.com/supabase/cli/internal/inspect/role_connections"
"github.com/supabase/cli/internal/inspect/seq_scans"
"github.com/supabase/cli/internal/inspect/table_index_sizes"
Expand Down Expand Up @@ -65,6 +66,8 @@ func TestReportCommand(t *testing.T) {
Reply("COPY 0").
Query(wrapQuery(replication_slots.ReplicationSlotsQuery)).
Reply("COPY 0").
Query(wrapQuery(role_configs.RoleConfigsQuery)).
Reply("COPY 0").
Query(wrapQuery(role_connections.RoleConnectionsQuery)).
Reply("COPY 0").
Query(wrapQuery(seq_scans.SeqScansQuery)).
Expand All @@ -89,7 +92,7 @@ func TestReportCommand(t *testing.T) {
assert.NoError(t, err)
matches, err := afero.Glob(fsys, "*.csv")
assert.NoError(t, err)
assert.Len(t, matches, 19)
assert.Len(t, matches, 20)
})
}

Expand Down
46 changes: 46 additions & 0 deletions internal/inspect/role_configs/role_configs.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package role_configs

import (
"context"
_ "embed"
"fmt"

"github.com/go-errors/errors"
"github.com/jackc/pgconn"
"github.com/jackc/pgx/v4"
"github.com/spf13/afero"
"github.com/supabase/cli/internal/migration/list"
"github.com/supabase/cli/internal/utils"
"github.com/supabase/cli/pkg/pgxv5"
)

//go:embed role_configs.sql
var RoleConfigsQuery string

type Result struct {
Role_name string
Custom_config string
}

func Run(ctx context.Context, config pgconn.Config, fsys afero.Fs, options ...func(*pgx.ConnConfig)) error {
conn, err := utils.ConnectByConfig(ctx, config, options...)
if err != nil {
return err
}
defer conn.Close(context.Background())
rows, err := conn.Query(ctx, RoleConfigsQuery)
if err != nil {
return errors.Errorf("failed to query rows: %w", err)
}
result, err := pgxv5.CollectRows[Result](rows)
if err != nil {
return err
}

table := "|Role name|Custom config|\n|-|-|\n"
for _, r := range result {
table += fmt.Sprintf("|`%s`|`%s`|\n", r.Role_name, r.Custom_config)
}

return list.RenderTable(table)
}
5 changes: 5 additions & 0 deletions internal/inspect/role_configs/role_configs.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
select
rolname as role_name,
array_to_string(rolconfig, ',', '*') as custom_config
from
pg_roles where rolconfig is not null;
38 changes: 38 additions & 0 deletions internal/inspect/role_configs/role_configs_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package role_configs

import (
"context"
"testing"

"github.com/jackc/pgconn"
"github.com/spf13/afero"
"github.com/stretchr/testify/assert"
"github.com/supabase/cli/pkg/pgtest"
)

var dbConfig = pgconn.Config{
Host: "127.0.0.1",
Port: 5432,
User: "admin",
Password: "password",
Database: "postgres",
}

func TestRoleCommand(t *testing.T) {
t.Run("inspects role connections", func(t *testing.T) {
// Setup in-memory fs
fsys := afero.NewMemMapFs()
// Setup mock postgres
conn := pgtest.NewConn()
defer conn.Close(t)
conn.Query(RoleConfigsQuery).
Reply("SELECT 1", Result{
Role_name: "postgres",
Custom_config: "statement_timeout=3s",
})
// Run test
err := Run(context.Background(), dbConfig, fsys, conn.Intercept)
// Check error
assert.NoError(t, err)
})
}

0 comments on commit 68f9c56

Please sign in to comment.