Skip to content

Commit 415ec24

Browse files
Add new teradata connection to global credentials and teradata credential resource and data source (#381)
1 parent 7dc8d0d commit 415ec24

18 files changed

Lines changed: 1430 additions & 1 deletion

docs/data-sources/global_connection.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ data dbtcloud_global_connection my_connection {
4242
- `snowflake` (Attributes) Snowflake connection configuration (see [below for nested schema](#nestedatt--snowflake))
4343
- `starburst` (Attributes) Starburst/Trino connection configuration. (see [below for nested schema](#nestedatt--starburst))
4444
- `synapse` (Attributes) Azure Synapse Analytics connection configuration. (see [below for nested schema](#nestedatt--synapse))
45+
- `teradata` (Attributes) Teradata connection configuration. (see [below for nested schema](#nestedatt--teradata))
4546

4647
<a id="nestedatt--apache_spark"></a>
4748
### Nested Schema for `apache_spark`
@@ -222,3 +223,15 @@ Read-Only:
222223
- `port` (Number) The port to connect to for this connection. Default=1433
223224
- `query_timeout` (Number) The number of seconds used to wait for a query before failing. Defaults to 0, which means that the timeout is disabled or uses the default system settings.
224225
- `retries` (Number) The number of automatic times to retry a query before failing. Defaults to 1. Queries with syntax errors will not be retried. This setting can be used to overcome intermittent network issues.
226+
227+
228+
<a id="nestedatt--teradata"></a>
229+
### Nested Schema for `teradata`
230+
231+
Read-Only:
232+
233+
- `host` (String) The hostname of the database.
234+
- `port` (String) The port to connect to for this connection. Default=1025
235+
- `request_timeout` (Number) The number of seconds used to establish a connection before failing. Defaults to 0, which means that the timeout is disabled or uses the default system settings.
236+
- `retries` (Number) The number of automatic times to retry a query before failing. Defaults to 1. Queries with syntax errors will not be retried. This setting can be used to overcome intermittent network issues.
237+
- `tmode` (String) The transaction mode to use for the connection.
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
---
2+
# generated by https://github.com/hashicorp/terraform-plugin-docs
3+
page_title: "dbtcloud_teradata_credential Data Source - dbtcloud"
4+
subcategory: ""
5+
description: |-
6+
Teradata credential data source
7+
---
8+
9+
# dbtcloud_teradata_credential (Data Source)
10+
11+
Teradata credential data source
12+
13+
14+
15+
<!-- schema generated by tfplugindocs -->
16+
## Schema
17+
18+
### Required
19+
20+
- `credential_id` (Number) Credential ID
21+
- `project_id` (Number) Project ID
22+
23+
### Read-Only
24+
25+
- `id` (String) The ID of this resource. Contains the project ID and the credential ID.
26+
- `password` (String, Sensitive) The password for the Teradata account
27+
- `schema` (String) The schema where to create models
28+
- `threads` (Number) The number of threads to use. Default is 1
29+
- `user` (String) The username for the Teradata account

docs/resources/global_connection.md

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,7 @@ resource "dbtcloud_global_connection" "synapse" {
164164
- `snowflake` (Attributes) Snowflake connection configuration (see [below for nested schema](#nestedatt--snowflake))
165165
- `starburst` (Attributes) Starburst/Trino connection configuration. (see [below for nested schema](#nestedatt--starburst))
166166
- `synapse` (Attributes) Azure Synapse Analytics connection configuration. (see [below for nested schema](#nestedatt--synapse))
167+
- `teradata` (Attributes) Teradata connection configuration. (see [below for nested schema](#nestedatt--teradata))
167168

168169
### Read-Only
169170

@@ -381,6 +382,21 @@ Optional:
381382
- `query_timeout` (Number) The number of seconds used to wait for a query before failing. Defaults to 0, which means that the timeout is disabled or uses the default system settings.
382383
- `retries` (Number) The number of automatic times to retry a query before failing. Defaults to 1. Queries with syntax errors will not be retried. This setting can be used to overcome intermittent network issues.
383384

385+
386+
<a id="nestedatt--teradata"></a>
387+
### Nested Schema for `teradata`
388+
389+
Required:
390+
391+
- `host` (String) The hostname of the database.
392+
- `tmode` (String) The transaction mode to use for the connection.
393+
394+
Optional:
395+
396+
- `port` (String) The port to connect to for this connection. Default=1025
397+
- `request_timeout` (Number) The number of seconds used to establish a connection before failing. Defaults to 0, which means that the timeout is disabled or uses the default system settings.
398+
- `retries` (Number) The number of automatic times to retry a query before failing. Defaults to 1. Queries with syntax errors will not be retried. This setting can be used to overcome intermittent network issues.
399+
384400
## Import
385401

386402
Import is supported using the following syntax:
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
---
2+
page_title: "dbtcloud_teradata_credential Resource - dbtcloud"
3+
subcategory: ""
4+
description: |-
5+
Teradata credential resource
6+
---
7+
8+
# dbtcloud_teradata_credential (Resource)
9+
10+
11+
Teradata credential resource
12+
13+
14+
15+
<!-- schema generated by tfplugindocs -->
16+
## Schema
17+
18+
### Required
19+
20+
- `password` (String, Sensitive) The password for the Teradata account
21+
- `project_id` (Number) Project ID to create the Teradata/Trino credential in
22+
- `schema` (String) The schema where to create models
23+
- `user` (String) The username for the Teradata account
24+
25+
### Optional
26+
27+
- `threads` (Number) The number of threads to use. Default is 1
28+
29+
### Read-Only
30+
31+
- `credential_id` (Number) The internal credential ID
32+
- `id` (String) The ID of this resource. Contains the project ID and the credential ID.

pkg/dbt_cloud/global_connection.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -510,3 +510,15 @@ type ApacheSparkConfig struct {
510510
func (ApacheSparkConfig) AdapterVersion() string {
511511
return "apache_spark_v0"
512512
}
513+
514+
type TeradataConfig struct {
515+
Port *string `json:"port,omitempty"`
516+
TMode *string `json:"tmode,omitempty"`
517+
Host *string `json:"host,omitempty"`
518+
Retries *int64 `json:"retries,omitempty"`
519+
RequestTimeout *int64 `json:"request_timeout,omitempty"`
520+
}
521+
522+
func (TeradataConfig) AdapterVersion() string {
523+
return "teradata_v0"
524+
}
Lines changed: 243 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,243 @@
1+
package dbt_cloud
2+
3+
import (
4+
"context"
5+
"encoding/json"
6+
"fmt"
7+
"net/http"
8+
"strings"
9+
10+
"github.com/hashicorp/terraform-plugin-log/tflog"
11+
)
12+
13+
type TeradataCredentialResponse struct {
14+
Data TeradataCredentialData `json:"data"`
15+
Status ResponseStatus `json:"status"`
16+
}
17+
18+
type TeradataUnencryptedCredentialDetails struct {
19+
Schema string `json:"schema"`
20+
TargetName string `json:"target_name"`
21+
Threads int `json:"threads"`
22+
}
23+
24+
// TeradataCredentialData represents the data returned by the API for an Teradata credential
25+
type TeradataCredentialData struct {
26+
ID *int `json:"id"`
27+
AccountID int `json:"account_id"`
28+
Threads int `json:"threads"`
29+
TargetName string `json:"target_name"`
30+
AdapterID int `json:"adapter_id"`
31+
AdapterVersion string `json:"adapter_version,omitempty"`
32+
UnencryptedCredentialDetails TeradataUnencryptedCredentialDetails `json:"unencrypted_credential_details"`
33+
}
34+
35+
// TeradataCredentialRequest is used for creating and updating Teradata credentials
36+
// It doesn't include the UnencryptedCredentialDetails field which is only returned by the API
37+
type TeradataCredentialRequest struct {
38+
ID *int `json:"id,omitempty"`
39+
AccountID int `json:"account_id"`
40+
ProjectID int `json:"project_id"`
41+
Type string `json:"type"`
42+
State int `json:"state"`
43+
Threads int `json:"threads"`
44+
TargetName string `json:"target_name"`
45+
AdapterID int `json:"adapter_id,omitempty"`
46+
AdapterVersion string `json:"adapter_version,omitempty"`
47+
CredentialDetails AdapterCredentialDetails `json:"credential_details"`
48+
}
49+
50+
func (c *Client) GetTeradataCredential(
51+
projectId int,
52+
credentialId int,
53+
) (*TeradataCredentialData, error) {
54+
req, err := http.NewRequest(
55+
"GET",
56+
fmt.Sprintf(
57+
"%s/v3/accounts/%d/projects/%d/credentials/%d/?include_related=[adapter]",
58+
c.HostURL,
59+
c.AccountID,
60+
projectId,
61+
credentialId,
62+
),
63+
nil,
64+
)
65+
if err != nil {
66+
return nil, err
67+
}
68+
69+
body, err := c.doRequest(req)
70+
if err != nil {
71+
return nil, err
72+
}
73+
74+
credentialResponse := TeradataCredentialResponse{}
75+
err = json.Unmarshal(body, &credentialResponse)
76+
if err != nil {
77+
return nil, err
78+
}
79+
80+
return &credentialResponse.Data, nil
81+
}
82+
83+
func (c *Client) CreateTeradataCredential(
84+
ctx context.Context,
85+
projectId int,
86+
username string,
87+
password string,
88+
schema string,
89+
threads int,
90+
) (*TeradataCredentialData, error) {
91+
credentialDetails, err := GenerateTeradataCredentialDetails(
92+
username,
93+
password,
94+
schema,
95+
threads,
96+
)
97+
if err != nil {
98+
return nil, err
99+
}
100+
101+
credential := TeradataCredentialRequest{
102+
ID: nil,
103+
AccountID: c.AccountID,
104+
ProjectID: projectId,
105+
Type: "adapter",
106+
State: STATE_ACTIVE,
107+
TargetName: DEFAULT_TARGET_NAME,
108+
Threads: threads,
109+
CredentialDetails: credentialDetails,
110+
AdapterVersion: "teradata_v0",
111+
}
112+
113+
rb, err := json.Marshal(credential)
114+
if err != nil {
115+
return nil, err
116+
}
117+
tflog.Debug(ctx, fmt.Sprintf("CreateTeradataCredential: %s", string(rb)))
118+
119+
req, err := http.NewRequest(
120+
"POST",
121+
fmt.Sprintf(
122+
"%s/v3/accounts/%d/projects/%d/credentials/",
123+
c.HostURL,
124+
c.AccountID,
125+
projectId,
126+
),
127+
strings.NewReader(string(rb)),
128+
)
129+
if err != nil {
130+
return nil, err
131+
}
132+
133+
body, err := c.doRequest(req)
134+
if err != nil {
135+
return nil, err
136+
}
137+
138+
tflog.Debug(ctx, fmt.Sprintf("CreateTeradataCredentialResponse: %s", string(body)))
139+
140+
credentialResponse := TeradataCredentialResponse{}
141+
err = json.Unmarshal(body, &credentialResponse)
142+
if err != nil {
143+
return nil, err
144+
}
145+
146+
return &credentialResponse.Data, nil
147+
}
148+
149+
func (c *Client) UpdateTeradataCredential(
150+
projectId int,
151+
credentialId int,
152+
teradataCredential TeradataCredentialRequest,
153+
) (*TeradataCredentialData, error) {
154+
rb, err := json.Marshal(teradataCredential)
155+
if err != nil {
156+
return nil, err
157+
}
158+
159+
req, err := http.NewRequest(
160+
"POST",
161+
fmt.Sprintf(
162+
"%s/v3/accounts/%d/projects/%d/credentials/%d/",
163+
c.HostURL,
164+
c.AccountID,
165+
projectId,
166+
credentialId,
167+
),
168+
strings.NewReader(string(rb)),
169+
)
170+
if err != nil {
171+
return nil, err
172+
}
173+
174+
body, err := c.doRequest(req)
175+
if err != nil {
176+
return nil, err
177+
}
178+
179+
credentialResponse := TeradataCredentialResponse{}
180+
err = json.Unmarshal(body, &credentialResponse)
181+
if err != nil {
182+
return nil, err
183+
}
184+
185+
return &credentialResponse.Data, nil
186+
}
187+
188+
func GenerateTeradataCredentialDetails(
189+
username string,
190+
password string,
191+
schema string,
192+
threads int,
193+
) (AdapterCredentialDetails, error) {
194+
// Create the credential details structure based on the payload example
195+
fields := map[string]AdapterCredentialField{
196+
"user": {
197+
Metadata: AdapterCredentialFieldMetadata{
198+
Label: "Teradata username",
199+
Description: "The username",
200+
Field_Type: "text",
201+
Encrypt: false,
202+
Overrideable: false,
203+
Validation: AdapterCredentialFieldMetadataValidation{Required: true},
204+
},
205+
Value: username,
206+
},
207+
"password": {
208+
Metadata: AdapterCredentialFieldMetadata{
209+
Label: "Teradata password",
210+
Description: "User's password",
211+
Field_Type: "text",
212+
Encrypt: true,
213+
Overrideable: false,
214+
Validation: AdapterCredentialFieldMetadataValidation{Required: true},
215+
},
216+
Value: password,
217+
},
218+
"schema": {
219+
Metadata: AdapterCredentialFieldMetadata{
220+
Label: "Schema",
221+
Description: "The schema to build models into",
222+
Field_Type: "text",
223+
Encrypt: false,
224+
Overrideable: false,
225+
Validation: AdapterCredentialFieldMetadataValidation{Required: true},
226+
},
227+
Value: schema,
228+
},
229+
"threads": {
230+
Metadata: AdapterCredentialFieldMetadata{
231+
Label: "Threads",
232+
Description: "The number of threads to use for dbt operations",
233+
Field_Type: "number",
234+
Encrypt: false,
235+
Overrideable: false,
236+
Validation: AdapterCredentialFieldMetadataValidation{Required: true},
237+
},
238+
Value: threads,
239+
},
240+
}
241+
242+
return AdapterCredentialDetails{Fields: fields}, nil
243+
}

0 commit comments

Comments
 (0)