Skip to content
This repository was archived by the owner on Jan 17, 2025. It is now read-only.

Commit a2815d1

Browse files
Add redshift database resource and data source.
Currently the redshift database resource only supports local databases, while the data source supports both local and datashare databases. I'm still trying to figure out whether it's best to manage datashare databases in the same resource definition or a separate one.
1 parent 8f40f4d commit a2815d1

10 files changed

Lines changed: 681 additions & 2 deletions

File tree

docs/data-sources/database.md

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
---
2+
# generated by https://github.com/hashicorp/terraform-plugin-docs
3+
page_title: "redshift_database Data Source - terraform-provider-redshift"
4+
subcategory: ""
5+
description: |-
6+
Fetches information about a Redshift database.
7+
---
8+
9+
# redshift_database (Data Source)
10+
11+
Fetches information about a Redshift database.
12+
13+
## Example Usage
14+
15+
```terraform
16+
data "redshift_database" "database" {
17+
name = "my_database"
18+
}
19+
```
20+
21+
<!-- schema generated by tfplugindocs -->
22+
## Schema
23+
24+
### Required
25+
26+
- **name** (String) Name of the database
27+
28+
### Optional
29+
30+
- **datashare_producer_account** (String) For databases created from datashares, this is the producer's account number.
31+
- **datashare_producer_name** (String) For databases created from datashares, this is the producer's datashare name.
32+
- **datashare_producer_namespace** (String) For databases created from datashares, this is the producer's namespace.
33+
- **id** (String) The ID of this resource.
34+
35+
### Read-Only
36+
37+
- **connection_limit** (Number) The maximum number of concurrent connections that can be made to this database. A value of -1 means no limit.
38+
- **owner** (String) Owner of the database, usually the user who created it
39+
40+

docs/resources/database.md

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
---
2+
# generated by https://github.com/hashicorp/terraform-plugin-docs
3+
page_title: "redshift_database Resource - terraform-provider-redshift"
4+
subcategory: ""
5+
description: |-
6+
Defines a local database.
7+
---
8+
9+
# redshift_database (Resource)
10+
11+
Defines a local database.
12+
13+
## Example Usage
14+
15+
```terraform
16+
resource "redshift_database" "db" {
17+
name = "my_database"
18+
owner = "my_user"
19+
connection_limit = 123456 # use -1 for unlimited
20+
21+
lifecycle {
22+
prevent_destroy = true
23+
}
24+
}
25+
```
26+
27+
<!-- schema generated by tfplugindocs -->
28+
## Schema
29+
30+
### Required
31+
32+
- **name** (String) Name of the database
33+
34+
### Optional
35+
36+
- **connection_limit** (Number) The maximum number of concurrent connections that can be made to this database. A value of -1 means no limit.
37+
- **id** (String) The ID of this resource.
38+
- **owner** (String) Owner of the database, usually the user who created it
39+
40+
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
data "redshift_database" "database" {
2+
name = "my_database"
3+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
resource "redshift_database" "db" {
2+
name = "my_database"
3+
owner = "my_user"
4+
connection_limit = 123456 # use -1 for unlimited
5+
6+
lifecycle {
7+
prevent_destroy = true
8+
}
9+
}
Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
package redshift
2+
3+
import (
4+
"database/sql"
5+
"strconv"
6+
"strings"
7+
8+
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
9+
)
10+
11+
const (
12+
datashareProducerNameAttr = "datashare_producer_name"
13+
datashareProducerAccountAttr = "datashare_producer_account"
14+
datashareProducerNamespaceAttr = "datashare_producer_namespace"
15+
)
16+
17+
func dataSourceRedshiftDatabase() *schema.Resource {
18+
return &schema.Resource{
19+
Description: `Fetches information about a Redshift database.`,
20+
Read: RedshiftResourceFunc(dataSourceRedshiftDatabaseRead),
21+
Schema: map[string]*schema.Schema{
22+
databaseNameAttr: {
23+
Type: schema.TypeString,
24+
Required: true,
25+
Description: "Name of the database",
26+
StateFunc: func(val interface{}) string {
27+
return strings.ToLower(val.(string))
28+
},
29+
},
30+
databaseOwnerAttr: {
31+
Type: schema.TypeString,
32+
Computed: true,
33+
Description: "Owner of the database, usually the user who created it",
34+
},
35+
databaseConnLimitAttr: {
36+
Type: schema.TypeInt,
37+
Computed: true,
38+
Description: "The maximum number of concurrent connections that can be made to this database. A value of -1 means no limit.",
39+
},
40+
datashareProducerNameAttr: {
41+
Type: schema.TypeString,
42+
Computed: true,
43+
Optional: true,
44+
Description: "For databases created from datashares, this is the producer's datashare name.",
45+
},
46+
datashareProducerAccountAttr: {
47+
Type: schema.TypeString,
48+
Computed: true,
49+
Optional: true,
50+
Description: "For databases created from datashares, this is the producer's account number.",
51+
},
52+
datashareProducerNamespaceAttr: {
53+
Type: schema.TypeString,
54+
Computed: true,
55+
Optional: true,
56+
Description: "For databases created from datashares, this is the producer's namespace.",
57+
},
58+
},
59+
}
60+
}
61+
62+
func dataSourceRedshiftDatabaseRead(db *DBConnection, d *schema.ResourceData) error {
63+
var id, owner, connLimit string
64+
var shareName, producerAccount, producerNamespace sql.NullString
65+
66+
err := db.QueryRow(`SELECT
67+
pg_database_info.datid,
68+
trim(pg_user_info.usename),
69+
COALESCE(pg_database_info.datconnlimit::text, 'UNLIMITED'),
70+
trim(svv_datashares.share_name),
71+
trim(svv_datashares.producer_account),
72+
trim(svv_datashares.producer_namespace)
73+
FROM
74+
svv_redshift_databases
75+
LEFT JOIN pg_database_info
76+
ON svv_redshift_databases.database_name=pg_database_info.datname
77+
LEFT JOIN pg_user_info
78+
ON pg_user_info.usesysid = svv_redshift_databases.database_owner
79+
LEFT JOIN svv_datashares
80+
on (svv_datashares.share_type='INBOUND' AND svv_datashares.consumer_database=svv_redshift_databases.database_name)
81+
WHERE svv_redshift_databases.database_name = $1
82+
`, d.Get(databaseNameAttr).(string)).Scan(&id, &owner, &connLimit, &shareName, &producerAccount, &producerNamespace)
83+
84+
if err != nil {
85+
return err
86+
}
87+
88+
connLimitNumber := -1
89+
if connLimit != "UNLIMITED" {
90+
if connLimitNumber, err = strconv.Atoi(connLimit); err != nil {
91+
return err
92+
}
93+
}
94+
95+
d.SetId(id)
96+
d.Set(databaseOwnerAttr, owner)
97+
d.Set(databaseConnLimitAttr, connLimitNumber)
98+
99+
if shareName.Valid {
100+
d.Set(datashareProducerNameAttr, shareName.String)
101+
} else {
102+
d.Set(datashareProducerNameAttr, nil)
103+
}
104+
105+
if producerAccount.Valid {
106+
d.Set(datashareProducerAccountAttr, producerAccount.String)
107+
} else {
108+
d.Set(datashareProducerAccountAttr, nil)
109+
}
110+
111+
if producerNamespace.Valid {
112+
d.Set(datashareProducerNamespaceAttr, producerNamespace.String)
113+
} else {
114+
d.Set(datashareProducerNamespaceAttr, nil)
115+
}
116+
117+
return nil
118+
}
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
package redshift
2+
3+
import (
4+
"fmt"
5+
"strings"
6+
"testing"
7+
8+
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/acctest"
9+
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
10+
)
11+
12+
func TestAccDataSourceRedshiftDatabase_basic(t *testing.T) {
13+
dbName := strings.ReplaceAll(acctest.RandomWithPrefix("tf_acc_data_basic"), "-", "_")
14+
resource.ParallelTest(t, resource.TestCase{
15+
PreCheck: func() { testAccPreCheck(t) },
16+
Providers: testAccProviders,
17+
Steps: []resource.TestStep{
18+
{
19+
Config: testAccDataSourceRedshiftDatabaseConfig_basic(dbName),
20+
Check: resource.ComposeAggregateTestCheckFunc(
21+
testAccCheckDatabaseExists(dbName),
22+
resource.TestCheckResourceAttr("data.redshift_database.db", databaseNameAttr, dbName),
23+
resource.TestCheckResourceAttrSet("data.redshift_database.db", databaseOwnerAttr),
24+
resource.TestCheckResourceAttrSet("data.redshift_database.db", databaseConnLimitAttr),
25+
resource.TestCheckResourceAttr("data.redshift_database.db", datashareProducerNameAttr, ""),
26+
resource.TestCheckResourceAttr("data.redshift_database.db", datashareProducerAccountAttr, ""),
27+
resource.TestCheckResourceAttr("data.redshift_database.db", datashareProducerNamespaceAttr, ""),
28+
),
29+
},
30+
},
31+
})
32+
}
33+
34+
func testAccDataSourceRedshiftDatabaseConfig_basic(dbName string) string {
35+
return fmt.Sprintf(`
36+
resource "redshift_database" "db" {
37+
%[1]s = %[2]q
38+
}
39+
40+
data "redshift_database" "db" {
41+
%[1]s = redshift_database.db.%[1]s
42+
}
43+
`, databaseNameAttr, dbName)
44+
}

redshift/helpers.go

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,19 @@ func RedshiftResourceFunc(fn func(*DBConnection, *schema.ResourceData) error) fu
8484
}
8585
}
8686

87+
func RedshiftImportFunc(fn func(*DBConnection, *schema.ResourceData) ([]*schema.ResourceData, error)) func(*schema.ResourceData, interface{}) ([]*schema.ResourceData, error) {
88+
return func(d *schema.ResourceData, meta interface{}) ([]*schema.ResourceData, error) {
89+
client := meta.(*Client)
90+
91+
db, err := client.Connect()
92+
if err != nil {
93+
return nil, err
94+
}
95+
96+
return fn(db, d)
97+
}
98+
}
99+
87100
func RedshiftResourceRetryOnPQErrors(fn func(*DBConnection, *schema.ResourceData) error) func(*DBConnection, *schema.ResourceData) error {
88101
return func(db *DBConnection, d *schema.ResourceData) error {
89102
for i := 0; i < 10; i++ {

redshift/provider.go

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -120,10 +120,12 @@ func Provider() *schema.Provider {
120120
"redshift_group": redshiftGroup(),
121121
"redshift_schema": redshiftSchema(),
122122
"redshift_privilege": redshiftPrivilege(),
123+
"redshift_database": redshiftDatabase(),
123124
},
124125
DataSourcesMap: map[string]*schema.Resource{
125-
"redshift_user": dataSourceRedshiftUser(),
126-
"redshift_group": dataSourceRedshiftGroup(),
126+
"redshift_user": dataSourceRedshiftUser(),
127+
"redshift_group": dataSourceRedshiftGroup(),
128+
"redshift_database": dataSourceRedshiftDatabase(),
127129
},
128130
ConfigureFunc: providerConfigure,
129131
}

0 commit comments

Comments
 (0)