From 1566aeaeca3e833b20653c766ab9135e98f46aa6 Mon Sep 17 00:00:00 2001 From: Keisuke Nitta Date: Thu, 11 Jul 2024 15:07:11 +0900 Subject: [PATCH] feat: reimplement "mackerel_role_metadata" resource --- internal/provider/provider.go | 1 + .../resource_mackerel_role_metadata.go | 171 ++++++++++++++++++ .../resource_mackerel_role_metadata_test.go | 25 +++ mackerel/provider.go | 1 + 4 files changed, 198 insertions(+) create mode 100644 internal/provider/resource_mackerel_role_metadata.go create mode 100644 internal/provider/resource_mackerel_role_metadata_test.go diff --git a/internal/provider/provider.go b/internal/provider/provider.go index 55d61c7..bced53f 100644 --- a/internal/provider/provider.go +++ b/internal/provider/provider.go @@ -84,6 +84,7 @@ func (m *mackerelProvider) Configure(ctx context.Context, req provider.Configure func (m *mackerelProvider) Resources(context.Context) []func() resource.Resource { return []func() resource.Resource{ NewMackerelNotificationGroupResource, + NewMackerelRoleMetadataResource, NewMackerelServiceResource, NewMackerelServiceMetadataResource, } diff --git a/internal/provider/resource_mackerel_role_metadata.go b/internal/provider/resource_mackerel_role_metadata.go new file mode 100644 index 0000000..614c175 --- /dev/null +++ b/internal/provider/resource_mackerel_role_metadata.go @@ -0,0 +1,171 @@ +package provider + +import ( + "context" + + "github.com/hashicorp/terraform-plugin-framework-jsontypes/jsontypes" + "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/schema/validator" + "github.com/mackerelio-labs/terraform-provider-mackerel/internal/mackerel" +) + +var ( + _ resource.Resource = (*mackerelRoleMetadataResource)(nil) + _ resource.ResourceWithConfigure = (*mackerelRoleMetadataResource)(nil) + _ resource.ResourceWithImportState = (*mackerelRoleMetadataResource)(nil) +) + +func NewMackerelRoleMetadataResource() resource.Resource { + return &mackerelRoleMetadataResource{} +} + +type mackerelRoleMetadataResource struct { + Client *mackerel.Client +} + +func (r *mackerelRoleMetadataResource) Metadata(_ context.Context, req resource.MetadataRequest, resp *resource.MetadataResponse) { + resp.TypeName = req.ProviderTypeName + "_role_metadata" +} + +func (r *mackerelRoleMetadataResource) Schema(_ context.Context, _ resource.SchemaRequest, resp *resource.SchemaResponse) { + resp.Schema = schema.Schema{ + Description: "This resource creates and manages a Role Metadata.", + + Attributes: map[string]schema.Attribute{ + "id": schema.StringAttribute{ + Computed: true, + PlanModifiers: []planmodifier.String{ + stringplanmodifier.UseStateForUnknown(), // immutable + }, + }, + "service": schema.StringAttribute{ + Description: "The name of the service.", + Required: true, + Validators: []validator.String{ + mackerel.ServiceNameValidator(), + }, + PlanModifiers: []planmodifier.String{ + stringplanmodifier.RequiresReplace(), // force new + }, + }, + "role": schema.StringAttribute{ + Description: "The name of the role.", + Required: true, + Validators: []validator.String{ + mackerel.RoleNameValidator(), + }, + PlanModifiers: []planmodifier.String{ + stringplanmodifier.RequiresReplace(), // force new + }, + }, + "namespace": schema.StringAttribute{ + Description: "The idenfier for the metadata.", + Required: true, + PlanModifiers: []planmodifier.String{ + stringplanmodifier.RequiresReplace(), // force new + }, + }, + "metadata_json": schema.StringAttribute{ + Description: "Arbitrary JSON data for the role.", + Required: true, + CustomType: jsontypes.NormalizedType{}, + }, + }, + } +} + +func (r *mackerelRoleMetadataResource) Configure(ctx context.Context, req resource.ConfigureRequest, resp *resource.ConfigureResponse) { + client, diags := retrieveClient(ctx, req.ProviderData) + resp.Diagnostics.Append(diags...) + if diags.HasError() { + return + } + r.Client = client +} + +func (r *mackerelRoleMetadataResource) Create(ctx context.Context, req resource.CreateRequest, resp *resource.CreateResponse) { + var data mackerel.RoleMetadataModel + resp.Diagnostics.Append(req.Plan.Get(ctx, &data)...) + if resp.Diagnostics.HasError() { + return + } + + if err := data.Create(ctx, r.Client); err != nil { + resp.Diagnostics.AddError( + "Unable to create Role Metadata", + err.Error(), + ) + return + } + + resp.Diagnostics.Append(resp.State.Set(ctx, &data)...) +} + +func (r *mackerelRoleMetadataResource) Read(ctx context.Context, req resource.ReadRequest, resp *resource.ReadResponse) { + var data mackerel.RoleMetadataModel + resp.Diagnostics.Append(req.State.Get(ctx, &data)...) + if resp.Diagnostics.HasError() { + return + } + + if err := data.Read(ctx, r.Client); err != nil { + resp.Diagnostics.AddError( + "Unable to read Role Metadata", + err.Error(), + ) + return + } + + resp.Diagnostics.Append(resp.State.Set(ctx, &data)...) +} + +func (r *mackerelRoleMetadataResource) Update(ctx context.Context, req resource.UpdateRequest, resp *resource.UpdateResponse) { + var data mackerel.RoleMetadataModel + resp.Diagnostics.Append(req.Plan.Get(ctx, &data)...) + if resp.Diagnostics.HasError() { + return + } + + if err := data.Update(ctx, r.Client); err != nil { + resp.Diagnostics.AddError( + "Unable to update Role Metadata", + err.Error(), + ) + return + } + + resp.Diagnostics.Append(resp.State.Set(ctx, &data)...) +} + +func (r *mackerelRoleMetadataResource) Delete(ctx context.Context, req resource.DeleteRequest, resp *resource.DeleteResponse) { + var data mackerel.RoleMetadataModel + resp.Diagnostics.Append(req.State.Get(ctx, &data)...) + if resp.Diagnostics.HasError() { + return + } + + if err := data.Delete(ctx, r.Client); err != nil { + resp.Diagnostics.AddError( + "Unable to delete Role Metadata", + err.Error(), + ) + return + } +} + +func (r *mackerelRoleMetadataResource) ImportState(ctx context.Context, req resource.ImportStateRequest, resp *resource.ImportStateResponse) { + data, err := mackerel.ImportRoleMetadata(req.ID) + if err != nil { + resp.Diagnostics.AddAttributeError( + path.Root("id"), + "Invalid ID", + err.Error(), + ) + return + } + resp.Diagnostics.Append(resp.State.Set(ctx, &data)...) +} diff --git a/internal/provider/resource_mackerel_role_metadata_test.go b/internal/provider/resource_mackerel_role_metadata_test.go new file mode 100644 index 0000000..78380e3 --- /dev/null +++ b/internal/provider/resource_mackerel_role_metadata_test.go @@ -0,0 +1,25 @@ +package provider_test + +import ( + "context" + "testing" + + fwresource "github.com/hashicorp/terraform-plugin-framework/resource" + "github.com/mackerelio-labs/terraform-provider-mackerel/internal/provider" +) + +func Test_MackerelRoleMetadataResource_schema(t *testing.T) { + t.Parallel() + + ctx := context.Background() + req := fwresource.SchemaRequest{} + resp := fwresource.SchemaResponse{} + provider.NewMackerelRoleMetadataResource().Schema(ctx, req, &resp) + if resp.Diagnostics.HasError() { + t.Fatalf("schema diagnostics: %+v", resp.Diagnostics) + } + + if diags := resp.Schema.ValidateImplementation(ctx); diags.HasError() { + t.Fatalf("schema validation diagnostics: %+v", diags) + } +} diff --git a/mackerel/provider.go b/mackerel/provider.go index 0b74c95..96b3856 100644 --- a/mackerel/provider.go +++ b/mackerel/provider.go @@ -83,6 +83,7 @@ func protoV5ProviderServer(provider *schema.Provider) tfprotov5.ProviderServer { // Resources delete(provider.ResourcesMap, "mackerel_notification_group") + delete(provider.ResourcesMap, "mackerel_role_metadata") delete(provider.ResourcesMap, "mackerel_service") delete(provider.ResourcesMap, "mackerel_service_metadata")