Skip to content

Commit 24e6267

Browse files
authored
ClickPipe resource import support (#277)
1 parent 6be3f68 commit 24e6267

File tree

5 files changed

+74
-16
lines changed

5 files changed

+74
-16
lines changed

examples/clickpipe/kafka_confluent/main.tf

+4
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
variable "organization_id" {}
2+
variable "token_key" {}
3+
variable "token_secret" {}
4+
15
variable "service_id" {
26
description = "ClickHouse service ID"
37
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
# ClickPipes can be imported by specifying both service ID and clickpipe ID.
2+
terraform import clickhouse_clickpipe.example xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
# ClickPipes reverse private endpoints can be imported by specifying both service ID and clickpipe ID.
2+
terraform import clickhouse_clickpipes_reverse_private_endpoint.example xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx

pkg/resource/clickpipe.go

+61-14
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import (
1313
"github.com/hashicorp/terraform-plugin-framework-validators/stringvalidator"
1414
"github.com/hashicorp/terraform-plugin-framework/attr"
1515
"github.com/hashicorp/terraform-plugin-framework/diag"
16+
"github.com/hashicorp/terraform-plugin-framework/path"
1617
"github.com/hashicorp/terraform-plugin-framework/resource"
1718
"github.com/hashicorp/terraform-plugin-framework/resource/schema"
1819
"github.com/hashicorp/terraform-plugin-framework/resource/schema/booldefault"
@@ -29,9 +30,10 @@ import (
2930
)
3031

3132
var (
32-
_ resource.Resource = &ClickPipeResource{}
33-
_ resource.ResourceWithModifyPlan = &ClickPipeResource{}
34-
_ resource.ResourceWithConfigure = &ClickPipeResource{}
33+
_ resource.Resource = &ClickPipeResource{}
34+
_ resource.ResourceWithModifyPlan = &ClickPipeResource{}
35+
_ resource.ResourceWithConfigure = &ClickPipeResource{}
36+
_ resource.ResourceWithImportState = &ClickPipeResource{}
3537
)
3638

3739
const clickPipeResourceDescription = `
@@ -884,15 +886,19 @@ func (c *ClickPipeResource) syncClickPipeState(ctx context.Context, state *model
884886
}
885887

886888
stateSourceModel := models.ClickPipeSourceModel{}
887-
if diags := state.Source.As(ctx, &stateSourceModel, basetypes.ObjectAsOptions{}); diags.HasError() {
888-
return fmt.Errorf("error reading ClickPipe source: %v", diags)
889+
if !state.Source.IsNull() {
890+
if diags := state.Source.As(ctx, &stateSourceModel, basetypes.ObjectAsOptions{}); diags.HasError() {
891+
return fmt.Errorf("error reading ClickPipe source: %v", diags)
892+
}
889893
}
890894

891895
sourceModel := models.ClickPipeSourceModel{}
892896
if clickPipe.Source.Kafka != nil {
893897
stateKafkaModel := models.ClickPipeKafkaSourceModel{}
894-
if diags := stateSourceModel.Kafka.As(ctx, &stateKafkaModel, basetypes.ObjectAsOptions{}); diags.HasError() {
895-
return fmt.Errorf("error reading ClickPipe Kafka source: %v", diags)
898+
if !stateSourceModel.Kafka.IsNull() {
899+
if diags := stateSourceModel.Kafka.As(ctx, &stateKafkaModel, basetypes.ObjectAsOptions{}); diags.HasError() {
900+
return fmt.Errorf("error reading ClickPipe Kafka source: %v", diags)
901+
}
896902
}
897903

898904
var consumerGroup string
@@ -923,8 +929,10 @@ func (c *ClickPipeResource) syncClickPipeState(ctx context.Context, state *model
923929

924930
if clickPipe.Source.Kafka.SchemaRegistry != nil {
925931
var stateSchemaRegistryModel models.ClickPipeKafkaSchemaRegistryModel
926-
if diags := stateKafkaModel.SchemaRegistry.As(ctx, &stateSchemaRegistryModel, basetypes.ObjectAsOptions{}); diags.HasError() {
927-
return fmt.Errorf("error reading ClickPipe Kafka source schema registry: %v", diags)
932+
if !stateKafkaModel.SchemaRegistry.IsNull() {
933+
if diags := stateKafkaModel.SchemaRegistry.As(ctx, &stateSchemaRegistryModel, basetypes.ObjectAsOptions{}); diags.HasError() {
934+
return fmt.Errorf("error reading ClickPipe Kafka source schema registry: %v", diags)
935+
}
928936
}
929937

930938
schemaRegistryModel := models.ClickPipeKafkaSchemaRegistryModel{
@@ -966,8 +974,11 @@ func (c *ClickPipeResource) syncClickPipeState(ctx context.Context, state *model
966974

967975
if clickPipe.Source.ObjectStorage != nil {
968976
stateObjectStorageModel := models.ClickPipeObjectStorageSourceModel{}
969-
if diags := stateSourceModel.ObjectStorage.As(ctx, &stateObjectStorageModel, basetypes.ObjectAsOptions{}); diags.HasError() {
970-
return fmt.Errorf("error reading ClickPipe object storage source: %v", diags)
977+
978+
if !stateSourceModel.ObjectStorage.IsNull() {
979+
if diags := stateSourceModel.ObjectStorage.As(ctx, &stateObjectStorageModel, basetypes.ObjectAsOptions{}); diags.HasError() {
980+
return fmt.Errorf("error reading ClickPipe object storage source: %v", diags)
981+
}
971982
}
972983

973984
objectStorageModel := models.ClickPipeObjectStorageSourceModel{
@@ -1009,12 +1020,19 @@ func (c *ClickPipeResource) syncClickPipeState(ctx context.Context, state *model
10091020
}
10101021

10111022
stateDestinationModel := models.ClickPipeDestinationModel{}
1012-
if diags := state.Destination.As(ctx, &stateDestinationModel, basetypes.ObjectAsOptions{}); diags.HasError() {
1013-
return fmt.Errorf("error reading ClickPipe destination: %v", diags)
1023+
1024+
if !state.Destination.IsNull() {
1025+
if diags := state.Destination.As(ctx, &stateDestinationModel, basetypes.ObjectAsOptions{}); diags.HasError() {
1026+
return fmt.Errorf("error reading ClickPipe destination: %v", diags)
1027+
}
10141028
}
10151029

10161030
// Destination roles are not persisted on ClickPipes side. Used only during pipe creation.
1017-
destinationModel.Roles = stateDestinationModel.Roles
1031+
if !stateDestinationModel.Roles.IsNull() {
1032+
destinationModel.Roles = stateDestinationModel.Roles
1033+
} else {
1034+
destinationModel.Roles = types.ListNull(types.StringType)
1035+
}
10181036

10191037
columnList := make([]attr.Value, len(clickPipe.Destination.Columns))
10201038
for i, column := range clickPipe.Destination.Columns {
@@ -1259,3 +1277,32 @@ func (c *ClickPipeResource) Delete(ctx context.Context, request resource.DeleteR
12591277
)
12601278
}
12611279
}
1280+
1281+
// ImportState imports a ClickPipe reverse private endpoint into the state.
1282+
// We don't have access to configuration/plan, so service id is required
1283+
// to be provided as a part of the import id.
1284+
func (r *ClickPipeResource) ImportState(ctx context.Context, req resource.ImportStateRequest, resp *resource.ImportStateResponse) {
1285+
idParts := strings.Split(req.ID, ":")
1286+
1287+
if len(idParts) != 2 {
1288+
resp.Diagnostics.AddError(
1289+
"Invalid Import ID",
1290+
fmt.Sprintf("Expected import identifier with format: service_id:id. Got: %q", req.ID),
1291+
)
1292+
return
1293+
}
1294+
1295+
id := idParts[0]
1296+
endpointID := idParts[1]
1297+
1298+
resp.Diagnostics.Append(resp.State.SetAttribute(ctx, path.Root("service_id"), id)...)
1299+
resp.Diagnostics.Append(resp.State.SetAttribute(ctx, path.Root("id"), endpointID)...)
1300+
1301+
resp.Diagnostics.AddWarning(
1302+
"Credentials state diverge",
1303+
"Importing a ClickPipe will not persist credentials into your state.\n"+
1304+
"Sensitive values are only stored in your state and provider is not able to import them.\n"+
1305+
"Run a `terraform apply` to ensure sensitive values state is up to date with a ClickPipe.\n"+
1306+
"Important: your configuration (in *.tf files) has to provide valid credentials.",
1307+
)
1308+
}

pkg/resource/clickpipe_reverse_private_endpoint.go

+5-2
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,11 @@ import (
2323
)
2424

2525
// Ensure provider defined types fully satisfy framework interfaces
26-
var _ resource.Resource = &ClickPipeReversePrivateEndpointResource{}
27-
var _ resource.ResourceWithImportState = &ClickPipeReversePrivateEndpointResource{}
26+
var (
27+
_ resource.Resource = &ClickPipeReversePrivateEndpointResource{}
28+
_ resource.ResourceWithConfigure = &ClickPipeReversePrivateEndpointResource{}
29+
_ resource.ResourceWithImportState = &ClickPipeReversePrivateEndpointResource{}
30+
)
2831

2932
const clickPipeReversePrivateEndpointResourceDescription = `
3033
This experimental resource allows you to create and manage ClickPipes reverse private endpoints for a secure data source connections in ClickHouse Cloud.

0 commit comments

Comments
 (0)