diff --git a/pkg/config-api-provider/provider/provider.go b/pkg/config-api-provider/provider/provider.go index a13f4666..7f6c6e53 100644 --- a/pkg/config-api-provider/provider/provider.go +++ b/pkg/config-api-provider/provider/provider.go @@ -62,5 +62,6 @@ func (p *uxiConfigurationProvider) Resources(_ context.Context) []func() resourc resources.NewSensorResource, resources.NewWiredNetworkResource, resources.NewWirelessNetworkResource, + resources.NewServiceTestResource, } } diff --git a/pkg/config-api-provider/provider/resources/service.go b/pkg/config-api-provider/provider/resources/service.go new file mode 100644 index 00000000..93415317 --- /dev/null +++ b/pkg/config-api-provider/provider/resources/service.go @@ -0,0 +1,127 @@ +package resources + +import ( + "context" + + // "github.com/aruba-uxi/configuration-api-terraform-provider/pkg/config-api-client" + "github.com/hashicorp/terraform-plugin-framework/path" + "github.com/hashicorp/terraform-plugin-framework/resource" + "github.com/hashicorp/terraform-plugin-framework/resource/schema" + "github.com/hashicorp/terraform-plugin-framework/resource/schema/planmodifier" + "github.com/hashicorp/terraform-plugin-framework/resource/schema/stringplanmodifier" + "github.com/hashicorp/terraform-plugin-framework/types" +) + +// Ensure the implementation satisfies the expected interfaces. +var ( + _ resource.Resource = &serviceTestResource{} + _ resource.ResourceWithConfigure = &serviceTestResource{} +) + +type serviceTestResourceModel struct { + ID types.String `tfsdk:"id"` + Title types.String `tfsdk:"title"` +} + +// TODO: Switch this to use the Client Model when that becomes available +type ServiceTestResponseModel struct { + Uid string // , + Category string // , + Title string // , + Target string // Nullable<>, + Template string // , + IsEnabled bool // +} + +func NewServiceTestResource() resource.Resource { + return &serviceTestResource{} +} + +type serviceTestResource struct{} + +func (r *serviceTestResource) Metadata(ctx context.Context, req resource.MetadataRequest, resp *resource.MetadataResponse) { + resp.TypeName = req.ProviderTypeName + "_service_test" +} + +func (r *serviceTestResource) Schema(_ context.Context, _ resource.SchemaRequest, resp *resource.SchemaResponse) { + resp.Schema = schema.Schema{ + Attributes: map[string]schema.Attribute{ + "id": schema.StringAttribute{ + Computed: true, + PlanModifiers: []planmodifier.String{ + stringplanmodifier.UseStateForUnknown(), + }, + }, + "title": schema.StringAttribute{ + Required: true, + }, + }, + } +} + +func (r *serviceTestResource) Configure(_ context.Context, req resource.ConfigureRequest, resp *resource.ConfigureResponse) { +} + +func (r *serviceTestResource) Create(ctx context.Context, req resource.CreateRequest, resp *resource.CreateResponse) { + // Retrieve values from plan + var plan serviceTestResourceModel + diags := req.Plan.Get(ctx, &plan) + diags.AddError("operation not supported", "creating a service_test is not supported; service_tests can only be imported") + resp.Diagnostics.Append(diags...) +} + +func (r *serviceTestResource) Read(ctx context.Context, req resource.ReadRequest, resp *resource.ReadResponse) { + // Get current state + var state serviceTestResourceModel + diags := req.State.Get(ctx, &state) + resp.Diagnostics.Append(diags...) + if resp.Diagnostics.HasError() { + return + } + + response := GetServiceTest() + + // Update state from client response + state.Title = types.StringValue(response.Title) + + // Set refreshed state + diags = resp.State.Set(ctx, &state) + resp.Diagnostics.Append(diags...) + if resp.Diagnostics.HasError() { + return + } +} + +func (r *serviceTestResource) Update(ctx context.Context, req resource.UpdateRequest, resp *resource.UpdateResponse) { + // Retrieve values from plan + var plan serviceTestResourceModel + diags := req.Plan.Get(ctx, &plan) + diags.AddError("operation not supported", "updating a service_test is not supported; service_tests can only be updated through the dashboard") + resp.Diagnostics.Append(diags...) +} + +func (r *serviceTestResource) Delete(ctx context.Context, req resource.DeleteRequest, resp *resource.DeleteResponse) { + // Retrieve values from state + var state serviceTestResourceModel + diags := req.State.Get(ctx, &state) + diags.AddError("operation not supported", "deleting a service_test is not supported; service_tests can only removed from state") + resp.Diagnostics.Append(diags...) +} + +func (r *serviceTestResource) ImportState(ctx context.Context, req resource.ImportStateRequest, resp *resource.ImportStateResponse) { + resource.ImportStatePassthroughID(ctx, path.Root("id"), req, resp) +} + +// Get the serviceTest using the configuration-api client +var GetServiceTest = func() ServiceTestResponseModel { + // TODO: Query the serviceTest using the client + + return ServiceTestResponseModel{ + Uid: "uid", + Category: "category", + Title: "title", + Target: "target", + Template: "template", + IsEnabled: true, + } +} diff --git a/pkg/config-api-provider/test/service_test.go b/pkg/config-api-provider/test/service_test.go new file mode 100644 index 00000000..53e1d945 --- /dev/null +++ b/pkg/config-api-provider/test/service_test.go @@ -0,0 +1,91 @@ +package test + +import ( + "regexp" + "testing" + + "github.com/aruba-uxi/configuration-api-terraform-provider/pkg/terraform-provider-configuration/provider/resources" + "github.com/hashicorp/terraform-plugin-testing/helper/resource" + "github.com/hashicorp/terraform-plugin-testing/tfversion" +) + +func TestServiceTestResource(t *testing.T) { + + resource.Test(t, resource.TestCase{ + ProtoV6ProviderFactories: testAccProtoV6ProviderFactories, + TerraformVersionChecks: []tfversion.TerraformVersionCheck{ + // we required terraform 1.7.0 and above for the `removed` block + tfversion.RequireAbove(tfversion.Version1_7_0), + }, + Steps: []resource.TestStep{ + // Creating a service_test is not allowed + { + Config: providerConfig + ` + resource "uxi_service_test" "my_service_test" { + title = "title" + }`, + + ExpectError: regexp.MustCompile(`(?s)creating a service_test is not supported; service_tests can only be\s*imported`), + }, + // Importing a service_test + { + PreConfig: func() { + resources.GetServiceTest = func() resources.ServiceTestResponseModel { + return resources.ServiceTestResponseModel{ + Uid: "uid", + Category: "external", + Title: "title", + Target: "target", + Template: "template", + IsEnabled: true, + } + } + }, + Config: providerConfig + ` + resource "uxi_service_test" "my_service_test" { + title = "title" + } + + import { + to = uxi_service_test.my_service_test + id = "uid" + }`, + + Check: resource.ComposeAggregateTestCheckFunc( + resource.TestCheckResourceAttr("uxi_service_test.my_service_test", "title", "title"), + resource.TestCheckResourceAttr("uxi_service_test.my_service_test", "id", "uid"), + ), + }, + // ImportState testing + { + ResourceName: "uxi_service_test.my_service_test", + ImportState: true, + ImportStateVerify: true, + }, + // Updating a service_test is not allowed + { + Config: providerConfig + ` + resource "uxi_service_test" "my_service_test" { + title = "updated_title" + }`, + ExpectError: regexp.MustCompile(`(?s)updating a service_test is not supported; service_tests can only be updated\s*through the dashboard`), + }, + // Deleting a service_test is not allowed + { + Config: providerConfig + ``, + ExpectError: regexp.MustCompile(`(?s)deleting a service_test is not supported; service_tests can only removed from\s*state`), + }, + // Remove service_test from state + { + Config: providerConfig + ` + removed { + from = uxi_service_test.my_service_test + + lifecycle { + destroy = false + } + }`, + }, + }, + }) +}