-
Notifications
You must be signed in to change notification settings - Fork 391
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
[Internal] Migrate databricks_clusters
data source to plugin framework
#3998
base: main
Are you sure you want to change the base?
Changes from all commits
7ac1db9
d7cf48a
3bb5ba5
c7c258a
93c023a
a7ff8cc
e6703ad
a707ca1
eed6c80
04ab5e7
ceaf1a7
c5d1bb6
2b0e0be
f2b558a
5c71dc6
c4de462
d98e1dc
ed43879
607809b
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,106 @@ | ||
package cluster | ||
|
||
import ( | ||
"context" | ||
"fmt" | ||
|
||
"github.com/databricks/databricks-sdk-go/apierr" | ||
"github.com/databricks/databricks-sdk-go/service/compute" | ||
"github.com/databricks/terraform-provider-databricks/common" | ||
pluginfwcommon "github.com/databricks/terraform-provider-databricks/internal/providers/pluginfw/common" | ||
"github.com/databricks/terraform-provider-databricks/internal/providers/pluginfw/converters" | ||
"github.com/databricks/terraform-provider-databricks/internal/providers/pluginfw/tfschema" | ||
"github.com/databricks/terraform-provider-databricks/internal/service/compute_tf" | ||
"github.com/hashicorp/terraform-plugin-framework/datasource" | ||
"github.com/hashicorp/terraform-plugin-framework/datasource/schema" | ||
"github.com/hashicorp/terraform-plugin-framework/types" | ||
) | ||
|
||
func DataSourceCluster() datasource.DataSource { | ||
return &ClusterDataSource{} | ||
} | ||
|
||
var _ datasource.DataSourceWithConfigure = &ClusterDataSource{} | ||
|
||
type ClusterDataSource struct { | ||
Client *common.DatabricksClient | ||
} | ||
|
||
type ClusterInfo struct { | ||
ClusterId types.String `tfsdk:"cluster_id" tf:"optional,computed"` | ||
Name types.String `tfsdk:"cluster_name" tf:"optional,computed"` | ||
ClusterInfo *compute_tf.ClusterDetails `tfsdk:"cluster_info" tf:"optional,computed"` | ||
} | ||
|
||
func (d *ClusterDataSource) Metadata(ctx context.Context, req datasource.MetadataRequest, resp *datasource.MetadataResponse) { | ||
resp.TypeName = "databricks_cluster_pluginframework" | ||
} | ||
|
||
func (d *ClusterDataSource) Schema(ctx context.Context, req datasource.SchemaRequest, resp *datasource.SchemaResponse) { | ||
resp.Schema = schema.Schema{ | ||
Attributes: tfschema.DataSourceStructToSchemaMap(ClusterInfo{}, nil), | ||
} | ||
} | ||
|
||
func (d *ClusterDataSource) Configure(_ context.Context, req datasource.ConfigureRequest, resp *datasource.ConfigureResponse) { | ||
if d.Client == nil { | ||
d.Client = pluginfwcommon.ConfigureDataSource(req, resp) | ||
} | ||
} | ||
|
||
func (d *ClusterDataSource) Read(ctx context.Context, req datasource.ReadRequest, resp *datasource.ReadResponse) { | ||
w, diags := d.Client.GetWorkspaceClient() | ||
resp.Diagnostics.Append(diags...) | ||
if resp.Diagnostics.HasError() { | ||
return | ||
} | ||
|
||
var clusterInfo ClusterInfo | ||
resp.Diagnostics.Append(req.Config.Get(ctx, &clusterInfo)...) | ||
if resp.Diagnostics.HasError() { | ||
return | ||
} | ||
if clusterInfo.Name.ValueString() != "" { | ||
clusters, err := w.Clusters.ListAll(ctx, compute.ListClustersRequest{}) | ||
if err != nil { | ||
if apierr.IsMissing(err) { | ||
resp.State.RemoveResource(ctx) | ||
} | ||
resp.Diagnostics.AddError("failed to list clusters", err.Error()) | ||
return | ||
} | ||
var clustersTfSDK []compute_tf.ClusterDetails | ||
converters.GoSdkToTfSdkStruct(ctx, clusters, clustersTfSDK) | ||
namedClusters := []compute_tf.ClusterDetails{} | ||
for _, clst := range clustersTfSDK { | ||
cluster := clst | ||
if cluster.ClusterName == clusterInfo.Name { | ||
namedClusters = append(namedClusters, cluster) | ||
} | ||
} | ||
if len(namedClusters) == 0 { | ||
resp.Diagnostics.AddError(fmt.Sprintf("there is no cluster with name '%s'", clusterInfo.Name.ValueString()), "") | ||
return | ||
} | ||
if len(namedClusters) > 1 { | ||
resp.Diagnostics.AddError(fmt.Sprintf("there is more than one cluster with name '%s'", clusterInfo.Name.ValueString()), "") | ||
return | ||
} | ||
clusterInfo.ClusterInfo = &namedClusters[0] | ||
} else if clusterInfo.ClusterId.ValueString() != "" { | ||
cluster, err := w.Clusters.GetByClusterId(ctx, clusterInfo.ClusterId.ValueString()) | ||
if err != nil { | ||
if apierr.IsMissing(err) { | ||
resp.State.RemoveResource(ctx) | ||
} | ||
resp.Diagnostics.AddError(fmt.Sprintf("failed to get cluster with cluster id: %s", clusterInfo.ClusterId.ValueString()), err.Error()) | ||
return | ||
} | ||
converters.GoSdkToTfSdkStruct(ctx, cluster, clusterInfo.ClusterInfo) | ||
} else { | ||
resp.Diagnostics.AddError("you need to specify either `cluster_name` or `cluster_id`", "") | ||
return | ||
} | ||
clusterInfo.ClusterId = clusterInfo.ClusterInfo.ClusterId | ||
resp.Diagnostics.Append(resp.State.Set(ctx, clusterInfo)...) | ||
} |
Original file line number | Diff line number | Diff line change | ||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
@@ -0,0 +1,81 @@ | ||||||||||||||||
package cluster | ||||||||||||||||
|
||||||||||||||||
import ( | ||||||||||||||||
"context" | ||||||||||||||||
"strings" | ||||||||||||||||
|
||||||||||||||||
"github.com/databricks/databricks-sdk-go/apierr" | ||||||||||||||||
"github.com/databricks/databricks-sdk-go/service/compute" | ||||||||||||||||
"github.com/databricks/terraform-provider-databricks/common" | ||||||||||||||||
pluginfwcommon "github.com/databricks/terraform-provider-databricks/internal/providers/pluginfw/common" | ||||||||||||||||
"github.com/databricks/terraform-provider-databricks/internal/providers/pluginfw/tfschema" | ||||||||||||||||
"github.com/hashicorp/terraform-plugin-framework/datasource" | ||||||||||||||||
"github.com/hashicorp/terraform-plugin-framework/datasource/schema" | ||||||||||||||||
"github.com/hashicorp/terraform-plugin-framework/types" | ||||||||||||||||
) | ||||||||||||||||
|
||||||||||||||||
func DataSourceClusters() datasource.DataSource { | ||||||||||||||||
return &ClustersDataSource{} | ||||||||||||||||
} | ||||||||||||||||
|
||||||||||||||||
var _ datasource.DataSourceWithConfigure = &ClustersDataSource{} | ||||||||||||||||
|
||||||||||||||||
type ClustersDataSource struct { | ||||||||||||||||
Client *common.DatabricksClient | ||||||||||||||||
} | ||||||||||||||||
|
||||||||||||||||
type ClustersInfo struct { | ||||||||||||||||
Ids []types.String `tfsdk:"ids" tf:"optional,computed"` | ||||||||||||||||
ClusterNameContains types.String `tfsdk:"cluster_name_contains" tf:"optional"` | ||||||||||||||||
} | ||||||||||||||||
|
||||||||||||||||
func (d *ClustersDataSource) Metadata(ctx context.Context, req datasource.MetadataRequest, resp *datasource.MetadataResponse) { | ||||||||||||||||
resp.TypeName = "databricks_clusters_pluginframework" | ||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ditto here |
||||||||||||||||
} | ||||||||||||||||
|
||||||||||||||||
func (d *ClustersDataSource) Schema(ctx context.Context, req datasource.SchemaRequest, resp *datasource.SchemaResponse) { | ||||||||||||||||
resp.Schema = schema.Schema{ | ||||||||||||||||
Attributes: tfschema.DataSourceStructToSchemaMap(ClustersInfo{}, nil), | ||||||||||||||||
} | ||||||||||||||||
} | ||||||||||||||||
|
||||||||||||||||
func (d *ClustersDataSource) Configure(_ context.Context, req datasource.ConfigureRequest, resp *datasource.ConfigureResponse) { | ||||||||||||||||
if d.Client == nil { | ||||||||||||||||
d.Client = pluginfwcommon.ConfigureDataSource(req, resp) | ||||||||||||||||
} | ||||||||||||||||
} | ||||||||||||||||
|
||||||||||||||||
func (d *ClustersDataSource) Read(ctx context.Context, req datasource.ReadRequest, resp *datasource.ReadResponse) { | ||||||||||||||||
w, diags := d.Client.GetWorkspaceClient() | ||||||||||||||||
resp.Diagnostics.Append(diags...) | ||||||||||||||||
if resp.Diagnostics.HasError() { | ||||||||||||||||
return | ||||||||||||||||
} | ||||||||||||||||
|
||||||||||||||||
var clustersInfo ClustersInfo | ||||||||||||||||
resp.Diagnostics.Append(req.Config.Get(ctx, &clustersInfo)...) | ||||||||||||||||
if resp.Diagnostics.HasError() { | ||||||||||||||||
return | ||||||||||||||||
} | ||||||||||||||||
|
||||||||||||||||
clusters, err := w.Clusters.ListAll(ctx, compute.ListClustersRequest{}) | ||||||||||||||||
if err != nil { | ||||||||||||||||
if apierr.IsMissing(err) { | ||||||||||||||||
resp.State.RemoveResource(ctx) | ||||||||||||||||
} | ||||||||||||||||
Comment on lines
+63
to
+65
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Would this happen? Is it an error if there are no clusters? (Probably not.) |
||||||||||||||||
resp.Diagnostics.AddError("failed to list clusters", err.Error()) | ||||||||||||||||
return | ||||||||||||||||
} | ||||||||||||||||
|
||||||||||||||||
ids := make([]types.String, 0, len(clusters)) | ||||||||||||||||
name_contains := strings.ToLower(clustersInfo.ClusterNameContains.ValueString()) | ||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. can we use camelCase? |
||||||||||||||||
for _, v := range clusters { | ||||||||||||||||
match_name := strings.Contains(strings.ToLower(v.ClusterName), name_contains) | ||||||||||||||||
if name_contains != "" && !match_name { | ||||||||||||||||
continue | ||||||||||||||||
} | ||||||||||||||||
ids = append(ids, types.StringValue(v.ClusterId)) | ||||||||||||||||
Comment on lines
+74
to
+77
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. strings.Contains(any string, "") should always be true.
Suggested change
|
||||||||||||||||
} | ||||||||||||||||
clustersInfo.Ids = ids | ||||||||||||||||
resp.Diagnostics.Append(resp.State.Set(ctx, clustersInfo)...) | ||||||||||||||||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
package tests | ||
|
||
import ( | ||
"testing" | ||
|
||
"github.com/databricks/terraform-provider-databricks/internal/acceptance" | ||
) | ||
|
||
func TestAccDataSourceCluster(t *testing.T) { | ||
acceptance.WorkspaceLevel(t, acceptance.Step{ | ||
Template: ` | ||
data "databricks_cluster_pluginframework" "this" { | ||
cluster_id = "{env.TEST_DEFAULT_CLUSTER_ID}" | ||
} | ||
|
||
output "cluster_info" { | ||
value = data.databricks_cluster_pluginframework.this.cluster_info | ||
}`, | ||
}) | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
package tests | ||
|
||
import ( | ||
"testing" | ||
|
||
"github.com/databricks/terraform-provider-databricks/internal/acceptance" | ||
) | ||
|
||
func TestAccDataSourceClustersNoFilter(t *testing.T) { | ||
acceptance.WorkspaceLevel(t, acceptance.Step{ | ||
Template: ` | ||
data "databricks_clusters_pluginframework" "this" { | ||
} `, | ||
}) | ||
} | ||
|
||
func TestAccDataSourceClustersWithFilter(t *testing.T) { | ||
acceptance.WorkspaceLevel(t, acceptance.Step{ | ||
Template: ` | ||
data "databricks_clusters_pluginframework" "this" { | ||
cluster_name_contains = "Default" | ||
}`, | ||
}) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we should also try adding a proto level annotation for making a field computed in the tf configuration, so the generated tfsdk structs will have these