WARNING: THIS SITE IS A MIRROR OF GITHUB.COM / IT CANNOT LOGIN OR REGISTER ACCOUNTS / THE CONTENTS ARE PROVIDED AS-IS / THIS SITE ASSUMES NO RESPONSIBILITY FOR ANY DISPLAYED CONTENT OR LINKS / IF YOU FOUND SOMETHING MAY NOT GOOD FOR EVERYONE, CONTACT ADMIN AT ilovescratch@foxmail.com
Skip to content

Commit d4a4de2

Browse files
authored
Merge pull request #10 from dbsystel/fix-provider-calculated-values
Fix errors with calculated provider attributes
2 parents b1f340c + 3a37dc5 commit d4a4de2

File tree

4 files changed

+137
-86
lines changed

4 files changed

+137
-86
lines changed

redshift/config_data_api.go

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -24,12 +24,6 @@ func buildConnStrFromDataApiConfig(workgroupName, database, awsRegion string) st
2424

2525
func getConfigFromDataApiResourceData(d *schema.ResourceData, database string) (*Config, error) {
2626
workgroupName := d.Get("data_api.0.workgroup_name").(string)
27-
if workgroupName == "" {
28-
return nil, fmt.Errorf(`attribute "workgroup_name" is required in data_api configuration`)
29-
}
3027
region := d.Get("data_api.0.region").(string)
31-
if region == "" {
32-
return nil, fmt.Errorf(`attribute "region" is required in data_api configuration`)
33-
}
3428
return NewDataApiConfig(workgroupName, database, region, 1), nil
3529
}

redshift/config_pq_proxy.go

Lines changed: 8 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -21,11 +21,11 @@ import (
2121
type temporaryCredentialsResolverFunc func(username string, d *schema.ResourceData) (string, string, error)
2222

2323
func NewPqConfig(host, database, username, password string, port int, sslMode string, maxConns int) *Config {
24-
connStr := buildConnStrFromPqConfig(host, database, username, password, port, sslMode, maxConns)
24+
connStr := buildConnStrFromPqConfig(host, database, username, password, port, sslMode)
2525
return NewConfig(proxyDriverName, connStr, database, maxConns)
2626
}
2727

28-
func buildConnStrFromPqConfig(host, database, username, password string, port int, sslMode string, maxConns int) string {
28+
func buildConnStrFromPqConfig(host, database, username, password string, port int, sslMode string) string {
2929
params := map[string]string{}
3030

3131
params["sslmode"] = sslMode
@@ -47,31 +47,14 @@ func buildConnStrFromPqConfig(host, database, username, password string, port in
4747
strings.Join(paramsArray, "&"),
4848
)
4949
}
50-
func getRequiredResourceDataValue[V int | string](d *schema.ResourceData, path string) (V, error) {
51-
valueRaw, valuePresent := d.GetOk(path)
52-
if !valuePresent {
53-
var emptyValue V
54-
return emptyValue, fmt.Errorf("attribute %q is required in pq configuration", path)
55-
}
56-
return valueRaw.(V), nil
57-
}
5850

5951
func getConfigFromPqResourceData(d *schema.ResourceData, database string, maxConnections int, temporaryCredentialsResolver temporaryCredentialsResolverFunc) (*Config, error) {
6052
var err error
61-
var host, username, password, sslMode string
62-
var port int
63-
if host, err = getRequiredResourceDataValue[string](d, "host"); err != nil {
64-
return nil, err
65-
}
66-
if username, err = getRequiredResourceDataValue[string](d, "username"); err != nil {
67-
return nil, err
68-
}
69-
if port, err = getRequiredResourceDataValue[int](d, "port"); err != nil {
70-
return nil, err
71-
}
72-
if sslMode, err = getRequiredResourceDataValue[string](d, "sslmode"); err != nil {
73-
return nil, err
74-
}
53+
var password string
54+
host := d.Get("host").(string)
55+
username := d.Get("username").(string)
56+
port := d.Get("port").(int)
57+
sslMode := d.Get("sslmode").(string)
7558
_, useTemporaryCredentials := d.GetOk("temporary_credentials")
7659
if useTemporaryCredentials {
7760
log.Println("[DEBUG] using temporary credentials authentication")
@@ -82,9 +65,7 @@ func getConfigFromPqResourceData(d *schema.ResourceData, database string, maxCon
8265
log.Printf("[DEBUG] got temporary credentials with username %s\n", username)
8366
} else {
8467
log.Println("[DEBUG] using password authentication")
85-
if password, err = getRequiredResourceDataValue[string](d, "password"); err != nil {
86-
return nil, err
87-
}
68+
password = d.Get("password").(string)
8869
}
8970
return NewPqConfig(host, database, username, password, port, sslMode, maxConnections), nil
9071
}

redshift/provider.go

Lines changed: 14 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -23,15 +23,14 @@ func Provider() *schema.Provider {
2323
Type: schema.TypeString,
2424
Description: "Name of Redshift server address to connect to.",
2525
Optional: true,
26-
DefaultFunc: schema.EnvDefaultFunc("REDSHIFT_HOST", ""),
26+
DefaultFunc: schema.EnvDefaultFunc("REDSHIFT_HOST", nil),
2727
ConflictsWith: []string{"data_api"},
2828
},
2929
"username": {
30-
Type: schema.TypeString,
31-
Optional: true,
32-
DefaultFunc: schema.EnvDefaultFunc("REDSHIFT_USER", "root"),
33-
Description: "Redshift user name to connect as.",
34-
ConflictsWith: []string{"data_api"},
30+
Type: schema.TypeString,
31+
Optional: true,
32+
DefaultFunc: schema.EnvDefaultFunc("REDSHIFT_USER", "root"),
33+
Description: "Redshift user name to connect as.",
3534
},
3635
"password": {
3736
Type: schema.TypeString,
@@ -41,15 +40,13 @@ func Provider() *schema.Provider {
4140
Sensitive: true,
4241
ConflictsWith: []string{
4342
"temporary_credentials",
44-
"data_api",
4543
},
4644
},
4745
"port": {
48-
Type: schema.TypeInt,
49-
Description: "The Redshift port number to connect to at the server host.",
50-
Optional: true,
51-
DefaultFunc: schema.EnvDefaultFunc("REDSHIFT_PORT", 5439),
52-
ConflictsWith: []string{"data_api"},
46+
Type: schema.TypeInt,
47+
Description: "The Redshift port number to connect to at the server host.",
48+
Optional: true,
49+
DefaultFunc: schema.EnvDefaultFunc("REDSHIFT_PORT", 5439),
5350
},
5451
"sslmode": {
5552
Type: schema.TypeString,
@@ -62,7 +59,6 @@ func Provider() *schema.Provider {
6259
"verify-ca",
6360
"verify-full",
6461
}, false),
65-
ConflictsWith: []string{"data_api"},
6662
},
6763
"database": {
6864
Type: schema.TypeString,
@@ -71,12 +67,11 @@ func Provider() *schema.Provider {
7167
DefaultFunc: schema.EnvDefaultFunc("REDSHIFT_DATABASE", "redshift"),
7268
},
7369
"max_connections": {
74-
Type: schema.TypeInt,
75-
Optional: true,
76-
Default: defaultProviderMaxOpenConnections,
77-
Description: "Maximum number of connections to establish to the database. Zero means unlimited.",
78-
ValidateFunc: validation.IntAtLeast(-1),
79-
ConflictsWith: []string{"data_api"},
70+
Type: schema.TypeInt,
71+
Optional: true,
72+
Default: defaultProviderMaxOpenConnections,
73+
Description: "Maximum number of connections to establish to the database. Zero means unlimited.",
74+
ValidateFunc: validation.IntAtLeast(-1),
8075
},
8176
"data_api": {
8277
Type: schema.TypeList,
@@ -85,12 +80,7 @@ func Provider() *schema.Provider {
8580
MaxItems: 1,
8681
ConflictsWith: []string{
8782
"host",
88-
"username",
8983
"password",
90-
"port",
91-
"sslmode",
92-
"max_connections",
93-
"temporary_credentials",
9484
},
9585
Elem: &schema.Resource{
9686
Schema: map[string]*schema.Schema{

redshift/provider_test.go

Lines changed: 115 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,14 @@ import (
55
"fmt"
66
"log"
77
"os"
8+
"regexp"
89
"strings"
910
"testing"
1011

1112
"github.com/aws/aws-sdk-go-v2/config"
1213
"github.com/aws/aws-sdk-go-v2/service/sts"
14+
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
15+
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
1316
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
1417
"github.com/hashicorp/terraform-plugin-sdk/v2/terraform"
1518
redshiftdatasqldriver "github.com/mmichaelb/redshift-data-sql-driver"
@@ -23,7 +26,8 @@ var (
2326
func init() {
2427
testAccProvider = Provider()
2528
testAccProviders = map[string]func() (*schema.Provider, error){
26-
"redshift": func() (*schema.Provider, error) { return testAccProvider, nil },
29+
"redshift": func() (*schema.Provider, error) { return testAccProvider, nil },
30+
"testvalues": getTestValuesProvider,
2731
}
2832
}
2933

@@ -191,21 +195,6 @@ func Test_getConfigFromResourceData(t *testing.T) {
191195
},
192196
false,
193197
},
194-
{
195-
"Data API config missing region",
196-
args{
197-
d: schema.TestResourceDataRaw(t, Provider().Schema, map[string]interface{}{
198-
"database": "some-database",
199-
"data_api": []interface{}{
200-
map[string]interface{}{
201-
"workgroup_name": "some-workgroup",
202-
},
203-
},
204-
}),
205-
},
206-
nil,
207-
true,
208-
},
209198
{
210199
"PQ config",
211200
args{
@@ -251,19 +240,6 @@ func Test_getConfigFromResourceData(t *testing.T) {
251240
},
252241
false,
253242
},
254-
{
255-
"PQ config - missing host",
256-
args{
257-
d: schema.TestResourceDataRaw(t, Provider().Schema, map[string]interface{}{
258-
"username": "some-user",
259-
"port": 4122,
260-
"database": "some-database",
261-
"sslmode": "require",
262-
}),
263-
},
264-
nil,
265-
true,
266-
},
267243
}
268244
for _, tt := range tests {
269245
t.Run(tt.name, func(t *testing.T) {
@@ -291,6 +267,63 @@ func Test_getConfigFromResourceData(t *testing.T) {
291267
}
292268
}
293269

270+
func TestAccProviderCalculatedValues_HostConfig(t *testing.T) {
271+
testHostValue := generateRandomObjectName("tf_acc_calc_val_host")
272+
providerConfig := fmt.Sprintf(`
273+
provider "redshift" {
274+
host = testvalues_value.calculated_host.result
275+
password = "somepassword"
276+
}
277+
278+
resource "testvalues_value" "calculated_host" {
279+
value = %[1]q
280+
}
281+
`, testHostValue)
282+
expectedError := fmt.Sprintf(`dial tcp: lookup %s: no such host`, testHostValue)
283+
// no such host error should occur, not a missing attribute error
284+
testCalculatedProviderValues(t, providerConfig, expectedError)
285+
}
286+
287+
func TestAccProviderCalculatedValues_RedshiftDataConfig(t *testing.T) {
288+
testWorkgroupValue := generateRandomObjectName("tf_acc_calc_val_host")
289+
providerConfig := fmt.Sprintf(`
290+
provider "redshift" {
291+
database = "somedb"
292+
293+
data_api {
294+
workgroup_name = testvalues_value.calculated_workgroup.result
295+
region = "us-west-2"
296+
}
297+
}
298+
299+
resource "testvalues_value" "calculated_workgroup" {
300+
value = %[1]q
301+
}
302+
`, testWorkgroupValue)
303+
// redshift endpoint doesn't exist in this region error should occur, not a missing attribute error
304+
expectedError := "ValidationException: Redshift endpoint doesn't exist in this region."
305+
testCalculatedProviderValues(t, providerConfig, expectedError)
306+
}
307+
308+
func testCalculatedProviderValues(t *testing.T, providerConfig string, expectedError string) {
309+
defer unsetAndSetEnvVars("REDSHIFT_DATABASE", "REDSHIFT_HOST", "REDSHIFT_USER", "REDSHIFT_PASSWORD", "REDSHIFT_DATA_API_SERVERLESS_WORKGROUP_NAME")()
310+
testDbName := generateRandomObjectName("tf_acc_calc_val_db")
311+
testDbConfig := testAccDataSourceRedshiftDatabaseConfigBasic(testDbName)
312+
cfg := fmt.Sprintf(`
313+
%[1]s
314+
%[2]s
315+
`, providerConfig, testDbConfig)
316+
resource.ParallelTest(t, resource.TestCase{
317+
ProviderFactories: testAccProviders,
318+
Steps: []resource.TestStep{
319+
{
320+
Config: cfg,
321+
ExpectError: regexp.MustCompile(expectedError),
322+
},
323+
},
324+
})
325+
}
326+
294327
func unsetAndSetEnvVars(envName ...string) func() {
295328
envValues := make(map[string]string)
296329
for _, env := range envName {
@@ -308,3 +341,56 @@ func unsetAndSetEnvVars(envName ...string) func() {
308341
}
309342
}
310343
}
344+
345+
type testValuesProvider struct {
346+
testValues map[string]interface{}
347+
}
348+
349+
func (p *testValuesProvider) getProvider() *schema.Provider {
350+
return &schema.Provider{
351+
ResourcesMap: map[string]*schema.Resource{
352+
"testvalues_value": {
353+
CreateContext: func(ctx context.Context, data *schema.ResourceData, i interface{}) diag.Diagnostics {
354+
value := data.Get("value").(string)
355+
data.Set("result", value)
356+
data.SetId(value)
357+
p.testValues[value] = &struct{}{}
358+
return nil
359+
},
360+
DeleteContext: func(ctx context.Context, data *schema.ResourceData, i interface{}) diag.Diagnostics {
361+
value := data.Get("value").(string)
362+
delete(p.testValues, value)
363+
data.SetId("")
364+
return nil
365+
},
366+
ReadContext: func(ctx context.Context, data *schema.ResourceData, i interface{}) diag.Diagnostics {
367+
value := data.Get("value").(string)
368+
369+
if _, ok := p.testValues[value]; !ok {
370+
data.SetId("")
371+
return nil
372+
} else {
373+
data.SetId(value)
374+
data.Set("result", value)
375+
}
376+
return nil
377+
},
378+
Schema: map[string]*schema.Schema{
379+
"value": {
380+
Type: schema.TypeString,
381+
Required: true,
382+
ForceNew: true,
383+
},
384+
"result": {
385+
Type: schema.TypeString,
386+
Computed: true,
387+
},
388+
},
389+
},
390+
},
391+
}
392+
}
393+
394+
func getTestValuesProvider() (*schema.Provider, error) {
395+
return (&testValuesProvider{testValues: make(map[string]interface{})}).getProvider(), nil
396+
}

0 commit comments

Comments
 (0)