Skip to content

Commit bf4e924

Browse files
committed
Add connection URL output when creating or resetting Postgres roles
Display credentials in a vertical layout with DATABASE URL when creating a role or resetting a role's password. This makes it easier for users to copy the connection string directly. Human output: ID role-abc123 NAME my-role USERNAME my-role_abc123 PASSWORD secretpass123 ACCESS HOST URL pg.psdb.cloud DATABASE URL postgresql://... JSON/CSV output includes the new database_url field. The connection URL follows the format: postgresql://username:password@host:port/postgres?sslmode=verify-full
1 parent 0bcf3b5 commit bf4e924

4 files changed

Lines changed: 39 additions & 1 deletion

File tree

internal/cmd/role/create.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,8 @@ func CreateCmd(ch *cmdutil.Helper) *cobra.Command {
6666
saveWarning := printer.BoldRed("Please save the values below as they will not be shown again")
6767
ch.Printer.Printf("Role %s was successfully created in %s/%s.\n%s\n\n",
6868
printer.BoldBlue(role.Name), printer.BoldBlue(database), printer.BoldBlue(branch), saveWarning)
69+
printPostgresRoleCredentials(ch.Printer, toPostgresRole(role))
70+
return nil
6971
}
7072

7173
return ch.Printer.PrintResource(toPostgresRole(role))

internal/cmd/role/reset.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,8 +90,10 @@ func ResetCmd(ch *cmdutil.Helper) *cobra.Command {
9090
end()
9191

9292
if ch.Printer.Format() == printer.Human {
93-
ch.Printer.Printf("Password for role %s was successfully reset in %s/%s.\n",
93+
ch.Printer.Printf("Password for role %s was successfully reset in %s/%s.\n\n",
9494
printer.BoldBlue(roleID), printer.BoldBlue(database), printer.BoldBlue(branch))
95+
printPostgresRoleCredentials(ch.Printer, toPostgresRole(role))
96+
return nil
9597
}
9698

9799
return ch.Printer.PrintResource(toPostgresRole(role))

internal/cmd/role/reset_default.go

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ package role
33
import (
44
"errors"
55
"fmt"
6+
"net"
7+
"net/url"
68
"os"
79

810
"github.com/AlecAivazis/survey/v2"
@@ -91,6 +93,8 @@ func ResetDefaultCmd(ch *cmdutil.Helper) *cobra.Command {
9193
saveWarning := printer.BoldRed("Please save the values below as they will not be shown again. We recommend using these credentials only for creating usernames and passwords for accessing your database.")
9294

9395
ch.Printer.Printf("Role was successfully reset for %s in %s.\n%s\n\n", printer.BoldBlue(branch), printer.BoldBlue(database), saveWarning)
96+
printPostgresRoleCredentials(ch.Printer, toPostgresRole(role))
97+
return nil
9498
}
9599

96100
return ch.Printer.PrintResource(toPostgresRole(role))
@@ -108,6 +112,7 @@ type PostgresRole struct {
108112
Username string `header:"username" json:"username"`
109113
Password string `header:"password" json:"password"`
110114
AccessHostURL string `header:"access_host_url" json:"access_host_url"`
115+
DatabaseURL string `header:"database_url" json:"database_url"`
111116

112117
orig *ps.PostgresRole
113118
}
@@ -119,6 +124,34 @@ func toPostgresRole(role *ps.PostgresRole) *PostgresRole {
119124
Username: role.Username,
120125
Password: role.Password,
121126
AccessHostURL: role.AccessHostURL,
127+
DatabaseURL: buildPostgresConnectionURL(role.Username, role.Password, role.AccessHostURL),
122128
orig: role,
123129
}
124130
}
131+
132+
// printPostgresRoleCredentials prints role credentials in a vertical layout.
133+
func printPostgresRoleCredentials(p *printer.Printer, role *PostgresRole) {
134+
p.Printf("%-17s %s\n", "ID", role.PublicID)
135+
p.Printf("%-17s %s\n", "NAME", role.Name)
136+
p.Printf("%-17s %s\n", "USERNAME", role.Username)
137+
p.Printf("%-17s %s\n", "PASSWORD", role.Password)
138+
p.Printf("%-17s %s\n", "ACCESS HOST URL", role.AccessHostURL)
139+
p.Printf("%-17s %s\n", "DATABASE URL", role.DatabaseURL)
140+
}
141+
142+
// buildPostgresConnectionURL constructs a PostgreSQL connection URL from role credentials.
143+
func buildPostgresConnectionURL(username, password, accessHostURL string) string {
144+
host, port, err := net.SplitHostPort(accessHostURL)
145+
if err != nil {
146+
// If no port specified, use the host as-is and default to 5432
147+
host = accessHostURL
148+
port = "5432"
149+
}
150+
151+
return fmt.Sprintf("postgresql://%s:%s@%s:%s/postgres?sslmode=verify-full",
152+
url.PathEscape(username),
153+
url.PathEscape(password),
154+
host,
155+
port,
156+
)
157+
}

internal/cmd/role/reset_default_test.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ func TestResetDefaultCmd(t *testing.T) {
6868
"username": "postgres",
6969
"password": "new-password-123",
7070
"access_host_url": "pg.psdb.cloud",
71+
"database_url": "postgresql://postgres:new-password-123@pg.psdb.cloud:5432/postgres?sslmode=verify-full",
7172
}
7273
c.Assert(buf.String(), qt.JSONEquals, expectedOutput)
7374
}

0 commit comments

Comments
 (0)