diff --git a/README.md b/README.md index 9152a0d..7c40104 100644 --- a/README.md +++ b/README.md @@ -57,6 +57,7 @@ resource "schemaregistry_schema" "example" { subject = "example" schema_type = "AVRO" compatibility_level = "NONE" + hard_delete = false schema = file("path/to/your/schema.avsc") # optional list of schema references diff --git a/docs/resources/schemaregistry_schema.md b/docs/resources/schemaregistry_schema.md index cda607e..172a734 100644 --- a/docs/resources/schemaregistry_schema.md +++ b/docs/resources/schemaregistry_schema.md @@ -17,6 +17,7 @@ resource "schemaregistry_schema" "example" { subject = "example" schema_type = "AVRO" compatibility_level = "FORWARD_TRANSITIVE" + hard_delete = true schema = "example" # optional list of schema references @@ -37,8 +38,9 @@ The following arguments are supported: * `subject` - (Required) The subject related to the schema. * `schema_type` - (Required) The schema type. * `compatibility_level` - (Required) The schema compatibility level. -* `schema` - (Required) The schema string. +* `schema` - (Optional) The schema string. * `references` - (Optional) The referenced schema list. +* `hard_delete` - (Optional) Controls whether the subject is soft or hard deleted. ## Attributes Reference diff --git a/examples/resources/schemaregistry_schema/resource.tf b/examples/resources/schemaregistry_schema/resource.tf index c1bc3bc..1f47aad 100644 --- a/examples/resources/schemaregistry_schema/resource.tf +++ b/examples/resources/schemaregistry_schema/resource.tf @@ -3,4 +3,5 @@ resource "schemaregistry_schema" "example" { schema = "{\"type\":\"record\",\"name\":\"Test\",\"fields\":[{\"name\":\"f1\",\"type\":\"string\"}]}" schema_type = "AVRO" compatibility_level = "FORWARD_TRANSITIVE" + hard_delete = true } diff --git a/internal/provider/data_source_schema.go b/internal/provider/data_source_schema.go index 176c875..b37f4d8 100644 --- a/internal/provider/data_source_schema.go +++ b/internal/provider/data_source_schema.go @@ -40,10 +40,12 @@ type schemaDataSourceModel struct { Version types.Int64 `tfsdk:"version"` Reference types.List `tfsdk:"reference"` CompatibilityLevel types.String `tfsdk:"compatibility_level"` + HardDelete types.Bool `tfsdk:"hard_delete"` } // Metadata returns the data source type name. -func (d *schemaDataSource) Metadata(_ context.Context, req datasource.MetadataRequest, resp *datasource.MetadataResponse) { +func (d *schemaDataSource) Metadata(_ context.Context, req datasource.MetadataRequest, + resp *datasource.MetadataResponse) { resp.TypeName = req.ProviderTypeName + "_schema" } @@ -55,7 +57,7 @@ func (d *schemaDataSource) Schema(_ context.Context, _ datasource.SchemaRequest, Description: "Fetches a schema from the Schema Registry.", Attributes: map[string]schema.Attribute{ "id": schema.StringAttribute{ - Description: "UID for the schema, which is the subject name.", + Description: "The globally unique ID of the schema.", Computed: true, }, "subject": schema.StringAttribute{ @@ -63,7 +65,7 @@ func (d *schemaDataSource) Schema(_ context.Context, _ datasource.SchemaRequest, Required: true, }, "schema": schema.StringAttribute{ - Description: "The schema string.", + Description: "The schema definition.", Computed: true, CustomType: jsontypes.NormalizedType{}, }, @@ -107,7 +109,7 @@ func (d *schemaDataSource) Schema(_ context.Context, _ datasource.SchemaRequest, }, }, "compatibility_level": schema.StringAttribute{ - Description: "The compatibility level of the schema. Default is FORWARD_TRANSITIVE.", + Description: "The compatibility level of the schema.", Computed: true, Validators: []validator.String{ stringvalidator.OneOf( @@ -121,12 +123,17 @@ func (d *schemaDataSource) Schema(_ context.Context, _ datasource.SchemaRequest, ), }, }, + "hard_delete": schema.BoolAttribute{ + Description: "Controls whether a schema should be soft or hard deleted.", + Optional: true, + }, }, } } // Configure adds the provider configured client to the data source. -func (d *schemaDataSource) Configure(_ context.Context, req datasource.ConfigureRequest, resp *datasource.ConfigureResponse) { +func (d *schemaDataSource) Configure(_ context.Context, req datasource.ConfigureRequest, + resp *datasource.ConfigureResponse) { if req.ProviderData == nil { return } diff --git a/internal/provider/data_source_schema_test.go b/internal/provider/data_source_schema_test.go index c854222..bd42406 100644 --- a/internal/provider/data_source_schema_test.go +++ b/internal/provider/data_source_schema_test.go @@ -94,6 +94,7 @@ resource "schemaregistry_schema" "test_01" { subject = "%s" schema_type = "AVRO" compatibility_level = "NONE" + hard_delete = false schema = jsonencode({ "type": "record", "name": "Test", @@ -124,6 +125,7 @@ resource "schemaregistry_schema" "test_01" { subject = "%s" schema_type = "AVRO" compatibility_level = "BACKWARD" + hard_delete = false schema = jsonencode({ type = "record", name = "TestUpdated", diff --git a/internal/provider/resource_schema.go b/internal/provider/resource_schema.go index 8c093a2..225ac02 100644 --- a/internal/provider/resource_schema.go +++ b/internal/provider/resource_schema.go @@ -9,6 +9,7 @@ import ( "github.com/hashicorp/terraform-plugin-framework/attr" "github.com/hashicorp/terraform-plugin-framework/resource" "github.com/hashicorp/terraform-plugin-framework/resource/schema" + "github.com/hashicorp/terraform-plugin-framework/resource/schema/booldefault" "github.com/hashicorp/terraform-plugin-framework/resource/schema/planmodifier" "github.com/hashicorp/terraform-plugin-framework/resource/schema/stringplanmodifier" "github.com/hashicorp/terraform-plugin-framework/schema/validator" @@ -43,6 +44,7 @@ type schemaResourceModel struct { Version types.Int64 `tfsdk:"version"` Reference types.List `tfsdk:"references"` CompatibilityLevel types.String `tfsdk:"compatibility_level"` + HardDelete types.Bool `tfsdk:"hard_delete"` } // Metadata returns the resource type name. @@ -73,7 +75,7 @@ func (r *schemaResource) Schema(_ context.Context, _ resource.SchemaRequest, res }, "schema": schema.StringAttribute{ Description: "The schema definition.", - Required: true, + Optional: true, CustomType: jsontypes.NormalizedType{}, Validators: []validator.String{ stringvalidator.LengthAtLeast(2), @@ -85,7 +87,7 @@ func (r *schemaResource) Schema(_ context.Context, _ resource.SchemaRequest, res }, "schema_type": schema.StringAttribute{ Description: "The schema format.", - Optional: true, + Required: true, PlanModifiers: []planmodifier.String{ stringplanmodifier.RequiresReplace(), }, @@ -130,6 +132,7 @@ func (r *schemaResource) Schema(_ context.Context, _ resource.SchemaRequest, res "compatibility_level": schema.StringAttribute{ Description: "The compatibility level of the schema.", Optional: true, + Computed: true, Validators: []validator.String{ stringvalidator.OneOf( "NONE", @@ -142,6 +145,12 @@ func (r *schemaResource) Schema(_ context.Context, _ resource.SchemaRequest, res ), }, }, + "hard_delete": schema.BoolAttribute{ + Description: "Controls whether a schema should be soft or hard deleted.", + Optional: true, + Computed: true, + Default: booldefault.StaticBool(false), + }, }, } } @@ -229,6 +238,7 @@ func (r *schemaResource) Create(ctx context.Context, req resource.CreateRequest, plan.SchemaType = types.StringValue(schemaTypeStr) plan.Version = types.Int64Value(1) // Set the version to 1 for new schema plan.Reference = FromRegistryReferences(schema.References()) + plan.HardDelete = types.BoolValue(plan.HardDelete.ValueBool()) // Set state to fully populated data diags = resp.State.Set(ctx, plan) @@ -276,6 +286,7 @@ func (r *schemaResource) Read(ctx context.Context, req resource.ReadRequest, res state.SchemaType = types.StringValue(schemaType) state.Version = types.Int64Value(int64(schema.Version())) state.Reference = FromRegistryReferences(schema.References()) + state.HardDelete = types.BoolValue(state.HardDelete.ValueBool()) // Set refreshed state diags = resp.State.Set(ctx, &state) @@ -336,6 +347,7 @@ func (r *schemaResource) Update(ctx context.Context, req resource.UpdateRequest, plan.SchemaID = types.Int64Value(int64(schema.ID())) plan.Version = types.Int64Value(int64(schema.Version())) plan.Reference = FromRegistryReferences(schema.References()) + plan.HardDelete = types.BoolValue(plan.HardDelete.ValueBool()) diags = resp.State.Set(ctx, plan) resp.Diagnostics.Append(diags...) @@ -354,8 +366,10 @@ func (r *schemaResource) Delete(ctx context.Context, req resource.DeleteRequest, return } - // Soft deletes existing schema - err := r.client.DeleteSubject(state.Subject.ValueString(), false) + deletionType := state.HardDelete.ValueBool() + + // Delete existing schema + err := r.client.DeleteSubject(state.Subject.ValueString(), deletionType) if err != nil { resp.Diagnostics.AddError( "Error Deleting Schema", diff --git a/internal/provider/resource_schema_test.go b/internal/provider/resource_schema_test.go index 11ce02c..b244d50 100644 --- a/internal/provider/resource_schema_test.go +++ b/internal/provider/resource_schema_test.go @@ -53,6 +53,7 @@ func TestAccSchemaResource_basic(t *testing.T) { resource.TestCheckResourceAttr(resourceName, "schema", NormalizedJSON(initialSchema)), resource.TestCheckResourceAttr(resourceName, "schema_type", "AVRO"), resource.TestCheckResourceAttr(resourceName, "compatibility_level", "NONE"), + resource.TestCheckResourceAttr(resourceName, "hard_delete", "false"), resource.TestCheckResourceAttrSet(resourceName, "schema_id"), resource.TestCheckResourceAttrSet(resourceName, "version"), ), @@ -73,6 +74,7 @@ func TestAccSchemaResource_basic(t *testing.T) { resource.TestCheckResourceAttr(resourceName, "schema", NormalizedJSON(updatedSchema)), resource.TestCheckResourceAttr(resourceName, "schema_type", "AVRO"), resource.TestCheckResourceAttr(resourceName, "compatibility_level", "BACKWARD"), + resource.TestCheckResourceAttr(resourceName, "hard_delete", "true"), resource.TestCheckResourceAttrSet(resourceName, "schema_id"), resource.TestCheckResourceAttrSet(resourceName, "version"), ), @@ -158,6 +160,7 @@ resource "schemaregistry_schema" "test_01" { subject = "%s" schema_type = "AVRO" compatibility_level = "NONE" + hard_delete = false schema = jsonencode({ "type": "record", "name": "Test", @@ -203,6 +206,7 @@ resource "schemaregistry_schema" "test_01" { subject = "%s" schema_type = "AVRO" compatibility_level = "BACKWARD" + hard_delete = true schema = jsonencode({ "type": "record", "name": "TestUpdated",