This repository has been archived by the owner on Aug 22, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 30
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add support of environment variables.
pgSCV can be configured using config file only, which might be tricky in containerized environments (requires volumes for config). This commit allows define basic configuration using environment variables. This is not support complex configuration related to collectors settings or user-defined metrics.
- Loading branch information
Showing
5 changed files
with
267 additions
and
17 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
package service | ||
|
||
import ( | ||
"fmt" | ||
"strings" | ||
) | ||
|
||
// ConnSetting describes connection settings required for connecting to particular service. | ||
// This is primarily used for describing services defined by user in the config file (or env vars). | ||
type ConnSetting struct { | ||
// ServiceType defines type of service for which these connection settings are used. | ||
ServiceType string `yaml:"service_type"` | ||
// Conninfo is the connection string in service-specific format. | ||
Conninfo string `yaml:"conninfo"` | ||
} | ||
|
||
// ConnsSettings defines a set of all connection settings of exact services. | ||
type ConnsSettings map[string]ConnSetting | ||
|
||
// ParsePostgresDSNEnv is a public wrapper over parseDSNEnv. | ||
func ParsePostgresDSNEnv(key, value string) (string, ConnSetting, error) { | ||
return parseDSNEnv("POSTGRES_DSN", key, value) | ||
} | ||
|
||
// ParsePgbouncerDSNEnv is a public wrapper over parseDSNEnv. | ||
func ParsePgbouncerDSNEnv(key, value string) (string, ConnSetting, error) { | ||
return parseDSNEnv("PGBOUNCER_DSN", key, value) | ||
} | ||
|
||
// parseDSNEnv returns valid ConnSetting accordingly to passed prefix and environment key/value. | ||
func parseDSNEnv(prefix, key, value string) (string, ConnSetting, error) { | ||
var stype string | ||
switch prefix { | ||
case "POSTGRES_DSN": | ||
stype = "postgres" | ||
case "PGBOUNCER_DSN": | ||
stype = "pgbouncer" | ||
default: | ||
return "", ConnSetting{}, fmt.Errorf("invalid prefix %s", prefix) | ||
} | ||
|
||
// Prefix must be the part of key. | ||
if !strings.HasPrefix(key, prefix) { | ||
return "", ConnSetting{}, fmt.Errorf("invalid key %s", key) | ||
} | ||
|
||
// Nothing to parse if prefix and key are the same, just use the type as service ID. | ||
if key == prefix { | ||
return stype, ConnSetting{ServiceType: stype, Conninfo: value}, nil | ||
} | ||
|
||
// If prefix and key are not the same, strip prefix from key and use the rest as service ID. | ||
// Use double Trim to avoid leaking 'prefix' string into ID value (see unit tests for examples). | ||
id := strings.TrimPrefix(strings.TrimPrefix(key, prefix), "_") | ||
|
||
if id == "" { | ||
return "", ConnSetting{}, fmt.Errorf("invalid value '%s' is in %s", value, key) | ||
} | ||
|
||
return id, ConnSetting{ServiceType: stype, Conninfo: value}, nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
package service | ||
|
||
import ( | ||
"github.com/stretchr/testify/assert" | ||
"testing" | ||
) | ||
|
||
func Test_ParsePostgresDSNEnv(t *testing.T) { | ||
gotID, gotCS, err := ParsePostgresDSNEnv("POSTGRES_DSN", "conninfo") | ||
assert.NoError(t, err) | ||
assert.Equal(t, "postgres", gotID) | ||
assert.Equal(t, ConnSetting{ServiceType: "postgres", Conninfo: "conninfo"}, gotCS) | ||
|
||
_, _, err = ParsePostgresDSNEnv("INVALID", "conninfo") | ||
assert.Error(t, err) | ||
} | ||
|
||
func Test_ParsePgbouncerDSNEnv(t *testing.T) { | ||
gotID, gotCS, err := ParsePgbouncerDSNEnv("PGBOUNCER_DSN", "conninfo") | ||
assert.NoError(t, err) | ||
assert.Equal(t, "pgbouncer", gotID) | ||
assert.Equal(t, ConnSetting{ServiceType: "pgbouncer", Conninfo: "conninfo"}, gotCS) | ||
|
||
_, _, err = ParsePgbouncerDSNEnv("INVALID", "conninfo") | ||
assert.Error(t, err) | ||
} | ||
|
||
func Test_parseDSNEnv(t *testing.T) { | ||
testcases := []struct { | ||
valid bool | ||
prefix string | ||
key string | ||
wantId string | ||
wantType string | ||
}{ | ||
{valid: true, prefix: "POSTGRES_DSN", key: "POSTGRES_DSN", wantId: "postgres", wantType: "postgres"}, | ||
{valid: true, prefix: "POSTGRES_DSN", key: "POSTGRES_DSN_POSTGRES_123", wantId: "POSTGRES_123", wantType: "postgres"}, | ||
{valid: true, prefix: "POSTGRES_DSN", key: "POSTGRES_DSN1", wantId: "1", wantType: "postgres"}, | ||
{valid: true, prefix: "POSTGRES_DSN", key: "POSTGRES_DSN_POSTGRES_5432", wantId: "POSTGRES_5432", wantType: "postgres"}, | ||
{valid: true, prefix: "PGBOUNCER_DSN", key: "PGBOUNCER_DSN", wantId: "pgbouncer", wantType: "pgbouncer"}, | ||
{valid: true, prefix: "PGBOUNCER_DSN", key: "PGBOUNCER_DSN_PGBOUNCER_123", wantId: "PGBOUNCER_123", wantType: "pgbouncer"}, | ||
{valid: true, prefix: "PGBOUNCER_DSN", key: "PGBOUNCER_DSN1", wantId: "1", wantType: "pgbouncer"}, | ||
{valid: true, prefix: "PGBOUNCER_DSN", key: "PGBOUNCER_DSN_PGBOUNCER_6432", wantId: "PGBOUNCER_6432", wantType: "pgbouncer"}, | ||
{valid: false, prefix: "POSTGRES_DSN", key: "POSTGRES_DSN_"}, | ||
{valid: false, prefix: "POSTGRES_DSN", key: "INVALID"}, | ||
{valid: false, prefix: "INVALID", key: "INVALID"}, | ||
} | ||
|
||
for _, tc := range testcases { | ||
gotID, gotCS, err := parseDSNEnv(tc.prefix, tc.key, "conninfo") | ||
if tc.valid { | ||
assert.NoError(t, err) | ||
assert.Equal(t, tc.wantId, gotID) | ||
assert.Equal(t, ConnSetting{ServiceType: tc.wantType, Conninfo: "conninfo"}, gotCS) | ||
} else { | ||
assert.Error(t, err) | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters