diff --git a/pkg/config-api-provider/examples/full-demo/main.tf b/pkg/config-api-provider/examples/full-demo/main.tf index 5aa3d077..1cc21ee3 100644 --- a/pkg/config-api-provider/examples/full-demo/main.tf +++ b/pkg/config-api-provider/examples/full-demo/main.tf @@ -8,10 +8,10 @@ terraform { provider "uxi" {} -# resource "uxi_group" "group" { -# name = "test_name" -# parent_uid = "9999" -# } +resource "uxi_group" "my_group" { + name = "name" + parent_uid = "parent_uid" +} // Sensor Resource /* @@ -103,6 +103,27 @@ resource "uxi_wired_network" "my_wired_network" { alias = "alias" } +// Service Test Resource +/* +To import: +import { + to = uxi_service_test.my_service_test + id = "uid" +} + +To remove: +removed { + from = uxi_service_test.my_service_test + + lifecycle { + destroy = false + } +} +*/ +resource "uxi_service_test" "my_service_test" { + title = "title" +} + # output "group" { # value = uxi_group.group diff --git a/pkg/config-api-provider/provider/resources/group.go b/pkg/config-api-provider/provider/resources/group.go index 4b313b1e..96f73dd9 100644 --- a/pkg/config-api-provider/provider/resources/group.go +++ b/pkg/config-api-provider/provider/resources/group.go @@ -3,8 +3,6 @@ package resources import ( "context" - "time" - "github.com/hashicorp/terraform-plugin-framework/path" "github.com/hashicorp/terraform-plugin-framework/resource" "github.com/hashicorp/terraform-plugin-framework/resource/schema" @@ -20,19 +18,27 @@ var ( ) type groupResourceModel struct { - ID types.String `tfsdk:"id"` - Name types.String `tfsdk:"name"` - ParentUid types.String `tfsdk:"parent_uid"` - LastUpdated types.String `tfsdk:"last_updated"` + ID types.String `tfsdk:"id"` + Name types.String `tfsdk:"name"` + ParentUid types.String `tfsdk:"parent_uid"` } -type groupResponseModel struct { +type GroupResponseModel struct { UID string Name string ParentUid string Path string } +type GroupCreateRequestModel struct { + Name string + ParentUid string +} + +type GroupUpdateRequestModel struct { + Name string +} + func NewGroupResource() resource.Resource { return &groupResource{} } @@ -52,16 +58,15 @@ func (r *groupResource) Schema(_ context.Context, _ resource.SchemaRequest, resp stringplanmodifier.UseStateForUnknown(), }, }, - "last_updated": schema.StringAttribute{ - Computed: true, - }, "name": schema.StringAttribute{ - Computed: false, Required: true, }, "parent_uid": schema.StringAttribute{ - Computed: false, Required: true, + PlanModifiers: []planmodifier.String{ + // UXI business logic does not permit moving of groups + stringplanmodifier.RequiresReplace(), + }, }, }, } @@ -81,11 +86,15 @@ func (r *groupResource) Create(ctx context.Context, req resource.CreateRequest, // TODO: Call client create-group method // We are mocking the response of the client for this early stage of development - mock_response_uid := "test_uid" + group := CreateGroup(GroupCreateRequestModel{ + Name: plan.Name.ValueString(), + ParentUid: plan.ParentUid.ValueString(), + }) // Update the state to match the plan (replace with response from client) - plan.ID = types.StringValue(mock_response_uid) - plan.LastUpdated = types.StringValue(time.Now().Format(time.RFC850)) + plan.ID = types.StringValue(group.UID) + plan.Name = types.StringValue(group.Name) + plan.ParentUid = types.StringValue(group.ParentUid) // Set state to fully populated data diags = resp.State.Set(ctx, plan) @@ -111,7 +120,6 @@ func (r *groupResource) Read(ctx context.Context, req resource.ReadRequest, resp // Update state from client response state.Name = types.StringValue(response.Name) state.ParentUid = types.StringValue(response.ParentUid) - state.LastUpdated = types.StringValue(time.Now().Format(time.RFC850)) // Set refreshed state diags = resp.State.Set(ctx, &state) @@ -130,10 +138,14 @@ func (r *groupResource) Update(ctx context.Context, req resource.UpdateRequest, return } - // TODO: Call client create-group method + // TODO: Call client updateGroup method + group := UpdateGroup(GroupUpdateRequestModel{ + Name: plan.Name.ValueString(), + }) // Update the state to match the plan (replace with response from client) - plan.LastUpdated = types.StringValue(time.Now().Format(time.RFC850)) + plan.Name = types.StringValue(group.Name) + plan.ParentUid = types.StringValue(group.ParentUid) // Set state to fully populated data diags = resp.State.Set(ctx, plan) @@ -159,14 +171,35 @@ func (r *groupResource) ImportState(ctx context.Context, req resource.ImportStat resource.ImportStatePassthroughID(ctx, path.Root("id"), req, resp) } -// Get the group using the configuration-api client -func GetGroup() groupResponseModel { +var GetGroup = func() GroupResponseModel { + // TODO: Query the group using the client + + return GroupResponseModel{ + UID: "mock_uid", + Name: "mock_name", + ParentUid: "mock_parent_uid", + Path: "mock_path", + } +} + +var CreateGroup = func(request GroupCreateRequestModel) GroupResponseModel { + // TODO: Query the group using the client + + return GroupResponseModel{ + UID: "mock_uid", + Name: "mock_name", + ParentUid: "mock_parent_uid", + Path: "mock_path", + } +} + +var UpdateGroup = func(request GroupUpdateRequestModel) GroupResponseModel { // TODO: Query the group using the client - return groupResponseModel{ - UID: "temporary_uid", - Name: "temporary_name", - ParentUid: "temporary_parent_uid", - Path: "temporary_path", + return GroupResponseModel{ + UID: "mock_uid", + Name: "mock_name", + ParentUid: "mock_parent_uid", + Path: "mock_path", } } diff --git a/pkg/config-api-provider/test/group_test.go b/pkg/config-api-provider/test/group_test.go index d192e7f6..115d0e42 100644 --- a/pkg/config-api-provider/test/group_test.go +++ b/pkg/config-api-provider/test/group_test.go @@ -3,6 +3,7 @@ package test import ( "testing" + "github.com/aruba-uxi/configuration-api-terraform-provider/pkg/terraform-provider-configuration/provider/resources" "github.com/hashicorp/terraform-plugin-testing/helper/resource" ) @@ -11,25 +12,115 @@ type Fetcher interface { } func TestGroupResource(t *testing.T) { - createGroupConfig := ` - resource "uxi_group" "test_group" { - name = "temporary_name" - parent_uid = "temporary_parent_uid" - }` resource.Test(t, resource.TestCase{ ProtoV6ProviderFactories: testAccProtoV6ProviderFactories, Steps: []resource.TestStep{ // Create and Read testing { - Config: providerConfig + createGroupConfig, + PreConfig: func() { + response := resources.GroupResponseModel{ + UID: "uid", + Name: "name", + ParentUid: "parent_uid", + Path: "parent_uid.uid", + } + resources.CreateGroup = func(request resources.GroupCreateRequestModel) resources.GroupResponseModel { + return response + } + resources.GetGroup = func() resources.GroupResponseModel { + return response + } + }, + Config: providerConfig + ` + resource "uxi_group" "my_group" { + name = "name" + parent_uid = "parent_uid" + }`, Check: resource.ComposeAggregateTestCheckFunc( - resource.TestCheckResourceAttr("uxi_group.test_group", "name", "temporary_name"), - resource.TestCheckResourceAttr("uxi_group.test_group", "parent_uid", "temporary_parent_uid"), - resource.TestCheckResourceAttrSet("uxi_group.test_group", "id"), - resource.TestCheckResourceAttrSet("uxi_group.test_group", "last_updated"), + resource.TestCheckResourceAttr("uxi_group.my_group", "name", "name"), + resource.TestCheckResourceAttr("uxi_group.my_group", "parent_uid", "parent_uid"), + resource.TestCheckResourceAttr("uxi_group.my_group", "id", "uid"), ), }, + // ImportState testing + { + ResourceName: "uxi_group.my_group", + ImportState: true, + ImportStateVerify: true, + }, + // Update that does not trigger a recreate + { + PreConfig: func() { + response := resources.GroupResponseModel{ + UID: "uid", + Name: "updated_name", + ParentUid: "parent_uid", + Path: "parent_uid.uid", + } + resources.UpdateGroup = func(request resources.GroupUpdateRequestModel) resources.GroupResponseModel { + return response + } + resources.GetGroup = func() resources.GroupResponseModel { + return response + } + }, + Config: providerConfig + ` + resource "uxi_group" "my_group" { + name = "updated_name" + parent_uid = "parent_uid" + }`, + Check: resource.ComposeAggregateTestCheckFunc( + resource.TestCheckResourceAttr("uxi_group.my_group", "name", "updated_name"), + resource.TestCheckResourceAttr("uxi_group.my_group", "parent_uid", "parent_uid"), + resource.TestCheckResourceAttr("uxi_group.my_group", "id", "uid"), + ), + Destroy: false, + }, + // Update that does trigger a recreate + { + PreConfig: func() { + response := resources.GroupResponseModel{ + UID: "new_uid", + Name: "name", + ParentUid: "updated_parent_uid", + Path: "updated_parent_uid.uid", + } + resources.CreateGroup = func(request resources.GroupCreateRequestModel) resources.GroupResponseModel { + return response + } + called := false + resources.GetGroup = func() resources.GroupResponseModel { + if !called { + called = true + return resources.GroupResponseModel{ + UID: "uid", + Name: "name", + ParentUid: "parent_uid", + Path: "parent_uid.uid", + } + } else { + return resources.GroupResponseModel{ + UID: "new_uid", + Name: "name", + ParentUid: "updated_parent_uid", + Path: "updated_parent_uid.uid", + } + } + } + }, + Config: providerConfig + ` + resource "uxi_group" "my_group" { + name = "name" + parent_uid = "updated_parent_uid" + }`, + Check: resource.ComposeAggregateTestCheckFunc( + resource.TestCheckResourceAttr("uxi_group.my_group", "name", "name"), + resource.TestCheckResourceAttr("uxi_group.my_group", "parent_uid", "updated_parent_uid"), + resource.TestCheckResourceAttr("uxi_group.my_group", "id", "new_uid"), + ), + }, + // Delete testing automatically occurs in TestCase }, }) }