diff --git a/go.mod b/go.mod index ad8d376..5ac5b32 100644 --- a/go.mod +++ b/go.mod @@ -6,6 +6,7 @@ require ( github.com/golangci/golangci-lint v1.50.1 github.com/google/go-cmp v0.6.0 github.com/hashicorp/terraform-plugin-framework v1.8.0 + github.com/hashicorp/terraform-plugin-framework-jsontypes v0.1.0 github.com/hashicorp/terraform-plugin-framework-validators v0.12.0 github.com/hashicorp/terraform-plugin-go v0.23.0 github.com/hashicorp/terraform-plugin-mux v0.16.0 diff --git a/go.sum b/go.sum index d4d17cb..d15fcdc 100644 --- a/go.sum +++ b/go.sum @@ -342,6 +342,8 @@ github.com/hashicorp/terraform-json v0.22.1 h1:xft84GZR0QzjPVWs4lRUwvTcPnegqlyS7 github.com/hashicorp/terraform-json v0.22.1/go.mod h1:JbWSQCLFSXFFhg42T7l9iJwdGXBYV8fmmD6o/ML4p3A= github.com/hashicorp/terraform-plugin-framework v1.8.0 h1:P07qy8RKLcoBkCrY2RHJer5AEvJnDuXomBgou6fD8kI= github.com/hashicorp/terraform-plugin-framework v1.8.0/go.mod h1:/CpTukO88PcL/62noU7cuyaSJ4Rsim+A/pa+3rUVufY= +github.com/hashicorp/terraform-plugin-framework-jsontypes v0.1.0 h1:b8vZYB/SkXJT4YPbT3trzE6oJ7dPyMy68+9dEDKsJjE= +github.com/hashicorp/terraform-plugin-framework-jsontypes v0.1.0/go.mod h1:tP9BC3icoXBz72evMS5UTFvi98CiKhPdXF6yLs1wS8A= github.com/hashicorp/terraform-plugin-framework-validators v0.12.0 h1:HOjBuMbOEzl7snOdOoUfE2Jgeto6JOjLVQ39Ls2nksc= github.com/hashicorp/terraform-plugin-framework-validators v0.12.0/go.mod h1:jfHGE/gzjxYz6XoUwi/aYiiKrJDeutQNUtGQXkaHklg= github.com/hashicorp/terraform-plugin-go v0.23.0 h1:AALVuU1gD1kPb48aPQUjug9Ir/125t+AAurhqphJ2Co= diff --git a/internal/mackerel/service_metadata.go b/internal/mackerel/service_metadata.go new file mode 100644 index 0000000..ea108c5 --- /dev/null +++ b/internal/mackerel/service_metadata.go @@ -0,0 +1,149 @@ +package mackerel + +import ( + "context" + "encoding/json" + "fmt" + "strings" + + "github.com/hashicorp/terraform-plugin-framework-jsontypes/jsontypes" + "github.com/hashicorp/terraform-plugin-framework/diag" + "github.com/hashicorp/terraform-plugin-framework/path" + "github.com/hashicorp/terraform-plugin-framework/types" + "github.com/mackerelio/mackerel-client-go" +) + +type ServiceMetadataModel struct { + ID types.String `tfsdk:"id"` + ServiceName types.String `tfsdk:"service"` + Namespace types.String `tfsdk:"namespace"` + MetadataJSON jsontypes.Normalized `tfsdk:"metadata_json"` +} + +func serviceMetadataID(serviceName, namespace string) string { + return strings.Join([]string{serviceName, namespace}, "/") +} + +func parseServiceMetadataID(id string) (serviceName, namespace string, err error) { + first, last, ok := strings.Cut(id, "/") + if !ok { + return "", "", fmt.Errorf("The ID is expected to have `/` format, but got: '%s'.", id) + } + return first, last, nil +} + +func ReadServiceMetadata(ctx context.Context, client *Client, data ServiceMetadataModel) (ServiceMetadataModel, error) { + return readServiceMetadataInner(ctx, client, data) +} + +type serviceMetadataGetter interface { + GetServiceMetaData(string, string) (*mackerel.ServiceMetaDataResp, error) +} + +func readServiceMetadataInner(_ context.Context, client serviceMetadataGetter, data ServiceMetadataModel) (ServiceMetadataModel, error) { + serviceName, namespace, err := data.getID() + if err != nil { + return ServiceMetadataModel{}, err + } + + metadataResp, err := client.GetServiceMetaData(serviceName, namespace) + if err != nil { + return ServiceMetadataModel{}, err + } + + data.ID = types.StringValue(serviceMetadataID(serviceName, namespace)) + data.ServiceName = types.StringValue(serviceName) + data.Namespace = types.StringValue(namespace) + + if metadataResp.ServiceMetaData == nil { + if /* expected not to be deleted */ !data.MetadataJSON.IsNull() { + data.MetadataJSON = jsontypes.NewNormalizedValue("") + } + return data, nil + } + + metadataJSON, err := json.Marshal(metadataResp.ServiceMetaData) + if err != nil { + return ServiceMetadataModel{}, fmt.Errorf("failed to marshal result: %w", err) + } + + data.MetadataJSON = jsontypes.NewNormalizedValue(string(metadataJSON)) + return data, nil +} + +func (m *ServiceMetadataModel) Validate(base path.Path) (diags diag.Diagnostics) { + if m.ID.IsNull() || m.ID.IsUnknown() { + return + } + id := m.ID.ValueString() + idPath := base.AtName("id") + + serviceName, namespace, err := parseServiceMetadataID(id) + if err != nil { + diags.AddAttributeError( + idPath, + "Invalid ID", + err.Error(), + ) + return + } + + if !m.ServiceName.IsNull() && !m.ServiceName.IsUnknown() && m.ServiceName.ValueString() != serviceName { + diags.AddAttributeError( + idPath, + "Invalid ID", + fmt.Sprintf("ID is expected to start with '%s/', but got: '%s'", m.ServiceName.ValueString(), id), + ) + } + if !m.Namespace.IsNull() && !m.Namespace.IsUnknown() && m.Namespace.ValueString() != namespace { + diags.AddAttributeError( + idPath, + "Invalid ID", + fmt.Sprintf("ID is expected to end with '/%s', but got: '%s'", m.Namespace.ValueString(), id), + ) + } + + return +} + +func (m *ServiceMetadataModel) CreateOrUpdateMetadata(_ context.Context, client *Client) error { + serviceName, namespace, err := m.getID() + if err != nil { + return err + } + + var metadata mackerel.ServiceMetaData + + if err := json.Unmarshal( + []byte(m.MetadataJSON.ValueString()), &metadata, + ); err != nil { + return fmt.Errorf("failed to unmarshal metadata: %w", err) + } + + if err := client.PutServiceMetaData(serviceName, namespace, metadata); err != nil { + return err + } + + m.ID = types.StringValue(serviceMetadataID(serviceName, namespace)) + return nil +} + +func (m *ServiceMetadataModel) Delete(_ context.Context, client *Client) error { + serviceName, namespace, err := m.getID() + if err != nil { + return err + } + + if err := client.DeleteServiceMetaData(serviceName, namespace); err != nil { + return err + } + + return nil +} + +func (m *ServiceMetadataModel) getID() (serviceName, namespace string, err error) { + if !m.ID.IsNull() && !m.ID.IsUnknown() { + return parseServiceMetadataID(m.ID.ValueString()) + } + return m.ServiceName.ValueString(), m.Namespace.ValueString(), nil +} diff --git a/internal/mackerel/service_metadata_test.go b/internal/mackerel/service_metadata_test.go new file mode 100644 index 0000000..cbf91b6 --- /dev/null +++ b/internal/mackerel/service_metadata_test.go @@ -0,0 +1,171 @@ +package mackerel + +import ( + "context" + "fmt" + "slices" + "testing" + + "github.com/google/go-cmp/cmp" + "github.com/hashicorp/terraform-plugin-framework-jsontypes/jsontypes" + "github.com/hashicorp/terraform-plugin-framework/diag" + "github.com/hashicorp/terraform-plugin-framework/path" + "github.com/hashicorp/terraform-plugin-framework/types" + "github.com/mackerelio/mackerel-client-go" +) + +func Test_ReadServiceMetadata(t *testing.T) { + t.Parallel() + + cases := map[string]struct { + inClient serviceMetadataGetterFunc + in ServiceMetadataModel + + wants ServiceMetadataModel + wantFail bool + }{ + "from service name and namespace": { + inClient: func(s, ns string) (*mackerel.ServiceMetaDataResp, error) { + if s != "service0" || ns != "data0" { + return nil, fmt.Errorf("no metadata found") + } + return &mackerel.ServiceMetaDataResp{ + ServiceMetaData: map[string]any{ + "foo": "bar", + }, + }, nil + }, + in: ServiceMetadataModel{ + ID: types.StringUnknown(), + ServiceName: types.StringValue("service0"), + Namespace: types.StringValue("data0"), + }, + + wants: ServiceMetadataModel{ + ID: types.StringValue("service0/data0"), + ServiceName: types.StringValue("service0"), + Namespace: types.StringValue("data0"), + MetadataJSON: jsontypes.NewNormalizedValue(`{"foo":"bar"}`), + }, + }, + "from id": { + inClient: func(s, ns string) (*mackerel.ServiceMetaDataResp, error) { + if s != "service0" || ns != "data0" { + return nil, fmt.Errorf("no metadata found") + } + return &mackerel.ServiceMetaDataResp{ + ServiceMetaData: map[string]any{ + "foo": "bar", + }, + }, nil + }, + in: ServiceMetadataModel{ + ID: types.StringValue("service0/data0"), + }, + + wants: ServiceMetadataModel{ + ID: types.StringValue("service0/data0"), + ServiceName: types.StringValue("service0"), + Namespace: types.StringValue("data0"), + MetadataJSON: jsontypes.NewNormalizedValue(`{"foo":"bar"}`), + }, + }, + } + + ctx := context.Background() + for name, tt := range cases { + t.Run(name, func(t *testing.T) { + t.Parallel() + + actual, err := readServiceMetadataInner(ctx, tt.inClient, tt.in) + if (err != nil) != tt.wantFail { + if tt.wantFail { + t.Errorf("unexpected success") + } else { + t.Errorf("unexpected error: %+v", err) + } + return + } + + if diff := cmp.Diff(tt.wants, actual); diff != "" { + t.Errorf("%s", diff) + } + }) + } + +} + +type serviceMetadataGetterFunc func(string, string) (*mackerel.ServiceMetaDataResp, error) + +func (f serviceMetadataGetterFunc) GetServiceMetaData(serviceName, namespace string) (*mackerel.ServiceMetaDataResp, error) { + return f(serviceName, namespace) +} + +func Test_ServiceMetadata_Validate(t *testing.T) { + t.Parallel() + + cases := map[string]struct { + in ServiceMetadataModel + + wantError bool + wantErrorIn path.Expressions + }{ + "valid": { + in: ServiceMetadataModel{ + ID: types.StringValue("service/namespace"), + ServiceName: types.StringValue("service"), + Namespace: types.StringValue("namespace"), + }, + }, + "invalid id syntax": { + in: ServiceMetadataModel{ + ID: types.StringValue("service,namespace"), + }, + wantError: true, + wantErrorIn: path.Expressions{path.MatchRoot("id")}, + }, + "unmatched service": { + in: ServiceMetadataModel{ + ID: types.StringValue("service0/namespace"), + ServiceName: types.StringValue("service1"), + Namespace: types.StringValue("namespace"), + }, + wantError: true, + wantErrorIn: path.Expressions{path.MatchRoot("id")}, + }, + "unmatched namespace": { + in: ServiceMetadataModel{ + ID: types.StringValue("service/namespace0"), + ServiceName: types.StringValue("service"), + Namespace: types.StringValue("namespace1"), + }, + wantError: true, + wantErrorIn: path.Expressions{path.MatchRoot("id")}, + }, + } + + for name, tt := range cases { + t.Run(name, func(t *testing.T) { + t.Parallel() + + diags := tt.in.Validate(path.Empty()) + for _, d := range diags { + if d.Severity() != diag.SeverityError { + continue + } + dwp, ok := d.(diag.DiagnosticWithPath) + if ok { + p := dwp.Path() + if slices.ContainsFunc(tt.wantErrorIn, func(expr path.Expression) bool { + return expr.Matches(p) + }) { + continue + } + } else if tt.wantError { + continue + } + t.Errorf("unexpected error: %v", d) + } + }) + } +} diff --git a/internal/provider/data_source_mackerel_metadata_test.go b/internal/provider/data_source_mackerel_metadata_test.go new file mode 100644 index 0000000..58e4310 --- /dev/null +++ b/internal/provider/data_source_mackerel_metadata_test.go @@ -0,0 +1,27 @@ +package provider_test + +import ( + "context" + "testing" + + fwdatasource "github.com/hashicorp/terraform-plugin-framework/datasource" + "github.com/mackerelio-labs/terraform-provider-mackerel/internal/provider" +) + +func Test_MackerelServiceMetadataDataSource_schema(t *testing.T) { + t.Parallel() + + ctx := context.Background() + + req := fwdatasource.SchemaRequest{} + resp := &fwdatasource.SchemaResponse{} + provider.NewMackerelServiceMetadataDataSource().Schema(ctx, req, resp) + if resp.Diagnostics.HasError() { + t.Errorf("schema method: %+v", resp.Diagnostics) + return + } + + if diags := resp.Schema.ValidateImplementation(ctx); diags.HasError() { + t.Errorf("schema validation: %+v", diags) + } +} diff --git a/internal/provider/data_source_mackerel_service_metadata.go b/internal/provider/data_source_mackerel_service_metadata.go new file mode 100644 index 0000000..d571101 --- /dev/null +++ b/internal/provider/data_source_mackerel_service_metadata.go @@ -0,0 +1,85 @@ +package provider + +import ( + "context" + "fmt" + + "github.com/hashicorp/terraform-plugin-framework-jsontypes/jsontypes" + "github.com/hashicorp/terraform-plugin-framework/datasource" + "github.com/hashicorp/terraform-plugin-framework/datasource/schema" + "github.com/hashicorp/terraform-plugin-framework/schema/validator" + "github.com/mackerelio-labs/terraform-provider-mackerel/internal/mackerel" +) + +var ( + _ datasource.DataSourceWithConfigure = (*mackerelServiceMetadataDataSource)(nil) +) + +func NewMackerelServiceMetadataDataSource() datasource.DataSource { + return &mackerelServiceMetadataDataSource{} +} + +type mackerelServiceMetadataDataSource struct { + Client *mackerel.Client +} + +func (d *mackerelServiceMetadataDataSource) Metadata(_ context.Context, req datasource.MetadataRequest, resp *datasource.MetadataResponse) { + resp.TypeName = req.ProviderTypeName + "_service_metadata" +} + +func (d *mackerelServiceMetadataDataSource) Schema(_ context.Context, _ datasource.SchemaRequest, resp *datasource.SchemaResponse) { + resp.Schema = schema.Schema{ + Description: "This data source allows access to details of a specific Service Metadata.", + + Attributes: map[string]schema.Attribute{ + "id": schema.StringAttribute{ + Computed: true, + }, + "service": schema.StringAttribute{ + Description: "The name of the service.", + + Required: true, + Validators: []validator.String{mackerel.ServiceNameValidator()}, + }, + "namespace": schema.StringAttribute{ + Description: "Identifier for the metadata.", + + Required: true, + }, + "metadata_json": schema.StringAttribute{ + Description: "Arbitrary JSON data for the service.", + + Computed: true, + CustomType: jsontypes.NormalizedType{}, + }, + }, + } +} + +func (d *mackerelServiceMetadataDataSource) Configure(ctx context.Context, req datasource.ConfigureRequest, resp *datasource.ConfigureResponse) { + client, diags := retrieveClient(ctx, req.ProviderData) + resp.Diagnostics.Append(diags...) + if diags.HasError() { + return + } + d.Client = client +} + +func (d *mackerelServiceMetadataDataSource) Read(ctx context.Context, req datasource.ReadRequest, resp *datasource.ReadResponse) { + var data mackerel.ServiceMetadataModel + resp.Diagnostics.Append(req.Config.Get(ctx, &data)...) + if resp.Diagnostics.HasError() { + return + } + + remoteData, err := mackerel.ReadServiceMetadata(ctx, d.Client, data) + if err != nil { + resp.Diagnostics.AddError( + fmt.Sprintf("Unable to read Service Metadata: %s/%s", data.ServiceName.ValueString(), data.Namespace.ValueString()), + err.Error(), + ) + return + } + + resp.Diagnostics.Append(resp.State.Set(ctx, &remoteData)...) +} diff --git a/internal/provider/provider.go b/internal/provider/provider.go index 5fe3556..dbfece1 100644 --- a/internal/provider/provider.go +++ b/internal/provider/provider.go @@ -84,12 +84,14 @@ func (m *mackerelProvider) Configure(ctx context.Context, req provider.Configure func (m *mackerelProvider) Resources(context.Context) []func() resource.Resource { return []func() resource.Resource{ NewMackerelServiceResource, + NewMackerelServiceMetadataResource, } } func (m *mackerelProvider) DataSources(context.Context) []func() datasource.DataSource { return []func() datasource.DataSource{ NewMackerelServiceDataSource, + NewMackerelServiceMetadataDataSource, } } diff --git a/internal/provider/resource_mackerel_service_metadata.go b/internal/provider/resource_mackerel_service_metadata.go new file mode 100644 index 0000000..c82d66d --- /dev/null +++ b/internal/provider/resource_mackerel_service_metadata.go @@ -0,0 +1,184 @@ +package provider + +import ( + "context" + "fmt" + + "github.com/hashicorp/terraform-plugin-framework-jsontypes/jsontypes" + "github.com/hashicorp/terraform-plugin-framework/diag" + "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 = (*mackerelServiceMetadataResource)(nil) + _ resource.ResourceWithValidateConfig = (*mackerelServiceMetadataResource)(nil) + _ resource.ResourceWithConfigure = (*mackerelServiceMetadataResource)(nil) + _ resource.ResourceWithImportState = (*mackerelServiceMetadataResource)(nil) +) + +func NewMackerelServiceMetadataResource() resource.Resource { + return &mackerelServiceMetadataResource{} +} + +type mackerelServiceMetadataResource struct { + Client *mackerel.Client +} + +func (r *mackerelServiceMetadataResource) Metadata(_ context.Context, req resource.MetadataRequest, resp *resource.MetadataResponse) { + resp.TypeName = req.ProviderTypeName + "_service_metadata" +} + +func (r *mackerelServiceMetadataResource) Schema(_ context.Context, _ resource.SchemaRequest, resp *resource.SchemaResponse) { + resp.Schema = schema.Schema{ + Description: "This resource allows creating and management of Service Metadata.", + Attributes: map[string]schema.Attribute{ + "id": schema.StringAttribute{ + Computed: true, + PlanModifiers: []planmodifier.String{ + stringplanmodifier.UseStateForUnknown(), + }, + }, + "service": schema.StringAttribute{ + Description: "The name of the service.", + + Required: true, + Validators: []validator.String{ + mackerel.ServiceNameValidator(), + }, + PlanModifiers: []planmodifier.String{ + stringplanmodifier.RequiresReplace(), + }, + }, + "namespace": schema.StringAttribute{ + Description: "Identifier for the metadata.", + + Required: true, + PlanModifiers: []planmodifier.String{ + stringplanmodifier.RequiresReplace(), + }, + }, + "metadata_json": schema.StringAttribute{ + Description: "Arbitrary JSON data for the service.", + + Required: true, + CustomType: jsontypes.NormalizedType{}, + }, + }, + } +} + +func (r *mackerelServiceMetadataResource) ValidateConfig(ctx context.Context, req resource.ValidateConfigRequest, resp *resource.ValidateConfigResponse) { + var data mackerel.ServiceMetadataModel + resp.Diagnostics.Append(req.Config.Get(ctx, &data)...) + if resp.Diagnostics.HasError() { + return + } + + resp.Diagnostics.Append(data.Validate(path.Empty())...) +} + +func (r *mackerelServiceMetadataResource) Configure(ctx context.Context, req resource.ConfigureRequest, resp *resource.ConfigureResponse) { + client, diags := retrieveClient(ctx, req.ProviderData) + resp.Diagnostics.Append(diags...) + if resp.Diagnostics.HasError() { + return + } + r.Client = client +} + +func (r *mackerelServiceMetadataResource) Create(ctx context.Context, req resource.CreateRequest, resp *resource.CreateResponse) { + var data mackerel.ServiceMetadataModel + resp.Diagnostics.Append(req.Plan.Get(ctx, &data)...) + if resp.Diagnostics.HasError() { + return + } + + resp.Diagnostics.Append(r.createOrUpdate(ctx, &data)...) + if resp.Diagnostics.HasError() { + return + } + + resp.Diagnostics.Append(resp.State.Set(ctx, &data)...) +} + +func (r *mackerelServiceMetadataResource) Read(ctx context.Context, req resource.ReadRequest, resp *resource.ReadResponse) { + var data mackerel.ServiceMetadataModel + resp.Diagnostics.Append(req.State.Get(ctx, &data)...) + if resp.Diagnostics.HasError() { + return + } + + remoteData, err := mackerel.ReadServiceMetadata(ctx, r.Client, data) + if err != nil { + resp.Diagnostics.AddError( + fmt.Sprintf("Unable to read Service Metadata: %s", data.ID.ValueString()), + err.Error(), + ) + return + } + + resp.Diagnostics.Append(resp.State.Set(ctx, &remoteData)...) +} + +func (r *mackerelServiceMetadataResource) Update(ctx context.Context, req resource.UpdateRequest, resp *resource.UpdateResponse) { + var data mackerel.ServiceMetadataModel + resp.Diagnostics.Append(req.Plan.Get(ctx, &data)...) + if resp.Diagnostics.HasError() { + return + } + + resp.Diagnostics.Append(r.createOrUpdate(ctx, &data)...) + if resp.Diagnostics.HasError() { + return + } + + resp.Diagnostics.Append(resp.State.Set(ctx, &data)...) +} + +func (r *mackerelServiceMetadataResource) Delete(ctx context.Context, req resource.DeleteRequest, resp *resource.DeleteResponse) { + var data mackerel.ServiceMetadataModel + 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 Service Metadata", + err.Error(), + ) + return + } +} + +func (r *mackerelServiceMetadataResource) ImportState(ctx context.Context, req resource.ImportStateRequest, resp *resource.ImportStateResponse) { + resource.ImportStatePassthroughID(ctx, path.Root("id"), req, resp) +} + +func (r *mackerelServiceMetadataResource) createOrUpdate(ctx context.Context, data *mackerel.ServiceMetadataModel) (diags diag.Diagnostics) { + if err := data.CreateOrUpdateMetadata(ctx, r.Client); err != nil { + diags.AddError( + "Unable to put Service Metadata", + err.Error(), + ) + return + } + + remoteData, err := mackerel.ReadServiceMetadata(ctx, r.Client, *data) + if err != nil { + diags.AddError( + "Unable to refresh Service Metadata after updates", + err.Error(), + ) + return + } + *data = remoteData + + return +} diff --git a/internal/provider/resource_mackerel_service_metadata_test.go b/internal/provider/resource_mackerel_service_metadata_test.go new file mode 100644 index 0000000..d831944 --- /dev/null +++ b/internal/provider/resource_mackerel_service_metadata_test.go @@ -0,0 +1,27 @@ +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_MackerelServiceMetadataResource_schema(t *testing.T) { + t.Parallel() + + ctx := context.Background() + + req := fwresource.SchemaRequest{} + resp := &fwresource.SchemaResponse{} + provider.NewMackerelServiceMetadataResource().Schema(ctx, req, resp) + if resp.Diagnostics.HasError() { + t.Errorf("schema method: %+v", resp.Diagnostics) + return + } + + if diags := resp.Schema.ValidateImplementation(ctx); diags.HasError() { + t.Errorf("schema validation: %+v", diags) + } +} diff --git a/mackerel/provider.go b/mackerel/provider.go index 1188eb6..e5781d3 100644 --- a/mackerel/provider.go +++ b/mackerel/provider.go @@ -83,9 +83,11 @@ func protoV5ProviderServer(provider *schema.Provider) tfprotov5.ProviderServer { // Resources delete(provider.ResourcesMap, "mackerel_service") + delete(provider.ResourcesMap, "mackerel_service_metadata") // Data Sources delete(provider.DataSourcesMap, "mackerel_service") + delete(provider.DataSourcesMap, "mackerel_service_metadata") mux, err := tf5muxserver.NewMuxServer( context.Background(),