Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit bfa3cb2

Browse files
committed
fix: appropriate error message
1 parent 8574592 commit bfa3cb2

File tree

8 files changed

+88
-29
lines changed

8 files changed

+88
-29
lines changed

cli/server.go

Lines changed: 49 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -395,22 +395,18 @@ func (r *RootCmd) Server(newAPI func(context.Context, *coderd.Options) (*coderd.
395395

396396
config := r.createConfig()
397397

398-
if vals.PostgresURL != "" && (vals.PostgresHost != "" || vals.PostgresUsername != "" ||
399-
vals.PostgresPassword != "" || vals.PostgresDatabase != "") {
400-
return xerrors.New("cannot specify both --postgres-url and individual postgres connection flags " +
401-
"(--postgres-host, --postgres-username, etc). Please use only one connection method")
398+
if err := validatePostgresFlags(vals); err != nil {
399+
return xerrors.Errorf("validate postgres configuration: %w", err)
402400
}
403401

404402
if vals.PostgresURL == "" && vals.PostgresHost != "" && vals.PostgresUsername != "" && vals.PostgresPassword != "" && vals.PostgresDatabase != "" {
405-
pgURL := fmt.Sprintf("postgres://%s:%s@%s:%s/%s?%s",
406-
vals.PostgresUsername.String(),
407-
vals.PostgresPassword.String(),
408-
vals.PostgresHost.String(),
409-
vals.PostgresPort.String(),
410-
vals.PostgresDatabase.String(),
411-
vals.PostgresOptions.String(),
412-
)
413-
err = vals.PostgresURL.Set(pgURL)
403+
err = vals.PostgresURL.Set((&url.URL{
404+
Scheme: "postgres",
405+
User: url.UserPassword(vals.PostgresUsername.String(), vals.PostgresPassword.String()),
406+
Host: net.JoinHostPort(vals.PostgresHost.String(), vals.PostgresPort.String()),
407+
Path: "/" + vals.PostgresDatabase.String(),
408+
RawQuery: strings.Join(vals.PostgresOptions.GetSlice(), "&"),
409+
}).String())
414410
if err != nil {
415411
return err
416412
}
@@ -1271,6 +1267,46 @@ func (r *RootCmd) Server(newAPI func(context.Context, *coderd.Options) (*coderd.
12711267
return serverCmd
12721268
}
12731269

1270+
// validatePostgresFlags checks if the provided PostgreSQL connection flags are valid.
1271+
// It returns an error if:
1272+
// - Both postgres-url and individual flags are specified
1273+
// - Individual flags are used but some required flags are missing
1274+
func validatePostgresFlags(vals *codersdk.DeploymentValues) error {
1275+
// Check for conflicting connection methods
1276+
if vals.PostgresURL != "" && (vals.PostgresHost != "" || vals.PostgresUsername != "" ||
1277+
vals.PostgresPassword != "" || vals.PostgresDatabase != "") {
1278+
return xerrors.New("cannot specify both --postgres-url and individual postgres connection flags " +
1279+
"(--postgres-host, --postgres-username, etc), please specify only one connection method")
1280+
}
1281+
1282+
// Check for incomplete individual flag configuration
1283+
if vals.PostgresHost != "" || vals.PostgresUsername != "" || vals.PostgresPassword != "" || vals.PostgresDatabase != "" {
1284+
missingFlags := []string{}
1285+
if vals.PostgresHost == "" {
1286+
missingFlags = append(missingFlags, "--postgres-host")
1287+
}
1288+
if vals.PostgresUsername == "" {
1289+
missingFlags = append(missingFlags, "--postgres-username")
1290+
}
1291+
if vals.PostgresPassword == "" {
1292+
missingFlags = append(missingFlags, "--postgres-password")
1293+
}
1294+
if vals.PostgresDatabase == "" {
1295+
missingFlags = append(missingFlags, "--postgres-database")
1296+
}
1297+
1298+
if len(missingFlags) > 0 {
1299+
return xerrors.Errorf("incomplete postgres connection details - when using individual flags, all of the following are required: "+
1300+
"--postgres-host, --postgres-username, --postgres-password, --postgres-database\n"+
1301+
"Missing flags: %s\n"+
1302+
"Alternatively, use --postgres-url to specify the full connection URL",
1303+
strings.Join(missingFlags, ", "))
1304+
}
1305+
}
1306+
1307+
return nil
1308+
}
1309+
12741310
// templateHelpers builds a set of functions which can be called in templates.
12751311
// We build them here to avoid an import cycle by using coderd.Options in notifications.Manager.
12761312
// We can later use this to inject whitelabel fields when app name / logo URL are overridden.

cli/server_test.go

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -182,7 +182,7 @@ func TestServer(t *testing.T) {
182182
"--postgres-username", pgURL.User.Username(),
183183
"--postgres-password", password,
184184
"--postgres-database", database,
185-
"--postgres-options", pgURL.Query().Encode(),
185+
"--postgres-options", pgURL.Query().Encode()+",connect_timeout=30",
186186
)
187187

188188
clitest.Start(t, inv.WithContext(ctx))
@@ -205,18 +205,39 @@ func TestServer(t *testing.T) {
205205
"--access-url", "https://foobarbaz.mydomain",
206206
"--cache-dir", t.TempDir(),
207207
"--postgres-host", "localhost",
208-
"--postgres-host", "localhost",
209208
"--postgres-port", "5432",
210209
"--postgres-username", "coder",
211210
"--postgres-password", "password",
212211
"--postgres-database", "coder",
213-
"--postgres-options", "sslmode=disable",
212+
"--postgres-options", "sslmode=disable, connect_timeout=30",
214213
"--postgres-url", "postgres://coder:password@localhost:5432/coder?sslmode=disable",
215214
)
216215

217216
err := inv.WithContext(ctx).Run()
218217
require.Error(t, err)
219-
require.ErrorContains(t, err, "cannot specify both --postgres-url and individual postgres connection flags (--postgres-host, --postgres-username, etc). Please use only one connection method")
218+
require.ErrorContains(t, err, "cannot specify both --postgres-url and individual postgres connection flags (--postgres-host, --postgres-username, etc), please specify only one connection method")
219+
})
220+
221+
t.Run("IncompletePostgresConnectionFlags", func(t *testing.T) {
222+
t.Parallel()
223+
224+
ctx, cancelFunc := context.WithTimeout(context.Background(), testutil.WaitSuperLong*3)
225+
defer cancelFunc()
226+
227+
inv, _ := clitest.New(t,
228+
"server",
229+
"--http-address", ":0",
230+
"--access-url", "https://foobarbaz.mydomain",
231+
"--cache-dir", t.TempDir(),
232+
"--postgres-host", "localhost",
233+
"--postgres-port", "5432",
234+
"--postgres-database", "coder",
235+
"--postgres-options", "sslmode=disable",
236+
)
237+
238+
err := inv.WithContext(ctx).Run()
239+
require.Error(t, err)
240+
require.ErrorContains(t, err, "incomplete postgres connection details - when using individual flags, all of the following are required: --postgres-host, --postgres-username, --postgres-password, --postgres-database\n Missing flags: --postgres-username, --postgres-password\n Alternatively, use --postgres-url to specify the full connection URL")
220241
})
221242

222243
t.Run("BuiltinPostgres", func(t *testing.T) {

cli/testdata/coder_server_--help.golden

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -67,8 +67,9 @@ OPTIONS:
6767
--postgres-host string, $CODER_PG_HOST
6868
PostgreSQL server hostname.
6969

70-
--postgres-options string, $CODER_PG_OPTIONS
71-
PostgreSQL connection options (e.g. 'sslmode=require').
70+
--postgres-options string-array, $CODER_PG_OPTIONS
71+
PostgreSQL connection options (e.g. 'sslmode=require',
72+
'connect_timeout=30').
7273

7374
--postgres-password string, $CODER_PG_PASSWORD
7475
PostgreSQL password.

cli/testdata/server-config.yaml.golden

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -455,9 +455,9 @@ pgUsername: ""
455455
# PostgreSQL database name.
456456
# (default: <unset>, type: string)
457457
pgDatabase: ""
458-
# PostgreSQL connection options (e.g. 'sslmode=require').
459-
# (default: <unset>, type: string)
460-
pgOptions: ""
458+
# PostgreSQL connection options (e.g. 'sslmode=require', 'connect_timeout=30').
459+
# (default: <unset>, type: string-array)
460+
pgOptions: []
461461
# A URL to an external Terms of Service that must be accepted by users when
462462
# logging in.
463463
# (default: <unset>, type: string)

codersdk/deployment.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -357,7 +357,7 @@ type DeploymentValues struct {
357357
PostgresUsername serpent.String `json:"pg_username,omitempty" typescript:",notnull"`
358358
PostgresPassword serpent.String `json:"pg_password,omitempty" typescript:",notnull"`
359359
PostgresDatabase serpent.String `json:"pg_database,omitempty" typescript:",notnull"`
360-
PostgresOptions serpent.String `json:"pg_options,omitempty" typescript:",notnull"`
360+
PostgresOptions serpent.StringArray `json:"pg_options,omitempty" typescript:",notnull"`
361361
OAuth2 OAuth2Config `json:"oauth2,omitempty" typescript:",notnull"`
362362
OIDC OIDCConfig `json:"oidc,omitempty" typescript:",notnull"`
363363
Telemetry TelemetryConfig `json:"telemetry,omitempty" typescript:",notnull"`
@@ -2315,7 +2315,7 @@ when required by your organization's security policy.`,
23152315
},
23162316
{
23172317
Name: "Postgres Options",
2318-
Description: "PostgreSQL connection options (e.g. 'sslmode=require').",
2318+
Description: "PostgreSQL connection options (e.g. 'sslmode=require', 'connect_timeout=30').",
23192319
Flag: "postgres-options",
23202320
Env: "CODER_PG_OPTIONS",
23212321
Value: &c.PostgresOptions,

docs/reference/cli/server.md

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

enterprise/cli/testdata/coder_server_--help.golden

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -68,8 +68,9 @@ OPTIONS:
6868
--postgres-host string, $CODER_PG_HOST
6969
PostgreSQL server hostname.
7070

71-
--postgres-options string, $CODER_PG_OPTIONS
72-
PostgreSQL connection options (e.g. 'sslmode=require').
71+
--postgres-options string-array, $CODER_PG_OPTIONS
72+
PostgreSQL connection options (e.g. 'sslmode=require',
73+
'connect_timeout=30').
7374

7475
--postgres-password string, $CODER_PG_PASSWORD
7576
PostgreSQL password.

site/src/api/typesGenerated.ts

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)