Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

feat(config): Add env and file support for database max connections #1776

Merged
merged 1 commit into from
Dec 9, 2021
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
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -6,6 +6,9 @@ Canonical reference for changes, improvements, and bugfixes for Boundary.

### New and Improved

* config: The `max_open_connections` field for the database field in controllers now supports being set
from environment variables or a file on disk
([PR](https://github.com/hashicorp/boundary/pull/1776))
* config: The `execution_dir` field for plugins now supports being set from environment variables
or a file on disk.([PR](https://github.com/hashicorp/boundary/pull/1772))
* config: Add support for reading worker controllers off of environment
29 changes: 26 additions & 3 deletions internal/cmd/config/config.go
Original file line number Diff line number Diff line change
@@ -10,6 +10,7 @@ import (
"io"
"io/ioutil"
"reflect"
"strconv"
"strings"
"time"

@@ -198,9 +199,10 @@ func initNameIfEmpty(name *string) error {
}

type Database struct {
Url string `hcl:"url"`
MigrationUrl string `hcl:"migration_url"`
MaxOpenConnections int `hcl:"max_open_connections"`
Url string `hcl:"url"`
MigrationUrl string `hcl:"migration_url"`
MaxOpenConnections int `hcl:"-"`
MaxOpenConnectionsRaw interface{} `hcl:"max_open_connections"`
}

type Plugins struct {
@@ -338,6 +340,27 @@ func Parse(d string) (*Config, error) {
}
result.Controller.AuthTokenTimeToStaleDuration = t
}

if result.Controller.Database != nil {
if result.Controller.Database.MaxOpenConnectionsRaw != nil {
switch t := result.Controller.Database.MaxOpenConnectionsRaw.(type) {
case string:
maxOpenConnectionsString, err := parseutil.ParsePath(t)
if err != nil {
return nil, fmt.Errorf("Error parsing database max open connections: %w", err)
}
result.Controller.Database.MaxOpenConnections, err = strconv.Atoi(maxOpenConnectionsString)
if err != nil {
return nil, fmt.Errorf("Database max open connections value is not an int: %w", err)
}
case int:
result.Controller.Database.MaxOpenConnections = t
default:
return nil, fmt.Errorf("Database max open connections: unsupported type %q",
reflect.TypeOf(t).String())
}
}
}
}

// Parse worker tags
93 changes: 93 additions & 0 deletions internal/cmd/config/config_test.go
Original file line number Diff line number Diff line change
@@ -1052,3 +1052,96 @@ func TestPluginExecutionDir(t *testing.T) {
})
}
}

func TestDatabaseMaxConnections(t *testing.T) {
tests := []struct {
name string
in string
envMaxOpenConnections string
expMaxOpenConnections int
expErr bool
expErrStr string
}{
{
name: "Valid integer value",
in: `
controller {
name = "example-controller"
database {
max_open_connections = 5
}
}`,
expMaxOpenConnections: 5,
expErr: false,
},
{
name: "Invalid value string",
in: `
controller {
name = "example-controller"
database {
max_open_connections = "string bad"
}
}`,
expErr: true,
expErrStr: "Database max open connections value is not an int: " +
"strconv.Atoi: parsing \"string bad\": invalid syntax",
},
{
name: "Invalid value type",
in: `
controller {
name = "example-controller"
database {
max_open_connections = false
}
}`,
expErr: true,
expErrStr: "Database max open connections: unsupported type \"bool\"",
},
{
name: "Valid env var",
in: `
controller {
name = "example-controller"
database {
max_open_connections = "env://ENV_MAX_CONN"
}
}`,
expMaxOpenConnections: 8,
envMaxOpenConnections: "8",
expErr: false,
},
{
name: "Invalid env var",
in: `
controller {
name = "example-controller"
database {
max_open_connections = "env://ENV_MAX_CONN"
}
}`,
envMaxOpenConnections: "bogus value",
expErr: true,
expErrStr: "Database max open connections value is not an int: " +
"strconv.Atoi: parsing \"bogus value\": invalid syntax",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
t.Setenv("ENV_MAX_CONN", tt.envMaxOpenConnections)
c, err := Parse(tt.in)
if tt.expErr {
require.EqualError(t, err, tt.expErrStr)
require.Nil(t, c)
return
}

require.NoError(t, err)
require.NotNil(t, c)
require.NotNil(t, c.Controller)
require.NotNil(t, c.Controller.Database)
require.Equal(t, tt.expMaxOpenConnections, c.Controller.Database.MaxOpenConnections)
})
}
}
4 changes: 3 additions & 1 deletion website/content/docs/configuration/controller.mdx
Original file line number Diff line number Diff line change
@@ -41,7 +41,9 @@ description will be read.
connections that can be opened by the controller.
The minimum number of connections required is 5.
Setting this value to 0 will allow the controller to open as many
connections as needed.
connections as needed. This value can be a string representing the max number of connections, can refer to a file
on disk (file://) from which the number of connections will be read; or an env var (env://) from which the
number of connections will be read.

Either URL can refer to a file on disk (file://) from which a URL will be read; an env
var (env://) from which the URL will be read; or a direct database URL (postgres://).