Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Various changes to the PostgreSQL provider #10682

Merged
merged 46 commits into from
Dec 12, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
46 commits
Select commit Hold shift + click to select a range
f31ebff
Change the PostgreSQL PGSSLMODE option to sslmode to match PostgreSQL…
sean- Sep 5, 2016
b68ef2c
Fall through to using the defaults from github.com/lib/pq
sean- Sep 5, 2016
ec130d5
Add comments requesting that the testing-specific environment variables
sean- Sep 5, 2016
655617e
Remove the PGPASSWORD requirement for tests.
sean- Sep 6, 2016
7e5ccc0
Spell `ssl_mode` like `sslmode`
sean- Sep 6, 2016
2aee081
Eh, specify default values lib/pq zero initializes itself
sean- Sep 6, 2016
f3add9e
Flesh out the CREATE DATABASE for PostgreSQL.
sean- Sep 6, 2016
68cadd3
Update the FIXME/TODO style to match Google style guides
sean- Sep 6, 2016
deb91f6
Update the descriptions to mostly match the official PostgreSQL docs.
sean- Sep 6, 2016
02dea2e
Add missing descriptions to owner and name
sean- Sep 6, 2016
242405b
Factor out the validate function for connection limits
sean- Sep 6, 2016
547dcf2
Decorate the computed attribute where appropriate
sean- Sep 6, 2016
5b66bf0
ForceNew is required when changing the locale, ctype, and encoding.
sean- Sep 6, 2016
3779dff
Use a string instead of the `%t` modifier for printing a bool in SQL
sean- Sep 6, 2016
55061d1
Prefer PGHOSTADDR over PGHOST, if set.
sean- Nov 5, 2016
44d907a
Revert "Prefer PGHOSTADDR over PGHOST, if set." lib/pq doesn't suppo…
sean- Nov 5, 2016
602a908
Add a `fallback_application_name` to the PostgreSQL DSN.
sean- Nov 6, 2016
a200899
Allow the PostgreSQL provider to talk to a non-default database.
sean- Nov 6, 2016
3750bf7
Depreciate the PostgreSQL provider's `ssl_mode` option in favor of `s…
sean- Nov 6, 2016
300ef2b
Add `connect_timeout` support to the PostgreSQL provider.
sean- Nov 6, 2016
59f4ad6
Alpha sort the resources in the PostgreSQL map.
sean- Nov 6, 2016
5280c37
`postgresql_database` resource provider should now be feature complete.
sean- Nov 6, 2016
f253fc9
Commit miss earlier, fix syntax from unstaged commit.
sean- Nov 6, 2016
e9b2b38
Remove SetId() call from *Read(), this isn't required for import to w…
sean- Nov 6, 2016
37fdc95
Always remove the IS_TEMPLATE attribute before dropping a database.
sean- Nov 6, 2016
6b540ec
Don't use d.GetOk() when the zero value is a required attribute.
sean- Nov 6, 2016
2e52914
Remove unused code.
sean- Nov 6, 2016
bfc2a2d
Commit WIP re: updated postgresql_role provider.
sean- Nov 6, 2016
db5d7b0
Style nit
sean- Nov 6, 2016
e244847
Clean up the DatabaseCreate call.
sean- Nov 7, 2016
15cd542
Remove a duplicate `connect_timeout` from a rebase+stash.
sean- Dec 12, 2016
b576a3e
Rename variable from `roleSuperUserAttr` to `roleSuperuserAttr`.
sean- Dec 12, 2016
e9dc92c
Change the default for `inherit` from `false` to `true` to match Post…
sean- Dec 12, 2016
e36827c
Change the default for `valid_until` to `infinity` to match the default.
sean- Dec 12, 2016
6deb61b
Enable import support for PostgreSQL's extensions.
sean- Dec 12, 2016
4c6c52e
Nuke some whitespace.
sean- Dec 12, 2016
1a93309
Expand postgresql_role support to include all known options.
sean- Dec 12, 2016
d1c9ebb
Add PostgreSQL schema support
sean- Dec 12, 2016
201d9b9
Fix the description for the postgresql_role.
sean- Dec 12, 2016
daa9514
Teach postgresql_extension about schemas.
sean- Dec 12, 2016
c602f02
Fix the remaining `postgresql_extension` unit test.
sean- Dec 12, 2016
a4965c0
Fix up helpers.
sean- Dec 12, 2016
8c41f08
Add the version attribute to postgresql_extension.
sean- Dec 12, 2016
6ed3777
Add the testing Makefile that I'm using for testing the provider loca…
sean- Dec 12, 2016
2ecd42c
Remove non-standard environment variables in prep for 0.8.
sean- Dec 12, 2016
ce60c4f
gofmt cleanup on imports.
sean- Dec 12, 2016
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
28 changes: 28 additions & 0 deletions builtin/providers/postgresql/GNUmakefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
POSTGRES?=/opt/local/lib/postgresql96/bin/postgres
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it's worth adding a comment to the top of this file stating the intended use, or use the "self-documenting" structure and make the help target be the default.

PSQL?=/opt/local/lib/postgresql96/bin/psql

PGDATA?=$(GOPATH)/src/github.com/hashicorp/terraform/builtin/providers/postgresql/data

initdb::
/opt/local/lib/postgresql96/bin/initdb --no-locale -U postgres -D $(PGDATA)

startdb::
2>&1 \
$(POSTGRES) \
-D $(PGDATA) \
-c log_connections=on \
-c log_disconnections=on \
-c log_duration=on \
-c log_statement=all \
| tee postgresql.log

cleandb::
rm -rf $(PGDATA)

freshdb:: cleandb initdb startdb

test::
2>&1 PGSSLMODE=disable PGHOST=/tmp PGUSER=postgres make -C ../../.. testacc TEST=./builtin/providers/postgresql | tee test.log

psql::
$(PSQL) -E postgres postgres
24 changes: 17 additions & 7 deletions builtin/providers/postgresql/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,22 @@ package postgresql
import (
"database/sql"
"fmt"
"log"

_ "github.com/lib/pq" //PostgreSQL db
)

// Config - provider config
type Config struct {
Host string
Port int
Username string
Password string
SslMode string
Timeout int
Host string
Port int
Database string
Username string
Password string
SSLMode string
ApplicationName string
Timeout int
ConnectTimeoutSec int
}

// Client struct holding connection string
Expand All @@ -25,8 +29,14 @@ type Client struct {

// NewClient returns new client config
func (c *Config) NewClient() (*Client, error) {
connStr := fmt.Sprintf("host=%s port=%d user=%s password=%s dbname=postgres sslmode=%s connect_timeout=%d", c.Host, c.Port, c.Username, c.Password, c.SslMode, c.Timeout)
// NOTE: dbname must come before user otherwise dbname will be set to
// user.
const dsnFmt = "host=%s port=%d dbname=%s user=%s password=%s sslmode=%s fallback_application_name=%s connect_timeout=%d"

logDSN := fmt.Sprintf(dsnFmt, c.Host, c.Port, c.Database, c.Username, "<redacted>", c.SSLMode, c.ApplicationName, c.ConnectTimeoutSec)
log.Printf("[INFO] PostgreSQL DSN: `%s`", logDSN)

connStr := fmt.Sprintf(dsnFmt, c.Host, c.Port, c.Database, c.Username, c.Password, c.SSLMode, c.ApplicationName, c.ConnectTimeoutSec)
client := Client{
connStr: connStr,
username: c.Username,
Expand Down
24 changes: 24 additions & 0 deletions builtin/providers/postgresql/helpers.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package postgresql

import (
"fmt"
"strings"
)

// pqQuoteLiteral returns a string literal safe for inclusion in a PostgreSQL
// query as a parameter. The resulting string still needs to be wrapped in
// single quotes in SQL (i.e. fmt.Sprintf(`'%s'`, pqQuoteLiteral("str"))). See
// quote_literal_internal() in postgresql/backend/utils/adt/quote.c:77.
func pqQuoteLiteral(in string) string {
in = strings.Replace(in, `\`, `\\`, -1)
in = strings.Replace(in, `'`, `''`, -1)
return in
}

func validateConnLimit(v interface{}, key string) (warnings []string, errors []error) {
value := v.(int)
if value < -1 {
errors = append(errors, fmt.Errorf("%s can not be less than -1", key))
}
return
}
94 changes: 69 additions & 25 deletions builtin/providers/postgresql/provider.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
package postgresql

import (
"bytes"
"fmt"

"github.com/hashicorp/errwrap"
"github.com/hashicorp/terraform/helper/schema"
"github.com/hashicorp/terraform/terraform"
Expand All @@ -12,61 +15,89 @@ func Provider() terraform.ResourceProvider {
Schema: map[string]*schema.Schema{
"host": {
Type: schema.TypeString,
Required: true,
DefaultFunc: schema.MultiEnvDefaultFunc([]string{"PGHOST", "POSTGRESQL_HOST"}, nil),
Description: "The PostgreSQL server address",
Optional: true,
DefaultFunc: schema.EnvDefaultFunc("PGHOST", nil),
Description: "Name of PostgreSQL server address to connect to",
},
"port": {
Type: schema.TypeInt,
Optional: true,
Default: 5432,
Description: "The PostgreSQL server port",
DefaultFunc: schema.EnvDefaultFunc("PGPORT", 5432),
Description: "The PostgreSQL port number to connect to at the server host, or socket file name extension for Unix-domain connections",
},
"database": {
Type: schema.TypeString,
Optional: true,
Description: "The name of the database to connect to in order to conenct to (defaults to `postgres`).",
DefaultFunc: schema.EnvDefaultFunc("PGDATABASE", "postgres"),
},
"username": {
Type: schema.TypeString,
Required: true,
DefaultFunc: schema.MultiEnvDefaultFunc([]string{"PGUSER", "POSTGRESQL_USER"}, nil),
Description: "Username for PostgreSQL server connection",
Optional: true,
DefaultFunc: schema.EnvDefaultFunc("PGUSER", "postgres"),
Description: "PostgreSQL user name to connect as",
},
"password": {
Type: schema.TypeString,
Optional: true,
DefaultFunc: schema.MultiEnvDefaultFunc([]string{"PGPASSWORD", "POSTGRESQL_PASSWORD"}, nil),
Description: "Password for PostgreSQL server connection",
DefaultFunc: schema.EnvDefaultFunc("PGPASSWORD", nil),
Description: "Password to be used if the PostgreSQL server demands password authentication",
},
"ssl_mode": {
"sslmode": {
Type: schema.TypeString,
Optional: true,
DefaultFunc: schema.EnvDefaultFunc("PGSSLMODE", "require"),
Description: "Connection mode for PostgreSQL server",
DefaultFunc: schema.EnvDefaultFunc("PGSSLMODE", nil),
Description: "This option determines whether or with what priority a secure SSL TCP/IP connection will be negotiated with the PostgreSQL server",
},
"ssl_mode": {
Type: schema.TypeString,
Optional: true,
Deprecated: "Rename PostgreSQL provider `ssl_mode` attribute to `sslmode`",
},
"connect_timeout": {
Type: schema.TypeInt,
Optional: true,
Default: 15,
DefaultFunc: schema.EnvDefaultFunc("PGCONNECT_TIMEOUT", nil),
Description: "Maximum wait for connection, in seconds. Zero or not specified means wait indefinitely.",
Type: schema.TypeInt,
Optional: true,
DefaultFunc: schema.EnvDefaultFunc("PGCONNECT_TIMEOUT", 180),
Description: "Maximum wait for connection, in seconds. Zero or not specified means wait indefinitely.",
ValidateFunc: validateConnTimeout,
},
},

ResourcesMap: map[string]*schema.Resource{
"postgresql_database": resourcePostgreSQLDatabase(),
"postgresql_role": resourcePostgreSQLRole(),
"postgresql_extension": resourcePostgreSQLExtension(),
"postgresql_schema": resourcePostgreSQLSchema(),
"postgresql_role": resourcePostgreSQLRole(),
},

ConfigureFunc: providerConfigure,
}
}

func validateConnTimeout(v interface{}, key string) (warnings []string, errors []error) {
value := v.(int)
if value < 0 {
errors = append(errors, fmt.Errorf("%s can not be less than 0", key))
}
return
}

func providerConfigure(d *schema.ResourceData) (interface{}, error) {
var sslMode string
if sslModeRaw, ok := d.GetOk("sslmode"); ok {
sslMode = sslModeRaw.(string)
} else {
sslMode = d.Get("ssl_mode").(string)
}
config := Config{
Host: d.Get("host").(string),
Port: d.Get("port").(int),
Username: d.Get("username").(string),
Password: d.Get("password").(string),
SslMode: d.Get("ssl_mode").(string),
Timeout: d.Get("connect_timeout").(int),
Host: d.Get("host").(string),
Port: d.Get("port").(int),
Database: d.Get("database").(string),
Username: d.Get("username").(string),
Password: d.Get("password").(string),
SSLMode: sslMode,
ApplicationName: tfAppName(),
ConnectTimeoutSec: d.Get("connect_timeout").(int),
}

client, err := config.NewClient()
Expand All @@ -76,3 +107,16 @@ func providerConfigure(d *schema.ResourceData) (interface{}, error) {

return client, nil
}

func tfAppName() string {
const VersionPrerelease = terraform.VersionPrerelease
var versionString bytes.Buffer

fmt.Fprintf(&versionString, "'Terraform v%s", terraform.Version)
if terraform.VersionPrerelease != "" {
fmt.Fprintf(&versionString, "-%s", terraform.VersionPrerelease)
}
fmt.Fprintf(&versionString, "'")

return versionString.String()
}
3 changes: 0 additions & 3 deletions builtin/providers/postgresql/provider_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,4 @@ func testAccPreCheck(t *testing.T) {
if v := os.Getenv("PGUSER"); v == "" {
t.Fatal("PGUSER must be set for acceptance tests")
}
if v := os.Getenv("PGPASSWORD"); v == "" && host != "localhost" {
t.Fatal("PGPASSWORD must be set for acceptance tests if PGHOST is not localhost")
}
}
Loading