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

feat: Add port/protocol for driver #962

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
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
8 changes: 6 additions & 2 deletions docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,10 @@ provider "snowflake" {
oauth_redirect_url = "..."

// optional
role = "..."
host = "..."
role = "..."
host = "..."
protocol = "https"
port = 443
}
```

Expand All @@ -59,9 +61,11 @@ provider "snowflake" {
- **oauth_redirect_url** (String, Sensitive) Required when `oauth_refresh_token` is used. Can be sourced from `SNOWFLAKE_OAUTH_REDIRECT_URL` environment variable.
- **oauth_refresh_token** (String, Sensitive) Token for use with OAuth. Setup and generation of the token is left to other tools. Should be used in conjunction with `oauth_client_id`, `oauth_client_secret`, `oauth_endpoint`, `oauth_redirect_url`. Cannot be used with `browser_auth`, `private_key_path`, `oauth_access_token` or `password`. Can be sourced from `SNOWFLAKE_OAUTH_REFRESH_TOKEN` environment variable.
- **password** (String, Sensitive) Password for username+password auth. Cannot be used with `browser_auth` or `private_key_path`. Can be source from `SNOWFLAKE_PASSWORD` environment variable.
- **port** (Number) Support custom port values to snowflake go driver for use with privatelink. Can be sourced from `SNOWFLAKE_PORT` environment variable.
- **private_key** (String, Sensitive) Private Key for username+private-key auth. Cannot be used with `browser_auth` or `password`. Can be source from `SNOWFLAKE_PRIVATE_KEY` environment variable.
- **private_key_passphrase** (String, Sensitive) Supports the encryption ciphers aes-128-cbc, aes-128-gcm, aes-192-cbc, aes-192-gcm, aes-256-cbc, aes-256-gcm, and des-ede3-cbc
- **private_key_path** (String, Sensitive) Path to a private key for using keypair authentication. Cannot be used with `browser_auth`, `oauth_access_token` or `password`. Can be source from `SNOWFLAKE_PRIVATE_KEY_PATH` environment variable.
- **protocol** (String) Support custom protocols to snowflake go driver. Can be sourced from `SNOWFLAKE_PROTOCOL` environment variable.
- **region** (String) [Snowflake region](https://docs.snowflake.com/en/user-guide/intro-regions.html) to use. Can be source from the `SNOWFLAKE_REGION` environment variable.
- **role** (String) Snowflake role to use for operations. If left unset, default role for user will be used. Can come from the `SNOWFLAKE_ROLE` environment variable.

Expand Down
6 changes: 4 additions & 2 deletions examples/provider/provider.tf
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ provider "snowflake" {
oauth_redirect_url = "..."

// optional
role = "..."
host = "..."
role = "..."
host = "..."
protocol = "https"
port = 443
}
30 changes: 25 additions & 5 deletions pkg/provider/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,18 @@ func Provider() *schema.Provider {
Optional: true,
DefaultFunc: schema.EnvDefaultFunc("SNOWFLAKE_HOST", nil),
},
"port": {
Type: schema.TypeInt,
Description: "Support custom port values to snowflake go driver for use with privatelink. Can be sourced from `SNOWFLAKE_PORT` environment variable.",
Optional: true,
DefaultFunc: schema.EnvDefaultFunc("SNOWFLAKE_PORT", 443),
},
"protocol": {
Type: schema.TypeString,
Description: "Support custom protocols to snowflake go driver. Can be sourced from `SNOWFLAKE_PROTOCOL` environment variable.",
Optional: true,
DefaultFunc: schema.EnvDefaultFunc("SNOWFLAKE_PROTOCOL", "https"),
},
},
ResourcesMap: getResources(),
DataSourcesMap: getDataSources(),
Expand Down Expand Up @@ -282,6 +294,8 @@ func ConfigureProvider(s *schema.ResourceData) (interface{}, error) {
oauthEndpoint := s.Get("oauth_endpoint").(string)
oauthRedirectURL := s.Get("oauth_redirect_url").(string)
host := s.Get("host").(string)
protocol := s.Get("protocol").(string)
port := s.Get("port").(int)

if oauthRefreshToken != "" {
accessToken, err := GetOauthAccessToken(oauthEndpoint, oauthClientID, oauthClientSecret, GetOauthData(oauthRefreshToken, oauthRedirectURL))
Expand All @@ -303,6 +317,8 @@ func ConfigureProvider(s *schema.ResourceData) (interface{}, error) {
region,
role,
host,
protocol,
port,
)
if err != nil {
return nil, errors.Wrap(err, "could not build dsn for snowflake connection")
Expand All @@ -327,7 +343,9 @@ func DSN(
oauthAccessToken,
region,
role,
host string) (string, error) {
host,
protocol string,
port int) (string, error) {

// us-west-2 is their default region, but if you actually specify that it won't trigger their default code
// https://github.com/snowflakedb/gosnowflake/blob/52137ce8c32eaf93b0bd22fc5c7297beff339812/dsn.go#L61
Expand All @@ -336,10 +354,12 @@ func DSN(
}

config := gosnowflake.Config{
Account: account,
User: user,
Region: region,
Role: role,
Account: account,
User: user,
Region: region,
Role: role,
Port: port,
Protocol: protocol,
}

// If host is set trust it and do not use the region value
Expand Down
18 changes: 10 additions & 8 deletions pkg/provider/provider_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,26 +34,28 @@ func TestDSN(t *testing.T) {
browserAuth bool
region,
role,
host string
host,
protocol string
port int
}
tests := []struct {
name string
args args
want string
wantErr bool
}{
{"simple", args{"acct", "user", "pass", false, "region", "role", ""},
{"simple", args{"acct", "user", "pass", false, "region", "role", "", "https", 443},
"user:[email protected]:443?ocspFailOpen=true&region=region&role=role&validateDefaultParameters=true", false},
{"us-west-2 special case", args{"acct2", "user2", "pass2", false, "us-west-2", "role2", ""},
{"us-west-2 special case", args{"acct2", "user2", "pass2", false, "us-west-2", "role2", "", "https", 443},
"user2:[email protected]:443?ocspFailOpen=true&role=role2&validateDefaultParameters=true", false},
{"customhostwregion", args{"acct3", "user3", "pass3", false, "", "role3", "zha123.us-east-1.privatelink.snowflakecomputing.com"},
{"customhostwregion", args{"acct3", "user3", "pass3", false, "", "role3", "zha123.us-east-1.privatelink.snowflakecomputing.com", "https", 443},
"user3:[email protected]:443?account=acct3&ocspFailOpen=true&role=role3&validateDefaultParameters=true", false},
{"customhostignoreregion", args{"acct4", "user4", "pass4", false, "fakeregion", "role4", "zha1234.us-east-1.privatelink.snowflakecomputing.com"},
"user4:[email protected]:443?account=acct4&ocspFailOpen=true&role=role4&validateDefaultParameters=true", false},
{"customhostignoreregion", args{"acct4", "user4", "pass4", false, "fakeregion", "role4", "zha1234.us-east-1.privatelink.snowflakecomputing.com", "http", 8443},
"user4:[email protected]:8443?account=acct4&ocspFailOpen=true&protocol=http&role=role4&validateDefaultParameters=true", false},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got, err := provider.DSN(tt.args.account, tt.args.user, tt.args.password, tt.args.browserAuth, "", "", "", "", tt.args.region, tt.args.role, tt.args.host)
got, err := provider.DSN(tt.args.account, tt.args.user, tt.args.password, tt.args.browserAuth, "", "", "", "", tt.args.region, tt.args.role, tt.args.host, tt.args.protocol, tt.args.port)
if (err != nil) != tt.wantErr {
t.Errorf("DSN() error = %v, wantErr %v", err, tt.wantErr)
return
Expand Down Expand Up @@ -89,7 +91,7 @@ func TestOAuthDSN(t *testing.T) {
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got, err := provider.DSN(tt.args.account, tt.args.user, "", false, "", "", "", tt.args.oauthAccessToken, tt.args.region, tt.args.role, "")
got, err := provider.DSN(tt.args.account, tt.args.user, "", false, "", "", "", tt.args.oauthAccessToken, tt.args.region, tt.args.role, "", "https", 443)

if (err != nil) != tt.wantErr {
t.Errorf("DSN() error = %v, dsn = %v, wantErr %v", err, got, tt.wantErr)
Expand Down