Add database URL. (#365)
* Add database URL. This allows specification of either a file://, env://, or other string. If it starts with file:// or env:// the actual value will be read from those resources. * Tidy up the KMS output * Also run migrations in test mode when specifying the URL
This commit is contained in:
1 parent
c2b49dbc7d
commit
c4e2b88022
5 files changed
+83
-7
No files matched your search
@@ -349,7 +349,10 @@ func (b *Server) SetupKMSes(ui cli.Ui, config *config.Config) error {
|
||||
|
||||
kmsLogger := b.Logger.ResetNamed(fmt.Sprintf("kms-%s-%s", purpose, kms.Type))
|
||||
|
||||
origPurpose := kms.Purpose
|
||||
kms.Purpose = []string{purpose}
|
||||
wrapper, wrapperConfigError := configutil.ConfigureWrapper(kms, &b.InfoKeys, &b.Info, kmsLogger)
|
||||
kms.Purpose = origPurpose
|
||||
if wrapperConfigError != nil {
|
||||
if !errwrap.ContainsType(wrapperConfigError, new(logical.KeyNotFoundError)) {
|
||||
return fmt.Errorf(
|
||||
|
||||
@@ -9,6 +9,7 @@ import (
|
||||
"github.com/hashicorp/boundary/internal/auth/password"
|
||||
"github.com/hashicorp/boundary/internal/cmd/base"
|
||||
"github.com/hashicorp/boundary/internal/cmd/config"
|
||||
"github.com/hashicorp/boundary/internal/db"
|
||||
"github.com/hashicorp/boundary/internal/servers/controller"
|
||||
"github.com/hashicorp/boundary/sdk/strutil"
|
||||
"github.com/hashicorp/boundary/sdk/wrapper"
|
||||
@@ -304,10 +305,29 @@ func (c *Command) Run(args []string) int {
|
||||
}
|
||||
}
|
||||
if err := c.CreateDevDatabase("postgres", opts...); err != nil {
|
||||
c.UI.Error(fmt.Errorf("Error creating dev database container: %s", err.Error()).Error())
|
||||
c.UI.Error(fmt.Errorf("Error creating dev database container: %w", err).Error())
|
||||
return 1
|
||||
}
|
||||
c.ShutdownFuncs = append(c.ShutdownFuncs, c.DestroyDevDatabase)
|
||||
} else {
|
||||
if c.Config.Database == nil || c.Config.Database.Url == "" {
|
||||
c.UI.Error(`"url" not specified in "database" config block"`)
|
||||
return 1
|
||||
}
|
||||
dbaseUrl, err := config.ParseAddress(c.Config.Database.Url)
|
||||
if err != nil && err != config.ErrNotAUrl {
|
||||
c.UI.Error(fmt.Errorf("Error parsing database url: %w", err).Error())
|
||||
return 1
|
||||
}
|
||||
c.DatabaseUrl = strings.TrimSpace(dbaseUrl)
|
||||
if err := db.InitStore("postgres", nil, c.DatabaseUrl); err != nil {
|
||||
c.UI.Error(fmt.Errorf("Error running database migrations: %w", err).Error())
|
||||
return 1
|
||||
}
|
||||
if err := c.ConnectToDatabase("postgres"); err != nil {
|
||||
c.UI.Error(fmt.Errorf("Error connecting to database: %w", err).Error())
|
||||
return 1
|
||||
}
|
||||
}
|
||||
|
||||
defer func() {
|
||||
|
||||
@@ -4,9 +4,13 @@ import (
|
||||
"bytes"
|
||||
"crypto/rand"
|
||||
"encoding/base64"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"net/url"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
wrapping "github.com/hashicorp/go-kms-wrapping"
|
||||
"github.com/hashicorp/hcl"
|
||||
@@ -91,6 +95,7 @@ type Config struct {
|
||||
PassthroughDirectory string `hcl:"-"`
|
||||
Worker *Worker `hcl:"worker"`
|
||||
Controller *Controller `hcl:"controller"`
|
||||
Database *Database `hcl:"database"`
|
||||
}
|
||||
|
||||
type Controller struct {
|
||||
@@ -107,6 +112,10 @@ type Worker struct {
|
||||
Controllers []string `hcl:"controllers"`
|
||||
}
|
||||
|
||||
type Database struct {
|
||||
Url string `hcl:"url"`
|
||||
}
|
||||
|
||||
// DevWorker is a Config that is used for dev mode of Boundary
|
||||
// workers
|
||||
func DevWorker() (*Config, error) {
|
||||
@@ -235,3 +244,37 @@ func (c *Config) Sanitized() map[string]interface{} {
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
var ErrNotAUrl = errors.New("not a url")
|
||||
|
||||
// ParseAddress parses a URL with schemes file://, env://, or any other.
|
||||
// Depending on the scheme it will return specific types of data:
|
||||
//
|
||||
// * file:// will return a string with the file's contents * env:// will return
|
||||
// a string with the env var's contents * anything else will return the string
|
||||
// as it was
|
||||
//
|
||||
// On error, we return the original string along with the error. The caller can
|
||||
// switch on ErrNotAUrl to understand whether it was the parsing step that
|
||||
// errored or something else. This is useful to attempt to read a non-URL string
|
||||
// from some resource, but where the original input may simply be a valid string
|
||||
// of that type.
|
||||
func ParseAddress(addr string) (string, error) {
|
||||
addr = strings.TrimSpace(addr)
|
||||
parsed, err := url.Parse(addr)
|
||||
if err != nil {
|
||||
return addr, ErrNotAUrl
|
||||
}
|
||||
switch parsed.Scheme {
|
||||
case "file":
|
||||
contents, err := ioutil.ReadFile(strings.TrimPrefix(addr, "file://"))
|
||||
if err != nil {
|
||||
return addr, fmt.Errorf("error reading file at %s: %w", addr, err)
|
||||
}
|
||||
return string(contents), nil
|
||||
case "env":
|
||||
return os.Getenv(strings.TrimPrefix(addr, "env://")), nil
|
||||
}
|
||||
|
||||
return addr, nil
|
||||
}
|
||||
+12
-6
@@ -139,24 +139,30 @@ func InitStore(dialect string, cleanup func() error, url string) error {
|
||||
source, err := migrations.NewMigrationSource(dialect)
|
||||
if err != nil {
|
||||
mErr = multierror.Append(mErr, fmt.Errorf("error creating migration driver: %w", err))
|
||||
if err := cleanup(); err != nil {
|
||||
mErr = multierror.Append(mErr, fmt.Errorf("error cleaning up from creating driver: %w", err))
|
||||
if cleanup != nil {
|
||||
if err := cleanup(); err != nil {
|
||||
mErr = multierror.Append(mErr, fmt.Errorf("error cleaning up from creating driver: %w", err))
|
||||
}
|
||||
}
|
||||
return mErr.ErrorOrNil()
|
||||
}
|
||||
m, err := migrate.NewWithSourceInstance("httpfs", source, url)
|
||||
if err != nil {
|
||||
mErr = multierror.Append(mErr, fmt.Errorf("error creating migrations: %w", err))
|
||||
if err := cleanup(); err != nil {
|
||||
mErr = multierror.Append(mErr, fmt.Errorf("error cleaning up from creating migrations: %w", err))
|
||||
if cleanup != nil {
|
||||
if err := cleanup(); err != nil {
|
||||
mErr = multierror.Append(mErr, fmt.Errorf("error cleaning up from creating migrations: %w", err))
|
||||
}
|
||||
}
|
||||
return mErr.ErrorOrNil()
|
||||
|
||||
}
|
||||
if err := m.Up(); err != nil && err != migrate.ErrNoChange {
|
||||
mErr = multierror.Append(mErr, fmt.Errorf("error running migrations: %w", err))
|
||||
if err := cleanup(); err != nil {
|
||||
mErr = multierror.Append(mErr, fmt.Errorf("error cleaning up from running migrations: %w", err))
|
||||
if cleanup != nil {
|
||||
if err := cleanup(); err != nil {
|
||||
mErr = multierror.Append(mErr, fmt.Errorf("error cleaning up from running migrations: %w", err))
|
||||
}
|
||||
}
|
||||
return mErr.ErrorOrNil()
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@ import (
|
||||
"github.com/hashicorp/boundary/api/authtokens"
|
||||
"github.com/hashicorp/boundary/internal/cmd/base"
|
||||
"github.com/hashicorp/boundary/internal/cmd/config"
|
||||
"github.com/hashicorp/boundary/internal/db"
|
||||
"github.com/hashicorp/boundary/internal/iam"
|
||||
"github.com/hashicorp/boundary/internal/servers"
|
||||
"github.com/hashicorp/go-hclog"
|
||||
@@ -343,6 +344,9 @@ func NewTestController(t *testing.T, opts *TestControllerOpts) *TestController {
|
||||
|
||||
if opts.DatabaseUrl != "" {
|
||||
tc.b.DatabaseUrl = opts.DatabaseUrl
|
||||
if err := db.InitStore("postgres", nil, tc.b.DatabaseUrl); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := tc.b.ConnectToDatabase("postgres"); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user