Skip to content

Commit de22f31

Browse files
Migrate snowflake credential data-source & resource (#376)
* Migrate snowflake credential data-source * Remove sdkv2 data-source * Migrate snowflake credential resource * Add conformance tests and fix issues * Fixed conformance tests. * Update docs
1 parent 81bffb8 commit de22f31

13 files changed

Lines changed: 958 additions & 598 deletions

File tree

docs/data-sources/snowflake_credential.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,12 @@
33
page_title: "dbtcloud_snowflake_credential Data Source - dbtcloud"
44
subcategory: ""
55
description: |-
6-
6+
Snowflake credential data source
77
---
88

99
# dbtcloud_snowflake_credential (Data Source)
1010

11-
11+
Snowflake credential data source
1212

1313

1414

@@ -23,8 +23,8 @@ description: |-
2323
### Read-Only
2424

2525
- `auth_type` (String) The type of Snowflake credential ('password' or 'keypair')
26-
- `id` (String) The ID of this resource.
26+
- `id` (String) The ID of this resource. Contains the project ID and the credential ID.
2727
- `is_active` (Boolean) Whether the Snowflake credential is active
2828
- `num_threads` (Number) Number of threads to use
29-
- `schema` (String) Default schema name
29+
- `schema` (String) The schema where to create models
3030
- `user` (String) Username for Snowflake

docs/resources/snowflake_credential.md

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,13 @@
22
page_title: "dbtcloud_snowflake_credential Resource - dbtcloud"
33
subcategory: ""
44
description: |-
5-
5+
Snowflake credential resource
66
---
77

88
# dbtcloud_snowflake_credential (Resource)
99

1010

11-
11+
Snowflake credential resource
1212

1313
## Example Usage
1414

@@ -31,23 +31,23 @@ resource "dbtcloud_snowflake_credential" "prod_credential" {
3131
- `auth_type` (String) The type of Snowflake credential ('password' or 'keypair')
3232
- `num_threads` (Number) Number of threads to use
3333
- `project_id` (Number) Project ID to create the Snowflake credential in
34-
- `schema` (String) Default schema name
35-
- `user` (String) Username for Snowflake
34+
- `schema` (String) The schema where to create models
35+
- `user` (String) The username for the Snowflake account
3636

3737
### Optional
3838

39-
- `database` (String) Database to connect to
39+
- `database` (String) The catalog to connect use
4040
- `is_active` (Boolean) Whether the Snowflake credential is active
41-
- `password` (String, Sensitive) Password for Snowflake
42-
- `private_key` (String, Sensitive) Private key for Snowflake
43-
- `private_key_passphrase` (String, Sensitive) Private key passphrase for Snowflake
44-
- `role` (String) Role to assume
45-
- `warehouse` (String) Warehouse to use
41+
- `password` (String, Sensitive) The password for the Snowflake account
42+
- `private_key` (String, Sensitive) The private key for the Snowflake account
43+
- `private_key_passphrase` (String, Sensitive) The passphrase for the private key
44+
- `role` (String) The role to assume
45+
- `warehouse` (String) The warehouse to use
4646

4747
### Read-Only
4848

49-
- `credential_id` (Number) The system Snowflake credential ID
50-
- `id` (String) The ID of this resource.
49+
- `credential_id` (Number) The internal credential ID
50+
- `id` (String) The ID of this resource. Contains the project ID and the credential ID.
5151

5252
## Import
5353

pkg/framework/objects/athena_credential/resource_acceptance_test.go

Lines changed: 88 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import (
55
"regexp"
66
"testing"
77

8+
"github.com/dbt-labs/terraform-provider-dbtcloud/pkg/framework/acctest_config"
89
"github.com/dbt-labs/terraform-provider-dbtcloud/pkg/framework/acctest_helper"
910
"github.com/dbt-labs/terraform-provider-dbtcloud/pkg/helper"
1011
"github.com/hashicorp/terraform-plugin-testing/helper/acctest"
@@ -18,64 +19,101 @@ func TestAccDbtCloudAthenaCredentialResource(t *testing.T) {
1819
awsAccessKeyID := "test_access_key_id"
1920
awsSecretAccessKey := "test_secret_access_key"
2021

22+
var step1 = resource.TestStep{
23+
Config: testAccDbtCloudAthenaCredentialResourceConfig(
24+
projectName,
25+
schema,
26+
awsAccessKeyID,
27+
awsSecretAccessKey,
28+
),
29+
Check: resource.ComposeAggregateTestCheckFunc(
30+
testAccCheckDbtCloudAthenaCredentialExists("dbtcloud_athena_credential.test"),
31+
resource.TestCheckResourceAttrSet(
32+
"dbtcloud_athena_credential.test",
33+
"id",
34+
),
35+
resource.TestCheckResourceAttrSet(
36+
"dbtcloud_athena_credential.test",
37+
"credential_id",
38+
),
39+
resource.TestCheckResourceAttr(
40+
"dbtcloud_athena_credential.test",
41+
"schema",
42+
schema,
43+
),
44+
),
45+
}
46+
47+
var step2 = resource.TestStep{
48+
ResourceName: "dbtcloud_athena_credential.test",
49+
ImportState: true,
50+
ImportStateVerify: true,
51+
// These fields can't be read from the API
52+
ImportStateVerifyIgnore: []string{
53+
"aws_access_key_id",
54+
"aws_secret_access_key",
55+
},
56+
}
57+
58+
var step3 = resource.TestStep{
59+
Config: testAccDbtCloudAthenaCredentialResourceConfig(
60+
projectName,
61+
"updated_schema",
62+
awsAccessKeyID,
63+
awsSecretAccessKey,
64+
),
65+
Check: resource.ComposeAggregateTestCheckFunc(
66+
testAccCheckDbtCloudAthenaCredentialExists("dbtcloud_athena_credential.test"),
67+
resource.TestCheckResourceAttr(
68+
"dbtcloud_athena_credential.test",
69+
"schema",
70+
"updated_schema",
71+
),
72+
),
73+
}
74+
2175
resource.ParallelTest(t, resource.TestCase{
2276
PreCheck: func() { acctest_helper.TestAccPreCheck(t) },
2377
ProtoV6ProviderFactories: acctest_helper.TestAccProtoV6ProviderFactories,
2478
CheckDestroy: testAccCheckDbtCloudAthenaCredentialDestroy,
2579
Steps: []resource.TestStep{
2680
// Create and Read testing
27-
{
28-
Config: testAccDbtCloudAthenaCredentialResourceConfig(
29-
projectName,
30-
schema,
31-
awsAccessKeyID,
32-
awsSecretAccessKey,
33-
),
34-
Check: resource.ComposeAggregateTestCheckFunc(
35-
testAccCheckDbtCloudAthenaCredentialExists("dbtcloud_athena_credential.test"),
36-
resource.TestCheckResourceAttrSet(
37-
"dbtcloud_athena_credential.test",
38-
"id",
39-
),
40-
resource.TestCheckResourceAttrSet(
41-
"dbtcloud_athena_credential.test",
42-
"credential_id",
43-
),
44-
resource.TestCheckResourceAttr(
45-
"dbtcloud_athena_credential.test",
46-
"schema",
47-
schema,
48-
),
49-
),
50-
},
81+
step1,
5182
// ImportState testing
52-
{
53-
ResourceName: "dbtcloud_athena_credential.test",
54-
ImportState: true,
55-
ImportStateVerify: true,
56-
// These fields can't be read from the API
57-
ImportStateVerifyIgnore: []string{
58-
"aws_access_key_id",
59-
"aws_secret_access_key",
60-
},
61-
},
83+
step2,
6284
// Update and Read testing
63-
{
64-
Config: testAccDbtCloudAthenaCredentialResourceConfig(
65-
projectName,
66-
"updated_schema",
67-
awsAccessKeyID,
68-
awsSecretAccessKey,
69-
),
70-
Check: resource.ComposeAggregateTestCheckFunc(
71-
testAccCheckDbtCloudAthenaCredentialExists("dbtcloud_athena_credential.test"),
72-
resource.TestCheckResourceAttr(
73-
"dbtcloud_athena_credential.test",
74-
"schema",
75-
"updated_schema",
76-
),
77-
),
78-
},
85+
step3,
86+
},
87+
})
88+
89+
// test the Framework implementation
90+
resource.Test(t, resource.TestCase{
91+
PreCheck: func() { acctest_helper.TestAccPreCheck(t) },
92+
ProtoV6ProviderFactories: acctest_helper.TestAccProtoV6ProviderFactories,
93+
CheckDestroy: testAccCheckDbtCloudAthenaCredentialDestroy,
94+
Steps: []resource.TestStep{
95+
step1,
96+
step2,
97+
step3,
98+
},
99+
})
100+
101+
resource.Test(t, resource.TestCase{
102+
PreCheck: func() { acctest_helper.TestAccPreCheck(t) },
103+
CheckDestroy: testAccCheckDbtCloudAthenaCredentialDestroy,
104+
Steps: []resource.TestStep{
105+
acctest_helper.MakeExternalProviderTestStep(step1, acctest_config.LAST_VERSION_BEFORE_FRAMEWORK_MIGRATION),
106+
acctest_helper.MakeCurrentProviderNoOpTestStep(step1),
107+
},
108+
})
109+
110+
// MODIFY: test that running commands in SDKv2 and then the same commands in Framework generates a NoOp plan
111+
resource.Test(t, resource.TestCase{
112+
PreCheck: func() { acctest_helper.TestAccPreCheck(t) },
113+
CheckDestroy: testAccCheckDbtCloudAthenaCredentialDestroy,
114+
Steps: []resource.TestStep{
115+
acctest_helper.MakeExternalProviderTestStep(step3, acctest_config.LAST_VERSION_BEFORE_FRAMEWORK_MIGRATION),
116+
acctest_helper.MakeCurrentProviderNoOpTestStep(step3),
79117
},
80118
})
81119
}
Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
package snowflake_credential
2+
3+
import (
4+
"context"
5+
"fmt"
6+
7+
"github.com/dbt-labs/terraform-provider-dbtcloud/pkg/dbt_cloud"
8+
"github.com/hashicorp/terraform-plugin-framework/datasource"
9+
"github.com/hashicorp/terraform-plugin-framework/types"
10+
)
11+
12+
// Ensure the implementation satisfies the expected interfaces.
13+
var (
14+
_ datasource.DataSource = &snowflakeCredentialDataSource{}
15+
_ datasource.DataSourceWithConfigure = &snowflakeCredentialDataSource{}
16+
)
17+
18+
// SnowflakeCredentialDataSource is a helper function to simplify the provider implementation.
19+
func SnowflakeCredentialDataSource() datasource.DataSource {
20+
return &snowflakeCredentialDataSource{}
21+
}
22+
23+
// snowflakeCredentialDataSource is the data source implementation.
24+
type snowflakeCredentialDataSource struct {
25+
client *dbt_cloud.Client
26+
}
27+
28+
// Configure adds the provider configured client to the data source.
29+
func (d *snowflakeCredentialDataSource) Configure(
30+
ctx context.Context,
31+
req datasource.ConfigureRequest,
32+
resp *datasource.ConfigureResponse,
33+
) {
34+
if req.ProviderData == nil {
35+
return
36+
}
37+
38+
client, ok := req.ProviderData.(*dbt_cloud.Client)
39+
if !ok {
40+
resp.Diagnostics.AddError(
41+
"Unexpected Data Source Configure Type",
42+
fmt.Sprintf(
43+
"Expected *dbt_cloud.Client, got: %T. Please report this issue to the provider developers.",
44+
req.ProviderData,
45+
),
46+
)
47+
return
48+
}
49+
50+
d.client = client
51+
}
52+
53+
// Metadata returns the data source type name.
54+
func (d *snowflakeCredentialDataSource) Metadata(
55+
ctx context.Context,
56+
req datasource.MetadataRequest,
57+
resp *datasource.MetadataResponse,
58+
) {
59+
resp.TypeName = req.ProviderTypeName + "_snowflake_credential"
60+
}
61+
62+
// Schema defines the schema for the data source.
63+
func (d *snowflakeCredentialDataSource) Schema(
64+
ctx context.Context,
65+
req datasource.SchemaRequest,
66+
resp *datasource.SchemaResponse,
67+
) {
68+
resp.Schema = datasourceSchema
69+
}
70+
71+
// Read refreshes the Terraform state with the latest data.
72+
func (d *snowflakeCredentialDataSource) Read(
73+
ctx context.Context,
74+
req datasource.ReadRequest,
75+
resp *datasource.ReadResponse,
76+
) {
77+
var state SnowflakeCredentialDataSourceModel
78+
diags := req.Config.Get(ctx, &state)
79+
resp.Diagnostics.Append(diags...)
80+
if resp.Diagnostics.HasError() {
81+
return
82+
}
83+
84+
projectID := int(state.ProjectID.ValueInt64())
85+
credentialID := int(state.CredentialID.ValueInt64())
86+
87+
credential, err := d.client.GetSnowflakeCredential(projectID, credentialID)
88+
if err != nil {
89+
resp.Diagnostics.AddError(
90+
"Error reading Snowflake credential",
91+
"Could not read Snowflake credential ID "+state.ID.ValueString()+": "+err.Error(),
92+
)
93+
return
94+
}
95+
96+
// Map response body to model
97+
state.ID = types.StringValue(fmt.Sprintf("%d:%d", projectID, credentialID))
98+
state.Schema = types.StringValue(credential.Schema)
99+
state.IsActive = types.BoolValue(credential.State == dbt_cloud.STATE_ACTIVE)
100+
state.AuthType = types.StringValue(credential.Auth_Type)
101+
state.ProjectID = types.Int64Value(int64(projectID))
102+
state.CredentialID = types.Int64Value(int64(credentialID))
103+
state.User = types.StringValue(credential.User)
104+
state.NumThreads = types.Int64Value(int64(credential.Threads))
105+
106+
// Set state
107+
diags = resp.State.Set(ctx, &state)
108+
resp.Diagnostics.Append(diags...)
109+
if resp.Diagnostics.HasError() {
110+
return
111+
}
112+
}

pkg/sdkv2/data_sources/snowflake_credential_acceptance_test.go renamed to pkg/framework/objects/snowflake_credential/data_source_acceptance_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package data_sources_test
1+
package snowflake_credential_test
22

33
import (
44
"fmt"
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
package snowflake_credential
2+
3+
import (
4+
"github.com/hashicorp/terraform-plugin-framework/types"
5+
)
6+
7+
// SnowflakeCredentialDataSourceModel is the model for the data source
8+
type SnowflakeCredentialDataSourceModel struct {
9+
ID types.String `tfsdk:"id"`
10+
CredentialID types.Int64 `tfsdk:"credential_id"`
11+
IsActive types.Bool `tfsdk:"is_active"`
12+
AuthType types.String `tfsdk:"auth_type"`
13+
ProjectID types.Int64 `tfsdk:"project_id"`
14+
Schema types.String `tfsdk:"schema"`
15+
User types.String `tfsdk:"user"`
16+
NumThreads types.Int64 `tfsdk:"num_threads"`
17+
}
18+
19+
// SnowflakeCredentialResourceModel is the model for the resource
20+
type SnowflakeCredentialResourceModel struct {
21+
ID types.String `tfsdk:"id"`
22+
CredentialID types.Int64 `tfsdk:"credential_id"`
23+
ProjectID types.Int64 `tfsdk:"project_id"`
24+
User types.String `tfsdk:"user"`
25+
Password types.String `tfsdk:"password"`
26+
AuthType types.String `tfsdk:"auth_type"`
27+
Database types.String `tfsdk:"database"`
28+
Role types.String `tfsdk:"role"`
29+
Warehouse types.String `tfsdk:"warehouse"`
30+
Schema types.String `tfsdk:"schema"`
31+
PrivateKey types.String `tfsdk:"private_key"`
32+
PrivateKeyPassphrase types.String `tfsdk:"private_key_passphrase"`
33+
IsActive types.Bool `tfsdk:"is_active"`
34+
NumThreads types.Int64 `tfsdk:"num_threads"`
35+
}

0 commit comments

Comments
 (0)